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