diff --git a/fmt/format.h b/fmt/format.h index e6ea86d4..9a7a99a9 100644 --- a/fmt/format.h +++ b/fmt/format.h @@ -1639,6 +1639,52 @@ enum { CHAR_FLAG = 0x10 // Argument has char type - used in error reporting. }; +enum format_spec_tag {fill_tag, align_tag, width_tag, type_tag}; + +// Format specifier. +template +class format_spec { + private: + T value_; + + public: + typedef T value_type; + + explicit format_spec(T value) : value_(value) {} + + T value() const { return value_; } +}; + +template +using fill_spec = format_spec; + +using width_spec = format_spec; +using type_spec = format_spec; + +class fill_spec_factory { + public: + constexpr fill_spec_factory() {} + + template + fill_spec operator=(Char value) const { + return fill_spec(value); + } +}; + +template +class format_spec_factory { + public: + constexpr format_spec_factory() {} + + FormatSpec operator=(typename FormatSpec::value_type value) const { + return FormatSpec(value); + } +}; + +constexpr fill_spec_factory fill; +constexpr format_spec_factory width; +constexpr format_spec_factory type; + // An empty format specifier. struct EmptySpec {}; @@ -1688,15 +1734,40 @@ struct AlignTypeSpec : AlignSpec { }; // A full format specifier. -struct FormatSpec : AlignSpec { +class FormatSpec : public AlignSpec { + private: + void set(fill_spec fill) { + fill_ = fill.value(); + } + + void set(width_spec width) { + width_ = width.value(); + } + + void set(type_spec type) { + type_ = type.value(); + } + + template + void set(Spec spec, Specs... tail) { + set(spec); + set(tail...); + } + + public: unsigned flags_; int precision_; char type_; - FormatSpec( - unsigned width = 0, char type = 0, wchar_t fill = ' ') + FormatSpec(unsigned width = 0, char type = 0, wchar_t fill = ' ') : AlignSpec(width, fill), flags_(0), precision_(-1), type_(type) {} + template + explicit FormatSpec(FormatSpecs... specs) + : AlignSpec(0, ' '), flags_(0), precision_(-1), type_(0){ + set(specs...); + } + bool flag(unsigned f) const { return (flags_ & f) != 0; } int precision() const { return precision_; } char type() const { return type_; } @@ -1811,13 +1882,6 @@ inline IntFormatSpec > pad( \ TYPE value, unsigned width) { \ return IntFormatSpec >( \ value, AlignTypeSpec<0>(width, ' ')); \ -} \ - \ -template \ -inline IntFormatSpec, Char> pad( \ - TYPE value, unsigned width, Char fill) { \ - return IntFormatSpec, Char>( \ - value, AlignTypeSpec<0>(width, fill)); \ } FMT_DEFINE_INT_FORMATTERS(int) @@ -2226,6 +2290,17 @@ class SystemError : public internal::RuntimeError { FMT_API void format_system_error(fmt::writer &out, int error_code, fmt::StringRef message) FMT_NOEXCEPT; +namespace internal { +// Named format specifier. +template +class named_format_spec { + public: + constexpr named_format_spec() {} +}; + +constexpr named_format_spec width; +} + /** \rst This template provides operations for formatting and writing data into @@ -2309,7 +2384,7 @@ class basic_writer { CharPtr prepare_int_buffer(unsigned num_digits, const Spec &spec, const char *prefix, unsigned prefix_size); - // Formats an integer. + // Writes a formatted integer. template void write_int(T value, Spec spec); @@ -2449,6 +2524,12 @@ class basic_writer { *this << IntFormatSpec(value); } + template + typename std::enable_if::value, void>::type + write(T value, FormatSpecs... specs) { + write_int(value, FormatSpec(specs...)); + } + void write(double value) { write_double(value, FormatSpec()); }