1 //===- FormatProviders.h - Formatters for common LLVM types -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements format providers for many common LLVM types, for example
11 // allowing precision and width specifiers for scalar and string types.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_SUPPORT_FORMATPROVIDERS_H
16 #define LLVM_SUPPORT_FORMATPROVIDERS_H
18 #include "llvm/ADT/Optional.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/StringSwitch.h"
21 #include "llvm/Support/FormatVariadicDetails.h"
22 #include "llvm/Support/NativeFormatting.h"
24 #include <type_traits>
30 struct use_integral_formatter
31 : public std::integral_constant<
32 bool, is_one_of<T, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
33 int64_t, uint64_t, int, unsigned, long, unsigned long,
34 long long, unsigned long long>::value> {};
37 struct use_char_formatter
38 : public std::integral_constant<bool, std::is_same<T, char>::value> {};
42 : public std::integral_constant<bool,
43 is_one_of<T, char *, const char *>::value> {
47 struct use_string_formatter
48 : public std::integral_constant<
49 bool, is_one_of<T, llvm::StringRef, std::string>::value ||
50 is_cstring<T>::value> {};
53 struct use_pointer_formatter
54 : public std::integral_constant<bool, std::is_pointer<T>::value &&
55 !is_cstring<T>::value> {};
58 struct use_double_formatter
59 : public std::integral_constant<bool, std::is_floating_point<T>::value> {};
61 class HelperFunctions {
63 static Optional<size_t> parseNumericPrecision(StringRef Str) {
65 Optional<size_t> Result;
68 else if (Str.getAsInteger(10, Prec)) {
69 assert(false && "Invalid precision specifier");
72 assert(Prec < 100 && "Precision out of range");
73 Result = std::min<size_t>(99u, Prec);
78 static bool consumeHexStyle(StringRef &Str, HexPrintStyle &Style) {
79 if (!Str.startswith_lower("x"))
82 if (Str.consume_front("x-"))
83 Style = HexPrintStyle::Lower;
84 else if (Str.consume_front("X-"))
85 Style = HexPrintStyle::Upper;
86 else if (Str.consume_front("x+") || Str.consume_front("x"))
87 Style = HexPrintStyle::PrefixLower;
88 else if (Str.consume_front("X+") || Str.consume_front("X"))
89 Style = HexPrintStyle::PrefixUpper;
93 static size_t consumeNumHexDigits(StringRef &Str, HexPrintStyle Style,
95 Str.consumeInteger(10, Default);
96 if (isPrefixedHexStyle(Style))
103 /// Implementation of format_provider<T> for integral arithmetic types.
105 /// The options string of an integral type has the grammar:
107 /// integer_options :: [style][digits]
108 /// style :: <see table below>
109 /// digits :: <non-negative integer> 0-99
111 /// ==========================================================================
112 /// | style | Meaning | Example | Digits Meaning |
113 /// --------------------------------------------------------------------------
114 /// | | | Input | Output | |
115 /// ==========================================================================
116 /// | x- | Hex no prefix, lower | 42 | 2a | Minimum # digits |
117 /// | X- | Hex no prefix, upper | 42 | 2A | Minimum # digits |
118 /// | x+ / x | Hex + prefix, lower | 42 | 0x2a | Minimum # digits |
119 /// | X+ / X | Hex + prefix, upper | 42 | 0x2A | Minimum # digits |
120 /// | N / n | Digit grouped number | 123456 | 123,456 | Ignored |
121 /// | D / d | Integer | 100000 | 100000 | Ignored |
122 /// | (empty) | Same as D / d | | | |
123 /// ==========================================================================
126 template <typename T>
127 struct format_provider<
128 T, typename std::enable_if<detail::use_integral_formatter<T>::value>::type>
129 : public detail::HelperFunctions {
132 static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
135 if (consumeHexStyle(Style, HS)) {
136 Digits = consumeNumHexDigits(Style, HS, 0);
137 write_hex(Stream, V, HS, Digits);
141 IntegerStyle IS = IntegerStyle::Integer;
142 if (Style.consume_front("N") || Style.consume_front("n"))
143 IS = IntegerStyle::Number;
144 else if (Style.consume_front("D") || Style.consume_front("d"))
145 IS = IntegerStyle::Integer;
147 Style.consumeInteger(10, Digits);
148 assert(Style.empty() && "Invalid integral format style!");
149 write_integer(Stream, V, Digits, IS);
153 /// Implementation of format_provider<T> for integral pointer types.
155 /// The options string of a pointer type has the grammar:
157 /// pointer_options :: [style][precision]
158 /// style :: <see table below>
159 /// digits :: <non-negative integer> 0-sizeof(void*)
161 /// ==========================================================================
162 /// | S | Meaning | Example |
163 /// --------------------------------------------------------------------------
164 /// | | | Input | Output |
165 /// ==========================================================================
166 /// | x- | Hex no prefix, lower | 0xDEADBEEF | deadbeef |
167 /// | X- | Hex no prefix, upper | 0xDEADBEEF | DEADBEEF |
168 /// | x+ / x | Hex + prefix, lower | 0xDEADBEEF | 0xdeadbeef |
169 /// | X+ / X | Hex + prefix, upper | 0xDEADBEEF | 0xDEADBEEF |
170 /// | (empty) | Same as X+ / X | | |
171 /// ==========================================================================
173 /// The default precision is the number of nibbles in a machine word, and in all
174 /// cases indicates the minimum number of nibbles to print.
175 template <typename T>
176 struct format_provider<
177 T, typename std::enable_if<detail::use_pointer_formatter<T>::value>::type>
178 : public detail::HelperFunctions {
181 static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
182 HexPrintStyle HS = HexPrintStyle::PrefixUpper;
183 consumeHexStyle(Style, HS);
184 size_t Digits = consumeNumHexDigits(Style, HS, sizeof(void *) * 2);
185 write_hex(Stream, reinterpret_cast<std::uintptr_t>(V), HS, Digits);
189 /// Implementation of format_provider<T> for c-style strings and string
190 /// objects such as std::string and llvm::StringRef.
192 /// The options string of a string type has the grammar:
194 /// string_options :: [length]
196 /// where `length` is an optional integer specifying the maximum number of
197 /// characters in the string to print. If `length` is omitted, the string is
198 /// printed up to the null terminator.
200 template <typename T>
201 struct format_provider<
202 T, typename std::enable_if<detail::use_string_formatter<T>::value>::type> {
203 static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
204 size_t N = StringRef::npos;
205 if (!Style.empty() && Style.getAsInteger(10, N)) {
206 assert(false && "Style is not a valid integer");
208 llvm::StringRef S(V);
209 Stream << S.substr(0, N);
213 /// Implementation of format_provider<T> for characters.
215 /// The options string of a character type has the grammar:
217 /// char_options :: (empty) | [integer_options]
219 /// If `char_options` is empty, the character is displayed as an ASCII
220 /// character. Otherwise, it is treated as an integer options string.
222 template <typename T>
223 struct format_provider<
224 T, typename std::enable_if<detail::use_char_formatter<T>::value>::type> {
225 static void format(const char &V, llvm::raw_ostream &Stream,
230 int X = static_cast<int>(V);
231 format_provider<int>::format(X, Stream, Style);
236 /// Implementation of format_provider<T> for type `bool`
238 /// The options string of a boolean type has the grammar:
240 /// bool_options :: "" | "Y" | "y" | "D" | "d" | "T" | "t"
242 /// ==================================
244 /// ==================================
247 /// | D / d | Integer 0 or 1 |
248 /// | T | TRUE / FALSE |
249 /// | t | true / false |
250 /// | (empty) | Equivalent to 't' |
251 /// ==================================
252 template <> struct format_provider<bool> {
253 static void format(const bool &B, llvm::raw_ostream &Stream,
255 Stream << StringSwitch<const char *>(Style)
256 .Case("Y", B ? "YES" : "NO")
257 .Case("y", B ? "yes" : "no")
258 .CaseLower("D", B ? "1" : "0")
259 .Case("T", B ? "TRUE" : "FALSE")
260 .Cases("t", "", B ? "true" : "false")
261 .Default(B ? "1" : "0");
265 /// Implementation of format_provider<T> for floating point types.
267 /// The options string of a floating point type has the format:
269 /// float_options :: [style][precision]
270 /// style :: <see table below>
271 /// precision :: <non-negative integer> 0-99
273 /// =====================================================
274 /// | style | Meaning | Example |
275 /// -----------------------------------------------------
276 /// | | | Input | Output |
277 /// =====================================================
278 /// | P / p | Percentage | 0.05 | 5.00% |
279 /// | F / f | Fixed point | 1.0 | 1.00 |
280 /// | E | Exponential with E | 100000 | 1.0E+05 |
281 /// | e | Exponential with e | 100000 | 1.0e+05 |
282 /// | (empty) | Same as F / f | | |
283 /// =====================================================
285 /// The default precision is 6 for exponential (E / e) and 2 for everything
288 template <typename T>
289 struct format_provider<
290 T, typename std::enable_if<detail::use_double_formatter<T>::value>::type>
291 : public detail::HelperFunctions {
292 static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
294 if (Style.consume_front("P") || Style.consume_front("p"))
295 S = FloatStyle::Percent;
296 else if (Style.consume_front("F") || Style.consume_front("f"))
297 S = FloatStyle::Fixed;
298 else if (Style.consume_front("E"))
299 S = FloatStyle::ExponentUpper;
300 else if (Style.consume_front("e"))
301 S = FloatStyle::Exponent;
303 S = FloatStyle::Fixed;
305 Optional<size_t> Precision = parseNumericPrecision(Style);
306 if (!Precision.hasValue())
307 Precision = getDefaultPrecision(S);
309 write_double(Stream, static_cast<double>(V), S, Precision);
314 template <typename IterT>
315 using IterValue = typename std::iterator_traits<IterT>::value_type;
317 template <typename IterT>
318 struct range_item_has_provider
319 : public std::integral_constant<
320 bool, !uses_missing_provider<IterValue<IterT>>::value> {};
323 /// Implementation of format_provider<T> for ranges.
325 /// This will print an arbitrary range as a delimited sequence of items.
327 /// The options string of a range type has the grammar:
329 /// range_style ::= [separator] [element_style]
330 /// separator ::= "$" delimeted_expr
331 /// element_style ::= "@" delimeted_expr
332 /// delimeted_expr ::= "[" expr "]" | "(" expr ")" | "<" expr ">"
333 /// expr ::= <any string not containing delimeter>
335 /// where the separator expression is the string to insert between consecutive
336 /// items in the range and the argument expression is the Style specification to
337 /// be used when formatting the underlying type. The default separator if
338 /// unspecified is ' ' (space). The syntax of the argument expression follows
339 /// whatever grammar is dictated by the format provider or format adapter used
340 /// to format the value type.
342 /// Note that attempting to format an `iterator_range<T>` where no format
343 /// provider can be found for T will result in a compile error.
346 template <typename IterT> class format_provider<llvm::iterator_range<IterT>> {
347 using value = typename std::iterator_traits<IterT>::value_type;
348 using reference = typename std::iterator_traits<IterT>::reference;
350 static StringRef consumeOneOption(StringRef &Style, char Indicator,
354 if (Style.front() != Indicator)
356 Style = Style.drop_front();
358 assert(false && "Invalid range style");
362 std::vector<const char *> Delims = {"[]", "<>", "()"};
363 for (const char *D : Delims) {
364 if (Style.front() != D[0])
366 size_t End = Style.find_first_of(D[1]);
367 if (End == StringRef::npos) {
368 assert(false && "Missing range option end delimeter!");
371 StringRef Result = Style.slice(1, End);
372 Style = Style.drop_front(End + 1);
375 assert(false && "Invalid range style!");
379 static std::pair<StringRef, StringRef> parseOptions(StringRef Style) {
380 StringRef Sep = consumeOneOption(Style, '$', ", ");
381 StringRef Args = consumeOneOption(Style, '@', "");
382 assert(Style.empty() && "Unexpected text in range option string!");
383 return std::make_pair(Sep, Args);
387 static_assert(detail::range_item_has_provider<IterT>::value,
388 "Range value_type does not have a format provider!");
389 static void format(const llvm::iterator_range<IterT> &V,
390 llvm::raw_ostream &Stream, StringRef Style) {
393 std::tie(Sep, ArgStyle) = parseOptions(Style);
394 auto Begin = V.begin();
398 detail::build_format_adapter(std::forward<reference>(*Begin));
399 Adapter.format(Stream, ArgStyle);
402 while (Begin != End) {
405 detail::build_format_adapter(std::forward<reference>(*Begin));
406 Adapter.format(Stream, ArgStyle);