summaryrefslogtreecommitdiff
path: root/asl
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2024-10-10 23:38:35 +0200
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2024-12-20 15:35:58 +0100
commite020805cb140ed98d09e606a867b910fce78ad15 (patch)
tree08e79fbfa9e799b15f170bdeb198c2ba19287189 /asl
parent8dfd173285df515fe9b41d970321da9d049460f8 (diff)
Integers formatting
Diffstat (limited to 'asl')
-rw-r--r--asl/format.cpp118
-rw-r--r--asl/format.hpp13
-rw-r--r--asl/format_tests.cpp20
-rw-r--r--asl/meta.hpp2
-rw-r--r--asl/meta_tests.cpp6
-rw-r--r--asl/utility.hpp7
6 files changed, 166 insertions, 0 deletions
diff --git a/asl/format.cpp b/asl/format.cpp
index 4866562..eb653e9 100644
--- a/asl/format.cpp
+++ b/asl/format.cpp
@@ -1,4 +1,6 @@
#include "asl/format.hpp"
+#include "asl/utility.hpp"
+#include "asl/assert.hpp"
void asl::format_internals::format(
writer* writer,
@@ -67,3 +69,119 @@ void asl::format_internals::format(
f.write(begin, fmt - begin);
}
+
+void asl::AslFormat(formatter& f, float)
+{
+ f.write("<FLOAT>", 7); // @Todo Float formatting
+}
+
+void asl::AslFormat(formatter& f, double)
+{
+ f.write("<DOUBLE>", 8); // @Todo Float formatting
+}
+
+void asl::AslFormat(formatter& f, uint8_t v)
+{
+ AslFormat(f, static_cast<uint64_t>(v));
+}
+
+void asl::AslFormat(formatter& f, uint16_t v)
+{
+ AslFormat(f, static_cast<uint64_t>(v));
+}
+
+void asl::AslFormat(formatter& f, uint32_t v)
+{
+ AslFormat(f, static_cast<uint64_t>(v));
+}
+
+void asl::AslFormat(formatter& f, uint64_t v)
+{
+ static constexpr char pairs[] = {
+ '0', '0', '0', '1', '0', '2', '0', '3', '0', '4',
+ '0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
+ '1', '0', '1', '1', '1', '2', '1', '3', '1', '4',
+ '1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
+ '2', '0', '2', '1', '2', '2', '2', '3', '2', '4',
+ '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
+ '3', '0', '3', '1', '3', '2', '3', '3', '3', '4',
+ '3', '5', '3', '6', '3', '7', '3', '8', '3', '9',
+ '4', '0', '4', '1', '4', '2', '4', '3', '4', '4',
+ '4', '5', '4', '6', '4', '7', '4', '8', '4', '9',
+ '5', '0', '5', '1', '5', '2', '5', '3', '5', '4',
+ '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
+ '6', '0', '6', '1', '6', '2', '6', '3', '6', '4',
+ '6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
+ '7', '0', '7', '1', '7', '2', '7', '3', '7', '4',
+ '7', '5', '7', '6', '7', '7', '7', '8', '7', '9',
+ '8', '0', '8', '1', '8', '2', '8', '3', '8', '4',
+ '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
+ '9', '0', '9', '1', '9', '2', '9', '3', '9', '4',
+ '9', '5', '9', '6', '9', '7', '9', '8', '9', '9',
+ };
+
+ static constexpr int32_t kMaxDigits = 20;
+ char buffer[kMaxDigits];
+ int32_t cursor = kMaxDigits;
+
+ auto write_two = [&buffer, &cursor](const char* str)
+ {
+ ASL_ASSERT(cursor >= 2);
+ buffer[--cursor] = str[1];
+ buffer[--cursor] = str[0];
+ };
+
+ auto write_one = [&buffer, &cursor](char c)
+ {
+ ASL_ASSERT(cursor >= 1);
+ buffer[--cursor] = c;
+ };
+
+ while (v >= 100)
+ {
+ uint64_t x = v % 100;
+ v /= 100;
+ write_two(pairs + x * 2);
+ }
+
+ if (v >= 10)
+ {
+ write_two(pairs + v * 2);
+ }
+ else if (v > 0 || cursor == kMaxDigits)
+ {
+ ASL_ASSERT(v < 10);
+ write_one('0' + (char)v);
+ }
+
+ f.write(buffer + cursor, kMaxDigits - cursor);
+}
+
+void asl::AslFormat(formatter& f, int8_t v)
+{
+ AslFormat(f, static_cast<int64_t>(v));
+}
+
+void asl::AslFormat(formatter& f, int16_t v)
+{
+ AslFormat(f, static_cast<int64_t>(v));
+}
+
+void asl::AslFormat(formatter& f, int32_t v)
+{
+ AslFormat(f, static_cast<int64_t>(v));
+}
+
+void asl::AslFormat(formatter& f, int64_t v)
+{
+ if (v < 0)
+ {
+ f.write("-", 1);
+ uint64_t absolute_value = ~(bit_cast<uint64_t>(v) - 1);
+ AslFormat(f, absolute_value);
+ }
+ else
+ {
+ AslFormat(f, static_cast<uint64_t>(v));
+ }
+}
diff --git a/asl/format.hpp b/asl/format.hpp
index 1b4088e..f17329f 100644
--- a/asl/format.hpp
+++ b/asl/format.hpp
@@ -93,4 +93,17 @@ void AslFormat(formatter& f, const char (&str)[N])
f.write(str, N - 1);
}
+void AslFormat(formatter& f, float);
+void AslFormat(formatter& f, double);
+
+void AslFormat(formatter& f, uint8_t);
+void AslFormat(formatter& f, uint16_t);
+void AslFormat(formatter& f, uint32_t);
+void AslFormat(formatter& f, uint64_t);
+
+void AslFormat(formatter& f, int8_t);
+void AslFormat(formatter& f, int16_t);
+void AslFormat(formatter& f, int32_t);
+void AslFormat(formatter& f, int64_t);
+
} // namespace asl
diff --git a/asl/format_tests.cpp b/asl/format_tests.cpp
index 2288a77..55ed97b 100644
--- a/asl/format_tests.cpp
+++ b/asl/format_tests.cpp
@@ -78,5 +78,25 @@ int main()
asl::format(&sink, "{{{}}} }", "CHEESE");
assert(strcmp(sink.cstr(), "{CHEESE} }") == 0);
+ sink.reset();
+ asl::format(&sink, "{} {} {}", 0, 1, 2);
+ assert(strcmp(sink.cstr(), "0 1 2") == 0);
+
+ sink.reset();
+ asl::format(&sink, "{} {} {}", 10, 11, 12);
+ assert(strcmp(sink.cstr(), "10 11 12") == 0);
+
+ sink.reset();
+ asl::format(&sink, "{} {} {}", 100, 101, 102);
+ assert(strcmp(sink.cstr(), "100 101 102") == 0);
+
+ sink.reset();
+ asl::format(&sink, "{} {} {}", 1000, 1001, 1002);
+ assert(strcmp(sink.cstr(), "1000 1001 1002") == 0);
+
+ sink.reset();
+ asl::format(&sink, "{} {} {} {}", -1, -23, -456, -7890);
+ assert(strcmp(sink.cstr(), "-1 -23 -456 -7890") == 0);
+
return 0;
}
diff --git a/asl/meta.hpp b/asl/meta.hpp
index 7372c3f..d05b095 100644
--- a/asl/meta.hpp
+++ b/asl/meta.hpp
@@ -65,6 +65,8 @@ template<typename T> concept trivially_move_assignable = trivially_assignable<as
template<typename T> concept trivially_destructible = __is_trivially_destructible(T);
+template<typename T> concept trivially_copyable = __is_trivially_copyable(T);
+
using nullptr_t = decltype(nullptr);
template<typename T> struct _un_const_helper { using type = T; };
diff --git a/asl/meta_tests.cpp b/asl/meta_tests.cpp
index e53f870..2bebb01 100644
--- a/asl/meta_tests.cpp
+++ b/asl/meta_tests.cpp
@@ -163,4 +163,10 @@ static_assert(asl::types_count<int, int> == 2);
static_assert(asl::types_count<int> == 1);
static_assert(asl::types_count<> == 0);
+static_assert(asl::trivially_copyable<int>);
+static_assert(!asl::trivially_copyable<HasDestructor>);
+static_assert(!asl::trivially_copyable<CopyAssignable>);
+static_assert(asl::trivially_copyable<DefaultConstructible>);
+static_assert(asl::trivially_copyable<TriviallyDefaultConstructible>);
+
int main() { return 0; }
diff --git a/asl/utility.hpp b/asl/utility.hpp
index 2cbf8db..2d9ef05 100644
--- a/asl/utility.hpp
+++ b/asl/utility.hpp
@@ -1,6 +1,7 @@
#pragma once
#include "asl/meta.hpp"
+#include "asl/layout.hpp"
#define ASL_MOVE(expr_) (static_cast<::asl::un_ref_t<decltype(expr_)>&&>(expr_))
@@ -17,6 +18,12 @@ T exchange(T& obj, U&& new_value)
return old_value;
}
+template<trivially_copyable U, trivially_copyable T>
+constexpr U bit_cast(T value) requires (size_of<T> == size_of<U>)
+{
+ return __builtin_bit_cast(U, value);
+}
+
#define ASL_DELETE_COPY(T) \
T(const T&) = delete; \
T& operator=(const T&) = delete;