Conditionally compile constexpr
This commit is contained in:
parent
5d8ba816de
commit
dc5403612e
@ -42,6 +42,14 @@
|
||||
# define FMT_MSC_VER 0
|
||||
#endif
|
||||
|
||||
#ifndef FMT_CONSTEXPR
|
||||
# if FMT_HAS_FEATURE(cxx_constexpr)
|
||||
# define FMT_CONSTEXPR constexpr
|
||||
# else
|
||||
# define FMT_CONSTEXPR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef FMT_OVERRIDE
|
||||
# if FMT_HAS_FEATURE(cxx_override) || \
|
||||
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
|
||||
@ -141,10 +149,10 @@ class basic_string_view {
|
||||
using char_type = Char;
|
||||
using iterator = const Char *;
|
||||
|
||||
constexpr basic_string_view() FMT_NOEXCEPT : data_(0), size_(0) {}
|
||||
FMT_CONSTEXPR basic_string_view() FMT_NOEXCEPT : data_(0), size_(0) {}
|
||||
|
||||
/** Constructs a string reference object from a C string and a size. */
|
||||
constexpr basic_string_view(const Char *s, size_t size) FMT_NOEXCEPT
|
||||
FMT_CONSTEXPR basic_string_view(const Char *s, size_t size) FMT_NOEXCEPT
|
||||
: data_(s), size_(size) {}
|
||||
|
||||
/**
|
||||
@ -162,7 +170,7 @@ class basic_string_view {
|
||||
\endrst
|
||||
*/
|
||||
template <typename Alloc>
|
||||
constexpr basic_string_view(
|
||||
FMT_CONSTEXPR basic_string_view(
|
||||
const std::basic_string<Char, Alloc> &s) FMT_NOEXCEPT
|
||||
: data_(s.c_str()), size_(s.size()) {}
|
||||
|
||||
@ -179,12 +187,12 @@ class basic_string_view {
|
||||
const Char *data() const { return data_; }
|
||||
|
||||
/** Returns the string size. */
|
||||
constexpr size_t size() const { return size_; }
|
||||
FMT_CONSTEXPR size_t size() const { return size_; }
|
||||
|
||||
constexpr iterator begin() const { return data_; }
|
||||
constexpr iterator end() const { return data_ + size_; }
|
||||
FMT_CONSTEXPR iterator begin() const { return data_; }
|
||||
FMT_CONSTEXPR iterator end() const { return data_ + size_; }
|
||||
|
||||
constexpr void remove_prefix(size_t n) {
|
||||
FMT_CONSTEXPR void remove_prefix(size_t n) {
|
||||
data_ += n;
|
||||
size_ -= n;
|
||||
}
|
||||
@ -338,8 +346,8 @@ template <typename T>
|
||||
inline T const_check(T value) { return value; }
|
||||
|
||||
struct error_handler {
|
||||
constexpr error_handler() {}
|
||||
constexpr error_handler(const error_handler &) {}
|
||||
FMT_CONSTEXPR error_handler() {}
|
||||
FMT_CONSTEXPR error_handler(const error_handler &) {}
|
||||
|
||||
// This function is intentionally not constexpr to give a compile-time error.
|
||||
void on_error(const char *message);
|
||||
@ -377,12 +385,12 @@ enum type {
|
||||
CSTRING, STRING, POINTER, CUSTOM
|
||||
};
|
||||
|
||||
constexpr bool is_integral(type t) {
|
||||
FMT_CONSTEXPR bool is_integral(type t) {
|
||||
FMT_ASSERT(t != internal::NAMED_ARG, "invalid argument type");
|
||||
return t > internal::NONE && t <= internal::LAST_INTEGER_TYPE;
|
||||
}
|
||||
|
||||
constexpr bool is_arithmetic(type t) {
|
||||
FMT_CONSTEXPR bool is_arithmetic(type t) {
|
||||
FMT_ASSERT(t != internal::NAMED_ARG, "invalid argument type");
|
||||
return t > internal::NONE && t <= internal::LAST_NUMERIC_TYPE;
|
||||
}
|
||||
@ -403,82 +411,6 @@ FMT_DISABLE_CONVERSION_TO_INT(float);
|
||||
FMT_DISABLE_CONVERSION_TO_INT(double);
|
||||
FMT_DISABLE_CONVERSION_TO_INT(long double);
|
||||
|
||||
// Disambiguates conversions to different integral types.
|
||||
struct type_selector {
|
||||
static int convert(...);
|
||||
static int convert(int);
|
||||
static unsigned convert(unsigned);
|
||||
static long convert(long);
|
||||
static unsigned long convert(unsigned long);
|
||||
static long long convert(long long);
|
||||
static unsigned long long convert(unsigned long long);
|
||||
|
||||
template <typename T>
|
||||
static constexpr type select() {
|
||||
return sizeof(convert(std::declval<T>())) == sizeof(int) ? INT : LONG_LONG;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr type get_type() {
|
||||
return std::is_reference<T>::value || std::is_array<T>::value ?
|
||||
get_type<typename std::decay<T>::type>() :
|
||||
(is_named_arg<T>::value ?
|
||||
NAMED_ARG : (convert_to_int<T>::value ?
|
||||
type_selector::select<T>() : CUSTOM));
|
||||
}
|
||||
|
||||
template <> constexpr type get_type<bool>() { return BOOL; }
|
||||
template <> constexpr type get_type<short>() { return INT; }
|
||||
template <> constexpr type get_type<unsigned short>() { return UINT; }
|
||||
template <> constexpr type get_type<int>() { return INT; }
|
||||
template <> constexpr type get_type<unsigned>() { return UINT; }
|
||||
template <> constexpr type get_type<long>() {
|
||||
return sizeof(long) == sizeof(int) ? INT : LONG_LONG;
|
||||
}
|
||||
template <> constexpr type get_type<unsigned long>() {
|
||||
return sizeof(unsigned long) == sizeof(unsigned) ? UINT : ULONG_LONG;
|
||||
}
|
||||
template <> constexpr type get_type<long long>() { return LONG_LONG; }
|
||||
template <> constexpr type get_type<unsigned long long>() { return ULONG_LONG; }
|
||||
template <> constexpr type get_type<float>() { return DOUBLE; }
|
||||
template <> constexpr type get_type<double>() { return DOUBLE; }
|
||||
template <> constexpr type get_type<long double>() { return LONG_DOUBLE; }
|
||||
template <> constexpr type get_type<signed char>() { return INT; }
|
||||
template <> constexpr type get_type<unsigned char>() { return UINT; }
|
||||
template <> constexpr type get_type<char>() { return CHAR; }
|
||||
|
||||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
template <> constexpr type get_type<wchar_t>() { return CHAR; }
|
||||
#endif
|
||||
|
||||
template <> constexpr type get_type<char *>() { return CSTRING; }
|
||||
template <> constexpr type get_type<const char *>() { return CSTRING; }
|
||||
template <> constexpr type get_type<signed char *>() { return CSTRING; }
|
||||
template <> constexpr type get_type<const signed char *>() { return CSTRING; }
|
||||
template <> constexpr type get_type<unsigned char *>() { return CSTRING; }
|
||||
template <> constexpr type get_type<const unsigned char *>() { return CSTRING; }
|
||||
template <> constexpr type get_type<std::string>() { return STRING; }
|
||||
template <> constexpr type get_type<string_view>() { return STRING; }
|
||||
template <> constexpr type get_type<wchar_t *>() { return CSTRING; }
|
||||
template <> constexpr type get_type<const wchar_t *>() { return CSTRING; }
|
||||
template <> constexpr type get_type<std::wstring>() { return STRING; }
|
||||
template <> constexpr type get_type<wstring_view>() { return STRING; }
|
||||
template <> constexpr type get_type<void *>() { return POINTER; }
|
||||
template <> constexpr type get_type<const void *>() { return POINTER; }
|
||||
template <> constexpr type get_type<std::nullptr_t>() { return POINTER; }
|
||||
|
||||
template <typename Arg, typename... Args>
|
||||
constexpr uint64_t get_types() {
|
||||
return get_type<Arg>() | (get_types<Args...>() << 4);
|
||||
}
|
||||
|
||||
template <>
|
||||
constexpr uint64_t get_types<void>() { return 0; }
|
||||
|
||||
template <typename Context, typename T>
|
||||
constexpr basic_arg<Context> make_arg(const T &value);
|
||||
|
||||
template <typename Char>
|
||||
struct string_value {
|
||||
const Char *value;
|
||||
@ -511,118 +443,40 @@ class value {
|
||||
custom_value<Context> custom;
|
||||
};
|
||||
|
||||
constexpr value() : int_value(0) {}
|
||||
value(bool val) { set<BOOL>(int_value, val); }
|
||||
value(short val) { set<INT>(int_value, val); }
|
||||
value(unsigned short val) { set<UINT>(uint_value, val); }
|
||||
constexpr value(int val) : int_value(val) {}
|
||||
value(unsigned val) { set<UINT>(uint_value, val); }
|
||||
|
||||
value(long val) {
|
||||
// To minimize the number of types we need to deal with, long is
|
||||
// translated either to int or to long long depending on its size.
|
||||
if (const_check(sizeof(val) == sizeof(int)))
|
||||
int_value = static_cast<int>(val);
|
||||
else
|
||||
long_long_value = val;
|
||||
FMT_CONSTEXPR value(int val = 0) : int_value(val) {}
|
||||
value(unsigned val) { uint_value = val; }
|
||||
value(long long val) { long_long_value = val; }
|
||||
value(unsigned long long val) { ulong_long_value = val; }
|
||||
value(double val) { double_value = val; }
|
||||
value(long double val) { long_double_value = val; }
|
||||
value(const char_type *val) { string.value = val; }
|
||||
value(const signed char *val) {
|
||||
static_assert(std::is_same<char, char_type>::value,
|
||||
"incompatible string types");
|
||||
sstring.value = val;
|
||||
}
|
||||
|
||||
value(unsigned long val) {
|
||||
if (const_check(sizeof(val) == sizeof(unsigned)))
|
||||
uint_value = static_cast<unsigned>(val);
|
||||
else
|
||||
ulong_long_value = val;
|
||||
value(const unsigned char *val) {
|
||||
static_assert(std::is_same<char, char_type>::value,
|
||||
"incompatible string types");
|
||||
ustring.value = val;
|
||||
}
|
||||
|
||||
value(long long val) { set<LONG_LONG>(long_long_value, val); }
|
||||
value(unsigned long long val) { set<ULONG_LONG>(ulong_long_value, val); }
|
||||
value(float val) { set<DOUBLE>(double_value, val); }
|
||||
value(double val) { set<DOUBLE>(double_value, val); }
|
||||
value(long double val) { set<LONG_DOUBLE>(long_double_value, val); }
|
||||
value(signed char val) { set<INT>(int_value, val); }
|
||||
value(unsigned char val) { set<UINT>(uint_value, val); }
|
||||
value(char val) { set<CHAR>(int_value, val); }
|
||||
|
||||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
value(wchar_t val) {
|
||||
require_wchar<char_type>();
|
||||
set<CHAR>(int_value, val);
|
||||
value(basic_string_view<char_type> val) {
|
||||
string.value = val.data();
|
||||
string.size = val.size();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Formatting of wide strings into a narrow buffer and multibyte strings
|
||||
// into a wide buffer is disallowed (https://github.com/fmtlib/fmt/pull/606).
|
||||
value(char_type *s) { set<CSTRING>(string.value, s); }
|
||||
value(const char_type *s) { set<CSTRING>(string.value, s); }
|
||||
value(signed char *s) { set_cstring(sstring.value, s); }
|
||||
value(const signed char *s) { set_cstring(sstring.value, s); }
|
||||
value(unsigned char *s) { set_cstring(ustring.value, s); }
|
||||
value(const unsigned char *s) { set_cstring(ustring.value, s); }
|
||||
value(basic_string_view<char_type> s) { set_string(s); }
|
||||
value(const std::basic_string<char_type> &s) { set_string(s); }
|
||||
value(const void *val) { pointer = val; }
|
||||
|
||||
template <typename T>
|
||||
value(T *p) { set_pointer(p); }
|
||||
|
||||
template <typename T>
|
||||
value(const T *p) { set_pointer(p); }
|
||||
|
||||
value(std::nullptr_t) { pointer = nullptr; }
|
||||
|
||||
template <typename T>
|
||||
value(const T &val,
|
||||
typename std::enable_if<!convert_to_int<T>::value, int>::type = 0) {
|
||||
static_assert(get_type<T>() == CUSTOM, "invalid type");
|
||||
explicit value(const T &val) {
|
||||
custom.value = &val;
|
||||
custom.format = &format_custom_arg<T>;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
value(const named_arg<T, char_type> &val) {
|
||||
static_assert(get_type<const named_arg<T, char_type> &>() == NAMED_ARG,
|
||||
"invalid type");
|
||||
basic_arg<Context> arg = make_arg<Context>(val.value);
|
||||
std::memcpy(val.data, &arg, sizeof(arg));
|
||||
pointer = &val;
|
||||
}
|
||||
|
||||
const named_arg_base<char_type> &as_named_arg() {
|
||||
return *static_cast<const named_arg_base<char_type>*>(pointer);
|
||||
}
|
||||
|
||||
private:
|
||||
template <type TYPE, typename T, typename U>
|
||||
constexpr void set(T &field, const U &val) {
|
||||
static_assert(get_type<U>() == TYPE, "invalid type");
|
||||
field = val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void set_string(const T &val) {
|
||||
static_assert(get_type<T>() == STRING, "invalid type");
|
||||
string.value = val.data();
|
||||
string.size = val.size();
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
constexpr void set_cstring(T &field, const U *str) {
|
||||
static_assert(std::is_same<char, char_type>::value,
|
||||
"incompatible string types");
|
||||
set<CSTRING>(field, str);
|
||||
}
|
||||
|
||||
// Formatting of arbitrary pointers is disallowed. If you want to output a
|
||||
// pointer cast it to "void *" or "const void *". In particular, this forbids
|
||||
// formatting of "[const] volatile char *" which is printed as bool by
|
||||
// iostreams.
|
||||
template <typename T>
|
||||
void set_pointer(T *p) {
|
||||
using nonconst_type = typename std::remove_const<T>::type;
|
||||
static_assert(std::is_same<nonconst_type, void>::value,
|
||||
"formatting of non-void pointers is disallowed");
|
||||
set<POINTER>(pointer, p);
|
||||
}
|
||||
|
||||
// Formats an argument of a custom type, such as a user-defined class.
|
||||
template <typename T>
|
||||
static void format_custom_arg(const void *arg, Context &ctx) {
|
||||
@ -636,6 +490,97 @@ class value {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Context, type TYPE>
|
||||
struct typed_value : value<Context> {
|
||||
static const type type_tag = TYPE;
|
||||
|
||||
template <typename T>
|
||||
FMT_CONSTEXPR typed_value(const T &val) : value<Context>(val) {}
|
||||
};
|
||||
|
||||
template <typename Context, typename T>
|
||||
FMT_CONSTEXPR basic_arg<Context> make_arg(const T &value);
|
||||
|
||||
#define FMT_MAKE_VALUE(TAG, ArgType, ValueType) \
|
||||
template <typename C, typename char_type = typename C::char_type> \
|
||||
FMT_CONSTEXPR typed_value<C, TAG> make_value(ArgType val) { \
|
||||
return static_cast<ValueType>(val); \
|
||||
}
|
||||
|
||||
FMT_MAKE_VALUE(BOOL, bool, int)
|
||||
FMT_MAKE_VALUE(INT, short, int)
|
||||
FMT_MAKE_VALUE(UINT, unsigned short, unsigned)
|
||||
FMT_MAKE_VALUE(INT, int, int)
|
||||
FMT_MAKE_VALUE(UINT, unsigned, unsigned)
|
||||
|
||||
// To minimize the number of types we need to deal with, long is translated
|
||||
// either to int or to long long depending on its size.
|
||||
using long_type =
|
||||
std::conditional<sizeof(long) == sizeof(int), int, long long>::type;
|
||||
FMT_MAKE_VALUE(sizeof(long) == sizeof(int) ? INT : LONG_LONG, long, long_type);
|
||||
using ulong_type =
|
||||
std::conditional<sizeof(unsigned long) == sizeof(unsigned),
|
||||
unsigned, unsigned long long>::type;
|
||||
FMT_MAKE_VALUE(sizeof(unsigned long) == sizeof(unsigned) ? UINT : ULONG_LONG,
|
||||
unsigned long, ulong_type)
|
||||
|
||||
FMT_MAKE_VALUE(LONG_LONG, long long, long long)
|
||||
FMT_MAKE_VALUE(ULONG_LONG, unsigned long long, unsigned long long)
|
||||
FMT_MAKE_VALUE(INT, signed char, int)
|
||||
FMT_MAKE_VALUE(UINT, unsigned char, unsigned)
|
||||
FMT_MAKE_VALUE(CHAR, char, int)
|
||||
|
||||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
template <typename C>
|
||||
inline typed_value<C, CHAR> make_value(wchar_t val) {
|
||||
require_wchar<typename C::char_type>();
|
||||
return static_cast<int>(val);
|
||||
}
|
||||
#endif
|
||||
|
||||
FMT_MAKE_VALUE(DOUBLE, float, double)
|
||||
FMT_MAKE_VALUE(DOUBLE, double, double)
|
||||
FMT_MAKE_VALUE(LONG_DOUBLE, long double, long double)
|
||||
|
||||
// Formatting of wide strings into a narrow buffer and multibyte strings
|
||||
// into a wide buffer is disallowed (https://github.com/fmtlib/fmt/pull/606).
|
||||
FMT_MAKE_VALUE(CSTRING, char_type*, const char_type*)
|
||||
FMT_MAKE_VALUE(CSTRING, const char_type*, const char_type*)
|
||||
|
||||
FMT_MAKE_VALUE(CSTRING, signed char*, const signed char*)
|
||||
FMT_MAKE_VALUE(CSTRING, const signed char*, const signed char*)
|
||||
FMT_MAKE_VALUE(CSTRING, unsigned char*, const unsigned char*)
|
||||
FMT_MAKE_VALUE(CSTRING, const unsigned char*, const unsigned char*)
|
||||
FMT_MAKE_VALUE(STRING, basic_string_view<char_type>,
|
||||
basic_string_view<char_type>)
|
||||
FMT_MAKE_VALUE(STRING, const std::basic_string<char_type>&,
|
||||
basic_string_view<char_type>)
|
||||
FMT_MAKE_VALUE(POINTER, void*, const void*)
|
||||
FMT_MAKE_VALUE(POINTER, const void*, const void*)
|
||||
FMT_MAKE_VALUE(POINTER, std::nullptr_t, const void*)
|
||||
|
||||
// Formatting of arbitrary pointers is disallowed. If you want to output a
|
||||
// pointer cast it to "void *" or "const void *". In particular, this forbids
|
||||
// formatting of "[const] volatile char *" which is printed as bool by
|
||||
// iostreams.
|
||||
template <typename T>
|
||||
void make_value(const T *p) {
|
||||
static_assert(!sizeof(T), "formatting of non-void pointers is disallowed");
|
||||
}
|
||||
|
||||
template <typename C, typename T>
|
||||
inline typename std::enable_if<
|
||||
!convert_to_int<T>::value, typed_value<C, CUSTOM>>::type
|
||||
make_value(const T &val) { return val; }
|
||||
|
||||
template <typename C, typename T>
|
||||
typed_value<C, NAMED_ARG>
|
||||
make_value(const named_arg<T, typename C::char_type> &val) {
|
||||
basic_arg<C> arg = make_arg<C>(val.value);
|
||||
std::memcpy(val.data, &arg, sizeof(arg));
|
||||
return static_cast<const void*>(&val);
|
||||
}
|
||||
|
||||
// Maximum number of arguments with packed types.
|
||||
enum { MAX_PACKED_ARGS = 15 };
|
||||
|
||||
@ -652,10 +597,10 @@ class basic_arg {
|
||||
internal::type type_;
|
||||
|
||||
template <typename ContextType, typename T>
|
||||
friend constexpr basic_arg<ContextType> internal::make_arg(const T &value);
|
||||
friend FMT_CONSTEXPR basic_arg<ContextType> internal::make_arg(const T &value);
|
||||
|
||||
template <typename Visitor, typename Ctx>
|
||||
friend constexpr typename std::result_of<Visitor(int)>::type
|
||||
friend FMT_CONSTEXPR typename std::result_of<Visitor(int)>::type
|
||||
visit(Visitor &&vis, basic_arg<Ctx> arg);
|
||||
|
||||
friend class basic_format_args<Context>;
|
||||
@ -674,7 +619,7 @@ class basic_arg {
|
||||
internal::custom_value<Context> custom_;
|
||||
};
|
||||
|
||||
constexpr basic_arg() : type_(internal::NONE) {}
|
||||
FMT_CONSTEXPR basic_arg() : type_(internal::NONE) {}
|
||||
|
||||
explicit operator bool() const FMT_NOEXCEPT {
|
||||
return type_ != internal::NONE;
|
||||
@ -699,26 +644,28 @@ class basic_parse_context : private ErrorHandler {
|
||||
using char_type = Char;
|
||||
using iterator = typename basic_string_view<Char>::iterator;
|
||||
|
||||
explicit constexpr basic_parse_context(
|
||||
explicit FMT_CONSTEXPR basic_parse_context(
|
||||
basic_string_view<Char> format_str, ErrorHandler eh = ErrorHandler())
|
||||
: ErrorHandler(eh), format_str_(format_str), next_arg_id_(0) {}
|
||||
|
||||
// Returns an iterator to the beginning of the format string range being
|
||||
// parsed.
|
||||
constexpr iterator begin() const FMT_NOEXCEPT { return format_str_.begin(); }
|
||||
FMT_CONSTEXPR iterator begin() const FMT_NOEXCEPT {
|
||||
return format_str_.begin();
|
||||
}
|
||||
|
||||
// Returns an iterator past the end of the format string range being parsed.
|
||||
constexpr iterator end() const FMT_NOEXCEPT { return format_str_.end(); }
|
||||
FMT_CONSTEXPR iterator end() const FMT_NOEXCEPT { return format_str_.end(); }
|
||||
|
||||
// Advances the begin iterator to ``it``.
|
||||
constexpr void advance_to(iterator it) {
|
||||
FMT_CONSTEXPR void advance_to(iterator it) {
|
||||
format_str_.remove_prefix(it - begin());
|
||||
}
|
||||
|
||||
// Returns the next argument index.
|
||||
constexpr unsigned next_arg_id();
|
||||
FMT_CONSTEXPR unsigned next_arg_id();
|
||||
|
||||
constexpr bool check_arg_id(unsigned) {
|
||||
FMT_CONSTEXPR bool check_arg_id(unsigned) {
|
||||
if (next_arg_id_ > 0) {
|
||||
on_error("cannot switch from automatic to manual argument indexing");
|
||||
return false;
|
||||
@ -728,37 +675,17 @@ class basic_parse_context : private ErrorHandler {
|
||||
}
|
||||
void check_arg_id(basic_string_view<Char>) {}
|
||||
|
||||
constexpr void on_error(const char *message) {
|
||||
FMT_CONSTEXPR void on_error(const char *message) {
|
||||
ErrorHandler::on_error(message);
|
||||
}
|
||||
|
||||
constexpr ErrorHandler error_handler() const { return *this; }
|
||||
FMT_CONSTEXPR ErrorHandler error_handler() const { return *this; }
|
||||
};
|
||||
|
||||
using parse_context = basic_parse_context<char>;
|
||||
using wparse_context = basic_parse_context<wchar_t>;
|
||||
|
||||
namespace internal {
|
||||
template <typename Context, typename T>
|
||||
constexpr basic_arg<Context> make_arg(const T &value) {
|
||||
basic_arg<Context> arg;
|
||||
arg.type_ = get_type<T>();
|
||||
arg.value_ = value;
|
||||
return arg;
|
||||
}
|
||||
|
||||
template <bool IS_PACKED, typename Context, typename T>
|
||||
inline typename std::enable_if<IS_PACKED, value<Context>>::type
|
||||
make_arg(const T &value) {
|
||||
return {value};
|
||||
}
|
||||
|
||||
template <bool IS_PACKED, typename Context, typename T>
|
||||
inline typename std::enable_if<!IS_PACKED, basic_arg<Context>>::type
|
||||
make_arg(const T &value) {
|
||||
return make_arg<Context>(value);
|
||||
}
|
||||
|
||||
// A map from argument names to their values for named arguments.
|
||||
template <typename Context>
|
||||
class arg_map {
|
||||
@ -920,10 +847,47 @@ class basic_context :
|
||||
format_arg get_arg(basic_string_view<char_type> name);
|
||||
};
|
||||
|
||||
using context = basic_context<
|
||||
std::back_insert_iterator<internal::buffer>, char>;
|
||||
using wcontext = basic_context<
|
||||
std::back_insert_iterator<internal::wbuffer>, wchar_t>;
|
||||
template <typename Char>
|
||||
using buffer_context_t = basic_context<
|
||||
std::back_insert_iterator<internal::basic_buffer<Char>>, Char>;
|
||||
using context = buffer_context_t<char>;
|
||||
using wcontext = buffer_context_t<wchar_t>;
|
||||
|
||||
namespace internal {
|
||||
template <typename Context, typename T>
|
||||
FMT_CONSTEXPR type get_type() {
|
||||
using value_type = decltype(make_value<Context>(std::declval<T>()));
|
||||
return value_type::type_tag;
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
FMT_CONSTEXPR uint64_t get_types() { return 0; }
|
||||
|
||||
template <typename Context, typename Arg, typename... Args>
|
||||
FMT_CONSTEXPR uint64_t get_types() {
|
||||
return get_type<Context, Arg>() | (get_types<Context, Args...>() << 4);
|
||||
}
|
||||
|
||||
template <typename Context, typename T>
|
||||
FMT_CONSTEXPR basic_arg<Context> make_arg(const T &value) {
|
||||
basic_arg<Context> arg;
|
||||
arg.type_ = get_type<Context, T>();
|
||||
arg.value_ = make_value<Context>(value);
|
||||
return arg;
|
||||
}
|
||||
|
||||
template <bool IS_PACKED, typename Context, typename T>
|
||||
inline typename std::enable_if<IS_PACKED, value<Context>>::type
|
||||
make_arg(const T &value) {
|
||||
return make_value<Context>(value);
|
||||
}
|
||||
|
||||
template <bool IS_PACKED, typename Context, typename T>
|
||||
inline typename std::enable_if<!IS_PACKED, basic_arg<Context>>::type
|
||||
make_arg(const T &value) {
|
||||
return make_arg<Context>(value);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Context, typename ...Args>
|
||||
class arg_store {
|
||||
@ -940,8 +904,7 @@ class arg_store {
|
||||
value_type data_[NUM_ARGS + (IS_PACKED && NUM_ARGS != 0 ? 0 : 1)];
|
||||
|
||||
public:
|
||||
static const uint64_t TYPES = IS_PACKED ?
|
||||
internal::get_types<Args..., void>() : -static_cast<int64_t>(NUM_ARGS);
|
||||
static const uint64_t TYPES;
|
||||
|
||||
arg_store(const Args &... args)
|
||||
: data_{internal::make_arg<IS_PACKED, Context>(args)...} {}
|
||||
@ -951,6 +914,11 @@ class arg_store {
|
||||
const value_type *data() const { return data_; }
|
||||
};
|
||||
|
||||
template <typename Context, typename ...Args>
|
||||
const uint64_t arg_store<Context, Args...>::TYPES = IS_PACKED ?
|
||||
internal::get_types<Context, Args...>() :
|
||||
-static_cast<int64_t>(NUM_ARGS);
|
||||
|
||||
template <typename Context, typename ...Args>
|
||||
inline arg_store<Context, Args...> make_args(const Args & ... args) {
|
||||
return arg_store<Context, Args...>(args...);
|
||||
|
@ -293,7 +293,7 @@ namespace internal {
|
||||
|
||||
// Casts nonnegative integer to unsigned.
|
||||
template <typename Int>
|
||||
constexpr typename std::make_unsigned<Int>::type to_unsigned(Int value) {
|
||||
FMT_CONSTEXPR typename std::make_unsigned<Int>::type to_unsigned(Int value) {
|
||||
FMT_ASSERT(value >= 0, "negative value");
|
||||
return static_cast<typename std::make_unsigned<Int>::type>(value);
|
||||
}
|
||||
@ -561,7 +561,7 @@ template <typename Char>
|
||||
class null_terminating_iterator;
|
||||
|
||||
template <typename Char>
|
||||
constexpr const Char *pointer_from(null_terminating_iterator<Char> it);
|
||||
FMT_CONSTEXPR const Char *pointer_from(null_terminating_iterator<Char> it);
|
||||
|
||||
// An iterator that produces a null terminator on *end. This simplifies parsing
|
||||
// and allows comparing the performance of processing a null-terminated string
|
||||
@ -577,11 +577,11 @@ class null_terminating_iterator {
|
||||
|
||||
null_terminating_iterator() : ptr_(0), end_(0) {}
|
||||
|
||||
constexpr null_terminating_iterator(const Char *ptr, const Char *end)
|
||||
FMT_CONSTEXPR null_terminating_iterator(const Char *ptr, const Char *end)
|
||||
: ptr_(ptr), end_(end) {}
|
||||
|
||||
template <typename Range>
|
||||
constexpr explicit null_terminating_iterator(const Range &r)
|
||||
FMT_CONSTEXPR explicit null_terminating_iterator(const Range &r)
|
||||
: ptr_(r.begin()), end_(r.end()) {}
|
||||
|
||||
null_terminating_iterator &operator=(const Char *ptr) {
|
||||
@ -590,44 +590,45 @@ class null_terminating_iterator {
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Char operator*() const {
|
||||
FMT_CONSTEXPR Char operator*() const {
|
||||
return ptr_ != end_ ? *ptr_ : 0;
|
||||
}
|
||||
|
||||
constexpr null_terminating_iterator operator++() {
|
||||
FMT_CONSTEXPR null_terminating_iterator operator++() {
|
||||
++ptr_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr null_terminating_iterator operator++(int) {
|
||||
FMT_CONSTEXPR null_terminating_iterator operator++(int) {
|
||||
null_terminating_iterator result(*this);
|
||||
++ptr_;
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr null_terminating_iterator operator--() {
|
||||
FMT_CONSTEXPR null_terminating_iterator operator--() {
|
||||
--ptr_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr null_terminating_iterator operator+(difference_type n) {
|
||||
FMT_CONSTEXPR null_terminating_iterator operator+(difference_type n) {
|
||||
return null_terminating_iterator(ptr_ + n, end_);
|
||||
}
|
||||
|
||||
constexpr null_terminating_iterator operator-(difference_type n) {
|
||||
FMT_CONSTEXPR null_terminating_iterator operator-(difference_type n) {
|
||||
return null_terminating_iterator(ptr_ - n, end_);
|
||||
}
|
||||
|
||||
constexpr null_terminating_iterator operator+=(difference_type n) {
|
||||
FMT_CONSTEXPR null_terminating_iterator operator+=(difference_type n) {
|
||||
ptr_ += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr difference_type operator-(null_terminating_iterator other) const {
|
||||
FMT_CONSTEXPR difference_type operator-(
|
||||
null_terminating_iterator other) const {
|
||||
return ptr_ - other.ptr_;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(null_terminating_iterator other) const {
|
||||
FMT_CONSTEXPR bool operator!=(null_terminating_iterator other) const {
|
||||
return ptr_ != other.ptr_;
|
||||
}
|
||||
|
||||
@ -635,7 +636,8 @@ class null_terminating_iterator {
|
||||
return ptr_ >= other.ptr_;
|
||||
}
|
||||
|
||||
friend constexpr const Char *pointer_from<Char>(null_terminating_iterator it);
|
||||
friend FMT_CONSTEXPR const Char *pointer_from<Char>(
|
||||
null_terminating_iterator it);
|
||||
|
||||
private:
|
||||
const Char *ptr_;
|
||||
@ -643,10 +645,10 @@ class null_terminating_iterator {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr const T *pointer_from(const T *p) { return p; }
|
||||
FMT_CONSTEXPR const T *pointer_from(const T *p) { return p; }
|
||||
|
||||
template <typename Char>
|
||||
constexpr const Char *pointer_from(null_terminating_iterator<Char> it) {
|
||||
FMT_CONSTEXPR const Char *pointer_from(null_terminating_iterator<Char> it) {
|
||||
return it.ptr_;
|
||||
}
|
||||
|
||||
@ -686,12 +688,12 @@ class counting_iterator {
|
||||
// Returns true if value is negative, false otherwise.
|
||||
// Same as (value < 0) but doesn't produce warnings if T is an unsigned type.
|
||||
template <typename T>
|
||||
constexpr typename std::enable_if<
|
||||
FMT_CONSTEXPR typename std::enable_if<
|
||||
std::numeric_limits<T>::is_signed, bool>::type is_negative(T value) {
|
||||
return value < 0;
|
||||
}
|
||||
template <typename T>
|
||||
constexpr typename std::enable_if<
|
||||
FMT_CONSTEXPR typename std::enable_if<
|
||||
!std::numeric_limits<T>::is_signed, bool>::type is_negative(T) {
|
||||
return false;
|
||||
}
|
||||
@ -988,7 +990,7 @@ struct monostate {};
|
||||
\endrst
|
||||
*/
|
||||
template <typename Visitor, typename Context>
|
||||
constexpr typename std::result_of<Visitor(int)>::type
|
||||
FMT_CONSTEXPR typename std::result_of<Visitor(int)>::type
|
||||
visit(Visitor &&vis, basic_arg<Context> arg) {
|
||||
using char_type = typename Context::char_type;
|
||||
switch (arg.type_) {
|
||||
@ -1071,13 +1073,13 @@ struct align_spec : empty_spec {
|
||||
wchar_t fill_;
|
||||
alignment align_;
|
||||
|
||||
constexpr align_spec(
|
||||
FMT_CONSTEXPR align_spec(
|
||||
unsigned width, wchar_t fill, alignment align = ALIGN_DEFAULT)
|
||||
: width_(width), fill_(fill), align_(align) {}
|
||||
|
||||
constexpr unsigned width() const { return width_; }
|
||||
constexpr wchar_t fill() const { return fill_; }
|
||||
constexpr alignment align() const { return align_; }
|
||||
FMT_CONSTEXPR unsigned width() const { return width_; }
|
||||
FMT_CONSTEXPR wchar_t fill() const { return fill_; }
|
||||
FMT_CONSTEXPR alignment align() const { return align_; }
|
||||
|
||||
int precision() const { return -1; }
|
||||
};
|
||||
@ -1112,7 +1114,7 @@ class basic_format_specs : public align_spec {
|
||||
int precision_;
|
||||
Char type_;
|
||||
|
||||
constexpr basic_format_specs(
|
||||
FMT_CONSTEXPR basic_format_specs(
|
||||
unsigned width = 0, char type = 0, wchar_t fill = ' ')
|
||||
: align_spec(width, fill), flags_(0), precision_(-1), type_(type) {}
|
||||
|
||||
@ -1122,15 +1124,15 @@ class basic_format_specs : public align_spec {
|
||||
set(specs...);
|
||||
}
|
||||
|
||||
constexpr bool flag(unsigned f) const { return (flags_ & f) != 0; }
|
||||
constexpr int precision() const { return precision_; }
|
||||
constexpr Char type() const { return type_; }
|
||||
FMT_CONSTEXPR bool flag(unsigned f) const { return (flags_ & f) != 0; }
|
||||
FMT_CONSTEXPR int precision() const { return precision_; }
|
||||
FMT_CONSTEXPR Char type() const { return type_; }
|
||||
};
|
||||
|
||||
typedef basic_format_specs<char> format_specs;
|
||||
|
||||
template <typename Char, typename ErrorHandler>
|
||||
constexpr unsigned basic_parse_context<Char, ErrorHandler>::next_arg_id() {
|
||||
FMT_CONSTEXPR unsigned basic_parse_context<Char, ErrorHandler>::next_arg_id() {
|
||||
if (next_arg_id_ >= 0)
|
||||
return internal::to_unsigned(next_arg_id_++);
|
||||
on_error("cannot switch from manual to automatic argument indexing");
|
||||
@ -1140,7 +1142,7 @@ constexpr unsigned basic_parse_context<Char, ErrorHandler>::next_arg_id() {
|
||||
namespace internal {
|
||||
|
||||
template <typename Handler>
|
||||
constexpr void handle_int_type_spec(char spec, Handler &&handler) {
|
||||
FMT_CONSTEXPR void handle_int_type_spec(char spec, Handler &&handler) {
|
||||
switch (spec) {
|
||||
case 0: case 'd':
|
||||
handler.on_dec();
|
||||
@ -1163,7 +1165,7 @@ constexpr void handle_int_type_spec(char spec, Handler &&handler) {
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
constexpr void handle_float_type_spec(char spec, Handler &&handler) {
|
||||
FMT_CONSTEXPR void handle_float_type_spec(char spec, Handler &&handler) {
|
||||
switch (spec) {
|
||||
case 0: case 'g': case 'G':
|
||||
handler.on_general();
|
||||
@ -1184,7 +1186,7 @@ constexpr void handle_float_type_spec(char spec, Handler &&handler) {
|
||||
}
|
||||
|
||||
template <typename Char, typename Handler>
|
||||
constexpr void handle_char_specs(
|
||||
FMT_CONSTEXPR void handle_char_specs(
|
||||
const basic_format_specs<Char> &specs, Handler &&handler) {
|
||||
if (specs.type() && specs.type() != 'c') {
|
||||
handler.on_int();
|
||||
@ -1196,7 +1198,7 @@ constexpr void handle_char_specs(
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
constexpr void handle_cstring_type_spec(char spec, Handler &&handler) {
|
||||
FMT_CONSTEXPR void handle_cstring_type_spec(char spec, Handler &&handler) {
|
||||
if (spec == 0 || spec == 's')
|
||||
handler.on_string();
|
||||
else if (spec == 'p')
|
||||
@ -1206,13 +1208,13 @@ constexpr void handle_cstring_type_spec(char spec, Handler &&handler) {
|
||||
}
|
||||
|
||||
template <typename Char, typename ErrorHandler>
|
||||
constexpr void check_string_type_spec(Char spec, ErrorHandler &&eh) {
|
||||
FMT_CONSTEXPR void check_string_type_spec(Char spec, ErrorHandler &&eh) {
|
||||
if (spec != 0 && spec != 's')
|
||||
eh.on_error("invalid type specifier");
|
||||
}
|
||||
|
||||
template <typename ErrorHandler>
|
||||
constexpr void check_pointer_type_spec(char spec, ErrorHandler &&eh) {
|
||||
FMT_CONSTEXPR void check_pointer_type_spec(char spec, ErrorHandler &&eh) {
|
||||
if (spec != 0 && spec != 'p')
|
||||
eh.on_error("invalid type specifier");
|
||||
}
|
||||
@ -1220,15 +1222,15 @@ constexpr void check_pointer_type_spec(char spec, ErrorHandler &&eh) {
|
||||
template <typename ErrorHandler>
|
||||
class int_type_checker : private ErrorHandler {
|
||||
public:
|
||||
constexpr explicit int_type_checker(ErrorHandler eh) : ErrorHandler(eh) {}
|
||||
FMT_CONSTEXPR explicit int_type_checker(ErrorHandler eh) : ErrorHandler(eh) {}
|
||||
|
||||
constexpr void on_dec() {}
|
||||
constexpr void on_hex() {}
|
||||
constexpr void on_bin() {}
|
||||
constexpr void on_oct() {}
|
||||
constexpr void on_num() {}
|
||||
FMT_CONSTEXPR void on_dec() {}
|
||||
FMT_CONSTEXPR void on_hex() {}
|
||||
FMT_CONSTEXPR void on_bin() {}
|
||||
FMT_CONSTEXPR void on_oct() {}
|
||||
FMT_CONSTEXPR void on_num() {}
|
||||
|
||||
constexpr void on_error() {
|
||||
FMT_CONSTEXPR void on_error() {
|
||||
ErrorHandler::on_error("invalid type specifier");
|
||||
}
|
||||
};
|
||||
@ -1236,14 +1238,15 @@ class int_type_checker : private ErrorHandler {
|
||||
template <typename ErrorHandler>
|
||||
class float_type_checker : private ErrorHandler {
|
||||
public:
|
||||
constexpr explicit float_type_checker(ErrorHandler eh) : ErrorHandler(eh) {}
|
||||
FMT_CONSTEXPR explicit float_type_checker(ErrorHandler eh)
|
||||
: ErrorHandler(eh) {}
|
||||
|
||||
constexpr void on_general() {}
|
||||
constexpr void on_exp() {}
|
||||
constexpr void on_fixed() {}
|
||||
constexpr void on_hex() {}
|
||||
FMT_CONSTEXPR void on_general() {}
|
||||
FMT_CONSTEXPR void on_exp() {}
|
||||
FMT_CONSTEXPR void on_fixed() {}
|
||||
FMT_CONSTEXPR void on_hex() {}
|
||||
|
||||
constexpr void on_error() {
|
||||
FMT_CONSTEXPR void on_error() {
|
||||
ErrorHandler::on_error("invalid type specifier");
|
||||
}
|
||||
};
|
||||
@ -1254,22 +1257,23 @@ class char_specs_checker : public ErrorHandler {
|
||||
char type_;
|
||||
|
||||
public:
|
||||
constexpr char_specs_checker(char type, ErrorHandler eh)
|
||||
FMT_CONSTEXPR char_specs_checker(char type, ErrorHandler eh)
|
||||
: ErrorHandler(eh), type_(type) {}
|
||||
|
||||
constexpr void on_int() {
|
||||
FMT_CONSTEXPR void on_int() {
|
||||
handle_int_type_spec(type_, int_type_checker<ErrorHandler>(*this));
|
||||
}
|
||||
constexpr void on_char() {}
|
||||
FMT_CONSTEXPR void on_char() {}
|
||||
};
|
||||
|
||||
template <typename ErrorHandler>
|
||||
class cstring_type_checker : public ErrorHandler {
|
||||
public:
|
||||
constexpr explicit cstring_type_checker(ErrorHandler eh) : ErrorHandler(eh) {}
|
||||
FMT_CONSTEXPR explicit cstring_type_checker(ErrorHandler eh)
|
||||
: ErrorHandler(eh) {}
|
||||
|
||||
constexpr void on_string() {}
|
||||
constexpr void on_pointer() {}
|
||||
FMT_CONSTEXPR void on_string() {}
|
||||
FMT_CONSTEXPR void on_pointer() {}
|
||||
};
|
||||
|
||||
template <typename Context>
|
||||
@ -1412,7 +1416,7 @@ class arg_formatter_base {
|
||||
struct format_string {};
|
||||
|
||||
template <typename Char>
|
||||
constexpr bool is_name_start(Char c) {
|
||||
FMT_CONSTEXPR bool is_name_start(Char c) {
|
||||
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;
|
||||
}
|
||||
|
||||
@ -1420,7 +1424,7 @@ constexpr bool is_name_start(Char c) {
|
||||
// first character is a digit and presence of a non-digit character at the end.
|
||||
// it: an iterator pointing to the beginning of the input range.
|
||||
template <typename Iterator, typename ErrorHandler>
|
||||
constexpr unsigned parse_nonnegative_int(Iterator &it, ErrorHandler &&eh) {
|
||||
FMT_CONSTEXPR unsigned parse_nonnegative_int(Iterator &it, ErrorHandler &&eh) {
|
||||
assert('0' <= *it && *it <= '9');
|
||||
unsigned value = 0;
|
||||
// Convert to unsigned to prevent a warning.
|
||||
@ -1471,10 +1475,10 @@ struct is_integer {
|
||||
template <typename ErrorHandler>
|
||||
class width_checker {
|
||||
public:
|
||||
explicit constexpr width_checker(ErrorHandler &eh) : handler_(eh) {}
|
||||
explicit FMT_CONSTEXPR width_checker(ErrorHandler &eh) : handler_(eh) {}
|
||||
|
||||
template <typename T>
|
||||
constexpr typename std::enable_if<
|
||||
FMT_CONSTEXPR typename std::enable_if<
|
||||
is_integer<T>::value, unsigned long long>::type operator()(T value) {
|
||||
if (is_negative(value))
|
||||
handler_.on_error("negative width");
|
||||
@ -1482,7 +1486,7 @@ class width_checker {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr typename std::enable_if<
|
||||
FMT_CONSTEXPR typename std::enable_if<
|
||||
!is_integer<T>::value, unsigned long long>::type operator()(T) {
|
||||
handler_.on_error("width is not integer");
|
||||
return 0;
|
||||
@ -1495,10 +1499,10 @@ class width_checker {
|
||||
template <typename ErrorHandler>
|
||||
class precision_checker {
|
||||
public:
|
||||
explicit constexpr precision_checker(ErrorHandler &eh) : handler_(eh) {}
|
||||
explicit FMT_CONSTEXPR precision_checker(ErrorHandler &eh) : handler_(eh) {}
|
||||
|
||||
template <typename T>
|
||||
constexpr typename std::enable_if<
|
||||
FMT_CONSTEXPR typename std::enable_if<
|
||||
is_integer<T>::value, unsigned long long>::type operator()(T value) {
|
||||
if (is_negative(value))
|
||||
handler_.on_error("negative precision");
|
||||
@ -1506,7 +1510,7 @@ class precision_checker {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr typename std::enable_if<
|
||||
FMT_CONSTEXPR typename std::enable_if<
|
||||
!is_integer<T>::value, unsigned long long>::type operator()(T) {
|
||||
handler_.on_error("precision is not integer");
|
||||
return 0;
|
||||
@ -1520,30 +1524,30 @@ class precision_checker {
|
||||
template <typename Char>
|
||||
class specs_setter {
|
||||
public:
|
||||
explicit constexpr specs_setter(basic_format_specs<Char> &specs):
|
||||
explicit FMT_CONSTEXPR specs_setter(basic_format_specs<Char> &specs):
|
||||
specs_(specs) {}
|
||||
|
||||
constexpr specs_setter(const specs_setter &other) : specs_(other.specs_) {}
|
||||
FMT_CONSTEXPR specs_setter(const specs_setter &other) : specs_(other.specs_) {}
|
||||
|
||||
constexpr void on_align(alignment align) { specs_.align_ = align; }
|
||||
constexpr void on_fill(Char fill) { specs_.fill_ = fill; }
|
||||
constexpr void on_plus() { specs_.flags_ |= SIGN_FLAG | PLUS_FLAG; }
|
||||
constexpr void on_minus() { specs_.flags_ |= MINUS_FLAG; }
|
||||
constexpr void on_space() { specs_.flags_ |= SIGN_FLAG; }
|
||||
constexpr void on_hash() { specs_.flags_ |= HASH_FLAG; }
|
||||
FMT_CONSTEXPR void on_align(alignment align) { specs_.align_ = align; }
|
||||
FMT_CONSTEXPR void on_fill(Char fill) { specs_.fill_ = fill; }
|
||||
FMT_CONSTEXPR void on_plus() { specs_.flags_ |= SIGN_FLAG | PLUS_FLAG; }
|
||||
FMT_CONSTEXPR void on_minus() { specs_.flags_ |= MINUS_FLAG; }
|
||||
FMT_CONSTEXPR void on_space() { specs_.flags_ |= SIGN_FLAG; }
|
||||
FMT_CONSTEXPR void on_hash() { specs_.flags_ |= HASH_FLAG; }
|
||||
|
||||
constexpr void on_zero() {
|
||||
FMT_CONSTEXPR void on_zero() {
|
||||
specs_.align_ = ALIGN_NUMERIC;
|
||||
specs_.fill_ = '0';
|
||||
}
|
||||
|
||||
constexpr void on_width(unsigned width) { specs_.width_ = width; }
|
||||
constexpr void on_precision(unsigned precision) {
|
||||
FMT_CONSTEXPR void on_width(unsigned width) { specs_.width_ = width; }
|
||||
FMT_CONSTEXPR void on_precision(unsigned precision) {
|
||||
specs_.precision_ = precision;
|
||||
}
|
||||
constexpr void end_precision() {}
|
||||
FMT_CONSTEXPR void end_precision() {}
|
||||
|
||||
constexpr void on_type(Char type) { specs_.type_ = type; }
|
||||
FMT_CONSTEXPR void on_type(Char type) { specs_.type_ = type; }
|
||||
|
||||
protected:
|
||||
basic_format_specs<Char> &specs_;
|
||||
@ -1554,55 +1558,55 @@ class specs_setter {
|
||||
template <typename Handler>
|
||||
class specs_checker : public Handler {
|
||||
public:
|
||||
constexpr specs_checker(const Handler& handler, internal::type arg_type)
|
||||
FMT_CONSTEXPR specs_checker(const Handler& handler, internal::type arg_type)
|
||||
: Handler(handler), arg_type_(arg_type) {}
|
||||
|
||||
constexpr specs_checker(const specs_checker &other)
|
||||
FMT_CONSTEXPR specs_checker(const specs_checker &other)
|
||||
: Handler(other), arg_type_(other.arg_type_) {}
|
||||
|
||||
constexpr void on_align(alignment align) {
|
||||
FMT_CONSTEXPR void on_align(alignment align) {
|
||||
if (align == ALIGN_NUMERIC)
|
||||
require_numeric_argument();
|
||||
Handler::on_align(align);
|
||||
}
|
||||
|
||||
constexpr void on_plus() {
|
||||
FMT_CONSTEXPR void on_plus() {
|
||||
check_sign();
|
||||
Handler::on_plus();
|
||||
}
|
||||
|
||||
constexpr void on_minus() {
|
||||
FMT_CONSTEXPR void on_minus() {
|
||||
check_sign();
|
||||
Handler::on_minus();
|
||||
}
|
||||
|
||||
constexpr void on_space() {
|
||||
FMT_CONSTEXPR void on_space() {
|
||||
check_sign();
|
||||
Handler::on_space();
|
||||
}
|
||||
|
||||
constexpr void on_hash() {
|
||||
FMT_CONSTEXPR void on_hash() {
|
||||
require_numeric_argument();
|
||||
Handler::on_hash();
|
||||
}
|
||||
|
||||
constexpr void on_zero() {
|
||||
FMT_CONSTEXPR void on_zero() {
|
||||
require_numeric_argument();
|
||||
Handler::on_zero();
|
||||
}
|
||||
|
||||
constexpr void end_precision() {
|
||||
FMT_CONSTEXPR void end_precision() {
|
||||
if (is_integral(arg_type_) || arg_type_ == POINTER)
|
||||
this->on_error("precision not allowed for this argument type");
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr void require_numeric_argument() {
|
||||
FMT_CONSTEXPR void require_numeric_argument() {
|
||||
if (!is_arithmetic(arg_type_))
|
||||
this->on_error("format specifier requires numeric argument");
|
||||
}
|
||||
|
||||
constexpr void check_sign() {
|
||||
FMT_CONSTEXPR void check_sign() {
|
||||
require_numeric_argument();
|
||||
if (is_integral(arg_type_) && arg_type_ != INT && arg_type_ != LONG_LONG &&
|
||||
arg_type_ != CHAR) {
|
||||
@ -1615,7 +1619,7 @@ class specs_checker : public Handler {
|
||||
|
||||
template <template <typename> class Handler, typename T,
|
||||
typename Context, typename ErrorHandler>
|
||||
constexpr void set_dynamic_spec(
|
||||
FMT_CONSTEXPR void set_dynamic_spec(
|
||||
T &value, basic_arg<Context> arg, ErrorHandler eh) {
|
||||
unsigned long long big_value = visit(Handler<ErrorHandler>(eh), arg);
|
||||
if (big_value > (std::numeric_limits<int>::max)())
|
||||
@ -1631,17 +1635,17 @@ class specs_handler: public specs_setter<typename Context::char_type> {
|
||||
public:
|
||||
typedef typename Context::char_type char_type;
|
||||
|
||||
constexpr specs_handler(basic_format_specs<char_type> &specs, Context &ctx)
|
||||
FMT_CONSTEXPR specs_handler(basic_format_specs<char_type> &specs, Context &ctx)
|
||||
: specs_setter<char_type>(specs), context_(ctx) {}
|
||||
|
||||
template <typename Id>
|
||||
constexpr void on_dynamic_width(Id arg_id) {
|
||||
FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
|
||||
set_dynamic_spec<width_checker>(
|
||||
this->specs_.width_, get_arg(arg_id), context_.error_handler());
|
||||
}
|
||||
|
||||
template <typename Id>
|
||||
constexpr void on_dynamic_precision(Id arg_id) {
|
||||
FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {
|
||||
set_dynamic_spec<precision_checker>(
|
||||
this->specs_.precision_, get_arg(arg_id), context_.error_handler());
|
||||
}
|
||||
@ -1651,12 +1655,12 @@ class specs_handler: public specs_setter<typename Context::char_type> {
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr basic_arg<Context> get_arg(auto_id) {
|
||||
FMT_CONSTEXPR basic_arg<Context> get_arg(auto_id) {
|
||||
return context_.next_arg();
|
||||
}
|
||||
|
||||
template <typename Id>
|
||||
constexpr basic_arg<Context> get_arg(Id arg_id) {
|
||||
FMT_CONSTEXPR basic_arg<Context> get_arg(Id arg_id) {
|
||||
context_.parse_context().check_arg_id(arg_id);
|
||||
return context_.get_arg(arg_id);
|
||||
}
|
||||
@ -1669,11 +1673,11 @@ template <typename Char>
|
||||
struct arg_ref {
|
||||
enum Kind { NONE, INDEX, NAME };
|
||||
|
||||
constexpr arg_ref() : kind(NONE), index(0) {}
|
||||
constexpr explicit arg_ref(unsigned index) : kind(INDEX), index(index) {}
|
||||
FMT_CONSTEXPR arg_ref() : kind(NONE), index(0) {}
|
||||
FMT_CONSTEXPR explicit arg_ref(unsigned index) : kind(INDEX), index(index) {}
|
||||
explicit arg_ref(basic_string_view<Char> name) : kind(NAME), name(name) {}
|
||||
|
||||
constexpr arg_ref &operator=(unsigned index) {
|
||||
FMT_CONSTEXPR arg_ref &operator=(unsigned index) {
|
||||
kind = INDEX;
|
||||
this->index = index;
|
||||
return *this;
|
||||
@ -1703,25 +1707,25 @@ class dynamic_specs_handler :
|
||||
public:
|
||||
using char_type = typename ParseContext::char_type;
|
||||
|
||||
constexpr dynamic_specs_handler(
|
||||
FMT_CONSTEXPR dynamic_specs_handler(
|
||||
dynamic_format_specs<char_type> &specs, ParseContext &ctx)
|
||||
: specs_setter<char_type>(specs), specs_(specs), context_(ctx) {}
|
||||
|
||||
constexpr dynamic_specs_handler(const dynamic_specs_handler &other)
|
||||
FMT_CONSTEXPR dynamic_specs_handler(const dynamic_specs_handler &other)
|
||||
: specs_setter<char_type>(other),
|
||||
specs_(other.specs_), context_(other.context_) {}
|
||||
|
||||
template <typename Id>
|
||||
constexpr void on_dynamic_width(Id arg_id) {
|
||||
FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
|
||||
specs_.width_ref = make_arg_ref(arg_id);
|
||||
}
|
||||
|
||||
template <typename Id>
|
||||
constexpr void on_dynamic_precision(Id arg_id) {
|
||||
FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {
|
||||
specs_.precision_ref = make_arg_ref(arg_id);
|
||||
}
|
||||
|
||||
constexpr void on_error(const char *message) {
|
||||
FMT_CONSTEXPR void on_error(const char *message) {
|
||||
context_.on_error(message);
|
||||
}
|
||||
|
||||
@ -1729,12 +1733,12 @@ class dynamic_specs_handler :
|
||||
using arg_ref_type = arg_ref<char_type>;
|
||||
|
||||
template <typename Id>
|
||||
constexpr arg_ref_type make_arg_ref(Id arg_id) {
|
||||
FMT_CONSTEXPR arg_ref_type make_arg_ref(Id arg_id) {
|
||||
context_.check_arg_id(arg_id);
|
||||
return arg_ref_type(arg_id);
|
||||
}
|
||||
|
||||
constexpr arg_ref_type make_arg_ref(auto_id) {
|
||||
FMT_CONSTEXPR arg_ref_type make_arg_ref(auto_id) {
|
||||
return arg_ref_type(context_.next_arg_id());
|
||||
}
|
||||
|
||||
@ -1743,7 +1747,7 @@ class dynamic_specs_handler :
|
||||
};
|
||||
|
||||
template <typename Iterator, typename IDHandler>
|
||||
constexpr Iterator parse_arg_id(Iterator it, IDHandler &&handler) {
|
||||
FMT_CONSTEXPR Iterator parse_arg_id(Iterator it, IDHandler &&handler) {
|
||||
using char_type = typename std::iterator_traits<Iterator>::value_type;
|
||||
char_type c = *it;
|
||||
if (c == '}' || c == ':') {
|
||||
@ -1774,15 +1778,17 @@ constexpr Iterator parse_arg_id(Iterator it, IDHandler &&handler) {
|
||||
// Adapts SpecHandler to IDHandler API for dynamic width.
|
||||
template <typename SpecHandler, typename Char>
|
||||
struct width_adapter {
|
||||
explicit constexpr width_adapter(SpecHandler &h) : handler(h) {}
|
||||
explicit FMT_CONSTEXPR width_adapter(SpecHandler &h) : handler(h) {}
|
||||
|
||||
constexpr void operator()() { handler.on_dynamic_width(auto_id()); }
|
||||
constexpr void operator()(unsigned id) { handler.on_dynamic_width(id); }
|
||||
constexpr void operator()(basic_string_view<Char> id) {
|
||||
FMT_CONSTEXPR void operator()() { handler.on_dynamic_width(auto_id()); }
|
||||
FMT_CONSTEXPR void operator()(unsigned id) { handler.on_dynamic_width(id); }
|
||||
FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {
|
||||
handler.on_dynamic_width(id);
|
||||
}
|
||||
|
||||
constexpr void on_error(const char *message) { handler.on_error(message); }
|
||||
FMT_CONSTEXPR void on_error(const char *message) {
|
||||
handler.on_error(message);
|
||||
}
|
||||
|
||||
SpecHandler &handler;
|
||||
};
|
||||
@ -1790,15 +1796,17 @@ struct width_adapter {
|
||||
// Adapts SpecHandler to IDHandler API for dynamic precision.
|
||||
template <typename SpecHandler, typename Char>
|
||||
struct precision_adapter {
|
||||
explicit constexpr precision_adapter(SpecHandler &h) : handler(h) {}
|
||||
explicit FMT_CONSTEXPR precision_adapter(SpecHandler &h) : handler(h) {}
|
||||
|
||||
constexpr void operator()() { handler.on_dynamic_precision(auto_id()); }
|
||||
constexpr void operator()(unsigned id) { handler.on_dynamic_precision(id); }
|
||||
constexpr void operator()(basic_string_view<Char> id) {
|
||||
FMT_CONSTEXPR void operator()() { handler.on_dynamic_precision(auto_id()); }
|
||||
FMT_CONSTEXPR void operator()(unsigned id) {
|
||||
handler.on_dynamic_precision(id);
|
||||
}
|
||||
FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {
|
||||
handler.on_dynamic_precision(id);
|
||||
}
|
||||
|
||||
constexpr void on_error(const char *message) { handler.on_error(message); }
|
||||
FMT_CONSTEXPR void on_error(const char *message) { handler.on_error(message); }
|
||||
|
||||
SpecHandler &handler;
|
||||
};
|
||||
@ -1809,7 +1817,7 @@ struct precision_adapter {
|
||||
// characters, possibly emulated via null_terminating_iterator, representing
|
||||
// format specifiers.
|
||||
template <typename Iterator, typename SpecHandler>
|
||||
constexpr Iterator parse_format_specs(Iterator it, SpecHandler &&handler) {
|
||||
FMT_CONSTEXPR Iterator parse_format_specs(Iterator it, SpecHandler &&handler) {
|
||||
using char_type = typename std::iterator_traits<Iterator>::value_type;
|
||||
// Parse fill and alignment.
|
||||
if (char_type c = *it) {
|
||||
@ -1912,15 +1920,15 @@ constexpr Iterator parse_format_specs(Iterator it, SpecHandler &&handler) {
|
||||
|
||||
template <typename Handler, typename Char>
|
||||
struct id_adapter {
|
||||
constexpr explicit id_adapter(Handler &h): handler(h) {}
|
||||
FMT_CONSTEXPR explicit id_adapter(Handler &h): handler(h) {}
|
||||
|
||||
constexpr void operator()() { handler.on_arg_id(); }
|
||||
constexpr void operator()(unsigned id) { handler.on_arg_id(id); }
|
||||
constexpr void operator()(basic_string_view<Char> id) {
|
||||
FMT_CONSTEXPR void operator()() { handler.on_arg_id(); }
|
||||
FMT_CONSTEXPR void operator()(unsigned id) { handler.on_arg_id(id); }
|
||||
FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {
|
||||
handler.on_arg_id(id);
|
||||
}
|
||||
|
||||
constexpr void on_error(const char *message) {
|
||||
FMT_CONSTEXPR void on_error(const char *message) {
|
||||
handler.on_error(message);
|
||||
}
|
||||
|
||||
@ -1928,7 +1936,7 @@ struct id_adapter {
|
||||
};
|
||||
|
||||
template <typename Iterator, typename Handler>
|
||||
constexpr void parse_format_string(Iterator it, Handler &&handler) {
|
||||
FMT_CONSTEXPR void parse_format_string(Iterator it, Handler &&handler) {
|
||||
using char_type = typename std::iterator_traits<Iterator>::value_type;
|
||||
auto start = it;
|
||||
while (*it) {
|
||||
@ -1966,7 +1974,7 @@ constexpr void parse_format_string(Iterator it, Handler &&handler) {
|
||||
}
|
||||
|
||||
template <typename T, typename ParseContext>
|
||||
constexpr const typename ParseContext::char_type *
|
||||
FMT_CONSTEXPR const typename ParseContext::char_type *
|
||||
parse_format_specs(ParseContext &ctx) {
|
||||
formatter<T, typename ParseContext::char_type> f;
|
||||
return f.parse(ctx);
|
||||
@ -1975,40 +1983,40 @@ constexpr const typename ParseContext::char_type *
|
||||
template <typename Char, typename ErrorHandler, typename... Args>
|
||||
class format_string_checker {
|
||||
public:
|
||||
explicit constexpr format_string_checker(
|
||||
explicit FMT_CONSTEXPR format_string_checker(
|
||||
basic_string_view<Char> format_str, ErrorHandler eh)
|
||||
: context_(format_str, eh) {}
|
||||
|
||||
constexpr void on_text(const Char *, const Char *) {}
|
||||
FMT_CONSTEXPR void on_text(const Char *, const Char *) {}
|
||||
|
||||
constexpr void on_arg_id() {
|
||||
FMT_CONSTEXPR void on_arg_id() {
|
||||
arg_id_ = context_.next_arg_id();
|
||||
check_arg_id();
|
||||
}
|
||||
constexpr void on_arg_id(unsigned id) {
|
||||
FMT_CONSTEXPR void on_arg_id(unsigned id) {
|
||||
arg_id_ = id;
|
||||
context_.check_arg_id(id);
|
||||
check_arg_id();
|
||||
}
|
||||
constexpr void on_arg_id(basic_string_view<Char>) {}
|
||||
FMT_CONSTEXPR void on_arg_id(basic_string_view<Char>) {}
|
||||
|
||||
constexpr void on_replacement_field(const Char *) {}
|
||||
FMT_CONSTEXPR void on_replacement_field(const Char *) {}
|
||||
|
||||
constexpr const Char *on_format_specs(const Char *s) {
|
||||
FMT_CONSTEXPR const Char *on_format_specs(const Char *s) {
|
||||
context_.advance_to(s);
|
||||
return to_unsigned(arg_id_) < NUM_ARGS ?
|
||||
parse_funcs_[arg_id_](context_) : s;
|
||||
}
|
||||
|
||||
constexpr void on_error(const char *message) {
|
||||
FMT_CONSTEXPR void on_error(const char *message) {
|
||||
context_.on_error(message);
|
||||
}
|
||||
|
||||
private:
|
||||
using parse_context_type = basic_parse_context<Char, ErrorHandler>;
|
||||
constexpr static size_t NUM_ARGS = sizeof...(Args);
|
||||
enum { NUM_ARGS = sizeof...(Args) };
|
||||
|
||||
constexpr void check_arg_id() {
|
||||
FMT_CONSTEXPR void check_arg_id() {
|
||||
if (internal::to_unsigned(arg_id_) >= NUM_ARGS)
|
||||
context_.on_error("argument index out of range");
|
||||
}
|
||||
@ -2024,7 +2032,7 @@ class format_string_checker {
|
||||
};
|
||||
|
||||
template <typename Char, typename ErrorHandler, typename... Args>
|
||||
constexpr bool check_format_string(
|
||||
FMT_CONSTEXPR bool check_format_string(
|
||||
basic_string_view<Char> s, ErrorHandler eh = ErrorHandler()) {
|
||||
format_string_checker<Char, ErrorHandler, Args...> checker(s, eh);
|
||||
parse_format_string(s.begin(), checker);
|
||||
@ -2034,8 +2042,9 @@ constexpr bool check_format_string(
|
||||
// Specifies whether to format T using the standard formatter.
|
||||
// It is not possible to use get_type in formatter specialization directly
|
||||
// because of a bug in MSVC.
|
||||
template <typename T>
|
||||
struct format_type : std::integral_constant<bool, get_type<T>() != CUSTOM> {};
|
||||
template <typename Context, typename T>
|
||||
struct format_type :
|
||||
std::integral_constant<bool, get_type<Context, T>() != CUSTOM> {};
|
||||
|
||||
// Specifies whether to format enums.
|
||||
template <typename T, typename Enable = void>
|
||||
@ -2326,7 +2335,7 @@ class basic_writer {
|
||||
void on_num() {
|
||||
unsigned num_digits = internal::count_digits(abs_value);
|
||||
char_type sep = internal::thousands_sep<char_type>(writer.locale_.get());
|
||||
static constexpr unsigned SEP_SIZE = 1;
|
||||
static FMT_CONSTEXPR unsigned SEP_SIZE = 1;
|
||||
unsigned size = num_digits + SEP_SIZE * ((num_digits - 1) / 3);
|
||||
writer.write_int(size, get_prefix(), spec, [this, size, sep](auto &&it) {
|
||||
basic_string_view<char_type> s(&sep, SEP_SIZE);
|
||||
@ -2809,15 +2818,17 @@ inline void format_decimal(char *&buffer, T value) {
|
||||
// Formatter of objects of type T.
|
||||
template <typename T, typename Char>
|
||||
struct formatter<
|
||||
T, Char, typename std::enable_if<internal::format_type<T>::value>::type> {
|
||||
T, Char,
|
||||
typename std::enable_if<
|
||||
internal::format_type<buffer_context_t<Char>, T>::value>::type> {
|
||||
|
||||
// Parses format specifiers stopping either at the end of the range or at the
|
||||
// terminating '}'.
|
||||
template <typename ParseContext>
|
||||
constexpr typename ParseContext::iterator parse(ParseContext &ctx) {
|
||||
FMT_CONSTEXPR typename ParseContext::iterator parse(ParseContext &ctx) {
|
||||
auto it = internal::null_terminating_iterator<Char>(ctx);
|
||||
using handler_type = internal::dynamic_specs_handler<ParseContext>;
|
||||
auto type = internal::get_type<T>();
|
||||
auto type = internal::get_type<buffer_context_t<Char>, T>();
|
||||
internal::specs_checker<handler_type>
|
||||
handler(handler_type(specs_, ctx), type);
|
||||
it = parse_format_specs(it, handler);
|
||||
@ -2922,7 +2933,7 @@ struct dynamic_formatter {
|
||||
void on_hash() {}
|
||||
};
|
||||
internal::specs_checker<null_handler>
|
||||
checker(null_handler(), internal::get_type<T>());
|
||||
checker(null_handler(), internal::get_type<FormatContext, T>());
|
||||
checker.on_align(specs_.align());
|
||||
if (specs_.flags_ == 0) {
|
||||
// Do nothing.
|
||||
@ -3039,7 +3050,7 @@ inline const void *ptr(const T *p) { return p; }
|
||||
|
||||
class fill_spec_factory {
|
||||
public:
|
||||
constexpr fill_spec_factory() {}
|
||||
FMT_CONSTEXPR fill_spec_factory() {}
|
||||
|
||||
template <typename Char>
|
||||
fill_spec<Char> operator=(Char value) const {
|
||||
@ -3050,16 +3061,16 @@ class fill_spec_factory {
|
||||
template <typename FormatSpec>
|
||||
class format_spec_factory {
|
||||
public:
|
||||
constexpr format_spec_factory() {}
|
||||
FMT_CONSTEXPR format_spec_factory() {}
|
||||
|
||||
FormatSpec operator=(typename FormatSpec::value_type value) const {
|
||||
return FormatSpec(value);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr fill_spec_factory fill;
|
||||
constexpr format_spec_factory<width_spec> width;
|
||||
constexpr format_spec_factory<type_spec> type;
|
||||
FMT_CONSTEXPR fill_spec_factory fill;
|
||||
FMT_CONSTEXPR format_spec_factory<width_spec> width;
|
||||
FMT_CONSTEXPR format_spec_factory<type_spec> type;
|
||||
|
||||
template <typename It, typename Char>
|
||||
struct arg_join {
|
||||
@ -3205,7 +3216,7 @@ template <typename String, typename... Args>
|
||||
inline typename std::enable_if<
|
||||
std::is_base_of<internal::format_string, String>::value, std::string>::type
|
||||
format(String format_str, const Args & ... args) {
|
||||
constexpr bool invalid_format =
|
||||
FMT_CONSTEXPR bool invalid_format =
|
||||
internal::check_format_string<char, internal::error_handler, Args...>(
|
||||
string_view(format_str.value(), format_str.size()));
|
||||
(void)invalid_format;
|
||||
@ -3232,8 +3243,8 @@ class udl_formatter {
|
||||
public:
|
||||
template <typename... Args>
|
||||
std::basic_string<Char> operator()(const Args &... args) const {
|
||||
constexpr Char s[] = {CHARS..., '\0'};
|
||||
constexpr bool invalid_format =
|
||||
FMT_CONSTEXPR Char s[] = {CHARS..., '\0'};
|
||||
FMT_CONSTEXPR bool invalid_format =
|
||||
check_format_string<Char, error_handler, Args...>(
|
||||
basic_string_view<Char>(s, sizeof...(CHARS)));
|
||||
(void)invalid_format;
|
||||
@ -3269,7 +3280,7 @@ inline namespace literals {
|
||||
|
||||
# if FMT_UDL_TEMPLATE
|
||||
template <typename Char, Char... CHARS>
|
||||
constexpr internal::udl_formatter<Char, CHARS...> operator""_format() {
|
||||
FMT_CONSTEXPR internal::udl_formatter<Char, CHARS...> operator""_format() {
|
||||
return {};
|
||||
}
|
||||
# else
|
||||
@ -3309,8 +3320,8 @@ operator"" _a(const wchar_t *s, std::size_t) { return {s}; }
|
||||
|
||||
#define FMT_STRING(s) [] { \
|
||||
struct S : fmt::internal::format_string { \
|
||||
static constexpr auto value() { return s; } \
|
||||
static constexpr size_t size() { return sizeof(s); } \
|
||||
static FMT_CONSTEXPR auto value() { return s; } \
|
||||
static FMT_CONSTEXPR size_t size() { return sizeof(s); } \
|
||||
}; \
|
||||
return S{}; \
|
||||
}()
|
||||
|
@ -103,7 +103,8 @@ struct format_enum<T,
|
||||
// Formats an object of type T that has an overloaded ostream operator<<.
|
||||
template <typename T, typename Char>
|
||||
struct formatter<T, Char,
|
||||
typename std::enable_if<!internal::format_type<T>::value>::type>
|
||||
typename std::enable_if<
|
||||
!internal::format_type<buffer_context_t<Char>, T>::value>::type>
|
||||
: formatter<basic_string_view<Char>, Char> {
|
||||
|
||||
template <typename Context>
|
||||
|
@ -1222,7 +1222,7 @@ namespace fmt {
|
||||
template <>
|
||||
struct formatter<Date> {
|
||||
template <typename ParseContext>
|
||||
constexpr auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
|
||||
auto it = ctx.begin();
|
||||
if (*it == 'd')
|
||||
++it;
|
||||
@ -1604,22 +1604,22 @@ struct test_arg_id_handler {
|
||||
unsigned index = 0;
|
||||
string_view name;
|
||||
|
||||
constexpr void operator()() { res = EMPTY; }
|
||||
FMT_CONSTEXPR void operator()() { res = EMPTY; }
|
||||
|
||||
constexpr void operator()(unsigned index) {
|
||||
FMT_CONSTEXPR void operator()(unsigned index) {
|
||||
res = INDEX;
|
||||
this->index = index;
|
||||
}
|
||||
|
||||
constexpr void operator()(string_view name) {
|
||||
FMT_CONSTEXPR void operator()(string_view name) {
|
||||
res = NAME;
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
constexpr void on_error(const char *) { res = ERROR; }
|
||||
FMT_CONSTEXPR void on_error(const char *) { res = ERROR; }
|
||||
};
|
||||
|
||||
constexpr test_arg_id_handler parse_arg_id(const char* s) {
|
||||
FMT_CONSTEXPR test_arg_id_handler parse_arg_id(const char* s) {
|
||||
test_arg_id_handler h;
|
||||
fmt::internal::parse_arg_id(s, h);
|
||||
return h;
|
||||
@ -1649,39 +1649,39 @@ struct test_format_specs_handler {
|
||||
|
||||
// Workaround for MSVC2017 bug that results in "expression did not evaluate
|
||||
// to a constant" with compiler-generated copy ctor.
|
||||
constexpr test_format_specs_handler() {}
|
||||
constexpr test_format_specs_handler(const test_format_specs_handler &other)
|
||||
FMT_CONSTEXPR test_format_specs_handler() {}
|
||||
FMT_CONSTEXPR test_format_specs_handler(const test_format_specs_handler &other)
|
||||
: res(other.res), align(other.align), fill(other.fill),
|
||||
width(other.width), width_ref(other.width_ref),
|
||||
precision(other.precision), precision_ref(other.precision_ref),
|
||||
type(other.type) {}
|
||||
|
||||
constexpr void on_align(fmt::alignment align) { this->align = align; }
|
||||
constexpr void on_fill(char fill) { this->fill = fill; }
|
||||
constexpr void on_plus() { res = PLUS; }
|
||||
constexpr void on_minus() { res = MINUS; }
|
||||
constexpr void on_space() { res = SPACE; }
|
||||
constexpr void on_hash() { res = HASH; }
|
||||
constexpr void on_zero() { res = ZERO; }
|
||||
FMT_CONSTEXPR void on_align(fmt::alignment align) { this->align = align; }
|
||||
FMT_CONSTEXPR void on_fill(char fill) { this->fill = fill; }
|
||||
FMT_CONSTEXPR void on_plus() { res = PLUS; }
|
||||
FMT_CONSTEXPR void on_minus() { res = MINUS; }
|
||||
FMT_CONSTEXPR void on_space() { res = SPACE; }
|
||||
FMT_CONSTEXPR void on_hash() { res = HASH; }
|
||||
FMT_CONSTEXPR void on_zero() { res = ZERO; }
|
||||
|
||||
constexpr void on_width(unsigned width) { this->width = width; }
|
||||
constexpr void on_dynamic_width(fmt::internal::auto_id) {}
|
||||
constexpr void on_dynamic_width(unsigned index) { width_ref = index; }
|
||||
constexpr void on_dynamic_width(string_view) {}
|
||||
FMT_CONSTEXPR void on_width(unsigned width) { this->width = width; }
|
||||
FMT_CONSTEXPR void on_dynamic_width(fmt::internal::auto_id) {}
|
||||
FMT_CONSTEXPR void on_dynamic_width(unsigned index) { width_ref = index; }
|
||||
FMT_CONSTEXPR void on_dynamic_width(string_view) {}
|
||||
|
||||
constexpr void on_precision(unsigned precision) {
|
||||
FMT_CONSTEXPR void on_precision(unsigned precision) {
|
||||
this->precision = precision;
|
||||
}
|
||||
constexpr void on_dynamic_precision(fmt::internal::auto_id) {}
|
||||
constexpr void on_dynamic_precision(unsigned index) { precision_ref = index; }
|
||||
constexpr void on_dynamic_precision(string_view) {}
|
||||
FMT_CONSTEXPR void on_dynamic_precision(fmt::internal::auto_id) {}
|
||||
FMT_CONSTEXPR void on_dynamic_precision(unsigned index) { precision_ref = index; }
|
||||
FMT_CONSTEXPR void on_dynamic_precision(string_view) {}
|
||||
|
||||
constexpr void end_precision() {}
|
||||
constexpr void on_type(char type) { this->type = type; }
|
||||
constexpr void on_error(const char *) { res = ERROR; }
|
||||
FMT_CONSTEXPR void end_precision() {}
|
||||
FMT_CONSTEXPR void on_type(char type) { this->type = type; }
|
||||
FMT_CONSTEXPR void on_error(const char *) { res = ERROR; }
|
||||
};
|
||||
|
||||
constexpr test_format_specs_handler parse_test_specs(const char *s) {
|
||||
FMT_CONSTEXPR test_format_specs_handler parse_test_specs(const char *s) {
|
||||
test_format_specs_handler h;
|
||||
fmt::internal::parse_format_specs(s, h);
|
||||
return h;
|
||||
@ -1707,27 +1707,27 @@ TEST(FormatTest, ConstexprParseFormatSpecs) {
|
||||
struct test_context {
|
||||
using char_type = char;
|
||||
|
||||
constexpr fmt::basic_arg<test_context> next_arg() {
|
||||
FMT_CONSTEXPR fmt::basic_arg<test_context> next_arg() {
|
||||
return fmt::internal::make_arg<test_context>(11);
|
||||
}
|
||||
|
||||
template <typename Id>
|
||||
constexpr fmt::basic_arg<test_context> get_arg(Id) {
|
||||
FMT_CONSTEXPR fmt::basic_arg<test_context> get_arg(Id) {
|
||||
return fmt::internal::make_arg<test_context>(22);
|
||||
}
|
||||
|
||||
template <typename Id>
|
||||
constexpr void check_arg_id(Id) {}
|
||||
FMT_CONSTEXPR void check_arg_id(Id) {}
|
||||
|
||||
constexpr unsigned next_arg_id() { return 33; }
|
||||
FMT_CONSTEXPR unsigned next_arg_id() { return 33; }
|
||||
|
||||
void on_error(const char *) {}
|
||||
|
||||
constexpr test_context &parse_context() { return *this; }
|
||||
constexpr test_context error_handler() { return *this; }
|
||||
FMT_CONSTEXPR test_context &parse_context() { return *this; }
|
||||
FMT_CONSTEXPR test_context error_handler() { return *this; }
|
||||
};
|
||||
|
||||
constexpr fmt::format_specs parse_specs(const char *s) {
|
||||
FMT_CONSTEXPR fmt::format_specs parse_specs(const char *s) {
|
||||
fmt::format_specs specs;
|
||||
test_context ctx;
|
||||
fmt::internal::specs_handler<test_context> h(specs, ctx);
|
||||
@ -1752,7 +1752,7 @@ TEST(FormatTest, ConstexprSpecsHandler) {
|
||||
static_assert(parse_specs("d").type() == 'd', "");
|
||||
}
|
||||
|
||||
constexpr fmt::internal::dynamic_format_specs<char>
|
||||
FMT_CONSTEXPR fmt::internal::dynamic_format_specs<char>
|
||||
parse_dynamic_specs(const char *s) {
|
||||
fmt::internal::dynamic_format_specs<char> specs;
|
||||
test_context ctx;
|
||||
@ -1778,7 +1778,7 @@ TEST(FormatTest, ConstexprDynamicSpecsHandler) {
|
||||
static_assert(parse_dynamic_specs("d").type() == 'd', "");
|
||||
}
|
||||
|
||||
constexpr test_format_specs_handler check_specs(const char *s) {
|
||||
FMT_CONSTEXPR test_format_specs_handler check_specs(const char *s) {
|
||||
fmt::internal::specs_checker<test_format_specs_handler>
|
||||
checker(test_format_specs_handler(), fmt::internal::DOUBLE);
|
||||
parse_format_specs(s, checker);
|
||||
@ -1803,23 +1803,23 @@ TEST(FormatTest, ConstexprSpecsChecker) {
|
||||
}
|
||||
|
||||
struct test_format_string_handler {
|
||||
constexpr void on_text(const char *, const char *) {}
|
||||
FMT_CONSTEXPR void on_text(const char *, const char *) {}
|
||||
|
||||
constexpr void on_arg_id() {}
|
||||
FMT_CONSTEXPR void on_arg_id() {}
|
||||
|
||||
template <typename T>
|
||||
constexpr void on_arg_id(T) {}
|
||||
FMT_CONSTEXPR void on_arg_id(T) {}
|
||||
|
||||
constexpr void on_replacement_field(const char *) {}
|
||||
FMT_CONSTEXPR void on_replacement_field(const char *) {}
|
||||
|
||||
constexpr const char *on_format_specs(const char *s) { return s; }
|
||||
FMT_CONSTEXPR const char *on_format_specs(const char *s) { return s; }
|
||||
|
||||
constexpr void on_error(const char *) { error = true; }
|
||||
FMT_CONSTEXPR void on_error(const char *) { error = true; }
|
||||
|
||||
bool error = false;
|
||||
};
|
||||
|
||||
constexpr bool parse_string(const char *s) {
|
||||
FMT_CONSTEXPR bool parse_string(const char *s) {
|
||||
test_format_string_handler h;
|
||||
fmt::internal::parse_format_string(s, h);
|
||||
return !h.error;
|
||||
@ -1843,25 +1843,25 @@ TEST(FormatTest, UdlTemplate) {
|
||||
struct test_error_handler {
|
||||
const char *&error;
|
||||
|
||||
constexpr test_error_handler(const char *&err): error(err) {}
|
||||
FMT_CONSTEXPR test_error_handler(const char *&err): error(err) {}
|
||||
|
||||
constexpr test_error_handler(const test_error_handler &other)
|
||||
FMT_CONSTEXPR test_error_handler(const test_error_handler &other)
|
||||
: error(other.error) {}
|
||||
|
||||
constexpr void on_error(const char *message) {
|
||||
FMT_CONSTEXPR void on_error(const char *message) {
|
||||
if (!error)
|
||||
error = message;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr size_t len(const char *s) {
|
||||
FMT_CONSTEXPR size_t len(const char *s) {
|
||||
size_t len = 0;
|
||||
while (*s++)
|
||||
++len;
|
||||
return len;
|
||||
}
|
||||
|
||||
constexpr bool equal(const char *s1, const char *s2) {
|
||||
FMT_CONSTEXPR bool equal(const char *s1, const char *s2) {
|
||||
if (!s1 || !s2)
|
||||
return s1 == s2;
|
||||
while (*s1 && *s1 == *s2) {
|
||||
@ -1872,7 +1872,7 @@ constexpr bool equal(const char *s1, const char *s2) {
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
constexpr bool test_error(const char *fmt, const char *expected_error) {
|
||||
FMT_CONSTEXPR bool test_error(const char *fmt, const char *expected_error) {
|
||||
const char *actual_error = nullptr;
|
||||
fmt::internal::check_format_string<char, test_error_handler, Args...>(
|
||||
string_view(fmt, len(fmt)), test_error_handler(actual_error));
|
||||
|
@ -459,7 +459,8 @@ struct custom_context {
|
||||
|
||||
TEST(UtilTest, MakeValueWithCustomFormatter) {
|
||||
::Test t;
|
||||
fmt::internal::value<custom_context> arg(t);
|
||||
fmt::internal::value<custom_context> arg =
|
||||
fmt::internal::make_value<custom_context>(t);
|
||||
custom_context ctx = {false};
|
||||
arg.custom.format(&t, ctx);
|
||||
EXPECT_TRUE(ctx.called);
|
||||
|
Loading…
Reference in New Issue
Block a user