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