Commit bd6fe569 authored by gabime's avatar gabime

astyle previous commits

parent d142f135
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -14,98 +14,101 @@ For the license information refer to format.h. ...@@ -14,98 +14,101 @@ For the license information refer to format.h.
// #include "format.h" // #include "format.h"
#include <ostream> #include <ostream>
namespace fmt { namespace fmt
{
namespace internal {
namespace internal
template <class Char> {
class FormatBuf: public std::basic_streambuf<Char>
{ template <class Char>
private: class FormatBuf: public std::basic_streambuf<Char>
typedef typename std::basic_streambuf<Char>::int_type int_type; {
typedef typename std::basic_streambuf<Char>::traits_type traits_type; private:
typedef typename std::basic_streambuf<Char>::int_type int_type;
Buffer<Char> &buffer_; typedef typename std::basic_streambuf<Char>::traits_type traits_type;
Char *start_;
Buffer<Char> &buffer_;
public: Char *start_;
FormatBuf(Buffer<Char> &buffer): buffer_(buffer), start_(&buffer[0])
{ public:
this->setp(start_, start_ + buffer_.capacity()); FormatBuf(Buffer<Char> &buffer): buffer_(buffer), start_(&buffer[0])
} {
this->setp(start_, start_ + buffer_.capacity());
int_type overflow(int_type ch = traits_type::eof()) }
{
if (!traits_type::eq_int_type(ch, traits_type::eof())) { int_type overflow(int_type ch = traits_type::eof())
size_t buf_size = size(); {
buffer_.resize(buf_size); if (!traits_type::eq_int_type(ch, traits_type::eof()))
buffer_.reserve(buf_size * 2); {
size_t buf_size = size();
start_ = &buffer_[0]; buffer_.resize(buf_size);
start_[buf_size] = traits_type::to_char_type(ch); buffer_.reserve(buf_size * 2);
this->setp(start_ + buf_size + 1, start_ + buf_size * 2);
} start_ = &buffer_[0];
return ch; start_[buf_size] = traits_type::to_char_type(ch);
} this->setp(start_ + buf_size + 1, start_ + buf_size * 2);
}
size_t size() const return ch;
{ }
return to_unsigned(this->pptr() - start_);
} size_t size() const
}; {
return to_unsigned(this->pptr() - start_);
Yes &convert(std::ostream &); }
};
struct DummyStream: std::ostream
{ Yes &convert(std::ostream &);
DummyStream(); // Suppress a bogus warning in MSVC.
// Hide all operator<< overloads from std::ostream. struct DummyStream: std::ostream
void operator<<(Null<>); {
}; DummyStream(); // Suppress a bogus warning in MSVC.
// Hide all operator<< overloads from std::ostream.
No &operator<<(std::ostream &, int); void operator<<(Null<>);
};
template<typename T>
struct ConvertToIntImpl<T, true> No &operator<<(std::ostream &, int);
{
// Convert to int only if T doesn't have an overloaded operator<<. template<typename T>
enum struct ConvertToIntImpl<T, true>
{ {
value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No) // Convert to int only if T doesn't have an overloaded operator<<.
}; enum
}; {
value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No)
// Write the content of w to os. };
void write(std::ostream &os, Writer &w); };
} // namespace internal
// Write the content of w to os.
// Formats a value. void write(std::ostream &os, Writer &w);
template <typename Char, typename ArgFormatter, typename T> } // namespace internal
void format_arg(BasicFormatter<Char, ArgFormatter> &f,
const Char *&format_str, const T &value) // Formats a value.
{ template <typename Char, typename ArgFormatter, typename T>
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer; void format_arg(BasicFormatter<Char, ArgFormatter> &f,
const Char *&format_str, const T &value)
internal::FormatBuf<Char> format_buf(buffer); {
std::basic_ostream<Char> output(&format_buf); internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
output << value;
internal::FormatBuf<Char> format_buf(buffer);
BasicStringRef<Char> str(&buffer[0], format_buf.size()); std::basic_ostream<Char> output(&format_buf);
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg; output << value;
format_str = f.format(format_str, MakeArg(str));
} BasicStringRef<Char> str(&buffer[0], format_buf.size());
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
/** format_str = f.format(format_str, MakeArg(str));
\rst }
Prints formatted data to the stream *os*.
/**
**Example**:: \rst
Prints formatted data to the stream *os*.
print(cerr, "Don't {}!", "panic");
\endrst **Example**::
*/
FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args); print(cerr, "Don't {}!", "panic");
FMT_VARIADIC(void, print, std::ostream &, CStringRef) \endrst
*/
FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args);
FMT_VARIADIC(void, print, std::ostream &, CStringRef)
} // namespace fmt } // namespace fmt
#ifdef FMT_HEADER_ONLY #ifdef FMT_HEADER_ONLY
......
...@@ -15,609 +15,640 @@ For the license information refer to format.h. ...@@ -15,609 +15,640 @@ For the license information refer to format.h.
#include "ostream.h" #include "ostream.h"
namespace fmt { namespace fmt
namespace internal { {
namespace internal
// Checks if a value fits in int - used to avoid warnings about comparing {
// signed and unsigned integers.
template <bool IsSigned> // Checks if a value fits in int - used to avoid warnings about comparing
struct IntChecker // signed and unsigned integers.
{ template <bool IsSigned>
template <typename T> struct IntChecker
static bool fits_in_int(T value) {
{ template <typename T>
unsigned max = std::numeric_limits<int>::max(); static bool fits_in_int(T value)
return value <= max; {
} unsigned max = std::numeric_limits<int>::max();
static bool fits_in_int(bool) return value <= max;
{ }
return true; static bool fits_in_int(bool)
} {
}; return true;
}
template <> };
struct IntChecker<true>
{ template <>
template <typename T> struct IntChecker<true>
static bool fits_in_int(T value) {
{ template <typename T>
return value >= std::numeric_limits<int>::min() && static bool fits_in_int(T value)
value <= std::numeric_limits<int>::max(); {
} return value >= std::numeric_limits<int>::min() &&
static bool fits_in_int(int) value <= std::numeric_limits<int>::max();
{ }
return true; static bool fits_in_int(int)
} {
}; return true;
}
class PrecisionHandler: public ArgVisitor<PrecisionHandler, int> };
{
public: class PrecisionHandler: public ArgVisitor<PrecisionHandler, int>
void report_unhandled_arg() {
{ public:
FMT_THROW(FormatError("precision is not integer")); void report_unhandled_arg()
} {
FMT_THROW(FormatError("precision is not integer"));
template <typename T> }
int visit_any_int(T value)
{ template <typename T>
if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value)) int visit_any_int(T value)
FMT_THROW(FormatError("number is too big")); {
return static_cast<int>(value); if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
} FMT_THROW(FormatError("number is too big"));
}; return static_cast<int>(value);
}
// IsZeroInt::visit(arg) returns true iff arg is a zero integer. };
class IsZeroInt: public ArgVisitor<IsZeroInt, bool>
{ // IsZeroInt::visit(arg) returns true iff arg is a zero integer.
public: class IsZeroInt: public ArgVisitor<IsZeroInt, bool>
template <typename T> {
bool visit_any_int(T value) public:
{ template <typename T>
return value == 0; bool visit_any_int(T value)
} {
}; return value == 0;
}
template <typename T, typename U> };
struct is_same
{ template <typename T, typename U>
enum struct is_same
{ {
value = 0 enum
}; {
}; value = 0
};
template <typename T> };
struct is_same<T, T>
{ template <typename T>
enum struct is_same<T, T>
{ {
value = 1 enum
}; {
}; value = 1
};
// An argument visitor that converts an integer argument to T for printf, };
// if T is an integral type. If T is void, the argument is converted to
// corresponding signed or unsigned type depending on the type specifier: // An argument visitor that converts an integer argument to T for printf,
// 'd' and 'i' - signed, other - unsigned) // if T is an integral type. If T is void, the argument is converted to
template <typename T = void> // corresponding signed or unsigned type depending on the type specifier:
class ArgConverter: public ArgVisitor<ArgConverter<T>, void> // 'd' and 'i' - signed, other - unsigned)
{ template <typename T = void>
private: class ArgConverter: public ArgVisitor<ArgConverter<T>, void>
internal::Arg &arg_; {
wchar_t type_; private:
internal::Arg &arg_;
FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter); wchar_t type_;
public: FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
ArgConverter(internal::Arg &arg, wchar_t type)
: arg_(arg), type_(type) public:
{} ArgConverter(internal::Arg &arg, wchar_t type)
: arg_(arg), type_(type)
void visit_bool(bool value) {}
{
if (type_ != 's') void visit_bool(bool value)
visit_any_int(value); {
} if (type_ != 's')
visit_any_int(value);
template <typename U> }
void visit_any_int(U value)
{ template <typename U>
bool is_signed = type_ == 'd' || type_ == 'i'; void visit_any_int(U value)
using internal::Arg; {
typedef typename internal::Conditional< bool is_signed = type_ == 'd' || type_ == 'i';
is_same<T, void>::value, U, T>::type TargetType; using internal::Arg;
if (sizeof(TargetType) <= sizeof(int)) { typedef typename internal::Conditional<
// Extra casts are used to silence warnings. is_same<T, void>::value, U, T>::type TargetType;
if (is_signed) { if (sizeof(TargetType) <= sizeof(int))
arg_.type = Arg::INT; {
arg_.int_value = static_cast<int>(static_cast<TargetType>(value)); // Extra casts are used to silence warnings.
} if (is_signed)
else { {
arg_.type = Arg::UINT; arg_.type = Arg::INT;
typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned; arg_.int_value = static_cast<int>(static_cast<TargetType>(value));
arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value)); }
} else
} {
else { arg_.type = Arg::UINT;
if (is_signed) { typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned;
arg_.type = Arg::LONG_LONG; arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value));
// glibc's printf doesn't sign extend arguments of smaller types: }
// std::printf("%lld", -42); // prints "4294967254" }
// but we don't have to do the same because it's a UB. else
arg_.long_long_value = static_cast<LongLong>(value); {
} if (is_signed)
else { {
arg_.type = Arg::ULONG_LONG; arg_.type = Arg::LONG_LONG;
arg_.ulong_long_value = // glibc's printf doesn't sign extend arguments of smaller types:
static_cast<typename internal::MakeUnsigned<U>::Type>(value); // std::printf("%lld", -42); // prints "4294967254"
} // but we don't have to do the same because it's a UB.
} arg_.long_long_value = static_cast<LongLong>(value);
} }
}; else
{
// Converts an integer argument to char for printf. arg_.type = Arg::ULONG_LONG;
class CharConverter: public ArgVisitor<CharConverter, void> arg_.ulong_long_value =
{ static_cast<typename internal::MakeUnsigned<U>::Type>(value);
private: }
internal::Arg &arg_; }
}
FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); };
public: // Converts an integer argument to char for printf.
explicit CharConverter(internal::Arg &arg): arg_(arg) class CharConverter: public ArgVisitor<CharConverter, void>
{} {
private:
template <typename T> internal::Arg &arg_;
void visit_any_int(T value)
{ FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
arg_.type = internal::Arg::CHAR;
arg_.int_value = static_cast<char>(value); public:
} explicit CharConverter(internal::Arg &arg): arg_(arg)
}; {}
// Checks if an argument is a valid printf width specifier and sets template <typename T>
// left alignment if it is negative. void visit_any_int(T value)
class WidthHandler: public ArgVisitor<WidthHandler, unsigned> {
{ arg_.type = internal::Arg::CHAR;
private: arg_.int_value = static_cast<char>(value);
FormatSpec &spec_; }
};
FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
// Checks if an argument is a valid printf width specifier and sets
public: // left alignment if it is negative.
explicit WidthHandler(FormatSpec &spec): spec_(spec) class WidthHandler: public ArgVisitor<WidthHandler, unsigned>
{} {
private:
void report_unhandled_arg() FormatSpec &spec_;
{
FMT_THROW(FormatError("width is not integer")); FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
}
public:
template <typename T> explicit WidthHandler(FormatSpec &spec): spec_(spec)
unsigned visit_any_int(T value) {}
{
typedef typename internal::IntTraits<T>::MainType UnsignedType; void report_unhandled_arg()
UnsignedType width = static_cast<UnsignedType>(value); {
if (internal::is_negative(value)) { FMT_THROW(FormatError("width is not integer"));
spec_.align_ = ALIGN_LEFT; }
width = 0 - width;
} template <typename T>
unsigned int_max = std::numeric_limits<int>::max(); unsigned visit_any_int(T value)
if (width > int_max) {
FMT_THROW(FormatError("number is too big")); typedef typename internal::IntTraits<T>::MainType UnsignedType;
return static_cast<unsigned>(width); UnsignedType width = static_cast<UnsignedType>(value);
} if (internal::is_negative(value))
}; {
} // namespace internal spec_.align_ = ALIGN_LEFT;
width = 0 - width;
/** }
\rst unsigned int_max = std::numeric_limits<int>::max();
A ``printf`` argument formatter based on the `curiously recurring template if (width > int_max)
pattern <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_. FMT_THROW(FormatError("number is too big"));
return static_cast<unsigned>(width);
To use `~fmt::BasicPrintfArgFormatter` define a subclass that implements some }
or all of the visit methods with the same signatures as the methods in };
`~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`. } // namespace internal
Pass the subclass as the *Impl* template parameter. When a formatting
function processes an argument, it will dispatch to a visit method /**
specific to the argument type. For example, if the argument type is \rst
``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass A ``printf`` argument formatter based on the `curiously recurring template
will be called. If the subclass doesn't contain a method with this signature, pattern <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_.
then a corresponding method of `~fmt::BasicPrintfArgFormatter` or its
superclass will be called. To use `~fmt::BasicPrintfArgFormatter` define a subclass that implements some
\endrst or all of the visit methods with the same signatures as the methods in
*/ `~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`.
template <typename Impl, typename Char> Pass the subclass as the *Impl* template parameter. When a formatting
class BasicPrintfArgFormatter: public internal::ArgFormatterBase<Impl, Char> function processes an argument, it will dispatch to a visit method
{ specific to the argument type. For example, if the argument type is
private: ``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass
void write_null_pointer() will be called. If the subclass doesn't contain a method with this signature,
{ then a corresponding method of `~fmt::BasicPrintfArgFormatter` or its
this->spec().type_ = 0; superclass will be called.
this->write("(nil)"); \endrst
} */
template <typename Impl, typename Char>
typedef internal::ArgFormatterBase<Impl, Char> Base; class BasicPrintfArgFormatter: public internal::ArgFormatterBase<Impl, Char>
{
public: private:
/** void write_null_pointer()
\rst {
Constructs an argument formatter object. this->spec().type_ = 0;
*writer* is a reference to the output writer and *spec* contains format this->write("(nil)");
specifier information for standard argument types. }
\endrst
*/ typedef internal::ArgFormatterBase<Impl, Char> Base;
BasicPrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
: internal::ArgFormatterBase<Impl, Char>(w, s) public:
{} /**
\rst
/** Formats an argument of type ``bool``. */ Constructs an argument formatter object.
void visit_bool(bool value) *writer* is a reference to the output writer and *spec* contains format
{ specifier information for standard argument types.
FormatSpec &fmt_spec = this->spec(); \endrst
if (fmt_spec.type_ != 's') */
return this->visit_any_int(value); BasicPrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
fmt_spec.type_ = 0; : internal::ArgFormatterBase<Impl, Char>(w, s)
this->write(value); {}
}
/** Formats an argument of type ``bool``. */
/** Formats a character. */ void visit_bool(bool value)
void visit_char(int value) {
{ FormatSpec &fmt_spec = this->spec();
const FormatSpec &fmt_spec = this->spec(); if (fmt_spec.type_ != 's')
BasicWriter<Char> &w = this->writer(); return this->visit_any_int(value);
if (fmt_spec.type_ && fmt_spec.type_ != 'c') fmt_spec.type_ = 0;
w.write_int(value, fmt_spec); this->write(value);
typedef typename BasicWriter<Char>::CharPtr CharPtr; }
CharPtr out = CharPtr();
if (fmt_spec.width_ > 1) { /** Formats a character. */
Char fill = ' '; void visit_char(int value)
out = w.grow_buffer(fmt_spec.width_); {
if (fmt_spec.align_ != ALIGN_LEFT) { const FormatSpec &fmt_spec = this->spec();
std::fill_n(out, fmt_spec.width_ - 1, fill); BasicWriter<Char> &w = this->writer();
out += fmt_spec.width_ - 1; if (fmt_spec.type_ && fmt_spec.type_ != 'c')
} w.write_int(value, fmt_spec);
else { typedef typename BasicWriter<Char>::CharPtr CharPtr;
std::fill_n(out + 1, fmt_spec.width_ - 1, fill); CharPtr out = CharPtr();
} if (fmt_spec.width_ > 1)
} {
else { Char fill = ' ';
out = w.grow_buffer(1); out = w.grow_buffer(fmt_spec.width_);
} if (fmt_spec.align_ != ALIGN_LEFT)
*out = static_cast<Char>(value); {
} std::fill_n(out, fmt_spec.width_ - 1, fill);
out += fmt_spec.width_ - 1;
/** Formats a null-terminated C string. */ }
void visit_cstring(const char *value) else
{ {
if (value) std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
Base::visit_cstring(value); }
else if (this->spec().type_ == 'p') }
write_null_pointer(); else
else {
this->write("(null)"); out = w.grow_buffer(1);
} }
*out = static_cast<Char>(value);
/** Formats a pointer. */ }
void visit_pointer(const void *value)
{ /** Formats a null-terminated C string. */
if (value) void visit_cstring(const char *value)
return Base::visit_pointer(value); {
this->spec().type_ = 0; if (value)
write_null_pointer(); Base::visit_cstring(value);
} else if (this->spec().type_ == 'p')
write_null_pointer();
/** Formats an argument of a custom (user-defined) type. */ else
void visit_custom(internal::Arg::CustomValue c) this->write("(null)");
{ }
BasicFormatter<Char> formatter(ArgList(), this->writer());
const Char format_str[] = { '}', 0 }; /** Formats a pointer. */
const Char *format = format_str; void visit_pointer(const void *value)
c.format(&formatter, c.value, &format); {
} if (value)
}; return Base::visit_pointer(value);
this->spec().type_ = 0;
/** The default printf argument formatter. */ write_null_pointer();
template <typename Char> }
class PrintfArgFormatter
: public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char> /** Formats an argument of a custom (user-defined) type. */
{ void visit_custom(internal::Arg::CustomValue c)
public: {
/** Constructs an argument formatter object. */ BasicFormatter<Char> formatter(ArgList(), this->writer());
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s) const Char format_str[] = { '}', 0 };
: BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char>(w, s) const Char *format = format_str;
{} c.format(&formatter, c.value, &format);
}; }
};
/** This template formats data and writes the output to a writer. */
template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char> > /** The default printf argument formatter. */
class PrintfFormatter: private internal::FormatterBase template <typename Char>
{ class PrintfArgFormatter
private: : public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char>
BasicWriter<Char> &writer_; {
public:
void parse_flags(FormatSpec &spec, const Char *&s); /** Constructs an argument formatter object. */
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
// Returns the argument with specified index or, if arg_index is equal : BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char>(w, s)
// to the maximum unsigned value, the next argument. {}
internal::Arg get_arg( };
const Char *s,
unsigned arg_index = (std::numeric_limits<unsigned>::max)()); /** This template formats data and writes the output to a writer. */
template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char> >
// Parses argument index, flags and width and returns the argument index. class PrintfFormatter: private internal::FormatterBase
unsigned parse_header(const Char *&s, FormatSpec &spec); {
private:
public: BasicWriter<Char> &writer_;
/**
\rst void parse_flags(FormatSpec &spec, const Char *&s);
Constructs a ``PrintfFormatter`` object. References to the arguments and
the writer are stored in the formatter object so make sure they have // Returns the argument with specified index or, if arg_index is equal
appropriate lifetimes. // to the maximum unsigned value, the next argument.
\endrst internal::Arg get_arg(
*/ const Char *s,
explicit PrintfFormatter(const ArgList &al, BasicWriter<Char> &w) unsigned arg_index = (std::numeric_limits<unsigned>::max)());
: FormatterBase(al), writer_(w)
{} // Parses argument index, flags and width and returns the argument index.
unsigned parse_header(const Char *&s, FormatSpec &spec);
/** Formats stored arguments and writes the output to the writer. */
FMT_API void format(BasicCStringRef<Char> format_str); public:
}; /**
\rst
template <typename Char, typename AF> Constructs a ``PrintfFormatter`` object. References to the arguments and
void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s) the writer are stored in the formatter object so make sure they have
{ appropriate lifetimes.
for (;;) { \endrst
switch (*s++) { */
case '-': explicit PrintfFormatter(const ArgList &al, BasicWriter<Char> &w)
spec.align_ = ALIGN_LEFT; : FormatterBase(al), writer_(w)
break; {}
case '+':
spec.flags_ |= SIGN_FLAG | PLUS_FLAG; /** Formats stored arguments and writes the output to the writer. */
break; FMT_API void format(BasicCStringRef<Char> format_str);
case '0': };
spec.fill_ = '0';
break; template <typename Char, typename AF>
case ' ': void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s)
spec.flags_ |= SIGN_FLAG; {
break; for (;;)
case '#': {
spec.flags_ |= HASH_FLAG; switch (*s++)
break; {
default: case '-':
--s; spec.align_ = ALIGN_LEFT;
return; break;
} case '+':
} spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
} break;
case '0':
template <typename Char, typename AF> spec.fill_ = '0';
internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s, break;
unsigned arg_index) case ' ':
{ spec.flags_ |= SIGN_FLAG;
(void)s; break;
const char *error = FMT_NULL; case '#':
internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ? spec.flags_ |= HASH_FLAG;
next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); break;
if (error) default:
FMT_THROW(FormatError(!*s ? "invalid format string" : error)); --s;
return arg; return;
} }
}
template <typename Char, typename AF> }
unsigned PrintfFormatter<Char, AF>::parse_header(
const Char *&s, FormatSpec &spec) template <typename Char, typename AF>
{ internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
unsigned arg_index = std::numeric_limits<unsigned>::max(); unsigned arg_index)
Char c = *s; {
if (c >= '0' && c <= '9') { (void)s;
// Parse an argument index (if followed by '$') or a width possibly const char *error = FMT_NULL;
// preceded with '0' flag(s). internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ?
unsigned value = internal::parse_nonnegative_int(s); next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
if (*s == '$') { // value is an argument index if (error)
++s; FMT_THROW(FormatError(!*s ? "invalid format string" : error));
arg_index = value; return arg;
} }
else {
if (c == '0') template <typename Char, typename AF>
spec.fill_ = '0'; unsigned PrintfFormatter<Char, AF>::parse_header(
if (value != 0) { const Char *&s, FormatSpec &spec)
// Nonzero value means that we parsed width and don't need to {
// parse it or flags again, so return now. unsigned arg_index = std::numeric_limits<unsigned>::max();
spec.width_ = value; Char c = *s;
return arg_index; if (c >= '0' && c <= '9')
} {
} // Parse an argument index (if followed by '$') or a width possibly
} // preceded with '0' flag(s).
parse_flags(spec, s); unsigned value = internal::parse_nonnegative_int(s);
// Parse width. if (*s == '$') // value is an argument index
if (*s >= '0' && *s <= '9') { {
spec.width_ = internal::parse_nonnegative_int(s); ++s;
} arg_index = value;
else if (*s == '*') { }
++s; else
spec.width_ = internal::WidthHandler(spec).visit(get_arg(s)); {
} if (c == '0')
return arg_index; spec.fill_ = '0';
} if (value != 0)
{
template <typename Char, typename AF> // Nonzero value means that we parsed width and don't need to
void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str) // parse it or flags again, so return now.
{ spec.width_ = value;
const Char *start = format_str.c_str(); return arg_index;
const Char *s = start; }
while (*s) { }
Char c = *s++; }
if (c != '%') continue; parse_flags(spec, s);
if (*s == c) { // Parse width.
write(writer_, start, s); if (*s >= '0' && *s <= '9')
start = ++s; {
continue; spec.width_ = internal::parse_nonnegative_int(s);
} }
write(writer_, start, s - 1); else if (*s == '*')
{
FormatSpec spec; ++s;
spec.align_ = ALIGN_RIGHT; spec.width_ = internal::WidthHandler(spec).visit(get_arg(s));
}
// Parse argument index, flags and width. return arg_index;
unsigned arg_index = parse_header(s, spec); }
// Parse precision. template <typename Char, typename AF>
if (*s == '.') { void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
++s; {
if ('0' <= *s && *s <= '9') { const Char *start = format_str.c_str();
spec.precision_ = static_cast<int>(internal::parse_nonnegative_int(s)); const Char *s = start;
} while (*s)
else if (*s == '*') { {
++s; Char c = *s++;
spec.precision_ = internal::PrecisionHandler().visit(get_arg(s)); if (c != '%') continue;
} if (*s == c)
} {
write(writer_, start, s);
using internal::Arg; start = ++s;
Arg arg = get_arg(s, arg_index); continue;
if (spec.flag(HASH_FLAG) && internal::IsZeroInt().visit(arg)) }
spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG); write(writer_, start, s - 1);
if (spec.fill_ == '0') {
if (arg.type <= Arg::LAST_NUMERIC_TYPE) FormatSpec spec;
spec.align_ = ALIGN_NUMERIC; spec.align_ = ALIGN_RIGHT;
else
spec.fill_ = ' '; // Ignore '0' flag for non-numeric types. // Parse argument index, flags and width.
} unsigned arg_index = parse_header(s, spec);
// Parse length and convert the argument to the required type. // Parse precision.
using internal::ArgConverter; if (*s == '.')
switch (*s++) { {
case 'h': ++s;
if (*s == 'h') if ('0' <= *s && *s <= '9')
ArgConverter<signed char>(arg, *++s).visit(arg); {
else spec.precision_ = static_cast<int>(internal::parse_nonnegative_int(s));
ArgConverter<short>(arg, *s).visit(arg); }
break; else if (*s == '*')
case 'l': {
if (*s == 'l') ++s;
ArgConverter<fmt::LongLong>(arg, *++s).visit(arg); spec.precision_ = internal::PrecisionHandler().visit(get_arg(s));
else }
ArgConverter<long>(arg, *s).visit(arg); }
break;
case 'j': using internal::Arg;
ArgConverter<intmax_t>(arg, *s).visit(arg); Arg arg = get_arg(s, arg_index);
break; if (spec.flag(HASH_FLAG) && internal::IsZeroInt().visit(arg))
case 'z': spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG);
ArgConverter<std::size_t>(arg, *s).visit(arg); if (spec.fill_ == '0')
break; {
case 't': if (arg.type <= Arg::LAST_NUMERIC_TYPE)
ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg); spec.align_ = ALIGN_NUMERIC;
break; else
case 'L': spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
// printf produces garbage when 'L' is omitted for long double, no }
// need to do the same.
break; // Parse length and convert the argument to the required type.
default: using internal::ArgConverter;
--s; switch (*s++)
ArgConverter<void>(arg, *s).visit(arg); {
} case 'h':
if (*s == 'h')
// Parse type. ArgConverter<signed char>(arg, *++s).visit(arg);
if (!*s) else
FMT_THROW(FormatError("invalid format string")); ArgConverter<short>(arg, *s).visit(arg);
spec.type_ = static_cast<char>(*s++); break;
if (arg.type <= Arg::LAST_INTEGER_TYPE) { case 'l':
// Normalize type. if (*s == 'l')
switch (spec.type_) { ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
case 'i': case 'u': else
spec.type_ = 'd'; ArgConverter<long>(arg, *s).visit(arg);
break; break;
case 'c': case 'j':
// TODO: handle wchar_t ArgConverter<intmax_t>(arg, *s).visit(arg);
internal::CharConverter(arg).visit(arg); break;
break; case 'z':
} ArgConverter<std::size_t>(arg, *s).visit(arg);
} break;
case 't':
start = s; ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
break;
// Format argument. case 'L':
AF(writer_, spec).visit(arg); // printf produces garbage when 'L' is omitted for long double, no
} // need to do the same.
write(writer_, start, s); break;
} default:
--s;
template <typename Char> ArgConverter<void>(arg, *s).visit(arg);
void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) }
{
PrintfFormatter<Char>(args, w).format(format); // Parse type.
} if (!*s)
FMT_THROW(FormatError("invalid format string"));
/** spec.type_ = static_cast<char>(*s++);
\rst if (arg.type <= Arg::LAST_INTEGER_TYPE)
Formats arguments and returns the result as a string. {
// Normalize type.
**Example**:: switch (spec.type_)
{
std::string message = fmt::sprintf("The answer is %d", 42); case 'i':
\endrst case 'u':
*/ spec.type_ = 'd';
inline std::string sprintf(CStringRef format, ArgList args) break;
{ case 'c':
MemoryWriter w; // TODO: handle wchar_t
printf(w, format, args); internal::CharConverter(arg).visit(arg);
return w.str(); break;
} }
FMT_VARIADIC(std::string, sprintf, CStringRef) }
inline std::wstring sprintf(WCStringRef format, ArgList args) start = s;
{
WMemoryWriter w; // Format argument.
printf(w, format, args); AF(writer_, spec).visit(arg);
return w.str(); }
} write(writer_, start, s);
FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef) }
/** template <typename Char>
\rst void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args)
Prints formatted data to the file *f*. {
PrintfFormatter<Char>(args, w).format(format);
**Example**:: }
fmt::fprintf(stderr, "Don't %s!", "panic"); /**
\endrst \rst
*/ Formats arguments and returns the result as a string.
FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args);
FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) **Example**::
/** std::string message = fmt::sprintf("The answer is %d", 42);
\rst \endrst
Prints formatted data to ``stdout``. */
inline std::string sprintf(CStringRef format, ArgList args)
**Example**:: {
MemoryWriter w;
fmt::printf("Elapsed time: %.2f seconds", 1.23); printf(w, format, args);
\endrst return w.str();
*/ }
inline int printf(CStringRef format, ArgList args) FMT_VARIADIC(std::string, sprintf, CStringRef)
{
return fprintf(stdout, format, args); inline std::wstring sprintf(WCStringRef format, ArgList args)
} {
FMT_VARIADIC(int, printf, CStringRef) WMemoryWriter w;
printf(w, format, args);
/** return w.str();
\rst }
Prints formatted data to the stream *os*. FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef)
**Example**:: /**
\rst
fprintf(cerr, "Don't %s!", "panic"); Prints formatted data to the file *f*.
\endrst
*/ **Example**::
inline int fprintf(std::ostream &os, CStringRef format_str, ArgList args)
{ fmt::fprintf(stderr, "Don't %s!", "panic");
MemoryWriter w; \endrst
printf(w, format_str, args); */
internal::write(os, w); FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args);
return static_cast<int>(w.size()); FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
}
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef) /**
\rst
Prints formatted data to ``stdout``.
**Example**::
fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst
*/
inline int printf(CStringRef format, ArgList args)
{
return fprintf(stdout, format, args);
}
FMT_VARIADIC(int, printf, CStringRef)
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fprintf(cerr, "Don't %s!", "panic");
\endrst
*/
inline int fprintf(std::ostream &os, CStringRef format_str, ArgList args)
{
MemoryWriter w;
printf(w, format_str, args);
internal::write(os, w);
return static_cast<int>(w.size());
}
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
} // namespace fmt } // namespace fmt
#ifdef FMT_HEADER_ONLY #ifdef FMT_HEADER_ONLY
......
...@@ -17,7 +17,7 @@ class sink ...@@ -17,7 +17,7 @@ class sink
public: public:
sink() sink()
{ {
_level = level::trace; _level = level::trace;
} }
virtual ~sink() {} virtual ~sink() {}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment