WPILibC++ 2025.2.1
Loading...
Searching...
No Matches
args.h
Go to the documentation of this file.
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#ifndef FMT_MODULE
12# include <functional> // std::reference_wrapper
13# include <memory> // std::unique_ptr
14# include <vector>
15#endif
16
17#include "format.h" // std_string_view
18
20namespace detail {
21
22template <typename T> struct is_reference_wrapper : std::false_type {};
23template <typename T>
24struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {};
25
26template <typename T> auto unwrap(const T& v) -> const T& { return v; }
27template <typename T>
28auto unwrap(const std::reference_wrapper<T>& v) -> const T& {
29 return static_cast<const T&>(v);
30}
31
32// node is defined outside dynamic_arg_list to workaround a C2504 bug in MSVC
33// 2022 (v17.10.0).
34//
35// Workaround for clang's -Wweak-vtables. Unlike for regular classes, for
36// templates it doesn't complain about inability to deduce single translation
37// unit for placing vtable. So node is made a fake template.
38template <typename = void> struct node {
39 virtual ~node() = default;
40 std::unique_ptr<node<>> next;
41};
42
44 template <typename T> struct typed_node : node<> {
45 T value;
46
47 template <typename Arg>
48 FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {}
49
50 template <typename Char>
52 : value(arg.data(), arg.size()) {}
53 };
54
55 std::unique_ptr<node<>> head_;
56
57 public:
58 template <typename T, typename Arg> auto push(const Arg& arg) -> const T& {
59 auto new_node = std::unique_ptr<typed_node<T>>(new typed_node<T>(arg));
60 auto& value = new_node->value;
61 new_node->next = std::move(head_);
62 head_ = std::move(new_node);
63 return value;
64 }
65};
66} // namespace detail
67
68/**
69 * A dynamic list of formatting arguments with storage.
70 *
71 * It can be implicitly converted into `fmt::basic_format_args` for passing
72 * into type-erased formatting functions such as `fmt::vformat`.
73 */
74template <typename Context> class dynamic_format_arg_store {
75 private:
76 using char_type = typename Context::char_type;
77
78 template <typename T> struct need_copy {
79 static constexpr detail::type mapped_type =
81
82 enum {
84 std::is_same<T, basic_string_view<char_type>>::value ||
85 std::is_same<T, detail::std_string_view<char_type>>::value ||
86 (mapped_type != detail::type::cstring_type &&
87 mapped_type != detail::type::string_type &&
88 mapped_type != detail::type::custom_type))
89 };
90 };
91
92 template <typename T>
93 using stored_t = conditional_t<
94 std::is_convertible<T, std::basic_string<char_type>>::value &&
96 std::basic_string<char_type>, T>;
97
98 // Storage of basic_format_arg must be contiguous.
99 std::vector<basic_format_arg<Context>> data_;
100 std::vector<detail::named_arg_info<char_type>> named_info_;
101
102 // Storage of arguments not fitting into basic_format_arg must grow
103 // without relocation because items in data_ refer to it.
105
106 friend class basic_format_args<Context>;
107
108 auto data() const -> const basic_format_arg<Context>* {
109 return named_info_.empty() ? data_.data() : data_.data() + 1;
110 }
111
112 template <typename T> void emplace_arg(const T& arg) {
113 data_.emplace_back(arg);
114 }
115
116 template <typename T>
117 void emplace_arg(const detail::named_arg<char_type, T>& arg) {
118 if (named_info_.empty())
119 data_.insert(data_.begin(), basic_format_arg<Context>(nullptr, 0));
120 data_.emplace_back(detail::unwrap(arg.value));
121 auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {
122 data->pop_back();
123 };
124 std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)>
125 guard{&data_, pop_one};
126 named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)});
127 data_[0] = {named_info_.data(), named_info_.size()};
128 guard.release();
129 }
130
131 public:
132 constexpr dynamic_format_arg_store() = default;
133
134 operator basic_format_args<Context>() const {
135 return basic_format_args<Context>(data(), static_cast<int>(data_.size()),
136 !named_info_.empty());
137 }
138
139 /**
140 * Adds an argument into the dynamic store for later passing to a formatting
141 * function.
142 *
143 * Note that custom types and string types (but not string views) are copied
144 * into the store dynamically allocating memory if necessary.
145 *
146 * **Example**:
147 *
148 * fmt::dynamic_format_arg_store<fmt::format_context> store;
149 * store.push_back(42);
150 * store.push_back("abc");
151 * store.push_back(1.5f);
152 * std::string result = fmt::vformat("{} and {} and {}", store);
153 */
154 template <typename T> void push_back(const T& arg) {
155 if (detail::const_check(need_copy<T>::value))
156 emplace_arg(dynamic_args_.push<stored_t<T>>(arg));
157 else
158 emplace_arg(detail::unwrap(arg));
159 }
160
161 /**
162 * Adds a reference to the argument into the dynamic store for later passing
163 * to a formatting function.
164 *
165 * **Example**:
166 *
167 * fmt::dynamic_format_arg_store<fmt::format_context> store;
168 * char band[] = "Rolling Stones";
169 * store.push_back(std::cref(band));
170 * band[9] = 'c'; // Changing str affects the output.
171 * std::string result = fmt::vformat("{}", store);
172 * // result == "Rolling Scones"
173 */
174 template <typename T> void push_back(std::reference_wrapper<T> arg) {
175 static_assert(
176 need_copy<T>::value,
177 "objects of built-in types and string views are always copied");
178 emplace_arg(arg.get());
179 }
180
181 /**
182 * Adds named argument into the dynamic store for later passing to a
183 * formatting function. `std::reference_wrapper` is supported to avoid
184 * copying of the argument. The name is always copied into the store.
185 */
186 template <typename T>
188 const char_type* arg_name =
189 dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str();
190 if (detail::const_check(need_copy<T>::value)) {
191 emplace_arg(
192 fmt::arg(arg_name, dynamic_args_.push<stored_t<T>>(arg.value)));
193 } else {
194 emplace_arg(fmt::arg(arg_name, arg.value));
195 }
196 }
197
198 /// Erase all elements from the store.
199 void clear() {
200 data_.clear();
201 named_info_.clear();
202 dynamic_args_ = {};
203 }
204
205 /// Reserves space to store at least `new_cap` arguments including
206 /// `new_cap_named` named arguments.
207 void reserve(size_t new_cap, size_t new_cap_named) {
208 FMT_ASSERT(new_cap >= new_cap_named,
209 "set of arguments includes set of named arguments");
210 data_.reserve(new_cap);
211 named_info_.reserve(new_cap_named);
212 }
213
214 /// Returns the number of elements in the store.
215 size_t size() const noexcept { return data_.size(); }
216};
217
219
220#endif // FMT_ARGS_H_
Definition base.h:2428
A view of a collection of formatting arguments.
Definition base.h:2509
An implementation of std::basic_string_view for pre-C++17.
Definition base.h:504
Definition args.h:43
auto push(const Arg &arg) -> const T &
Definition args.h:58
Definition base.h:2081
constexpr FMT_INLINE value()
Definition base.h:2104
A dynamic list of formatting arguments with storage.
Definition args.h:74
void push_back(const detail::named_arg< char_type, T > &arg)
Adds named argument into the dynamic store for later passing to a formatting function.
Definition args.h:187
size_t size() const noexcept
Returns the number of elements in the store.
Definition args.h:215
constexpr dynamic_format_arg_store()=default
void push_back(const T &arg)
Adds an argument into the dynamic store for later passing to a formatting function.
Definition args.h:154
void clear()
Erase all elements from the store.
Definition args.h:199
void reserve(size_t new_cap, size_t new_cap_named)
Reserves space to store at least new_cap arguments including new_cap_named named arguments.
Definition args.h:207
friend class basic_format_args< Context >
Definition args.h:106
void push_back(std::reference_wrapper< T > arg)
Adds a reference to the argument into the dynamic store for later passing to a formatting function.
Definition args.h:174
detail namespace with internal helper functions
Definition input_adapters.h:32
@ value
the parser finished reading a JSON value
FMT_ALWAYS_INLINE constexpr auto const_check(T val) -> T
Definition base.h:367
auto unwrap(const T &v) -> const T &
Definition args.h:26
type
Definition base.h:937
Implement std::hash so that hash_code can be used in STL containers.
Definition PointerIntPair.h:280
Definition args.h:22
Definition base.h:1020
Definition args.h:38
virtual ~node()=default
std::unique_ptr< node<> > next
Definition args.h:40
Definition base.h:962
#define FMT_ASSERT(condition, message)
Definition base.h:381
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Returns a named argument to be used in a formatting function.
Definition base.h:2775
#define FMT_CONSTEXPR
Definition base.h:113
#define FMT_BEGIN_NAMESPACE
Definition base.h:239
typename std::conditional< B, T, F >::type conditional_t
Definition base.h:299
#define FMT_END_NAMESPACE
Definition base.h:242