diff --git a/src/include/units/format.h b/src/include/units/format.h index df2d3d79..9d6647a1 100644 --- a/src/include/units/format.h +++ b/src/include/units/format.h @@ -57,7 +57,7 @@ namespace units { ++ptr; continue; } - if (begin != ptr) + if(begin != ptr) handler.on_text(begin, ptr); ++ptr; // consume '%' if(ptr == end) @@ -94,8 +94,8 @@ namespace units { } struct units_format_checker { - template - void on_text(const Char*, const Char*) {} + template + void on_text(const CharT*, const CharT*) {} void on_quantity_value() {} void on_quantity_unit() {} }; @@ -114,108 +114,25 @@ namespace units { return format_to(out, "{}", unit_text().c_str()); } - // If T is an integral type, maps T to its unsigned counterpart, otherwise - // leaves it unchanged (unlike std::make_unsigned). - template> - struct make_unsigned_or_unchanged { - using type = T; - }; - - template - struct make_unsigned_or_unchanged { - using type = std::make_unsigned_t; - }; - - // converts value to int and checks that it's in the range [0, upper). - template - requires std::is_integral_v - inline int to_nonnegative_int(T value, int upper) - { - FMT_ASSERT(value >= 0 && value <= upper, "invalid value"); - (void)upper; - return static_cast(value); - } - - template - inline int to_nonnegative_int(T value, int upper) - { - FMT_ASSERT(units::isnan(value) || (value >= 0 && value <= static_cast(upper)), "invalid value"); - (void)upper; - return static_cast(value); - } - - template + template struct units_formatter { - FormatContext& context; OutputIt out; - // rep is unsigned to avoid overflow. - using rep = conditional && sizeof(Rep) < sizeof(int), - unsigned, typename make_unsigned_or_unchanged::type>; - bool negative = false; - rep val; + Rep val; int precision; - using char_type = FormatContext::char_type; - - explicit units_formatter(FormatContext& ctx, OutputIt o, quantity q, int prec): - context(ctx), out(o), negative(q.count() < 0), val(negative ? -q.count() : q.count()), precision(prec) + explicit units_formatter(OutputIt o, quantity q, int prec): + out(o), val(q.count()), precision(prec) { } - // returns true if nan or inf, writes to out. - bool handle_nan_inf() - { - if(units::isfinite(val)) { - return false; - } - if(units::isnan(val)) { - write_nan(); - return true; - } - // must be +-inf - if(val > 0) { - write_pinf(); - } - else { - write_ninf(); - } - return true; - } - - void write_sign() - { - if(negative) { - *out++ = '-'; - negative = false; - } - } - - void write(Rep value, int width) - { - write_sign(); - if(units::isnan(value)) - return write_nan(); - fmt::internal::uint32_or_64_t n = fmt::internal::to_unsigned(to_nonnegative_int(value, std::numeric_limits::max())); - int num_digits = fmt::internal::count_digits(n); - if(width > num_digits) - out = std::fill_n(out, width - num_digits, '0'); - out = fmt::internal::format_decimal(out, n, num_digits); - } - - void write_nan() { std::copy_n("nan", 3, out); } - void write_pinf() { std::copy_n("inf", 3, out); } - void write_ninf() { std::copy_n("-inf", 4, out); } - - void on_text(const char_type* begin, const char_type* end) + template + void on_text(const CharT* begin, const CharT* end) { std::copy(begin, end, out); } void on_quantity_value() { - if(handle_nan_inf()) - return; - write_sign(); out = format_units_quantity_value(out, val, precision); } @@ -261,7 +178,7 @@ private: return arg_ref_type(str_val); } - constexpr arg_ref_type make_arg_ref(internal::auto_id) + constexpr arg_ref_type make_arg_ref(fmt::internal::auto_id) { return arg_ref_type(context.next_arg_id()); } @@ -279,7 +196,8 @@ private: f.width_ref = make_arg_ref(arg_id); } - template void on_dynamic_precision(Id arg_id) + template + void on_dynamic_precision(Id arg_id) { f.precision_ref = make_arg_ref(arg_id); } @@ -317,6 +235,7 @@ private: handler.on_error("precision not allowed for integral quantity representation"); } + // parse units-specific specification end = parse_units_format(begin, end, units::detail::units_format_checker()); return {begin, end}; @@ -352,7 +271,7 @@ public: } else { // user provided format - units::detail::units_formatter f(ctx, out, q, precision); + units::detail::units_formatter f(out, q, precision); parse_units_format(begin, end, f); } @@ -362,7 +281,5 @@ public: w.write(buf.data(), buf.size(), specs); return w.out(); - -// return format_to(ctx.out(), "{} {}", q.count(), units::detail::unit_text().c_str()); } };