deps: Update {fmt} to 7.1.3 and include ranges.h cause its nice (#479)

This commit is contained in:
Tyler Wilding 2021-05-13 00:40:43 -04:00 committed by GitHub
parent 53a7d6512f
commit acac7d0e4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 3142 additions and 861 deletions

View File

@ -327,9 +327,9 @@ class text_style {
}
friend FMT_CONSTEXPR_DECL text_style fg(detail::color_type foreground)
FMT_NOEXCEPT;
FMT_NOEXCEPT;
friend FMT_CONSTEXPR_DECL text_style bg(detail::color_type background)
FMT_NOEXCEPT;
FMT_NOEXCEPT;
detail::color_type foreground_color;
detail::color_type background_color;
@ -463,16 +463,16 @@ template <> inline void reset_color<wchar_t>(FILE* stream) FMT_NOEXCEPT {
}
template <typename Char>
inline void reset_color(basic_memory_buffer<Char>& buffer) FMT_NOEXCEPT {
inline void reset_color(buffer<Char>& buffer) FMT_NOEXCEPT {
const char* begin = data::reset_color;
const char* end = begin + sizeof(data::reset_color) - 1;
buffer.append(begin, end);
}
template <typename Char>
void vformat_to(basic_memory_buffer<Char>& buf, const text_style& ts,
void vformat_to(buffer<Char>& buf, const text_style& ts,
basic_string_view<Char> format_str,
basic_format_args<buffer_context<Char>> args) {
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
bool has_style = false;
if (ts.has_emphasis()) {
has_style = true;
@ -496,7 +496,7 @@ void vformat_to(basic_memory_buffer<Char>& buf, const text_style& ts,
template <typename S, typename Char = char_t<S>>
void vprint(std::FILE* f, const text_style& ts, const S& format,
basic_format_args<buffer_context<Char>> args) {
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
basic_memory_buffer<Char> buf;
detail::vformat_to(buf, ts, to_string_view(format), args);
buf.push_back(Char(0));
@ -504,20 +504,22 @@ void vprint(std::FILE* f, const text_style& ts, const S& format,
}
/**
\rst
Formats a string and prints it to the specified file stream using ANSI
escape sequences to specify text formatting.
Example:
**Example**::
fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
"Elapsed time: {0:.2f} seconds", 1.23);
\endrst
*/
template <typename S, typename... Args,
FMT_ENABLE_IF(detail::is_string<S>::value)>
FMT_ENABLE_IF(detail::is_string<S>::value)>
void print(std::FILE* f, const text_style& ts, const S& format_str,
const Args&... args) {
detail::check_format_string<Args...>(format_str);
using context = buffer_context<char_t<S>>;
format_arg_store<context, Args...> as{args...};
vprint(f, ts, format_str, basic_format_args<context>(as));
vprint(f, ts, format_str,
fmt::make_args_checked<Args...>(format_str, args...));
}
/**
@ -528,7 +530,7 @@ void print(std::FILE* f, const text_style& ts, const S& format_str,
"Elapsed time: {0:.2f} seconds", 1.23);
*/
template <typename S, typename... Args,
FMT_ENABLE_IF(detail::is_string<S>::value)>
FMT_ENABLE_IF(detail::is_string<S>::value)>
void print(const text_style& ts, const S& format_str, const Args&... args) {
return print(stdout, ts, format_str, args...);
}
@ -558,9 +560,44 @@ template <typename S, typename... Args, typename Char = char_t<S>>
inline std::basic_string<Char> format(const text_style& ts, const S& format_str,
const Args&... args) {
return vformat(ts, to_string_view(format_str),
detail::make_args_checked<Args...>(format_str, args...));
fmt::make_args_checked<Args...>(format_str, args...));
}
/**
Formats a string with the given text_style and writes the output to ``out``.
*/
template <typename OutputIt, typename Char,
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
OutputIt vformat_to(
OutputIt out, const text_style& ts, basic_string_view<Char> format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out));
detail::vformat_to(buf, ts, format_str, args);
return detail::get_iterator(buf);
}
/**
\rst
Formats arguments with the given text_style, writes the result to the output
iterator ``out`` and returns the iterator past the end of the output range.
**Example**::
std::vector<char> out;
fmt::format_to(std::back_inserter(out),
fmt::emphasis::bold | fg(fmt::color::red), "{}", 42);
\endrst
*/
template <typename OutputIt, typename S, typename... Args,
bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value&&
detail::is_string<S>::value>
inline auto format_to(OutputIt out, const text_style& ts, const S& format_str,
Args&&... args) ->
typename std::enable_if<enable, OutputIt>::type {
return vformat_to(out, ts, to_string_view(format_str),
fmt::make_args_checked<Args...>(format_str, args...));
}
FMT_END_NAMESPACE
#endif // FMT_COLOR_H_
#endif // FMT_COLOR_H_

448
third-party/fmt/core.h vendored
View File

@ -18,7 +18,7 @@
#include <vector>
// The fmt library version in the form major * 10000 + minor * 100 + patch.
#define FMT_VERSION 70003
#define FMT_VERSION 70103
#ifdef __clang__
# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
@ -57,6 +57,7 @@
# define FMT_MSC_VER 0
# define FMT_SUPPRESS_MSC_WARNING(n)
#endif
#ifdef __has_feature
# define FMT_HAS_FEATURE(x) __has_feature(x)
#else
@ -64,7 +65,7 @@
#endif
#if defined(__has_include) && !defined(__INTELLISENSE__) && \
!(FMT_ICC_VERSION && FMT_ICC_VERSION < 1600)
(!FMT_ICC_VERSION || FMT_ICC_VERSION >= 1600)
# define FMT_HAS_INCLUDE(x) __has_include(x)
#else
# define FMT_HAS_INCLUDE(x) 0
@ -99,7 +100,7 @@
#endif
#ifndef FMT_OVERRIDE
# if FMT_HAS_FEATURE(cxx_override) || \
# if FMT_HAS_FEATURE(cxx_override_control) || \
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900
# define FMT_OVERRIDE override
# else
@ -152,7 +153,7 @@
# if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VER >= 1900
# define FMT_DEPRECATED [[deprecated]]
# else
# if defined(__GNUC__) || defined(__clang__)
# if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__)
# define FMT_DEPRECATED __attribute__((deprecated))
# elif FMT_MSC_VER
# define FMT_DEPRECATED __declspec(deprecated)
@ -177,9 +178,17 @@
# endif
#endif
#ifndef FMT_BEGIN_NAMESPACE
#ifndef FMT_USE_INLINE_NAMESPACES
# if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || \
FMT_MSC_VER >= 1900
(FMT_MSC_VER >= 1900 && !_MANAGED)
# define FMT_USE_INLINE_NAMESPACES 1
# else
# define FMT_USE_INLINE_NAMESPACES 0
# endif
#endif
#ifndef FMT_BEGIN_NAMESPACE
# if FMT_USE_INLINE_NAMESPACES
# define FMT_INLINE_NAMESPACE inline namespace
# define FMT_END_NAMESPACE \
} \
@ -269,8 +278,7 @@ struct monostate {};
namespace detail {
// A helper function to suppress bogus "conditional expression is constant"
// warnings.
// A helper function to suppress "conditional expression is constant" warnings.
template <typename T> constexpr T const_check(T value) { return value; }
FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
@ -299,7 +307,8 @@ template <typename T> struct std_string_view {};
#ifdef FMT_USE_INT128
// Do nothing.
#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && !(FMT_CLANG_VERSION && FMT_MSC_VER)
#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && \
!(FMT_CLANG_VERSION && FMT_MSC_VER)
# define FMT_USE_INT128 1
using int128_t = __int128_t;
using uint128_t = __uint128_t;
@ -506,6 +515,18 @@ template <typename S> struct char_t_impl<S, enable_if_t<is_string<S>::value>> {
using type = typename result::value_type;
};
// Reports a compile-time error if S is not a valid format string.
template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)>
FMT_INLINE void check_format_string(const S&) {
#ifdef FMT_ENFORCE_COMPILE_STRING
static_assert(is_compile_string<S>::value,
"FMT_ENFORCE_COMPILE_STRING requires all format strings to use "
"FMT_STRING.");
#endif
}
template <typename..., typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
void check_format_string(S);
struct error_handler {
constexpr error_handler() = default;
constexpr error_handler(const error_handler&) = default;
@ -545,8 +566,9 @@ class basic_format_parse_context : private ErrorHandler {
using iterator = typename basic_string_view<Char>::iterator;
explicit constexpr basic_format_parse_context(
basic_string_view<Char> format_str, ErrorHandler eh = {})
: ErrorHandler(eh), format_str_(format_str), next_arg_id_(0) {}
basic_string_view<Char> format_str, ErrorHandler eh = {},
int next_arg_id = 0)
: ErrorHandler(eh), format_str_(format_str), next_arg_id_(next_arg_id) {}
/**
Returns an iterator to the beginning of the format string range being
@ -616,8 +638,24 @@ template <typename T, typename Context>
using has_formatter =
std::is_constructible<typename Context::template formatter_type<T>>;
// Checks whether T is a container with contiguous storage.
template <typename T> struct is_contiguous : std::false_type {};
template <typename Char>
struct is_contiguous<std::basic_string<Char>> : std::true_type {};
namespace detail {
// Extracts a reference to the container from back_insert_iterator.
template <typename Container>
inline Container& get_container(std::back_insert_iterator<Container> it) {
using bi_iterator = std::back_insert_iterator<Container>;
struct accessor : bi_iterator {
accessor(bi_iterator iter) : bi_iterator(iter) {}
using bi_iterator::container;
};
return *accessor(it).container;
}
/**
\rst
A contiguous memory buffer with an optional growing ability. It is an internal
@ -640,6 +678,8 @@ template <typename T> class buffer {
size_(sz),
capacity_(cap) {}
~buffer() = default;
/** Sets the buffer data and capacity. */
void set(T* buf_data, size_t buf_capacity) FMT_NOEXCEPT {
ptr_ = buf_data;
@ -655,7 +695,6 @@ template <typename T> class buffer {
buffer(const buffer&) = delete;
void operator=(const buffer&) = delete;
virtual ~buffer() = default;
T* begin() FMT_NOEXCEPT { return ptr_; }
T* end() FMT_NOEXCEPT { return ptr_ + size_; }
@ -675,24 +714,26 @@ template <typename T> class buffer {
/** Returns a pointer to the buffer data. */
const T* data() const FMT_NOEXCEPT { return ptr_; }
/**
Resizes the buffer. If T is a POD type new elements may not be initialized.
*/
void resize(size_t new_size) {
reserve(new_size);
size_ = new_size;
}
/** Clears this buffer. */
void clear() { size_ = 0; }
/** Reserves space to store at least *capacity* elements. */
void reserve(size_t new_capacity) {
// Tries resizing the buffer to contain *count* elements. If T is a POD type
// the new elements may not be initialized.
void try_resize(size_t count) {
try_reserve(count);
size_ = count <= capacity_ ? count : capacity_;
}
// Tries increasing the buffer capacity to *new_capacity*. It can increase the
// capacity by a smaller amount than requested but guarantees there is space
// for at least one additional element either by increasing the capacity or by
// flushing the buffer if it is full.
void try_reserve(size_t new_capacity) {
if (new_capacity > capacity_) grow(new_capacity);
}
void push_back(const T& value) {
reserve(size_ + 1);
try_reserve(size_ + 1);
ptr_[size_++] = value;
}
@ -705,32 +746,150 @@ template <typename T> class buffer {
}
};
// A container-backed buffer.
struct buffer_traits {
explicit buffer_traits(size_t) {}
size_t count() const { return 0; }
size_t limit(size_t size) { return size; }
};
class fixed_buffer_traits {
private:
size_t count_ = 0;
size_t limit_;
public:
explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
size_t count() const { return count_; }
size_t limit(size_t size) {
size_t n = limit_ > count_ ? limit_ - count_ : 0;
count_ += size;
return size < n ? size : n;
}
};
// A buffer that writes to an output iterator when flushed.
template <typename OutputIt, typename T, typename Traits = buffer_traits>
class iterator_buffer final : public Traits, public buffer<T> {
private:
OutputIt out_;
enum { buffer_size = 256 };
T data_[buffer_size];
protected:
void grow(size_t) final FMT_OVERRIDE {
if (this->size() == buffer_size) flush();
}
void flush();
public:
explicit iterator_buffer(OutputIt out, size_t n = buffer_size)
: Traits(n),
buffer<T>(data_, 0, buffer_size),
out_(out) {}
~iterator_buffer() { flush(); }
OutputIt out() {
flush();
return out_;
}
size_t count() const { return Traits::count() + this->size(); }
};
template <typename T> class iterator_buffer<T*, T> final : public buffer<T> {
protected:
void grow(size_t) final FMT_OVERRIDE {}
public:
explicit iterator_buffer(T* out, size_t = 0) : buffer<T>(out, 0, ~size_t()) {}
T* out() { return &*this->end(); }
};
// A buffer that writes to a container with the contiguous storage.
template <typename Container>
class container_buffer : public buffer<typename Container::value_type> {
class iterator_buffer<std::back_insert_iterator<Container>,
enable_if_t<is_contiguous<Container>::value,
typename Container::value_type>>
final : public buffer<typename Container::value_type> {
private:
Container& container_;
protected:
void grow(size_t capacity) FMT_OVERRIDE {
void grow(size_t capacity) final FMT_OVERRIDE {
container_.resize(capacity);
this->set(&container_[0], capacity);
}
public:
explicit container_buffer(Container& c)
explicit iterator_buffer(Container& c)
: buffer<typename Container::value_type>(c.size()), container_(c) {}
explicit iterator_buffer(std::back_insert_iterator<Container> out, size_t = 0)
: iterator_buffer(get_container(out)) {}
std::back_insert_iterator<Container> out() {
return std::back_inserter(container_);
}
};
// Extracts a reference to the container from back_insert_iterator.
template <typename Container>
inline Container& get_container(std::back_insert_iterator<Container> it) {
using bi_iterator = std::back_insert_iterator<Container>;
struct accessor : bi_iterator {
accessor(bi_iterator iter) : bi_iterator(iter) {}
using bi_iterator::container;
};
return *accessor(it).container;
// A buffer that counts the number of code units written discarding the output.
template <typename T = char> class counting_buffer final : public buffer<T> {
private:
enum { buffer_size = 256 };
T data_[buffer_size];
size_t count_ = 0;
protected:
void grow(size_t) final FMT_OVERRIDE {
if (this->size() != buffer_size) return;
count_ += this->size();
this->clear();
}
public:
counting_buffer() : buffer<T>(data_, 0, buffer_size) {}
size_t count() { return count_ + this->size(); }
};
// An output iterator that appends to the buffer.
// It is used to reduce symbol sizes for the common case.
template <typename T>
class buffer_appender : public std::back_insert_iterator<buffer<T>> {
using base = std::back_insert_iterator<buffer<T>>;
public:
explicit buffer_appender(buffer<T>& buf) : base(buf) {}
buffer_appender(base it) : base(it) {}
buffer_appender& operator++() {
base::operator++();
return *this;
}
buffer_appender operator++(int) {
buffer_appender tmp = *this;
++*this;
return tmp;
}
};
// Maps an output iterator into a buffer.
template <typename T, typename OutputIt>
iterator_buffer<OutputIt, T> get_buffer(OutputIt);
template <typename T> buffer<T>& get_buffer(buffer_appender<T>);
template <typename OutputIt> OutputIt get_buffer_init(OutputIt out) {
return out;
}
template <typename T> buffer<T>& get_buffer_init(buffer_appender<T> out) {
return get_container(out);
}
template <typename Buffer>
auto get_iterator(Buffer& buf) -> decltype(buf.out()) {
return buf.out();
}
template <typename T> buffer_appender<T> get_iterator(buffer<T>& buf) {
return buffer_appender<T>(buf);
}
template <typename T, typename Char = char, typename Enable = void>
@ -759,7 +918,8 @@ template <typename Char> struct named_arg_info {
template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS>
struct arg_data {
// args_[0].named_args points to named_args_ to avoid bloating format_args.
T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : 1)];
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)];
named_arg_info<Char> named_args_[NUM_NAMED_ARGS];
template <typename... U>
@ -771,7 +931,8 @@ struct arg_data {
template <typename T, typename Char, size_t NUM_ARGS>
struct arg_data<T, Char, NUM_ARGS, 0> {
T args_[NUM_ARGS != 0 ? NUM_ARGS : 1];
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
T args_[NUM_ARGS != 0 ? NUM_ARGS : +1];
template <typename... U>
FMT_INLINE arg_data(const U&... init) : args_{init...} {}
@ -959,6 +1120,8 @@ enum { long_short = sizeof(long) == sizeof(int) };
using long_type = conditional_t<long_short, int, long long>;
using ulong_type = conditional_t<long_short, unsigned, unsigned long long>;
struct unformattable {};
// Maps formatting arguments to core types.
template <typename Context> struct arg_mapper {
using char_type = typename Context::char_type;
@ -1067,15 +1230,7 @@ template <typename Context> struct arg_mapper {
return map(val.value);
}
int map(...) {
constexpr bool formattable = sizeof(Context) == 0;
static_assert(
formattable,
"Cannot format argument. To make type T formattable provide a "
"formatter<T> specialization: "
"https://fmt.dev/latest/api.html#formatting-user-defined-types");
return 0;
}
unformattable map(...) { return {}; }
};
// A type constant after applying arg_mapper<Context>.
@ -1199,15 +1354,25 @@ FMT_CONSTEXPR_DECL FMT_INLINE auto visit_format_arg(
return vis(monostate());
}
// Checks whether T is a container with contiguous storage.
template <typename T> struct is_contiguous : std::false_type {};
template <typename Char>
struct is_contiguous<std::basic_string<Char>> : std::true_type {};
template <typename Char>
struct is_contiguous<detail::buffer<Char>> : std::true_type {};
template <typename T> struct formattable : std::false_type {};
namespace detail {
// A workaround for gcc 4.8 to make void_t work in a SFINAE context.
template <typename... Ts> struct void_t_impl { using type = void; };
template <typename... Ts>
using void_t = typename detail::void_t_impl<Ts...>::type;
template <typename It, typename T, typename Enable = void>
struct is_output_iterator : std::false_type {};
template <typename It, typename T>
struct is_output_iterator<
It, T,
void_t<typename std::iterator_traits<It>::iterator_category,
decltype(*std::declval<It>() = std::declval<T>())>>
: std::true_type {};
template <typename OutputIt>
struct is_back_insert_iterator : std::false_type {};
template <typename Container>
@ -1219,6 +1384,9 @@ struct is_contiguous_back_insert_iterator : std::false_type {};
template <typename Container>
struct is_contiguous_back_insert_iterator<std::back_insert_iterator<Container>>
: is_contiguous<Container> {};
template <typename Char>
struct is_contiguous_back_insert_iterator<buffer_appender<Char>>
: std::true_type {};
// A type-erased reference to an std::locale to avoid heavy <locale> include.
class locale_ref {
@ -1250,13 +1418,24 @@ FMT_CONSTEXPR basic_format_arg<Context> make_arg(const T& value) {
return arg;
}
template <typename T> int check(unformattable) {
static_assert(
formattable<T>(),
"Cannot format an argument. To make type T formattable provide a "
"formatter<T> specialization: https://fmt.dev/latest/api.html#udt");
return 0;
}
template <typename T, typename U> inline const U& check(const U& val) {
return val;
}
// The type template parameter is there to avoid an ODR violation when using
// a fallback formatter in one translation unit and an implicit conversion in
// another (not recommended).
template <bool IS_PACKED, typename Context, type, typename T,
FMT_ENABLE_IF(IS_PACKED)>
inline value<Context> make_arg(const T& val) {
return arg_mapper<Context>().map(val);
return check<T>(arg_mapper<Context>().map(val));
}
template <bool IS_PACKED, typename Context, type, typename T,
@ -1356,13 +1535,13 @@ template <typename OutputIt, typename Char> class basic_format_context {
template <typename Char>
using buffer_context =
basic_format_context<std::back_insert_iterator<detail::buffer<Char>>, Char>;
basic_format_context<detail::buffer_appender<Char>, Char>;
using format_context = buffer_context<char>;
using wformat_context = buffer_context<wchar_t>;
// Workaround a bug in gcc: https://stackoverflow.com/q/62767544/471164.
// Workaround an alias issue: https://stackoverflow.com/q/62767544/471164.
#define FMT_BUFFER_CONTEXT(Char) \
basic_format_context<std::back_insert_iterator<detail::buffer<Char>>, Char>
basic_format_context<detail::buffer_appender<Char>, Char>
/**
\rst
@ -1414,7 +1593,7 @@ class format_arg_store
/**
\rst
Constructs an `~fmt::format_arg_store` object that contains references to
Constructs a `~fmt::format_arg_store` object that contains references to
arguments and can be implicitly converted to `~fmt::format_args`. `Context`
can be omitted in which case it defaults to `~fmt::context`.
See `~fmt::arg` for lifetime considerations.
@ -1426,6 +1605,27 @@ inline format_arg_store<Context, Args...> make_format_args(
return {args...};
}
/**
\rst
Constructs a `~fmt::format_arg_store` object that contains references
to arguments and can be implicitly converted to `~fmt::format_args`.
If ``format_str`` is a compile-time string then `make_args_checked` checks
its validity at compile time.
\endrst
*/
template <typename... Args, typename S, typename Char = char_t<S>>
inline auto make_args_checked(const S& format_str,
const remove_reference_t<Args>&... args)
-> format_arg_store<buffer_context<Char>, remove_reference_t<Args>...> {
static_assert(
detail::count<(
std::is_base_of<detail::view, remove_reference_t<Args>>::value &&
std::is_reference<Args>::value)...>() == 0,
"passing views as lvalues is disallowed");
detail::check_format_string<Args...>(format_str);
return {args...};
}
/**
\rst
Returns a named argument to be used in a formatting function. It should only
@ -1729,7 +1929,14 @@ template <typename Context> class basic_format_args {
}
};
/** An alias to ``basic_format_args<context>``. */
#ifdef FMT_ARM_ABI_COMPATIBILITY
/** An alias to ``basic_format_args<format_context>``. */
// Separate types would result in shorter symbols but break ABI compatibility
// between clang and gcc on ARM (#1919).
using format_args = basic_format_args<format_context>;
using wformat_args = basic_format_args<wformat_context>;
#else
// DEPRECATED! These are kept for ABI compatibility.
// It is a separate type rather than an alias to make symbols readable.
struct format_args : basic_format_args<format_context> {
template <typename... Args>
@ -1738,32 +1945,10 @@ struct format_args : basic_format_args<format_context> {
struct wformat_args : basic_format_args<wformat_context> {
using basic_format_args::basic_format_args;
};
#endif
namespace detail {
// Reports a compile-time error if S is not a valid format string.
template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)>
FMT_INLINE void check_format_string(const S&) {
#ifdef FMT_ENFORCE_COMPILE_STRING
static_assert(is_compile_string<S>::value,
"FMT_ENFORCE_COMPILE_STRING requires all format strings to use "
"FMT_STRING.");
#endif
}
template <typename..., typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
void check_format_string(S);
template <typename... Args, typename S, typename Char = char_t<S>>
inline format_arg_store<buffer_context<Char>, remove_reference_t<Args>...>
make_args_checked(const S& format_str,
const remove_reference_t<Args>&... args) {
static_assert(count<(std::is_base_of<view, remove_reference_t<Args>>::value &&
std::is_reference<Args>::value)...>() == 0,
"passing views as lvalues is disallowed");
check_format_string<Args...>(format_str);
return {args...};
}
template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
std::basic_string<Char> vformat(
basic_string_view<Char> format_str,
@ -1772,9 +1957,10 @@ std::basic_string<Char> vformat(
FMT_API std::string vformat(string_view format_str, format_args args);
template <typename Char>
typename FMT_BUFFER_CONTEXT(Char)::iterator vformat_to(
void vformat_to(
buffer<Char>& buf, basic_string_view<Char> format_str,
basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args);
basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args,
detail::locale_ref loc = {});
template <typename Char, typename Args,
FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
@ -1789,26 +1975,80 @@ inline void vprint_mojibake(std::FILE*, string_view, format_args) {}
/** Formats a string and writes the output to ``out``. */
// GCC 8 and earlier cannot handle std::back_insert_iterator<Container> with
// vformat_to<ArgFormatter>(...) overload, so SFINAE on iterator type instead.
template <
typename OutputIt, typename S, typename Char = char_t<S>,
FMT_ENABLE_IF(detail::is_contiguous_back_insert_iterator<OutputIt>::value)>
OutputIt vformat_to(
OutputIt out, const S& format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
auto& c = detail::get_container(out);
detail::container_buffer<remove_reference_t<decltype(c)>> buf(c);
template <typename OutputIt, typename S, typename Char = char_t<S>,
bool enable = detail::is_output_iterator<OutputIt, Char>::value>
auto vformat_to(OutputIt out, const S& format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args)
-> typename std::enable_if<enable, OutputIt>::type {
decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out));
detail::vformat_to(buf, to_string_view(format_str), args);
return out;
return detail::get_iterator(buf);
}
template <typename Container, typename S, typename... Args,
FMT_ENABLE_IF(
is_contiguous<Container>::value&& detail::is_string<S>::value)>
inline std::back_insert_iterator<Container> format_to(
std::back_insert_iterator<Container> out, const S& format_str,
Args&&... args) {
return vformat_to(out, to_string_view(format_str),
detail::make_args_checked<Args...>(format_str, args...));
/**
\rst
Formats arguments, writes the result to the output iterator ``out`` and returns
the iterator past the end of the output range.
**Example**::
std::vector<char> out;
fmt::format_to(std::back_inserter(out), "{}", 42);
\endrst
*/
// We cannot use FMT_ENABLE_IF because of a bug in gcc 8.3.
template <typename OutputIt, typename S, typename... Args,
bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value>
inline auto format_to(OutputIt out, const S& format_str, Args&&... args) ->
typename std::enable_if<enable, OutputIt>::type {
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
return vformat_to(out, to_string_view(format_str), vargs);
}
template <typename OutputIt> struct format_to_n_result {
/** Iterator past the end of the output range. */
OutputIt out;
/** Total (not truncated) output size. */
size_t size;
};
template <typename OutputIt, typename Char, typename... Args,
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
inline format_to_n_result<OutputIt> vformat_to_n(
OutputIt out, size_t n, basic_string_view<Char> format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
detail::iterator_buffer<OutputIt, Char, detail::fixed_buffer_traits> buf(out,
n);
detail::vformat_to(buf, format_str, args);
return {buf.out(), buf.count()};
}
/**
\rst
Formats arguments, writes up to ``n`` characters of the result to the output
iterator ``out`` and returns the total output size and the iterator past the
end of the output range.
\endrst
*/
template <typename OutputIt, typename S, typename... Args,
bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value>
inline auto format_to_n(OutputIt out, size_t n, const S& format_str,
const Args&... args) ->
typename std::enable_if<enable, format_to_n_result<OutputIt>>::type {
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
return vformat_to_n(out, n, to_string_view(format_str), vargs);
}
/**
Returns the number of characters in the output of
``format(format_str, args...)``.
*/
template <typename... Args>
inline size_t formatted_size(string_view format_str, Args&&... args) {
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
detail::counting_buffer<> buf;
detail::vformat_to(buf, format_str, vargs);
return buf.count();
}
template <typename S, typename Char = char_t<S>>
@ -1832,7 +2072,7 @@ FMT_INLINE std::basic_string<Char> vformat(
// std::basic_string<char_t<S>> to reduce the symbol size.
template <typename S, typename... Args, typename Char = char_t<S>>
FMT_INLINE std::basic_string<Char> format(const S& format_str, Args&&... args) {
const auto& vargs = detail::make_args_checked<Args...>(format_str, args...);
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
return detail::vformat(to_string_view(format_str), vargs);
}
@ -1852,7 +2092,7 @@ FMT_API void vprint(std::FILE*, string_view, format_args);
*/
template <typename S, typename... Args, typename Char = char_t<S>>
inline void print(std::FILE* f, const S& format_str, Args&&... args) {
const auto& vargs = detail::make_args_checked<Args...>(format_str, args...);
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
return detail::is_unicode<Char>()
? vprint(f, to_string_view(format_str), vargs)
: detail::vprint_mojibake(f, to_string_view(format_str), vargs);
@ -1871,7 +2111,7 @@ inline void print(std::FILE* f, const S& format_str, Args&&... args) {
*/
template <typename S, typename... Args, typename Char = char_t<S>>
inline void print(const S& format_str, Args&&... args) {
const auto& vargs = detail::make_args_checked<Args...>(format_str, args...);
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
return detail::is_unicode<Char>()
? vprint(to_string_view(format_str), vargs)
: detail::vprint_mojibake(stdout, to_string_view(format_str),

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,36 @@ int format_float(char* buf, std::size_t size, const char* format, int precision,
return precision < 0 ? snprintf_ptr(buf, size, format, value)
: snprintf_ptr(buf, size, format, precision, value);
}
template FMT_API dragonbox::decimal_fp<float> dragonbox::to_decimal(float x)
FMT_NOEXCEPT;
template FMT_API dragonbox::decimal_fp<double> dragonbox::to_decimal(double x)
FMT_NOEXCEPT;
// DEPRECATED! This function exists for ABI compatibility.
template <typename Char>
typename basic_format_context<std::back_insert_iterator<buffer<Char>>,
Char>::iterator
vformat_to(buffer<Char>& buf, basic_string_view<Char> format_str,
basic_format_args<basic_format_context<
std::back_insert_iterator<buffer<type_identity_t<Char>>>,
type_identity_t<Char>>>
args) {
using iterator = std::back_insert_iterator<buffer<char>>;
using context = basic_format_context<
std::back_insert_iterator<buffer<type_identity_t<Char>>>,
type_identity_t<Char>>;
auto out = iterator(buf);
format_handler<iterator, Char, context> h(out, format_str, args, {});
parse_format_string<false>(format_str, h);
return out;
}
template basic_format_context<std::back_insert_iterator<buffer<char>>,
char>::iterator
vformat_to(buffer<char>&, string_view,
basic_format_args<basic_format_context<
std::back_insert_iterator<buffer<type_identity_t<char>>>,
type_identity_t<char>>>);
} // namespace detail
template struct FMT_INSTANTIATION_DEF_API detail::basic_data<void>;
@ -44,9 +74,9 @@ template FMT_API char detail::decimal_point_impl(locale_ref);
template FMT_API void detail::buffer<char>::append(const char*, const char*);
template FMT_API FMT_BUFFER_CONTEXT(char)::iterator detail::vformat_to(
template FMT_API void detail::vformat_to(
detail::buffer<char>&, string_view,
basic_format_args<FMT_BUFFER_CONTEXT(char)>);
basic_format_args<FMT_BUFFER_CONTEXT(char)>, detail::locale_ref);
template FMT_API int detail::snprintf_float(double, int, detail::float_specs,
detail::buffer<char>&);

1160
third-party/fmt/format.h vendored

File diff suppressed because it is too large Load Diff

396
third-party/fmt/ranges.h vendored Normal file
View File

@ -0,0 +1,396 @@
// Formatting library for C++ - experimental range support
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
//
// Copyright (c) 2018 - present, Remotion (Igor Schulz)
// All Rights Reserved
// {fmt} support for ranges, containers and types tuple interface.
#ifndef FMT_RANGES_H_
#define FMT_RANGES_H_
#include <initializer_list>
#include <type_traits>
#include "format.h"
// output only up to N items from the range.
#ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT
# define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256
#endif
FMT_BEGIN_NAMESPACE
template <typename Char> struct formatting_base {
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
};
template <typename Char, typename Enable = void>
struct formatting_range : formatting_base<Char> {
static FMT_CONSTEXPR_DECL const size_t range_length_limit =
FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the
// range.
Char prefix;
Char delimiter;
Char postfix;
formatting_range() : prefix('{'), delimiter(','), postfix('}') {}
static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
};
template <typename Char, typename Enable = void>
struct formatting_tuple : formatting_base<Char> {
Char prefix;
Char delimiter;
Char postfix;
formatting_tuple() : prefix('('), delimiter(','), postfix(')') {}
static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
};
namespace detail {
template <typename RangeT, typename OutputIterator>
OutputIterator copy(const RangeT& range, OutputIterator out) {
for (auto it = range.begin(), end = range.end(); it != end; ++it)
*out++ = *it;
return out;
}
template <typename OutputIterator>
OutputIterator copy(const char* str, OutputIterator out) {
while (*str) *out++ = *str++;
return out;
}
template <typename OutputIterator>
OutputIterator copy(char ch, OutputIterator out) {
*out++ = ch;
return out;
}
/// Return true value if T has std::string interface, like std::string_view.
template <typename T> class is_like_std_string {
template <typename U>
static auto check(U* p)
-> decltype((void)p->find('a'), p->length(), (void)p->data(), int());
template <typename> static void check(...);
public:
static FMT_CONSTEXPR_DECL const bool value =
is_string<T>::value || !std::is_void<decltype(check<T>(nullptr))>::value;
};
template <typename Char>
struct is_like_std_string<fmt::basic_string_view<Char>> : std::true_type {};
template <typename... Ts> struct conditional_helper {};
template <typename T, typename _ = void> struct is_range_ : std::false_type {};
#if !FMT_MSC_VER || FMT_MSC_VER > 1800
template <typename T>
struct is_range_<
T, conditional_t<false,
conditional_helper<decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end())>,
void>> : std::true_type {};
#endif
/// tuple_size and tuple_element check.
template <typename T> class is_tuple_like_ {
template <typename U>
static auto check(U* p) -> decltype(std::tuple_size<U>::value, int());
template <typename> static void check(...);
public:
static FMT_CONSTEXPR_DECL const bool value =
!std::is_void<decltype(check<T>(nullptr))>::value;
};
// Check for integer_sequence
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
template <typename T, T... N>
using integer_sequence = std::integer_sequence<T, N...>;
template <size_t... N> using index_sequence = std::index_sequence<N...>;
template <size_t N> using make_index_sequence = std::make_index_sequence<N>;
#else
template <typename T, T... N> struct integer_sequence {
using value_type = T;
static FMT_CONSTEXPR size_t size() { return sizeof...(N); }
};
template <size_t... N> using index_sequence = integer_sequence<size_t, N...>;
template <typename T, size_t N, T... Ns>
struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
template <typename T, T... Ns>
struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
template <size_t N>
using make_index_sequence = make_integer_sequence<size_t, N>;
#endif
template <class Tuple, class F, size_t... Is>
void for_each(index_sequence<Is...>, Tuple&& tup, F&& f) FMT_NOEXCEPT {
using std::get;
// using free function get<I>(T) now.
const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
(void)_; // blocks warnings
}
template <class T>
FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value> get_indexes(
T const&) {
return {};
}
template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) {
const auto indexes = get_indexes(tup);
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
}
template <typename Range>
using value_type = remove_cvref_t<decltype(*std::declval<Range>().begin())>;
template <typename Arg, FMT_ENABLE_IF(!is_like_std_string<
typename std::decay<Arg>::type>::value)>
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
return add_space ? " {}" : "{}";
}
template <typename Arg, FMT_ENABLE_IF(is_like_std_string<
typename std::decay<Arg>::type>::value)>
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
return add_space ? " \"{}\"" : "\"{}\"";
}
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char*) {
return add_space ? " \"{}\"" : "\"{}\"";
}
FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t*) {
return add_space ? L" \"{}\"" : L"\"{}\"";
}
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char) {
return add_space ? " '{}'" : "'{}'";
}
FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) {
return add_space ? L" '{}'" : L"'{}'";
}
} // namespace detail
template <typename T> struct is_tuple_like {
static FMT_CONSTEXPR_DECL const bool value =
detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
};
template <typename TupleT, typename Char>
struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
private:
// C++11 generic lambda for format()
template <typename FormatContext> struct format_each {
template <typename T> void operator()(const T& v) {
if (i > 0) {
if (formatting.add_prepostfix_space) {
*out++ = ' ';
}
out = detail::copy(formatting.delimiter, out);
}
out = format_to(out,
detail::format_str_quoted(
(formatting.add_delimiter_spaces && i > 0), v),
v);
++i;
}
formatting_tuple<Char>& formatting;
size_t& i;
typename std::add_lvalue_reference<decltype(
std::declval<FormatContext>().out())>::type out;
};
public:
formatting_tuple<Char> formatting;
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return formatting.parse(ctx);
}
template <typename FormatContext = format_context>
auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) {
auto out = ctx.out();
size_t i = 0;
detail::copy(formatting.prefix, out);
detail::for_each(values, format_each<FormatContext>{formatting, i, out});
if (formatting.add_prepostfix_space) {
*out++ = ' ';
}
detail::copy(formatting.postfix, out);
return ctx.out();
}
};
template <typename T, typename Char> struct is_range {
static FMT_CONSTEXPR_DECL const bool value =
detail::is_range_<T>::value && !detail::is_like_std_string<T>::value &&
!std::is_convertible<T, std::basic_string<Char>>::value &&
!std::is_constructible<detail::std_string_view<Char>, T>::value;
};
template <typename T, typename Char>
struct formatter<
T, Char,
enable_if_t<fmt::is_range<T, Char>::value
// Workaround a bug in MSVC 2017 and earlier.
#if !FMT_MSC_VER || FMT_MSC_VER >= 1927
&&
(has_formatter<detail::value_type<T>, format_context>::value ||
detail::has_fallback_formatter<detail::value_type<T>,
format_context>::value)
#endif
>> {
formatting_range<Char> formatting;
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return formatting.parse(ctx);
}
template <typename FormatContext>
typename FormatContext::iterator format(const T& values, FormatContext& ctx) {
auto out = detail::copy(formatting.prefix, ctx.out());
size_t i = 0;
auto it = values.begin();
auto end = values.end();
for (; it != end; ++it) {
if (i > 0) {
if (formatting.add_prepostfix_space) *out++ = ' ';
out = detail::copy(formatting.delimiter, out);
}
out = format_to(out,
detail::format_str_quoted(
(formatting.add_delimiter_spaces && i > 0), *it),
*it);
if (++i > formatting.range_length_limit) {
out = format_to(out, " ... <other elements>");
break;
}
}
if (formatting.add_prepostfix_space) *out++ = ' ';
return detail::copy(formatting.postfix, out);
}
};
template <typename Char, typename... T> struct tuple_arg_join : detail::view {
const std::tuple<T...>& tuple;
basic_string_view<Char> sep;
tuple_arg_join(const std::tuple<T...>& t, basic_string_view<Char> s)
: tuple{t}, sep{s} {}
};
template <typename Char, typename... T>
struct formatter<tuple_arg_join<Char, T...>, Char> {
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
template <typename FormatContext>
typename FormatContext::iterator format(
const tuple_arg_join<Char, T...>& value, FormatContext& ctx) {
return format(value, ctx, detail::make_index_sequence<sizeof...(T)>{});
}
private:
template <typename FormatContext, size_t... N>
typename FormatContext::iterator format(
const tuple_arg_join<Char, T...>& value, FormatContext& ctx,
detail::index_sequence<N...>) {
return format_args(value, ctx, std::get<N>(value.tuple)...);
}
template <typename FormatContext>
typename FormatContext::iterator format_args(
const tuple_arg_join<Char, T...>&, FormatContext& ctx) {
// NOTE: for compilers that support C++17, this empty function instantiation
// can be replaced with a constexpr branch in the variadic overload.
return ctx.out();
}
template <typename FormatContext, typename Arg, typename... Args>
typename FormatContext::iterator format_args(
const tuple_arg_join<Char, T...>& value, FormatContext& ctx,
const Arg& arg, const Args&... args) {
using base = formatter<typename std::decay<Arg>::type, Char>;
auto out = ctx.out();
out = base{}.format(arg, ctx);
if (sizeof...(Args) > 0) {
out = std::copy(value.sep.begin(), value.sep.end(), out);
ctx.advance_to(out);
return format_args(value, ctx, args...);
}
return out;
}
};
/**
\rst
Returns an object that formats `tuple` with elements separated by `sep`.
**Example**::
std::tuple<int, char> t = {1, 'a'};
fmt::print("{}", fmt::join(t, ", "));
// Output: "1, a"
\endrst
*/
template <typename... T>
FMT_CONSTEXPR tuple_arg_join<char, T...> join(const std::tuple<T...>& tuple,
string_view sep) {
return {tuple, sep};
}
template <typename... T>
FMT_CONSTEXPR tuple_arg_join<wchar_t, T...> join(const std::tuple<T...>& tuple,
wstring_view sep) {
return {tuple, sep};
}
/**
\rst
Returns an object that formats `initializer_list` with elements separated by
`sep`.
**Example**::
fmt::print("{}", fmt::join({1, 2, 3}, ", "));
// Output: "1, 2, 3"
\endrst
*/
template <typename T>
arg_join<const T*, const T*, char> join(std::initializer_list<T> list,
string_view sep) {
return join(std::begin(list), std::end(list), sep);
}
template <typename T>
arg_join<const T*, const T*, wchar_t> join(std::initializer_list<T> list,
wstring_view sep) {
return join(std::begin(list), std::end(list), sep);
}
FMT_END_NAMESPACE
#endif // FMT_RANGES_H_