Parameterize format_specs on character type

This commit is contained in:
Victor Zverovich 2017-01-28 13:17:47 +00:00
parent 296e9cada2
commit bf0f107564
2 changed files with 29 additions and 8 deletions

View File

@ -1739,10 +1739,13 @@ struct AlignTypeSpec : AlignSpec {
}; };
// Format specifiers. // Format specifiers.
class format_specs : public AlignSpec { template <typename Char>
class basic_format_specs : public AlignSpec {
private: private:
template <typename Char> template <typename FillChar>
void set(fill_spec<Char> fill) { typename std::enable_if<std::is_same<FillChar, Char>::value ||
std::is_same<FillChar, char>::value, void>::type
set(fill_spec<FillChar> fill) {
fill_ = fill.value(); fill_ = fill.value();
} }
@ -1765,11 +1768,11 @@ class format_specs : public AlignSpec {
int precision_; int precision_;
char type_; char type_;
format_specs(unsigned width = 0, char type = 0, wchar_t fill = ' ') basic_format_specs(unsigned width = 0, char type = 0, wchar_t fill = ' ')
: AlignSpec(width, fill), flags_(0), precision_(-1), type_(type) {} : AlignSpec(width, fill), flags_(0), precision_(-1), type_(type) {}
template <typename... FormatSpecs> template <typename... FormatSpecs>
explicit format_specs(FormatSpecs... specs) explicit basic_format_specs(FormatSpecs... specs)
: AlignSpec(0, ' '), flags_(0), precision_(-1), type_(0){ : AlignSpec(0, ' '), flags_(0), precision_(-1), type_(0){
set(specs...); set(specs...);
} }
@ -1779,6 +1782,8 @@ class format_specs : public AlignSpec {
char type() const { return type_; } char type() const { return type_; }
}; };
typedef basic_format_specs<char> format_specs;
namespace internal { namespace internal {
template <typename Context> template <typename Context>
@ -1853,6 +1858,9 @@ void ArgMap<Context>::init(const basic_format_args<Context> &args) {
template <typename Char> template <typename Char>
class ArgFormatterBase { class ArgFormatterBase {
public:
typedef basic_format_specs<Char> format_specs;
private: private:
basic_writer<Char> &writer_; basic_writer<Char> &writer_;
format_specs &spec_; format_specs &spec_;
@ -2035,7 +2043,11 @@ class ArgFormatter : public internal::ArgFormatterBase<Char> {
private: private:
basic_format_context<Char> &ctx_; basic_format_context<Char> &ctx_;
typedef internal::ArgFormatterBase<Char> Base;
public: public:
typedef typename Base::format_specs format_specs;
/** /**
\rst \rst
Constructs an argument formatter object. Constructs an argument formatter object.
@ -2186,6 +2198,9 @@ constexpr named_format_spec<unsigned> width;
*/ */
template <typename Char> template <typename Char>
class basic_writer { class basic_writer {
public:
typedef basic_format_specs<Char> format_specs;
private: private:
// Output buffer. // Output buffer.
Buffer<Char> &buffer_; Buffer<Char> &buffer_;
@ -2461,7 +2476,7 @@ typename basic_writer<Char>::CharPtr basic_writer<Char>::write_str(
template <typename Char> template <typename Char>
template <typename StrChar> template <typename StrChar>
void basic_writer<Char>::write_str( void basic_writer<Char>::write_str(
BasicStringRef<StrChar> s, const format_specs &spec) { BasicStringRef<StrChar> s, const basic_writer<Char>::format_specs &spec) {
// Check if StrChar is convertible to Char. // Check if StrChar is convertible to Char.
internal::CharTraits<Char>::convert(StrChar()); internal::CharTraits<Char>::convert(StrChar());
if (spec.type_ && spec.type_ != 's') if (spec.type_ && spec.type_ != 's')
@ -3366,7 +3381,7 @@ template <typename ArgFormatter, typename Char, typename Context>
void do_format_arg(basic_writer<Char> &writer, basic_format_arg<Context> arg, void do_format_arg(basic_writer<Char> &writer, basic_format_arg<Context> arg,
Context &ctx) { Context &ctx) {
const Char *&s = ctx.ptr(); const Char *&s = ctx.ptr();
format_specs spec; basic_format_specs<Char> spec;
if (*s == ':') { if (*s == ':') {
if (visit(internal::CustomFormatter<Char, Context>(writer, ctx), arg)) if (visit(internal::CustomFormatter<Char, Context>(writer, ctx), arg))
return; return;

View File

@ -168,8 +168,11 @@ class CharConverter {
// Checks if an argument is a valid printf width specifier and sets // Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative. // left alignment if it is negative.
template <typename Char>
class PrintfWidthHandler { class PrintfWidthHandler {
private: private:
typedef basic_format_specs<Char> format_specs;
format_specs &spec_; format_specs &spec_;
FMT_DISALLOW_COPY_AND_ASSIGN(PrintfWidthHandler); FMT_DISALLOW_COPY_AND_ASSIGN(PrintfWidthHandler);
@ -217,6 +220,8 @@ class PrintfArgFormatter : public internal::ArgFormatterBase<Char> {
typedef internal::ArgFormatterBase<Char> Base; typedef internal::ArgFormatterBase<Char> Base;
public: public:
typedef typename Base::format_specs format_specs;
/** /**
\rst \rst
Constructs an argument formatter object. Constructs an argument formatter object.
@ -301,6 +306,7 @@ class printf_context :
private: private:
typedef internal::format_context_base<Char, printf_context> Base; typedef internal::format_context_base<Char, printf_context> Base;
typedef typename Base::format_arg format_arg; typedef typename Base::format_arg format_arg;
typedef basic_format_specs<Char> format_specs;
void parse_flags(format_specs &spec, const Char *&s); void parse_flags(format_specs &spec, const Char *&s);
@ -396,7 +402,7 @@ unsigned printf_context<Char, AF>::parse_header(
spec.width_ = internal::parse_nonnegative_int(s); spec.width_ = internal::parse_nonnegative_int(s);
} else if (*s == '*') { } else if (*s == '*') {
++s; ++s;
spec.width_ = visit(internal::PrintfWidthHandler(spec), get_arg(s)); spec.width_ = visit(internal::PrintfWidthHandler<Char>(spec), get_arg(s));
} }
return arg_index; return arg_index;
} }