WPILibC++ 2024.3.2
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#include <functional> // std::reference_wrapper
12#include <memory> // std::unique_ptr
13#include <vector>
14
15#include "core.h"
16
18
19namespace detail {
20
21template <typename T> struct is_reference_wrapper : std::false_type {};
22template <typename T>
23struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {};
24
25template <typename T> const T& unwrap(const T& v) { return v; }
26template <typename T> const T& unwrap(const std::reference_wrapper<T>& v) {
27 return static_cast<const T&>(v);
28}
29
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>
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 */
73template <typename Context>
76 // Workaround a GCC template argument substitution bug.
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 =
86
87 enum {
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 &&
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.
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>
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
233
234#endif // FMT_ARGS_H_
you may not use this file except in compliance with the License You may obtain a copy of the License at software distributed under the License is distributed on an AS IS WITHOUT WARRANTIES OR CONDITIONS OF ANY either express or implied See the License for the specific language governing permissions and limitations under the License LLVM Exceptions to the Apache License As an if
Definition: ThirdPartyNotices.txt:289
Definition: core.h:1603
\rst A view of a collection of formatting arguments.
Definition: core.h:1857
An implementation of std::basic_string_view for pre-C++17.
Definition: core.h:398
Definition: args.h:30
const T & push(const Arg &arg)
Definition: args.h:53
Definition: core.h:1238
constexpr FMT_INLINE value()
Definition: core.h:1261
\rst A dynamic version of fmt::format_arg_store.
Definition: args.h:79
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:200
constexpr dynamic_format_arg_store()=default
void push_back(const T &arg)
\rst Adds an argument into the dynamic store for later passing to a formatting function.
Definition: args.h:165
void clear()
Erase all elements from the store.
Definition: args.h:212
void reserve(size_t new_cap, size_t new_cap_named)
\rst Reserves space to store at least new_cap arguments including new_cap_named* named arguments.
Definition: args.h:224
void push_back(std::reference_wrapper< T > arg)
Definition: args.h:187
#define FMT_ASSERT(condition, message)
Definition: core.h:336
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
\rst Returns a named argument to be used in a formatting function.
Definition: core.h:1841
#define FMT_GCC_VERSION
Definition: core.h:33
#define FMT_CONSTEXPR
Definition: core.h:105
#define FMT_BEGIN_NAMESPACE
Definition: core.h:174
typename std::conditional< B, T, F >::type conditional_t
Definition: core.h:258
#define FMT_END_NAMESPACE
Definition: core.h:177
detail namespace with internal helper functions
Definition: xchar.h:20
const T & unwrap(const T &v)
Definition: args.h:25
@ has_named_args_bit
Definition: core.h:1485
@ is_unpacked_bit
Definition: core.h:1484
type
Definition: core.h:556
constexpr FMT_INLINE auto const_check(T value) -> T
Definition: core.h:323
Definition: array.h:89
Definition: args.h:21
Definition: core.h:1137
Definition: core.h:581