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