HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
fmt.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenImageIO project.
2 // SPDX-License-Identifier: Apache-2.0
3 // https://github.com/AcademySoftwareFoundation/OpenImageIO
4 
5 #pragma once
6 #define OIIO_FMT_H
7 
8 #include <OpenImageIO/dassert.h>
9 #include <OpenImageIO/platform.h>
11 
12 // We want the header-only implementation of fmt
13 #ifndef FMT_HEADER_ONLY
14 # define FMT_HEADER_ONLY
15 #endif
16 
17 // Disable fmt exceptions
18 #ifndef FMT_EXCEPTIONS
19 # define FMT_EXCEPTIONS 0
20 #endif
21 
22 // Redefining FMT_THROW to something benign seems to avoid some UB or possibly
23 // gcc 11+ compiler bug triggered by the definition of FMT_THROW in fmt 10.1+
24 // when FMT_EXCEPTIONS=0, which results in mangling SIMD math. This nugget
25 // below works around the problems for hard to understand reasons.
26 #if !defined(FMT_THROW) && !FMT_EXCEPTIONS && OIIO_GNUC_VERSION >= 110000
27 # define FMT_THROW(x) \
28  OIIO_ASSERT_MSG(0, "fmt exception: %s", (x).what()), std::terminate()
29 #endif
30 
31 // Use the grisu fast floating point formatting for old fmt versions
32 // (irrelevant for >= 7.1).
33 #ifndef FMT_USE_GRISU
34 # define FMT_USE_GRISU 1
35 #endif
36 
37 // fmt 8.1 stopped automatically enabling formatting of anything that supports
38 // ostream output. This breaks a lot! Re-enable this old behavior.
39 // NOTE: fmt 10.0 removed this support entirely.
40 #ifndef FMT_DEPRECATED_OSTREAM
41 # define FMT_DEPRECATED_OSTREAM 1
42 #endif
43 
44 // fmt 9 started using the __float128 type, which is not supported by the
45 // nvptx backend for llvm, so we disable its usage on this target, which
46 // can be identified by the combination of __CUDA_ARCH__ and __clang__
47 #if defined(__CUDA_ARCH__) && defined(__clang__) && !defined(FMT_USE_FLOAT128)
48 # define FMT_USE_FLOAT128 0
49 #endif
50 
51 // Suppress certain warnings generated in the fmt headers themselves
53 #if OIIO_GNUC_VERSION >= 70000
54 # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
55 #endif
56 #if OIIO_GNUC_VERSION >= 130000
57 # pragma GCC diagnostic ignored "-Wdangling-reference"
58 #endif
59 #if OIIO_INTEL_LLVM_COMPILER
60 # pragma GCC diagnostic ignored "-Wtautological-constant-compare"
61 #endif
62 #if OIIO_CLANG_VERSION >= 180000
63 # pragma clang diagnostic ignored "-Wdeprecated-declarations"
64 #endif
65 
69 
71 
72 // At some point a method signature changed
73 #if FMT_VERSION >= 90000
74 # define OIIO_FMT_CUSTOM_FORMATTER_CONST const
75 #else
76 # define OIIO_FMT_CUSTOM_FORMATTER_CONST
77 #endif
78 
79 
81 namespace pvt {
82 
83 
84 // Custom inheritable parse() method used by fmt formatters. In addition to
85 // saving the formatting spec, it also checks for a (nonstandard) optional
86 // leading ',' and records it as a separator flag.
89  {
90  auto beg = ctx.begin(), end = ctx.end();
91  if (beg != end && *beg == ',')
92  sep = *beg++;
93  auto it = beg; // where's the close brace?
94  for (; it != end && *it != '}'; ++it)
95  ;
96  elem_fmt = fmt::string_view(beg, it - beg);
97  return it;
98  }
99 
100 protected:
102  char sep = 0;
103 };
104 
105 
106 
107 // fmtlib custom formatter that formats a type `T` that has array-like
108 // semantics (must have a valid operator[] and size() method) by printing each
109 // element according to the format spec. For example, if the object has 3
110 // float elements and the spec is "{:.3f}", then the output might be "1.234
111 // 2.345 3.456".
112 //
113 // In addition to the usual formatting spec, we also recognize the following
114 // special extension: If the first character of the format spec is ','
115 // (comma), then the array elements will be separated by ", " rather than the
116 // default " ".
117 //
118 // For example, `format("[{:,.3f}]")` will format the array as `[1.234, 2.345,
119 // 3.456]`.
120 //
121 // Now then, the way this class is helpful is to inherit from it for a custom
122 // formatter. For example, this will make this formatter be used for
123 // Imath::V3f:
124 //
125 // // in global namespace:
126 // template<> struct fmt::formatter<Imath::V3f>
127 // : OIIO::array_formatter<Imath::V3f, float, 3> {};
128 //
129 template<typename T,
132  // inherits parse() from format_parser_with_separator
133  template<typename FormatContext>
134  auto format(const T& v, FormatContext& ctx) OIIO_FMT_CUSTOM_FORMATTER_CONST
135  {
136  std::string vspec = elem_fmt.size() ? fmt::format("{{:{}}}", elem_fmt)
137  : std::string("{}");
138  for (size_t i = 0; i < size_t(v.size()); ++i) {
139  if (i)
140  fmt::format_to(ctx.out(), "{}", sep == ',' ? ", " : " ");
141 #if FMT_VERSION >= 80000
142  fmt::format_to(ctx.out(), fmt::runtime(vspec), v[i]);
143 #else
144  fmt::format_to(ctx.out(), vspec, v[i]);
145 #endif
146  }
147  return ctx.out();
148  }
149 };
150 
151 
152 
153 // fmtlib custom formatter that formats a type `T` as if it were an array
154 // `Elem[Size]` (and it must be laid out that way in memory). The formatting
155 // spec will apply to each element. For example, if the object has 3 float
156 // elements and the spec is "{:.3f}", then the output might be "1.234 2.345
157 // 3.456".
158 //
159 // In addition to the usual formatting spec, we also recognize the following
160 // special extension: If the first character of the format spec is ','
161 // (comma), then the array elements will be separated by ", " rather than the
162 // default " ".
163 //
164 // For example, `format("[{:,.3f}]")` will format the array as `[1.234, 2.345,
165 // 3.456]`.
166 //
167 // Now then, the way this class is helpful is to inherit from it for a custom
168 // formatter. For example, this will make this formatter be used for
169 // Imath::V3f:
170 //
171 // // in global namespace:
172 // template<> struct fmt::formatter<Imath::V3f>
173 // : OIIO::array_formatter<Imath::V3f, float, 3> {};
174 //
175 template<typename T, typename Elem, int Size>
177  // inherits parse() from format_parser_with_separator
178  template<typename FormatContext>
179  auto format(const T& v, FormatContext& ctx) OIIO_FMT_CUSTOM_FORMATTER_CONST
180  {
181  std::string vspec = elem_fmt.size() ? fmt::format("{{:{}}}", elem_fmt)
182  : std::string("{}");
183  for (int i = 0; i < Size; ++i) {
184  if (i)
185  fmt::format_to(ctx.out(), "{}", sep == ',' ? ", " : " ");
186 #if FMT_VERSION >= 80000
187  fmt::format_to(ctx.out(), fmt::runtime(vspec),
188  ((const Elem*)&v)[i]);
189 #else
190  fmt::format_to(ctx.out(), vspec, ((const Elem*)&v)[i]);
191 #endif
192  }
193  return ctx.out();
194  }
195 };
196 
197 
198 } // namespace pvt
const GLdouble * v
Definition: glcorearb.h:837
auto format(const T &v, FormatContext &ctx) OIIO_FMT_CUSTOM_FORMATTER_CONST
Definition: fmt.h:134
FMT_CONSTEXPR auto parse(fmt::format_parse_context &ctx)
Definition: fmt.h:88
#define OIIO_ENABLE_IF(...)
Definition: platform.h:676
has_subscript<T>::value is true if T has a subscript operator.
Definition: type_traits.h:54
auto runtime(string_view s) -> runtime_format_string<>
Definition: core.h:2798
#define OIIO_PRAGMA_WARNING_PUSH
Definition: platform.h:297
basic_format_parse_context< char > format_parse_context
Definition: core.h:719
basic_string_view< char > string_view
Definition: core.h:501
#define OIIO_PRAGMA_WARNING_POP
Definition: platform.h:298
GLuint GLuint end
Definition: glcorearb.h:475
GLint GLint GLsizei GLint GLenum format
Definition: glcorearb.h:108
fmt::string_view elem_fmt
Definition: fmt.h:101
#define FMT_CONSTEXPR
Definition: core.h:104
#define OIIO_FMT_CUSTOM_FORMATTER_CONST
Definition: fmt.h:76
FMT_INLINE auto format_to(OutputIt out, format_string< T...> fmt, T &&...args) -> OutputIt
Definition: core.h:2843
auto format(const T &v, FormatContext &ctx) OIIO_FMT_CUSTOM_FORMATTER_CONST
Definition: fmt.h:179
#define OIIO_NAMESPACE_END
Definition: oiioversion.h:127
#define OIIO_NAMESPACE_BEGIN
Definition: oiioversion.h:126