mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-15 07:20:05 +00:00
Refactor `format_specs` and related APIs to support variable-width fill (#1109), improve naming consistency, remove legacy setters (#940), and optimize layout.
This commit is contained in:
parent
8e0dcd20b3
commit
e4f84ee1c6
@ -715,7 +715,7 @@ struct chrono_formatter {
|
|||||||
template <typename Rep, typename Period, typename Char>
|
template <typename Rep, typename Period, typename Char>
|
||||||
struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||||
private:
|
private:
|
||||||
align_spec spec;
|
basic_format_specs<Char> spec;
|
||||||
int precision;
|
int precision;
|
||||||
typedef internal::arg_ref<Char> arg_ref_type;
|
typedef internal::arg_ref<Char> arg_ref_type;
|
||||||
arg_ref_type width_ref;
|
arg_ref_type width_ref;
|
||||||
@ -744,9 +744,9 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void on_error(const char* msg) { FMT_THROW(format_error(msg)); }
|
void on_error(const char* msg) { FMT_THROW(format_error(msg)); }
|
||||||
void on_fill(Char fill) { f.spec.fill_ = fill; }
|
void on_fill(Char fill) { f.spec.fill[0] = fill; }
|
||||||
void on_align(alignment align) { f.spec.align_ = align; }
|
void on_align(align_t align) { f.spec.align = align; }
|
||||||
void on_width(unsigned width) { f.spec.width_ = width; }
|
void on_width(unsigned width) { f.spec.width = width; }
|
||||||
void on_precision(unsigned precision) { f.precision = precision; }
|
void on_precision(unsigned precision) { f.precision = precision; }
|
||||||
void end_precision() {}
|
void end_precision() {}
|
||||||
|
|
||||||
@ -804,7 +804,7 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
|||||||
using range = internal::output_range<decltype(ctx.out()), Char>;
|
using range = internal::output_range<decltype(ctx.out()), Char>;
|
||||||
internal::basic_writer<range> w(range(ctx.out()));
|
internal::basic_writer<range> w(range(ctx.out()));
|
||||||
internal::handle_dynamic_spec<internal::width_checker>(
|
internal::handle_dynamic_spec<internal::width_checker>(
|
||||||
spec.width_, width_ref, ctx, format_str.begin());
|
spec.width, width_ref, ctx, format_str.begin());
|
||||||
internal::handle_dynamic_spec<internal::precision_checker>(
|
internal::handle_dynamic_spec<internal::precision_checker>(
|
||||||
precision, precision_ref, ctx, format_str.begin());
|
precision, precision_ref, ctx, format_str.begin());
|
||||||
if (begin == end || *begin == '}') {
|
if (begin == end || *begin == '}') {
|
||||||
|
@ -763,7 +763,7 @@ char* sprintf_format(Double value, internal::buffer<char>& buf,
|
|||||||
char format[max_format_size];
|
char format[max_format_size];
|
||||||
char* format_ptr = format;
|
char* format_ptr = format;
|
||||||
*format_ptr++ = '%';
|
*format_ptr++ = '%';
|
||||||
if (spec.has(HASH_FLAG) || !spec.type) *format_ptr++ = '#';
|
if (spec.alt || !spec.type) *format_ptr++ = '#';
|
||||||
if (spec.precision >= 0) {
|
if (spec.precision >= 0) {
|
||||||
*format_ptr++ = '.';
|
*format_ptr++ = '.';
|
||||||
*format_ptr++ = '*';
|
*format_ptr++ = '*';
|
||||||
|
@ -898,53 +898,74 @@ FMT_API void format_windows_error(fmt::internal::buffer<char>& out,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T = void> struct null {};
|
template <typename T = void> struct null {};
|
||||||
|
|
||||||
|
// Workaround an array initialization issue in gcc 4.8.
|
||||||
|
template <typename Char> struct fill_t {
|
||||||
|
private:
|
||||||
|
Char data_[6];
|
||||||
|
|
||||||
|
public:
|
||||||
|
FMT_CONSTEXPR Char& operator[](size_t index) { return data_[index]; }
|
||||||
|
FMT_CONSTEXPR const Char& operator[](size_t index) const {
|
||||||
|
return data_[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
static FMT_CONSTEXPR fill_t<Char> make() {
|
||||||
|
auto fill = fill_t<Char>();
|
||||||
|
fill[0] = Char(' ');
|
||||||
|
return fill;
|
||||||
|
}
|
||||||
|
};
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
enum alignment {
|
// We cannot use enum classes as bit fields because of a gcc bug
|
||||||
ALIGN_DEFAULT,
|
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414.
|
||||||
ALIGN_LEFT,
|
namespace align {
|
||||||
ALIGN_RIGHT,
|
enum type { none, left, right, center, numeric };
|
||||||
ALIGN_CENTER,
|
}
|
||||||
ALIGN_NUMERIC
|
using align_t = align::type;
|
||||||
|
|
||||||
|
namespace sign {
|
||||||
|
enum type { none, minus, plus, space };
|
||||||
|
}
|
||||||
|
using sign_t = sign::type;
|
||||||
|
|
||||||
|
// Format specifiers for built-in and string types.
|
||||||
|
template <typename Char> struct basic_format_specs {
|
||||||
|
int width;
|
||||||
|
int precision;
|
||||||
|
char type;
|
||||||
|
align_t align : 4;
|
||||||
|
sign_t sign : 3;
|
||||||
|
bool alt : 1; // Alternate form ('#').
|
||||||
|
internal::fill_t<Char> fill;
|
||||||
|
|
||||||
|
constexpr basic_format_specs()
|
||||||
|
: width(0),
|
||||||
|
precision(-1),
|
||||||
|
type(0),
|
||||||
|
align(align::none),
|
||||||
|
sign(sign::none),
|
||||||
|
alt(false),
|
||||||
|
fill(internal::fill_t<Char>::make()) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flags.
|
using format_specs = basic_format_specs<char>;
|
||||||
enum { SIGN_FLAG = 1, PLUS_FLAG = 2, MINUS_FLAG = 4, HASH_FLAG = 8 };
|
|
||||||
|
|
||||||
// An alignment specifier.
|
namespace internal {
|
||||||
struct align_spec {
|
|
||||||
unsigned width_;
|
|
||||||
// Fill is always wchar_t and cast to char if necessary to avoid having
|
|
||||||
// two specialization of align_spec and its subclasses.
|
|
||||||
wchar_t fill_;
|
|
||||||
alignment align_;
|
|
||||||
|
|
||||||
FMT_CONSTEXPR align_spec() : width_(0), fill_(' '), align_(ALIGN_DEFAULT) {}
|
|
||||||
FMT_CONSTEXPR unsigned width() const { return width_; }
|
|
||||||
FMT_CONSTEXPR wchar_t fill() const { return fill_; }
|
|
||||||
FMT_CONSTEXPR alignment align() const { return align_; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct core_format_specs {
|
struct core_format_specs {
|
||||||
int precision;
|
int precision;
|
||||||
uint_least8_t flags;
|
|
||||||
char type;
|
char type;
|
||||||
|
bool alt : 1;
|
||||||
|
|
||||||
FMT_CONSTEXPR core_format_specs() : precision(-1), flags(0), type(0) {}
|
template <typename Char>
|
||||||
FMT_CONSTEXPR bool has(unsigned f) const { return (flags & f) != 0; }
|
constexpr core_format_specs(basic_format_specs<Char> specs)
|
||||||
FMT_CONSTEXPR bool has_precision() const { return precision != -1; }
|
: precision(specs.precision), type(specs.type), alt(specs.alt) {}
|
||||||
|
|
||||||
|
constexpr bool has_precision() const { return precision >= 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Format specifiers.
|
|
||||||
template <typename Char>
|
|
||||||
struct basic_format_specs : align_spec, core_format_specs {
|
|
||||||
FMT_CONSTEXPR basic_format_specs() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef basic_format_specs<char> format_specs;
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
namespace grisu_options {
|
namespace grisu_options {
|
||||||
enum { fixed = 1, grisu3 = 2 };
|
enum { fixed = 1, grisu3 = 2 };
|
||||||
}
|
}
|
||||||
@ -1117,7 +1138,7 @@ FMT_CONSTEXPR void handle_char_specs(const basic_format_specs<Char>* specs,
|
|||||||
Handler&& handler) {
|
Handler&& handler) {
|
||||||
if (!specs) return handler.on_char();
|
if (!specs) return handler.on_char();
|
||||||
if (specs->type && specs->type != 'c') return handler.on_int();
|
if (specs->type && specs->type != 'c') return handler.on_int();
|
||||||
if (specs->align() == ALIGN_NUMERIC || specs->flags != 0)
|
if (specs->align == align::numeric || specs->sign != sign::none || specs->alt)
|
||||||
handler.on_error("invalid format specifier for char");
|
handler.on_error("invalid format specifier for char");
|
||||||
handler.on_char();
|
handler.on_char();
|
||||||
}
|
}
|
||||||
@ -1262,20 +1283,20 @@ template <typename Range> class basic_writer {
|
|||||||
template <typename Spec, typename F>
|
template <typename Spec, typename F>
|
||||||
void write_int(int num_digits, string_view prefix, const Spec& spec, F f) {
|
void write_int(int num_digits, string_view prefix, const Spec& spec, F f) {
|
||||||
std::size_t size = prefix.size() + internal::to_unsigned(num_digits);
|
std::size_t size = prefix.size() + internal::to_unsigned(num_digits);
|
||||||
char_type fill = static_cast<char_type>(spec.fill());
|
char_type fill = spec.fill[0];
|
||||||
std::size_t padding = 0;
|
std::size_t padding = 0;
|
||||||
if (spec.align() == ALIGN_NUMERIC) {
|
if (spec.align == align::numeric) {
|
||||||
if (spec.width() > size) {
|
if (internal::to_unsigned(spec.width) > size) {
|
||||||
padding = spec.width() - size;
|
padding = spec.width - size;
|
||||||
size = spec.width();
|
size = spec.width;
|
||||||
}
|
}
|
||||||
} else if (spec.precision > num_digits) {
|
} else if (spec.precision > num_digits) {
|
||||||
size = prefix.size() + internal::to_unsigned(spec.precision);
|
size = prefix.size() + internal::to_unsigned(spec.precision);
|
||||||
padding = internal::to_unsigned(spec.precision - num_digits);
|
padding = internal::to_unsigned(spec.precision - num_digits);
|
||||||
fill = static_cast<char_type>('0');
|
fill = static_cast<char_type>('0');
|
||||||
}
|
}
|
||||||
align_spec as = spec;
|
format_specs as = spec;
|
||||||
if (spec.align() == ALIGN_DEFAULT) as.align_ = ALIGN_RIGHT;
|
if (spec.align == align::none) as.align = align::right;
|
||||||
write_padded(as, padded_int_writer<F>{size, prefix, fill, padding, f});
|
write_padded(as, padded_int_writer<F>{size, prefix, fill, padding, f});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1312,8 +1333,8 @@ template <typename Range> class basic_writer {
|
|||||||
prefix[0] = '-';
|
prefix[0] = '-';
|
||||||
++prefix_size;
|
++prefix_size;
|
||||||
abs_value = 0 - abs_value;
|
abs_value = 0 - abs_value;
|
||||||
} else if (spec.has(SIGN_FLAG)) {
|
} else if (spec.sign != sign::none && spec.sign != sign::minus) {
|
||||||
prefix[0] = spec.has(PLUS_FLAG) ? '+' : ' ';
|
prefix[0] = spec.sign == sign::plus ? '+' : ' ';
|
||||||
++prefix_size;
|
++prefix_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1344,9 +1365,9 @@ template <typename Range> class basic_writer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void on_hex() {
|
void on_hex() {
|
||||||
if (spec.has(HASH_FLAG)) {
|
if (spec.alt) {
|
||||||
prefix[prefix_size++] = '0';
|
prefix[prefix_size++] = '0';
|
||||||
prefix[prefix_size++] = static_cast<char>(spec.type);
|
prefix[prefix_size++] = spec.type;
|
||||||
}
|
}
|
||||||
int num_digits = internal::count_digits<4>(abs_value);
|
int num_digits = internal::count_digits<4>(abs_value);
|
||||||
writer.write_int(num_digits, get_prefix(), spec,
|
writer.write_int(num_digits, get_prefix(), spec,
|
||||||
@ -1363,7 +1384,7 @@ template <typename Range> class basic_writer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void on_bin() {
|
void on_bin() {
|
||||||
if (spec.has(HASH_FLAG)) {
|
if (spec.alt) {
|
||||||
prefix[prefix_size++] = '0';
|
prefix[prefix_size++] = '0';
|
||||||
prefix[prefix_size++] = static_cast<char>(spec.type);
|
prefix[prefix_size++] = static_cast<char>(spec.type);
|
||||||
}
|
}
|
||||||
@ -1374,7 +1395,7 @@ template <typename Range> class basic_writer {
|
|||||||
|
|
||||||
void on_oct() {
|
void on_oct() {
|
||||||
int num_digits = internal::count_digits<3>(abs_value);
|
int num_digits = internal::count_digits<3>(abs_value);
|
||||||
if (spec.has(HASH_FLAG) && spec.precision <= num_digits) {
|
if (spec.alt && spec.precision <= num_digits) {
|
||||||
// Octal prefix '0' is counted as a digit, so only add it if precision
|
// Octal prefix '0' is counted as a digit, so only add it if precision
|
||||||
// is not greater than the number of digits.
|
// is not greater than the number of digits.
|
||||||
prefix[prefix_size++] = '0';
|
prefix[prefix_size++] = '0';
|
||||||
@ -1538,18 +1559,18 @@ template <typename Range> class basic_writer {
|
|||||||
// Writes a value in the format
|
// Writes a value in the format
|
||||||
// <left-padding><value><right-padding>
|
// <left-padding><value><right-padding>
|
||||||
// where <value> is written by f(it).
|
// where <value> is written by f(it).
|
||||||
template <typename F> void write_padded(const align_spec& spec, F&& f) {
|
template <typename F> void write_padded(const format_specs& spec, F&& f) {
|
||||||
unsigned width = spec.width(); // User-perceived width (in code points).
|
unsigned width = spec.width; // User-perceived width (in code points).
|
||||||
size_t size = f.size(); // The number of code units.
|
size_t size = f.size(); // The number of code units.
|
||||||
size_t num_code_points = width != 0 ? f.width() : size;
|
size_t num_code_points = width != 0 ? f.width() : size;
|
||||||
if (width <= num_code_points) return f(reserve(size));
|
if (width <= num_code_points) return f(reserve(size));
|
||||||
auto&& it = reserve(width + (size - num_code_points));
|
auto&& it = reserve(width + (size - num_code_points));
|
||||||
char_type fill = static_cast<char_type>(spec.fill());
|
char_type fill = spec.fill[0];
|
||||||
std::size_t padding = width - num_code_points;
|
std::size_t padding = width - num_code_points;
|
||||||
if (spec.align() == ALIGN_RIGHT) {
|
if (spec.align == align::right) {
|
||||||
it = std::fill_n(it, padding, fill);
|
it = std::fill_n(it, padding, fill);
|
||||||
f(it);
|
f(it);
|
||||||
} else if (spec.align() == ALIGN_CENTER) {
|
} else if (spec.align == align::center) {
|
||||||
std::size_t left_padding = padding / 2;
|
std::size_t left_padding = padding / 2;
|
||||||
it = std::fill_n(it, left_padding, fill);
|
it = std::fill_n(it, left_padding, fill);
|
||||||
f(it);
|
f(it);
|
||||||
@ -1584,7 +1605,7 @@ template <typename Range> class basic_writer {
|
|||||||
FMT_ENABLE_IF(std::is_integral<T>::value)>
|
FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||||
void write(T value, FormatSpec spec, FormatSpecs... specs) {
|
void write(T value, FormatSpec spec, FormatSpecs... specs) {
|
||||||
format_specs s(spec, specs...);
|
format_specs s(spec, specs...);
|
||||||
s.align_ = ALIGN_RIGHT;
|
s.align = align::right;
|
||||||
write_int(value, s);
|
write_int(value, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1635,7 +1656,7 @@ template <typename Range> class basic_writer {
|
|||||||
|
|
||||||
// Writes a formatted string.
|
// Writes a formatted string.
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
void write(const Char* s, std::size_t size, const align_spec& spec) {
|
void write(const Char* s, std::size_t size, const format_specs& spec) {
|
||||||
write_padded(spec, str_writer<Char>{s, size});
|
write_padded(spec, str_writer<Char>{s, size});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1650,12 +1671,12 @@ template <typename Range> class basic_writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename UIntPtr>
|
template <typename UIntPtr>
|
||||||
void write_pointer(UIntPtr value, const align_spec* spec) {
|
void write_pointer(UIntPtr value, const format_specs* spec) {
|
||||||
int num_digits = internal::count_digits<4>(value);
|
int num_digits = internal::count_digits<4>(value);
|
||||||
auto pw = pointer_writer<UIntPtr>{value, num_digits};
|
auto pw = pointer_writer<UIntPtr>{value, num_digits};
|
||||||
if (!spec) return pw(reserve(num_digits + 2));
|
if (!spec) return pw(reserve(num_digits + 2));
|
||||||
align_spec as = *spec;
|
format_specs as = *spec;
|
||||||
if (as.align() == ALIGN_DEFAULT) as.align_ = ALIGN_RIGHT;
|
if (as.align == align::none) as.align = align::right;
|
||||||
write_padded(as, pw);
|
write_padded(as, pw);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1907,19 +1928,19 @@ template <typename Char> class specs_setter {
|
|||||||
FMT_CONSTEXPR specs_setter(const specs_setter& other)
|
FMT_CONSTEXPR specs_setter(const specs_setter& other)
|
||||||
: specs_(other.specs_) {}
|
: specs_(other.specs_) {}
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_align(alignment align) { specs_.align_ = align; }
|
FMT_CONSTEXPR void on_align(align_t align) { specs_.align = align; }
|
||||||
FMT_CONSTEXPR void on_fill(Char fill) { specs_.fill_ = fill; }
|
FMT_CONSTEXPR void on_fill(Char fill) { specs_.fill[0] = fill; }
|
||||||
FMT_CONSTEXPR void on_plus() { specs_.flags |= SIGN_FLAG | PLUS_FLAG; }
|
FMT_CONSTEXPR void on_plus() { specs_.sign = sign::plus; }
|
||||||
FMT_CONSTEXPR void on_minus() { specs_.flags |= MINUS_FLAG; }
|
FMT_CONSTEXPR void on_minus() { specs_.sign = sign::minus; }
|
||||||
FMT_CONSTEXPR void on_space() { specs_.flags |= SIGN_FLAG; }
|
FMT_CONSTEXPR void on_space() { specs_.sign = sign::space; }
|
||||||
FMT_CONSTEXPR void on_hash() { specs_.flags |= HASH_FLAG; }
|
FMT_CONSTEXPR void on_hash() { specs_.alt = true; }
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_zero() {
|
FMT_CONSTEXPR void on_zero() {
|
||||||
specs_.align_ = ALIGN_NUMERIC;
|
specs_.align = align::numeric;
|
||||||
specs_.fill_ = '0';
|
specs_.fill[0] = Char('0');
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_width(unsigned width) { specs_.width_ = width; }
|
FMT_CONSTEXPR void on_width(unsigned width) { specs_.width = width; }
|
||||||
FMT_CONSTEXPR void on_precision(unsigned precision) {
|
FMT_CONSTEXPR void on_precision(unsigned precision) {
|
||||||
specs_.precision = static_cast<int>(precision);
|
specs_.precision = static_cast<int>(precision);
|
||||||
}
|
}
|
||||||
@ -1971,8 +1992,8 @@ template <typename Handler> class specs_checker : public Handler {
|
|||||||
FMT_CONSTEXPR specs_checker(const specs_checker& other)
|
FMT_CONSTEXPR specs_checker(const specs_checker& other)
|
||||||
: Handler(other), checker_(*this, other.arg_type_) {}
|
: Handler(other), checker_(*this, other.arg_type_) {}
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_align(alignment align) {
|
FMT_CONSTEXPR void on_align(align_t align) {
|
||||||
if (align == ALIGN_NUMERIC) checker_.require_numeric_argument();
|
if (align == align::numeric) checker_.require_numeric_argument();
|
||||||
Handler::on_align(align);
|
Handler::on_align(align);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2039,7 +2060,7 @@ class specs_handler : public specs_setter<typename Context::char_type> {
|
|||||||
context_(ctx) {}
|
context_(ctx) {}
|
||||||
|
|
||||||
template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
|
template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
|
||||||
set_dynamic_spec<width_checker>(this->specs_.width_, get_arg(arg_id),
|
set_dynamic_spec<width_checker>(this->specs_.width, get_arg(arg_id),
|
||||||
context_.error_handler());
|
context_.error_handler());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2242,25 +2263,25 @@ template <typename Char, typename Handler>
|
|||||||
FMT_CONSTEXPR const Char* parse_align(const Char* begin, const Char* end,
|
FMT_CONSTEXPR const Char* parse_align(const Char* begin, const Char* end,
|
||||||
Handler&& handler) {
|
Handler&& handler) {
|
||||||
FMT_ASSERT(begin != end, "");
|
FMT_ASSERT(begin != end, "");
|
||||||
alignment align = ALIGN_DEFAULT;
|
auto align = align::none;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (begin + 1 != end) ++i;
|
if (begin + 1 != end) ++i;
|
||||||
do {
|
do {
|
||||||
switch (static_cast<char>(begin[i])) {
|
switch (static_cast<char>(begin[i])) {
|
||||||
case '<':
|
case '<':
|
||||||
align = ALIGN_LEFT;
|
align = align::left;
|
||||||
break;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
align = ALIGN_RIGHT;
|
align = align::right;
|
||||||
break;
|
break;
|
||||||
case '=':
|
case '=':
|
||||||
align = ALIGN_NUMERIC;
|
align = align::numeric;
|
||||||
break;
|
break;
|
||||||
case '^':
|
case '^':
|
||||||
align = ALIGN_CENTER;
|
align = align::center;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (align != ALIGN_DEFAULT) {
|
if (align != align::none) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
auto c = *begin;
|
auto c = *begin;
|
||||||
if (c == '{')
|
if (c == '{')
|
||||||
@ -2715,8 +2736,11 @@ void internal::basic_writer<Range>::write_double(T value,
|
|||||||
if (std::signbit(value)) {
|
if (std::signbit(value)) {
|
||||||
sign = '-';
|
sign = '-';
|
||||||
value = -value;
|
value = -value;
|
||||||
} else if (spec.has(SIGN_FLAG)) {
|
} else if (spec.sign != sign::none) {
|
||||||
sign = spec.has(PLUS_FLAG) ? '+' : ' ';
|
if (spec.sign == sign::plus)
|
||||||
|
sign = '+';
|
||||||
|
else if (spec.sign == sign::space)
|
||||||
|
sign = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!std::isfinite(value)) {
|
if (!std::isfinite(value)) {
|
||||||
@ -2732,7 +2756,7 @@ void internal::basic_writer<Range>::write_double(T value,
|
|||||||
|
|
||||||
memory_buffer buffer;
|
memory_buffer buffer;
|
||||||
int exp = 0;
|
int exp = 0;
|
||||||
int precision = spec.has_precision() || !spec.type ? spec.precision : 6;
|
int precision = spec.precision >= 0 || !spec.type ? spec.precision : 6;
|
||||||
unsigned options = handler.fixed ? internal::grisu_options::fixed : 0;
|
unsigned options = handler.fixed ? internal::grisu_options::fixed : 0;
|
||||||
bool use_grisu = USE_GRISU &&
|
bool use_grisu = USE_GRISU &&
|
||||||
(spec.type != 'a' && spec.type != 'A' && spec.type != 'e' &&
|
(spec.type != 'a' && spec.type != 'A' && spec.type != 'e' &&
|
||||||
@ -2747,17 +2771,17 @@ void internal::basic_writer<Range>::write_double(T value,
|
|||||||
buffer.push_back('%');
|
buffer.push_back('%');
|
||||||
--exp; // Adjust decimal place position.
|
--exp; // Adjust decimal place position.
|
||||||
}
|
}
|
||||||
align_spec as = spec;
|
format_specs as = spec;
|
||||||
if (spec.align() == ALIGN_NUMERIC) {
|
if (spec.align == align::numeric) {
|
||||||
if (sign) {
|
if (sign) {
|
||||||
auto&& it = reserve(1);
|
auto&& it = reserve(1);
|
||||||
*it++ = static_cast<char_type>(sign);
|
*it++ = static_cast<char_type>(sign);
|
||||||
sign = 0;
|
sign = 0;
|
||||||
if (as.width_) --as.width_;
|
if (as.width) --as.width;
|
||||||
}
|
}
|
||||||
as.align_ = ALIGN_RIGHT;
|
as.align = align::right;
|
||||||
} else if (spec.align() == ALIGN_DEFAULT) {
|
} else if (spec.align == align::none) {
|
||||||
as.align_ = ALIGN_RIGHT;
|
as.align = align::right;
|
||||||
}
|
}
|
||||||
char_type decimal_point = handler.use_locale
|
char_type decimal_point = handler.use_locale
|
||||||
? internal::decimal_point<char_type>(locale_)
|
? internal::decimal_point<char_type>(locale_)
|
||||||
@ -2766,8 +2790,8 @@ void internal::basic_writer<Range>::write_double(T value,
|
|||||||
auto params = internal::gen_digits_params();
|
auto params = internal::gen_digits_params();
|
||||||
params.fixed = handler.fixed;
|
params.fixed = handler.fixed;
|
||||||
params.num_digits = precision;
|
params.num_digits = precision;
|
||||||
params.trailing_zeros = (precision != 0 && (handler.fixed || !spec.type)) ||
|
params.trailing_zeros =
|
||||||
spec.has(HASH_FLAG);
|
(precision != 0 && (handler.fixed || !spec.type)) || spec.alt;
|
||||||
write_padded(as, grisu_writer(sign, buffer, exp, params, decimal_point));
|
write_padded(as, grisu_writer(sign, buffer, exp, params, decimal_point));
|
||||||
} else {
|
} else {
|
||||||
write_padded(as,
|
write_padded(as,
|
||||||
@ -2966,7 +2990,7 @@ struct formatter<T, Char,
|
|||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
|
auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||||
internal::handle_dynamic_spec<internal::width_checker>(
|
internal::handle_dynamic_spec<internal::width_checker>(
|
||||||
specs_.width_, specs_.width_ref, ctx, format_str_);
|
specs_.width, specs_.width_ref, ctx, format_str_);
|
||||||
internal::handle_dynamic_spec<internal::precision_checker>(
|
internal::handle_dynamic_spec<internal::precision_checker>(
|
||||||
specs_.precision, specs_.precision_ref, ctx, format_str_);
|
specs_.precision, specs_.precision_ref, ctx, format_str_);
|
||||||
using range_type =
|
using range_type =
|
||||||
@ -3031,7 +3055,7 @@ struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> {
|
|||||||
template <typename Char = char> class dynamic_formatter {
|
template <typename Char = char> class dynamic_formatter {
|
||||||
private:
|
private:
|
||||||
struct null_handler : internal::error_handler {
|
struct null_handler : internal::error_handler {
|
||||||
void on_align(alignment) {}
|
void on_align(align_t) {}
|
||||||
void on_plus() {}
|
void on_plus() {}
|
||||||
void on_minus() {}
|
void on_minus() {}
|
||||||
void on_space() {}
|
void on_space() {}
|
||||||
@ -3053,16 +3077,22 @@ template <typename Char = char> class dynamic_formatter {
|
|||||||
internal::specs_checker<null_handler> checker(
|
internal::specs_checker<null_handler> checker(
|
||||||
null_handler(),
|
null_handler(),
|
||||||
internal::mapped_type_constant<T, FormatContext>::value);
|
internal::mapped_type_constant<T, FormatContext>::value);
|
||||||
checker.on_align(specs_.align());
|
checker.on_align(specs_.align);
|
||||||
if (specs_.flags == 0)
|
switch (specs_.sign) {
|
||||||
; // Do nothing.
|
case sign::none:
|
||||||
else if (specs_.has(SIGN_FLAG))
|
break;
|
||||||
specs_.has(PLUS_FLAG) ? checker.on_plus() : checker.on_space();
|
case sign::plus:
|
||||||
else if (specs_.has(MINUS_FLAG))
|
checker.on_plus();
|
||||||
|
break;
|
||||||
|
case sign::minus:
|
||||||
checker.on_minus();
|
checker.on_minus();
|
||||||
else if (specs_.has(HASH_FLAG))
|
break;
|
||||||
checker.on_hash();
|
case sign::space:
|
||||||
if (specs_.precision != -1) checker.end_precision();
|
checker.on_space();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (specs_.alt) checker.on_hash();
|
||||||
|
if (specs_.precision >= 0) checker.end_precision();
|
||||||
typedef internal::output_range<typename FormatContext::iterator,
|
typedef internal::output_range<typename FormatContext::iterator,
|
||||||
typename FormatContext::char_type>
|
typename FormatContext::char_type>
|
||||||
range;
|
range;
|
||||||
@ -3074,7 +3104,7 @@ template <typename Char = char> class dynamic_formatter {
|
|||||||
private:
|
private:
|
||||||
template <typename Context> void handle_specs(Context& ctx) {
|
template <typename Context> void handle_specs(Context& ctx) {
|
||||||
internal::handle_dynamic_spec<internal::width_checker>(
|
internal::handle_dynamic_spec<internal::width_checker>(
|
||||||
specs_.width_, specs_.width_ref, ctx, format_str_);
|
specs_.width, specs_.width_ref, ctx, format_str_);
|
||||||
internal::handle_dynamic_spec<internal::precision_checker>(
|
internal::handle_dynamic_spec<internal::precision_checker>(
|
||||||
specs_.precision, specs_.precision_ref, ctx, format_str_);
|
specs_.precision, specs_.precision_ref, ctx, format_str_);
|
||||||
}
|
}
|
||||||
|
@ -293,7 +293,7 @@ class prepared_format {
|
|||||||
auto specs = value.spec.parsed_specs;
|
auto specs = value.spec.parsed_specs;
|
||||||
|
|
||||||
handle_dynamic_spec<internal::width_checker>(
|
handle_dynamic_spec<internal::width_checker>(
|
||||||
specs.width_, specs.width_ref, ctx, format_view.begin());
|
specs.width, specs.width_ref, ctx, format_view.begin());
|
||||||
handle_dynamic_spec<internal::precision_checker>(
|
handle_dynamic_spec<internal::precision_checker>(
|
||||||
specs.precision, specs.precision_ref, ctx, format_view.begin());
|
specs.precision, specs.precision_ref, ctx, format_view.begin());
|
||||||
|
|
||||||
@ -330,21 +330,10 @@ class prepared_format {
|
|||||||
internal::type arg_type) const {
|
internal::type arg_type) const {
|
||||||
internal::error_handler h;
|
internal::error_handler h;
|
||||||
numeric_specs_checker<internal::error_handler> checker(h, arg_type);
|
numeric_specs_checker<internal::error_handler> checker(h, arg_type);
|
||||||
if (specs.align_ == ALIGN_NUMERIC) {
|
if (specs.align == align::numeric) checker.require_numeric_argument();
|
||||||
checker.require_numeric_argument();
|
if (specs.sign != sign::none) checker.check_sign();
|
||||||
}
|
if (specs.alt) checker.require_numeric_argument();
|
||||||
|
if (specs.precision >= 0) checker.check_precision();
|
||||||
if (specs.has(PLUS_FLAG | MINUS_FLAG | SIGN_FLAG)) {
|
|
||||||
checker.check_sign();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (specs.has(HASH_FLAG)) {
|
|
||||||
checker.require_numeric_argument();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (specs.has_precision()) {
|
|
||||||
checker.check_precision();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -160,7 +160,7 @@ template <typename Char> class printf_width_handler {
|
|||||||
unsigned operator()(T value) {
|
unsigned operator()(T value) {
|
||||||
auto width = static_cast<uint32_or_64_t<T>>(value);
|
auto width = static_cast<uint32_or_64_t<T>>(value);
|
||||||
if (internal::is_negative(value)) {
|
if (internal::is_negative(value)) {
|
||||||
spec_.align_ = ALIGN_LEFT;
|
spec_.align = align::left;
|
||||||
width = 0 - width;
|
width = 0 - width;
|
||||||
}
|
}
|
||||||
unsigned int_max = std::numeric_limits<int>::max();
|
unsigned int_max = std::numeric_limits<int>::max();
|
||||||
@ -248,8 +248,9 @@ class printf_arg_formatter : public internal::arg_formatter_base<Range> {
|
|||||||
format_specs& fmt_spec = *this->spec();
|
format_specs& fmt_spec = *this->spec();
|
||||||
if (fmt_spec.type && fmt_spec.type != 'c')
|
if (fmt_spec.type && fmt_spec.type != 'c')
|
||||||
return (*this)(static_cast<int>(value));
|
return (*this)(static_cast<int>(value));
|
||||||
fmt_spec.flags = 0;
|
fmt_spec.sign = sign::none;
|
||||||
fmt_spec.align_ = ALIGN_RIGHT;
|
fmt_spec.alt = false;
|
||||||
|
fmt_spec.align = align::right;
|
||||||
return base::operator()(value);
|
return base::operator()(value);
|
||||||
} else {
|
} else {
|
||||||
return base::operator()(value);
|
return base::operator()(value);
|
||||||
@ -378,19 +379,19 @@ void basic_printf_context<OutputIt, Char>::parse_flags(format_specs& spec,
|
|||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
switch (*it) {
|
switch (*it) {
|
||||||
case '-':
|
case '-':
|
||||||
spec.align_ = ALIGN_LEFT;
|
spec.align = align::left;
|
||||||
break;
|
break;
|
||||||
case '+':
|
case '+':
|
||||||
spec.flags |= SIGN_FLAG | PLUS_FLAG;
|
spec.sign = sign::plus;
|
||||||
break;
|
break;
|
||||||
case '0':
|
case '0':
|
||||||
spec.fill_ = '0';
|
spec.fill[0] = '0';
|
||||||
break;
|
break;
|
||||||
case ' ':
|
case ' ':
|
||||||
spec.flags |= SIGN_FLAG;
|
spec.sign = sign::space;
|
||||||
break;
|
break;
|
||||||
case '#':
|
case '#':
|
||||||
spec.flags |= HASH_FLAG;
|
spec.alt = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
@ -422,11 +423,11 @@ unsigned basic_printf_context<OutputIt, Char>::parse_header(
|
|||||||
++it;
|
++it;
|
||||||
arg_index = value;
|
arg_index = value;
|
||||||
} else {
|
} else {
|
||||||
if (c == '0') spec.fill_ = '0';
|
if (c == '0') spec.fill[0] = '0';
|
||||||
if (value != 0) {
|
if (value != 0) {
|
||||||
// Nonzero value means that we parsed width and don't need to
|
// Nonzero value means that we parsed width and don't need to
|
||||||
// parse it or flags again, so return now.
|
// parse it or flags again, so return now.
|
||||||
spec.width_ = value;
|
spec.width = value;
|
||||||
return arg_index;
|
return arg_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -436,10 +437,10 @@ unsigned basic_printf_context<OutputIt, Char>::parse_header(
|
|||||||
if (it != end) {
|
if (it != end) {
|
||||||
if (*it >= '0' && *it <= '9') {
|
if (*it >= '0' && *it <= '9') {
|
||||||
internal::error_handler eh;
|
internal::error_handler eh;
|
||||||
spec.width_ = parse_nonnegative_int(it, end, eh);
|
spec.width = parse_nonnegative_int(it, end, eh);
|
||||||
} else if (*it == '*') {
|
} else if (*it == '*') {
|
||||||
++it;
|
++it;
|
||||||
spec.width_ = visit_format_arg(
|
spec.width = visit_format_arg(
|
||||||
internal::printf_width_handler<char_type>(spec), get_arg());
|
internal::printf_width_handler<char_type>(spec), get_arg());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -464,7 +465,7 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
|||||||
out = std::copy(start, it - 1, out);
|
out = std::copy(start, it - 1, out);
|
||||||
|
|
||||||
format_specs spec;
|
format_specs spec;
|
||||||
spec.align_ = ALIGN_RIGHT;
|
spec.align = align::right;
|
||||||
|
|
||||||
// Parse argument index, flags and width.
|
// Parse argument index, flags and width.
|
||||||
unsigned arg_index = parse_header(it, end, spec);
|
unsigned arg_index = parse_header(it, end, spec);
|
||||||
@ -486,14 +487,13 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
format_arg arg = get_arg(arg_index);
|
format_arg arg = get_arg(arg_index);
|
||||||
if (spec.has(HASH_FLAG) && visit_format_arg(internal::is_zero_int(), arg))
|
if (spec.alt && visit_format_arg(internal::is_zero_int(), arg))
|
||||||
spec.flags = static_cast<uint_least8_t>(
|
spec.alt = false;
|
||||||
spec.flags & (~internal::to_unsigned<int>(HASH_FLAG)));
|
if (spec.fill[0] == '0') {
|
||||||
if (spec.fill_ == '0') {
|
|
||||||
if (arg.is_arithmetic())
|
if (arg.is_arithmetic())
|
||||||
spec.align_ = ALIGN_NUMERIC;
|
spec.align = align::numeric;
|
||||||
else
|
else
|
||||||
spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
|
spec.fill[0] = ' '; // Ignore '0' flag for non-numeric types.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse length and convert the argument to the required type.
|
// Parse length and convert the argument to the required type.
|
||||||
|
@ -690,7 +690,7 @@ struct formatter {
|
|||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
|
auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||||
fmt::internal::handle_dynamic_spec<fmt::internal::width_checker>(
|
fmt::internal::handle_dynamic_spec<fmt::internal::width_checker>(
|
||||||
specs_.width_, specs_.width_ref, ctx, nullptr);
|
specs_.width, specs_.width_ref, ctx, nullptr);
|
||||||
fmt::internal::handle_dynamic_spec<fmt::internal::precision_checker>(
|
fmt::internal::handle_dynamic_spec<fmt::internal::precision_checker>(
|
||||||
specs_.precision, specs_.precision_ref, ctx, nullptr);
|
specs_.precision, specs_.precision_ref, ctx, nullptr);
|
||||||
using range_type = fmt::internal::output_range<typename FormatContext::iterator,
|
using range_type = fmt::internal::output_range<typename FormatContext::iterator,
|
||||||
|
@ -2103,7 +2103,7 @@ struct test_format_specs_handler {
|
|||||||
enum Result { NONE, PLUS, MINUS, SPACE, HASH, ZERO, ERROR };
|
enum Result { NONE, PLUS, MINUS, SPACE, HASH, ZERO, ERROR };
|
||||||
Result res = NONE;
|
Result res = NONE;
|
||||||
|
|
||||||
fmt::alignment align_ = fmt::ALIGN_DEFAULT;
|
fmt::align_t align = fmt::align::none;
|
||||||
char fill = 0;
|
char fill = 0;
|
||||||
unsigned width = 0;
|
unsigned width = 0;
|
||||||
fmt::internal::arg_ref<char> width_ref;
|
fmt::internal::arg_ref<char> width_ref;
|
||||||
@ -2117,7 +2117,7 @@ struct test_format_specs_handler {
|
|||||||
FMT_CONSTEXPR test_format_specs_handler(
|
FMT_CONSTEXPR test_format_specs_handler(
|
||||||
const test_format_specs_handler& other)
|
const test_format_specs_handler& other)
|
||||||
: res(other.res),
|
: res(other.res),
|
||||||
align_(other.align_),
|
align(other.align),
|
||||||
fill(other.fill),
|
fill(other.fill),
|
||||||
width(other.width),
|
width(other.width),
|
||||||
width_ref(other.width_ref),
|
width_ref(other.width_ref),
|
||||||
@ -2125,7 +2125,7 @@ struct test_format_specs_handler {
|
|||||||
precision_ref(other.precision_ref),
|
precision_ref(other.precision_ref),
|
||||||
type(other.type) {}
|
type(other.type) {}
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_align(fmt::alignment a) { align_ = a; }
|
FMT_CONSTEXPR void on_align(fmt::align_t a) { align = a; }
|
||||||
FMT_CONSTEXPR void on_fill(char f) { fill = f; }
|
FMT_CONSTEXPR void on_fill(char f) { fill = f; }
|
||||||
FMT_CONSTEXPR void on_plus() { res = PLUS; }
|
FMT_CONSTEXPR void on_plus() { res = PLUS; }
|
||||||
FMT_CONSTEXPR void on_minus() { res = MINUS; }
|
FMT_CONSTEXPR void on_minus() { res = MINUS; }
|
||||||
@ -2159,7 +2159,7 @@ FMT_CONSTEXPR test_format_specs_handler parse_test_specs(const char (&s)[N]) {
|
|||||||
|
|
||||||
TEST(FormatTest, ConstexprParseFormatSpecs) {
|
TEST(FormatTest, ConstexprParseFormatSpecs) {
|
||||||
typedef test_format_specs_handler handler;
|
typedef test_format_specs_handler handler;
|
||||||
static_assert(parse_test_specs("<").align_ == fmt::ALIGN_LEFT, "");
|
static_assert(parse_test_specs("<").align == fmt::align::left, "");
|
||||||
static_assert(parse_test_specs("*^").fill == '*', "");
|
static_assert(parse_test_specs("*^").fill == '*', "");
|
||||||
static_assert(parse_test_specs("+").res == handler::PLUS, "");
|
static_assert(parse_test_specs("+").res == handler::PLUS, "");
|
||||||
static_assert(parse_test_specs("-").res == handler::MINUS, "");
|
static_assert(parse_test_specs("-").res == handler::MINUS, "");
|
||||||
@ -2216,16 +2216,16 @@ FMT_CONSTEXPR fmt::format_specs parse_specs(const char (&s)[N]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatTest, ConstexprSpecsHandler) {
|
TEST(FormatTest, ConstexprSpecsHandler) {
|
||||||
static_assert(parse_specs("<").align() == fmt::ALIGN_LEFT, "");
|
static_assert(parse_specs("<").align == fmt::align::left, "");
|
||||||
static_assert(parse_specs("*^").fill() == '*', "");
|
static_assert(parse_specs("*^").fill[0] == '*', "");
|
||||||
static_assert(parse_specs("+").has(fmt::PLUS_FLAG), "");
|
static_assert(parse_specs("+").sign == fmt::sign::plus, "");
|
||||||
static_assert(parse_specs("-").has(fmt::MINUS_FLAG), "");
|
static_assert(parse_specs("-").sign == fmt::sign::minus, "");
|
||||||
static_assert(parse_specs(" ").has(fmt::SIGN_FLAG), "");
|
static_assert(parse_specs(" ").sign == fmt::sign::space, "");
|
||||||
static_assert(parse_specs("#").has(fmt::HASH_FLAG), "");
|
static_assert(parse_specs("#").alt, "");
|
||||||
static_assert(parse_specs("0").align() == fmt::ALIGN_NUMERIC, "");
|
static_assert(parse_specs("0").align == fmt::align::numeric, "");
|
||||||
static_assert(parse_specs("42").width() == 42, "");
|
static_assert(parse_specs("42").width == 42, "");
|
||||||
static_assert(parse_specs("{}").width() == 11, "");
|
static_assert(parse_specs("{}").width == 11, "");
|
||||||
static_assert(parse_specs("{22}").width() == 22, "");
|
static_assert(parse_specs("{22}").width == 22, "");
|
||||||
static_assert(parse_specs(".42").precision == 42, "");
|
static_assert(parse_specs(".42").precision == 42, "");
|
||||||
static_assert(parse_specs(".{}").precision == 11, "");
|
static_assert(parse_specs(".{}").precision == 11, "");
|
||||||
static_assert(parse_specs(".{22}").precision == 22, "");
|
static_assert(parse_specs(".{22}").precision == 22, "");
|
||||||
@ -2243,14 +2243,14 @@ FMT_CONSTEXPR fmt::internal::dynamic_format_specs<char> parse_dynamic_specs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatTest, ConstexprDynamicSpecsHandler) {
|
TEST(FormatTest, ConstexprDynamicSpecsHandler) {
|
||||||
static_assert(parse_dynamic_specs("<").align() == fmt::ALIGN_LEFT, "");
|
static_assert(parse_dynamic_specs("<").align == fmt::align::left, "");
|
||||||
static_assert(parse_dynamic_specs("*^").fill() == '*', "");
|
static_assert(parse_dynamic_specs("*^").fill[0] == '*', "");
|
||||||
static_assert(parse_dynamic_specs("+").has(fmt::PLUS_FLAG), "");
|
static_assert(parse_dynamic_specs("+").sign == fmt::sign::plus, "");
|
||||||
static_assert(parse_dynamic_specs("-").has(fmt::MINUS_FLAG), "");
|
static_assert(parse_dynamic_specs("-").sign == fmt::sign::minus, "");
|
||||||
static_assert(parse_dynamic_specs(" ").has(fmt::SIGN_FLAG), "");
|
static_assert(parse_dynamic_specs(" ").sign == fmt::sign::space, "");
|
||||||
static_assert(parse_dynamic_specs("#").has(fmt::HASH_FLAG), "");
|
static_assert(parse_dynamic_specs("#").alt, "");
|
||||||
static_assert(parse_dynamic_specs("0").align() == fmt::ALIGN_NUMERIC, "");
|
static_assert(parse_dynamic_specs("0").align == fmt::align::numeric, "");
|
||||||
static_assert(parse_dynamic_specs("42").width() == 42, "");
|
static_assert(parse_dynamic_specs("42").width == 42, "");
|
||||||
static_assert(parse_dynamic_specs("{}").width_ref.val.index == 11, "");
|
static_assert(parse_dynamic_specs("{}").width_ref.val.index == 11, "");
|
||||||
static_assert(parse_dynamic_specs("{42}").width_ref.val.index == 42, "");
|
static_assert(parse_dynamic_specs("{42}").width_ref.val.index == 42, "");
|
||||||
static_assert(parse_dynamic_specs(".42").precision == 42, "");
|
static_assert(parse_dynamic_specs(".42").precision == 42, "");
|
||||||
@ -2269,7 +2269,7 @@ FMT_CONSTEXPR test_format_specs_handler check_specs(const char (&s)[N]) {
|
|||||||
|
|
||||||
TEST(FormatTest, ConstexprSpecsChecker) {
|
TEST(FormatTest, ConstexprSpecsChecker) {
|
||||||
typedef test_format_specs_handler handler;
|
typedef test_format_specs_handler handler;
|
||||||
static_assert(check_specs("<").align_ == fmt::ALIGN_LEFT, "");
|
static_assert(check_specs("<").align == fmt::align::left, "");
|
||||||
static_assert(check_specs("*^").fill == '*', "");
|
static_assert(check_specs("*^").fill == '*', "");
|
||||||
static_assert(check_specs("+").res == handler::PLUS, "");
|
static_assert(check_specs("+").res == handler::PLUS, "");
|
||||||
static_assert(check_specs("-").res == handler::MINUS, "");
|
static_assert(check_specs("-").res == handler::MINUS, "");
|
||||||
|
@ -71,12 +71,12 @@ bool operator==(const format_part<char>::specification& lhs,
|
|||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::tie(lhs.parsed_specs.width_, lhs.parsed_specs.fill_,
|
return std::tie(lhs.parsed_specs.width, lhs.parsed_specs.fill[0],
|
||||||
lhs.parsed_specs.align_, lhs.parsed_specs.precision,
|
lhs.parsed_specs.align, lhs.parsed_specs.precision,
|
||||||
lhs.parsed_specs.flags, lhs.parsed_specs.type) ==
|
lhs.parsed_specs.sign, lhs.parsed_specs.type) ==
|
||||||
std::tie(rhs.parsed_specs.width_, rhs.parsed_specs.fill_,
|
std::tie(rhs.parsed_specs.width, rhs.parsed_specs.fill[0],
|
||||||
rhs.parsed_specs.align_, rhs.parsed_specs.precision,
|
rhs.parsed_specs.align, rhs.parsed_specs.precision,
|
||||||
rhs.parsed_specs.flags, rhs.parsed_specs.type);
|
rhs.parsed_specs.sign, rhs.parsed_specs.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const format_part<char>::specification& lhs,
|
bool operator!=(const format_part<char>::specification& lhs,
|
||||||
@ -352,8 +352,8 @@ TEST(
|
|||||||
const auto last_part = format_part(0u);
|
const auto last_part = format_part(0u);
|
||||||
format_part::specification expected_specification(0u);
|
format_part::specification expected_specification(0u);
|
||||||
fmt::internal::dynamic_format_specs<char> specs{};
|
fmt::internal::dynamic_format_specs<char> specs{};
|
||||||
specs.align_ = fmt::alignment::ALIGN_LEFT;
|
specs.align = fmt::align::left;
|
||||||
specs.width_ = 10;
|
specs.width = 10;
|
||||||
expected_specification.parsed_specs = specs;
|
expected_specification.parsed_specs = specs;
|
||||||
|
|
||||||
auto expected_substitution_part = format_part(expected_specification);
|
auto expected_substitution_part = format_part(expected_specification);
|
||||||
@ -384,8 +384,8 @@ TEST(
|
|||||||
const auto last_part = format_part(format_part::named_argument_id(arg_id));
|
const auto last_part = format_part(format_part::named_argument_id(arg_id));
|
||||||
format_part::specification expected_specification(arg_id);
|
format_part::specification expected_specification(arg_id);
|
||||||
fmt::internal::dynamic_format_specs<char> specs{};
|
fmt::internal::dynamic_format_specs<char> specs{};
|
||||||
specs.align_ = fmt::alignment::ALIGN_LEFT;
|
specs.align = fmt::align::left;
|
||||||
specs.width_ = 10;
|
specs.width = 10;
|
||||||
expected_specification.parsed_specs = specs;
|
expected_specification.parsed_specs = specs;
|
||||||
|
|
||||||
auto expected_substitution_part = format_part(expected_specification);
|
auto expected_substitution_part = format_part(expected_specification);
|
||||||
|
Loading…
Reference in New Issue
Block a user