HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_Format.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_Format.h ( UT Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __UT_Format__
12 #define __UT_Format__
13 
14 #include "UT_API.h"
15 
16 #include "UT_Assert.h"
17 #include "UT_NonCopyable.h"
18 
19 #include <SYS/SYS_Types.h>
20 
21 #include <algorithm>
22 #include <initializer_list>
23 #include <iosfwd>
24 #include <limits>
25 #include <string>
26 #include <type_traits>
27 
28 #include <stdio.h>
29 
30 class UT_String;
31 class UT_StringHolder;
32 class UT_StringLit;
33 class UT_StringRef;
34 class UT_StringView;
35 
36 /// @file UT_Format.h
37 /// @brief Type-safe formatting, modeled on the Python @c str.format function.
38 ///
39 /// This formatter supports a sub-set of the Python format syntax. Notably,
40 /// only indexed arguments are supported for now, not named ones.
41 ///
42 /// Like with the @c printf() formatting, the format string contains
43 /// replacement fields that will be substituted by the textual representation
44 /// of the arguments to the various format functions. The replacement fields
45 /// for this formatter are surrounded by curly braces `{}`, rather than
46 /// prefixed with a `%`.
47 ///
48 /// Note the string `{{` or `}}` will result in a single `{` or `}` being
49 /// output.
50 ///
51 /// @section format_grammar Format Grammar
52 /// The grammar for the replacement field is as follows:
53 ///
54 /// {[<index>][:<spec>]}
55 ///
56 /// The `<index>` is an optional integer value, which refers to the position of
57 /// the argument after the format string. If the `<index>` is omitted for all
58 /// replacement fields, then they are automatically substituted with
59 /// `0, 1, 2, ...`
60 /// It is not permitted to mix indexed and non-indexed.
61 ///
62 /// If a colon separator is found, the string after that is interpreted as a
63 /// formatting specification. The grammar for the `<spec>` field is as follows:
64 ///
65 /// [[<fill>]<align>][<sign>][#][,][0][<width>][.<precision>][<type>]
66 ///
67 /// Where:
68 /// - `<fill>` is the fill character to use when the width of the field is
69 /// greater than the length of the argument value being printed.
70 /// - `<align>` is a single character code which sets the alignment of the
71 /// value within the field:
72 /// - `<`: The field is left-aligned. This is the default for non-numeric
73 /// values.
74 /// - `>`: The field is right-aligned. This is the default for numeric values.
75 /// - `^`: The field is center-aligned.
76 /// - `=`: The field is number aligned. This is the same as right-aligned,
77 /// except the fill value is inserted between the sign indicator and
78 /// the numeric value. This alignment is only available for numeric
79 /// values.
80 /// - <sign> is a single character that specifies how the sign is printed for
81 /// numeric values:
82 /// - `+`: Always print a sign, whether positive or negative.
83 /// - `-`: Only print a sign when the number is negative.
84 /// - `<space>`: Use a leading space on positive numbers, minus sign for
85 /// negative.
86 /// - The '#' option is only available for binary, octal or hexadecimal output.
87 /// It indicates that they should be prefixed with '0b', '0' and '0x',
88 /// respectively.
89 /// - The ',' option will add digit grouping to numerical outputs. For float
90 //// numbers, this only applies to the integer portion of the float.
91 /// - `<width>` specifies the minimum width of the field. Arguments wider than
92 /// this value will still be printed out in full. Preceding the width field
93 /// with `0` will automatically set the alignment to number alignment, and
94 /// the fill value to `0`.
95 /// - `<precision>` sets the precision for floating point numbers. For other
96 /// types it specifies the maximum width of the field.
97 /// - `<type>` is a single character code that specifies how the type should be
98 /// interpreted. If an argument type is not valid for the formatting type,
99 /// the formatting type is ignored. The supported types are:
100 /// - `b`: Output integers as binary numbers.
101 /// - `B`: Output integers as binary numbers with an upper-case prefix (if
102 /// using the `#` option.
103 /// - `c`: Output integers interpreted as a Unicode code point.
104 /// - `d`: Output integers as decimal numbers. This is the default for
105 /// integers.
106 /// - `e`: Use the exponent notation for floating point numbers.
107 /// - `E`: Same as `e`, except the exponent separator is upper-cased.
108 /// - `f`: Use the fixed point notation for floating point numbers.
109 /// - `F`: Same as `f`.
110 /// - `g`: Format a floating point number as either fixed point or scientific,
111 /// depending on its magnitude, which mostly results in the shortest
112 /// form being used. This is the default for floats.
113 /// - `G`: Same as `g`, except the exponent separator is upper-cased.
114 /// - `o`: Output integers as octals.
115 /// - `x`: Output integers and floats as hexadecimal. For floats this uses
116 /// the special hexadecimal float output.
117 /// - `X`: The same as `x`, except all alphabetic digits and prefix are
118 /// output in upper-case.
119 /// - `%`: Takes a floating point number, multiplies it by 100 and outputs it
120 /// with a percentage sign appended, using fixed point notation. The
121 /// default precision in this mode is 2.
122 ///
123 /// Example:
124 /// @code{.cpp}
125 /// UTformat("Number: {}\n", 1);
126 /// UTformat("String: {}\n", "foobar");
127 /// UTformat("Field : {:=^20}\n", 1);
128 /// UTformat("Index : {3} {0} {2} {1}\n", 'A', 'B', 'C', 'D');
129 /// UTformat("Perc : {:.1%}\n", 0.1234);
130 /// @endcode
131 /// Result:
132 /// @code{.txt}
133 /// Number: 1
134 /// String: foobar
135 /// Field : =========1==========
136 /// Index : D A C B
137 /// Perc : 12.3%
138 /// @endcode
139 /// @section printf_grammar Printf Grammar
140 /// The UTprintf and UT_Format::printf functions use formatting code very
141 /// similar to the POSIX specification for printf.
142 /// The code begins with a single @c % character, followed by zero or more
143 /// modifiers, ending with the type specifier. Where this implementation of the
144 /// @c printf formatting code differs, is that there is no need to add length
145 /// modifiers. Any length modifers will simply be ignored.
146 
147 /// @section custom_format Custom Formatting
148 /// Custom types are supported through custom formatting functions. To define
149 /// a custom formatting function for a specific type, the following function
150 /// specialization needs to be implemented:
151 /// @code{.cpp}
152 /// size_t format(char *buffer, size_t buffer_size, const CustomType &val);
153 /// @endcode
154 /// Where:
155 /// - @c buffer is a byte buffer to write the result into. If @c buffer is a
156 /// @c nullptr, then the function should return the number of bytes required
157 /// to store the final result.
158 /// - @c buffer_size is the size of the byte buffer passed in via @c buffer.
159 /// This should be ignored if @c buffer is @c nullptr.
160 /// - @val is value to custom format.
161 /// The function should return the number of bytes written out, or, if @c buffer
162 /// is @c nullptr, the amount of bytes needed to write out the entire custom
163 /// type representation.
164 
165 
166 /// @name Standalone formatting functions
167 /// @{
168 
169 /// Takes a formatting string and a set of arguments and writes out the
170 /// formatted string to the FILE pointer.
171 /// @param file The @c FILE pointer to write to. The FILE must be opened in
172 /// write or append mode.
173 /// @param format The formatting codes, as defined in @ref format_grammar.
174 /// @param args The arguments to the formatting.
175 /// @return The number of bytes successfully written out.
176 template<typename... Args>
177 size_t UTformat(FILE *file, const char *format, const Args& ...args);
178 
179 /// Takes a formatting string and a set of arguments and writes out the
180 /// formatted string to @c stdout.
181 /// @param format The formatting codes, as defined in @ref format_grammar.
182 /// @param args The arguments to the formatting.
183 /// @return The number of bytes successfully written out.
184 template<typename... Args>
185 size_t UTformat(const char *format, const Args& ...args);
186 
187 /// Takes a formatting string and a set of arguments and writes out the
188 /// formatted string to the output stream object.
189 /// @param os The output stream to write to.
190 /// @param format The formatting codes, as defined in @ref format_grammar.
191 /// @param args The arguments to the formatting.
192 /// @return The number of bytes successfully written out.
193 template<typename... Args>
194 size_t UTformat(std::ostream &os, const char *format, const Args& ...args);
195 
196 /// Takes a formatting string and a set of arguments and writes out the
197 /// formatted string into the buffer provided. If @c buffer is @c nullptr,
198 /// then nothing is written out, but the number of bytes needed to store
199 /// the entire formatted string is returned. A termination byte is not written
200 /// out to the buffer. If termination is required, the caller must take care
201 /// of it.
202 /// @param buffer The character buffer to write the formatted string to.
203 /// @param buffer_size The size of the character buffer.
204 /// @param format The formatting codes, as defined in @ref format_grammar.
205 /// @param args The arguments to the formatting.
206 /// @return The number of bytes successfully written out.
207 template<typename... Args>
208 size_t UTformat(char *buffer, size_t buffer_size, const char *format,
209  const Args& ...args);
210 
211 /// @}
212 
213 /// @name Standalone printf-like functions
214 /// @{
215 
216 /// Takes a formatting string and a set of arguments and writes out the
217 /// formatted string to the FILE pointer.
218 /// @param file The @c FILE pointer to write to. The FILE must be opened in
219 /// write or append mode.
220 /// @param format The formatting codes, as defined in @ref printf_grammar.
221 /// @param args The arguments to the formatting.
222 /// @return The number of bytes successfully written out.
223 template<typename... Args>
224 size_t UTprintf(FILE *file, const char *format, const Args& ...args);
225 
226 /// Takes a formatting string and a set of arguments and writes out the
227 /// formatted string to @c stdout.
228 /// @param format The formatting codes, as defined in @ref printf_grammar.
229 /// @param args The arguments to the formatting.
230 /// @return The number of bytes successfully written out.
231 template<typename... Args>
232 size_t UTprintf(const char *format, const Args& ...args);
233 
234 /// Takes a formatting string and a set of arguments and writes out the
235 /// formatted string to the output stream object.
236 /// @param os The output stream to write to.
237 /// @param format The formatting codes, as defined in @ref printf_grammar.
238 /// @param args The arguments to the formatting.
239 /// @return The number of bytes successfully written out.
240 template<typename... Args>
241 size_t UTprintf(std::ostream &os, const char *format, const Args& ...args);
242 
243 /// Takes a formatting string and a set of arguments and writes out the
244 /// formatted string into the buffer provided. If @c buffer is @c nullptr,
245 /// then nothing is written out, but the number of bytes needed to store
246 /// the entire formatted string is returned. A termination byte is not written
247 /// out to the buffer. If termination is required, the caller must take care
248 /// of it.
249 /// @param buffer The character buffer to write the formatted string to.
250 /// @param buffer_size The size of the character buffer.
251 /// @param format The formatting codes, as defined in @ref printf_grammar.
252 /// @param args The arguments to the formatting.
253 /// @return The number of bytes successfully written out.
254 template<typename... Args>
255 size_t UTprintf(char *buffer, size_t buffer_size, const char *format,
256  const Args& ...args);
257 
258 /// @}
259 
260 
261 namespace UT { namespace Format {
262 
263 /// @name Writer functors for formatted strings
264 /// @{
265 
266 /// A writer class that writes to a raw character buffer. If initializing with
267 /// a default constructor, the writer won't store anything. This can be useful
268 /// to count the number of bytes required for storage before allocating a buffer
269 /// for the final result.
270 struct Writer : public UT_NonCopyable
271 {
272  Writer() :
273  myBuffer(nullptr),
274  myBufferSize(std::numeric_limits<size_t>::max()) { }
275 
276  Writer(char *buffer, size_t buffer_size) :
277  myBuffer(buffer),
278  myBufferSize(buffer_size) { }
279 
280  void setBuffer(char *buffer, size_t buffer_size)
281  {
282  myBuffer = buffer;
283  myBufferSize = buffer_size;
284  }
285 
286  size_t operator()(const char *begin, const char *end)
287  {
288  // Exhausted?
289  if (!myBufferSize)
290  return false;
291 
292  size_t size = size_t(end - begin);
293  size = std::min(size, myBufferSize);
294  if (myBuffer)
295  {
296  std::copy(begin, begin + size, myBuffer);
297  myBuffer += size;
298  }
299  myBufferSize -= size;
300 
301  return size;
302  }
303 
304 private:
305  char *myBuffer;
306  size_t myBufferSize;
307 };
308 
309 /// A specialized @c Writer class that writes to a stdio @c FILE buffer.
311 {
312  FileWriter(FILE *file) : myFile(file) {}
313 
314  size_t operator()(const char *begin, const char *end);
315 
316 private:
317  FILE *myFile;
318 };
319 
320 /// A specialized @c Writer class that writes to a @c std::ostream object.
322 {
323  StreamWriter(std::ostream &os) : myOS(os) {}
324 
325  size_t operator()(const char *begin, const char *end);
326 
327 private:
328  std::ostream &myOS;
329 };
330 
331 /// Class outline of a writer class for the formatter. This serves as a
332 /// template when writing a new @ref Formatter writer for cases that the
333 /// @ref FileWriter, @ref StreamWriter, and @ref Writer don't cover.
335 {
336  /// Write the range of bytes from @c begin to @c end, non-inclusive (i.e.
337  /// don't write out the byte pointed to by @c end). Return the number of
338  /// bytes written.
339  size_t operator()(const char *begin, const char *end);
340 };
341 
342 /// @}
343 
344 // A template to check whether a variation of format(...) exists for the
345 // given type.
346 namespace Impl
347 {
348  template<typename> struct TrueType : std::true_type {};
349  // SFINAE will pick one of the two HasFormat() variants below, depending on
350  // if it can resolve the declaration type of the format() declaration given
351  // below. We wrap the result through the TrueType class above (which
352  // accepts any type) in order to get a true value for it in the actual
353  // HasFormat implementation below.
354  template<typename T>
355  static auto TestHasFormat(int) ->
357  size_t(), std::declval<T>()))>;
358  template<typename T>
359  static auto TestHasFormat(long) -> std::false_type;
360 }
361 
362 template<typename T>
363 struct HasFormat
364 {
365  static constexpr bool value = decltype(Impl::TestHasFormat<T>(0))::value;
366 };
367 
368 /// A container class that holds the individual argument values to be formatted
369 /// with the format string.
371 {
372 
373 public:
374  enum class Type
375  {
376  None,
377  Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64,
378  Float16, Float32, Float64,
379  ZeroString, SizedString, CharString,
380  Pointer, Custom
381  };
382 
383  ArgValue(char v) : myType(Type::CharString), myChar(v) {}
384  ArgValue(int8 v) : myType(Type::Int8), myI8(v) {}
385  ArgValue(uint8 v) : myType(Type::UInt8), myU8(v) {}
386  ArgValue(int16 v) : myType(Type::Int16), myI16(v) {}
387  ArgValue(uint16 v) : myType(Type::UInt16), myU16(v) {}
388  ArgValue(int32 v) : myType(Type::Int32), myI32(v) {}
389  ArgValue(uint32 v) : myType(Type::UInt32), myU32(v) {}
390  ArgValue(int64 v) : myType(Type::Int64), myI64(v) {}
391  ArgValue(uint64 v) : myType(Type::UInt64), myU64(v) {}
392  ArgValue(fpreal16 v) : myType(Type::Float16), myF16(v) {}
393  ArgValue(fpreal32 v) : myType(Type::Float32), myF32(v) {}
394  ArgValue(fpreal64 v) : myType(Type::Float64), myF64(v) {}
395 
396 #if defined(LINUX) && defined(AMD64)
397  // Special overload to deal with long longs, which both gcc and clang
398  // treat as a distinct type from long, on 64-bit Linux, even if they're the
399  // same size.
400  static_assert(sizeof(long long) == 8, "long long should be 8 bytes.");
401  ArgValue(long long v) : myType(Type::Int64), myI64(int64(v)) {}
402  ArgValue(unsigned long long v) : myType(Type::UInt64), myU64(uint64(v)) {}
403 #endif
404 #if defined(MBSD) && defined(__clang__)
405  // Special overload for size_t with clang on OSX.
406  ArgValue(size_t myValuePtr) : myType(Type::UInt64), myU64(uint64(myValuePtr)) {}
407 #endif
408 #if defined(MBSD)
409  // Special overload for long with OSX.
410  ArgValue(long v) : myType(Type::Int64), myI64(int64(v)) {}
411  // Note: unsigned long covered by size_t case above
412 #elif defined(_WIN32)
413  // Special overload for long with Windows.
414  ArgValue(long v) : myType(Type::Int32), myI32(int32(v)) {}
415  ArgValue(unsigned long v) : myType(Type::UInt32), myU32(uint32(v)) {}
416 #endif
417  ArgValue(bool v) : myType(Type::SizedString)
418  {
419  if (v)
420  {
421  mySizedStr.myStr = "true";
422  mySizedStr.mySize = 4;
423  }
424  else
425  {
426  mySizedStr.myStr = "false";
427  mySizedStr.mySize = 5;
428  }
429  }
430 
431  ArgValue(char *v) : myType(Type::ZeroString), myStr(v) {}
432  ArgValue(const char *v) : myType(Type::ZeroString), myStr(v) {}
433  ArgValue(const UT_String &v);
434  ArgValue(const UT_StringLit &v);
435  ArgValue(const UT_StringRef &v);
436  ArgValue(const UT_StringHolder &v);
437  ArgValue(const UT_StringView &v);
439  myType(Type::SizedString), mySizedStr(v.c_str(), v.length()) {}
440 
441  // void pointer overrides because std::is_pointer<void*>::value is false!
442  ArgValue(void *v) :
443  myType(Type::Pointer), myPtr(v)
444  {
445  }
446  ArgValue(const void *v) :
447  myType(Type::Pointer), myPtr(v)
448  {
449  }
450 
451 #define UT_ENABLE_IF(T) typename std::enable_if<T>::type * = nullptr
452 #define UT_HAS_FMT(T) HasFormat<T>::value
453 #define UT_REMOVE_PTR(T) typename std::remove_pointer<T>::type
454 #define UT_IS_PTR(T) std::is_pointer<T>::value
455 #define UT_IS_ENUM(T) std::is_enum<T>::value
456 
457  // Accept any pointer type that doesn't have a custom formatter.
458  // We use std::enable_if magic to allow SFINAE to elide any constructor
459  // that doesn't properly evaluate (a template argument value of false to
460  // std::enable_if results in std::enable_if::type not being defined).
461  template<typename T>
464  myType(Type::Pointer), myPtr(v)
465  {
466  }
467 
468  // For pointer types that have custom formatters. In this case we print
469  // out the pointer value and the de-referenced formatted value pointed to,
470  // or (null), if the value is \c nullptr.
471  template<typename T>
472  ArgValue(T v,
474  myType(Type::Custom)
475  {
476  myCustom.myFormatFunc = customPtrWrapper<UT_REMOVE_PTR(T)>;
477  myCustom.myValuePtr = static_cast<const void *>(v);
478  }
479 
480  // For fixed length arrays
481  template<typename T, unsigned N>
482  ArgValue(T (&v)[N]) :
483  myType(Type::Custom)
484  {
485  myCustom.myFormatFunc = customArrayWrapper<UT_REMOVE_PTR(T),N>;
486  myCustom.myValuePtr = static_cast<const void *>(&v[0]);
487  }
488 
489  template <typename T>
490  ArgValue(T &v,
491  UT_ENABLE_IF( UT_IS_ENUM(T) && !UT_HAS_FMT(T) ))
492  {
493  *this = ArgValue(static_cast<typename std::underlying_type<T>::type>(v));
494  }
495 
496  template <typename T>
497  ArgValue(T &v,
498  UT_ENABLE_IF( UT_IS_ENUM(T) && UT_HAS_FMT(T) )) :
499  myType(Type::Custom)
500  {
501  myCustom.myFormatFunc = customRefWrapper<T>;
502  myCustom.myValuePtr = &v;
503  }
504 
505  // For reference types that have custom formatters.
506  template<typename T>
508  myType(Type::Custom)
509  {
510  static_assert(UT_HAS_FMT(T), "No formatting function for custom type.");
511  myCustom.myFormatFunc = customRefWrapper<T>;
512  myCustom.myValuePtr = &t;
513  }
514 
515  size_t formatCustom(char *buffer, size_t buffer_size) const
516  {
517  UT_ASSERT(isCustom());
518  if (!isCustom())
519  return 0;
520 
521  return myCustom.myFormatFunc(buffer, buffer_size, myCustom.myValuePtr);
522  }
523 
524 #undef UT_ENABLE_IF
525 #undef UT_HAS_FMT
526 #undef UT_REMOVE_PTR
527 #undef UT_IS_PTR
528 
529  // In the presence of a union with non-POD types, we have to provide our
530  // own destructor, even if there are no destructors to call.
532 
533  Type type() const { return myType; }
534 
535  bool isEmpty() const { return myType == Type::None; }
536 
537  bool isInteger() const
538  {
539  return myType == Type::Int8 || myType == Type::UInt8 ||
540  myType == Type::Int16 || myType == Type::UInt16 ||
541  myType == Type::Int32 || myType == Type::UInt32 ||
542  myType == Type::Int64 || myType == Type::UInt64;
543  }
544 
545  bool isFloat() const
546  {
547  return myType == Type::Float16 ||
548  myType == Type::Float32 ||
549  myType == Type::Float64;
550  }
551 
552  bool isSigned() const
553  {
554  return myType == Type::Int8 ||
555  myType == Type::Int16 ||
556  myType == Type::Int32 ||
557  myType == Type::Int64 ||
558  isFloat();
559  }
560 
561  bool isNumeric() const
562  {
563  return isInteger() || isFloat();
564  }
565 
566  bool isString() const
567  {
568  return myType == Type::CharString ||
569  myType == Type::ZeroString ||
570  myType == Type::SizedString;
571  }
572 
573  bool isPointer() const
574  {
575  return myType == Type::Pointer;
576  }
577 
578  bool isCustom() const
579  {
580  return myType == Type::Custom;
581  }
582 
583 protected:
584  template<typename W> friend class Formatter;
585 
586  ArgValue() : myType(Type::None), myU64(0) {}
587  ArgValue(Type type) : myType(type), myI64(0) {}
588 
589  struct SizedString
590  {
591  SizedString(const char *str, size_t size) : myStr(str), mySize(size) {}
592  const char *myStr;
593  size_t mySize;
594  };
595 
596  using CustomFormat = size_t(*)(char *buffer, size_t buffer_size, const void *value);
597 
598  struct Custom
599  {
600  const void *myValuePtr;
602  };
603 
604  union
605  {
617  char myChar;
618  const char *myStr;
620  const void *myPtr;
622  };
623 
624 private:
625  Type myType;
626 
627  // Wraper function to invoke the writer for the custom type.
628  template <typename T>
629  static inline size_t
630  customRefWrapper(char *buffer, size_t buffer_size, const void *value)
631  {
632  return format(buffer, buffer_size, *static_cast<const T*>(value));
633  }
634 
635  template <typename T>
636  static inline size_t
637  customPtrWrapper(char *buffer, size_t buffer_size, const void *value)
638  {
639  if (value)
640  return UTformat(buffer, buffer_size, "<{} {}>",
641  value, *static_cast<const T*>(value));
642  else
643  return UTformat(buffer, buffer_size, "<{}>", value);
644  }
645 
646  template <typename T, unsigned N>
647  static inline size_t
648  customArrayWrapper(char *buffer, size_t buffer_size, const void *value);
649 };
650 
651 /// The main formatting class. This accepts a set of arguments and can
652 /// subsequently format them in various ways.
653 template<typename W = Writer>
654 class Formatter : public UT_NonCopyable
655 {
656  // A utility class to keep track of number of bytes written.
657  struct WriteTracker
658  {
659  WriteTracker(W &writer) : myWriter(writer), myBytesWritten(0) {}
660 
661  bool write(const char *begin, const char *end)
662  {
663  size_t bytes_to_write = size_t(end - begin);
664  size_t n_written = myWriter(begin, end);
665  myBytesWritten += n_written;
666  return n_written == bytes_to_write;
667  }
668  size_t written() const { return myBytesWritten; }
669 
670  void increment(size_t n_bytes) { myBytesWritten += n_bytes; }
671 
672  private:
673  W &myWriter;
674  size_t myBytesWritten;
675  };
676 public:
677  using WriterType = W;
678 
679  /// Constructs a new @ref Formatter object.
681  myNextArgIndex(0),
682  myReportErrors(true),
683  myDigitGroupings(false) {}
684 
685  /// Sets whether to report format string errors or not.
686  void setReportErrors(bool flag) { myReportErrors = flag; }
687 
688  /// Sets whether to force numbers to print with digit grouping. Otherwise
689  /// only the ',' (format), or '\'' (printf) flags dictate whether digit
690  /// grouping is done.
691  void setForceDigitGroupings(bool flag) { myDigitGroupings = flag; }
692 
693  /// Format the arguments into the writer, using the format string given.
694  /// Returns the number of bytes written.
695  /// @param writer A functor that does the writing of the formatted output.
696  /// See @ref CustomWriter for an example of how to do a custom writer.
697  /// @param format The formatting codes, as defined in @ref format_grammar.
698  /// @param args An initializer list that forms the list of arguments to
699  /// bake into the formatted result using the format string.
700  /// @return The number of bytes written out to the @p writer functor.
701  size_t format(W &writer, const char * format,
702  std::initializer_list<ArgValue> args);
703 
704  /// Format the arguments into the writer, using the format string given.
705  /// Returns the number of bytes written.
706  /// @param writer A functor that does the writing of the formatted output.
707  /// See @ref CustomWriter for an example of how to do a custom writer.
708  /// @param format The formatting codes, as defined in @ref format_grammar.
709  /// @param args An array of arguments to bake into the formatted result
710  /// using the format string.
711  /// @param nb_args The number of items in the argument array passed in.
712  /// @return The number of bytes written out to the @p writer functor.
713  size_t format(W &writer, const char * format,
714  const ArgValue args[], size_t nb_args);
715 
716  /// Format the arguments into the writer, using the format string given.
717  /// Returns the number of bytes written.
718  /// @param writer A functor that does the writing of the formatted output.
719  /// See @ref CustomWriter for an example of how to do a custom writer.
720  /// @param format The formatting codes, as defined by
721  /// [std::printf](http://www.cplusplus.com/reference/cstdio/printf/)
722  /// @param args An initializer list that forms the list of arguments to
723  /// bake into the formatted result using the format string.
724  /// @return The number of bytes written out to the @p writer functor.
725  size_t printf(W &writer, const char * format,
726  std::initializer_list<ArgValue> args);
727 
728  /// Format the arguments into the writer, using the format string given.
729  /// Returns the number of bytes written.
730  /// @param writer A functor that does the writing of the formatted output.
731  /// See @ref CustomWriter for an example of how to do a custom writer.
732  /// @param format The formatting codes, as defined by
733  /// [std::printf](http://www.cplusplus.com/reference/cstdio/printf/)
734  /// @param args An array of arguments to bake into the formatted result
735  /// using the format string.
736  /// @param nb_args The number of items in the argument array passed in.
737  /// @return The number of bytes written out to the @p writer functor.
738  size_t printf(W &writer, const char * format,
739  const ArgValue args[], size_t nb_args);
740 
741 private:
742  struct FormatSpec
743  {
744  FormatSpec() :
745  field_width(0),
746  str_width(std::numeric_limits<size_t>::max()),
747  precision(-1),
748  align(Left),
749  sign(Minus),
750  alt_form(false),
751  digit_grouping(false),
752  fill(' '),
753  type(0)
754  {
755  }
756 
757  size_t field_width;
758  size_t str_width;
760  enum { Left, Center, Right, Number } align;
761  enum { Minus, Plus, Space } sign;
762  bool alt_form;
763  bool digit_grouping;
764  char fill;
765  char type;
766  };
767 
768  bool parseFormatSpec(const char *&ptr, const ArgValue &arg,
769  const ArgValue args[], size_t nb_args,
770  FormatSpec &spec);
771  bool parsePrintfSpec(const char *&ptr, const ArgValue &arg,
772  const ArgValue args[], size_t nb_args,
773  FormatSpec &spec);
774 
775  size_t formatArg(W &writer, const FormatSpec &spec, const ArgValue &arg);
776  size_t formatInteger(W &writer, const FormatSpec &spec, const ArgValue &arg);
777  size_t formatFloat(W &writer, const FormatSpec &spec, const ArgValue &arg);
778  size_t formatString(W &writer, const FormatSpec &spec, const ArgValue &arg);
779  size_t formatPointer(W &writer, const FormatSpec &spec, const ArgValue &arg);
780  size_t formatCustom(W &writer, const FormatSpec &spec, const ArgValue &arg);
781  size_t formatCodePoint(W &writer, const FormatSpec &spec, const ArgValue &arg);
782  size_t formatPercentage(W &writer, const FormatSpec &spec, const ArgValue &arg);
783 
784  size_t formatAdjustAndFill(W &writer, const char *str, size_t str_size,
785  const FormatSpec &spec);
786 
787  // Get the argument pointed at by the current location of the format string.
788  // If the first character is a digit, assume the argument is being referred
789  // to by index, otherwise assume we're using the next argument.
790  const ArgValue &getFormatArg(const char *&ptr, const ArgValue args[],
791  size_t nb_args);
792  const ArgValue &getPrintfArg(const char *&ptr, const ArgValue args[],
793  size_t nb_args);
794  static int64 getIntValueFromArg(const ArgValue &arg);
795  static fpreal64 getFloatValueFromArg(const ArgValue &arg);
796 
797  int64 myNextArgIndex;
798  bool myReportErrors:1,
799  myDigitGroupings:1;
800 };
801 
802  } // namespace Format
803 } // namespace UT
804 
805 // The inline implementation
806 #include "UT_FormatImpl.h"
807 
808 #endif // __UT_Format__
size_t printf(W &writer, const char *format, std::initializer_list< ArgValue > args)
type
Definition: core.h:977
ArgValue(T &v, UT_ENABLE_IF(UT_IS_ENUM(T)&&!UT_HAS_FMT(T)))
Definition: UT_Format.h:490
#define UT_IS_PTR(T)
Definition: UT_Format.h:454
unsigned short uint16
Definition: SYS_Types.h:38
size_t format(W &writer, const char *format, std::initializer_list< ArgValue > args)
int int32
Definition: SYS_Types.h:39
size_t formatCustom(char *buffer, size_t buffer_size) const
Definition: UT_Format.h:515
SizedString(const char *str, size_t size)
Definition: UT_Format.h:591
#define UT_ENABLE_IF(T)
Definition: UT_Format.h:451
void setBuffer(char *buffer, size_t buffer_size)
Definition: UT_Format.h:280
void setForceDigitGroupings(bool flag)
Definition: UT_Format.h:691
ArgValue(fpreal64 v)
Definition: UT_Format.h:394
ArgValue(const std::string &v)
Definition: UT_Format.h:438
#define UT_API
Definition: UT_API.h:14
ArgValue(uint32 v)
Definition: UT_Format.h:389
#define UT_HAS_FMT(T)
Definition: UT_Format.h:452
unsigned long long uint64
Definition: SYS_Types.h:117
size_t(*)(char *buffer, size_t buffer_size, const void *value) CustomFormat
Definition: UT_Format.h:596
float fpreal32
Definition: SYS_Types.h:200
GLdouble GLdouble t
Definition: glew.h:1403
GLuint buffer
Definition: glcorearb.h:659
ArgValue(const char *v)
Definition: UT_Format.h:432
ArgValue(uint16 v)
Definition: UT_Format.h:387
bool isFloat() const
Definition: UT_Format.h:545
GLsizeiptr size
Definition: glcorearb.h:663
double fpreal64
Definition: SYS_Types.h:201
unsigned char uint8
Definition: SYS_Types.h:36
A utility class to do read-only operations on a subset of an existing string.
Definition: UT_StringView.h:40
Format
Definition: oidn.hpp:16
Formatter()
Constructs a new Formatter object.
Definition: UT_Format.h:680
#define UT_IS_ENUM(T)
Definition: UT_Format.h:455
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:107
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
StreamWriter(std::ostream &os)
Definition: UT_Format.h:323
ArgValue(T v, UT_ENABLE_IF(!UT_IS_ENUM(T)&&UT_IS_PTR(T)&&!UT_HAS_FMT(UT_REMOVE_PTR(T))))
Definition: UT_Format.h:462
bool isString() const
Definition: UT_Format.h:566
bool isNumeric() const
Definition: UT_Format.h:561
const GLdouble * v
Definition: glcorearb.h:836
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER typedef long long unsigned int Int64
Definition: ImathInt64.h:58
#define UT_REMOVE_PTR(T)
Definition: UT_Format.h:453
GLuint GLuint end
Definition: glcorearb.h:474
GLsizei const GLchar *const * string
Definition: glcorearb.h:813
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
ArgValue(T &t, UT_ENABLE_IF(!UT_IS_PTR(T)&&!UT_IS_ENUM(T)))
Definition: UT_Format.h:507
void setReportErrors(bool flag)
Sets whether to report format string errors or not.
Definition: UT_Format.h:686
bool isPointer() const
Definition: UT_Format.h:573
A specialized Writer class that writes to a std::ostream object.
Definition: UT_Format.h:321
long long int64
Definition: SYS_Types.h:116
ArgValue(fpreal32 v)
Definition: UT_Format.h:393
int sign(T a)
Definition: ImathFun.h:63
signed char int8
Definition: SYS_Types.h:35
ArgValue(T v, UT_ENABLE_IF(!UT_IS_ENUM(T)&&UT_IS_PTR(T)&&UT_HAS_FMT(UT_REMOVE_PTR(T))))
Definition: UT_Format.h:472
const void * myPtr
Definition: UT_Format.h:620
A specialized Writer class that writes to a stdio FILE buffer.
Definition: UT_Format.h:310
Type type() const
Definition: UT_Format.h:533
detail::named_arg< Char, T > arg(const Char *name, const T &arg)
Definition: core.h:1640
size_t UTprintf(FILE *file, const char *format, const Args &...args)
GLenum GLint GLint * precision
Definition: glcorearb.h:1924
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:794
GLint GLint GLsizei GLint GLenum format
Definition: glcorearb.h:107
bool isEmpty() const
Definition: UT_Format.h:535
Writer(char *buffer, size_t buffer_size)
Definition: UT_Format.h:276
SizedString mySizedStr
Definition: UT_Format.h:619
const void * ptr(const T *p)
Definition: format.h:3603
short int16
Definition: SYS_Types.h:37
size_t operator()(const char *begin, const char *end)
Definition: UT_Format.h:286
bool isSigned() const
Definition: UT_Format.h:552
OIIO_API bool copy(string_view from, string_view to, std::string &err)
ArgValue(T(&v)[N])
Definition: UT_Format.h:482
GA_API const UT_StringHolder N
ArgValue(T &v, UT_ENABLE_IF(UT_IS_ENUM(T)&&UT_HAS_FMT(T)))
Definition: UT_Format.h:497
GLsizei const GLfloat * value
Definition: glcorearb.h:823
size_t UTformat(FILE *file, const char *format, const Args &...args)
**If you just want to fire and args
Definition: thread.h:615
unsigned int uint32
Definition: SYS_Types.h:40
ArgValue(Type type)
Definition: UT_Format.h:587
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:171
ArgValue(fpreal16 v)
Definition: UT_Format.h:392
void write(T &out, bool v)
Definition: ImfXdr.h:332
ArgValue(const void *v)
Definition: UT_Format.h:446
FileWriter(FILE *file)
Definition: UT_Format.h:312
const char * myStr
Definition: UT_Format.h:618
bool isInteger() const
Definition: UT_Format.h:537
size_t operator()(const char *begin, const char *end)
bool isCustom() const
Definition: UT_Format.h:578
ArgValue(uint64 v)
Definition: UT_Format.h:391
FMT_NOINLINE OutputIt fill(OutputIt it, size_t n, const fill_t< Char > &fill)
Definition: format.h:1483