Support named arguments (done)
This commit is contained in:
parent
344de54aa9
commit
f2c4b65549
@ -72,6 +72,10 @@ Write API
|
|||||||
Utilities
|
Utilities
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
.. doxygenfunction:: fmt::arg(StringRef, const T&)
|
||||||
|
|
||||||
|
.. doxygendefine:: FMT_CAPTURE
|
||||||
|
|
||||||
.. doxygendefine:: FMT_VARIADIC
|
.. doxygendefine:: FMT_VARIADIC
|
||||||
|
|
||||||
.. doxygenclass:: fmt::ArgList
|
.. doxygenclass:: fmt::ArgList
|
||||||
|
|||||||
89
format.cc
89
format.cc
@ -268,7 +268,7 @@ int parse_nonnegative_int(const Char *&s) {
|
|||||||
template <typename Char>
|
template <typename Char>
|
||||||
inline bool is_name_start(Char c)
|
inline bool is_name_start(Char c)
|
||||||
{
|
{
|
||||||
return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '_' == c;
|
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void require_numeric_argument(const Arg &arg, char spec) {
|
inline void require_numeric_argument(const Arg &arg, char spec) {
|
||||||
@ -408,10 +408,10 @@ inline Arg::StringValue<wchar_t> ignore_incompatible_str(
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
FMT_FUNC void fmt::SystemError::init(
|
FMT_FUNC void fmt::SystemError::init(
|
||||||
int err_code, StringRef format_str, ArgList args, const ArgMap &map) {
|
int err_code, StringRef format_str, ArgList args) {
|
||||||
error_code_ = err_code;
|
error_code_ = err_code;
|
||||||
MemoryWriter w;
|
MemoryWriter w;
|
||||||
internal::format_system_error(w, err_code, format(format_str, args, map));
|
internal::format_system_error(w, err_code, format(format_str, args));
|
||||||
std::runtime_error &base = *this;
|
std::runtime_error &base = *this;
|
||||||
base = std::runtime_error(w.str());
|
base = std::runtime_error(w.str());
|
||||||
}
|
}
|
||||||
@ -524,10 +524,10 @@ FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FMT_FUNC void fmt::WindowsError::init(
|
FMT_FUNC void fmt::WindowsError::init(
|
||||||
int err_code, StringRef format_str, ArgList args, const ArgMap &map) {
|
int err_code, StringRef format_str, ArgList args) {
|
||||||
error_code_ = err_code;
|
error_code_ = err_code;
|
||||||
MemoryWriter w;
|
MemoryWriter w;
|
||||||
internal::format_windows_error(w, err_code, format(format_str, args, map));
|
internal::format_windows_error(w, err_code, format(format_str, args));
|
||||||
std::runtime_error &base = *this;
|
std::runtime_error &base = *this;
|
||||||
base = std::runtime_error(w.str());
|
base = std::runtime_error(w.str());
|
||||||
}
|
}
|
||||||
@ -700,21 +700,18 @@ inline Arg fmt::BasicFormatter<Char>::parse_arg_index(const Char *&s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
inline Arg fmt::BasicFormatter<Char>::parse_arg_name(const Char *&s, const fmt::BasicArgMap<Char> &map) {
|
inline Arg fmt::BasicFormatter<Char>::parse_arg_name(const Char *&s) {
|
||||||
assert(is_name_start(*s));
|
assert(is_name_start(*s));
|
||||||
const Char *start = s;
|
const Char *start = s;
|
||||||
Char c;
|
Char c;
|
||||||
do {
|
do {
|
||||||
c = *++s;
|
c = *++s;
|
||||||
} while ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9');
|
} while (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9'));
|
||||||
const int* index = map.find(fmt::BasicStringRef<Char>(start, s - start));
|
const char *error = 0;
|
||||||
if (!index)
|
Arg arg = get_arg(fmt::BasicStringRef<Char>(start, s - start), error);
|
||||||
FMT_THROW(fmt::FormatError("argument not found"));
|
if (error)
|
||||||
const char *error = 0;
|
FMT_THROW(fmt::FormatError(error));
|
||||||
Arg arg = get_arg(*index, error);
|
return arg;
|
||||||
if (error)
|
|
||||||
FMT_THROW(fmt::FormatError(error));
|
|
||||||
return arg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
|
FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
|
||||||
@ -742,6 +739,18 @@ inline Arg fmt::internal::FormatterBase::get_arg(
|
|||||||
return Arg();
|
return Arg();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Char>
|
||||||
|
inline Arg fmt::internal::FormatterBase::get_arg(
|
||||||
|
const BasicStringRef<Char>& arg_name, const char *&error) {
|
||||||
|
const BasicArgMap<Char>* map = args_.get_arg_map<Char>();
|
||||||
|
assert(map);
|
||||||
|
const unsigned* index = map->find(arg_name);
|
||||||
|
if (index)
|
||||||
|
return get_arg(*index, error);
|
||||||
|
error = "argument not found";
|
||||||
|
return Arg();
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
void fmt::internal::PrintfFormatter<Char>::parse_flags(
|
void fmt::internal::PrintfFormatter<Char>::parse_flags(
|
||||||
FormatSpec &spec, const Char *&s) {
|
FormatSpec &spec, const Char *&s) {
|
||||||
@ -984,7 +993,7 @@ void fmt::internal::PrintfFormatter<Char>::format(
|
|||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
const Char *fmt::BasicFormatter<Char>::format(
|
const Char *fmt::BasicFormatter<Char>::format(
|
||||||
const Char *&format_str, const Arg &arg, const BasicArgMap<Char> &map) {
|
const Char *&format_str, const Arg &arg) {
|
||||||
const Char *s = format_str;
|
const Char *s = format_str;
|
||||||
FormatSpec spec;
|
FormatSpec spec;
|
||||||
if (*s == ':') {
|
if (*s == ':') {
|
||||||
@ -1062,7 +1071,7 @@ const Char *fmt::BasicFormatter<Char>::format(
|
|||||||
spec.width_ = parse_nonnegative_int(s);
|
spec.width_ = parse_nonnegative_int(s);
|
||||||
} else if (*s == '{') {
|
} else if (*s == '{') {
|
||||||
++s;
|
++s;
|
||||||
const Arg &width_arg = is_name_start(*s) ? parse_arg_name(s, map) : parse_arg_index(s);
|
const Arg &width_arg = is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
|
||||||
if (*s++ != '}')
|
if (*s++ != '}')
|
||||||
FMT_THROW(FormatError("invalid format string"));
|
FMT_THROW(FormatError("invalid format string"));
|
||||||
ULongLong value = 0;
|
ULongLong value = 0;
|
||||||
@ -1099,7 +1108,7 @@ const Char *fmt::BasicFormatter<Char>::format(
|
|||||||
spec.precision_ = parse_nonnegative_int(s);
|
spec.precision_ = parse_nonnegative_int(s);
|
||||||
} else if (*s == '{') {
|
} else if (*s == '{') {
|
||||||
++s;
|
++s;
|
||||||
const Arg &precision_arg = is_name_start(*s) ? parse_arg_name(s, map) : parse_arg_index(s);
|
const Arg &precision_arg = is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
|
||||||
if (*s++ != '}')
|
if (*s++ != '}')
|
||||||
FMT_THROW(FormatError("invalid format string"));
|
FMT_THROW(FormatError("invalid format string"));
|
||||||
ULongLong value = 0;
|
ULongLong value = 0;
|
||||||
@ -1152,7 +1161,7 @@ const Char *fmt::BasicFormatter<Char>::format(
|
|||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
void fmt::BasicFormatter<Char>::format(
|
void fmt::BasicFormatter<Char>::format(
|
||||||
BasicStringRef<Char> format_str, const ArgList &args, const BasicArgMap<Char> &map) {
|
BasicStringRef<Char> format_str, const ArgList &args) {
|
||||||
const Char *s = start_ = format_str.c_str();
|
const Char *s = start_ = format_str.c_str();
|
||||||
set_args(args);
|
set_args(args);
|
||||||
while (*s) {
|
while (*s) {
|
||||||
@ -1166,8 +1175,8 @@ void fmt::BasicFormatter<Char>::format(
|
|||||||
if (c == '}')
|
if (c == '}')
|
||||||
FMT_THROW(FormatError("unmatched '}' in format string"));
|
FMT_THROW(FormatError("unmatched '}' in format string"));
|
||||||
write(writer_, start_, s - 1);
|
write(writer_, start_, s - 1);
|
||||||
Arg arg = is_name_start(*s) ? parse_arg_name(s, map) : parse_arg_index(s);
|
Arg arg = is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
|
||||||
s = format(s, arg, map);
|
s = format(s, arg);
|
||||||
}
|
}
|
||||||
write(writer_, start_, s);
|
write(writer_, start_, s);
|
||||||
}
|
}
|
||||||
@ -1184,33 +1193,33 @@ FMT_FUNC void fmt::report_windows_error(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FMT_FUNC void fmt::print(std::FILE *f, StringRef format_str, ArgList args, const ArgMap &map) {
|
FMT_FUNC void fmt::print(std::FILE *f, StringRef format_str, ArgList args) {
|
||||||
MemoryWriter w;
|
MemoryWriter w;
|
||||||
w.write(format_str, args, map);
|
w.write(format_str, args);
|
||||||
std::fwrite(w.data(), 1, w.size(), f);
|
std::fwrite(w.data(), 1, w.size(), f);
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_FUNC void fmt::print(StringRef format_str, ArgList args, const ArgMap &map) {
|
FMT_FUNC void fmt::print(StringRef format_str, ArgList args) {
|
||||||
print(stdout, format_str, args, map);
|
print(stdout, format_str, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_FUNC void fmt::print(std::ostream &os, StringRef format_str, ArgList args, const ArgMap &map) {
|
FMT_FUNC void fmt::print(std::ostream &os, StringRef format_str, ArgList args) {
|
||||||
MemoryWriter w;
|
MemoryWriter w;
|
||||||
w.write(format_str, args, map);
|
w.write(format_str, args);
|
||||||
os.write(w.data(), w.size());
|
os.write(w.data(), w.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_FUNC void fmt::print_colored(Color c, StringRef format, ArgList args, const ArgMap &map) {
|
FMT_FUNC void fmt::print_colored(Color c, StringRef format, ArgList args) {
|
||||||
char escape[] = "\x1b[30m";
|
char escape[] = "\x1b[30m";
|
||||||
escape[3] = '0' + static_cast<char>(c);
|
escape[3] = '0' + static_cast<char>(c);
|
||||||
std::fputs(escape, stdout);
|
std::fputs(escape, stdout);
|
||||||
print(format, args, map);
|
print(format, args);
|
||||||
std::fputs(RESET_COLOR, stdout);
|
std::fputs(RESET_COLOR, stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_FUNC int fmt::fprintf(std::FILE *f, StringRef format, ArgList args, const ArgMap &map) {
|
FMT_FUNC int fmt::fprintf(std::FILE *f, StringRef format, ArgList args) {
|
||||||
MemoryWriter w;
|
MemoryWriter w;
|
||||||
printf(w, format, args, map);
|
printf(w, format, args);
|
||||||
std::size_t size = w.size();
|
std::size_t size = w.size();
|
||||||
return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
|
return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
|
||||||
}
|
}
|
||||||
@ -1224,10 +1233,10 @@ template struct fmt::internal::BasicData<void>;
|
|||||||
template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
|
template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
|
||||||
|
|
||||||
template const char *fmt::BasicFormatter<char>::format(
|
template const char *fmt::BasicFormatter<char>::format(
|
||||||
const char *&format_str, const fmt::internal::Arg &arg, const BasicArgMap<char> &map);
|
const char *&format_str, const fmt::internal::Arg &arg);
|
||||||
|
|
||||||
template void fmt::BasicFormatter<char>::format(
|
template void fmt::BasicFormatter<char>::format(
|
||||||
BasicStringRef<char> format, const ArgList &args, const BasicArgMap<char> &map);
|
BasicStringRef<char> format, const ArgList &args);
|
||||||
|
|
||||||
template void fmt::internal::PrintfFormatter<char>::format(
|
template void fmt::internal::PrintfFormatter<char>::format(
|
||||||
BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
|
BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
|
||||||
@ -1245,10 +1254,10 @@ template int fmt::internal::CharTraits<char>::format_float(
|
|||||||
template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
|
template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
|
||||||
|
|
||||||
template const wchar_t *fmt::BasicFormatter<wchar_t>::format(
|
template const wchar_t *fmt::BasicFormatter<wchar_t>::format(
|
||||||
const wchar_t *&format_str, const fmt::internal::Arg &arg, const BasicArgMap<wchar_t> &map);
|
const wchar_t *&format_str, const fmt::internal::Arg &arg);
|
||||||
|
|
||||||
template void fmt::BasicFormatter<wchar_t>::format(
|
template void fmt::BasicFormatter<wchar_t>::format(
|
||||||
BasicStringRef<wchar_t> format, const ArgList &args, const BasicArgMap<wchar_t> &map);
|
BasicStringRef<wchar_t> format, const ArgList &args);
|
||||||
|
|
||||||
template void fmt::internal::PrintfFormatter<wchar_t>::format(
|
template void fmt::internal::PrintfFormatter<wchar_t>::format(
|
||||||
BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
|
BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
|
||||||
|
|||||||
318
format.h
318
format.h
@ -768,12 +768,11 @@ struct Value {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Char, typename T>
|
template <typename Char, typename T>
|
||||||
struct NamedArg
|
struct NamedArg {
|
||||||
{
|
BasicStringRef<Char> name;
|
||||||
BasicStringRef<Char> name;
|
T const& arg;
|
||||||
T const& arg;
|
|
||||||
|
|
||||||
NamedArg(BasicStringRef<Char> name, T const& arg) : name(name), arg(arg) {}
|
NamedArg(BasicStringRef<Char> name, T const& arg) : name(name), arg(arg) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// A formatting argument. It is a POD type to allow storage in
|
// A formatting argument. It is a POD type to allow storage in
|
||||||
@ -980,47 +979,13 @@ class MakeValue : public Arg {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline const T &strip_name(const T &arg)
|
inline const T &strip_name(const T &arg) {
|
||||||
{
|
return arg;
|
||||||
return arg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char, typename T>
|
template <typename Char, typename T>
|
||||||
inline const T &strip_name(const NamedArg<Char, T> &namedArg)
|
inline const T &strip_name(const NamedArg<Char, T> &namedArg) {
|
||||||
{
|
return namedArg.arg;
|
||||||
return namedArg.arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... T>
|
|
||||||
struct NamedArgsCounter
|
|
||||||
{
|
|
||||||
static const int value = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename... U>
|
|
||||||
struct NamedArgsCounter<T, U...> : NamedArgsCounter<U...>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <typename Char, typename T, typename... U>
|
|
||||||
struct NamedArgsCounter<NamedArg<Char, T>, U...>
|
|
||||||
{
|
|
||||||
static const int value = 1 + NamedArgsCounter<U...>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <int N, typename NameIndexPair>
|
|
||||||
inline void add_named_args(NameIndexPair*) {}
|
|
||||||
|
|
||||||
template <int N, typename NameIndexPair, typename T, typename... U>
|
|
||||||
inline void add_named_args(NameIndexPair* map, T const&, U const&... rest)
|
|
||||||
{
|
|
||||||
add_named_args<N + 1>(map, rest...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int N, typename NameIndexPair, typename Char, typename T, typename... U>
|
|
||||||
inline void add_named_args(NameIndexPair* map, const NamedArg<Char, T> &namedArg, U const&... rest)
|
|
||||||
{
|
|
||||||
*map = NameIndexPair(namedArg.name, N);
|
|
||||||
add_named_args<N + 1>(map + 1, rest...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FMT_DISPATCH(call) static_cast<Impl*>(this)->call
|
#define FMT_DISPATCH(call) static_cast<Impl*>(this)->call
|
||||||
@ -1142,6 +1107,45 @@ class RuntimeError : public std::runtime_error {
|
|||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
class ArgFormatter;
|
class ArgFormatter;
|
||||||
|
|
||||||
|
template <typename Char>
|
||||||
|
struct BasicArgMap {
|
||||||
|
typedef std::pair<BasicStringRef<Char>, unsigned> value_type;
|
||||||
|
|
||||||
|
struct Compare {
|
||||||
|
bool operator()(const value_type &lhs, const value_type &rhs) const {
|
||||||
|
return lhs.first < rhs.first;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BasicArgMap() : map_(), size_() {}
|
||||||
|
|
||||||
|
BasicArgMap(value_type* map, unsigned size)
|
||||||
|
: map_(map), size_(size) {
|
||||||
|
std::sort(map, map + size, Compare());
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned* find(BasicStringRef<Char> name) const {
|
||||||
|
value_type* first = map_;
|
||||||
|
value_type* last = map_ + size_;
|
||||||
|
while (first != last)
|
||||||
|
{
|
||||||
|
value_type* it(first + ((last - first) >> 1));
|
||||||
|
if (name < it->first)
|
||||||
|
last = it;
|
||||||
|
else if (it->first < name)
|
||||||
|
first = ++it;
|
||||||
|
else
|
||||||
|
return &it->second;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
value_type* map_;
|
||||||
|
unsigned size_;
|
||||||
|
};
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
/** An argument list. */
|
/** An argument list. */
|
||||||
@ -1159,6 +1163,7 @@ class ArgList {
|
|||||||
const internal::Value *values_;
|
const internal::Value *values_;
|
||||||
const internal::Arg *args_;
|
const internal::Arg *args_;
|
||||||
};
|
};
|
||||||
|
const void* map_;
|
||||||
|
|
||||||
internal::Arg::Type type(unsigned index) const {
|
internal::Arg::Type type(unsigned index) const {
|
||||||
unsigned shift = index * 4;
|
unsigned shift = index * 4;
|
||||||
@ -1171,12 +1176,15 @@ class ArgList {
|
|||||||
// Maximum number of arguments with packed types.
|
// Maximum number of arguments with packed types.
|
||||||
enum { MAX_PACKED_ARGS = 16 };
|
enum { MAX_PACKED_ARGS = 16 };
|
||||||
|
|
||||||
ArgList() : types_(0) {}
|
ArgList() : types_(0), map_() {}
|
||||||
|
|
||||||
ArgList(ULongLong types, const internal::Value *values)
|
template <typename Char>
|
||||||
: types_(types), values_(values) {}
|
ArgList(ULongLong types, const internal::Value *values, const internal::BasicArgMap<Char>* map)
|
||||||
ArgList(ULongLong types, const internal::Arg *args)
|
: types_(types), values_(values), map_(map) {}
|
||||||
: types_(types), args_(args) {}
|
|
||||||
|
template <typename Char>
|
||||||
|
ArgList(ULongLong types, const internal::Arg *args, const internal::BasicArgMap<Char>* map)
|
||||||
|
: types_(types), args_(args), map_(map) {}
|
||||||
|
|
||||||
/** Returns the argument at specified index. */
|
/** Returns the argument at specified index. */
|
||||||
internal::Arg operator[](unsigned index) const {
|
internal::Arg operator[](unsigned index) const {
|
||||||
@ -1203,52 +1211,15 @@ class ArgList {
|
|||||||
}
|
}
|
||||||
return args_[index];
|
return args_[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Char>
|
||||||
|
const internal::BasicArgMap<Char>* get_arg_map() const {
|
||||||
|
return static_cast<const internal::BasicArgMap<Char>*>(map_);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FormatSpec;
|
struct FormatSpec;
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
struct BasicArgMap
|
|
||||||
{
|
|
||||||
typedef std::pair<BasicStringRef<Char>, int> value_type;
|
|
||||||
|
|
||||||
BasicArgMap() : map_(), size_() {}
|
|
||||||
|
|
||||||
BasicArgMap(value_type* map, int size)
|
|
||||||
: map_(map), size_(size)
|
|
||||||
{
|
|
||||||
std::sort(map, map + size, [](const value_type &lhs, const value_type &rhs)
|
|
||||||
{
|
|
||||||
return lhs.first < rhs.first;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const int* find(BasicStringRef<Char> name) const
|
|
||||||
{
|
|
||||||
value_type* first = map_;
|
|
||||||
value_type* last = map_ + size_;
|
|
||||||
while (first != last)
|
|
||||||
{
|
|
||||||
value_type* it(first + (last - first >> 1));
|
|
||||||
if (name < it->first)
|
|
||||||
last = it;
|
|
||||||
else if (it->first < name)
|
|
||||||
first = ++it;
|
|
||||||
else
|
|
||||||
return &it->second;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
value_type* map_;
|
|
||||||
int size_;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef BasicArgMap<char> ArgMap;
|
|
||||||
typedef BasicArgMap<wchar_t> WArgMap;
|
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
class FormatterBase {
|
class FormatterBase {
|
||||||
@ -1272,6 +1243,11 @@ class FormatterBase {
|
|||||||
// specified index.
|
// specified index.
|
||||||
Arg get_arg(unsigned arg_index, const char *&error);
|
Arg get_arg(unsigned arg_index, const char *&error);
|
||||||
|
|
||||||
|
// Checks if manual indexing is used and returns the argument with
|
||||||
|
// specified name.
|
||||||
|
template <typename Char>
|
||||||
|
Arg get_arg(const BasicStringRef<Char>& arg_name, const char *&error);
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
|
void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
|
||||||
if (start != end)
|
if (start != end)
|
||||||
@ -1312,16 +1288,16 @@ class BasicFormatter : private internal::FormatterBase {
|
|||||||
internal::Arg parse_arg_index(const Char *&s);
|
internal::Arg parse_arg_index(const Char *&s);
|
||||||
|
|
||||||
// Parses argument name and returns corresponding argument.
|
// Parses argument name and returns corresponding argument.
|
||||||
internal::Arg parse_arg_name(const Char *&s, const BasicArgMap<Char> &map);
|
internal::Arg parse_arg_name(const Char *&s);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit BasicFormatter(BasicWriter<Char> &w) : writer_(w) {}
|
explicit BasicFormatter(BasicWriter<Char> &w) : writer_(w) {}
|
||||||
|
|
||||||
BasicWriter<Char> &writer() { return writer_; }
|
BasicWriter<Char> &writer() { return writer_; }
|
||||||
|
|
||||||
void format(BasicStringRef<Char> format_str, const ArgList &args, const BasicArgMap<Char> &map);
|
void format(BasicStringRef<Char> format_str, const ArgList &args);
|
||||||
|
|
||||||
const Char *format(const Char *&format_str, const internal::Arg &arg, const BasicArgMap<Char> &map);
|
const Char *format(const Char *&format_str, const internal::Arg &arg);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Alignment {
|
enum Alignment {
|
||||||
@ -1582,6 +1558,14 @@ struct ArgArray {
|
|||||||
(N < ArgList::MAX_PACKED_ARGS), Value, Arg>::type Type[SIZE];
|
(N < ArgList::MAX_PACKED_ARGS), Value, Arg>::type Type[SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename NameIndexPair, typename T>
|
||||||
|
inline void add_named_arg(NameIndexPair* map, T const&, unsigned) {}
|
||||||
|
|
||||||
|
template <typename NameIndexPair, typename Char, typename T>
|
||||||
|
inline void add_named_arg(NameIndexPair*& map, const NamedArg<Char, T> &namedArg, unsigned n) {
|
||||||
|
*map++ = NameIndexPair(namedArg.name, n);
|
||||||
|
}
|
||||||
|
|
||||||
#if FMT_USE_VARIADIC_TEMPLATES
|
#if FMT_USE_VARIADIC_TEMPLATES
|
||||||
template <typename Arg, typename... Args>
|
template <typename Arg, typename... Args>
|
||||||
inline uint64_t make_type(const Arg &first, const Args & ... tail) {
|
inline uint64_t make_type(const Arg &first, const Args & ... tail) {
|
||||||
@ -1622,12 +1606,36 @@ inline void store_args(Arg *args, const T &arg, const Args & ... tail) {
|
|||||||
|
|
||||||
template <typename Char, typename... Args>
|
template <typename Char, typename... Args>
|
||||||
ArgList make_arg_list(typename ArgArray<sizeof...(Args)>::Type array,
|
ArgList make_arg_list(typename ArgArray<sizeof...(Args)>::Type array,
|
||||||
|
const BasicArgMap<Char>* map,
|
||||||
const Args & ... args) {
|
const Args & ... args) {
|
||||||
if (check(sizeof...(Args) >= ArgList::MAX_PACKED_ARGS))
|
if (check(sizeof...(Args) >= ArgList::MAX_PACKED_ARGS))
|
||||||
set_types(array, args...);
|
set_types(array, args...);
|
||||||
store_args<Char>(array, args...);
|
store_args<Char>(array, args...);
|
||||||
return ArgList(make_type(args...), array);
|
return ArgList(make_type(args...), array, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
struct NamedArgsCounter {
|
||||||
|
static const int value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename... U>
|
||||||
|
struct NamedArgsCounter<T, U...> : NamedArgsCounter<U...> {};
|
||||||
|
|
||||||
|
template <typename Char, typename T, typename... U>
|
||||||
|
struct NamedArgsCounter<NamedArg<Char, T>, U...> {
|
||||||
|
static const int value = 1 + NamedArgsCounter<U...>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <unsigned N, typename NameIndexPair>
|
||||||
|
inline void add_named_args(NameIndexPair*) {}
|
||||||
|
|
||||||
|
template <unsigned N, typename NameIndexPair, typename T, typename... U>
|
||||||
|
inline void add_named_args(NameIndexPair* map, const T &arg, const U &... rest) {
|
||||||
|
add_named_arg(map, arg, N);
|
||||||
|
add_named_args<N + 1>(map, rest...);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
struct ArgType {
|
struct ArgType {
|
||||||
@ -1653,8 +1661,6 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
|
|||||||
# define FMT_MAKE_TEMPLATE_ARG(n) typename T##n
|
# define FMT_MAKE_TEMPLATE_ARG(n) typename T##n
|
||||||
# define FMT_MAKE_ARG_TYPE(n) T##n
|
# define FMT_MAKE_ARG_TYPE(n) T##n
|
||||||
# define FMT_MAKE_ARG(n) const T##n &v##n
|
# define FMT_MAKE_ARG(n) const T##n &v##n
|
||||||
# define FMT_MAKE_REF_char(n) fmt::internal::MakeValue<char>(v##n)
|
|
||||||
# define FMT_MAKE_REF_wchar_t(n) fmt::internal::MakeValue<wchar_t>(v##n)
|
|
||||||
|
|
||||||
#if FMT_USE_VARIADIC_TEMPLATES
|
#if FMT_USE_VARIADIC_TEMPLATES
|
||||||
// Defines a variadic function returning void.
|
// Defines a variadic function returning void.
|
||||||
@ -1663,10 +1669,10 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
|
|||||||
void func(arg_type arg0, const Args & ... args) { \
|
void func(arg_type arg0, const Args & ... args) { \
|
||||||
typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
|
typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
|
||||||
const int count = fmt::internal::NamedArgsCounter<Args...>::value; \
|
const int count = fmt::internal::NamedArgsCounter<Args...>::value; \
|
||||||
fmt::BasicArgMap<Char>::value_type mapArray[count + 1]; \
|
typename fmt::internal::BasicArgMap<Char>::value_type mapArray[count + 1]; \
|
||||||
fmt::internal::add_named_args<0>(mapArray, args...); \
|
fmt::internal::add_named_args<0>(mapArray, args...); \
|
||||||
fmt::BasicArgMap<Char> map(mapArray, count); \
|
fmt::internal::BasicArgMap<Char> map(mapArray, count); \
|
||||||
func(arg0, fmt::internal::make_arg_list<Char>(array, fmt::internal::strip_name(args)...), map); \
|
func(arg0, fmt::internal::make_arg_list<Char>(array, &map, fmt::internal::strip_name(args)...)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defines a variadic constructor.
|
// Defines a variadic constructor.
|
||||||
@ -1675,25 +1681,31 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
|
|||||||
ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \
|
ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \
|
||||||
typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
|
typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
|
||||||
const int count = fmt::internal::NamedArgsCounter<Args...>::value; \
|
const int count = fmt::internal::NamedArgsCounter<Args...>::value; \
|
||||||
fmt::BasicArgMap<Char>::value_type mapArray[count + 1]; \
|
typename fmt::internal::BasicArgMap<Char>::value_type mapArray[count + 1]; \
|
||||||
fmt::internal::add_named_args<0>(mapArray, args...); \
|
fmt::internal::add_named_args<0>(mapArray, args...); \
|
||||||
fmt::BasicArgMap<Char> map(mapArray, count); \
|
fmt::internal::BasicArgMap<Char> map(mapArray, count); \
|
||||||
func(arg0, arg1, fmt::internal::make_arg_list<Char>(array, fmt::internal::strip_name(args)...), map); \
|
func(arg0, arg1, fmt::internal::make_arg_list<Char>(array, &map, fmt::internal::strip_name(args)...)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
# define FMT_MAKE_REF(n) fmt::internal::MakeValue<Char>(v##n)
|
# define FMT_MAKE_REF(n) fmt::internal::MakeValue<Char>(fmt::internal::strip_name(v##n))
|
||||||
# define FMT_MAKE_REF2(n) v##n
|
# define FMT_MAKE_REF2(n) fmt::internal::strip_name(v##n)
|
||||||
|
# define FMT_ADD_NAMED_ARG(n) fmt::internal::add_named_arg(mapPtr, v##n, n)
|
||||||
|
|
||||||
// Defines a wrapper for a function taking one argument of type arg_type
|
// Defines a wrapper for a function taking one argument of type arg_type
|
||||||
// and n additional arguments of arbitrary types.
|
// and n additional arguments of arbitrary types.
|
||||||
# define FMT_WRAP1(func, arg_type, n) \
|
# define FMT_WRAP1(func, arg_type, n) \
|
||||||
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
|
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
|
||||||
inline void func(arg_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
|
inline void func(arg_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
|
||||||
|
typedef typename fmt::internal::BasicArgMap<Char>::value_type ArgMapValue; \
|
||||||
const fmt::internal::ArgArray<n>::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \
|
const fmt::internal::ArgArray<n>::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \
|
||||||
|
ArgMapValue mapArray[n]; \
|
||||||
|
ArgMapValue* mapPtr = mapArray; \
|
||||||
|
FMT_GEN(n, FMT_ADD_NAMED_ARG); \
|
||||||
|
fmt::internal::BasicArgMap<Char> map(mapArray, unsigned(mapPtr - mapArray)); \
|
||||||
func(arg1, fmt::ArgList( \
|
func(arg1, fmt::ArgList( \
|
||||||
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array)); \
|
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array, &map)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emulates a variadic function returning void on a pre-C++11 compiler.
|
// Emulates a variadic function returning void on a pre-C++11 compiler.
|
||||||
@ -1708,9 +1720,14 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
|
|||||||
# define FMT_CTOR(ctor, func, arg0_type, arg1_type, n) \
|
# define FMT_CTOR(ctor, func, arg0_type, arg1_type, n) \
|
||||||
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
|
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
|
||||||
ctor(arg0_type arg0, arg1_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
|
ctor(arg0_type arg0, arg1_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
|
||||||
|
typedef typename fmt::internal::BasicArgMap<Char>::value_type ArgMapValue; \
|
||||||
const fmt::internal::ArgArray<n>::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \
|
const fmt::internal::ArgArray<n>::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \
|
||||||
|
ArgMapValue mapArray[n]; \
|
||||||
|
ArgMapValue* mapPtr = mapArray; \
|
||||||
|
FMT_GEN(n, FMT_ADD_NAMED_ARG); \
|
||||||
|
fmt::internal::BasicArgMap<Char> map(mapArray, unsigned(mapPtr - mapArray)); \
|
||||||
func(arg0, arg1, fmt::ArgList( \
|
func(arg0, arg1, fmt::ArgList( \
|
||||||
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array)); \
|
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array, &map)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emulates a variadic constructor on a pre-C++11 compiler.
|
// Emulates a variadic constructor on a pre-C++11 compiler.
|
||||||
@ -1755,7 +1772,7 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
|
|||||||
*/
|
*/
|
||||||
class SystemError : public internal::RuntimeError {
|
class SystemError : public internal::RuntimeError {
|
||||||
private:
|
private:
|
||||||
void init(int err_code, StringRef format_str, ArgList args, const ArgMap &map);
|
void init(int err_code, StringRef format_str, ArgList args);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int error_code_;
|
int error_code_;
|
||||||
@ -1791,7 +1808,7 @@ class SystemError : public internal::RuntimeError {
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
SystemError(int error_code, StringRef message) {
|
SystemError(int error_code, StringRef message) {
|
||||||
init(error_code, message, ArgList(), ArgMap());
|
init(error_code, message, ArgList());
|
||||||
}
|
}
|
||||||
FMT_VARIADIC_CTOR(SystemError, init, int, StringRef)
|
FMT_VARIADIC_CTOR(SystemError, init, int, StringRef)
|
||||||
|
|
||||||
@ -1966,8 +1983,8 @@ class BasicWriter {
|
|||||||
See also :ref:`syntax`.
|
See also :ref:`syntax`.
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
void write(BasicStringRef<Char> format, ArgList args, const BasicArgMap<Char> &map) {
|
void write(BasicStringRef<Char> format, ArgList args) {
|
||||||
BasicFormatter<Char>(*this).format(format, args, map);
|
BasicFormatter<Char>(*this).format(format, args);
|
||||||
}
|
}
|
||||||
FMT_VARIADIC_VOID(write, BasicStringRef<Char>)
|
FMT_VARIADIC_VOID(write, BasicStringRef<Char>)
|
||||||
|
|
||||||
@ -2515,7 +2532,7 @@ void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value) {
|
|||||||
internal::Arg arg = internal::MakeValue<Char>(str);
|
internal::Arg arg = internal::MakeValue<Char>(str);
|
||||||
arg.type = static_cast<internal::Arg::Type>(
|
arg.type = static_cast<internal::Arg::Type>(
|
||||||
internal::MakeValue<Char>::type(str));
|
internal::MakeValue<Char>::type(str));
|
||||||
format_str = f.format(format_str, arg, BasicArgMap<Char>());
|
format_str = f.format(format_str, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reports a system error without throwing an exception.
|
// Reports a system error without throwing an exception.
|
||||||
@ -2527,7 +2544,7 @@ void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT;
|
|||||||
/** A Windows error. */
|
/** A Windows error. */
|
||||||
class WindowsError : public SystemError {
|
class WindowsError : public SystemError {
|
||||||
private:
|
private:
|
||||||
void init(int error_code, StringRef format_str, ArgList args, const ArgMap &map);
|
void init(int error_code, StringRef format_str, ArgList args);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -2559,7 +2576,7 @@ class WindowsError : public SystemError {
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
WindowsError(int error_code, StringRef message) {
|
WindowsError(int error_code, StringRef message) {
|
||||||
init(error_code, message, ArgList(), ArgMap());
|
init(error_code, message, ArgList());
|
||||||
}
|
}
|
||||||
FMT_VARIADIC_CTOR(WindowsError, init, int, StringRef)
|
FMT_VARIADIC_CTOR(WindowsError, init, int, StringRef)
|
||||||
};
|
};
|
||||||
@ -2578,7 +2595,7 @@ enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE };
|
|||||||
Example:
|
Example:
|
||||||
PrintColored(fmt::RED, "Elapsed time: {0:.2f} seconds") << 1.23;
|
PrintColored(fmt::RED, "Elapsed time: {0:.2f} seconds") << 1.23;
|
||||||
*/
|
*/
|
||||||
void print_colored(Color c, StringRef format, ArgList args, const ArgMap &map);
|
void print_colored(Color c, StringRef format, ArgList args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
@ -2589,15 +2606,15 @@ void print_colored(Color c, StringRef format, ArgList args, const ArgMap &map);
|
|||||||
std::string message = format("The answer is {}", 42);
|
std::string message = format("The answer is {}", 42);
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
inline std::string format(StringRef format_str, ArgList args, const ArgMap &map) {
|
inline std::string format(StringRef format_str, ArgList args) {
|
||||||
MemoryWriter w;
|
MemoryWriter w;
|
||||||
w.write(format_str, args, map);
|
w.write(format_str, args);
|
||||||
return w.str();
|
return w.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::wstring format(WStringRef format_str, ArgList args, const WArgMap &map) {
|
inline std::wstring format(WStringRef format_str, ArgList args) {
|
||||||
WMemoryWriter w;
|
WMemoryWriter w;
|
||||||
w.write(format_str, args, map);
|
w.write(format_str, args);
|
||||||
return w.str();
|
return w.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2610,7 +2627,7 @@ inline std::wstring format(WStringRef format_str, ArgList args, const WArgMap &m
|
|||||||
print(stderr, "Don't {}!", "panic");
|
print(stderr, "Don't {}!", "panic");
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
void print(std::FILE *f, StringRef format_str, ArgList args, const ArgMap &map);
|
void print(std::FILE *f, StringRef format_str, ArgList args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
@ -2621,7 +2638,7 @@ void print(std::FILE *f, StringRef format_str, ArgList args, const ArgMap &map);
|
|||||||
print("Elapsed time: {0:.2f} seconds", 1.23);
|
print("Elapsed time: {0:.2f} seconds", 1.23);
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
void print(StringRef format_str, ArgList args, const ArgMap &map);
|
void print(StringRef format_str, ArgList args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
@ -2632,10 +2649,10 @@ void print(StringRef format_str, ArgList args, const ArgMap &map);
|
|||||||
print(cerr, "Don't {}!", "panic");
|
print(cerr, "Don't {}!", "panic");
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
void print(std::ostream &os, StringRef format_str, ArgList args, const ArgMap &map);
|
void print(std::ostream &os, StringRef format_str, ArgList args);
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
void printf(BasicWriter<Char> &w, BasicStringRef<Char> format, ArgList args, const ArgMap &) {
|
void printf(BasicWriter<Char> &w, BasicStringRef<Char> format, ArgList args) {
|
||||||
internal::PrintfFormatter<Char>().format(w, format, args);
|
internal::PrintfFormatter<Char>().format(w, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2648,9 +2665,9 @@ void printf(BasicWriter<Char> &w, BasicStringRef<Char> format, ArgList args, con
|
|||||||
std::string message = fmt::sprintf("The answer is %d", 42);
|
std::string message = fmt::sprintf("The answer is %d", 42);
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
inline std::string sprintf(StringRef format, ArgList args, const ArgMap &map) {
|
inline std::string sprintf(StringRef format, ArgList args) {
|
||||||
MemoryWriter w;
|
MemoryWriter w;
|
||||||
printf(w, format, args, map);
|
printf(w, format, args);
|
||||||
return w.str();
|
return w.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2663,7 +2680,7 @@ inline std::string sprintf(StringRef format, ArgList args, const ArgMap &map) {
|
|||||||
fmt::fprintf(stderr, "Don't %s!", "panic");
|
fmt::fprintf(stderr, "Don't %s!", "panic");
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
int fprintf(std::FILE *f, StringRef format, ArgList args, const ArgMap &);
|
int fprintf(std::FILE *f, StringRef format, ArgList args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
@ -2674,8 +2691,8 @@ int fprintf(std::FILE *f, StringRef format, ArgList args, const ArgMap &);
|
|||||||
fmt::printf("Elapsed time: %.2f seconds", 1.23);
|
fmt::printf("Elapsed time: %.2f seconds", 1.23);
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
inline int printf(StringRef format, ArgList args, const ArgMap &map) {
|
inline int printf(StringRef format, ArgList args) {
|
||||||
return fprintf(stdout, format, args, map);
|
return fprintf(stdout, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2782,13 +2799,24 @@ inline void format_decimal(char *&buffer, T value) {
|
|||||||
buffer += 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>
|
template <typename T>
|
||||||
inline internal::NamedArg<char, T> arg(StringRef name, T const& arg) {
|
inline internal::NamedArg<char, T> arg(StringRef name, const T &arg) {
|
||||||
return internal::NamedArg<char, T>(name, arg);
|
return internal::NamedArg<char, T>(name, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline internal::NamedArg<wchar_t, T> arg(WStringRef name, T const& arg) {
|
inline internal::NamedArg<wchar_t, T> arg(WStringRef name, const T &arg) {
|
||||||
return internal::NamedArg<wchar_t, T>(name, arg);
|
return internal::NamedArg<wchar_t, T>(name, arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2827,22 +2855,28 @@ inline internal::NamedArg<wchar_t, T> arg(WStringRef name, T const& arg) {
|
|||||||
const Args & ... args) { \
|
const Args & ... args) { \
|
||||||
typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
|
typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
|
||||||
const int count = fmt::internal::NamedArgsCounter<Args...>::value; \
|
const int count = fmt::internal::NamedArgsCounter<Args...>::value; \
|
||||||
fmt::BasicArgMap<Char>::value_type mapArray[count + 1]; \
|
fmt::internal::BasicArgMap<Char>::value_type mapArray[count + 1]; \
|
||||||
fmt::internal::add_named_args<0>(mapArray, args...); \
|
fmt::internal::add_named_args<0>(mapArray, args...); \
|
||||||
fmt::BasicArgMap<Char> map(mapArray, count); \
|
fmt::internal::BasicArgMap<Char> map(mapArray, count); \
|
||||||
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
|
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
|
||||||
fmt::internal::make_arg_list<Char>(array, fmt::internal::strip_name(args)...), map); \
|
fmt::internal::make_arg_list<Char>(array, &map, fmt::internal::strip_name(args)...)); \
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Defines a wrapper for a function taking __VA_ARGS__ arguments
|
// Defines a wrapper for a function taking __VA_ARGS__ arguments
|
||||||
// and n additional arguments of arbitrary types.
|
// and n additional arguments of arbitrary types.
|
||||||
# define FMT_WRAP(Char, ReturnType, func, call, n, ...) \
|
# define FMT_WRAP(Char_, ReturnType, func, call, n, ...) \
|
||||||
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
|
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
|
||||||
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
||||||
FMT_GEN(n, FMT_MAKE_ARG)) { \
|
FMT_GEN(n, FMT_MAKE_ARG)) { \
|
||||||
fmt::internal::ArgArray<n>::Type arr = {FMT_GEN(n, FMT_MAKE_REF_##Char)}; \
|
typedef Char_ Char; \
|
||||||
|
typedef fmt::internal::BasicArgMap<Char>::value_type ArgMapValue; \
|
||||||
|
fmt::internal::ArgArray<n>::Type arr = {FMT_GEN(n, FMT_MAKE_REF)}; \
|
||||||
|
ArgMapValue mapArray[n]; \
|
||||||
|
ArgMapValue* mapPtr = mapArray; \
|
||||||
|
FMT_GEN(n, FMT_ADD_NAMED_ARG); \
|
||||||
|
fmt::internal::BasicArgMap<Char> map(mapArray, unsigned(mapPtr - mapArray)); \
|
||||||
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \
|
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \
|
||||||
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr)); \
|
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr, &map)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
|
# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
|
||||||
@ -2901,6 +2935,20 @@ inline internal::NamedArg<wchar_t, T> arg(WStringRef name, T const& arg) {
|
|||||||
|
|
||||||
#define FMT_CAPTURE_ARG_(id, index) ::fmt::arg(#id, id)
|
#define FMT_CAPTURE_ARG_(id, index) ::fmt::arg(#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(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_, __VA_ARGS__)
|
||||||
|
|
||||||
namespace fmt {
|
namespace fmt {
|
||||||
|
|||||||
4
posix.h
4
posix.h
@ -197,8 +197,8 @@ public:
|
|||||||
// of MinGW that define fileno as a macro.
|
// of MinGW that define fileno as a macro.
|
||||||
int (fileno)() const;
|
int (fileno)() const;
|
||||||
|
|
||||||
void print(fmt::StringRef format_str, const ArgList &args, const ArgMap &map) {
|
void print(fmt::StringRef format_str, const ArgList &args) {
|
||||||
fmt::print(file_, format_str, args, map);
|
fmt::print(file_, format_str, args);
|
||||||
}
|
}
|
||||||
FMT_VARIADIC(void, print, fmt::StringRef)
|
FMT_VARIADIC(void, print, fmt::StringRef)
|
||||||
};
|
};
|
||||||
|
|||||||
@ -606,6 +606,7 @@ TEST(FormatterTest, ManyArgs) {
|
|||||||
EXPECT_THROW_MSG(TestFormat<MAX_PACKED_ARGS>::format(format_str),
|
EXPECT_THROW_MSG(TestFormat<MAX_PACKED_ARGS>::format(format_str),
|
||||||
FormatError, "argument index out of range");
|
FormatError, "argument index out of range");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST(FormatterTest, NamedArg) {
|
TEST(FormatterTest, NamedArg) {
|
||||||
char a = 'A', b = 'B', c = 'C';
|
char a = 'A', b = 'B', c = 'C';
|
||||||
@ -620,7 +621,6 @@ TEST(FormatterTest, NamedArg) {
|
|||||||
EXPECT_EQ(" -42", format("{0:{width}}", -42, fmt::arg("width", 4)));
|
EXPECT_EQ(" -42", format("{0:{width}}", -42, fmt::arg("width", 4)));
|
||||||
EXPECT_EQ("st", format("{0:.{precision}}", "str", fmt::arg("precision", 2)));
|
EXPECT_EQ("st", format("{0:.{precision}}", "str", fmt::arg("precision", 2)));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
TEST(FormatterTest, AutoArgIndex) {
|
TEST(FormatterTest, AutoArgIndex) {
|
||||||
EXPECT_EQ("abc", format("{}{}{}", 'a', 'b', 'c'));
|
EXPECT_EQ("abc", format("{}{}{}", 'a', 'b', 'c'));
|
||||||
@ -1564,10 +1564,10 @@ TEST(StrTest, Convert) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string format_message(int id, const char *format,
|
std::string format_message(int id, const char *format,
|
||||||
const fmt::ArgList &args, const fmt::ArgMap &map) {
|
const fmt::ArgList &args) {
|
||||||
MemoryWriter w;
|
MemoryWriter w;
|
||||||
w.write("[{}] ", id);
|
w.write("[{}] ", id);
|
||||||
w.write(format, args, map);
|
w.write(format, args);
|
||||||
return w.str();
|
return w.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user