Improve handling of alignment

This commit is contained in:
Victor Zverovich 2020-05-03 10:08:57 -07:00
parent a71bc9c825
commit 8efd1a8ef6
2 changed files with 20 additions and 14 deletions

View File

@ -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 =

View File

@ -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'));