Bitcoin ABC 0.33.12
P2P Digital Currency
tinyformat.h
Go to the documentation of this file.
1// tinyformat.h
2// Copyright (C) 2011, Chris Foster [chris42f (at) gmail (d0t) com]
3//
4// Boost Software License - Version 1.0
5//
6// Permission is hereby granted, free of charge, to any person or organization
7// obtaining a copy of the software and accompanying documentation covered by
8// this license (the "Software") to use, reproduce, display, distribute,
9// execute, and transmit the Software, and to prepare derivative works of the
10// Software, and to permit third-parties to whom the Software is furnished to
11// do so, all subject to the following:
12//
13// The copyright notices in the Software and this entire statement, including
14// the above license grant, this restriction and the following disclaimer,
15// must be included in all copies of the Software, in whole or in part, and
16// all derivative works of the Software, unless such copies or derivative
17// works are solely in the form of machine-executable object code generated by
18// a source language processor.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
23// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
24// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
25// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26// DEALINGS IN THE SOFTWARE.
27
28//------------------------------------------------------------------------------
29// Tinyformat: A minimal type safe printf replacement
30//
31// tinyformat.h is a type safe printf replacement library in a single C++
32// header file. Design goals include:
33//
34// * Type safety and extensibility for user defined types.
35// * C99 printf() compatibility, to the extent possible using std::ostream
36// * POSIX extension for positional arguments
37// * Simplicity and minimalism. A single header file to include and distribute
38// with your projects.
39// * Augment rather than replace the standard stream formatting mechanism
40// * C++98 support, with optional C++11 niceties
41//
42//
43// Main interface example usage
44// ----------------------------
45//
46// To print a date to std::cout for American usage:
47//
48// std::string weekday = "Wednesday";
49// const char* month = "July";
50// size_t day = 27;
51// long hour = 14;
52// int min = 44;
53//
54// tfm::printf("%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min);
55//
56// POSIX extension for positional arguments is available.
57// The ability to rearrange formatting arguments is an important feature
58// for localization because the word order may vary in different languages.
59//
60// Previous example for German usage. Arguments are reordered:
61//
62// tfm::printf("%1$s, %3$d. %2$s, %4$d:%5$.2d\n", weekday, month, day, hour,
63// min);
64//
65// The strange types here emphasize the type safety of the interface; it is
66// possible to print a std::string using the "%s" conversion, and a
67// size_t using the "%d" conversion. A similar result could be achieved
68// using either of the tfm::format() functions. One prints on a user provided
69// stream:
70//
71// tfm::format(std::cerr, "%s, %s %d, %.2d:%.2d\n",
72// weekday, month, day, hour, min);
73//
74// The other returns a std::string:
75//
76// std::string date = tfm::format("%s, %s %d, %.2d:%.2d\n",
77// weekday, month, day, hour, min);
78// std::cout << date;
79//
80// These are the three primary interface functions. There is also a
81// convenience function printfln() which appends a newline to the usual result
82// of printf() for super simple logging.
83//
84//
85// User defined format functions
86// -----------------------------
87//
88// Simulating variadic templates in C++98 is pretty painful since it requires
89// writing out the same function for each desired number of arguments. To make
90// this bearable tinyformat comes with a set of macros which are used
91// internally to generate the API, but which may also be used in user code.
92//
93// The three macros TINYFORMAT_ARGTYPES(n), TINYFORMAT_VARARGS(n) and
94// TINYFORMAT_PASSARGS(n) will generate a list of n argument types,
95// type/name pairs and argument names respectively when called with an integer
96// n between 1 and 16. We can use these to define a macro which generates the
97// desired user defined function with n arguments. To generate all 16 user
98// defined function bodies, use the macro TINYFORMAT_FOREACH_ARGNUM. For an
99// example, see the implementation of printf() at the end of the source file.
100//
101// Sometimes it's useful to be able to pass a list of format arguments through
102// to a non-template function. The FormatList class is provided as a way to do
103// this by storing the argument list in a type-opaque way. Continuing the
104// example from above, we construct a FormatList using makeFormatList():
105//
106// FormatListRef formatList = tfm::makeFormatList(weekday, month, day, hour,
107// min);
108//
109// The format list can now be passed into any non-template function and used
110// via a call to the vformat() function:
111//
112// tfm::vformat(std::cout, "%s, %s %d, %.2d:%.2d\n", formatList);
113//
114//
115// Additional API information
116// --------------------------
117//
118// Error handling: Define TINYFORMAT_ERROR to customize the error handling for
119// format strings which are unsupported or have the wrong number of format
120// specifiers (calls assert() by default).
121//
122// User defined types: Uses operator<< for user defined types by default.
123// Overload formatValue() for more control.
124
125#ifndef TINYFORMAT_H_INCLUDED
126#define TINYFORMAT_H_INCLUDED
127
128namespace tinyformat {}
129//------------------------------------------------------------------------------
130// Config section. Customize to your liking!
131
132// Namespace alias to encourage brevity
133namespace tfm = tinyformat;
134
135// Error handling; calls assert() by default.
136#define TINYFORMAT_ERROR(reasonString) \
137 throw tinyformat::format_error(reasonString)
138
139// Define for C++11 variadic templates which make the code shorter & more
140// general. If you don't define this, C++11 support is autodetected below.
141#define TINYFORMAT_USE_VARIADIC_TEMPLATES
142
143//------------------------------------------------------------------------------
144// Implementation details.
145#include <algorithm>
146#include <cstdint>
147#include <iostream>
148#include <sstream>
149#include <stdexcept> // Added for Bitcoin
150
151#ifndef TINYFORMAT_ASSERT
152#include <cassert>
153#define TINYFORMAT_ASSERT(cond) assert(cond)
154#endif
155
156#ifndef TINYFORMAT_ERROR
157#include <cassert>
158#define TINYFORMAT_ERROR(reason) assert(0 && reason)
159#endif
160
161#if !defined(TINYFORMAT_USE_VARIADIC_TEMPLATES) && \
162 !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES)
163#ifdef __GXX_EXPERIMENTAL_CXX0X__
164#define TINYFORMAT_USE_VARIADIC_TEMPLATES
165#endif
166#endif
167
168#if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
169// std::showpos is broken on old libstdc++ as provided with macOS. See
170// http://gcc.gnu.org/ml/libstdc++/2007-11/msg00075.html
171#define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
172#endif
173
174#ifdef __APPLE__
175// Workaround macOS linker warning: Xcode uses different default symbol
176// visibilities for static libs vs executables (see issue #25)
177#define TINYFORMAT_HIDDEN __attribute__((visibility("hidden")))
178#else
179#define TINYFORMAT_HIDDEN
180#endif
181
182namespace tinyformat {
183
184// Added for Bitcoin
185class format_error : public std::runtime_error {
186public:
187 explicit format_error(const std::string &what) : std::runtime_error(what) {}
188};
189
190//------------------------------------------------------------------------------
191namespace detail {
192
193 // Test whether type T1 is convertible to type T2
194 template <typename T1, typename T2> struct is_convertible {
195 private:
196 // two types of different size
197 struct fail {
198 char dummy[2];
199 };
200 struct succeed {
201 char dummy;
202 };
203 // Try to convert a T1 to a T2 by plugging into tryConvert
204 static fail tryConvert(...);
205 static succeed tryConvert(const T2 &);
206 static const T1 &makeT1();
207
208 public:
209#ifdef _MSC_VER
210// Disable spurious loss of precision warnings in tryConvert(makeT1())
211#pragma warning(push)
212#pragma warning(disable : 4244)
213#pragma warning(disable : 4267)
214#endif
215 // Standard trick: the (...) version of tryConvert will be chosen from
216 // the overload set only if the version taking a T2 doesn't match. Then
217 // we compare the sizes of the return types to check which function
218 // matched. Very neat, in a disgusting kind of way :)
219 static const bool value =
220 sizeof(tryConvert(makeT1())) == sizeof(succeed);
221#ifdef _MSC_VER
222#pragma warning(pop)
223#endif
224 };
225
226 // Detect when a type is not a wchar_t string
227 template <typename T> struct is_wchar {
229 };
230 template <> struct is_wchar<wchar_t *> {};
231 template <> struct is_wchar<const wchar_t *> {};
232 template <int n> struct is_wchar<const wchar_t[n]> {};
233 template <int n> struct is_wchar<wchar_t[n]> {};
234
235 // Format the value by casting to type fmtT. This default implementation
236 // should never be called.
237 template <typename T, typename fmtT,
238 bool convertible = is_convertible<T, fmtT>::value>
240 static void invoke(std::ostream & /*out*/, const T & /*value*/) {
242 }
243 };
244 // Specialized version for types that can actually be converted to fmtT, as
245 // indicated by the "convertible" template parameter.
246 template <typename T, typename fmtT>
247 struct formatValueAsType<T, fmtT, true> {
248 static void invoke(std::ostream &out, const T &value) {
249 out << static_cast<fmtT>(value);
250 }
251 };
252
253#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
254 template <typename T, bool convertible = is_convertible<T, int>::value>
255 struct formatZeroIntegerWorkaround {
256 static bool invoke(std::ostream & , const T & ) {
257 return false;
258 }
259 };
260 template <typename T> struct formatZeroIntegerWorkaround<T, true> {
261 static bool invoke(std::ostream &out, const T &value) {
262 if (static_cast<int>(value) == 0 &&
263 out.flags() & std::ios::showpos) {
264 out << "+0";
265 return true;
266 }
267 return false;
268 }
269 };
270#endif // TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
271
272 // Convert an arbitrary type to integer. The version with convertible=false
273 // throws an error.
274 template <typename T, bool convertible = is_convertible<T, int>::value>
276 static int invoke(const T & /*value*/) {
277 TINYFORMAT_ERROR("tinyformat: Cannot convert from argument type to "
278 "integer for use as variable width or precision");
279 return 0;
280 }
281 };
282 // Specialization for convertToInt when conversion is possible
283 template <typename T> struct convertToInt<T, true> {
284 static int invoke(const T &value) { return static_cast<int>(value); }
285 };
286
287 // Format at most ntrunc characters to the given stream.
288 template <typename T>
289 inline void formatTruncated(std::ostream &out, const T &value, int ntrunc) {
290 std::ostringstream tmp;
291 tmp << value;
292 std::string result = tmp.str();
293 out.write(result.c_str(),
294 (std::min)(ntrunc, static_cast<int>(result.size())));
295 }
296#define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type) \
297 inline void formatTruncated(std::ostream &out, type *value, int ntrunc) { \
298 std::streamsize len = 0; \
299 while (len < ntrunc && value[len] != 0) \
300 ++len; \
301 out.write(value, len); \
302 }
303 // Overload for const char* and char*. Could overload for signed & unsigned
304 // char too, but these are technically unneeded for printf compatibility.
307#undef TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR
308
309} // namespace detail
310
311//------------------------------------------------------------------------------
312// Variable formatting functions. May be overridden for user-defined types if
313// desired.
314
326template <typename T>
327inline void formatValue(std::ostream &out, const char * /*fmtBegin*/,
328 const char *fmtEnd, int ntrunc, const T &value) {
329#ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS
330 // Since we don't support printing of wchar_t using "%ls", make it fail at
331 // compile time in preference to printing as a void* at runtime.
333 DummyType;
334 (void)DummyType(); // avoid unused type warning with gcc-4.8
335#endif
336 // The mess here is to support the %c and %p conversions: if these
337 // conversions are active we try to convert the type to a char or const
338 // void* respectively and format that instead of the value itself. For the
339 // %p conversion it's important to avoid dereferencing the pointer, which
340 // could otherwise lead to a crash when printing a dangling (const char*).
341 const bool canConvertToChar = detail::is_convertible<T, char>::value;
342 const bool canConvertToVoidPtr =
344 if (canConvertToChar && *(fmtEnd - 1) == 'c')
346 else if (canConvertToVoidPtr && *(fmtEnd - 1) == 'p')
348#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
349 else if (detail::formatZeroIntegerWorkaround<T>::invoke(out, value))
350 ;
351#endif
352 else if (ntrunc >= 0) {
353 // Take care not to overread C strings in truncating conversions like
354 // "%.4s" where at most 4 characters may be read.
355 detail::formatTruncated(out, value, ntrunc);
356 } else
357 out << value;
358}
359
360// Overloaded version for char types to support printing as an integer
361#define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \
362 inline void formatValue(std::ostream &out, const char * /*fmtBegin*/, \
363 const char *fmtEnd, int , charType value) { \
364 switch (*(fmtEnd - 1)) { \
365 case 'u': \
366 case 'd': \
367 case 'i': \
368 case 'o': \
369 case 'X': \
370 case 'x': \
371 out << static_cast<int>(value); \
372 break; \
373 default: \
374 out << value; \
375 break; \
376 } \
377 }
378// per 3.9.1: char, signed char and uint8_t are all distinct types
382#undef TINYFORMAT_DEFINE_FORMATVALUE_CHAR
383
384//------------------------------------------------------------------------------
385// Tools for emulating variadic templates in C++98. The basic idea here is
386// stolen from the boost preprocessor metaprogramming library and cut down to
387// be just general enough for what we need.
388
389#define TINYFORMAT_ARGTYPES(n) TINYFORMAT_ARGTYPES_##n
390#define TINYFORMAT_VARARGS(n) TINYFORMAT_VARARGS_##n
391#define TINYFORMAT_PASSARGS(n) TINYFORMAT_PASSARGS_##n
392#define TINYFORMAT_PASSARGS_TAIL(n) TINYFORMAT_PASSARGS_TAIL_##n
393
394// To keep it as transparent as possible, the macros below have been generated
395// using python via the excellent cog.py code generation script. This avoids
396// the need for a bunch of complex (but more general) preprocessor tricks as
397// used in boost.preprocessor.
398//
399// To rerun the code generation in place, use `cog.py -r tinyformat.h`
400// (see http://nedbatchelder.com/code/cog). Alternatively you can just create
401// extra versions by hand.
402
403/*[[[cog
404maxParams = 16
405
406def makeCommaSepLists(lineTemplate, elemTemplate, startInd=1):
407 for j in range(startInd,maxParams+1):
408 list = ', '.join([elemTemplate % {'i':i} for i in range(startInd,j+1)])
409 cog.outl(lineTemplate % {'j':j, 'list':list})
410
411makeCommaSepLists('#define TINYFORMAT_ARGTYPES_%(j)d %(list)s',
412 'class T%(i)d')
413
414cog.outl()
415makeCommaSepLists('#define TINYFORMAT_VARARGS_%(j)d %(list)s',
416 'const T%(i)d& v%(i)d')
417
418cog.outl()
419makeCommaSepLists('#define TINYFORMAT_PASSARGS_%(j)d %(list)s', 'v%(i)d')
420
421cog.outl()
422cog.outl('#define TINYFORMAT_PASSARGS_TAIL_1')
423makeCommaSepLists('#define TINYFORMAT_PASSARGS_TAIL_%(j)d , %(list)s',
424 'v%(i)d', startInd = 2)
425
426cog.outl()
427cog.outl('#define TINYFORMAT_FOREACH_ARGNUM(m) \\\n ' +
428 ' '.join(['m(%d)' % (j,) for j in range(1,maxParams+1)]))
429]]]*/
430#define TINYFORMAT_ARGTYPES_1 class T1
431#define TINYFORMAT_ARGTYPES_2 class T1, class T2
432#define TINYFORMAT_ARGTYPES_3 class T1, class T2, class T3
433#define TINYFORMAT_ARGTYPES_4 class T1, class T2, class T3, class T4
434#define TINYFORMAT_ARGTYPES_5 class T1, class T2, class T3, class T4, class T5
435#define TINYFORMAT_ARGTYPES_6 \
436 class T1, class T2, class T3, class T4, class T5, class T6
437#define TINYFORMAT_ARGTYPES_7 \
438 class T1, class T2, class T3, class T4, class T5, class T6, class T7
439#define TINYFORMAT_ARGTYPES_8 \
440 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
441 class T8
442#define TINYFORMAT_ARGTYPES_9 \
443 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
444 class T8, class T9
445#define TINYFORMAT_ARGTYPES_10 \
446 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
447 class T8, class T9, class T10
448#define TINYFORMAT_ARGTYPES_11 \
449 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
450 class T8, class T9, class T10, class T11
451#define TINYFORMAT_ARGTYPES_12 \
452 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
453 class T8, class T9, class T10, class T11, class T12
454#define TINYFORMAT_ARGTYPES_13 \
455 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
456 class T8, class T9, class T10, class T11, class T12, class T13
457#define TINYFORMAT_ARGTYPES_14 \
458 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
459 class T8, class T9, class T10, class T11, class T12, class T13, \
460 class T14
461#define TINYFORMAT_ARGTYPES_15 \
462 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
463 class T8, class T9, class T10, class T11, class T12, class T13, \
464 class T14, class T15
465#define TINYFORMAT_ARGTYPES_16 \
466 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
467 class T8, class T9, class T10, class T11, class T12, class T13, \
468 class T14, class T15, class T16
469
470#define TINYFORMAT_VARARGS_1 const T1 &v1
471#define TINYFORMAT_VARARGS_2 const T1 &v1, const T2 &v2
472#define TINYFORMAT_VARARGS_3 const T1 &v1, const T2 &v2, const T3 &v3
473#define TINYFORMAT_VARARGS_4 \
474 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4
475#define TINYFORMAT_VARARGS_5 \
476 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5
477#define TINYFORMAT_VARARGS_6 \
478 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
479 const T6 &v6
480#define TINYFORMAT_VARARGS_7 \
481 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
482 const T6 &v6, const T7 &v7
483#define TINYFORMAT_VARARGS_8 \
484 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
485 const T6 &v6, const T7 &v7, const T8 &v8
486#define TINYFORMAT_VARARGS_9 \
487 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
488 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9
489#define TINYFORMAT_VARARGS_10 \
490 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
491 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10
492#define TINYFORMAT_VARARGS_11 \
493 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
494 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
495 const T10 &v10, const T11 &v11
496#define TINYFORMAT_VARARGS_12 \
497 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
498 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
499 const T10 &v10, const T11 &v11, const T12 &v12
500#define TINYFORMAT_VARARGS_13 \
501 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
502 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
503 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13
504#define TINYFORMAT_VARARGS_14 \
505 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
506 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
507 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, \
508 const T14 &v14
509#define TINYFORMAT_VARARGS_15 \
510 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
511 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
512 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, \
513 const T14 &v14, const T15 &v15
514#define TINYFORMAT_VARARGS_16 \
515 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
516 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
517 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, \
518 const T14 &v14, const T15 &v15, const T16 &v16
519
520#define TINYFORMAT_PASSARGS_1 v1
521#define TINYFORMAT_PASSARGS_2 v1, v2
522#define TINYFORMAT_PASSARGS_3 v1, v2, v3
523#define TINYFORMAT_PASSARGS_4 v1, v2, v3, v4
524#define TINYFORMAT_PASSARGS_5 v1, v2, v3, v4, v5
525#define TINYFORMAT_PASSARGS_6 v1, v2, v3, v4, v5, v6
526#define TINYFORMAT_PASSARGS_7 v1, v2, v3, v4, v5, v6, v7
527#define TINYFORMAT_PASSARGS_8 v1, v2, v3, v4, v5, v6, v7, v8
528#define TINYFORMAT_PASSARGS_9 v1, v2, v3, v4, v5, v6, v7, v8, v9
529#define TINYFORMAT_PASSARGS_10 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10
530#define TINYFORMAT_PASSARGS_11 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
531#define TINYFORMAT_PASSARGS_12 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
532#define TINYFORMAT_PASSARGS_13 \
533 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
534#define TINYFORMAT_PASSARGS_14 \
535 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
536#define TINYFORMAT_PASSARGS_15 \
537 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
538#define TINYFORMAT_PASSARGS_16 \
539 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
540
541#define TINYFORMAT_PASSARGS_TAIL_1
542#define TINYFORMAT_PASSARGS_TAIL_2 , v2
543#define TINYFORMAT_PASSARGS_TAIL_3 , v2, v3
544#define TINYFORMAT_PASSARGS_TAIL_4 , v2, v3, v4
545#define TINYFORMAT_PASSARGS_TAIL_5 , v2, v3, v4, v5
546#define TINYFORMAT_PASSARGS_TAIL_6 , v2, v3, v4, v5, v6
547#define TINYFORMAT_PASSARGS_TAIL_7 , v2, v3, v4, v5, v6, v7
548#define TINYFORMAT_PASSARGS_TAIL_8 , v2, v3, v4, v5, v6, v7, v8
549#define TINYFORMAT_PASSARGS_TAIL_9 , v2, v3, v4, v5, v6, v7, v8, v9
550#define TINYFORMAT_PASSARGS_TAIL_10 , v2, v3, v4, v5, v6, v7, v8, v9, v10
551#define TINYFORMAT_PASSARGS_TAIL_11 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
552#define TINYFORMAT_PASSARGS_TAIL_12 \
553 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
554#define TINYFORMAT_PASSARGS_TAIL_13 \
555 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
556#define TINYFORMAT_PASSARGS_TAIL_14 \
557 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
558#define TINYFORMAT_PASSARGS_TAIL_15 \
559 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
560#define TINYFORMAT_PASSARGS_TAIL_16 \
561 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
562
563#define TINYFORMAT_FOREACH_ARGNUM(m) \
564 m(1) m(2) m(3) m(4) m(5) m(6) m(7) m(8) m(9) m(10) m(11) m(12) m(13) m(14) \
565 m(15) m(16)
566//[[[end]]]
567
568namespace detail {
569
570 // Type-opaque holder for an argument to format(), with associated actions
571 // on the type held as explicit function pointers. This allows FormatArg's
572 // for each argument to be allocated as a homogeneous array inside
573 // FormatList whereas a naive implementation based on inheritance does not.
574 class FormatArg {
575 public:
576 FormatArg() = default;
577
578 template <typename T>
579 explicit FormatArg(const T &value)
580 : m_value(static_cast<const void *>(&value)),
582
583 void format(std::ostream &out, const char *fmtBegin, const char *fmtEnd,
584 int ntrunc) const {
587 m_formatImpl(out, fmtBegin, fmtEnd, ntrunc, m_value);
588 }
589
590 int toInt() const {
593 return m_toIntImpl(m_value);
594 }
595
596 private:
597 template <typename T>
598 TINYFORMAT_HIDDEN static void
599 formatImpl(std::ostream &out, const char *fmtBegin, const char *fmtEnd,
600 int ntrunc, const void *value) {
601 formatValue(out, fmtBegin, fmtEnd, ntrunc,
602 *static_cast<const T *>(value));
603 }
604
605 template <typename T>
606 TINYFORMAT_HIDDEN static int toIntImpl(const void *value) {
607 return convertToInt<T>::invoke(*static_cast<const T *>(value));
608 }
609
610 const void *m_value{nullptr};
611 void (*m_formatImpl)(std::ostream &out, const char *fmtBegin,
612 const char *fmtEnd, int ntrunc,
613 const void *value){nullptr};
614 int (*m_toIntImpl)(const void *value){nullptr};
615 };
616
617 // Parse and return an integer from the string c, as atoi()
618 // On return, c is set to one past the end of the integer.
619 inline int parseIntAndAdvance(const char *&c) {
620 int i = 0;
621 for (; *c >= '0' && *c <= '9'; ++c)
622 i = 10 * i + (*c - '0');
623 return i;
624 }
625
626 // Parse width or precision `n` from format string pointer `c`, and advance
627 // it to the next character. If an indirection is requested with `*`, the
628 // argument is read from `args[argIndex]` and `argIndex` is incremented (or
629 // read from `args[n]` in positional mode). Returns true if one or more
630 // characters were read.
631 inline bool parseWidthOrPrecision(int &n, const char *&c,
632 bool positionalMode,
633 const detail::FormatArg *args,
634 int &argIndex, int numArgs) {
635 if (*c >= '0' && *c <= '9') {
636 n = parseIntAndAdvance(c);
637 } else if (*c == '*') {
638 ++c;
639 n = 0;
640 if (positionalMode) {
641 int pos = parseIntAndAdvance(c) - 1;
642 if (*c != '$')
643 TINYFORMAT_ERROR("tinyformat: Non-positional argument used "
644 "after a positional one");
645 if (pos >= 0 && pos < numArgs)
646 n = args[pos].toInt();
647 else
649 "tinyformat: Positional argument out of range");
650 ++c;
651 } else {
652 if (argIndex < numArgs)
653 n = args[argIndex++].toInt();
654 else
655 TINYFORMAT_ERROR("tinyformat: Not enough arguments to read "
656 "variable width or precision");
657 }
658 } else {
659 return false;
660 }
661 return true;
662 }
663
664 // Print literal part of format string and return next format spec position.
665 //
666 // Skips over any occurrences of '%%', printing a literal '%' to the output.
667 // The position of the first % character of the next nontrivial format spec
668 // is returned, or the end of string.
669 inline const char *printFormatStringLiteral(std::ostream &out,
670 const char *fmt) {
671 const char *c = fmt;
672 for (;; ++c) {
673 if (*c == '\0') {
674 out.write(fmt, c - fmt);
675 return c;
676 } else if (*c == '%') {
677 out.write(fmt, c - fmt);
678 if (*(c + 1) != '%') return c;
679 // for "%%", tack trailing % onto next literal section.
680 fmt = ++c;
681 }
682 }
683 }
684
685 // Parse a format string and set the stream state accordingly.
686 //
687 // The format mini-language recognized here is meant to be the one from C99,
688 // with the form "%[flags][width][.precision][length]type" with POSIX
689 // positional arguments extension.
690 //
691 // POSIX positional arguments extension:
692 // Conversions can be applied to the nth argument after the format in
693 // the argument list, rather than to the next unused argument. In this case,
694 // the conversion specifier character % (see below) is replaced by the
695 // sequence
696 // "%n$", where n is a decimal integer in the range [1,{NL_ARGMAX}],
697 // giving the position of the argument in the argument list. This feature
698 // provides for the definition of format strings that select arguments
699 // in an order appropriate to specific languages.
700 //
701 // The format can contain either numbered argument conversion specifications
702 // (that is, "%n$" and "*m$"), or unnumbered argument conversion
703 // specifications (that is, % and * ), but not both. The only exception to
704 // this is that %% can be mixed with the "%n$" form. The results of mixing
705 // numbered and unnumbered argument specifications in a format string are
706 // undefined. When numbered argument specifications are used, specifying the
707 // Nth argument requires that all the leading arguments, from the first to
708 // the (N-1)th, are specified in the format string.
709 //
710 // In format strings containing the "%n$" form of conversion specification,
711 // numbered arguments in the argument list can be referenced from the format
712 // string as many times as required.
713 //
714 // Formatting options which can't be natively represented using the ostream
715 // state are returned in spacePadPositive (for space padded positive
716 // numbers) and ntrunc (for truncating conversions). argIndex is incremented
717 // if necessary to pull out variable width and precision. The function
718 // returns a pointer to the character after the end of the current format
719 // spec.
720 inline const char *streamStateFromFormat(std::ostream &out,
721 bool &positionalMode,
722 bool &spacePadPositive,
723 int &ntrunc, const char *fmtStart,
724 const detail::FormatArg *args,
725 int &argIndex, int numArgs) {
726 TINYFORMAT_ASSERT(*fmtStart == '%');
727 // Reset stream state to defaults.
728 out.width(0);
729 out.precision(6);
730 out.fill(' ');
731 // Reset most flags; ignore irrelevant unitbuf & skipws.
732 out.unsetf(std::ios::adjustfield | std::ios::basefield |
733 std::ios::floatfield | std::ios::showbase |
734 std::ios::boolalpha | std::ios::showpoint |
735 std::ios::showpos | std::ios::uppercase);
736 bool precisionSet = false;
737 bool widthSet = false;
738 int widthExtra = 0;
739 const char *c = fmtStart + 1;
740
741 // 1) Parse an argument index (if followed by '$') or a width possibly
742 // preceded with '0' flag.
743 if (*c >= '0' && *c <= '9') {
744 const char tmpc = *c;
745 int value = parseIntAndAdvance(c);
746 if (*c == '$') {
747 // value is an argument index
748 if (value > 0 && value <= numArgs)
749 argIndex = value - 1;
750 else
752 "tinyformat: Positional argument out of range");
753 ++c;
754 positionalMode = true;
755 } else if (positionalMode) {
756 TINYFORMAT_ERROR("tinyformat: Non-positional argument used "
757 "after a positional one");
758 } else {
759 if (tmpc == '0') {
760 // Use internal padding so that numeric values are
761 // formatted correctly, eg -00010 rather than 000-10
762 out.fill('0');
763 out.setf(std::ios::internal, std::ios::adjustfield);
764 }
765 if (value != 0) {
766 // Nonzero value means that we parsed width.
767 widthSet = true;
768 out.width(value);
769 }
770 }
771 } else if (positionalMode) {
772 TINYFORMAT_ERROR("tinyformat: Non-positional argument used after a "
773 "positional one");
774 }
775 // 2) Parse flags and width if we did not do it in previous step.
776 if (!widthSet) {
777 // Parse flags
778 for (;; ++c) {
779 switch (*c) {
780 case '#':
781 out.setf(std::ios::showpoint | std::ios::showbase);
782 continue;
783 case '0':
784 // overridden by left alignment ('-' flag)
785 if (!(out.flags() & std::ios::left)) {
786 // Use internal padding so that numeric values are
787 // formatted correctly, eg -00010 rather than 000-10
788 out.fill('0');
789 out.setf(std::ios::internal, std::ios::adjustfield);
790 }
791 continue;
792 case '-':
793 out.fill(' ');
794 out.setf(std::ios::left, std::ios::adjustfield);
795 continue;
796 case ' ':
797 // overridden by show positive sign, '+' flag.
798 if (!(out.flags() & std::ios::showpos))
799 spacePadPositive = true;
800 continue;
801 case '+':
802 out.setf(std::ios::showpos);
803 spacePadPositive = false;
804 widthExtra = 1;
805 continue;
806 default:
807 break;
808 }
809 break;
810 }
811 // Parse width
812 int width = 0;
813 widthSet = parseWidthOrPrecision(width, c, positionalMode, args,
814 argIndex, numArgs);
815 if (widthSet) {
816 if (width < 0) {
817 // negative widths correspond to '-' flag set
818 out.fill(' ');
819 out.setf(std::ios::left, std::ios::adjustfield);
820 width = -width;
821 }
822 out.width(width);
823 }
824 }
825 // 3) Parse precision
826 if (*c == '.') {
827 ++c;
828 int precision = 0;
829 parseWidthOrPrecision(precision, c, positionalMode, args, argIndex,
830 numArgs);
831 // Presence of `.` indicates precision set, unless the inferred
832 // value was negative in which case the default is used.
833 precisionSet = precision >= 0;
834 if (precisionSet) out.precision(precision);
835 }
836 // 4) Ignore any C99 length modifier
837 while (*c == 'l' || *c == 'h' || *c == 'L' || *c == 'j' || *c == 'z' ||
838 *c == 't') {
839 ++c;
840 }
841 // 5) We're up to the conversion specifier character.
842 // Set stream flags based on conversion specifier (thanks to the
843 // boost::format class for forging the way here).
844 bool intConversion = false;
845 switch (*c) {
846 case 'u':
847 case 'd':
848 case 'i':
849 out.setf(std::ios::dec, std::ios::basefield);
850 intConversion = true;
851 break;
852 case 'o':
853 out.setf(std::ios::oct, std::ios::basefield);
854 intConversion = true;
855 break;
856 case 'X':
857 out.setf(std::ios::uppercase);
858 // Falls through
859 case 'x':
860 case 'p':
861 out.setf(std::ios::hex, std::ios::basefield);
862 intConversion = true;
863 break;
864 case 'E':
865 out.setf(std::ios::uppercase);
866 // Falls through
867 case 'e':
868 out.setf(std::ios::scientific, std::ios::floatfield);
869 out.setf(std::ios::dec, std::ios::basefield);
870 break;
871 case 'F':
872 out.setf(std::ios::uppercase);
873 // Falls through
874 case 'f':
875 out.setf(std::ios::fixed, std::ios::floatfield);
876 break;
877 case 'A':
878 out.setf(std::ios::uppercase);
879 // Falls through
880 case 'a':
881#ifdef _MSC_VER
882 // Workaround
883 // https://developercommunity.visualstudio.com/content/problem/520472/hexfloat-stream-output-does-not-ignore-precision-a.html
884 // by always setting maximum precision on MSVC to avoid
885 // precision loss for doubles.
886 out.precision(13);
887#endif
888 out.setf(std::ios::fixed | std::ios::scientific,
889 std::ios::floatfield);
890 break;
891 case 'G':
892 out.setf(std::ios::uppercase);
893 // Falls through
894 case 'g':
895 out.setf(std::ios::dec, std::ios::basefield);
896 // As in boost::format, let stream decide float format.
897 out.flags(out.flags() & ~std::ios::floatfield);
898 break;
899 case 'c':
900 // Handled as special case inside formatValue()
901 break;
902 case 's':
903 if (precisionSet) ntrunc = static_cast<int>(out.precision());
904 // Make %s print Booleans as "true" and "false"
905 out.setf(std::ios::boolalpha);
906 break;
907 case 'n':
908 // Not supported - will cause problems!
910 "tinyformat: %n conversion spec not supported");
911 break;
912 case '\0':
913 TINYFORMAT_ERROR("tinyformat: Conversion spec incorrectly "
914 "terminated by end of string");
915 return c;
916 default:
917 break;
918 }
919 if (intConversion && precisionSet && !widthSet) {
920 // "precision" for integers gives the minimum number of digits (to
921 // be padded with zeros on the left). This isn't really supported by
922 // the iostreams, but we can approximately simulate it with the
923 // width if the width isn't otherwise used.
924 out.width(out.precision() + widthExtra);
925 out.setf(std::ios::internal, std::ios::adjustfield);
926 out.fill('0');
927 }
928 return c + 1;
929 }
930
931 //------------------------------------------------------------------------------
932 inline void formatImpl(std::ostream &out, const char *fmt,
933 const detail::FormatArg *args, int numArgs) {
934 // Saved stream state
935 std::streamsize origWidth = out.width();
936 std::streamsize origPrecision = out.precision();
937 std::ios::fmtflags origFlags = out.flags();
938 char origFill = out.fill();
939
940 // "Positional mode" means all format specs should be of the form
941 // "%n$..." with `n` an integer. We detect this in
942 // `streamStateFromFormat`.
943 bool positionalMode = false;
944 int argIndex = 0;
945 while (true) {
946 fmt = printFormatStringLiteral(out, fmt);
947 if (*fmt == '\0') {
948 if (!positionalMode && argIndex < numArgs) {
949 TINYFORMAT_ERROR("tinyformat: Not enough conversion "
950 "specifiers in format string");
951 }
952 break;
953 }
954 bool spacePadPositive = false;
955 int ntrunc = -1;
956 const char *fmtEnd =
957 streamStateFromFormat(out, positionalMode, spacePadPositive,
958 ntrunc, fmt, args, argIndex, numArgs);
959 // NB: argIndex may be incremented by reading variable
960 // width/precision in `streamStateFromFormat`, so do the bounds
961 // check here.
962 if (argIndex >= numArgs) {
963 TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers "
964 "in format string");
965 return;
966 }
967 const FormatArg &arg = args[argIndex];
968 // Format the arg into the stream.
969 if (!spacePadPositive) {
970 arg.format(out, fmt, fmtEnd, ntrunc);
971 } else {
972 // The following is a special case with no direct correspondence
973 // between stream formatting and the printf() behaviour.
974 // Simulate it crudely by formatting into a temporary string
975 // stream and munging the resulting string.
976 std::ostringstream tmpStream;
977 tmpStream.copyfmt(out);
978 tmpStream.setf(std::ios::showpos);
979 arg.format(tmpStream, fmt, fmtEnd, ntrunc);
980 std::string result = tmpStream.str(); // allocates... yuck.
981 for (size_t i = 0, iend = result.size(); i < iend; ++i) {
982 if (result[i] == '+') result[i] = ' ';
983 }
984 out << result;
985 }
986 if (!positionalMode) ++argIndex;
987 fmt = fmtEnd;
988 }
989
990 // Restore stream state
991 out.width(origWidth);
992 out.precision(origPrecision);
993 out.flags(origFlags);
994 out.fill(origFill);
995 }
996
997} // namespace detail
998
1006public:
1007 FormatList(detail::FormatArg *args, int N) : m_args(args), m_N(N) {}
1008
1009 friend void vformat(std::ostream &out, const char *fmt,
1010 const FormatList &list);
1011
1012private:
1014 int m_N;
1015};
1016
1019
1020namespace detail {
1021
1022 // Format list subclass with fixed storage to avoid dynamic allocation
1023 template <int N> class FormatListN : public FormatList {
1024 public:
1025#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1026 template <typename... Args>
1027 explicit FormatListN(const Args &...args)
1028 : FormatList(&m_formatterStore[0], N),
1029 m_formatterStore{FormatArg(args)...} {
1030 static_assert(sizeof...(args) == N, "Number of args must be N");
1031 }
1032#else // C++98 version
1033 void init(int) {}
1034#define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
1035 \
1036 template <TINYFORMAT_ARGTYPES(n)> \
1037 FormatListN(TINYFORMAT_VARARGS(n)) : FormatList(&m_formatterStore[0], n) { \
1038 TINYFORMAT_ASSERT(n == N); \
1039 init(0, TINYFORMAT_PASSARGS(n)); \
1040 } \
1041 \
1042 template <TINYFORMAT_ARGTYPES(n)> \
1043 void init(int i, TINYFORMAT_VARARGS(n)) { \
1044 m_formatterStore[i] = FormatArg(v1); \
1045 init(i + 1 TINYFORMAT_PASSARGS_TAIL(n)); \
1046 }
1047
1048 TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR)
1049#undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
1050#endif
1052 : FormatList(&m_formatterStore[0], N) {
1053 std::copy(&other.m_formatterStore[0], &other.m_formatterStore[N],
1054 &m_formatterStore[0]);
1055 }
1056
1057 private:
1059 };
1060
1061 // Special 0-arg version - MSVC says zero-sized C array in struct is
1062 // nonstandard.
1063 template <> class FormatListN<0> : public FormatList {
1064 public:
1065 FormatListN() : FormatList(nullptr, 0) {}
1066 };
1067
1068} // namespace detail
1069
1070//------------------------------------------------------------------------------
1071// Primary API functions
1072
1073#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1074
1081template <typename... Args>
1082detail::FormatListN<sizeof...(Args)> makeFormatList(const Args &...args) {
1083 return detail::FormatListN<sizeof...(args)>(args...);
1084}
1085
1086#else // C++98 version
1087
1088inline detail::FormatListN<0> makeFormatList() {
1089 return detail::FormatListN<0>();
1090}
1091#define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
1092 template <TINYFORMAT_ARGTYPES(n)> \
1093 detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) { \
1094 return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
1095 }
1096TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_MAKEFORMATLIST)
1097#undef TINYFORMAT_MAKE_MAKEFORMATLIST
1098
1099#endif
1100
1105inline void vformat(std::ostream &out, const char *fmt, FormatListRef list) {
1106 detail::formatImpl(out, fmt, list.m_args, list.m_N);
1107}
1108
1109#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1110
1112template <typename... Args>
1113void format(std::ostream &out, const char *fmt, const Args &...args) {
1114 vformat(out, fmt, makeFormatList(args...));
1115}
1116
1119template <typename... Args>
1120std::string format(const char *fmt, const Args &...args) {
1121 std::ostringstream oss;
1122 format(oss, fmt, args...);
1123 return oss.str();
1124}
1125
1127template <typename... Args> void printf(const char *fmt, const Args &...args) {
1128 format(std::cout, fmt, args...);
1129}
1130
1131template <typename... Args>
1132void printfln(const char *fmt, const Args &...args) {
1133 format(std::cout, fmt, args...);
1134 std::cout << '\n';
1135}
1136
1137#else // C++98 version
1138
1139inline void format(std::ostream &out, const char *fmt) {
1140 vformat(out, fmt, makeFormatList());
1141}
1142
1143inline std::string format(const char *fmt) {
1144 std::ostringstream oss;
1145 format(oss, fmt);
1146 return oss.str();
1147}
1148
1149inline void printf(const char *fmt) {
1150 format(std::cout, fmt);
1151}
1152
1153inline void printfln(const char *fmt) {
1154 format(std::cout, fmt);
1155 std::cout << '\n';
1156}
1157
1158#define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
1159 \
1160 template <TINYFORMAT_ARGTYPES(n)> \
1161 void format(std::ostream &out, const char *fmt, TINYFORMAT_VARARGS(n)) { \
1162 vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
1163 } \
1164 \
1165 template <TINYFORMAT_ARGTYPES(n)> \
1166 std::string format(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1167 std::ostringstream oss; \
1168 format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
1169 return oss.str(); \
1170 } \
1171 \
1172 template <TINYFORMAT_ARGTYPES(n)> \
1173 void printf(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1174 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1175 } \
1176 \
1177 template <TINYFORMAT_ARGTYPES(n)> \
1178 void printfln(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1179 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1180 std::cout << '\n'; \
1181 }
1182
1183TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_FUNCS)
1184#undef TINYFORMAT_MAKE_FORMAT_FUNCS
1185
1186#endif
1187
1188// Added for Bitcoin
1189template <typename... Args>
1190std::string format(const std::string &fmt, const Args &...args) {
1191 std::ostringstream oss;
1192 format(oss, fmt.c_str(), args...);
1193 return oss.str();
1194}
1195
1196} // namespace tinyformat
1197
1198// Added for Bitcoin:
1203#define strprintf tfm::format
1204
1205#endif // TINYFORMAT_H_INCLUDED
List of template arguments format(), held in a type-opaque way.
Definition: tinyformat.h:1005
friend void vformat(std::ostream &out, const char *fmt, const FormatList &list)
FormatList(detail::FormatArg *args, int N)
Definition: tinyformat.h:1007
const detail::FormatArg * m_args
Definition: tinyformat.h:1013
static TINYFORMAT_HIDDEN void formatImpl(std::ostream &out, const char *fmtBegin, const char *fmtEnd, int ntrunc, const void *value)
Definition: tinyformat.h:599
void(* m_formatImpl)(std::ostream &out, const char *fmtBegin, const char *fmtEnd, int ntrunc, const void *value)
Definition: tinyformat.h:611
static TINYFORMAT_HIDDEN int toIntImpl(const void *value)
Definition: tinyformat.h:606
int(* m_toIntImpl)(const void *value)
Definition: tinyformat.h:614
void format(std::ostream &out, const char *fmtBegin, const char *fmtEnd, int ntrunc) const
Definition: tinyformat.h:583
FormatListN(const Args &...args)
Definition: tinyformat.h:1027
FormatListN(const FormatListN &other)
Definition: tinyformat.h:1051
format_error(const std::string &what)
Definition: tinyformat.h:187
Definition: common.cpp:23
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:259
void formatTruncated(std::ostream &out, const T &value, int ntrunc)
Definition: tinyformat.h:289
const char * printFormatStringLiteral(std::ostream &out, const char *fmt)
Definition: tinyformat.h:669
int parseIntAndAdvance(const char *&c)
Definition: tinyformat.h:619
void formatImpl(std::ostream &out, const char *fmt, const detail::FormatArg *args, int numArgs)
Definition: tinyformat.h:932
const char * streamStateFromFormat(std::ostream &out, bool &positionalMode, bool &spacePadPositive, int &ntrunc, const char *fmtStart, const detail::FormatArg *args, int &argIndex, int numArgs)
Definition: tinyformat.h:720
bool parseWidthOrPrecision(int &n, const char *&c, bool positionalMode, const detail::FormatArg *args, int &argIndex, int numArgs)
Definition: tinyformat.h:631
detail::FormatListN< sizeof...(Args)> makeFormatList(const Args &...args)
Make type-agnostic format list from list of template arguments.
Definition: tinyformat.h:1082
void vformat(std::ostream &out, const char *fmt, FormatListRef list)
Format list of arguments to the stream according to the given format string.
Definition: tinyformat.h:1105
void formatValue(std::ostream &out, const char *, const char *fmtEnd, int ntrunc, const T &value)
Format a value into a stream, delegating to operator<< by default.
Definition: tinyformat.h:327
const FormatList & FormatListRef
Reference to type-opaque format list for passing to vformat()
Definition: tinyformat.h:1018
void printfln(const char *fmt, const Args &...args)
Definition: tinyformat.h:1132
void format(std::ostream &out, const char *fmt, const Args &...args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1113
void printf(const char *fmt, const Args &...args)
Format list of arguments to std::cout, according to the given format string.
Definition: tinyformat.h:1127
static int invoke(const T &value)
Definition: tinyformat.h:284
static int invoke(const T &)
Definition: tinyformat.h:276
static void invoke(std::ostream &out, const T &value)
Definition: tinyformat.h:248
static void invoke(std::ostream &, const T &)
Definition: tinyformat.h:240
static succeed tryConvert(const T2 &)
#define TINYFORMAT_HIDDEN
Definition: tinyformat.h:179
#define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type)
Definition: tinyformat.h:296
#define TINYFORMAT_ASSERT(cond)
Definition: tinyformat.h:153
#define TINYFORMAT_ERROR(reasonString)
Definition: tinyformat.h:136
#define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType)
Definition: tinyformat.h:361
#define TINYFORMAT_FOREACH_ARGNUM(m)
Definition: tinyformat.h:563