Add vendor/fmt
[lttng-tools.git] / src / vendor / fmt / ranges.h
CommitLineData
05aa7e19
JG
1// Formatting library for C++ - experimental range support
2//
3// Copyright (c) 2012 - present, Victor Zverovich
4// All rights reserved.
5//
6// For the license information refer to format.h.
7//
8// Copyright (c) 2018 - present, Remotion (Igor Schulz)
9// All Rights Reserved
10// {fmt} support for ranges, containers and types tuple interface.
11
12#ifndef FMT_RANGES_H_
13#define FMT_RANGES_H_
14
15#include <initializer_list>
16#include <tuple>
17#include <type_traits>
18
19#include "format.h"
20
21FMT_BEGIN_NAMESPACE
22
23namespace detail {
24
25template <typename RangeT, typename OutputIterator>
26OutputIterator copy(const RangeT& range, OutputIterator out) {
27 for (auto it = range.begin(), end = range.end(); it != end; ++it)
28 *out++ = *it;
29 return out;
30}
31
32template <typename OutputIterator>
33OutputIterator copy(const char* str, OutputIterator out) {
34 while (*str) *out++ = *str++;
35 return out;
36}
37
38template <typename OutputIterator>
39OutputIterator copy(char ch, OutputIterator out) {
40 *out++ = ch;
41 return out;
42}
43
44template <typename OutputIterator>
45OutputIterator copy(wchar_t ch, OutputIterator out) {
46 *out++ = ch;
47 return out;
48}
49
50// Returns true if T has a std::string-like interface, like std::string_view.
51template <typename T> class is_std_string_like {
52 template <typename U>
53 static auto check(U* p)
54 -> decltype((void)p->find('a'), p->length(), (void)p->data(), int());
55 template <typename> static void check(...);
56
57 public:
58 static FMT_CONSTEXPR_DECL const bool value =
59 is_string<T>::value ||
60 std::is_convertible<T, std_string_view<char>>::value ||
61 !std::is_void<decltype(check<T>(nullptr))>::value;
62};
63
64template <typename Char>
65struct is_std_string_like<fmt::basic_string_view<Char>> : std::true_type {};
66
67template <typename T> class is_map {
68 template <typename U> static auto check(U*) -> typename U::mapped_type;
69 template <typename> static void check(...);
70
71 public:
72#ifdef FMT_FORMAT_MAP_AS_LIST
73 static FMT_CONSTEXPR_DECL const bool value = false;
74#else
75 static FMT_CONSTEXPR_DECL const bool value =
76 !std::is_void<decltype(check<T>(nullptr))>::value;
77#endif
78};
79
80template <typename T> class is_set {
81 template <typename U> static auto check(U*) -> typename U::key_type;
82 template <typename> static void check(...);
83
84 public:
85#ifdef FMT_FORMAT_SET_AS_LIST
86 static FMT_CONSTEXPR_DECL const bool value = false;
87#else
88 static FMT_CONSTEXPR_DECL const bool value =
89 !std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;
90#endif
91};
92
93template <typename... Ts> struct conditional_helper {};
94
95template <typename T, typename _ = void> struct is_range_ : std::false_type {};
96
97#if !FMT_MSC_VER || FMT_MSC_VER > 1800
98
99# define FMT_DECLTYPE_RETURN(val) \
100 ->decltype(val) { return val; } \
101 static_assert( \
102 true, "") // This makes it so that a semicolon is required after the
103 // macro, which helps clang-format handle the formatting.
104
105// C array overload
106template <typename T, std::size_t N>
107auto range_begin(const T (&arr)[N]) -> const T* {
108 return arr;
109}
110template <typename T, std::size_t N>
111auto range_end(const T (&arr)[N]) -> const T* {
112 return arr + N;
113}
114
115template <typename T, typename Enable = void>
116struct has_member_fn_begin_end_t : std::false_type {};
117
118template <typename T>
119struct has_member_fn_begin_end_t<T, void_t<decltype(std::declval<T>().begin()),
120 decltype(std::declval<T>().end())>>
121 : std::true_type {};
122
123// Member function overload
124template <typename T>
125auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).begin());
126template <typename T>
127auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).end());
128
129// ADL overload. Only participates in overload resolution if member functions
130// are not found.
131template <typename T>
132auto range_begin(T&& rng)
133 -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
134 decltype(begin(static_cast<T&&>(rng)))> {
135 return begin(static_cast<T&&>(rng));
136}
137template <typename T>
138auto range_end(T&& rng) -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
139 decltype(end(static_cast<T&&>(rng)))> {
140 return end(static_cast<T&&>(rng));
141}
142
143template <typename T, typename Enable = void>
144struct has_const_begin_end : std::false_type {};
145template <typename T, typename Enable = void>
146struct has_mutable_begin_end : std::false_type {};
147
148template <typename T>
149struct has_const_begin_end<
150 T,
151 void_t<
152 decltype(detail::range_begin(std::declval<const remove_cvref_t<T>&>())),
153 decltype(detail::range_end(std::declval<const remove_cvref_t<T>&>()))>>
154 : std::true_type {};
155
156template <typename T>
157struct has_mutable_begin_end<
158 T, void_t<decltype(detail::range_begin(std::declval<T>())),
159 decltype(detail::range_end(std::declval<T>())),
160 enable_if_t<std::is_copy_constructible<T>::value>>>
161 : std::true_type {};
162
163template <typename T>
164struct is_range_<T, void>
165 : std::integral_constant<bool, (has_const_begin_end<T>::value ||
166 has_mutable_begin_end<T>::value)> {};
167# undef FMT_DECLTYPE_RETURN
168#endif
169
170// tuple_size and tuple_element check.
171template <typename T> class is_tuple_like_ {
172 template <typename U>
173 static auto check(U* p) -> decltype(std::tuple_size<U>::value, int());
174 template <typename> static void check(...);
175
176 public:
177 static FMT_CONSTEXPR_DECL const bool value =
178 !std::is_void<decltype(check<T>(nullptr))>::value;
179};
180
181// Check for integer_sequence
182#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
183template <typename T, T... N>
184using integer_sequence = std::integer_sequence<T, N...>;
185template <size_t... N> using index_sequence = std::index_sequence<N...>;
186template <size_t N> using make_index_sequence = std::make_index_sequence<N>;
187#else
188template <typename T, T... N> struct integer_sequence {
189 using value_type = T;
190
191 static FMT_CONSTEXPR size_t size() { return sizeof...(N); }
192};
193
194template <size_t... N> using index_sequence = integer_sequence<size_t, N...>;
195
196template <typename T, size_t N, T... Ns>
197struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
198template <typename T, T... Ns>
199struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
200
201template <size_t N>
202using make_index_sequence = make_integer_sequence<size_t, N>;
203#endif
204
205template <class Tuple, class F, size_t... Is>
206void for_each(index_sequence<Is...>, Tuple&& tup, F&& f) FMT_NOEXCEPT {
207 using std::get;
208 // using free function get<I>(T) now.
209 const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
210 (void)_; // blocks warnings
211}
212
213template <class T>
214FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value> get_indexes(
215 T const&) {
216 return {};
217}
218
219template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) {
220 const auto indexes = get_indexes(tup);
221 for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
222}
223
224template <typename Range>
225using value_type =
226 remove_cvref_t<decltype(*detail::range_begin(std::declval<Range>()))>;
227
228template <typename OutputIt> OutputIt write_delimiter(OutputIt out) {
229 *out++ = ',';
230 *out++ = ' ';
231 return out;
232}
233
234struct singleton {
235 unsigned char upper;
236 unsigned char lower_count;
237};
238
239inline auto is_printable(uint16_t x, const singleton* singletons,
240 size_t singletons_size,
241 const unsigned char* singleton_lowers,
242 const unsigned char* normal, size_t normal_size)
243 -> bool {
244 auto upper = x >> 8;
245 auto lower_start = 0;
246 for (size_t i = 0; i < singletons_size; ++i) {
247 auto s = singletons[i];
248 auto lower_end = lower_start + s.lower_count;
249 if (upper < s.upper) break;
250 if (upper == s.upper) {
251 for (auto j = lower_start; j < lower_end; ++j) {
252 if (singleton_lowers[j] == (x & 0xff)) return false;
253 }
254 }
255 lower_start = lower_end;
256 }
257
258 auto xsigned = static_cast<int>(x);
259 auto current = true;
260 for (size_t i = 0; i < normal_size; ++i) {
261 auto v = static_cast<int>(normal[i]);
262 auto len = (v & 0x80) != 0 ? (v & 0x7f) << 8 | normal[++i] : v;
263 xsigned -= len;
264 if (xsigned < 0) break;
265 current = !current;
266 }
267 return current;
268}
269
270// Returns true iff the code point cp is printable.
271// This code is generated by support/printable.py.
272inline auto is_printable(uint32_t cp) -> bool {
273 static constexpr singleton singletons0[] = {
274 {0x00, 1}, {0x03, 5}, {0x05, 6}, {0x06, 3}, {0x07, 6}, {0x08, 8},
275 {0x09, 17}, {0x0a, 28}, {0x0b, 25}, {0x0c, 20}, {0x0d, 16}, {0x0e, 13},
276 {0x0f, 4}, {0x10, 3}, {0x12, 18}, {0x13, 9}, {0x16, 1}, {0x17, 5},
277 {0x18, 2}, {0x19, 3}, {0x1a, 7}, {0x1c, 2}, {0x1d, 1}, {0x1f, 22},
278 {0x20, 3}, {0x2b, 3}, {0x2c, 2}, {0x2d, 11}, {0x2e, 1}, {0x30, 3},
279 {0x31, 2}, {0x32, 1}, {0xa7, 2}, {0xa9, 2}, {0xaa, 4}, {0xab, 8},
280 {0xfa, 2}, {0xfb, 5}, {0xfd, 4}, {0xfe, 3}, {0xff, 9},
281 };
282 static constexpr unsigned char singletons0_lower[] = {
283 0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, 0x58, 0x8b, 0x8c, 0x90,
284 0x1c, 0x1d, 0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0xfb, 0xfc, 0x2e, 0x2f, 0x3f,
285 0x5c, 0x5d, 0x5f, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91, 0x92, 0xa9, 0xb1,
286 0xba, 0xbb, 0xc5, 0xc6, 0xc9, 0xca, 0xde, 0xe4, 0xe5, 0xff, 0x00, 0x04,
287 0x11, 0x12, 0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a, 0x5d,
288 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf,
289 0xe4, 0xe5, 0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
290 0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d,
291 0xc9, 0xce, 0xcf, 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65, 0x8d,
292 0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x0d,
293 0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5,
294 0xd7, 0xf0, 0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf, 0xc5, 0xc7,
295 0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49,
296 0x4e, 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, 0xb6, 0xb7,
297 0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7,
298 0xfe, 0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, 0x1f, 0x6e,
299 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, 0xaf, 0xbb, 0xbc, 0xfa, 0x16,
300 0x17, 0x1e, 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e,
301 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f,
302 0x74, 0x75, 0x96, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf,
303 0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98, 0x30, 0x8f, 0x1f, 0xc0,
304 0xc1, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27,
305 0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91,
306 0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7,
307 0xfe, 0xff,
308 };
309 static constexpr singleton singletons1[] = {
310 {0x00, 6}, {0x01, 1}, {0x03, 1}, {0x04, 2}, {0x08, 8}, {0x09, 2},
311 {0x0a, 5}, {0x0b, 2}, {0x0e, 4}, {0x10, 1}, {0x11, 2}, {0x12, 5},
312 {0x13, 17}, {0x14, 1}, {0x15, 2}, {0x17, 2}, {0x19, 13}, {0x1c, 5},
313 {0x1d, 8}, {0x24, 1}, {0x6a, 3}, {0x6b, 2}, {0xbc, 2}, {0xd1, 2},
314 {0xd4, 12}, {0xd5, 9}, {0xd6, 2}, {0xd7, 2}, {0xda, 1}, {0xe0, 5},
315 {0xe1, 2}, {0xe8, 2}, {0xee, 32}, {0xf0, 4}, {0xf8, 2}, {0xf9, 2},
316 {0xfa, 2}, {0xfb, 1},
317 };
318 static constexpr unsigned char singletons1_lower[] = {
319 0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, 0x9e, 0x9f, 0x06, 0x07,
320 0x09, 0x36, 0x3d, 0x3e, 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x36,
321 0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, 0xbd, 0x35, 0xe0, 0x12, 0x87,
322 0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
323 0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5c, 0xb6, 0xb7, 0x1b,
324 0x1c, 0x07, 0x08, 0x0a, 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, 0xa9,
325 0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x66,
326 0x69, 0x8f, 0x92, 0x6f, 0x5f, 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27,
327 0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad, 0xba, 0xbc,
328 0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7,
329 0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f, 0xc5, 0xc6,
330 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c,
331 0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66,
332 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0,
333 0xae, 0xaf, 0x79, 0xcc, 0x6e, 0x6f, 0x93,
334 };
335 static constexpr unsigned char normal0[] = {
336 0x00, 0x20, 0x5f, 0x22, 0x82, 0xdf, 0x04, 0x82, 0x44, 0x08, 0x1b, 0x04,
337 0x06, 0x11, 0x81, 0xac, 0x0e, 0x80, 0xab, 0x35, 0x28, 0x0b, 0x80, 0xe0,
338 0x03, 0x19, 0x08, 0x01, 0x04, 0x2f, 0x04, 0x34, 0x04, 0x07, 0x03, 0x01,
339 0x07, 0x06, 0x07, 0x11, 0x0a, 0x50, 0x0f, 0x12, 0x07, 0x55, 0x07, 0x03,
340 0x04, 0x1c, 0x0a, 0x09, 0x03, 0x08, 0x03, 0x07, 0x03, 0x02, 0x03, 0x03,
341 0x03, 0x0c, 0x04, 0x05, 0x03, 0x0b, 0x06, 0x01, 0x0e, 0x15, 0x05, 0x3a,
342 0x03, 0x11, 0x07, 0x06, 0x05, 0x10, 0x07, 0x57, 0x07, 0x02, 0x07, 0x15,
343 0x0d, 0x50, 0x04, 0x43, 0x03, 0x2d, 0x03, 0x01, 0x04, 0x11, 0x06, 0x0f,
344 0x0c, 0x3a, 0x04, 0x1d, 0x25, 0x5f, 0x20, 0x6d, 0x04, 0x6a, 0x25, 0x80,
345 0xc8, 0x05, 0x82, 0xb0, 0x03, 0x1a, 0x06, 0x82, 0xfd, 0x03, 0x59, 0x07,
346 0x15, 0x0b, 0x17, 0x09, 0x14, 0x0c, 0x14, 0x0c, 0x6a, 0x06, 0x0a, 0x06,
347 0x1a, 0x06, 0x59, 0x07, 0x2b, 0x05, 0x46, 0x0a, 0x2c, 0x04, 0x0c, 0x04,
348 0x01, 0x03, 0x31, 0x0b, 0x2c, 0x04, 0x1a, 0x06, 0x0b, 0x03, 0x80, 0xac,
349 0x06, 0x0a, 0x06, 0x21, 0x3f, 0x4c, 0x04, 0x2d, 0x03, 0x74, 0x08, 0x3c,
350 0x03, 0x0f, 0x03, 0x3c, 0x07, 0x38, 0x08, 0x2b, 0x05, 0x82, 0xff, 0x11,
351 0x18, 0x08, 0x2f, 0x11, 0x2d, 0x03, 0x20, 0x10, 0x21, 0x0f, 0x80, 0x8c,
352 0x04, 0x82, 0x97, 0x19, 0x0b, 0x15, 0x88, 0x94, 0x05, 0x2f, 0x05, 0x3b,
353 0x07, 0x02, 0x0e, 0x18, 0x09, 0x80, 0xb3, 0x2d, 0x74, 0x0c, 0x80, 0xd6,
354 0x1a, 0x0c, 0x05, 0x80, 0xff, 0x05, 0x80, 0xdf, 0x0c, 0xee, 0x0d, 0x03,
355 0x84, 0x8d, 0x03, 0x37, 0x09, 0x81, 0x5c, 0x14, 0x80, 0xb8, 0x08, 0x80,
356 0xcb, 0x2a, 0x38, 0x03, 0x0a, 0x06, 0x38, 0x08, 0x46, 0x08, 0x0c, 0x06,
357 0x74, 0x0b, 0x1e, 0x03, 0x5a, 0x04, 0x59, 0x09, 0x80, 0x83, 0x18, 0x1c,
358 0x0a, 0x16, 0x09, 0x4c, 0x04, 0x80, 0x8a, 0x06, 0xab, 0xa4, 0x0c, 0x17,
359 0x04, 0x31, 0xa1, 0x04, 0x81, 0xda, 0x26, 0x07, 0x0c, 0x05, 0x05, 0x80,
360 0xa5, 0x11, 0x81, 0x6d, 0x10, 0x78, 0x28, 0x2a, 0x06, 0x4c, 0x04, 0x80,
361 0x8d, 0x04, 0x80, 0xbe, 0x03, 0x1b, 0x03, 0x0f, 0x0d,
362 };
363 static constexpr unsigned char normal1[] = {
364 0x5e, 0x22, 0x7b, 0x05, 0x03, 0x04, 0x2d, 0x03, 0x66, 0x03, 0x01, 0x2f,
365 0x2e, 0x80, 0x82, 0x1d, 0x03, 0x31, 0x0f, 0x1c, 0x04, 0x24, 0x09, 0x1e,
366 0x05, 0x2b, 0x05, 0x44, 0x04, 0x0e, 0x2a, 0x80, 0xaa, 0x06, 0x24, 0x04,
367 0x24, 0x04, 0x28, 0x08, 0x34, 0x0b, 0x01, 0x80, 0x90, 0x81, 0x37, 0x09,
368 0x16, 0x0a, 0x08, 0x80, 0x98, 0x39, 0x03, 0x63, 0x08, 0x09, 0x30, 0x16,
369 0x05, 0x21, 0x03, 0x1b, 0x05, 0x01, 0x40, 0x38, 0x04, 0x4b, 0x05, 0x2f,
370 0x04, 0x0a, 0x07, 0x09, 0x07, 0x40, 0x20, 0x27, 0x04, 0x0c, 0x09, 0x36,
371 0x03, 0x3a, 0x05, 0x1a, 0x07, 0x04, 0x0c, 0x07, 0x50, 0x49, 0x37, 0x33,
372 0x0d, 0x33, 0x07, 0x2e, 0x08, 0x0a, 0x81, 0x26, 0x52, 0x4e, 0x28, 0x08,
373 0x2a, 0x56, 0x1c, 0x14, 0x17, 0x09, 0x4e, 0x04, 0x1e, 0x0f, 0x43, 0x0e,
374 0x19, 0x07, 0x0a, 0x06, 0x48, 0x08, 0x27, 0x09, 0x75, 0x0b, 0x3f, 0x41,
375 0x2a, 0x06, 0x3b, 0x05, 0x0a, 0x06, 0x51, 0x06, 0x01, 0x05, 0x10, 0x03,
376 0x05, 0x80, 0x8b, 0x62, 0x1e, 0x48, 0x08, 0x0a, 0x80, 0xa6, 0x5e, 0x22,
377 0x45, 0x0b, 0x0a, 0x06, 0x0d, 0x13, 0x39, 0x07, 0x0a, 0x36, 0x2c, 0x04,
378 0x10, 0x80, 0xc0, 0x3c, 0x64, 0x53, 0x0c, 0x48, 0x09, 0x0a, 0x46, 0x45,
379 0x1b, 0x48, 0x08, 0x53, 0x1d, 0x39, 0x81, 0x07, 0x46, 0x0a, 0x1d, 0x03,
380 0x47, 0x49, 0x37, 0x03, 0x0e, 0x08, 0x0a, 0x06, 0x39, 0x07, 0x0a, 0x81,
381 0x36, 0x19, 0x80, 0xb7, 0x01, 0x0f, 0x32, 0x0d, 0x83, 0x9b, 0x66, 0x75,
382 0x0b, 0x80, 0xc4, 0x8a, 0xbc, 0x84, 0x2f, 0x8f, 0xd1, 0x82, 0x47, 0xa1,
383 0xb9, 0x82, 0x39, 0x07, 0x2a, 0x04, 0x02, 0x60, 0x26, 0x0a, 0x46, 0x0a,
384 0x28, 0x05, 0x13, 0x82, 0xb0, 0x5b, 0x65, 0x4b, 0x04, 0x39, 0x07, 0x11,
385 0x40, 0x05, 0x0b, 0x02, 0x0e, 0x97, 0xf8, 0x08, 0x84, 0xd6, 0x2a, 0x09,
386 0xa2, 0xf7, 0x81, 0x1f, 0x31, 0x03, 0x11, 0x04, 0x08, 0x81, 0x8c, 0x89,
387 0x04, 0x6b, 0x05, 0x0d, 0x03, 0x09, 0x07, 0x10, 0x93, 0x60, 0x80, 0xf6,
388 0x0a, 0x73, 0x08, 0x6e, 0x17, 0x46, 0x80, 0x9a, 0x14, 0x0c, 0x57, 0x09,
389 0x19, 0x80, 0x87, 0x81, 0x47, 0x03, 0x85, 0x42, 0x0f, 0x15, 0x85, 0x50,
390 0x2b, 0x80, 0xd5, 0x2d, 0x03, 0x1a, 0x04, 0x02, 0x81, 0x70, 0x3a, 0x05,
391 0x01, 0x85, 0x00, 0x80, 0xd7, 0x29, 0x4c, 0x04, 0x0a, 0x04, 0x02, 0x83,
392 0x11, 0x44, 0x4c, 0x3d, 0x80, 0xc2, 0x3c, 0x06, 0x01, 0x04, 0x55, 0x05,
393 0x1b, 0x34, 0x02, 0x81, 0x0e, 0x2c, 0x04, 0x64, 0x0c, 0x56, 0x0a, 0x80,
394 0xae, 0x38, 0x1d, 0x0d, 0x2c, 0x04, 0x09, 0x07, 0x02, 0x0e, 0x06, 0x80,
395 0x9a, 0x83, 0xd8, 0x08, 0x0d, 0x03, 0x0d, 0x03, 0x74, 0x0c, 0x59, 0x07,
396 0x0c, 0x14, 0x0c, 0x04, 0x38, 0x08, 0x0a, 0x06, 0x28, 0x08, 0x22, 0x4e,
397 0x81, 0x54, 0x0c, 0x15, 0x03, 0x03, 0x05, 0x07, 0x09, 0x19, 0x07, 0x07,
398 0x09, 0x03, 0x0d, 0x07, 0x29, 0x80, 0xcb, 0x25, 0x0a, 0x84, 0x06,
399 };
400 auto lower = static_cast<uint16_t>(cp);
401 if (cp < 0x10000) {
402 return is_printable(lower, singletons0,
403 sizeof(singletons0) / sizeof(*singletons0),
404 singletons0_lower, normal0, sizeof(normal0));
405 }
406 if (cp < 0x20000) {
407 return is_printable(lower, singletons1,
408 sizeof(singletons1) / sizeof(*singletons1),
409 singletons1_lower, normal1, sizeof(normal1));
410 }
411 if (0x2a6de <= cp && cp < 0x2a700) return false;
412 if (0x2b735 <= cp && cp < 0x2b740) return false;
413 if (0x2b81e <= cp && cp < 0x2b820) return false;
414 if (0x2cea2 <= cp && cp < 0x2ceb0) return false;
415 if (0x2ebe1 <= cp && cp < 0x2f800) return false;
416 if (0x2fa1e <= cp && cp < 0x30000) return false;
417 if (0x3134b <= cp && cp < 0xe0100) return false;
418 if (0xe01f0 <= cp && cp < 0x110000) return false;
419 return cp < 0x110000;
420}
421
422inline auto needs_escape(uint32_t cp) -> bool {
423 return cp < 0x20 || cp == 0x7f || cp == '"' || cp == '\\' ||
424 !is_printable(cp);
425}
426
427template <typename Char> struct find_escape_result {
428 const Char* begin;
429 const Char* end;
430 uint32_t cp;
431};
432
433template <typename Char>
434auto find_escape(const Char* begin, const Char* end)
435 -> find_escape_result<Char> {
436 for (; begin != end; ++begin) {
437 auto cp = static_cast<typename std::make_unsigned<Char>::type>(*begin);
438 if (sizeof(Char) == 1 && cp >= 0x80) continue;
439 if (needs_escape(cp)) return {begin, begin + 1, cp};
440 }
441 return {begin, nullptr, 0};
442}
443
444inline auto find_escape(const char* begin, const char* end)
445 -> find_escape_result<char> {
446 if (!is_utf8()) return find_escape<char>(begin, end);
447 auto result = find_escape_result<char>{end, nullptr, 0};
448 for_each_codepoint(string_view(begin, to_unsigned(end - begin)),
449 [&](uint32_t cp, string_view sv) {
450 if (needs_escape(cp)) {
451 result = {sv.begin(), sv.end(), cp};
452 return false;
453 }
454 return true;
455 });
456 return result;
457}
458
459template <typename Char, typename OutputIt>
460auto write_range_entry(OutputIt out, basic_string_view<Char> str) -> OutputIt {
461 *out++ = '"';
462 auto begin = str.begin(), end = str.end();
463 do {
464 auto escape = find_escape(begin, end);
465 out = copy_str<Char>(begin, escape.begin, out);
466 begin = escape.end;
467 if (!begin) break;
468 auto c = static_cast<Char>(escape.cp);
469 switch (escape.cp) {
470 case '\n':
471 *out++ = '\\';
472 c = 'n';
473 break;
474 case '\r':
475 *out++ = '\\';
476 c = 'r';
477 break;
478 case '\t':
479 *out++ = '\\';
480 c = 't';
481 break;
482 case '"':
483 FMT_FALLTHROUGH;
484 case '\\':
485 *out++ = '\\';
486 break;
487 default:
488 if (is_utf8()) {
489 if (escape.cp < 0x100) {
490 out = format_to(out, "\\x{:02x}", escape.cp);
491 continue;
492 }
493 if (escape.cp < 0x10000) {
494 out = format_to(out, "\\u{:04x}", escape.cp);
495 continue;
496 }
497 if (escape.cp < 0x110000) {
498 out = format_to(out, "\\U{:08x}", escape.cp);
499 continue;
500 }
501 }
502 for (Char escape_char : basic_string_view<Char>(
503 escape.begin, to_unsigned(escape.end - escape.begin))) {
504 out = format_to(
505 out, "\\x{:02x}",
506 static_cast<typename std::make_unsigned<Char>::type>(escape_char));
507 }
508 continue;
509 }
510 *out++ = c;
511 } while (begin != end);
512 *out++ = '"';
513 return out;
514}
515
516template <typename Char, typename OutputIt, typename T,
517 FMT_ENABLE_IF(std::is_convertible<T, std_string_view<char>>::value)>
518inline auto write_range_entry(OutputIt out, const T& str) -> OutputIt {
519 auto sv = std_string_view<Char>(str);
520 return write_range_entry<Char>(out, basic_string_view<Char>(sv));
521}
522
523template <typename Char, typename OutputIt, typename Arg,
524 FMT_ENABLE_IF(std::is_same<Arg, Char>::value)>
525OutputIt write_range_entry(OutputIt out, const Arg v) {
526 *out++ = '\'';
527 *out++ = v;
528 *out++ = '\'';
529 return out;
530}
531
532template <
533 typename Char, typename OutputIt, typename Arg,
534 FMT_ENABLE_IF(!is_std_string_like<typename std::decay<Arg>::type>::value &&
535 !std::is_same<Arg, Char>::value)>
536OutputIt write_range_entry(OutputIt out, const Arg& v) {
537 return write<Char>(out, v);
538}
539
540} // namespace detail
541
542template <typename T> struct is_tuple_like {
543 static FMT_CONSTEXPR_DECL const bool value =
544 detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
545};
546
547template <typename TupleT, typename Char>
548struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
549 private:
550 // C++11 generic lambda for format().
551 template <typename FormatContext> struct format_each {
552 template <typename T> void operator()(const T& v) {
553 if (i > 0) out = detail::write_delimiter(out);
554 out = detail::write_range_entry<Char>(out, v);
555 ++i;
556 }
557 int i;
558 typename FormatContext::iterator& out;
559 };
560
561 public:
562 template <typename ParseContext>
563 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
564 return ctx.begin();
565 }
566
567 template <typename FormatContext = format_context>
568 auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) {
569 auto out = ctx.out();
570 *out++ = '(';
571 detail::for_each(values, format_each<FormatContext>{0, out});
572 *out++ = ')';
573 return out;
574 }
575};
576
577template <typename T, typename Char> struct is_range {
578 static FMT_CONSTEXPR_DECL const bool value =
579 detail::is_range_<T>::value && !detail::is_std_string_like<T>::value &&
580 !detail::is_map<T>::value &&
581 !std::is_convertible<T, std::basic_string<Char>>::value &&
582 !std::is_constructible<detail::std_string_view<Char>, T>::value;
583};
584
585template <typename T, typename Char>
586struct formatter<
587 T, Char,
588 enable_if_t<
589 fmt::is_range<T, Char>::value
590// Workaround a bug in MSVC 2019 and earlier.
591#if !FMT_MSC_VER
592 && (is_formattable<detail::value_type<T>, Char>::value ||
593 detail::has_fallback_formatter<detail::value_type<T>, Char>::value)
594#endif
595 >> {
596 template <typename ParseContext>
597 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
598 return ctx.begin();
599 }
600
601 template <
602 typename FormatContext, typename U,
603 FMT_ENABLE_IF(
604 std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value,
605 const T, T>>::value)>
606 auto format(U& range, FormatContext& ctx) -> decltype(ctx.out()) {
607#ifdef FMT_DEPRECATED_BRACED_RANGES
608 Char prefix = '{';
609 Char postfix = '}';
610#else
611 Char prefix = detail::is_set<T>::value ? '{' : '[';
612 Char postfix = detail::is_set<T>::value ? '}' : ']';
613#endif
614 auto out = ctx.out();
615 *out++ = prefix;
616 int i = 0;
617 auto it = std::begin(range);
618 auto end = std::end(range);
619 for (; it != end; ++it) {
620 if (i > 0) out = detail::write_delimiter(out);
621 out = detail::write_range_entry<Char>(out, *it);
622 ++i;
623 }
624 *out++ = postfix;
625 return out;
626 }
627};
628
629template <typename T, typename Char>
630struct formatter<
631 T, Char,
632 enable_if_t<
633 detail::is_map<T>::value
634// Workaround a bug in MSVC 2019 and earlier.
635#if !FMT_MSC_VER
636 && (is_formattable<detail::value_type<T>, Char>::value ||
637 detail::has_fallback_formatter<detail::value_type<T>, Char>::value)
638#endif
639 >> {
640 template <typename ParseContext>
641 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
642 return ctx.begin();
643 }
644
645 template <
646 typename FormatContext, typename U,
647 FMT_ENABLE_IF(
648 std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value,
649 const T, T>>::value)>
650 auto format(U& map, FormatContext& ctx) -> decltype(ctx.out()) {
651 auto out = ctx.out();
652 *out++ = '{';
653 int i = 0;
654 for (const auto& item : map) {
655 if (i > 0) out = detail::write_delimiter(out);
656 out = detail::write_range_entry<Char>(out, item.first);
657 *out++ = ':';
658 *out++ = ' ';
659 out = detail::write_range_entry<Char>(out, item.second);
660 ++i;
661 }
662 *out++ = '}';
663 return out;
664 }
665};
666
667template <typename Char, typename... T> struct tuple_join_view : detail::view {
668 const std::tuple<T...>& tuple;
669 basic_string_view<Char> sep;
670
671 tuple_join_view(const std::tuple<T...>& t, basic_string_view<Char> s)
672 : tuple(t), sep{s} {}
673};
674
675template <typename Char, typename... T>
676using tuple_arg_join = tuple_join_view<Char, T...>;
677
678// Define FMT_TUPLE_JOIN_SPECIFIERS to enable experimental format specifiers
679// support in tuple_join. It is disabled by default because of issues with
680// the dynamic width and precision.
681#ifndef FMT_TUPLE_JOIN_SPECIFIERS
682# define FMT_TUPLE_JOIN_SPECIFIERS 0
683#endif
684
685template <typename Char, typename... T>
686struct formatter<tuple_join_view<Char, T...>, Char> {
687 template <typename ParseContext>
688 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
689 return do_parse(ctx, std::integral_constant<size_t, sizeof...(T)>());
690 }
691
692 template <typename FormatContext>
693 auto format(const tuple_join_view<Char, T...>& value,
694 FormatContext& ctx) const -> typename FormatContext::iterator {
695 return do_format(value, ctx,
696 std::integral_constant<size_t, sizeof...(T)>());
697 }
698
699 private:
700 std::tuple<formatter<typename std::decay<T>::type, Char>...> formatters_;
701
702 template <typename ParseContext>
703 FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
704 std::integral_constant<size_t, 0>)
705 -> decltype(ctx.begin()) {
706 return ctx.begin();
707 }
708
709 template <typename ParseContext, size_t N>
710 FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
711 std::integral_constant<size_t, N>)
712 -> decltype(ctx.begin()) {
713 auto end = ctx.begin();
714#if FMT_TUPLE_JOIN_SPECIFIERS
715 end = std::get<sizeof...(T) - N>(formatters_).parse(ctx);
716 if (N > 1) {
717 auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());
718 if (end != end1)
719 FMT_THROW(format_error("incompatible format specs for tuple elements"));
720 }
721#endif
722 return end;
723 }
724
725 template <typename FormatContext>
726 auto do_format(const tuple_join_view<Char, T...>&, FormatContext& ctx,
727 std::integral_constant<size_t, 0>) const ->
728 typename FormatContext::iterator {
729 return ctx.out();
730 }
731
732 template <typename FormatContext, size_t N>
733 auto do_format(const tuple_join_view<Char, T...>& value, FormatContext& ctx,
734 std::integral_constant<size_t, N>) const ->
735 typename FormatContext::iterator {
736 auto out = std::get<sizeof...(T) - N>(formatters_)
737 .format(std::get<sizeof...(T) - N>(value.tuple), ctx);
738 if (N > 1) {
739 out = std::copy(value.sep.begin(), value.sep.end(), out);
740 ctx.advance_to(out);
741 return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
742 }
743 return out;
744 }
745};
746
747FMT_MODULE_EXPORT_BEGIN
748
749/**
750 \rst
751 Returns an object that formats `tuple` with elements separated by `sep`.
752
753 **Example**::
754
755 std::tuple<int, char> t = {1, 'a'};
756 fmt::print("{}", fmt::join(t, ", "));
757 // Output: "1, a"
758 \endrst
759 */
760template <typename... T>
761FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep)
762 -> tuple_join_view<char, T...> {
763 return {tuple, sep};
764}
765
766template <typename... T>
767FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple,
768 basic_string_view<wchar_t> sep)
769 -> tuple_join_view<wchar_t, T...> {
770 return {tuple, sep};
771}
772
773/**
774 \rst
775 Returns an object that formats `initializer_list` with elements separated by
776 `sep`.
777
778 **Example**::
779
780 fmt::print("{}", fmt::join({1, 2, 3}, ", "));
781 // Output: "1, 2, 3"
782 \endrst
783 */
784template <typename T>
785auto join(std::initializer_list<T> list, string_view sep)
786 -> join_view<const T*, const T*> {
787 return join(std::begin(list), std::end(list), sep);
788}
789
790FMT_MODULE_EXPORT_END
791FMT_END_NAMESPACE
792
793#endif // FMT_RANGES_H_
This page took 0.049779 seconds and 4 git commands to generate.