1 | //===- FormatProviders.h - Formatters for common LLVM types -----*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // This file implements format providers for many common LLVM types, for example |
11 | // allowing precision and width specifiers for scalar and string types. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_SUPPORT_FORMATPROVIDERS_H |
16 | #define LLVM_SUPPORT_FORMATPROVIDERS_H |
17 | |
18 | #include "llvm/ADT/Optional.h" |
19 | #include "llvm/ADT/STLExtras.h" |
20 | #include "llvm/ADT/StringSwitch.h" |
21 | #include "llvm/ADT/Twine.h" |
22 | #include "llvm/Support/FormatVariadicDetails.h" |
23 | #include "llvm/Support/NativeFormatting.h" |
24 | |
25 | #include <type_traits> |
26 | #include <vector> |
27 | |
28 | namespace llvm { |
29 | namespace detail { |
30 | template <typename T> |
31 | struct use_integral_formatter |
32 | : public std::integral_constant< |
33 | bool, is_one_of<T, uint8_t, int16_t, uint16_t, int32_t, uint32_t, |
34 | int64_t, uint64_t, int, unsigned, long, unsigned long, |
35 | long long, unsigned long long>::value> {}; |
36 | |
37 | template <typename T> |
38 | struct use_char_formatter |
39 | : public std::integral_constant<bool, std::is_same<T, char>::value> {}; |
40 | |
41 | template <typename T> |
42 | struct is_cstring |
43 | : public std::integral_constant<bool, |
44 | is_one_of<T, char *, const char *>::value> { |
45 | }; |
46 | |
47 | template <typename T> |
48 | struct use_string_formatter |
49 | : public std::integral_constant<bool, |
50 | std::is_convertible<T, llvm::StringRef>::value> {}; |
51 | |
52 | template <typename T> |
53 | struct use_pointer_formatter |
54 | : public std::integral_constant<bool, std::is_pointer<T>::value && |
55 | !is_cstring<T>::value> {}; |
56 | |
57 | template <typename T> |
58 | struct use_double_formatter |
59 | : public std::integral_constant<bool, std::is_floating_point<T>::value> {}; |
60 | |
61 | class HelperFunctions { |
62 | protected: |
63 | static Optional<size_t> parseNumericPrecision(StringRef Str) { |
64 | size_t Prec; |
65 | Optional<size_t> Result; |
66 | if (Str.empty()) |
67 | Result = None; |
68 | else if (Str.getAsInteger(10, Prec)) { |
69 | assert(false && "Invalid precision specifier" ); |
70 | Result = None; |
71 | } else { |
72 | assert(Prec < 100 && "Precision out of range" ); |
73 | Result = std::min<size_t>(99u, Prec); |
74 | } |
75 | return Result; |
76 | } |
77 | |
78 | static bool consumeHexStyle(StringRef &Str, HexPrintStyle &Style) { |
79 | if (!Str.startswith_lower("x" )) |
80 | return false; |
81 | |
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; |
90 | return true; |
91 | } |
92 | |
93 | static size_t (StringRef &Str, HexPrintStyle Style, |
94 | size_t Default) { |
95 | Str.consumeInteger(10, Default); |
96 | if (isPrefixedHexStyle(Style)) |
97 | Default += 2; |
98 | return Default; |
99 | } |
100 | }; |
101 | } |
102 | |
103 | /// Implementation of format_provider<T> for integral arithmetic types. |
104 | /// |
105 | /// The options string of an integral type has the grammar: |
106 | /// |
107 | /// integer_options :: [style][digits] |
108 | /// style :: <see table below> |
109 | /// digits :: <non-negative integer> 0-99 |
110 | /// |
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 | /// ========================================================================== |
124 | /// |
125 | |
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 { |
130 | private: |
131 | public: |
132 | static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) { |
133 | HexPrintStyle HS; |
134 | size_t Digits = 0; |
135 | if (consumeHexStyle(Style, HS)) { |
136 | Digits = consumeNumHexDigits(Style, HS, 0); |
137 | write_hex(Stream, V, HS, Digits); |
138 | return; |
139 | } |
140 | |
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; |
146 | |
147 | Style.consumeInteger(10, Digits); |
148 | assert(Style.empty() && "Invalid integral format style!" ); |
149 | write_integer(Stream, V, Digits, IS); |
150 | } |
151 | }; |
152 | |
153 | /// Implementation of format_provider<T> for integral pointer types. |
154 | /// |
155 | /// The options string of a pointer type has the grammar: |
156 | /// |
157 | /// pointer_options :: [style][precision] |
158 | /// style :: <see table below> |
159 | /// digits :: <non-negative integer> 0-sizeof(void*) |
160 | /// |
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 | /// ========================================================================== |
172 | /// |
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 { |
179 | private: |
180 | public: |
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); |
186 | } |
187 | }; |
188 | |
189 | /// Implementation of format_provider<T> for c-style strings and string |
190 | /// objects such as std::string and llvm::StringRef. |
191 | /// |
192 | /// The options string of a string type has the grammar: |
193 | /// |
194 | /// string_options :: [length] |
195 | /// |
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. |
199 | |
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" ); |
207 | } |
208 | llvm::StringRef S = V; |
209 | Stream << S.substr(0, N); |
210 | } |
211 | }; |
212 | |
213 | /// Implementation of format_provider<T> for llvm::Twine. |
214 | /// |
215 | /// This follows the same rules as the string formatter. |
216 | |
217 | template <> struct format_provider<Twine> { |
218 | static void format(const Twine &V, llvm::raw_ostream &Stream, |
219 | StringRef Style) { |
220 | format_provider<std::string>::format(V.str(), Stream, Style); |
221 | } |
222 | }; |
223 | |
224 | /// Implementation of format_provider<T> for characters. |
225 | /// |
226 | /// The options string of a character type has the grammar: |
227 | /// |
228 | /// char_options :: (empty) | [integer_options] |
229 | /// |
230 | /// If `char_options` is empty, the character is displayed as an ASCII |
231 | /// character. Otherwise, it is treated as an integer options string. |
232 | /// |
233 | template <typename T> |
234 | struct format_provider< |
235 | T, typename std::enable_if<detail::use_char_formatter<T>::value>::type> { |
236 | static void format(const char &V, llvm::raw_ostream &Stream, |
237 | StringRef Style) { |
238 | if (Style.empty()) |
239 | Stream << V; |
240 | else { |
241 | int X = static_cast<int>(V); |
242 | format_provider<int>::format(X, Stream, Style); |
243 | } |
244 | } |
245 | }; |
246 | |
247 | /// Implementation of format_provider<T> for type `bool` |
248 | /// |
249 | /// The options string of a boolean type has the grammar: |
250 | /// |
251 | /// bool_options :: "" | "Y" | "y" | "D" | "d" | "T" | "t" |
252 | /// |
253 | /// ================================== |
254 | /// | C | Meaning | |
255 | /// ================================== |
256 | /// | Y | YES / NO | |
257 | /// | y | yes / no | |
258 | /// | D / d | Integer 0 or 1 | |
259 | /// | T | TRUE / FALSE | |
260 | /// | t | true / false | |
261 | /// | (empty) | Equivalent to 't' | |
262 | /// ================================== |
263 | template <> struct format_provider<bool> { |
264 | static void format(const bool &B, llvm::raw_ostream &Stream, |
265 | StringRef Style) { |
266 | Stream << StringSwitch<const char *>(Style) |
267 | .Case("Y" , B ? "YES" : "NO" ) |
268 | .Case("y" , B ? "yes" : "no" ) |
269 | .CaseLower("D" , B ? "1" : "0" ) |
270 | .Case("T" , B ? "TRUE" : "FALSE" ) |
271 | .Cases("t" , "" , B ? "true" : "false" ) |
272 | .Default(B ? "1" : "0" ); |
273 | } |
274 | }; |
275 | |
276 | /// Implementation of format_provider<T> for floating point types. |
277 | /// |
278 | /// The options string of a floating point type has the format: |
279 | /// |
280 | /// float_options :: [style][precision] |
281 | /// style :: <see table below> |
282 | /// precision :: <non-negative integer> 0-99 |
283 | /// |
284 | /// ===================================================== |
285 | /// | style | Meaning | Example | |
286 | /// ----------------------------------------------------- |
287 | /// | | | Input | Output | |
288 | /// ===================================================== |
289 | /// | P / p | Percentage | 0.05 | 5.00% | |
290 | /// | F / f | Fixed point | 1.0 | 1.00 | |
291 | /// | E | Exponential with E | 100000 | 1.0E+05 | |
292 | /// | e | Exponential with e | 100000 | 1.0e+05 | |
293 | /// | (empty) | Same as F / f | | | |
294 | /// ===================================================== |
295 | /// |
296 | /// The default precision is 6 for exponential (E / e) and 2 for everything |
297 | /// else. |
298 | |
299 | template <typename T> |
300 | struct format_provider< |
301 | T, typename std::enable_if<detail::use_double_formatter<T>::value>::type> |
302 | : public detail::HelperFunctions { |
303 | static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) { |
304 | FloatStyle S; |
305 | if (Style.consume_front("P" ) || Style.consume_front("p" )) |
306 | S = FloatStyle::Percent; |
307 | else if (Style.consume_front("F" ) || Style.consume_front("f" )) |
308 | S = FloatStyle::Fixed; |
309 | else if (Style.consume_front("E" )) |
310 | S = FloatStyle::ExponentUpper; |
311 | else if (Style.consume_front("e" )) |
312 | S = FloatStyle::Exponent; |
313 | else |
314 | S = FloatStyle::Fixed; |
315 | |
316 | Optional<size_t> Precision = parseNumericPrecision(Style); |
317 | if (!Precision.hasValue()) |
318 | Precision = getDefaultPrecision(S); |
319 | |
320 | write_double(Stream, static_cast<double>(V), S, Precision); |
321 | } |
322 | }; |
323 | |
324 | namespace detail { |
325 | template <typename IterT> |
326 | using IterValue = typename std::iterator_traits<IterT>::value_type; |
327 | |
328 | template <typename IterT> |
329 | struct range_item_has_provider |
330 | : public std::integral_constant< |
331 | bool, !uses_missing_provider<IterValue<IterT>>::value> {}; |
332 | } |
333 | |
334 | /// Implementation of format_provider<T> for ranges. |
335 | /// |
336 | /// This will print an arbitrary range as a delimited sequence of items. |
337 | /// |
338 | /// The options string of a range type has the grammar: |
339 | /// |
340 | /// range_style ::= [separator] [element_style] |
341 | /// separator ::= "$" delimeted_expr |
342 | /// element_style ::= "@" delimeted_expr |
343 | /// delimeted_expr ::= "[" expr "]" | "(" expr ")" | "<" expr ">" |
344 | /// expr ::= <any string not containing delimeter> |
345 | /// |
346 | /// where the separator expression is the string to insert between consecutive |
347 | /// items in the range and the argument expression is the Style specification to |
348 | /// be used when formatting the underlying type. The default separator if |
349 | /// unspecified is ' ' (space). The syntax of the argument expression follows |
350 | /// whatever grammar is dictated by the format provider or format adapter used |
351 | /// to format the value type. |
352 | /// |
353 | /// Note that attempting to format an `iterator_range<T>` where no format |
354 | /// provider can be found for T will result in a compile error. |
355 | /// |
356 | |
357 | template <typename IterT> class format_provider<llvm::iterator_range<IterT>> { |
358 | using value = typename std::iterator_traits<IterT>::value_type; |
359 | using reference = typename std::iterator_traits<IterT>::reference; |
360 | |
361 | static StringRef consumeOneOption(StringRef &Style, char Indicator, |
362 | StringRef Default) { |
363 | if (Style.empty()) |
364 | return Default; |
365 | if (Style.front() != Indicator) |
366 | return Default; |
367 | Style = Style.drop_front(); |
368 | if (Style.empty()) { |
369 | assert(false && "Invalid range style" ); |
370 | return Default; |
371 | } |
372 | |
373 | for (const char *D : {"[]" , "<>" , "()" }) { |
374 | if (Style.front() != D[0]) |
375 | continue; |
376 | size_t End = Style.find_first_of(D[1]); |
377 | if (End == StringRef::npos) { |
378 | assert(false && "Missing range option end delimeter!" ); |
379 | return Default; |
380 | } |
381 | StringRef Result = Style.slice(1, End); |
382 | Style = Style.drop_front(End + 1); |
383 | return Result; |
384 | } |
385 | assert(false && "Invalid range style!" ); |
386 | return Default; |
387 | } |
388 | |
389 | static std::pair<StringRef, StringRef> parseOptions(StringRef Style) { |
390 | StringRef Sep = consumeOneOption(Style, '$', ", " ); |
391 | StringRef Args = consumeOneOption(Style, '@', "" ); |
392 | assert(Style.empty() && "Unexpected text in range option string!" ); |
393 | return std::make_pair(Sep, Args); |
394 | } |
395 | |
396 | public: |
397 | static_assert(detail::range_item_has_provider<IterT>::value, |
398 | "Range value_type does not have a format provider!" ); |
399 | static void format(const llvm::iterator_range<IterT> &V, |
400 | llvm::raw_ostream &Stream, StringRef Style) { |
401 | StringRef Sep; |
402 | StringRef ArgStyle; |
403 | std::tie(Sep, ArgStyle) = parseOptions(Style); |
404 | auto Begin = V.begin(); |
405 | auto End = V.end(); |
406 | if (Begin != End) { |
407 | auto Adapter = |
408 | detail::build_format_adapter(std::forward<reference>(*Begin)); |
409 | Adapter.format(Stream, ArgStyle); |
410 | ++Begin; |
411 | } |
412 | while (Begin != End) { |
413 | Stream << Sep; |
414 | auto Adapter = |
415 | detail::build_format_adapter(std::forward<reference>(*Begin)); |
416 | Adapter.format(Stream, ArgStyle); |
417 | ++Begin; |
418 | } |
419 | } |
420 | }; |
421 | } |
422 | |
423 | #endif |
424 | |