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