aboutsummaryrefslogtreecommitdiff
path: root/dep/cppformat/format.h
diff options
context:
space:
mode:
Diffstat (limited to 'dep/cppformat/format.h')
-rw-r--r--dep/cppformat/format.h567
1 files changed, 411 insertions, 156 deletions
diff --git a/dep/cppformat/format.h b/dep/cppformat/format.h
index 8d54bf521c7..dfe95a77931 100644
--- a/dep/cppformat/format.h
+++ b/dep/cppformat/format.h
@@ -39,6 +39,7 @@
#include <stdexcept>
#include <string>
#include <sstream>
+#include <map>
#if _SECURE_SCL
# include <iterator>
@@ -152,26 +153,34 @@ inline uint32_t clzll(uint64_t x) {
#endif
// Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature).
-#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
- (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11)
-# define FMT_NOEXCEPT noexcept
-#else
-# define FMT_NOEXCEPT throw()
+#ifndef FMT_NOEXCEPT
+# if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
+ (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11)
+# define FMT_NOEXCEPT noexcept
+# else
+# define FMT_NOEXCEPT throw()
+# endif
#endif
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
#if FMT_USE_DELETED_FUNCTIONS || FMT_HAS_FEATURE(cxx_deleted_functions) || \
(FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1800
+# define FMT_DELETED_OR_UNDEFINED = delete
# define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&) = delete; \
TypeName& operator=(const TypeName&) = delete
#else
+# define FMT_DELETED_OR_UNDEFINED
# define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
TypeName& operator=(const TypeName&)
#endif
+#ifndef FMT_ASSERT
+# define FMT_ASSERT(condition, message) assert((condition) && message)
+#endif
+
namespace fmt {
// Fix the warning about long long on older versions of GCC
@@ -197,8 +206,7 @@ void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value);
/**
\rst
- A string reference. It can be constructed from a C string or
- ``std::string``.
+ A string reference. It can be constructed from a C string or ``std::string``.
You can use one of the following typedefs for common character types:
@@ -227,39 +235,39 @@ class BasicStringRef {
std::size_t size_;
public:
- /**
- Constructs a string reference object from a C string and a size.
- */
+ /** Constructs a string reference object from a C string and a size. */
BasicStringRef(const Char *s, std::size_t size) : data_(s), size_(size) {}
/**
+ \rst
Constructs a string reference object from a C string computing
the size with ``std::char_traits<Char>::length``.
+ \endrst
*/
BasicStringRef(const Char *s)
: data_(s), size_(std::char_traits<Char>::length(s)) {}
/**
- Constructs a string reference from an `std::string` object.
+ \rst
+ Constructs a string reference from an ``std::string`` object.
+ \endrst
*/
BasicStringRef(const std::basic_string<Char> &s)
: data_(s.c_str()), size_(s.size()) {}
/**
- Converts a string reference to an `std::string` object.
+ \rst
+ Converts a string reference to an ``std::string`` object.
+ \endrst
*/
- operator std::basic_string<Char>() const {
- return std::basic_string<Char>(data_, size());
+ std::basic_string<Char> to_string() const {
+ return std::basic_string<Char>(data_, size_);
}
- /**
- Returns the pointer to a C string.
- */
- const Char *c_str() const { return data_; }
+ /** Returns the pointer to a C string. */
+ const Char *data() const { return data_; }
- /**
- Returns the string size.
- */
+ /** Returns the string size. */
std::size_t size() const { return size_; }
friend bool operator==(BasicStringRef lhs, BasicStringRef rhs) {
@@ -268,17 +276,70 @@ class BasicStringRef {
friend bool operator!=(BasicStringRef lhs, BasicStringRef rhs) {
return lhs.data_ != rhs.data_;
}
+ friend bool operator<(BasicStringRef lhs, BasicStringRef rhs) {
+ return std::lexicographical_compare(
+ lhs.data_, lhs.data_ + lhs.size_, rhs.data_, rhs.data_ + rhs.size_);
+ }
};
typedef BasicStringRef<char> StringRef;
typedef BasicStringRef<wchar_t> WStringRef;
+
+/**
+ \rst
+ A reference to a null terminated string. It can be constructed from a C
+ string or ``std::string``.
+
+ You can use one of the following typedefs for common character types:
+
+ +-------------+--------------------------+
+ | Type | Definition |
+ +=============+==========================+
+ | CStringRef | BasicCStringRef<char> |
+ +-------------+--------------------------+
+ | WCStringRef | BasicCStringRef<wchar_t> |
+ +-------------+--------------------------+
+
+ This class is most useful as a parameter type to allow passing
+ different types of strings to a function, for example::
+
+ template <typename... Args>
+ std::string format(CStringRef format_str, const Args & ... args);
+
+ format("{}", 42);
+ format(std::string("{}"), 42);
+ \endrst
+ */
+template <typename Char>
+class BasicCStringRef {
+ private:
+ const Char *data_;
+
+ public:
+ /** Constructs a string reference object from a C string. */
+ BasicCStringRef(const Char *s) : data_(s) {}
+
+ /**
+ \rst
+ Constructs a string reference from an ``std::string`` object.
+ \endrst
+ */
+ BasicCStringRef(const std::basic_string<Char> &s) : data_(s.c_str()) {}
+
+ /** Returns the pointer to a C string. */
+ const Char *c_str() const { return data_; }
+};
+
+typedef BasicCStringRef<char> CStringRef;
+typedef BasicCStringRef<wchar_t> WCStringRef;
+
/**
A formatting error such as invalid format string.
*/
class FormatError : public std::runtime_error {
public:
- explicit FormatError(StringRef message)
+ explicit FormatError(CStringRef message)
: std::runtime_error(message.c_str()) {}
};
@@ -299,7 +360,11 @@ inline T *make_ptr(T *ptr, std::size_t) { return ptr; }
#endif
} // namespace internal
-/** A buffer supporting a subset of ``std::vector``'s operations. */
+/**
+ \rst
+ A buffer supporting a subset of ``std::vector``'s operations.
+ \endrst
+ */
template <typename T>
class Buffer {
private:
@@ -314,8 +379,10 @@ class Buffer {
: ptr_(ptr), size_(0), capacity_(capacity) {}
/**
+ \rst
Increases the buffer capacity to hold at least *size* elements updating
``ptr_`` and ``capacity_``.
+ \endrst
*/
virtual void grow(std::size_t size) = 0;
@@ -337,7 +404,11 @@ class Buffer {
size_ = new_size;
}
- /** Reserves space to store at least *capacity* elements. */
+ /**
+ \rst
+ Reserves space to store at least *capacity* elements.
+ \endrst
+ */
void reserve(std::size_t capacity) {
if (capacity > capacity_)
grow(capacity);
@@ -352,14 +423,16 @@ class Buffer {
}
/** Appends data to the end of the buffer. */
- void append(const T *begin, const T *end);
+ template <typename U>
+ void append(const U *begin, const U *end);
T &operator[](std::size_t index) { return ptr_[index]; }
const T &operator[](std::size_t index) const { return ptr_[index]; }
};
template <typename T>
-void Buffer<T>::append(const T *begin, const T *end) {
+template <typename U>
+void Buffer<T>::append(const U *begin, const U *end) {
std::ptrdiff_t num_elements = end - begin;
if (size_ + num_elements > capacity_)
grow(size_ + num_elements);
@@ -485,7 +558,9 @@ inline int getsign(double value) {
return sign;
}
inline int isinfinity(double x) { return !_finite(x); }
-inline int isinfinity(long double x) { return !_finite(static_cast<double>(x)); }
+inline int isinfinity(long double x) {
+ return !_finite(static_cast<double>(x));
+}
#endif
template <typename Char>
@@ -496,6 +571,7 @@ class BasicCharTraits {
#else
typedef Char *CharPtr;
#endif
+ static Char cast(wchar_t value) { return static_cast<Char>(value); }
};
template <typename Char>
@@ -507,7 +583,7 @@ class CharTraits<char> : public BasicCharTraits<char> {
// Conversion from wchar_t to char is not allowed.
static char convert(wchar_t);
-public:
+ public:
static char convert(char value) { return value; }
// Formats a floating-point number.
@@ -656,7 +732,15 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
buffer[0] = Data::DIGITS[index];
}
-#ifdef _WIN32
+#ifndef _WIN32
+# define FMT_USE_WINDOWS_H 0
+#elif !defined(FMT_USE_WINDOWS_H)
+# define FMT_USE_WINDOWS_H 1
+#endif
+
+// Define FMT_USE_WINDOWS_H to 0 to disable use of windows.h.
+// All the functionality that relies on it will be disabled too.
+#if FMT_USE_WINDOWS_H
// A converter from UTF-8 to UTF-16.
// It is only provided for Windows since other systems support UTF-8 natively.
class UTF8ToUTF16 {
@@ -690,26 +774,16 @@ class UTF16ToUTF8 {
// in case of memory allocation error.
int convert(WStringRef s);
};
-#endif
-void format_system_error(fmt::Writer &out, int error_code,
- fmt::StringRef message) FMT_NOEXCEPT;
-
-#ifdef _WIN32
void format_windows_error(fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT;
#endif
-// Computes max(N, 1) at compile time. It is used to avoid errors about
-// allocating an array of 0 size.
-template <unsigned N>
-struct NonZero {
- enum { VALUE = N > 0 ? N : 1 };
-};
+void format_system_error(fmt::Writer &out, int error_code,
+ fmt::StringRef message) FMT_NOEXCEPT;
-// A formatting argument. It is a POD type to allow storage in
-// internal::MemoryBuffer.
-struct Arg {
+// A formatting argument value.
+struct Value {
template <typename Char>
struct StringValue {
const Char *value;
@@ -740,16 +814,24 @@ struct Arg {
};
enum Type {
- NONE,
+ NONE, NAMED_ARG,
// Integer types should go first,
- INT, UINT, LONG_LONG, ULONG_LONG, CHAR, LAST_INTEGER_TYPE = CHAR,
+ INT, UINT, LONG_LONG, ULONG_LONG, BOOL, CHAR, LAST_INTEGER_TYPE = CHAR,
// followed by floating-point types.
DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE,
CSTRING, STRING, WSTRING, POINTER, CUSTOM
};
+};
+
+// A formatting argument. It is a POD type to allow storage in
+// internal::MemoryBuffer.
+struct Arg : Value {
Type type;
};
+template <typename Char>
+struct NamedArg;
+
template <typename T = void>
struct None {};
@@ -800,6 +882,12 @@ struct EnableIf {};
template<class T>
struct EnableIf<true, T> { typedef T type; };
+template<bool B, class T, class F>
+struct Conditional { typedef T type; };
+
+template<class T, class F>
+struct Conditional<false, T, F> { typedef F type; };
+
// A helper function to suppress bogus "conditional expression is constant"
// warnings.
inline bool check(bool value) { return value; }
@@ -829,12 +917,12 @@ class MakeValue : public Arg {
MakeValue(typename WCharHelper<WStringRef, Char>::Unsupported);
void set_string(StringRef str) {
- string.value = str.c_str();
+ string.value = str.data();
string.size = str.size();
}
void set_string(WStringRef str) {
- wstring.value = str.c_str();
+ wstring.value = str.data();
wstring.size = str.size();
}
@@ -850,11 +938,14 @@ class MakeValue : public Arg {
public:
MakeValue() {}
-#define FMT_MAKE_VALUE(Type, field, TYPE) \
- MakeValue(Type value) { field = value; } \
+#define FMT_MAKE_VALUE_(Type, field, TYPE, rhs) \
+ MakeValue(Type value) { field = rhs; } \
static uint64_t type(Type) { return Arg::TYPE; }
- FMT_MAKE_VALUE(bool, int_value, INT)
+#define FMT_MAKE_VALUE(Type, field, TYPE) \
+ FMT_MAKE_VALUE_(Type, field, TYPE, value)
+
+ FMT_MAKE_VALUE(bool, int_value, BOOL)
FMT_MAKE_VALUE(short, int_value, INT)
FMT_MAKE_VALUE(unsigned short, uint_value, UINT)
FMT_MAKE_VALUE(int, int_value, INT)
@@ -907,6 +998,7 @@ class MakeValue : public Arg {
FMT_MAKE_VALUE(const unsigned char *, ustring.value, CSTRING)
FMT_MAKE_STR_VALUE(const std::string &, STRING)
FMT_MAKE_STR_VALUE(StringRef, STRING)
+ FMT_MAKE_VALUE_(CStringRef, string.value, CSTRING, value.c_str())
#define FMT_MAKE_WSTR_VALUE(Type, TYPE) \
MakeValue(typename WCharHelper<Type, Char>::Supported value) { \
@@ -939,6 +1031,25 @@ class MakeValue : public Arg {
static uint64_t type(const T &) {
return IsConvertibleToInt<T>::value ? Arg::INT : Arg::CUSTOM;
}
+
+ // Additional template param `Char_` is needed here because make_type always
+ // uses MakeValue<char>.
+ template <typename Char_>
+ MakeValue(const NamedArg<Char_> &value) { pointer = &value; }
+
+ template <typename Char_>
+ static uint64_t type(const NamedArg<Char_> &) { return Arg::NAMED_ARG; }
+};
+
+template <typename Char>
+struct NamedArg : Arg {
+ BasicStringRef<Char> name;
+
+ template <typename T>
+ NamedArg(BasicStringRef<Char> name, const T &value)
+ : name(name), Arg(MakeValue<Char>(value)) {
+ type = static_cast<internal::Arg::Type>(MakeValue<Char>::type(value));
+ }
};
#define FMT_DISPATCH(call) static_cast<Impl*>(this)->call
@@ -985,6 +1096,9 @@ class ArgVisitor {
Result visit_ulong_long(ULongLong value) {
return FMT_DISPATCH(visit_any_int(value));
}
+ Result visit_bool(bool value) {
+ return FMT_DISPATCH(visit_any_int(value));
+ }
Result visit_char(int value) {
return FMT_DISPATCH(visit_any_int(value));
}
@@ -1020,7 +1134,7 @@ class ArgVisitor {
Result visit(const Arg &arg) {
switch (arg.type) {
default:
- assert(false);
+ FMT_ASSERT(false, "invalid argument type");
return Result();
case Arg::INT:
return FMT_DISPATCH(visit_int(arg.int_value));
@@ -1030,12 +1144,14 @@ class ArgVisitor {
return FMT_DISPATCH(visit_long_long(arg.long_long_value));
case Arg::ULONG_LONG:
return FMT_DISPATCH(visit_ulong_long(arg.ulong_long_value));
+ case Arg::BOOL:
+ return FMT_DISPATCH(visit_bool(arg.int_value));
+ case Arg::CHAR:
+ return FMT_DISPATCH(visit_char(arg.int_value));
case Arg::DOUBLE:
return FMT_DISPATCH(visit_double(arg.double_value));
case Arg::LONG_DOUBLE:
return FMT_DISPATCH(visit_long_double(arg.long_double_value));
- case Arg::CHAR:
- return FMT_DISPATCH(visit_char(arg.int_value));
case Arg::CSTRING: {
Arg::StringValue<char> str = arg.string;
str.size = 0;
@@ -1058,8 +1174,14 @@ class RuntimeError : public std::runtime_error {
RuntimeError() : std::runtime_error("") {}
};
+template <typename Impl, typename Char>
+class BasicArgFormatter;
+
template <typename Char>
-class ArgFormatter;
+class PrintfArgFormatter;
+
+template <typename Char>
+class ArgMap;
} // namespace internal
/** An argument list. */
@@ -1068,7 +1190,15 @@ class ArgList {
// To reduce compiled code size per formatting function call, types of first
// MAX_PACKED_ARGS arguments are passed in the types_ field.
uint64_t types_;
- const internal::Arg *args_;
+ union {
+ // If the number of arguments is less than MAX_PACKED_ARGS, the argument
+ // values are stored in values_, otherwise they are stored in args_.
+ // This is done to reduce compiled code size as storing larger objects
+ // may require more code (at least on x86-64) even if the same amount of
+ // data is actually copied to stack. It saves ~10% on the bloat test.
+ const internal::Value *values_;
+ const internal::Arg *args_;
+ };
internal::Arg::Type type(unsigned index) const {
unsigned shift = index * 4;
@@ -1077,11 +1207,17 @@ class ArgList {
(types_ & (mask << shift)) >> shift);
}
+ template <typename Char>
+ friend class internal::ArgMap;
+
public:
// Maximum number of arguments with packed types.
enum { MAX_PACKED_ARGS = 16 };
ArgList() : types_(0) {}
+
+ ArgList(ULongLong types, const internal::Value *values)
+ : types_(types), values_(values) {}
ArgList(ULongLong types, const internal::Arg *args)
: types_(types), args_(args) {}
@@ -1089,14 +1225,18 @@ class ArgList {
internal::Arg operator[](unsigned index) const {
using internal::Arg;
Arg arg;
+ bool use_values = type(MAX_PACKED_ARGS - 1) == Arg::NONE;
if (index < MAX_PACKED_ARGS) {
Arg::Type arg_type = type(index);
+ internal::Value &val = arg;
if (arg_type != Arg::NONE)
- arg = args_[index];
+ val = use_values ? values_[index] : args_[index];
arg.type = arg_type;
return arg;
}
- if (type(MAX_PACKED_ARGS - 1) == Arg::NONE) {
+ if (use_values) {
+ // The index is greater than the number of arguments that can be stored
+ // in values, so return a "none" argument.
arg.type = Arg::NONE;
return arg;
}
@@ -1112,6 +1252,23 @@ struct FormatSpec;
namespace internal {
+template <typename Char>
+class ArgMap {
+ private:
+ typedef std::map<fmt::BasicStringRef<Char>, internal::Arg> MapType;
+ typedef typename MapType::value_type Pair;
+
+ MapType map_;
+
+ public:
+ void init(const ArgList &args);
+
+ const internal::Arg* find(const fmt::BasicStringRef<Char> &name) const {
+ typename MapType::const_iterator it = map_.find(name);
+ return it != map_.end() ? &it->second : 0;
+ }
+};
+
class FormatterBase {
private:
ArgList args_;
@@ -1121,6 +1278,8 @@ class FormatterBase {
Arg do_get_arg(unsigned arg_index, const char *&error);
protected:
+ const ArgList &args() const { return args_; }
+
void set_args(const ArgList &args) {
args_ = args;
next_arg_index_ = 0;
@@ -1133,6 +1292,8 @@ class FormatterBase {
// specified index.
Arg get_arg(unsigned arg_index, const char *&error);
+ bool check_no_auto_index(const char *&error);
+
template <typename Char>
void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
if (start != end)
@@ -1156,7 +1317,7 @@ class PrintfFormatter : private FormatterBase {
public:
void format(BasicWriter<Char> &writer,
- BasicStringRef<Char> format_str, const ArgList &args);
+ BasicCStringRef<Char> format_str, const ArgList &args);
};
} // namespace internal
@@ -1166,18 +1327,28 @@ class BasicFormatter : private internal::FormatterBase {
private:
BasicWriter<Char> &writer_;
const Char *start_;
+ internal::ArgMap<Char> map_;
FMT_DISALLOW_COPY_AND_ASSIGN(BasicFormatter);
+ using FormatterBase::get_arg;
+
+ // Checks if manual indexing is used and returns the argument with
+ // specified name.
+ internal::Arg get_arg(BasicStringRef<Char> arg_name, const char *&error);
+
// Parses argument index and returns corresponding argument.
internal::Arg parse_arg_index(const Char *&s);
+ // Parses argument name and returns corresponding argument.
+ internal::Arg parse_arg_name(const Char *&s);
+
public:
explicit BasicFormatter(BasicWriter<Char> &w) : writer_(w) {}
BasicWriter<Char> &writer() { return writer_; }
- void format(BasicStringRef<Char> format_str, const ArgList &args);
+ void format(BasicCStringRef<Char> format_str, const ArgList &args);
const Char *format(const Char *&format_str, const internal::Arg &arg);
};
@@ -1269,16 +1440,19 @@ class IntFormatSpec : public SpecT {
};
// A string format specifier.
-template <typename T>
+template <typename Char>
class StrFormatSpec : public AlignSpec {
private:
- const T *str_;
+ const Char *str_;
public:
- StrFormatSpec(const T *str, unsigned width, wchar_t fill)
- : AlignSpec(width, fill), str_(str) {}
+ template <typename FillChar>
+ StrFormatSpec(const Char *str, unsigned width, FillChar fill)
+ : AlignSpec(width, fill), str_(str) {
+ internal::CharTraits<Char>::convert(FillChar());
+ }
- const T *str() const { return str_; }
+ const Char *str() const { return str_; }
};
/**
@@ -1425,11 +1599,64 @@ inline uint64_t make_type() { return 0; }
template <typename T>
inline uint64_t make_type(const T &arg) { return MakeValue<char>::type(arg); }
+template <unsigned N>
+struct ArgArray {
+ // Computes the argument array size by adding 1 to N, which is the number of
+ // arguments, if N is zero, because array of zero size is invalid, or if N
+ // is greater than ArgList::MAX_PACKED_ARGS to accommodate for an extra
+ // argument that marks the end of the list.
+ enum { SIZE = N + (N == 0 || N >= ArgList::MAX_PACKED_ARGS ? 1 : 0) };
+
+ typedef typename Conditional<
+ (N < ArgList::MAX_PACKED_ARGS), Value, Arg>::type Type[SIZE];
+};
+
#if FMT_USE_VARIADIC_TEMPLATES
template <typename Arg, typename... Args>
inline uint64_t make_type(const Arg &first, const Args & ... tail) {
return make_type(first) | (make_type(tail...) << 4);
}
+
+inline void do_set_types(Arg *) {}
+
+template <typename T, typename... Args>
+inline void do_set_types(Arg *args, const T &arg, const Args & ... tail) {
+ args->type = static_cast<Arg::Type>(MakeValue<T>::type(arg));
+ do_set_types(args + 1, tail...);
+}
+
+template <typename... Args>
+inline void set_types(Arg *array, const Args & ... args) {
+ if (check(sizeof...(Args) > ArgList::MAX_PACKED_ARGS))
+ do_set_types(array, args...);
+ array[sizeof...(Args)].type = Arg::NONE;
+}
+
+template <typename... Args>
+inline void set_types(Value *, const Args & ...) {
+ // Do nothing as types are passed separately from values.
+}
+
+template <typename Char, typename Value>
+inline void store_args(Value *) {}
+
+template <typename Char, typename Arg, typename T, typename... Args>
+inline void store_args(Arg *args, const T &arg, const Args & ... tail) {
+ // Assign only the Value subobject of Arg and don't overwrite type (if any)
+ // that is assigned by set_types.
+ Value &value = *args;
+ value = MakeValue<Char>(arg);
+ store_args<Char>(args + 1, tail...);
+}
+
+template <typename Char, typename... Args>
+ArgList make_arg_list(typename ArgArray<sizeof...(Args)>::Type array,
+ const Args & ... args) {
+ if (check(sizeof...(Args) >= ArgList::MAX_PACKED_ARGS))
+ set_types(array, args...);
+ store_args<Char>(array, args...);
+ return ArgList(make_type(args...), array);
+}
#else
struct ArgType {
@@ -1462,24 +1689,17 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
// Defines a variadic function returning void.
# define FMT_VARIADIC_VOID(func, arg_type) \
template <typename... Args> \
- void func(arg_type arg1, const Args & ... args) { \
- const fmt::internal::Arg array[ \
- fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \
- fmt::internal::MakeValue<Char>(args)... \
- }; \
- func(arg1, ArgList(fmt::internal::make_type(args...), array)); \
+ void func(arg_type arg0, const Args & ... args) { \
+ typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
+ func(arg0, fmt::internal::make_arg_list<Char>(array, args...)); \
}
// Defines a variadic constructor.
# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \
template <typename... Args> \
ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \
- using fmt::internal::MakeValue; \
- const fmt::internal::Arg array[ \
- fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \
- MakeValue<Char>(args)... \
- }; \
- func(arg0, arg1, ArgList(fmt::internal::make_type(args...), array)); \
+ typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
+ func(arg0, arg1, fmt::internal::make_arg_list<Char>(array, args...)); \
}
#else
@@ -1492,9 +1712,9 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
# define FMT_WRAP1(func, arg_type, n) \
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
inline void func(arg_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
- const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \
+ const fmt::internal::ArgArray<n>::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \
func(arg1, fmt::ArgList( \
- fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), args)); \
+ fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array)); \
}
// Emulates a variadic function returning void on a pre-C++11 compiler.
@@ -1509,9 +1729,9 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
# define FMT_CTOR(ctor, func, arg0_type, arg1_type, n) \
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
ctor(arg0_type arg0, arg1_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
- const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \
+ const fmt::internal::ArgArray<n>::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \
func(arg0, arg1, fmt::ArgList( \
- fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), args)); \
+ fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array)); \
}
// Emulates a variadic constructor on a pre-C++11 compiler.
@@ -1556,7 +1776,7 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
*/
class SystemError : public internal::RuntimeError {
private:
- void init(int err_code, StringRef format_str, ArgList args);
+ void init(int err_code, CStringRef format_str, ArgList args);
protected:
int error_code_;
@@ -1591,10 +1811,10 @@ class SystemError : public internal::RuntimeError {
throw fmt::SystemError(errno, "cannot open file '{}'", filename);
\endrst
*/
- SystemError(int error_code, StringRef message) {
+ SystemError(int error_code, CStringRef message) {
init(error_code, message, ArgList());
}
- FMT_VARIADIC_CTOR(SystemError, init, int, StringRef)
+ FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef)
int error_code() const { return error_code_; }
};
@@ -1694,8 +1914,10 @@ class BasicWriter {
template<typename T>
void append_float_length(Char *&, T) {}
- friend class internal::ArgFormatter<Char>;
- friend class internal::PrintfFormatter<Char>;
+ template <typename Impl, typename Char_>
+ friend class internal::BasicArgFormatter;
+
+ friend class internal::PrintfArgFormatter<Char>;
protected:
/**
@@ -1705,7 +1927,9 @@ class BasicWriter {
public:
/**
+ \rst
Destroys a ``BasicWriter`` object.
+ \endrst
*/
virtual ~BasicWriter() {}
@@ -1732,7 +1956,9 @@ class BasicWriter {
}
/**
+ \rst
Returns the content of the output buffer as an `std::string`.
+ \endrst
*/
std::basic_string<Char> str() const {
return std::basic_string<Char>(&buffer_[0], buffer_.size());
@@ -1763,10 +1989,10 @@ class BasicWriter {
See also :ref:`syntax`.
\endrst
*/
- void write(BasicStringRef<Char> format, ArgList args) {
+ void write(BasicCStringRef<Char> format, ArgList args) {
BasicFormatter<Char>(*this).format(format, args);
}
- FMT_VARIADIC_VOID(write, BasicStringRef<Char>)
+ FMT_VARIADIC_VOID(write, BasicCStringRef<Char>)
BasicWriter &operator<<(int value) {
return *this << IntFormatSpec<int>(value);
@@ -1785,7 +2011,9 @@ class BasicWriter {
}
/**
+ \rst
Formats *value* and writes it to the stream.
+ \endrst
*/
BasicWriter &operator<<(ULongLong value) {
return *this << IntFormatSpec<ULongLong>(value);
@@ -1797,8 +2025,10 @@ class BasicWriter {
}
/**
+ \rst
Formats *value* using the general format for floating-point numbers
(``'g'``) and writes it to the stream.
+ \endrst
*/
BasicWriter &operator<<(long double value) {
write_double(value, FormatSpec());
@@ -1820,10 +2050,19 @@ class BasicWriter {
}
/**
+ \rst
Writes *value* to the stream.
+ \endrst
*/
BasicWriter &operator<<(fmt::BasicStringRef<Char> value) {
- const Char *str = value.c_str();
+ const Char *str = value.data();
+ buffer_.append(str, str + value.size());
+ return *this;
+ }
+
+ BasicWriter &operator<<(
+ typename internal::WCharHelper<StringRef, Char>::Supported value) {
+ const char *str = value.data();
buffer_.append(str, str + value.size());
return *this;
}
@@ -1838,7 +2077,6 @@ class BasicWriter {
template <typename StrChar>
BasicWriter &operator<<(const StrFormatSpec<StrChar> &spec) {
const StrChar *s = spec.str();
- // TODO: error if fill is not convertible to Char
write_str(s, std::char_traits<Char>::length(s), spec);
return *this;
}
@@ -1853,7 +2091,7 @@ typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
CharPtr out = CharPtr();
if (spec.width() > size) {
out = grow_buffer(spec.width());
- Char fill = static_cast<Char>(spec.fill());
+ Char fill = internal::CharTraits<Char>::cast(spec.fill());
if (spec.align() == ALIGN_RIGHT) {
std::fill_n(out, spec.width() - size, fill);
out += spec.width() - size;
@@ -1876,7 +2114,7 @@ typename BasicWriter<Char>::CharPtr
std::size_t content_size, wchar_t fill) {
std::size_t padding = total_size - content_size;
std::size_t left_padding = padding / 2;
- Char fill_char = static_cast<Char>(fill);
+ Char fill_char = internal::CharTraits<Char>::cast(fill);
std::fill_n(buffer, left_padding, fill_char);
buffer += left_padding;
CharPtr content = buffer;
@@ -1892,7 +2130,7 @@ typename BasicWriter<Char>::CharPtr
const char *prefix, unsigned prefix_size) {
unsigned width = spec.width();
Alignment align = spec.align();
- Char fill = static_cast<Char>(spec.fill());
+ Char fill = internal::CharTraits<Char>::cast(spec.fill());
if (spec.precision() > static_cast<int>(num_digits)) {
// Octal prefix '0' is counted as a digit, so ignore it if precision
// is specified.
@@ -2131,7 +2369,7 @@ void BasicWriter<Char>::write_double(
*format_ptr = '\0';
// Format using snprintf.
- Char fill = static_cast<Char>(spec.fill());
+ Char fill = internal::CharTraits<Char>::cast(spec.fill());
for (;;) {
std::size_t buffer_size = buffer_.capacity() - offset;
#if _MSC_VER
@@ -2284,8 +2522,7 @@ class BasicArrayWriter : public BasicWriter<Char> {
BasicArrayWriter(Char *array, std::size_t size)
: BasicWriter<Char>(buffer_), buffer_(array, size) {}
- // FIXME: this is temporary undocumented due to a bug in Sphinx
- /*
+ /**
\rst
Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the
size known at compile time.
@@ -2315,12 +2552,12 @@ void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value) {
// Can be used to report errors from destructors.
void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT;
-#ifdef _WIN32
+#if FMT_USE_WINDOWS_H
/** A Windows error. */
class WindowsError : public SystemError {
private:
- void init(int error_code, StringRef format_str, ArgList args);
+ void init(int error_code, CStringRef format_str, ArgList args);
public:
/**
@@ -2351,10 +2588,10 @@ class WindowsError : public SystemError {
}
\endrst
*/
- WindowsError(int error_code, StringRef message) {
+ WindowsError(int error_code, CStringRef message) {
init(error_code, message, ArgList());
}
- FMT_VARIADIC_CTOR(WindowsError, init, int, StringRef)
+ FMT_VARIADIC_CTOR(WindowsError, init, int, CStringRef)
};
// Reports a Windows error without throwing an exception.
@@ -2371,7 +2608,7 @@ enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE };
Example:
PrintColored(fmt::RED, "Elapsed time: {0:.2f} seconds") << 1.23;
*/
-void print_colored(Color c, StringRef format, ArgList args);
+void print_colored(Color c, CStringRef format, ArgList args);
/**
\rst
@@ -2382,13 +2619,13 @@ void print_colored(Color c, StringRef format, ArgList args);
std::string message = format("The answer is {}", 42);
\endrst
*/
-inline std::string format(StringRef format_str, ArgList args) {
+inline std::string format(CStringRef format_str, ArgList args) {
MemoryWriter w;
w.write(format_str, args);
return w.str();
}
-inline std::wstring format(WStringRef format_str, ArgList args) {
+inline std::wstring format(WCStringRef format_str, ArgList args) {
WMemoryWriter w;
w.write(format_str, args);
return w.str();
@@ -2403,7 +2640,7 @@ inline std::wstring format(WStringRef format_str, ArgList args) {
print(stderr, "Don't {}!", "panic");
\endrst
*/
-void print(std::FILE *f, StringRef format_str, ArgList args);
+void print(std::FILE *f, CStringRef format_str, ArgList args);
/**
\rst
@@ -2414,7 +2651,7 @@ void print(std::FILE *f, StringRef format_str, ArgList args);
print("Elapsed time: {0:.2f} seconds", 1.23);
\endrst
*/
-void print(StringRef format_str, ArgList args);
+void print(CStringRef format_str, ArgList args);
/**
\rst
@@ -2425,10 +2662,10 @@ void print(StringRef format_str, ArgList args);
print(cerr, "Don't {}!", "panic");
\endrst
*/
-void print(std::ostream &os, StringRef format_str, ArgList args);
+void print(std::ostream &os, CStringRef format_str, ArgList args);
template <typename Char>
-void printf(BasicWriter<Char> &w, BasicStringRef<Char> format, ArgList args) {
+void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) {
internal::PrintfFormatter<Char>().format(w, format, args);
}
@@ -2441,7 +2678,7 @@ void printf(BasicWriter<Char> &w, BasicStringRef<Char> format, ArgList args) {
std::string message = fmt::sprintf("The answer is %d", 42);
\endrst
*/
-inline std::string sprintf(StringRef format, ArgList args) {
+inline std::string sprintf(CStringRef format, ArgList args) {
MemoryWriter w;
printf(w, format, args);
return w.str();
@@ -2456,7 +2693,7 @@ inline std::string sprintf(StringRef format, ArgList args) {
fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst
*/
-int fprintf(std::FILE *f, StringRef format, ArgList args);
+int fprintf(std::FILE *f, CStringRef format, ArgList args);
/**
\rst
@@ -2467,7 +2704,7 @@ int fprintf(std::FILE *f, StringRef format, ArgList args);
fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst
*/
-inline int printf(StringRef format, ArgList args) {
+inline int printf(CStringRef format, ArgList args) {
return fprintf(stdout, format, args);
}
@@ -2543,7 +2780,9 @@ class FormatInt {
}
/**
- Returns the content of the output buffer as an `std::string`.
+ \rst
+ Returns the content of the output buffer as an ``std::string``.
+ \endrst
*/
std::string str() const { return std::string(str_, size()); }
};
@@ -2572,6 +2811,33 @@ inline void format_decimal(char *&buffer, T value) {
internal::format_decimal(buffer, abs_value, num_digits);
buffer += num_digits;
}
+
+/**
+ \rst
+ Returns a named argument for formatting functions.
+
+ **Example**::
+
+ print("Elapsed time: {s:.2f} seconds", arg("s", 1.23));
+
+ \endrst
+ */
+template <typename T>
+inline internal::NamedArg<char> arg(StringRef name, const T &arg) {
+ return internal::NamedArg<char>(name, arg);
+}
+
+template <typename T>
+inline internal::NamedArg<wchar_t> arg(WStringRef name, const T &arg) {
+ return internal::NamedArg<wchar_t>(name, arg);
+}
+
+// The following two functions are deleted intentionally to disable
+// nested named arguments as in ``format("{}", arg("a", arg("b", 42)))``.
+template <typename Char>
+void arg(StringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
+template <typename Char>
+void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
}
#if FMT_GCC_VERSION
@@ -2602,46 +2868,13 @@ inline void format_decimal(char *&buffer, T value) {
#define FMT_GET_ARG_NAME(type, index) arg##index
#if FMT_USE_VARIADIC_TEMPLATES
-
-namespace fmt {
-namespace internal {
-inline void do_set_types(Arg *) {}
-
-template <typename T, typename... Args>
-inline void do_set_types(Arg *args, const T &arg, const Args & ... tail) {
- args->type = static_cast<Arg::Type>(MakeValue<T>::type(arg));
- do_set_types(args + 1, tail...);
-}
-
-template <typename... Args>
-inline void set_types(Arg *array, const Args & ... args) {
- do_set_types(array, args...);
- array[sizeof...(Args)].type = Arg::NONE;
-}
-
-// Computes the argument array size by adding 1 to N, which is the number of
-// arguments, if N is zero, because array of zero size is invalid, or if N
-// is greater than ArgList::MAX_PACKED_ARGS to accommodate for an extra
-// argument that marks the end of the list.
-template <unsigned N>
-struct ArgArraySize {
- enum { VALUE = N + (N == 0 || N > ArgList::MAX_PACKED_ARGS ? 1 : 0) };
-};
-}
-}
-
# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
template <typename... Args> \
ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
const Args & ... args) { \
- using fmt::internal::Arg; \
- Arg array[fmt::internal::ArgArraySize<sizeof...(Args)>::VALUE] = { \
- fmt::internal::MakeValue<Char>(args)... \
- }; \
- if (fmt::internal::check((sizeof...(Args) > fmt::ArgList::MAX_PACKED_ARGS))) \
- set_types(array, args...); \
+ typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
- fmt::ArgList(fmt::internal::make_type(args...), array)); \
+ fmt::internal::make_arg_list<Char>(array, args...)); \
}
#else
// Defines a wrapper for a function taking __VA_ARGS__ arguments
@@ -2650,9 +2883,9 @@ struct ArgArraySize {
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
FMT_GEN(n, FMT_MAKE_ARG)) { \
- const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF_##Char)}; \
+ fmt::internal::ArgArray<n>::Type arr = {FMT_GEN(n, FMT_MAKE_REF_##Char)}; \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \
- fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), args)); \
+ fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr)); \
}
# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
@@ -2709,16 +2942,38 @@ struct ArgArraySize {
#define FMT_VARIADIC_W(ReturnType, func, ...) \
FMT_VARIADIC_(wchar_t, ReturnType, func, return func, __VA_ARGS__)
+#define FMT_CAPTURE_ARG_(id, index) ::fmt::arg(#id, id)
+
+#define FMT_CAPTURE_ARG_W_(id, index) ::fmt::arg(L###id, id)
+
+/**
+ \rst
+ Convenient macro to capture the arguments' names and values into several
+ ``fmt::arg(name, value)``.
+
+ **Example**::
+
+ int x = 1, y = 2;
+ print("point: ({x}, {y})", FMT_CAPTURE(x, y));
+ // same as:
+ // print("point: ({x}, {y})", arg("x", x), arg("y", y));
+
+ \endrst
+ */
+#define FMT_CAPTURE(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_, __VA_ARGS__)
+
+#define FMT_CAPTURE_W(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_W_, __VA_ARGS__)
+
namespace fmt {
-FMT_VARIADIC(std::string, format, StringRef)
-FMT_VARIADIC_W(std::wstring, format, WStringRef)
-FMT_VARIADIC(void, print, StringRef)
-FMT_VARIADIC(void, print, std::FILE *, StringRef)
-FMT_VARIADIC(void, print, std::ostream &, StringRef)
-FMT_VARIADIC(void, print_colored, Color, StringRef)
-FMT_VARIADIC(std::string, sprintf, StringRef)
-FMT_VARIADIC(int, printf, StringRef)
-FMT_VARIADIC(int, fprintf, std::FILE *, StringRef)
+FMT_VARIADIC(std::string, format, CStringRef)
+FMT_VARIADIC_W(std::wstring, format, WCStringRef)
+FMT_VARIADIC(void, print, CStringRef)
+FMT_VARIADIC(void, print, std::FILE *, CStringRef)
+FMT_VARIADIC(void, print, std::ostream &, CStringRef)
+FMT_VARIADIC(void, print_colored, Color, CStringRef)
+FMT_VARIADIC(std::string, sprintf, CStringRef)
+FMT_VARIADIC(int, printf, CStringRef)
+FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
}
// Restore warnings.