mirror of
https://github.com/fmtlib/fmt.git
synced 2025-04-16 05:42:19 +00:00
Improve handling of alignment
This commit is contained in:
parent
a71bc9c825
commit
8efd1a8ef6
@ -324,7 +324,9 @@ template <typename T> const char basic_data<T>::reset_color[] = "\x1b[0m";
|
|||||||
template <typename T> const wchar_t basic_data<T>::wreset_color[] = L"\x1b[0m";
|
template <typename T> const wchar_t basic_data<T>::wreset_color[] = L"\x1b[0m";
|
||||||
template <typename T> const char basic_data<T>::signs[] = {0, '-', '+', ' '};
|
template <typename T> const char basic_data<T>::signs[] = {0, '-', '+', ' '};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const char basic_data<T>::padding_shifts[] = {31, 31, 0, 1, 0};
|
const char basic_data<T>::left_padding_shifts[] = {31, 31, 0, 1, 0};
|
||||||
|
template <typename T>
|
||||||
|
const char basic_data<T>::right_padding_shifts[] = {0, 31, 0, 1, 0};
|
||||||
|
|
||||||
template <typename T> struct bits {
|
template <typename T> struct bits {
|
||||||
static FMT_CONSTEXPR_DECL const int value =
|
static FMT_CONSTEXPR_DECL const int value =
|
||||||
|
@ -345,8 +345,8 @@ template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
|
|||||||
#if FMT_CLANG_VERSION
|
#if FMT_CLANG_VERSION
|
||||||
__attribute__((no_sanitize("undefined")))
|
__attribute__((no_sanitize("undefined")))
|
||||||
#endif
|
#endif
|
||||||
inline checked_ptr<typename Container::value_type> reserve(
|
inline checked_ptr<typename Container::value_type>
|
||||||
std::back_insert_iterator<Container> it, std::size_t n) {
|
reserve(std::back_insert_iterator<Container> it, std::size_t n) {
|
||||||
Container& c = get_container(it);
|
Container& c = get_container(it);
|
||||||
std::size_t size = c.size();
|
std::size_t size = c.size();
|
||||||
c.resize(size + n);
|
c.resize(size + n);
|
||||||
@ -786,7 +786,8 @@ template <typename T = void> struct FMT_EXTERN_TEMPLATE_API basic_data {
|
|||||||
static const char reset_color[5];
|
static const char reset_color[5];
|
||||||
static const wchar_t wreset_color[5];
|
static const wchar_t wreset_color[5];
|
||||||
static const char signs[];
|
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<void>;
|
FMT_EXTERN template struct basic_data<void>;
|
||||||
@ -1383,13 +1384,17 @@ FMT_NOINLINE OutputIt fill(OutputIt it, size_t n, const fill_t<Char>& fill) {
|
|||||||
// Writes the output of f, padded according to format specifications in specs.
|
// Writes the output of f, padded according to format specifications in specs.
|
||||||
// size: output size in code units.
|
// size: output size in code units.
|
||||||
// width: output display width in (terminal) column positions.
|
// width: output display width in (terminal) column positions.
|
||||||
template <typename OutputIt, typename Char, typename F>
|
template <align::type align = align::left, typename OutputIt, typename Char,
|
||||||
|
typename F>
|
||||||
inline OutputIt write_padded(OutputIt out,
|
inline OutputIt write_padded(OutputIt out,
|
||||||
const basic_format_specs<Char>& specs, size_t size,
|
const basic_format_specs<Char>& specs, size_t size,
|
||||||
size_t width, const F& f) {
|
size_t width, const F& f) {
|
||||||
|
static_assert(align == align::left || align == align::right, "");
|
||||||
unsigned spec_width = to_unsigned(specs.width);
|
unsigned spec_width = to_unsigned(specs.width);
|
||||||
size_t padding = spec_width > width ? spec_width - width : 0;
|
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());
|
auto it = reserve(out, size + padding * specs.fill.size());
|
||||||
it = fill(it, left_padding, specs.fill);
|
it = fill(it, left_padding, specs.fill);
|
||||||
it = f(it);
|
it = f(it);
|
||||||
@ -1397,11 +1402,12 @@ inline OutputIt write_padded(OutputIt out,
|
|||||||
return base_iterator(out, it);
|
return base_iterator(out, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename Char, typename F>
|
template <align::type align = align::left, typename OutputIt, typename Char,
|
||||||
|
typename F>
|
||||||
inline OutputIt write_padded(OutputIt out,
|
inline OutputIt write_padded(OutputIt out,
|
||||||
const basic_format_specs<Char>& specs, size_t size,
|
const basic_format_specs<Char>& specs, size_t size,
|
||||||
const F& f) {
|
const F& f) {
|
||||||
return write_padded(out, specs, size, size, f);
|
return write_padded<align>(out, specs, size, size, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data for write_int that doesn't depend on output iterator type. It is used to
|
// Data for write_int that doesn't depend on output iterator type. It is used to
|
||||||
@ -1411,9 +1417,8 @@ template <typename Char> struct write_int_data {
|
|||||||
std::size_t padding;
|
std::size_t padding;
|
||||||
|
|
||||||
write_int_data(int num_digits, string_view prefix,
|
write_int_data(int num_digits, string_view prefix,
|
||||||
basic_format_specs<Char>& specs)
|
const basic_format_specs<Char>& specs)
|
||||||
: size(prefix.size() + to_unsigned(num_digits)),
|
: size(prefix.size() + to_unsigned(num_digits)), padding(0) {
|
||||||
padding(0) {
|
|
||||||
if (specs.align == align::numeric) {
|
if (specs.align == align::numeric) {
|
||||||
auto width = to_unsigned(specs.width);
|
auto width = to_unsigned(specs.width);
|
||||||
if (width > size) {
|
if (width > size) {
|
||||||
@ -1424,7 +1429,6 @@ template <typename Char> struct write_int_data {
|
|||||||
size = prefix.size() + to_unsigned(specs.precision);
|
size = prefix.size() + to_unsigned(specs.precision);
|
||||||
padding = to_unsigned(specs.precision - num_digits);
|
padding = to_unsigned(specs.precision - num_digits);
|
||||||
}
|
}
|
||||||
if (specs.align == align::none) specs.align = align::right;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1433,10 +1437,10 @@ template <typename Char> struct write_int_data {
|
|||||||
// where <digits> are written by f(it).
|
// where <digits> are written by f(it).
|
||||||
template <typename OutputIt, typename Char, typename F>
|
template <typename OutputIt, typename Char, typename F>
|
||||||
OutputIt write_int(OutputIt out, int num_digits, string_view prefix,
|
OutputIt write_int(OutputIt out, int num_digits, string_view prefix,
|
||||||
basic_format_specs<Char> specs, F f) {
|
const basic_format_specs<Char>& specs, F f) {
|
||||||
auto data = write_int_data<Char>(num_digits, prefix, specs);
|
auto data = write_int_data<Char>(num_digits, prefix, specs);
|
||||||
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
|
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
|
||||||
return write_padded(out, specs, data.size, [=](iterator it) {
|
return write_padded<align::right>(out, specs, data.size, [=](iterator it) {
|
||||||
if (prefix.size() != 0)
|
if (prefix.size() != 0)
|
||||||
it = copy_str<Char>(prefix.begin(), prefix.end(), it);
|
it = copy_str<Char>(prefix.begin(), prefix.end(), it);
|
||||||
it = std::fill_n(it, data.padding, static_cast<Char>('0'));
|
it = std::fill_n(it, data.padding, static_cast<Char>('0'));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user