Skip to content

Commit 1217383

Browse files
JacobDomagalacwschilly
authored andcommitted
#2216: Update fmt to 10.1
1 parent 4b39ad1 commit 1217383

File tree

17 files changed

+12551
-6507
lines changed

17 files changed

+12551
-6507
lines changed

lib/fmt/CMakeLists.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ function(add_headers VAR)
99
endfunction()
1010

1111
# Define the fmt library, its includes and the needed defines.
12-
add_headers(FMT_HEADERS core.h format.h format-inl.h ostream.h)
12+
add_headers(FMT_HEADERS args.h color.h core.h format-inl.h ostream.h ranges.h
13+
xchar.h chrono.h compile.h format.h printf.h std.h)
1314
set(FMT_SOURCES src/format.cc)
1415

1516
add_library(fmt ${FMT_SOURCES} ${FMT_HEADERS})

lib/fmt/include/fmt-vt/args.h

+234
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
// Formatting library for C++ - dynamic argument lists
2+
//
3+
// Copyright (c) 2012 - present, Victor Zverovich
4+
// All rights reserved.
5+
//
6+
// For the license information refer to format.h.
7+
8+
#ifndef FMT_ARGS_H_
9+
#define FMT_ARGS_H_
10+
11+
#include <functional> // std::reference_wrapper
12+
#include <memory> // std::unique_ptr
13+
#include <vector>
14+
15+
#include "core.h"
16+
17+
FMT_BEGIN_NAMESPACE
18+
19+
namespace detail {
20+
21+
template <typename T> struct is_reference_wrapper : std::false_type {};
22+
template <typename T>
23+
struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {};
24+
25+
template <typename T> const T& unwrap(const T& v) { return v; }
26+
template <typename T> const T& unwrap(const std::reference_wrapper<T>& v) {
27+
return static_cast<const T&>(v);
28+
}
29+
30+
class dynamic_arg_list {
31+
// Workaround for clang's -Wweak-vtables. Unlike for regular classes, for
32+
// templates it doesn't complain about inability to deduce single translation
33+
// unit for placing vtable. So storage_node_base is made a fake template.
34+
template <typename = void> struct node {
35+
virtual ~node() = default;
36+
std::unique_ptr<node<>> next;
37+
};
38+
39+
template <typename T> struct typed_node : node<> {
40+
T value;
41+
42+
template <typename Arg>
43+
FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {}
44+
45+
template <typename Char>
46+
FMT_CONSTEXPR typed_node(const basic_string_view<Char>& arg)
47+
: value(arg.data(), arg.size()) {}
48+
};
49+
50+
std::unique_ptr<node<>> head_;
51+
52+
public:
53+
template <typename T, typename Arg> const T& push(const Arg& arg) {
54+
auto new_node = std::unique_ptr<typed_node<T>>(new typed_node<T>(arg));
55+
auto& value = new_node->value;
56+
new_node->next = std::move(head_);
57+
head_ = std::move(new_node);
58+
return value;
59+
}
60+
};
61+
} // namespace detail
62+
63+
/**
64+
\rst
65+
A dynamic version of `fmt::format_arg_store`.
66+
It's equipped with a storage to potentially temporary objects which lifetimes
67+
could be shorter than the format arguments object.
68+
69+
It can be implicitly converted into `~fmt::basic_format_args` for passing
70+
into type-erased formatting functions such as `~fmt::vformat`.
71+
\endrst
72+
*/
73+
template <typename Context>
74+
class dynamic_format_arg_store
75+
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
76+
// Workaround a GCC template argument substitution bug.
77+
: public basic_format_args<Context>
78+
#endif
79+
{
80+
private:
81+
using char_type = typename Context::char_type;
82+
83+
template <typename T> struct need_copy {
84+
static constexpr detail::type mapped_type =
85+
detail::mapped_type_constant<T, Context>::value;
86+
87+
enum {
88+
value = !(detail::is_reference_wrapper<T>::value ||
89+
std::is_same<T, basic_string_view<char_type>>::value ||
90+
std::is_same<T, detail::std_string_view<char_type>>::value ||
91+
(mapped_type != detail::type::cstring_type &&
92+
mapped_type != detail::type::string_type &&
93+
mapped_type != detail::type::custom_type))
94+
};
95+
};
96+
97+
template <typename T>
98+
using stored_type = conditional_t<
99+
std::is_convertible<T, std::basic_string<char_type>>::value &&
100+
!detail::is_reference_wrapper<T>::value,
101+
std::basic_string<char_type>, T>;
102+
103+
// Storage of basic_format_arg must be contiguous.
104+
std::vector<basic_format_arg<Context>> data_;
105+
std::vector<detail::named_arg_info<char_type>> named_info_;
106+
107+
// Storage of arguments not fitting into basic_format_arg must grow
108+
// without relocation because items in data_ refer to it.
109+
detail::dynamic_arg_list dynamic_args_;
110+
111+
friend class basic_format_args<Context>;
112+
113+
unsigned long long get_types() const {
114+
return detail::is_unpacked_bit | data_.size() |
115+
(named_info_.empty()
116+
? 0ULL
117+
: static_cast<unsigned long long>(detail::has_named_args_bit));
118+
}
119+
120+
const basic_format_arg<Context>* data() const {
121+
return named_info_.empty() ? data_.data() : data_.data() + 1;
122+
}
123+
124+
template <typename T> void emplace_arg(const T& arg) {
125+
data_.emplace_back(detail::make_arg<Context>(arg));
126+
}
127+
128+
template <typename T>
129+
void emplace_arg(const detail::named_arg<char_type, T>& arg) {
130+
if (named_info_.empty()) {
131+
constexpr const detail::named_arg_info<char_type>* zero_ptr{nullptr};
132+
data_.insert(data_.begin(), {zero_ptr, 0});
133+
}
134+
data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value)));
135+
auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {
136+
data->pop_back();
137+
};
138+
std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)>
139+
guard{&data_, pop_one};
140+
named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)});
141+
data_[0].value_.named_args = {named_info_.data(), named_info_.size()};
142+
guard.release();
143+
}
144+
145+
public:
146+
constexpr dynamic_format_arg_store() = default;
147+
148+
/**
149+
\rst
150+
Adds an argument into the dynamic store for later passing to a formatting
151+
function.
152+
153+
Note that custom types and string types (but not string views) are copied
154+
into the store dynamically allocating memory if necessary.
155+
156+
**Example**::
157+
158+
fmt::dynamic_format_arg_store<fmt::format_context> store;
159+
store.push_back(42);
160+
store.push_back("abc");
161+
store.push_back(1.5f);
162+
std::string result = fmt::vformat("{} and {} and {}", store);
163+
\endrst
164+
*/
165+
template <typename T> void push_back(const T& arg) {
166+
if (detail::const_check(need_copy<T>::value))
167+
emplace_arg(dynamic_args_.push<stored_type<T>>(arg));
168+
else
169+
emplace_arg(detail::unwrap(arg));
170+
}
171+
172+
/**
173+
\rst
174+
Adds a reference to the argument into the dynamic store for later passing to
175+
a formatting function.
176+
177+
**Example**::
178+
179+
fmt::dynamic_format_arg_store<fmt::format_context> store;
180+
char band[] = "Rolling Stones";
181+
store.push_back(std::cref(band));
182+
band[9] = 'c'; // Changing str affects the output.
183+
std::string result = fmt::vformat("{}", store);
184+
// result == "Rolling Scones"
185+
\endrst
186+
*/
187+
template <typename T> void push_back(std::reference_wrapper<T> arg) {
188+
static_assert(
189+
need_copy<T>::value,
190+
"objects of built-in types and string views are always copied");
191+
emplace_arg(arg.get());
192+
}
193+
194+
/**
195+
Adds named argument into the dynamic store for later passing to a formatting
196+
function. ``std::reference_wrapper`` is supported to avoid copying of the
197+
argument. The name is always copied into the store.
198+
*/
199+
template <typename T>
200+
void push_back(const detail::named_arg<char_type, T>& arg) {
201+
const char_type* arg_name =
202+
dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str();
203+
if (detail::const_check(need_copy<T>::value)) {
204+
emplace_arg(
205+
fmt::arg(arg_name, dynamic_args_.push<stored_type<T>>(arg.value)));
206+
} else {
207+
emplace_arg(fmt::arg(arg_name, arg.value));
208+
}
209+
}
210+
211+
/** Erase all elements from the store */
212+
void clear() {
213+
data_.clear();
214+
named_info_.clear();
215+
dynamic_args_ = detail::dynamic_arg_list();
216+
}
217+
218+
/**
219+
\rst
220+
Reserves space to store at least *new_cap* arguments including
221+
*new_cap_named* named arguments.
222+
\endrst
223+
*/
224+
void reserve(size_t new_cap, size_t new_cap_named) {
225+
FMT_ASSERT(new_cap >= new_cap_named,
226+
"Set of arguments includes set of named arguments");
227+
data_.reserve(new_cap);
228+
named_info_.reserve(new_cap_named);
229+
}
230+
};
231+
232+
FMT_END_NAMESPACE
233+
234+
#endif // FMT_ARGS_H_

0 commit comments

Comments
 (0)