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