mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-30 18:57:34 +02:00
Make align a proper enum class
This commit is contained in:
@ -2060,11 +2060,6 @@ FMT_EXPORT using format_args = basic_format_args<format_context>;
|
|||||||
#else
|
#else
|
||||||
# define FMT_ENUM_UNDERLYING_TYPE(type) : type
|
# define FMT_ENUM_UNDERLYING_TYPE(type) : type
|
||||||
#endif
|
#endif
|
||||||
namespace align {
|
|
||||||
enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, left, right, center,
|
|
||||||
numeric};
|
|
||||||
}
|
|
||||||
using align_t = align::type;
|
|
||||||
namespace sign {
|
namespace sign {
|
||||||
enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, minus, plus, space};
|
enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, minus, plus, space};
|
||||||
}
|
}
|
||||||
@ -2119,10 +2114,12 @@ enum class presentation_type : unsigned char {
|
|||||||
hexfloat // 'a' or 'A'
|
hexfloat // 'a' or 'A'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class align { none, left, right, center, numeric };
|
||||||
|
|
||||||
// Basic format specifiers for built-in and string types.
|
// Basic format specifiers for built-in and string types.
|
||||||
class basic_specs {
|
class basic_specs {
|
||||||
private:
|
private:
|
||||||
// Upper 32-bit of data contain fill and lower 32-bit are arranged as follows:
|
// Data is arranged as follows:
|
||||||
//
|
//
|
||||||
// 0 1 2 3
|
// 0 1 2 3
|
||||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
@ -2159,7 +2156,7 @@ class basic_specs {
|
|||||||
max_fill_size = 4
|
max_fill_size = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned long long data_ = 1 << fill_size_shift;
|
unsigned long data_ = 1 << fill_size_shift;
|
||||||
|
|
||||||
// Character (code unit) type is erased to prevent template bloat.
|
// Character (code unit) type is erased to prevent template bloat.
|
||||||
char fill_data_[max_fill_size] = {' '};
|
char fill_data_[max_fill_size] = {' '};
|
||||||
@ -2176,10 +2173,10 @@ class basic_specs {
|
|||||||
data_ = (data_ & ~type_mask) | static_cast<unsigned>(t);
|
data_ = (data_ & ~type_mask) | static_cast<unsigned>(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr auto align() const -> align_t {
|
constexpr auto align() const -> align {
|
||||||
return static_cast<align_t>((data_ & align_mask) >> align_shift);
|
return static_cast<fmt::align>((data_ & align_mask) >> align_shift);
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR void set_align(align_t a) {
|
FMT_CONSTEXPR void set_align(fmt::align a) {
|
||||||
data_ = (data_ & ~align_mask) | (static_cast<unsigned>(a) << align_shift);
|
data_ = (data_ & ~align_mask) | (static_cast<unsigned>(a) << align_shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2346,7 +2343,7 @@ FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end,
|
|||||||
: error_value;
|
: error_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR inline auto parse_align(char c) -> align_t {
|
FMT_CONSTEXPR inline auto parse_align(char c) -> align {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '<':
|
case '<':
|
||||||
return align::left;
|
return align::left;
|
||||||
@ -2630,11 +2627,11 @@ FMT_CONSTEXPR auto parse_format_specs(const Char* begin, const Char* end,
|
|||||||
report_error("invalid fill character '{'");
|
report_error("invalid fill character '{'");
|
||||||
return begin;
|
return begin;
|
||||||
}
|
}
|
||||||
auto align = parse_align(to_ascii(*fill_end));
|
auto alignment = parse_align(to_ascii(*fill_end));
|
||||||
enter_state(state::align, align != align::none);
|
enter_state(state::align, alignment != align::none);
|
||||||
specs.set_fill(
|
specs.set_fill(
|
||||||
basic_string_view<Char>(begin, to_unsigned(fill_end - begin)));
|
basic_string_view<Char>(begin, to_unsigned(fill_end - begin)));
|
||||||
specs.set_align(align);
|
specs.set_align(alignment);
|
||||||
begin = fill_end + 1;
|
begin = fill_end + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1731,17 +1731,19 @@ FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n,
|
|||||||
// 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 Char, align::type align = align::left, typename OutputIt,
|
template <typename Char, align default_align = align::left, typename OutputIt,
|
||||||
typename F>
|
typename F>
|
||||||
FMT_CONSTEXPR auto write_padded(OutputIt out, const format_specs& specs,
|
FMT_CONSTEXPR auto write_padded(OutputIt out, const format_specs& specs,
|
||||||
size_t size, size_t width, F&& f) -> OutputIt {
|
size_t size, size_t width, F&& f) -> OutputIt {
|
||||||
static_assert(align == align::left || align == align::right, "");
|
static_assert(default_align == align::left || default_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;
|
||||||
// Shifts are encoded as string literals because static constexpr is not
|
// Shifts are encoded as string literals because static constexpr is not
|
||||||
// supported in constexpr functions.
|
// supported in constexpr functions.
|
||||||
auto* shifts = align == align::left ? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01";
|
auto* shifts =
|
||||||
size_t left_padding = padding >> shifts[specs.align()];
|
default_align == align::left ? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01";
|
||||||
|
size_t left_padding = padding >> shifts[static_cast<int>(specs.align())];
|
||||||
size_t right_padding = padding - left_padding;
|
size_t right_padding = padding - left_padding;
|
||||||
auto it = reserve(out, size + padding * specs.fill_size());
|
auto it = reserve(out, size + padding * specs.fill_size());
|
||||||
if (left_padding != 0) it = fill<Char>(it, left_padding, specs);
|
if (left_padding != 0) it = fill<Char>(it, left_padding, specs);
|
||||||
@ -1750,17 +1752,17 @@ FMT_CONSTEXPR auto write_padded(OutputIt out, const format_specs& specs,
|
|||||||
return base_iterator(out, it);
|
return base_iterator(out, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char, align::type align = align::left, typename OutputIt,
|
template <typename Char, align default_align = align::left, typename OutputIt,
|
||||||
typename F>
|
typename F>
|
||||||
constexpr auto write_padded(OutputIt out, const format_specs& specs,
|
constexpr auto write_padded(OutputIt out, const format_specs& specs,
|
||||||
size_t size, F&& f) -> OutputIt {
|
size_t size, F&& f) -> OutputIt {
|
||||||
return write_padded<Char, align>(out, specs, size, size, f);
|
return write_padded<Char, default_align>(out, specs, size, size, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char, align::type align = align::left, typename OutputIt>
|
template <typename Char, align default_align = align::left, typename OutputIt>
|
||||||
FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes,
|
FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes,
|
||||||
const format_specs& specs = {}) -> OutputIt {
|
const format_specs& specs = {}) -> OutputIt {
|
||||||
return write_padded<Char, align>(
|
return write_padded<Char, default_align>(
|
||||||
out, specs, bytes.size(), [bytes](reserve_iterator<OutputIt> it) {
|
out, specs, bytes.size(), [bytes](reserve_iterator<OutputIt> it) {
|
||||||
const char* data = bytes.data();
|
const char* data = bytes.data();
|
||||||
return copy<Char>(data, data + bytes.size(), it);
|
return copy<Char>(data, data + bytes.size(), it);
|
||||||
@ -2321,22 +2323,22 @@ template <typename Char>
|
|||||||
FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
|
FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
|
||||||
format_specs& specs) -> const Char* {
|
format_specs& specs) -> const Char* {
|
||||||
FMT_ASSERT(begin != end, "");
|
FMT_ASSERT(begin != end, "");
|
||||||
auto align = align::none;
|
auto alignment = align::none;
|
||||||
auto p = begin + code_point_length(begin);
|
auto p = begin + code_point_length(begin);
|
||||||
if (end - p <= 0) p = begin;
|
if (end - p <= 0) p = begin;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
switch (to_ascii(*p)) {
|
switch (to_ascii(*p)) {
|
||||||
case '<':
|
case '<':
|
||||||
align = align::left;
|
alignment = align::left;
|
||||||
break;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
align = align::right;
|
alignment = align::right;
|
||||||
break;
|
break;
|
||||||
case '^':
|
case '^':
|
||||||
align = align::center;
|
alignment = align::center;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (align != align::none) {
|
if (alignment != align::none) {
|
||||||
if (p != begin) {
|
if (p != begin) {
|
||||||
auto c = *begin;
|
auto c = *begin;
|
||||||
if (c == '}') return begin;
|
if (c == '}') return begin;
|
||||||
@ -2355,7 +2357,7 @@ FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
|
|||||||
}
|
}
|
||||||
p = begin;
|
p = begin;
|
||||||
}
|
}
|
||||||
specs.set_align(align);
|
specs.set_align(alignment);
|
||||||
return begin;
|
return begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user