Bitcoin ABC 0.26.3
P2P Digital Currency
Loading...
Searching...
No Matches
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,
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>
248 static void invoke(std::ostream &out, const T &value) {
250 }
251 };
252
253#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
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.
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*).
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:
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 {
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) {
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;
611 void (*m_formatImpl)(std::ostream &out, const char *fmtBegin,
612 const char *fmtEnd, int ntrunc, const void *value);
613 int (*m_toIntImpl)(const void *value);
614 };
615
616 // Parse and return an integer from the string c, as atoi()
617 // On return, c is set to one past the end of the integer.
618 inline int parseIntAndAdvance(const char *&c) {
619 int i = 0;
620 for (; *c >= '0' && *c <= '9'; ++c)
621 i = 10 * i + (*c - '0');
622 return i;
623 }
624
625 // Parse width or precision `n` from format string pointer `c`, and advance
626 // it to the next character. If an indirection is requested with `*`, the
627 // argument is read from `args[argIndex]` and `argIndex` is incremented (or
628 // read from `args[n]` in positional mode). Returns true if one or more
629 // characters were read.
630 inline bool parseWidthOrPrecision(int &n, const char *&c,
631 bool positionalMode,
632 const detail::FormatArg *args,
633 int &argIndex, int numArgs) {
634 if (*c >= '0' && *c <= '9') {
636 } else if (*c == '*') {
637 ++c;
638 n = 0;
639 if (positionalMode) {
640 int pos = parseIntAndAdvance(c) - 1;
641 if (*c != '$')
642 TINYFORMAT_ERROR("tinyformat: Non-positional argument used "
643 "after a positional one");
644 if (pos >= 0 && pos < numArgs)
645 n = args[pos].toInt();
646 else
648 "tinyformat: Positional argument out of range");
649 ++c;
650 } else {
651 if (argIndex < numArgs)
652 n = args[argIndex++].toInt();
653 else
654 TINYFORMAT_ERROR("tinyformat: Not enough arguments to read "
655 "variable width or precision");
656 }
657 } else {
658 return false;
659 }
660 return true;
661 }
662
663 // Print literal part of format string and return next format spec position.
664 //
665 // Skips over any occurrences of '%%', printing a literal '%' to the output.
666 // The position of the first % character of the next nontrivial format spec
667 // is returned, or the end of string.
668 inline const char *printFormatStringLiteral(std::ostream &out,
669 const char *fmt) {
670 const char *c = fmt;
671 for (;; ++c) {
672 if (*c == '\0') {
673 out.write(fmt, c - fmt);
674 return c;
675 } else if (*c == '%') {
676 out.write(fmt, c - fmt);
677 if (*(c + 1) != '%') return c;
678 // for "%%", tack trailing % onto next literal section.
679 fmt = ++c;
680 }
681 }
682 }
683
684 // Parse a format string and set the stream state accordingly.
685 //
686 // The format mini-language recognized here is meant to be the one from C99,
687 // with the form "%[flags][width][.precision][length]type" with POSIX
688 // positional arguments extension.
689 //
690 // POSIX positional arguments extension:
691 // Conversions can be applied to the nth argument after the format in
692 // the argument list, rather than to the next unused argument. In this case,
693 // the conversion specifier character % (see below) is replaced by the
694 // sequence
695 // "%n$", where n is a decimal integer in the range [1,{NL_ARGMAX}],
696 // giving the position of the argument in the argument list. This feature
697 // provides for the definition of format strings that select arguments
698 // in an order appropriate to specific languages.
699 //
700 // The format can contain either numbered argument conversion specifications
701 // (that is, "%n$" and "*m$"), or unnumbered argument conversion
702 // specifications (that is, % and * ), but not both. The only exception to
703 // this is that %% can be mixed with the "%n$" form. The results of mixing
704 // numbered and unnumbered argument specifications in a format string are
705 // undefined. When numbered argument specifications are used, specifying the
706 // Nth argument requires that all the leading arguments, from the first to
707 // the (N-1)th, are specified in the format string.
708 //
709 // In format strings containing the "%n$" form of conversion specification,
710 // numbered arguments in the argument list can be referenced from the format
711 // string as many times as required.
712 //
713 // Formatting options which can't be natively represented using the ostream
714 // state are returned in spacePadPositive (for space padded positive
715 // numbers) and ntrunc (for truncating conversions). argIndex is incremented
716 // if necessary to pull out variable width and precision. The function
717 // returns a pointer to the character after the end of the current format
718 // spec.
719 inline const char *streamStateFromFormat(std::ostream &out,
720 bool &positionalMode,
721 bool &spacePadPositive,
722 int &ntrunc, const char *fmtStart,
723 const detail::FormatArg *args,
724 int &argIndex, int numArgs) {
726 // Reset stream state to defaults.
727 out.width(0);
728 out.precision(6);
729 out.fill(' ');
730 // Reset most flags; ignore irrelevant unitbuf & skipws.
731 out.unsetf(std::ios::adjustfield | std::ios::basefield |
732 std::ios::floatfield | std::ios::showbase |
733 std::ios::boolalpha | std::ios::showpoint |
734 std::ios::showpos | std::ios::uppercase);
735 bool precisionSet = false;
736 bool widthSet = false;
737 int widthExtra = 0;
738 const char *c = fmtStart + 1;
739
740 // 1) Parse an argument index (if followed by '$') or a width possibly
741 // preceded with '0' flag.
742 if (*c >= '0' && *c <= '9') {
743 const char tmpc = *c;
744 int value = parseIntAndAdvance(c);
745 if (*c == '$') {
746 // value is an argument index
747 if (value > 0 && value <= numArgs)
748 argIndex = value - 1;
749 else
751 "tinyformat: Positional argument out of range");
752 ++c;
753 positionalMode = true;
754 } else if (positionalMode) {
755 TINYFORMAT_ERROR("tinyformat: Non-positional argument used "
756 "after a positional one");
757 } else {
758 if (tmpc == '0') {
759 // Use internal padding so that numeric values are
760 // formatted correctly, eg -00010 rather than 000-10
761 out.fill('0');
762 out.setf(std::ios::internal, std::ios::adjustfield);
763 }
764 if (value != 0) {
765 // Nonzero value means that we parsed width.
766 widthSet = true;
767 out.width(value);
768 }
769 }
770 } else if (positionalMode) {
771 TINYFORMAT_ERROR("tinyformat: Non-positional argument used after a "
772 "positional one");
773 }
774 // 2) Parse flags and width if we did not do it in previous step.
775 if (!widthSet) {
776 // Parse flags
777 for (;; ++c) {
778 switch (*c) {
779 case '#':
780 out.setf(std::ios::showpoint | std::ios::showbase);
781 continue;
782 case '0':
783 // overridden by left alignment ('-' flag)
784 if (!(out.flags() & std::ios::left)) {
785 // Use internal padding so that numeric values are
786 // formatted correctly, eg -00010 rather than 000-10
787 out.fill('0');
788 out.setf(std::ios::internal, std::ios::adjustfield);
789 }
790 continue;
791 case '-':
792 out.fill(' ');
793 out.setf(std::ios::left, std::ios::adjustfield);
794 continue;
795 case ' ':
796 // overridden by show positive sign, '+' flag.
797 if (!(out.flags() & std::ios::showpos))
798 spacePadPositive = true;
799 continue;
800 case '+':
801 out.setf(std::ios::showpos);
802 spacePadPositive = false;
803 widthExtra = 1;
804 continue;
805 default:
806 break;
807 }
808 break;
809 }
810 // Parse width
811 int width = 0;
814 if (widthSet) {
815 if (width < 0) {
816 // negative widths correspond to '-' flag set
817 out.fill(' ');
818 out.setf(std::ios::left, std::ios::adjustfield);
819 width = -width;
820 }
821 out.width(width);
822 }
823 }
824 // 3) Parse precision
825 if (*c == '.') {
826 ++c;
827 int precision = 0;
829 numArgs);
830 // Presence of `.` indicates precision set, unless the inferred
831 // value was negative in which case the default is used.
832 precisionSet = precision >= 0;
833 if (precisionSet) out.precision(precision);
834 }
835 // 4) Ignore any C99 length modifier
836 while (*c == 'l' || *c == 'h' || *c == 'L' || *c == 'j' || *c == 'z' ||
837 *c == 't') {
838 ++c;
839 }
840 // 5) We're up to the conversion specifier character.
841 // Set stream flags based on conversion specifier (thanks to the
842 // boost::format class for forging the way here).
843 bool intConversion = false;
844 switch (*c) {
845 case 'u':
846 case 'd':
847 case 'i':
848 out.setf(std::ios::dec, std::ios::basefield);
849 intConversion = true;
850 break;
851 case 'o':
852 out.setf(std::ios::oct, std::ios::basefield);
853 intConversion = true;
854 break;
855 case 'X':
856 out.setf(std::ios::uppercase);
857 // Falls through
858 case 'x':
859 case 'p':
860 out.setf(std::ios::hex, std::ios::basefield);
861 intConversion = true;
862 break;
863 case 'E':
864 out.setf(std::ios::uppercase);
865 // Falls through
866 case 'e':
867 out.setf(std::ios::scientific, std::ios::floatfield);
868 out.setf(std::ios::dec, std::ios::basefield);
869 break;
870 case 'F':
871 out.setf(std::ios::uppercase);
872 // Falls through
873 case 'f':
874 out.setf(std::ios::fixed, std::ios::floatfield);
875 break;
876 case 'A':
877 out.setf(std::ios::uppercase);
878 // Falls through
879 case 'a':
880#ifdef _MSC_VER
881 // Workaround
882 // https://developercommunity.visualstudio.com/content/problem/520472/hexfloat-stream-output-does-not-ignore-precision-a.html
883 // by always setting maximum precision on MSVC to avoid
884 // precision loss for doubles.
885 out.precision(13);
886#endif
887 out.setf(std::ios::fixed | std::ios::scientific,
888 std::ios::floatfield);
889 break;
890 case 'G':
891 out.setf(std::ios::uppercase);
892 // Falls through
893 case 'g':
894 out.setf(std::ios::dec, std::ios::basefield);
895 // As in boost::format, let stream decide float format.
896 out.flags(out.flags() & ~std::ios::floatfield);
897 break;
898 case 'c':
899 // Handled as special case inside formatValue()
900 break;
901 case 's':
902 if (precisionSet) ntrunc = static_cast<int>(out.precision());
903 // Make %s print Booleans as "true" and "false"
904 out.setf(std::ios::boolalpha);
905 break;
906 case 'n':
907 // Not supported - will cause problems!
909 "tinyformat: %n conversion spec not supported");
910 break;
911 case '\0':
912 TINYFORMAT_ERROR("tinyformat: Conversion spec incorrectly "
913 "terminated by end of string");
914 return c;
915 default:
916 break;
917 }
919 // "precision" for integers gives the minimum number of digits (to
920 // be padded with zeros on the left). This isn't really supported by
921 // the iostreams, but we can approximately simulate it with the
922 // width if the width isn't otherwise used.
923 out.width(out.precision() + widthExtra);
924 out.setf(std::ios::internal, std::ios::adjustfield);
925 out.fill('0');
926 }
927 return c + 1;
928 }
929
930 //------------------------------------------------------------------------------
931 inline void formatImpl(std::ostream &out, const char *fmt,
932 const detail::FormatArg *args, int numArgs) {
933 // Saved stream state
934 std::streamsize origWidth = out.width();
935 std::streamsize origPrecision = out.precision();
936 std::ios::fmtflags origFlags = out.flags();
937 char origFill = out.fill();
938
939 // "Positional mode" means all format specs should be of the form
940 // "%n$..." with `n` an integer. We detect this in
941 // `streamStateFromFormat`.
942 bool positionalMode = false;
943 int argIndex = 0;
944 while (true) {
946 if (*fmt == '\0') {
947 if (!positionalMode && argIndex < numArgs) {
948 TINYFORMAT_ERROR("tinyformat: Not enough conversion "
949 "specifiers in format string");
950 }
951 break;
952 }
953 bool spacePadPositive = false;
954 int ntrunc = -1;
955 const char *fmtEnd =
957 ntrunc, fmt, args, argIndex, numArgs);
958 // NB: argIndex may be incremented by reading variable
959 // width/precision in `streamStateFromFormat`, so do the bounds
960 // check here.
961 if (argIndex >= numArgs) {
962 TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers "
963 "in format string");
964 return;
965 }
966 const FormatArg &arg = args[argIndex];
967 // Format the arg into the stream.
968 if (!spacePadPositive) {
969 arg.format(out, fmt, fmtEnd, ntrunc);
970 } else {
971 // The following is a special case with no direct correspondence
972 // between stream formatting and the printf() behaviour.
973 // Simulate it crudely by formatting into a temporary string
974 // stream and munging the resulting string.
975 std::ostringstream tmpStream;
976 tmpStream.copyfmt(out);
977 tmpStream.setf(std::ios::showpos);
978 arg.format(tmpStream, fmt, fmtEnd, ntrunc);
979 std::string result = tmpStream.str(); // allocates... yuck.
980 for (size_t i = 0, iend = result.size(); i < iend; ++i) {
981 if (result[i] == '+') result[i] = ' ';
982 }
983 out << result;
984 }
985 if (!positionalMode) ++argIndex;
986 fmt = fmtEnd;
987 }
988
989 // Restore stream state
990 out.width(origWidth);
991 out.precision(origPrecision);
992 out.flags(origFlags);
993 out.fill(origFill);
994 }
995
996} // namespace detail
997
1005public:
1006 FormatList(detail::FormatArg *args, int N) : m_args(args), m_N(N) {}
1007
1008 friend void vformat(std::ostream &out, const char *fmt,
1009 const FormatList &list);
1010
1011private:
1013 int m_N;
1014};
1015
1018
1019namespace detail {
1020
1021 // Format list subclass with fixed storage to avoid dynamic allocation
1022 template <int N> class FormatListN : public FormatList {
1023 public:
1024#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1025 template <typename... Args>
1026 explicit FormatListN(const Args &...args)
1028 m_formatterStore{FormatArg(args)...} {
1029 static_assert(sizeof...(args) == N, "Number of args must be N");
1030 }
1031#else // C++98 version
1032 void init(int) {}
1033#define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
1034 \
1035 template <TINYFORMAT_ARGTYPES(n)> \
1036 FormatListN(TINYFORMAT_VARARGS(n)) : FormatList(&m_formatterStore[0], n) { \
1037 TINYFORMAT_ASSERT(n == N); \
1038 init(0, TINYFORMAT_PASSARGS(n)); \
1039 } \
1040 \
1041 template <TINYFORMAT_ARGTYPES(n)> \
1042 void init(int i, TINYFORMAT_VARARGS(n)) { \
1043 m_formatterStore[i] = FormatArg(v1); \
1044 init(i + 1 TINYFORMAT_PASSARGS_TAIL(n)); \
1045 }
1046
1048#undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
1049#endif
1051 : FormatList(&m_formatterStore[0], N) {
1052 std::copy(&other.m_formatterStore[0], &other.m_formatterStore[N],
1053 &m_formatterStore[0]);
1054 }
1055
1056 private:
1058 };
1059
1060 // Special 0-arg version - MSVC says zero-sized C array in struct is
1061 // nonstandard.
1062 template <> class FormatListN<0> : public FormatList {
1063 public:
1065 };
1066
1067} // namespace detail
1068
1069//------------------------------------------------------------------------------
1070// Primary API functions
1071
1072#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1073
1080template <typename... Args>
1081detail::FormatListN<sizeof...(Args)> makeFormatList(const Args &...args) {
1082 return detail::FormatListN<sizeof...(args)>(args...);
1083}
1084
1085#else // C++98 version
1086
1087inline detail::FormatListN<0> makeFormatList() {
1088 return detail::FormatListN<0>();
1089}
1090#define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
1091 template <TINYFORMAT_ARGTYPES(n)> \
1092 detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) { \
1093 return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
1094 }
1096#undef TINYFORMAT_MAKE_MAKEFORMATLIST
1097
1098#endif
1099
1104inline void vformat(std::ostream &out, const char *fmt, FormatListRef list) {
1105 detail::formatImpl(out, fmt, list.m_args, list.m_N);
1106}
1107
1108#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1109
1111template <typename... Args>
1112void format(std::ostream &out, const char *fmt, const Args &...args) {
1113 vformat(out, fmt, makeFormatList(args...));
1114}
1115
1118template <typename... Args>
1119std::string format(const char *fmt, const Args &...args) {
1120 std::ostringstream oss;
1121 format(oss, fmt, args...);
1122 return oss.str();
1123}
1124
1126template <typename... Args> void printf(const char *fmt, const Args &...args) {
1127 format(std::cout, fmt, args...);
1128}
1129
1130template <typename... Args>
1131void printfln(const char *fmt, const Args &...args) {
1132 format(std::cout, fmt, args...);
1133 std::cout << '\n';
1134}
1135
1136#else // C++98 version
1137
1138inline void format(std::ostream &out, const char *fmt) {
1139 vformat(out, fmt, makeFormatList());
1140}
1141
1142inline std::string format(const char *fmt) {
1143 std::ostringstream oss;
1144 format(oss, fmt);
1145 return oss.str();
1146}
1147
1148inline void printf(const char *fmt) {
1149 format(std::cout, fmt);
1150}
1151
1152inline void printfln(const char *fmt) {
1153 format(std::cout, fmt);
1154 std::cout << '\n';
1155}
1156
1157#define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
1158 \
1159 template <TINYFORMAT_ARGTYPES(n)> \
1160 void format(std::ostream &out, const char *fmt, TINYFORMAT_VARARGS(n)) { \
1161 vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
1162 } \
1163 \
1164 template <TINYFORMAT_ARGTYPES(n)> \
1165 std::string format(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1166 std::ostringstream oss; \
1167 format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
1168 return oss.str(); \
1169 } \
1170 \
1171 template <TINYFORMAT_ARGTYPES(n)> \
1172 void printf(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1173 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1174 } \
1175 \
1176 template <TINYFORMAT_ARGTYPES(n)> \
1177 void printfln(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1178 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1179 std::cout << '\n'; \
1180 }
1181
1183#undef TINYFORMAT_MAKE_FORMAT_FUNCS
1184
1185#endif
1186
1187// Added for Bitcoin
1188template <typename... Args>
1189std::string format(const std::string &fmt, const Args &...args) {
1190 std::ostringstream oss;
1191 format(oss, fmt.c_str(), args...);
1192 return oss.str();
1193}
1194
1195} // namespace tinyformat
1196
1197// Added for Bitcoin:
1202#define strprintf tfm::format
1203
1204#endif // TINYFORMAT_H_INCLUDED
List of template arguments format(), held in a type-opaque way.
friend void vformat(std::ostream &out, const char *fmt, const FormatList &list)
FormatList(detail::FormatArg *args, int N)
const detail::FormatArg * m_args
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:613
void format(std::ostream &out, const char *fmtBegin, const char *fmtEnd, int ntrunc) const
Definition tinyformat.h:583
FormatListN(const Args &...args)
FormatListN(const FormatListN &other)
format_error(const std::string &what)
Definition tinyformat.h:187
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:668
int parseIntAndAdvance(const char *&c)
Definition tinyformat.h:618
void formatImpl(std::ostream &out, const char *fmt, const detail::FormatArg *args, int numArgs)
Definition tinyformat.h:931
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:719
bool parseWidthOrPrecision(int &n, const char *&c, bool positionalMode, const detail::FormatArg *args, int &argIndex, int numArgs)
Definition tinyformat.h:630
detail::FormatListN< sizeof...(Args)> makeFormatList(const Args &...args)
Make type-agnostic format list from list of template arguments.
void vformat(std::ostream &out, const char *fmt, FormatListRef list)
Format list of arguments to the stream according to the given format string.
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()
void printfln(const char *fmt, const Args &...args)
void format(std::ostream &out, const char *fmt, const Args &...args)
Format list of arguments to the stream according to given format string.
void printf(const char *fmt, const Args &...args)
Format list of arguments to std::cout, according to the given format string.
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
Definition random.h:85
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