Bitcoin ABC  0.26.3
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 
128 namespace tinyformat {}
129 //------------------------------------------------------------------------------
130 // Config section. Customize to your liking!
131 
132 // Namespace alias to encourage brevity
133 namespace 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 
182 namespace tinyformat {
183 
184 // Added for Bitcoin
185 class format_error : public std::runtime_error {
186 public:
187  explicit format_error(const std::string &what) : std::runtime_error(what) {}
188 };
189 
190 //------------------------------------------------------------------------------
191 namespace 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>
275  struct convertToInt {
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 
326 template <typename T>
327 inline 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
404 maxParams = 16
405 
406 def 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 
411 makeCommaSepLists('#define TINYFORMAT_ARGTYPES_%(j)d %(list)s',
412  'class T%(i)d')
413 
414 cog.outl()
415 makeCommaSepLists('#define TINYFORMAT_VARARGS_%(j)d %(list)s',
416  'const T%(i)d& v%(i)d')
417 
418 cog.outl()
419 makeCommaSepLists('#define TINYFORMAT_PASSARGS_%(j)d %(list)s', 'v%(i)d')
420 
421 cog.outl()
422 cog.outl('#define TINYFORMAT_PASSARGS_TAIL_1')
423 makeCommaSepLists('#define TINYFORMAT_PASSARGS_TAIL_%(j)d , %(list)s',
424  'v%(i)d', startInd = 2)
425 
426 cog.outl()
427 cog.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 
568 namespace 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() : m_value(NULL), m_formatImpl(NULL), m_toIntImpl(NULL) {}
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;
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') {
635  n = parseIntAndAdvance(c);
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) {
725  TINYFORMAT_ASSERT(*fmtStart == '%');
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;
812  widthSet = parseWidthOrPrecision(width, c, positionalMode, args,
813  argIndex, numArgs);
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;
828  parseWidthOrPrecision(precision, c, positionalMode, args, argIndex,
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  }
918  if (intConversion && precisionSet && !widthSet) {
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) {
945  fmt = printFormatStringLiteral(out, fmt);
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 =
956  streamStateFromFormat(out, positionalMode, spacePadPositive,
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 
1004 class FormatList {
1005 public:
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 
1011 private:
1013  int m_N;
1014 };
1015 
1017 typedef const FormatList &FormatListRef;
1018 
1019 namespace 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  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 
1047  TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR)
1048 #undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
1049 #endif
1050  FormatListN(const FormatListN &other)
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 
1080 template <typename... Args>
1081 detail::FormatListN<sizeof...(Args)> makeFormatList(const Args &...args) {
1082  return detail::FormatListN<sizeof...(args)>(args...);
1083 }
1084 
1085 #else // C++98 version
1086 
1087 inline 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  }
1095 TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_MAKEFORMATLIST)
1096 #undef TINYFORMAT_MAKE_MAKEFORMATLIST
1097 
1098 #endif
1099 
1104 inline 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 
1111 template <typename... Args>
1112 void format(std::ostream &out, const char *fmt, const Args &...args) {
1113  vformat(out, fmt, makeFormatList(args...));
1114 }
1115 
1118 template <typename... Args>
1119 std::string format(const char *fmt, const Args &...args) {
1120  std::ostringstream oss;
1121  format(oss, fmt, args...);
1122  return oss.str();
1123 }
1124 
1126 template <typename... Args> void printf(const char *fmt, const Args &...args) {
1127  format(std::cout, fmt, args...);
1128 }
1129 
1130 template <typename... Args>
1131 void 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 
1138 inline void format(std::ostream &out, const char *fmt) {
1139  vformat(out, fmt, makeFormatList());
1140 }
1141 
1142 inline std::string format(const char *fmt) {
1143  std::ostringstream oss;
1144  format(oss, fmt);
1145  return oss.str();
1146 }
1147 
1148 inline void printf(const char *fmt) {
1149  format(std::cout, fmt);
1150 }
1151 
1152 inline 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 
1182 TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_FUNCS)
1183 #undef TINYFORMAT_MAKE_FORMAT_FUNCS
1184 
1185 #endif
1186 
1187 // Added for Bitcoin
1188 template <typename... Args>
1189 std::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.
Definition: tinyformat.h:1004
friend void vformat(std::ostream &out, const char *fmt, const FormatList &list)
FormatList(detail::FormatArg *args, int N)
Definition: tinyformat.h:1006
const detail::FormatArg * m_args
Definition: tinyformat.h:1012
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)
Definition: tinyformat.h:1026
FormatListN(const FormatListN &other)
Definition: tinyformat.h:1050
format_error(const std::string &what)
Definition: tinyformat.h:187
Definition: common.cpp:28
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:257
void formatTruncated(std::ostream &out, const T &value, int ntrunc)
Definition: tinyformat.h:289
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
const char * printFormatStringLiteral(std::ostream &out, const char *fmt)
Definition: tinyformat.h:668
bool parseWidthOrPrecision(int &n, const char *&c, bool positionalMode, const detail::FormatArg *args, int &argIndex, int numArgs)
Definition: tinyformat.h:630
Definition: fs.h:239
void formatValue(std::ostream &, const char *, const char *, int, const std::filesystem::path &)=delete
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:1104
detail::FormatListN< sizeof...(Args)> makeFormatList(const Args &...args)
Make type-agnostic format list from list of template arguments.
Definition: tinyformat.h:1081
const FormatList & FormatListRef
Reference to type-opaque format list for passing to vformat()
Definition: tinyformat.h:1017
void printfln(const char *fmt, const Args &...args)
Definition: tinyformat.h:1131
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:1112
void printf(const char *fmt, const Args &...args)
Format list of arguments to std::cout, according to the given format string.
Definition: tinyformat.h:1126
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