merge with vitaut/format

This commit is contained in:
Gregory Czajkowski 2013-12-10 17:43:21 -08:00
parent 5dd604b481
commit f2e75f74cc
2 changed files with 120 additions and 100 deletions

View File

@ -160,12 +160,6 @@ void fmt::BasicWriter<Char>::FormatDecimal(
buffer[0] = internal::DIGITS[index]; buffer[0] = internal::DIGITS[index];
} }
template <typename Char>
void fmt::BasicWriter<Char>::FormatDecimal(
CharPtr buffer, unsigned long long value, unsigned num_digits) {
return fmt::BasicWriter<Char>::FormatDecimal(buffer, static_cast<uint64_t>(value), num_digits);
}
template <typename Char> template <typename Char>
typename fmt::BasicWriter<Char>::CharPtr typename fmt::BasicWriter<Char>::CharPtr
fmt::BasicWriter<Char>::PrepareFilledBuffer( fmt::BasicWriter<Char>::PrepareFilledBuffer(
@ -402,13 +396,14 @@ inline const typename fmt::BasicFormatter<Char>::Arg
template <typename Char> template <typename Char>
void fmt::BasicFormatter<Char>::CheckSign(const Char *&s, const Arg &arg) { void fmt::BasicFormatter<Char>::CheckSign(const Char *&s, const Arg &arg) {
char sign = static_cast<char>(*s);
if (arg.type > LAST_NUMERIC_TYPE) { if (arg.type > LAST_NUMERIC_TYPE) {
ReportError(s, ReportError(s,
Format("format specifier '{0}' requires numeric argument") << *s); Format("format specifier '{}' requires numeric argument") << sign);
} }
if (arg.type == UINT || arg.type == ULONG || arg.type == ULLONG) { if (arg.type == UINT || arg.type == ULONG || arg.type == ULONG_LONG) {
ReportError(s, ReportError(s,
Format("format specifier '{0}' requires signed argument") << *s); Format("format specifier '{}' requires signed argument") << sign);
} }
++s; ++s;
} }
@ -419,7 +414,6 @@ void fmt::BasicFormatter<Char>::DoFormat() {
format_ = 0; format_ = 0;
next_arg_index_ = 0; next_arg_index_ = 0;
const Char *s = start; const Char *s = start;
typedef internal::Array<Char, BasicWriter<Char>::INLINE_BUFFER_SIZE> Buffer;
BasicWriter<Char> &writer = *writer_; BasicWriter<Char> &writer = *writer_;
while (*s) { while (*s) {
Char c = *s++; Char c = *s++;
@ -526,7 +520,7 @@ void fmt::BasicFormatter<Char>::DoFormat() {
++s; ++s;
++num_open_braces_; ++num_open_braces_;
const Arg &precision_arg = ParseArgIndex(s); const Arg &precision_arg = ParseArgIndex(s);
unsigned long long value = 0; ULongLong value = 0;
switch (precision_arg.type) { switch (precision_arg.type) {
case INT: case INT:
if (precision_arg.int_value < 0) if (precision_arg.int_value < 0)
@ -544,7 +538,12 @@ void fmt::BasicFormatter<Char>::DoFormat() {
case ULONG: case ULONG:
value = precision_arg.ulong_value; value = precision_arg.ulong_value;
break; break;
case ULLONG: case LONG_LONG:
if (precision_arg.long_long_value < 0)
ReportError(s, "negative precision in format");
value = precision_arg.long_long_value;
break;
case ULONG_LONG:
value = precision_arg.ulong_long_value; value = precision_arg.ulong_long_value;
break; break;
default: default:
@ -552,7 +551,7 @@ void fmt::BasicFormatter<Char>::DoFormat() {
} }
if (value > INT_MAX) if (value > INT_MAX)
ReportError(s, "number is too big in format"); ReportError(s, "number is too big in format");
precision = value; precision = static_cast<int>(value);
if (*s++ != '}') if (*s++ != '}')
throw FormatError("unmatched '{' in format"); throw FormatError("unmatched '{' in format");
--num_open_braces_; --num_open_braces_;
@ -588,7 +587,10 @@ void fmt::BasicFormatter<Char>::DoFormat() {
case ULONG: case ULONG:
writer.FormatInt(arg.ulong_value, spec); writer.FormatInt(arg.ulong_value, spec);
break; break;
case ULLONG: case LONG_LONG:
writer.FormatInt(arg.long_long_value, spec);
break;
case ULONG_LONG:
writer.FormatInt(arg.ulong_long_value, spec); writer.FormatInt(arg.ulong_long_value, spec);
break; break;
case DOUBLE: case DOUBLE:
@ -668,9 +670,6 @@ template fmt::BasicWriter<char>::CharPtr
template void fmt::BasicWriter<char>::FormatDecimal( template void fmt::BasicWriter<char>::FormatDecimal(
CharPtr buffer, uint64_t value, unsigned num_digits); CharPtr buffer, uint64_t value, unsigned num_digits);
template void fmt::BasicWriter<char>::FormatDecimal(
CharPtr buffer, unsigned long long value, unsigned num_digits);
template fmt::BasicWriter<char>::CharPtr template fmt::BasicWriter<char>::CharPtr
fmt::BasicWriter<char>::PrepareFilledBuffer( fmt::BasicWriter<char>::PrepareFilledBuffer(
unsigned size, const AlignSpec &spec, char sign); unsigned size, const AlignSpec &spec, char sign);
@ -703,9 +702,6 @@ template fmt::BasicWriter<wchar_t>::CharPtr
template void fmt::BasicWriter<wchar_t>::FormatDecimal( template void fmt::BasicWriter<wchar_t>::FormatDecimal(
CharPtr buffer, uint64_t value, unsigned num_digits); CharPtr buffer, uint64_t value, unsigned num_digits);
template void fmt::BasicWriter<wchar_t>::FormatDecimal(
CharPtr buffer, unsigned long long value, unsigned num_digits);
template fmt::BasicWriter<wchar_t>::CharPtr template fmt::BasicWriter<wchar_t>::CharPtr
fmt::BasicWriter<wchar_t>::PrepareFilledBuffer( fmt::BasicWriter<wchar_t>::PrepareFilledBuffer(
unsigned size, const AlignSpec &spec, char sign); unsigned size, const AlignSpec &spec, char sign);

178
format.h
View File

@ -42,24 +42,42 @@
#include <string> #include <string>
#include <sstream> #include <sstream>
#ifdef __GNUC__
# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#endif
// Compatibility with compilers other than clang. // Compatibility with compilers other than clang.
#ifndef __has_feature #ifndef __has_feature
# define __has_feature(x) 0 # define __has_feature(x) 0
#endif #endif
#ifndef FMT_USE_INITIALIZER_LIST
# define FMT_USE_INITIALIZER_LIST \
(__has_feature(cxx_generalized_initializers) || \
(FMT_GCC_VERSION >= 404 && __cplusplus >= 201103) || _MSC_VER >= 1700)
#endif
#if FMT_USE_INITIALIZER_LIST
# include <initializer_list>
#endif
// Define FMT_USE_NOEXCEPT to make format use noexcept (C++11 feature). // Define FMT_USE_NOEXCEPT to make format use noexcept (C++11 feature).
#if FMT_USE_NOEXCEPT || \ #if FMT_USE_NOEXCEPT || __has_feature(cxx_noexcept) || \
(defined(__has_feature) && __has_feature(cxx_noexcept)) (FMT_GCC_VERSION >= 408 && __cplusplus >= 201103)
# define FMT_NOEXCEPT(expr) noexcept(expr) # define FMT_NOEXCEPT(expr) noexcept(expr)
#else #else
# define FMT_NOEXCEPT(expr) # define FMT_NOEXCEPT(expr)
#endif #endif
#ifdef __GNUC__ #if FMT_GCC_VERSION >= 406
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) # define FMT_GCC_DIAGNOSTIC
# pragma GCC diagnostic push # pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wlong-long" # pragma GCC diagnostic ignored "-Wlong-long"
#endif #endif
#if _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4521)
#endif #endif
namespace fmt { namespace fmt {
@ -151,11 +169,16 @@ void Array<T, SIZE>::append(const T *begin, const T *end) {
} }
template <typename Char> template <typename Char>
struct CharTraits; class CharTraits;
template <> template <>
struct CharTraits<char> { class CharTraits<char> {
typedef wchar_t UnsupportedType; private:
// Conversion from wchar_t to char is not supported.
static char ConvertWChar(wchar_t);
public:
typedef const wchar_t *UnsupportedStrType;
template <typename T> template <typename T>
static int FormatFloat(char *buffer, std::size_t size, static int FormatFloat(char *buffer, std::size_t size,
@ -163,8 +186,11 @@ struct CharTraits<char> {
}; };
template <> template <>
struct CharTraits<wchar_t> { class CharTraits<wchar_t> {
typedef char UnsupportedType; public:
typedef const char *UnsupportedStrType;
static wchar_t ConvertWChar(wchar_t value) { return value; }
template <typename T> template <typename T>
static int FormatFloat(wchar_t *buffer, std::size_t size, static int FormatFloat(wchar_t *buffer, std::size_t size,
@ -189,9 +215,6 @@ struct SignedIntTraits {
template <> template <>
struct IntTraits<int> : SignedIntTraits<int, unsigned> {}; struct IntTraits<int> : SignedIntTraits<int, unsigned> {};
template <>
struct IntTraits<uint32_t> : SignedIntTraits<uint32_t, unsigned> {};
template <> template <>
struct IntTraits<long> : SignedIntTraits<long, unsigned long> {}; struct IntTraits<long> : SignedIntTraits<long, unsigned long> {};
@ -379,11 +402,6 @@ class IntFormatter : public SpecT {
*/ */
IntFormatter<int, TypeSpec<'b'> > bin(int value); IntFormatter<int, TypeSpec<'b'> > bin(int value);
/**
Returns an integer formatter that formats the value in base 2.
*/
IntFormatter<int, TypeSpec<'B'> > binu(int value);
/** /**
Returns an integer formatter that formats the value in base 8. Returns an integer formatter that formats the value in base 8.
*/ */
@ -421,9 +439,7 @@ IntFormatter<int, AlignTypeSpec<TYPE_CODE> > pad(
inline IntFormatter<TYPE, TypeSpec<'b'> > bin(TYPE value) { \ inline IntFormatter<TYPE, TypeSpec<'b'> > bin(TYPE value) { \
return IntFormatter<TYPE, TypeSpec<'b'> >(value, TypeSpec<'b'>()); \ return IntFormatter<TYPE, TypeSpec<'b'> >(value, TypeSpec<'b'>()); \
} \ } \
inline IntFormatter<TYPE, TypeSpec<'B'> > binu(TYPE value) { \ \
return IntFormatter<TYPE, TypeSpec<'B'> >(value, TypeSpec<'B'>()); \
} \
inline IntFormatter<TYPE, TypeSpec<'o'> > oct(TYPE value) { \ inline IntFormatter<TYPE, TypeSpec<'o'> > oct(TYPE value) { \
return IntFormatter<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \ return IntFormatter<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \
} \ } \
@ -454,6 +470,7 @@ DEFINE_INT_FORMATTERS(int)
DEFINE_INT_FORMATTERS(long) DEFINE_INT_FORMATTERS(long)
DEFINE_INT_FORMATTERS(unsigned) DEFINE_INT_FORMATTERS(unsigned)
DEFINE_INT_FORMATTERS(unsigned long) DEFINE_INT_FORMATTERS(unsigned long)
DEFINE_INT_FORMATTERS(long long)
DEFINE_INT_FORMATTERS(unsigned long long) DEFINE_INT_FORMATTERS(unsigned long long)
template <typename Char> template <typename Char>
@ -511,9 +528,6 @@ class BasicWriter {
static void FormatDecimal( static void FormatDecimal(
CharPtr buffer, uint64_t value, unsigned num_digits); CharPtr buffer, uint64_t value, unsigned num_digits);
static void FormatDecimal(
CharPtr buffer, unsigned long long value, unsigned num_digits);
static CharPtr FillPadding(CharPtr buffer, static CharPtr FillPadding(CharPtr buffer,
unsigned total_size, std::size_t content_size, wchar_t fill); unsigned total_size, std::size_t content_size, wchar_t fill);
@ -551,7 +565,7 @@ class BasicWriter {
// char stream and vice versa. If you want to print a wide string // char stream and vice versa. If you want to print a wide string
// as a pointer as std::ostream does, cast it to const void*. // as a pointer as std::ostream does, cast it to const void*.
// Do not implement! // Do not implement!
void operator<<(const typename internal::CharTraits<Char>::UnsupportedType *); void operator<<(typename internal::CharTraits<Char>::UnsupportedStrType);
public: public:
/** /**
@ -752,9 +766,8 @@ BasicWriter<Char> &BasicWriter<Char>::operator<<(
} while ((n >>= 1) != 0); } while ((n >>= 1) != 0);
Char *p = GetBase(PrepareFilledBuffer(size, f, sign)); Char *p = GetBase(PrepareFilledBuffer(size, f, sign));
n = abs_value; n = abs_value;
const char *digits = "01";
do { do {
*p-- = digits[n & 0x1]; *p-- = '0' + (n & 1);
} while ((n >>= 1) != 0); } while ((n >>= 1) != 0);
if (print_prefix) { if (print_prefix) {
*p-- = f.type(); *p-- = f.type();
@ -787,7 +800,8 @@ BasicWriter<Char> &BasicWriter<Char>::operator<<(
template <typename Char> template <typename Char>
BasicFormatter<Char> BasicWriter<Char>::Format(StringRef format) { BasicFormatter<Char> BasicWriter<Char>::Format(StringRef format) {
return BasicFormatter<Char>(*this, format.c_str()); BasicFormatter<Char> f(*this, format.c_str());
return f;
} }
typedef BasicWriter<char> Writer; typedef BasicWriter<char> Writer;
@ -826,7 +840,7 @@ class BasicFormatter {
enum Type { enum Type {
// Numeric types should go first. // Numeric types should go first.
INT, UINT, LONG, ULONG, ULLONG, DOUBLE, LONG_DOUBLE, INT, UINT, LONG, ULONG, LONG_LONG, ULONG_LONG, DOUBLE, LONG_DOUBLE,
LAST_NUMERIC_TYPE = LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE,
CHAR, STRING, WSTRING, POINTER, CUSTOM CHAR, STRING, WSTRING, POINTER, CUSTOM
}; };
@ -847,12 +861,6 @@ class BasicFormatter {
template <typename T> template <typename T>
Arg(T *value); Arg(T *value);
// This method is private to disallow formatting of wide characters.
// If you want to output a wide character cast it to integer type.
// Do not implement!
// TODO
//Arg(wchar_t value);
public: public:
Type type; Type type;
union { union {
@ -861,6 +869,7 @@ class BasicFormatter {
double double_value; double double_value;
long long_value; long long_value;
unsigned long ulong_value; unsigned long ulong_value;
long long long_long_value;
unsigned long long ulong_long_value; unsigned long long ulong_long_value;
long double long_double_value; long double long_double_value;
const void *pointer_value; const void *pointer_value;
@ -881,12 +890,18 @@ class BasicFormatter {
Arg(unsigned value) : type(UINT), uint_value(value), formatter(0) {} Arg(unsigned value) : type(UINT), uint_value(value), formatter(0) {}
Arg(long value) : type(LONG), long_value(value), formatter(0) {} Arg(long value) : type(LONG), long_value(value), formatter(0) {}
Arg(unsigned long value) : type(ULONG), ulong_value(value), formatter(0) {} Arg(unsigned long value) : type(ULONG), ulong_value(value), formatter(0) {}
Arg(unsigned long long value) : type(ULLONG), ulong_long_value(value), formatter(0) {} Arg(long long value)
: type(LONG_LONG), long_long_value(value), formatter(0) {}
Arg(unsigned long long value)
: type(ULONG_LONG), ulong_long_value(value), formatter(0) {}
Arg(float value) : type(DOUBLE), double_value(value), formatter(0) {} Arg(float value) : type(DOUBLE), double_value(value), formatter(0) {}
Arg(double value) : type(DOUBLE), double_value(value), formatter(0) {} Arg(double value) : type(DOUBLE), double_value(value), formatter(0) {}
Arg(long double value) Arg(long double value)
: type(LONG_DOUBLE), long_double_value(value), formatter(0) {} : type(LONG_DOUBLE), long_double_value(value), formatter(0) {}
Arg(Char value) : type(CHAR), int_value(value), formatter(0) {} Arg(char value) : type(CHAR), int_value(value), formatter(0) {}
Arg(wchar_t value)
: type(CHAR), int_value(internal::CharTraits<Char>::ConvertWChar(value)),
formatter(0) {}
Arg(const Char *value) : type(STRING), formatter(0) { Arg(const Char *value) : type(STRING), formatter(0) {
string.value = value; string.value = value;
@ -908,6 +923,11 @@ class BasicFormatter {
string.size = value.size(); string.size = value.size();
} }
Arg(StringRef value) : type(STRING), formatter(0) {
string.value = value.c_str();
string.size = value.size();
}
template <typename T> template <typename T>
Arg(const T &value) : type(CUSTOM), formatter(0) { Arg(const T &value) : type(CUSTOM), formatter(0) {
custom.value = &value; custom.value = &value;
@ -938,16 +958,18 @@ class BasicFormatter {
int num_open_braces_; int num_open_braces_;
int next_arg_index_; int next_arg_index_;
typedef unsigned long long ULongLong;
friend class internal::FormatterProxy<Char>; friend class internal::FormatterProxy<Char>;
// Forbid copying other than from a temporary. Do not implement. // Forbid copying from a temporary as in the following example:
BasicFormatter(BasicFormatter &); // fmt::Formatter<> f = Format("test"); // not allowed
// This is done because BasicFormatter objects should normally exist
// only as temporaries returned by one of the formatting functions.
// Do not implement.
BasicFormatter(const BasicFormatter &);
BasicFormatter& operator=(const BasicFormatter &); BasicFormatter& operator=(const BasicFormatter &);
void Add(const Arg &arg) {
args_.push_back(&arg);
}
void ReportError(const Char *s, StringRef message) const; void ReportError(const Char *s, StringRef message) const;
unsigned ParseUInt(const Char *&s) const; unsigned ParseUInt(const Char *&s) const;
@ -957,6 +979,8 @@ class BasicFormatter {
void CheckSign(const Char *&s, const Arg &arg); void CheckSign(const Char *&s, const Arg &arg);
// Parses the format string and performs the actual formatting,
// writing the output to writer_.
void DoFormat(); void DoFormat();
struct Proxy { struct Proxy {
@ -980,27 +1004,35 @@ class BasicFormatter {
public: public:
// Constructs a formatter with a writer to be used for output and a format // Constructs a formatter with a writer to be used for output and a format
// format string. // string.
BasicFormatter(BasicWriter<Char> &w, const Char *format = 0) BasicFormatter(BasicWriter<Char> &w, const Char *format = 0)
: writer_(&w), format_(format) {} : writer_(&w), format_(format) {}
#if FMT_USE_INITIALIZER_LIST
// Constructs a formatter with formatting arguments.
BasicFormatter(BasicWriter<Char> &w,
const Char *format, std::initializer_list<Arg> args)
: writer_(&w), format_(format) {
args_.reserve(args.size());
for (const Arg &arg: args)
args_.push_back(&arg);
}
#endif
// Performs formatting if the format string is non-null. The format string
// can be null if its ownership has been transferred to another formatter.
~BasicFormatter() { ~BasicFormatter() {
CompleteFormatting(); CompleteFormatting();
} }
// Constructs a formatter from a proxy object. BasicFormatter(BasicFormatter &f) : writer_(f.writer_), format_(f.format_) {
BasicFormatter(const Proxy &p) : writer_(p.writer), format_(p.format) {} f.format_ = 0;
operator Proxy() {
const Char *format = format_;
format_ = 0;
return Proxy(writer_, format);
} }
// Feeds an argument to a formatter. // Feeds an argument to a formatter.
BasicFormatter &operator<<(const Arg &arg) { BasicFormatter &operator<<(const Arg &arg) {
arg.formatter = this; arg.formatter = this;
Add(arg); args_.push_back(&arg);
return *this; return *this;
} }
@ -1089,7 +1121,8 @@ class NoAction {
// Formats an error message and prints it to stdout. // Formats an error message and prints it to stdout.
fmt::Formatter<PrintError> ReportError(const char *format) { fmt::Formatter<PrintError> ReportError(const char *format) {
return fmt::Formatter<PrintError>(format); fmt::Formatter f<PrintError>(format);
return f;
} }
ReportError("File not found: {}") << path; ReportError("File not found: {}") << path;
@ -1102,16 +1135,9 @@ class Formatter : private Action, public BasicFormatter<Char> {
bool inactive_; bool inactive_;
// Forbid copying other than from a temporary. Do not implement. // Forbid copying other than from a temporary. Do not implement.
Formatter(Formatter &); Formatter(const Formatter &);
Formatter& operator=(const Formatter &); Formatter& operator=(const Formatter &);
struct Proxy {
const Char *format;
Action action;
Proxy(const Char *fmt, Action a) : format(fmt), action(a) {}
};
public: public:
/** /**
\rst \rst
@ -1127,10 +1153,10 @@ class Formatter : private Action, public BasicFormatter<Char> {
inactive_(false) { inactive_(false) {
} }
// Constructs a formatter from a proxy object. Formatter(Formatter &f)
Formatter(const Proxy &p) : Action(f), BasicFormatter<Char>(writer_, f.TakeFormatString()),
: Action(p.action), BasicFormatter<Char>(writer_, p.format),
inactive_(false) { inactive_(false) {
f.inactive_ = true;
} }
/** /**
@ -1142,12 +1168,6 @@ class Formatter : private Action, public BasicFormatter<Char> {
(*this)(writer_); (*this)(writer_);
} }
} }
// Converts the formatter into a proxy object.
operator Proxy() {
inactive_ = true;
return Proxy(this->TakeFormatString(), *this);
}
}; };
/** /**
@ -1196,10 +1216,9 @@ class FormatInt {
} }
explicit FormatInt(unsigned value) : str_(FormatDecimal(value)) {} explicit FormatInt(unsigned value) : str_(FormatDecimal(value)) {}
explicit FormatInt(uint64_t value) : str_(FormatDecimal(value)) {} explicit FormatInt(uint64_t value) : str_(FormatDecimal(value)) {}
explicit FormatInt(unsigned long long value) : str_(FormatDecimal(value)) {}
inline const char *c_str() const { return str_; } const char *c_str() const { return str_; }
inline std::string str() const { return str_; } std::string str() const { return str_; }
}; };
/** /**
@ -1224,11 +1243,13 @@ class FormatInt {
\endrst \endrst
*/ */
inline Formatter<> Format(StringRef format) { inline Formatter<> Format(StringRef format) {
return Formatter<>(format); Formatter<> f(format);
return f;
} }
inline Formatter<NoAction, wchar_t> Format(WStringRef format) { inline Formatter<NoAction, wchar_t> Format(WStringRef format) {
return Formatter<NoAction, wchar_t>(format); Formatter<NoAction, wchar_t> f(format);
return f;
} }
/** A formatting action that writes formatted output to stdout. */ /** A formatting action that writes formatted output to stdout. */
@ -1244,14 +1265,17 @@ class Write {
// Example: // Example:
// Print("Elapsed time: {0:.2f} seconds") << 1.23; // Print("Elapsed time: {0:.2f} seconds") << 1.23;
inline Formatter<Write> Print(StringRef format) { inline Formatter<Write> Print(StringRef format) {
return Formatter<Write>(format); Formatter<Write> f(format);
return f;
} }
} }
#ifdef __GNUC__ #ifdef FMT_GCC_DIAGNOSTIC
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
# pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif #endif
#if _MSC_VER
# pragma warning(pop)
#endif #endif
#endif // FORMAT_H_ #endif // FORMAT_H_