diff --git a/inc/format.h b/inc/format.h index 62f0efd..18e7b8d 100644 --- a/inc/format.h +++ b/inc/format.h @@ -40,21 +40,16 @@ constexpr inline void check_fmt_params() { * */ -// TODO: Error handling template constexpr inline void format_arg(char* dest, arg_t arg) { - constexpr auto error_array = get_init_array('f'); - detail::format_int(dest, arg, fmt_data); }; -// TODO: Error handling + template constexpr inline void format_arg(char* dest, arg_t arg) { - *(dest) = 'f'; - *(dest + fmt_data.length - fmt_data.precision - 1) = '.'; - //detail::format_float(dest, arg, fmt_data); }; + // TODO: Error handling template constexpr inline void format_arg(char* dest, const char* arg) { @@ -87,7 +82,7 @@ constexpr inline void format_args(char* dest, first_arg_t first_arg, args_t... a template consteval inline std::array()> get_preproc_string() { - auto result = get_init_array()>('0'); + auto result = get_init_array()>('f'); int i = 0; diff --git a/inc/format_impl.h b/inc/format_impl.h index 40d4238..2624ae0 100644 --- a/inc/format_impl.h +++ b/inc/format_impl.h @@ -26,10 +26,44 @@ namespace detail { */ -#define FMT_POWERS_OF_10(factor) \ - factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \ - (factor)*1000000, (factor)*10000000, (factor)*100000000, \ - (factor)*1000000000 +#define FMT_POWERS_OF_10(factor) \ + factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \ + (factor)*1000000, (factor)*10000000, (factor)*100000000, \ + (factor)*1000000000 + +template +constexpr int count_digits_fallback(T n) { + int count = 1; + for (;;) { + if (n < 10) return count; + if (n < 100) return count + 1; + if (n < 1000) return count + 2; + if (n < 10000) return count + 3; + n /= 10000u; + count += 4; + } +} + +inline int do_count_digits(uint64_t n) { + // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)). + static constexpr uint8_t bsr2log10[] = { + 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, + 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, + 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, + 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20}; + auto t = bsr2log10[__builtin_clzll(n | 1) ^ 63]; + static constexpr const uint64_t zero_or_powers_of_10[] = { + 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL), + 10000000000000000000ULL}; + return t - (n < zero_or_powers_of_10[t]); +} + +constexpr inline auto count_digits(uint64_t n) -> int { + if (!std::is_constant_evaluated()) { + return do_count_digits(n); + } + return count_digits_fallback(n); +} // Converts value in the range [0, 100) to a string. @@ -54,6 +88,8 @@ constexpr inline void copy2(char* dst, const char* src) { template constexpr inline void format_decimal(char* out, uint_t value, int size) { + if (count_digits(value) > size) return; + out += size; while (value >= 100) { out -= 2; @@ -61,46 +97,15 @@ constexpr inline void format_decimal(char* out, uint_t value, int size) { value /= 100; } - if (value < 10) *--out = static_cast('0' + value); + if (value < 10) { + *--out = static_cast('0' + value); + return; + } out -= 2; copy2(out, digits2(static_cast(value))); } -template -constexpr int count_digits_fallback(T n) { - int count = 1; - for (;;) { - if (n < 10) return count; - if (n < 100) return count + 1; - if (n < 1000) return count + 2; - if (n < 10000) return count + 3; - n /= 10000u; - count += 4; - } -} - -inline int do_count_digits(uint64_t n) { - // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)). - static constexpr uint8_t bsr2log10[] = { - 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, - 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, - 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, - 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20}; - auto t = bsr2log10[__builtin_clzll(n | 1) ^ 63]; - static constexpr const uint64_t zero_or_powers_of_10[] = { - 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL), - 10000000000000000000ULL}; - return t - (n < zero_or_powers_of_10[t]); -} - -constexpr inline auto count_digits(uint64_t n) -> int { - if (!std::is_constant_evaluated()) { - return do_count_digits(n); - } - return count_digits_fallback(n); -} - /* * @@ -116,8 +121,14 @@ constexpr inline void format_int(char* out, uint_t value, fmt_data_t fmt_node) { template constexpr inline void format_int(char* out, uint_t value, fmt_data_t fmt_node) { - if (value < 0) value = -value; - format_decimal(out, value, fmt_node.length); + auto abs_value = static_cast(value); + const bool negative = value < 0; + + if (negative) abs_value = 0 - abs_value; + format_decimal(out + 1 * (negative), abs_value, + fmt_node.length - 1 * (negative)); + + if (negative) *out = '-'; } @@ -130,8 +141,10 @@ constexpr inline void format_int(char* out, uint_t value, fmt_data_t fmt_node) { template constexpr inline void format_float(char* out, float_t value, - fmt_data_t fmt_node) { - // TODO + fmt_data_t fmt_data) { + + *(out) = 'f'; + *(out + fmt_data.length - fmt_data.precision - 1) = '.'; } diff --git a/src/main.cpp b/src/main.cpp index ade67f8..75f277d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,11 +4,12 @@ int main(int argc, char* argv[]) { - auto formatted = "Test: {:12} {:012.5} {:8}"_fmt(argv[0], argc, -1234); + auto formatted = "Test: {:12} {:012.5} {:8}"_fmt(argv[0], 123.45, -1234567); for (const auto& c : formatted) std::cout << c; std::cout << std::endl; - return formatted[6]; +// return formatted[6]; + return 0; } \ No newline at end of file