PIVX Core  5.6.99
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 // * Simplicity and minimalism. A single header file to include and distribute
37 // with your projects.
38 // * Augment rather than replace the standard stream formatting mechanism
39 // * C++98 support, with optional C++11 niceties
40 //
41 //
42 // Main interface example usage
43 // ----------------------------
44 //
45 // To print a date to std::cout:
46 //
47 // std::string weekday = "Wednesday";
48 // const char* month = "July";
49 // size_t day = 27;
50 // long hour = 14;
51 // int min = 44;
52 //
53 // tfm::printf("%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min);
54 //
55 // The strange types here emphasize the type safety of the interface; it is
56 // possible to print a std::string using the "%s" conversion, and a
57 // size_t using the "%d" conversion. A similar result could be achieved
58 // using either of the tfm::format() functions. One prints on a user provided
59 // stream:
60 //
61 // tfm::format(std::cerr, "%s, %s %d, %.2d:%.2d\n",
62 // weekday, month, day, hour, min);
63 //
64 // The other returns a std::string:
65 //
66 // std::string date = tfm::format("%s, %s %d, %.2d:%.2d\n",
67 // weekday, month, day, hour, min);
68 // std::cout << date;
69 //
70 // These are the three primary interface functions. There is also a
71 // convenience function printfln() which appends a newline to the usual result
72 // of printf() for super simple logging.
73 //
74 //
75 // User defined format functions
76 // -----------------------------
77 //
78 // Simulating variadic templates in C++98 is pretty painful since it requires
79 // writing out the same function for each desired number of arguments. To make
80 // this bearable tinyformat comes with a set of macros which are used
81 // internally to generate the API, but which may also be used in user code.
82 //
83 // The three macros TINYFORMAT_ARGTYPES(n), TINYFORMAT_VARARGS(n) and
84 // TINYFORMAT_PASSARGS(n) will generate a list of n argument types,
85 // type/name pairs and argument names respectively when called with an integer
86 // n between 1 and 16. We can use these to define a macro which generates the
87 // desired user defined function with n arguments. To generate all 16 user
88 // defined function bodies, use the macro TINYFORMAT_FOREACH_ARGNUM. For an
89 // example, see the implementation of printf() at the end of the source file.
90 //
91 // Sometimes it's useful to be able to pass a list of format arguments through
92 // to a non-template function. The FormatList class is provided as a way to do
93 // this by storing the argument list in a type-opaque way. Continuing the
94 // example from above, we construct a FormatList using makeFormatList():
95 //
96 // FormatListRef formatList = tfm::makeFormatList(weekday, month, day, hour, min);
97 //
98 // The format list can now be passed into any non-template function and used
99 // via a call to the vformat() function:
100 //
101 // tfm::vformat(std::cout, "%s, %s %d, %.2d:%.2d\n", formatList);
102 //
103 //
104 // Additional API information
105 // --------------------------
106 //
107 // Error handling: Define TINYFORMAT_ERROR to customize the error handling for
108 // format strings which are unsupported or have the wrong number of format
109 // specifiers (calls assert() by default).
110 //
111 // User defined types: Uses operator<< for user defined types by default.
112 // Overload formatValue() for more control.
113 
114 
115 #ifndef TINYFORMAT_H_INCLUDED
116 #define TINYFORMAT_H_INCLUDED
117 
118 namespace tinyformat
119 {
120 }
121 //------------------------------------------------------------------------------
122 // Config section. Customize to your liking!
123 
124 // Namespace alias to encourage brevity
125 namespace tfm = tinyformat;
126 
127 // Error handling; calls assert() by default.
128 #define TINYFORMAT_ERROR(reasonString) throw tinyformat::format_error(reasonString)
129 
130 // Define for C++11 variadic templates which make the code shorter & more
131 // general. If you don't define this, C++11 support is autodetected below.
132 #define TINYFORMAT_USE_VARIADIC_TEMPLATES
133 
134 
135 //------------------------------------------------------------------------------
136 // Implementation details.
137 #include <algorithm>
138 #include <cassert>
139 #include <iostream>
140 #include <sstream>
141 #include <stdexcept>
142 
143 #ifndef TINYFORMAT_ERROR
144 #define TINYFORMAT_ERROR(reason) assert(0 && reason)
145 #endif
146 
147 #if !defined(TINYFORMAT_USE_VARIADIC_TEMPLATES) && !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES)
148 #ifdef __GXX_EXPERIMENTAL_CXX0X__
149 #define TINYFORMAT_USE_VARIADIC_TEMPLATES
150 #endif
151 #endif
152 
153 #if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
154 // std::showpos is broken on old libstdc++ as provided with OSX. See
155 // http://gcc.gnu.org/ml/libstdc++/2007-11/msg00075.html
156 #define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
157 #endif
158 
159 #ifdef __APPLE__
160 // Workaround OSX linker warning: xcode uses different default symbol
161 // visibilities for static libs vs executables (see bitcoin's issue #25)
162 # define TINYFORMAT_HIDDEN __attribute__((visibility("hidden")))
163 #else
164 # define TINYFORMAT_HIDDEN
165 #endif
166 
167 namespace tinyformat
168 {
169 
170 class format_error: public std::runtime_error
171 {
172 public:
173  explicit format_error(const std::string &what): std::runtime_error(what) {
174  }
175 };
176 
177 //------------------------------------------------------------------------------
178 namespace detail
179 {
180 // Test whether type T1 is convertible to type T2
181 template <typename T1, typename T2>
183 private:
184  // two types of different size
185  struct fail {
186  char dummy[2];
187  };
188  struct succeed {
189  char dummy;
190  };
191  // Try to convert a T1 to a T2 by plugging into tryConvert
192  static fail tryConvert(...);
193  static succeed tryConvert(const T2&);
194  static const T1& makeT1();
195 
196 public:
197 #ifdef _MSC_VER
198 // Disable spurious loss of precision warnings in tryConvert(makeT1())
199 #pragma warning(push)
200 #pragma warning(disable : 4244)
201 #pragma warning(disable : 4267)
202 #endif
203  // Standard trick: the (...) version of tryConvert will be chosen from
204  // the overload set only if the version taking a T2 doesn't match.
205  // Then we compare the sizes of the return types to check which
206  // function matched. Very neat, in a disgusting kind of way :)
207  static const bool value =
208  sizeof(tryConvert(makeT1())) == sizeof(succeed);
209 #ifdef _MSC_VER
210 #pragma warning(pop)
211 #endif
212 };
213 
214 
215 // Detect when a type is not a wchar_t string
216 template <typename T>
217 struct is_wchar {
219 };
220 template <>
221 struct is_wchar<wchar_t*> {
222 };
223 template <>
224 struct is_wchar<const wchar_t*> {
225 };
226 template <int n>
227 struct is_wchar<const wchar_t[n]> {
228 };
229 template <int n>
230 struct is_wchar<wchar_t[n]> {
231 };
232 
233 
234 // Format the value by casting to type fmtT. This default implementation
235 // should never be called.
236 template <typename T, typename fmtT, bool convertible = is_convertible<T, fmtT>::value>
238  static void invoke(std::ostream& /*out*/, const T& /*value*/) { assert(0); }
239 };
240 // Specialized version for types that can actually be converted to fmtT, as
241 // indicated by the "convertible" template parameter.
242 template <typename T, typename fmtT>
243 struct formatValueAsType<T, fmtT, true> {
244  static void invoke(std::ostream& out, const T& value)
245  {
246  out << static_cast<fmtT>(value);
247  }
248 };
249 
250 #ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
251 template <typename T, bool convertible = is_convertible<T, int>::value>
252 struct formatZeroIntegerWorkaround {
253  static bool invoke(std::ostream& , const T& ) { return false; }
254 };
255 template <typename T>
256 struct formatZeroIntegerWorkaround<T, true> {
257  static bool invoke(std::ostream& out, const T& value)
258  {
259  if (static_cast<int>(value) == 0 && out.flags() & std::ios::showpos) {
260  out << "+0";
261  return true;
262  }
263  return false;
264  }
265 };
266 #endif // TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
267 
268 // Convert an arbitrary type to integer. The version with convertible=false
269 // throws an error.
270 template <typename T, bool convertible = is_convertible<T, int>::value>
271 struct convertToInt {
272  static int invoke(const T& /*value*/)
273  {
274  TINYFORMAT_ERROR("tinyformat: Cannot convert from argument type to "
275  "integer for use as variable width or precision");
276  return 0;
277  }
278 };
279 // Specialization for convertToInt when conversion is possible
280 template <typename T>
281 struct convertToInt<T, true> {
282  static int invoke(const T& value) { return static_cast<int>(value); }
283 };
284 
285 // Format at most ntrunc characters to the given stream.
286 template<typename T>
287 inline void formatTruncated(std::ostream& out, const T& value, int ntrunc)
288 {
289  std::ostringstream tmp;
290  tmp << value;
291  std::string result = tmp.str();
292  out.write(result.c_str(), (std::min)(ntrunc, static_cast<int>(result.size())));
293 }
294 #define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type) \
295 inline void formatTruncated(std::ostream& out, type* value, int ntrunc) \
296 { \
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 //------------------------------------------------------------------------------
323 template <typename T>
324 inline void formatValue(std::ostream& out, const char* /*fmtBegin*/,
325  const char* fmtEnd, int ntrunc, const T& value)
326 {
327 #ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS
328  // Since we don't support printing of wchar_t using "%ls", make it fail at
329  // compile time in preference to printing as a void* at runtime.
331  (void)DummyType(); // avoid unused type warning with gcc-4.8
332 #endif
333  // The mess here is to support the %c and %p conversions: if these
334  // conversions are active we try to convert the type to a char or const
335  // void* respectively and format that instead of the value itself. For the
336  // %p conversion it's important to avoid dereferencing the pointer, which
337  // could otherwise lead to a crash when printing a dangling (const char*).
338  const bool canConvertToChar = detail::is_convertible<T, char>::value;
339  const bool canConvertToVoidPtr = detail::is_convertible<T, const void*>::value;
340  if (canConvertToChar && *(fmtEnd - 1) == 'c')
342  else if (canConvertToVoidPtr && *(fmtEnd - 1) == 'p')
344 #ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
345  else if (detail::formatZeroIntegerWorkaround<T>::invoke(out, value)) ;
346 #endif
347  else if(ntrunc >= 0)
348  {
349  // Take care not to overread C strings in truncating conversions like
350  // "%.4s" where at most 4 characters may be read.
351  detail::formatTruncated(out, value, ntrunc);
352  }
353  else
354  out << value;
355 }
356 
357 
358 // Overloaded version for char types to support printing as an integer
359 #define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \
360  inline void formatValue(std::ostream& out, const char* /*fmtBegin*/, \
361  const char* fmtEnd, int , charType value) \
362  { \
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 unsigned char are all distinct types
381 #undef TINYFORMAT_DEFINE_FORMATVALUE_CHAR
382 
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  std::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 class T1, class T2, class T3, class T4, class T5, class T6
436 #define TINYFORMAT_ARGTYPES_7 class T1, class T2, class T3, class T4, class T5, class T6, class T7
437 #define TINYFORMAT_ARGTYPES_8 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8
438 #define TINYFORMAT_ARGTYPES_9 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9
439 #define TINYFORMAT_ARGTYPES_10 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10
440 #define TINYFORMAT_ARGTYPES_11 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11
441 #define TINYFORMAT_ARGTYPES_12 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12
442 #define TINYFORMAT_ARGTYPES_13 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13
443 #define TINYFORMAT_ARGTYPES_14 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14
444 #define TINYFORMAT_ARGTYPES_15 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15
445 #define TINYFORMAT_ARGTYPES_16 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15, class T16
446 
447 #define TINYFORMAT_VARARGS_1 const T1& v1
448 #define TINYFORMAT_VARARGS_2 const T1 &v1, const T2 &v2
449 #define TINYFORMAT_VARARGS_3 const T1 &v1, const T2 &v2, const T3 &v3
450 #define TINYFORMAT_VARARGS_4 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4
451 #define TINYFORMAT_VARARGS_5 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5
452 #define TINYFORMAT_VARARGS_6 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6
453 #define TINYFORMAT_VARARGS_7 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7
454 #define TINYFORMAT_VARARGS_8 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8
455 #define TINYFORMAT_VARARGS_9 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9
456 #define TINYFORMAT_VARARGS_10 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10
457 #define TINYFORMAT_VARARGS_11 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10, const T11 &v11
458 #define TINYFORMAT_VARARGS_12 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10, const T11 &v11, const T12 &v12
459 #define TINYFORMAT_VARARGS_13 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13
460 #define TINYFORMAT_VARARGS_14 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, const T14 &v14
461 #define TINYFORMAT_VARARGS_15 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, const T14 &v14, const T15 &v15
462 #define TINYFORMAT_VARARGS_16 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, const T14 &v14, const T15 &v15, const T16 &v16
463 
464 #define TINYFORMAT_PASSARGS_1 v1
465 #define TINYFORMAT_PASSARGS_2 v1, v2
466 #define TINYFORMAT_PASSARGS_3 v1, v2, v3
467 #define TINYFORMAT_PASSARGS_4 v1, v2, v3, v4
468 #define TINYFORMAT_PASSARGS_5 v1, v2, v3, v4, v5
469 #define TINYFORMAT_PASSARGS_6 v1, v2, v3, v4, v5, v6
470 #define TINYFORMAT_PASSARGS_7 v1, v2, v3, v4, v5, v6, v7
471 #define TINYFORMAT_PASSARGS_8 v1, v2, v3, v4, v5, v6, v7, v8
472 #define TINYFORMAT_PASSARGS_9 v1, v2, v3, v4, v5, v6, v7, v8, v9
473 #define TINYFORMAT_PASSARGS_10 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10
474 #define TINYFORMAT_PASSARGS_11 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
475 #define TINYFORMAT_PASSARGS_12 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
476 #define TINYFORMAT_PASSARGS_13 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
477 #define TINYFORMAT_PASSARGS_14 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
478 #define TINYFORMAT_PASSARGS_15 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
479 #define TINYFORMAT_PASSARGS_16 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
480 
481 #define TINYFORMAT_PASSARGS_TAIL_1
482 #define TINYFORMAT_PASSARGS_TAIL_2 , v2
483 #define TINYFORMAT_PASSARGS_TAIL_3 , v2, v3
484 #define TINYFORMAT_PASSARGS_TAIL_4 , v2, v3, v4
485 #define TINYFORMAT_PASSARGS_TAIL_5 , v2, v3, v4, v5
486 #define TINYFORMAT_PASSARGS_TAIL_6 , v2, v3, v4, v5, v6
487 #define TINYFORMAT_PASSARGS_TAIL_7 , v2, v3, v4, v5, v6, v7
488 #define TINYFORMAT_PASSARGS_TAIL_8 , v2, v3, v4, v5, v6, v7, v8
489 #define TINYFORMAT_PASSARGS_TAIL_9 , v2, v3, v4, v5, v6, v7, v8, v9
490 #define TINYFORMAT_PASSARGS_TAIL_10 , v2, v3, v4, v5, v6, v7, v8, v9, v10
491 #define TINYFORMAT_PASSARGS_TAIL_11 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
492 #define TINYFORMAT_PASSARGS_TAIL_12 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
493 #define TINYFORMAT_PASSARGS_TAIL_13 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
494 #define TINYFORMAT_PASSARGS_TAIL_14 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
495 #define TINYFORMAT_PASSARGS_TAIL_15 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
496 #define TINYFORMAT_PASSARGS_TAIL_16 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
497 
498 #define TINYFORMAT_FOREACH_ARGNUM(m) \
499  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) m(15) m(16)
500 //[[[end]]]
501 
502 
503 namespace detail
504 {
505 // Type-opaque holder for an argument to format(), with associated actions on
506 // the type held as explicit function pointers. This allows FormatArg's for
507 // each argument to be allocated as a homogenous array inside FormatList
508 // whereas a naive implementation based on inheritance does not.
510 {
511 public:
513 
514  template<typename T>
515  explicit FormatArg(const T& value)
516  : m_value(static_cast<const void*>(&value)),
519  { }
520 
521  void format(std::ostream& out, const char* fmtBegin,
522  const char* fmtEnd, int ntrunc) const
523  {
524  m_formatImpl(out, fmtBegin, fmtEnd, ntrunc, m_value);
525  }
526 
527  int toInt() const
528  {
529  return m_toIntImpl(m_value);
530  }
531 
532 private:
533  template<typename T>
534  TINYFORMAT_HIDDEN static void formatImpl(std::ostream& out, const char* fmtBegin,
535  const char* fmtEnd, int ntrunc, const void* value)
536  {
537  formatValue(out, fmtBegin, fmtEnd, ntrunc, *static_cast<const T*>(value));
538  }
539 
540  template <typename T>
541  TINYFORMAT_HIDDEN static int toIntImpl(const void* value)
542  {
543  return convertToInt<T>::invoke(*static_cast<const T*>(value));
544  }
545 
546  const void* m_value;
547  void (*m_formatImpl)(std::ostream& out, const char* fmtBegin,
548  const char* fmtEnd, int ntrunc, const void* value);
549  int (*m_toIntImpl)(const void* value);
550 };
551 
552 
553 // Parse and return an integer from the string c, as atoi()
554 // On return, c is set to one past the end of the integer.
555 inline int parseIntAndAdvance(const char*& c)
556 {
557  int i = 0;
558  for(;*c >= '0' && *c <= '9'; ++c)
559  i = 10*i + (*c - '0');
560  return i;
561 }
562 
563 // Print literal part of format string and return next format spec
564 // position.
565 //
566 // Skips over any occurrences of '%%', printing a literal '%' to the
567 // output. The position of the first % character of the next
568 // nontrivial format spec is returned, or the end of string.
569 inline const char* printFormatStringLiteral(std::ostream& out, const char* fmt)
570 {
571  const char* c = fmt;
572  for(;; ++c) {
573  switch(*c)
574  {
575  case '\0':
576  out.write(fmt, c - fmt);
577  return c;
578  case '%':
579  out.write(fmt, c - fmt);
580  if(*(c+1) != '%')
581  return c;
582  // for "%%", tack trailing % onto next literal section.
583  fmt = ++c;
584  break;
585  default:
586  break;
587  }
588  }
589 }
590 
591 
592 // Parse a format string and set the stream state accordingly.
593 //
594 // The format mini-language recognized here is meant to be the one from C99,
595 // with the form "%[flags][width][.precision][length]type".
596 //
597 // Formatting options which can't be natively represented using the ostream
598 // state are returned in spacePadPositive (for space padded positive numbers)
599 // and ntrunc (for truncating conversions). argIndex is incremented if
600 // necessary to pull out variable width and precision . The function returns a
601 // pointer to the character after the end of the current format spec.
602 inline const char* streamStateFromFormat(std::ostream& out, bool& spacePadPositive,
603  int& ntrunc, const char* fmtStart,
604  const detail::FormatArg* formatters,
605  int& argIndex, int numFormatters)
606 {
607  if (*fmtStart != '%') {
608  TINYFORMAT_ERROR("tinyformat: Not enough conversion specifiers in format string");
609  return fmtStart;
610  }
611  // Reset stream state to defaults.
612  out.width(0);
613  out.precision(6);
614  out.fill(' ');
615  // Reset most flags; ignore irrelevant unitbuf & skipws.
616  out.unsetf(std::ios::adjustfield | std::ios::basefield |
617  std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |
618  std::ios::showpoint | std::ios::showpos | std::ios::uppercase);
619  bool precisionSet = false;
620  bool widthSet = false;
621  int widthExtra = 0;
622  const char* c = fmtStart + 1;
623  // 1) Parse flags
624  for (;; ++c) {
625  switch (*c) {
626  case '#':
627  out.setf(std::ios::showpoint | std::ios::showbase);
628  continue;
629  case '0':
630  // overridden by left alignment ('-' flag)
631  if (!(out.flags() & std::ios::left)) {
632  // Use internal padding so that numeric values are
633  // formatted correctly, eg -00010 rather than 000-10
634  out.fill('0');
635  out.setf(std::ios::internal, std::ios::adjustfield);
636  }
637  continue;
638  case '-':
639  out.fill(' ');
640  out.setf(std::ios::left, std::ios::adjustfield);
641  continue;
642  case ' ':
643  // overridden by show positive sign, '+' flag.
644  if (!(out.flags() & std::ios::showpos))
645  spacePadPositive = true;
646  continue;
647  case '+':
648  out.setf(std::ios::showpos);
649  spacePadPositive = false;
650  widthExtra = 1;
651  continue;
652  default:
653  break;
654  }
655  break;
656  }
657  // 2) Parse width
658  if (*c >= '0' && *c <= '9') {
659  widthSet = true;
660  out.width(parseIntAndAdvance(c));
661  }
662  if (*c == '*') {
663  widthSet = true;
664  int width = 0;
665  if(argIndex < numFormatters)
666  width = formatters[argIndex++].toInt();
667  else
668  TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable width");
669  if(width < 0) {
670  // negative widths correspond to '-' flag set
671  out.fill(' ');
672  out.setf(std::ios::left, std::ios::adjustfield);
673  width = -width;
674  }
675  out.width(width);
676  ++c;
677  }
678  // 3) Parse precision
679  if (*c == '.') {
680  ++c;
681  int precision = 0;
682  if (*c == '*') {
683  ++c;
684  if(argIndex < numFormatters)
685  precision = formatters[argIndex++].toInt();
686  else
687  TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable precision");
688  } else {
689  if (*c >= '0' && *c <= '9')
690  precision = parseIntAndAdvance(c);
691  else if (*c == '-') // negative precisions ignored, treated as zero.
692  parseIntAndAdvance(++c);
693  }
694  out.precision(precision);
695  precisionSet = true;
696  }
697  // 4) Ignore any C99 length modifier
698  while (*c == 'l' || *c == 'h' || *c == 'L' ||
699  *c == 'j' || *c == 'z' || *c == 't')
700  ++c;
701  // 5) We're up to the conversion specifier character.
702  // Set stream flags based on conversion specifier (thanks to the
703  // boost::format class for forging the way here).
704  bool intConversion = false;
705  switch (*c) {
706  case 'u':
707  case 'd':
708  case 'i':
709  out.setf(std::ios::dec, std::ios::basefield);
710  intConversion = true;
711  break;
712  case 'o':
713  out.setf(std::ios::oct, std::ios::basefield);
714  intConversion = true;
715  break;
716  case 'X':
717  out.setf(std::ios::uppercase);
718  case 'x':
719  case 'p':
720  out.setf(std::ios::hex, std::ios::basefield);
721  intConversion = true;
722  break;
723  case 'E':
724  out.setf(std::ios::uppercase);
725  case 'e':
726  out.setf(std::ios::scientific, std::ios::floatfield);
727  out.setf(std::ios::dec, std::ios::basefield);
728  break;
729  case 'F':
730  out.setf(std::ios::uppercase);
731  case 'f':
732  out.setf(std::ios::fixed, std::ios::floatfield);
733  break;
734  case 'G':
735  out.setf(std::ios::uppercase);
736  case 'g':
737  out.setf(std::ios::dec, std::ios::basefield);
738  // As in boost::format, let stream decide float format.
739  out.flags(out.flags() & ~std::ios::floatfield);
740  break;
741  case 'a':
742  case 'A':
743  TINYFORMAT_ERROR("tinyformat: the %a and %A conversion specs "
744  "are not supported");
745  break;
746  case 'c':
747  // Handled as special case inside formatValue()
748  break;
749  case 's':
750  if (precisionSet)
751  ntrunc = static_cast<int>(out.precision());
752  // Make %s print booleans as "true" and "false"
753  out.setf(std::ios::boolalpha);
754  break;
755  case 'n':
756  // Not supported - will cause problems!
757  TINYFORMAT_ERROR("tinyformat: %n conversion spec not supported");
758  break;
759  case '\0':
760  TINYFORMAT_ERROR("tinyformat: Conversion spec incorrectly "
761  "terminated by end of string");
762  return c;
763  default:
764  break;
765  }
766  if (intConversion && precisionSet && !widthSet) {
767  // "precision" for integers gives the minimum number of digits (to be
768  // padded with zeros on the left). This isn't really supported by the
769  // iostreams, but we can approximately simulate it with the width if
770  // the width isn't otherwise used.
771  out.width(out.precision() + widthExtra);
772  out.setf(std::ios::internal, std::ios::adjustfield);
773  out.fill('0');
774  }
775  return c + 1;
776 }
777 
778 
779 //------------------------------------------------------------------------------
780 inline void formatImpl(std::ostream& out, const char* fmt,
781  const detail::FormatArg* formatters,
782  int numFormatters)
783 {
784  // Saved stream state
785  std::streamsize origWidth = out.width();
786  std::streamsize origPrecision = out.precision();
787  std::ios::fmtflags origFlags = out.flags();
788  char origFill = out.fill();
789 
790  for (int argIndex = 0; argIndex < numFormatters; ++argIndex)
791  {
792  // Parse the format string
793  fmt = printFormatStringLiteral(out, fmt);
794  bool spacePadPositive = false;
795  int ntrunc = -1;
796  const char* fmtEnd = streamStateFromFormat(out, spacePadPositive, ntrunc, fmt,
797  formatters, argIndex, numFormatters);
798  if (argIndex >= numFormatters)
799  {
800  // Check args remain after reading any variable width/precision
801  TINYFORMAT_ERROR("tinyformat: Not enough format arguments");
802  return;
803  }
804  const FormatArg& arg = formatters[argIndex];
805  // Format the arg into the stream.
806  if(!spacePadPositive)
807  arg.format(out, fmt, fmtEnd, ntrunc);
808  else
809  {
810  // The following is a special case with no direct correspondence
811  // between stream formatting and the printf() behaviour. Simulate
812  // it crudely by formatting into a temporary string stream and
813  // munging the resulting string.
814  std::ostringstream tmpStream;
815  tmpStream.copyfmt(out);
816  tmpStream.setf(std::ios::showpos);
817  arg.format(tmpStream, fmt, fmtEnd, ntrunc);
818  std::string result = tmpStream.str(); // allocates... yuck.
819  for(size_t i = 0, iend = result.size(); i < iend; ++i)
820  if(result[i] == '+') result[i] = ' ';
821  out << result;
822  }
823  fmt = fmtEnd;
824  }
825 
826  // Print remaining part of format string.
827  fmt = printFormatStringLiteral(out, fmt);
828  if(*fmt != '\0')
829  TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string");
830 
831  // Restore stream state
832  out.width(origWidth);
833  out.precision(origPrecision);
834  out.flags(origFlags);
835  out.fill(origFill);
836 }
837 
838 } // namespace detail
839 
840 
848 {
849 public:
850  FormatList(detail::FormatArg* formatters, int N)
851  : m_formatters(formatters), m_N(N) { }
852 
853  friend void vformat(std::ostream& out, const char* fmt,
854  const FormatList& list);
855 
856 private:
858  int m_N;
859 };
860 
862 typedef const FormatList& FormatListRef;
863 
864 
865 namespace detail {
866 
867 // Format list subclass with fixed storage to avoid dynamic allocation
868 template<int N>
869 class FormatListN : public FormatList
870 {
871 public:
872 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
873  template<typename... Args>
874  explicit FormatListN(const Args&... args)
875  : FormatList(&m_formatterStore[0], N),
876  m_formatterStore { FormatArg(args)... }
877  { static_assert(sizeof...(args) == N, "Number of args must be N"); }
878 #else // C++98 version
879  void init(int) {}
880 # define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
881  \
882  template<TINYFORMAT_ARGTYPES(n)> \
883  explicit FormatListN(TINYFORMAT_VARARGS(n)) \
884  : FormatList(&m_formatterStore[0], n) \
885  { assert(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \
886  \
887  template<TINYFORMAT_ARGTYPES(n)> \
888  void init(int i, TINYFORMAT_VARARGS(n)) \
889  { \
890  m_formatterStore[i] = FormatArg(v1); \
891  init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \
892  }
893 
894  TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR)
895 # undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
896 #endif
897 private:
899 };
900 
901 // Special 0-arg version - MSVC says zero-sized C array in struct is nonstandard
902 template<> class FormatListN<0> : public FormatList
903 {
904  public: FormatListN() : FormatList(0, 0) {}
905 };
906 
907 } // namespace detail
908 
909 
910 //------------------------------------------------------------------------------
911 // Primary API functions
912 
913 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
914 
921 template<typename... Args>
922 detail::FormatListN<sizeof...(Args)> makeFormatList(const Args&... args)
923 {
924  return detail::FormatListN<sizeof...(args)>(args...);
925 }
926 
927 #else // C++98 version
928 
929 inline detail::FormatListN<0> makeFormatList()
930 {
931  return detail::FormatListN<0>();
932 }
933 #define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
934 template<TINYFORMAT_ARGTYPES(n)> \
935 detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) \
936 { \
937  return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
938 }
939 TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_MAKEFORMATLIST)
940 #undef TINYFORMAT_MAKE_MAKEFORMATLIST
941 
942 #endif
943 
948 inline void vformat(std::ostream& out, const char* fmt, FormatListRef list)
949 {
950  detail::formatImpl(out, fmt, list.m_formatters, list.m_N);
951 }
952 
953 
954 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
955 
957 template<typename... Args>
958 void format(std::ostream& out, const char* fmt, const Args&... args)
959 {
960  vformat(out, fmt, makeFormatList(args...));
961 }
962 
965 template<typename... Args>
966 std::string format(const char* fmt, const Args&... args)
967 {
968  std::ostringstream oss;
969  format(oss, fmt, args...);
970  return oss.str();
971 }
972 
974 template<typename... Args>
975 void printf(const char* fmt, const Args&... args)
976 {
977  format(std::cout, fmt, args...);
978 }
979 
980 template<typename... Args>
981 void printfln(const char* fmt, const Args&... args)
982 {
983  format(std::cout, fmt, args...);
984  std::cout << '\n';
985 }
986 
987 #else // C++98 version
988 
989 inline void format(std::ostream& out, const char* fmt)
990 {
991  vformat(out, fmt, makeFormatList());
992 }
993 
994 inline std::string format(const char* fmt)
995 {
996  std::ostringstream oss;
997  format(oss, fmt);
998  return oss.str();
999 }
1000 
1001 inline void printf(const char* fmt)
1002 {
1003  format(std::cout, fmt);
1004 }
1005 
1006 inline void printfln(const char* fmt)
1007 {
1008  format(std::cout, fmt);
1009  std::cout << '\n';
1010 }
1011 
1012 #define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
1013  \
1014  template <TINYFORMAT_ARGTYPES(n)> \
1015  void format(std::ostream& out, const char* fmt, TINYFORMAT_VARARGS(n)) \
1016  { \
1017  vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
1018  } \
1019  \
1020  template <TINYFORMAT_ARGTYPES(n)> \
1021  std::string format(const char* fmt, TINYFORMAT_VARARGS(n)) \
1022  { \
1023  std::ostringstream oss; \
1024  format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
1025  return oss.str(); \
1026  } \
1027  \
1028  template <TINYFORMAT_ARGTYPES(n)> \
1029  void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \
1030  { \
1031  format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1032  } \
1033  \
1034  template <TINYFORMAT_ARGTYPES(n)> \
1035  void printfln(const char* fmt, TINYFORMAT_VARARGS(n)) \
1036  { \
1037  format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1038  std::cout << '\n'; \
1039  }
1040 
1041 TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_FUNCS)
1042 #undef TINYFORMAT_MAKE_FORMAT_FUNCS
1043 #endif
1044 
1045 // Added for Bitcoin Core
1046 template<typename... Args>
1047 std::string format(const std::string &fmt, const Args&... args)
1048 {
1049  std::ostringstream oss;
1050  format(oss, fmt.c_str(), args...);
1051  return oss.str();
1052 }
1053 
1054 } // namespace tinyformat
1055 
1056 #define strprintf tfm::format
1057 
1058 #endif // TINYFORMAT_H_INCLUDED
true
Definition: bls_dkg.cpp:153
List of template arguments format(), held in a type-opaque way.
Definition: tinyformat.h:848
friend void vformat(std::ostream &out, const char *fmt, const FormatList &list)
FormatList(detail::FormatArg *formatters, int N)
Definition: tinyformat.h:850
const detail::FormatArg * m_formatters
Definition: tinyformat.h:857
static TINYFORMAT_HIDDEN void formatImpl(std::ostream &out, const char *fmtBegin, const char *fmtEnd, int ntrunc, const void *value)
Definition: tinyformat.h:534
void(* m_formatImpl)(std::ostream &out, const char *fmtBegin, const char *fmtEnd, int ntrunc, const void *value)
Definition: tinyformat.h:547
static TINYFORMAT_HIDDEN int toIntImpl(const void *value)
Definition: tinyformat.h:541
int(* m_toIntImpl)(const void *value)
Definition: tinyformat.h:549
void format(std::ostream &out, const char *fmtBegin, const char *fmtEnd, int ntrunc) const
Definition: tinyformat.h:521
FormatListN(const Args &... args)
Definition: tinyformat.h:874
format_error(const std::string &what)
Definition: tinyformat.h:173
#define T(expected, seed, data)
Definition: uint256.h:212
void formatImpl(std::ostream &out, const char *fmt, const detail::FormatArg *formatters, int numFormatters)
Definition: tinyformat.h:780
void formatTruncated(std::ostream &out, const T &value, int ntrunc)
Definition: tinyformat.h:287
int parseIntAndAdvance(const char *&c)
Definition: tinyformat.h:555
const char * streamStateFromFormat(std::ostream &out, bool &spacePadPositive, int &ntrunc, const char *fmtStart, const detail::FormatArg *formatters, int &argIndex, int numFormatters)
Definition: tinyformat.h:602
const char * printFormatStringLiteral(std::ostream &out, const char *fmt)
Definition: tinyformat.h:569
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:958
void printfln(const char *fmt, const Args &... args)
Definition: tinyformat.h:981
void printf(const char *fmt, const Args &... args)
Format list of arguments to std::cout, according to the given format string.
Definition: tinyformat.h:975
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:948
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:324
detail::FormatListN< sizeof...(Args)> makeFormatList(const Args &... args)
Make type-agnostic format list from list of template arguments.
Definition: tinyformat.h:922
const FormatList & FormatListRef
Reference to type-opaque format list for passing to vformat()
Definition: tinyformat.h:862
static int invoke(const T &value)
Definition: tinyformat.h:282
static int invoke(const T &)
Definition: tinyformat.h:272
static void invoke(std::ostream &out, const T &value)
Definition: tinyformat.h:244
static void invoke(std::ostream &, const T &)
Definition: tinyformat.h:238
static succeed tryConvert(const T2 &)
#define TINYFORMAT_HIDDEN
Definition: tinyformat.h:164
#define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type)
Definition: tinyformat.h:294
#define TINYFORMAT_ERROR(reasonString)
Definition: tinyformat.h:128
#define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType)
Definition: tinyformat.h:359
#define TINYFORMAT_FOREACH_ARGNUM(m)
Definition: tinyformat.h:498