diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 71ee20f5..258b3ae1 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -324,7 +324,9 @@ template const char basic_data::reset_color[] = "\x1b[0m"; template const wchar_t basic_data::wreset_color[] = L"\x1b[0m"; template const char basic_data::signs[] = {0, '-', '+', ' '}; template -const char basic_data::padding_shifts[] = {31, 31, 0, 1, 0}; +const char basic_data::left_padding_shifts[] = {31, 31, 0, 1, 0}; +template +const char basic_data::right_padding_shifts[] = {0, 31, 0, 1, 0}; template struct bits { static FMT_CONSTEXPR_DECL const int value = diff --git a/include/fmt/format.h b/include/fmt/format.h index 823d1817..e1ee0256 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -345,8 +345,8 @@ template ::value)> #if FMT_CLANG_VERSION __attribute__((no_sanitize("undefined"))) #endif -inline checked_ptr reserve( - std::back_insert_iterator it, std::size_t n) { +inline checked_ptr +reserve(std::back_insert_iterator it, std::size_t n) { Container& c = get_container(it); std::size_t size = c.size(); c.resize(size + n); @@ -786,7 +786,8 @@ template struct FMT_EXTERN_TEMPLATE_API basic_data { static const char reset_color[5]; static const wchar_t wreset_color[5]; static const char signs[]; - static const char padding_shifts[5]; + static const char left_padding_shifts[5]; + static const char right_padding_shifts[5]; }; FMT_EXTERN template struct basic_data; @@ -1383,13 +1384,17 @@ FMT_NOINLINE OutputIt fill(OutputIt it, size_t n, const fill_t& fill) { // Writes the output of f, padded according to format specifications in specs. // size: output size in code units. // width: output display width in (terminal) column positions. -template +template inline OutputIt write_padded(OutputIt out, const basic_format_specs& specs, size_t size, size_t width, const F& f) { + static_assert(align == align::left || align == align::right, ""); unsigned spec_width = to_unsigned(specs.width); size_t padding = spec_width > width ? spec_width - width : 0; - size_t left_padding = padding >> data::padding_shifts[specs.align]; + auto* shifts = align == align::left ? data::left_padding_shifts + : data::right_padding_shifts; + size_t left_padding = padding >> shifts[specs.align]; auto it = reserve(out, size + padding * specs.fill.size()); it = fill(it, left_padding, specs.fill); it = f(it); @@ -1397,11 +1402,12 @@ inline OutputIt write_padded(OutputIt out, return base_iterator(out, it); } -template +template inline OutputIt write_padded(OutputIt out, const basic_format_specs& specs, size_t size, const F& f) { - return write_padded(out, specs, size, size, f); + return write_padded(out, specs, size, size, f); } // Data for write_int that doesn't depend on output iterator type. It is used to @@ -1411,9 +1417,8 @@ template struct write_int_data { std::size_t padding; write_int_data(int num_digits, string_view prefix, - basic_format_specs& specs) - : size(prefix.size() + to_unsigned(num_digits)), - padding(0) { + const basic_format_specs& specs) + : size(prefix.size() + to_unsigned(num_digits)), padding(0) { if (specs.align == align::numeric) { auto width = to_unsigned(specs.width); if (width > size) { @@ -1424,7 +1429,6 @@ template struct write_int_data { size = prefix.size() + to_unsigned(specs.precision); padding = to_unsigned(specs.precision - num_digits); } - if (specs.align == align::none) specs.align = align::right; } }; @@ -1433,10 +1437,10 @@ template struct write_int_data { // where are written by f(it). template OutputIt write_int(OutputIt out, int num_digits, string_view prefix, - basic_format_specs specs, F f) { + const basic_format_specs& specs, F f) { auto data = write_int_data(num_digits, prefix, specs); using iterator = remove_reference_t; - return write_padded(out, specs, data.size, [=](iterator it) { + return write_padded(out, specs, data.size, [=](iterator it) { if (prefix.size() != 0) it = copy_str(prefix.begin(), prefix.end(), it); it = std::fill_n(it, data.padding, static_cast('0'));