From e020805cb140ed98d09e606a867b910fce78ad15 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Thu, 10 Oct 2024 23:38:35 +0200 Subject: Integers formatting --- asl/format.cpp | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++ asl/format.hpp | 13 ++++++ asl/format_tests.cpp | 20 +++++++++ asl/meta.hpp | 2 + asl/meta_tests.cpp | 6 +++ asl/utility.hpp | 7 +++ 6 files changed, 166 insertions(+) (limited to 'asl') 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("", 7); // @Todo Float formatting +} + +void asl::AslFormat(formatter& f, double) +{ + f.write("", 8); // @Todo Float formatting +} + +void asl::AslFormat(formatter& f, uint8_t v) +{ + AslFormat(f, static_cast(v)); +} + +void asl::AslFormat(formatter& f, uint16_t v) +{ + AslFormat(f, static_cast(v)); +} + +void asl::AslFormat(formatter& f, uint32_t v) +{ + AslFormat(f, static_cast(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(v)); +} + +void asl::AslFormat(formatter& f, int16_t v) +{ + AslFormat(f, static_cast(v)); +} + +void asl::AslFormat(formatter& f, int32_t v) +{ + AslFormat(f, static_cast(v)); +} + +void asl::AslFormat(formatter& f, int64_t v) +{ + if (v < 0) + { + f.write("-", 1); + uint64_t absolute_value = ~(bit_cast(v) - 1); + AslFormat(f, absolute_value); + } + else + { + AslFormat(f, static_cast(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 concept trivially_move_assignable = trivially_assignable concept trivially_destructible = __is_trivially_destructible(T); +template concept trivially_copyable = __is_trivially_copyable(T); + using nullptr_t = decltype(nullptr); template 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 == 2); static_assert(asl::types_count == 1); static_assert(asl::types_count<> == 0); +static_assert(asl::trivially_copyable); +static_assert(!asl::trivially_copyable); +static_assert(!asl::trivially_copyable); +static_assert(asl::trivially_copyable); +static_assert(asl::trivially_copyable); + 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&&>(expr_)) @@ -17,6 +18,12 @@ T exchange(T& obj, U&& new_value) return old_value; } +template +constexpr U bit_cast(T value) requires (size_of == size_of) +{ + return __builtin_bit_cast(U, value); +} + #define ASL_DELETE_COPY(T) \ T(const T&) = delete; \ T& operator=(const T&) = delete; -- cgit