RavEngine
Loading...
Searching...
No Matches
args.h
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_IMPORT_STD
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
19FMT_BEGIN_NAMESPACE
20
21namespace detail {
22
23template <typename T> struct is_reference_wrapper : std::false_type {};
24template <typename T>
25struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {};
26
27template <typename T> auto unwrap(const T& v) -> const T& { return v; }
28template <typename T>
29auto unwrap(const std::reference_wrapper<T>& v) -> const T& {
30 return static_cast<const T&>(v);
31}
32
34 // Workaround for clang's -Wweak-vtables. Unlike for regular classes, for
35 // templates it doesn't complain about inability to deduce single translation
36 // unit for placing vtable. So storage_node_base is made a fake template.
37 template <typename = void> struct node {
38 virtual ~node() = default;
39 std::unique_ptr<node<>> next;
40 };
41
42 template <typename T> struct typed_node : node<> {
43 T value;
44
45 template <typename Arg>
46 FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {}
47
48 template <typename Char>
49 FMT_CONSTEXPR typed_node(const basic_string_view<Char>& arg)
50 : value(arg.data(), arg.size()) {}
51 };
52
53 std::unique_ptr<node<>> head_;
54
55 public:
56 template <typename T, typename Arg> auto push(const Arg& arg) -> const T& {
57 auto new_node = std::unique_ptr<typed_node<T>>(new typed_node<T>(arg));
58 auto& value = new_node->value;
59 new_node->next = std::move(head_);
60 head_ = std::move(new_node);
61 return value;
62 }
63};
64} // namespace detail
65
76template <typename Context>
78#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
79 // Workaround a GCC template argument substitution bug.
81#endif
82{
83 private:
84 using char_type = typename Context::char_type;
85
86 template <typename T> struct need_copy {
87 static constexpr detail::type mapped_type =
89
90 enum {
92 std::is_same<T, basic_string_view<char_type>>::value ||
93 std::is_same<T, detail::std_string_view<char_type>>::value ||
94 (mapped_type != detail::type::cstring_type &&
95 mapped_type != detail::type::string_type &&
96 mapped_type != detail::type::custom_type))
97 };
98 };
99
100 template <typename T>
101 using stored_type = conditional_t<
102 std::is_convertible<T, std::basic_string<char_type>>::value &&
104 std::basic_string<char_type>, T>;
105
106 // Storage of basic_format_arg must be contiguous.
107 std::vector<basic_format_arg<Context>> data_;
108 std::vector<detail::named_arg_info<char_type>> named_info_;
109
110 // Storage of arguments not fitting into basic_format_arg must grow
111 // without relocation because items in data_ refer to it.
112 detail::dynamic_arg_list dynamic_args_;
113
114 friend class basic_format_args<Context>;
115
116 auto get_types() const -> unsigned long long {
117 return detail::is_unpacked_bit | data_.size() |
118 (named_info_.empty()
119 ? 0ULL
120 : static_cast<unsigned long long>(detail::has_named_args_bit));
121 }
122
123 auto data() const -> const basic_format_arg<Context>* {
124 return named_info_.empty() ? data_.data() : data_.data() + 1;
125 }
126
127 template <typename T> void emplace_arg(const T& arg) {
128 data_.emplace_back(detail::make_arg<Context>(arg));
129 }
130
131 template <typename T>
132 void emplace_arg(const detail::named_arg<char_type, T>& arg) {
133 if (named_info_.empty()) {
134 constexpr const detail::named_arg_info<char_type>* zero_ptr{nullptr};
135 data_.insert(data_.begin(), {zero_ptr, 0});
136 }
137 data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value)));
138 auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {
139 data->pop_back();
140 };
141 std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)>
142 guard{&data_, pop_one};
143 named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)});
144 data_[0].value_.named_args = {named_info_.data(), named_info_.size()};
145 guard.release();
146 }
147
148 public:
149 constexpr dynamic_format_arg_store() = default;
150
168 template <typename T> void push_back(const T& arg) {
169 if (detail::const_check(need_copy<T>::value))
170 emplace_arg(dynamic_args_.push<stored_type<T>>(arg));
171 else
172 emplace_arg(detail::unwrap(arg));
173 }
174
190 template <typename T> void push_back(std::reference_wrapper<T> arg) {
191 static_assert(
192 need_copy<T>::value,
193 "objects of built-in types and string views are always copied");
194 emplace_arg(arg.get());
195 }
196
202 template <typename T>
204 const char_type* arg_name =
205 dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str();
206 if (detail::const_check(need_copy<T>::value)) {
207 emplace_arg(
208 fmt::arg(arg_name, dynamic_args_.push<stored_type<T>>(arg.value)));
209 } else {
210 emplace_arg(fmt::arg(arg_name, arg.value));
211 }
212 }
213
215 void clear() {
216 data_.clear();
217 named_info_.clear();
218 dynamic_args_ = detail::dynamic_arg_list();
219 }
220
227 void reserve(size_t new_cap, size_t new_cap_named) {
228 FMT_ASSERT(new_cap >= new_cap_named,
229 "Set of arguments includes set of named arguments");
230 data_.reserve(new_cap);
231 named_info_.reserve(new_cap_named);
232 }
233};
234
235FMT_END_NAMESPACE
236
237#endif // FMT_ARGS_H_
Definition base.h:1707
Definition base.h:1827
Definition base.h:484
Definition args.h:33
Definition base.h:1310
Definition args.h:82
void push_back(const detail::named_arg< char_type, T > &arg)
Definition args.h:203
void push_back(const T &arg)
Definition args.h:168
void clear()
Definition args.h:215
void reserve(size_t new_cap, size_t new_cap_named)
Definition args.h:227
void push_back(std::reference_wrapper< T > arg)
Definition args.h:190
Definition args.h:23
Definition base.h:1264
Definition base.h:1258
Definition base.h:652