Commit 87ddb9a6 authored by gabime's avatar gabime

astyle

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