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 char basic_data<T>::signs[] = {0, '-', '+', ' '};
|
||||
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 {
|
||||
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
|
||||
__attribute__((no_sanitize("undefined")))
|
||||
#endif
|
||||
inline checked_ptr<typename Container::value_type> reserve(
|
||||
std::back_insert_iterator<Container> it, std::size_t n) {
|
||||
inline checked_ptr<typename Container::value_type>
|
||||
reserve(std::back_insert_iterator<Container> 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 <typename T = void> 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<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.
|
||||
// size: output size in code units.
|
||||
// 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,
|
||||
const basic_format_specs<Char>& 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 <typename OutputIt, typename Char, typename F>
|
||||
template <align::type align = align::left, typename OutputIt, typename Char,
|
||||
typename F>
|
||||
inline OutputIt write_padded(OutputIt out,
|
||||
const basic_format_specs<Char>& specs, size_t size,
|
||||
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
|
||||
@ -1411,9 +1417,8 @@ template <typename Char> struct write_int_data {
|
||||
std::size_t padding;
|
||||
|
||||
write_int_data(int num_digits, string_view prefix,
|
||||
basic_format_specs<Char>& specs)
|
||||
: size(prefix.size() + to_unsigned(num_digits)),
|
||||
padding(0) {
|
||||
const basic_format_specs<Char>& 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 <typename Char> 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 <typename Char> struct write_int_data {
|
||||
// where <digits> are written by f(it).
|
||||
template <typename OutputIt, typename Char, typename F>
|
||||
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);
|
||||
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)
|
||||
it = copy_str<Char>(prefix.begin(), prefix.end(), it);
|
||||
it = std::fill_n(it, data.padding, static_cast<Char>('0'));
|
||||
|
Loading…
Reference in New Issue
Block a user