Line data Source code
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 361 : static Optional<size_t> parseNumericPrecision(StringRef Str) {
64 : size_t Prec;
65 : Optional<size_t> Result;
66 361 : if (Str.empty())
67 : Result = None;
68 0 : 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 462 : Result = std::min<size_t>(99u, Prec);
74 : }
75 361 : return Result;
76 : }
77 :
78 19604 : static bool consumeHexStyle(StringRef &Str, HexPrintStyle &Style) {
79 19604 : if (!Str.startswith_lower("x"))
80 : return false;
81 :
82 : if (Str.consume_front("x-"))
83 5 : Style = HexPrintStyle::Lower;
84 : else if (Str.consume_front("X-"))
85 572 : Style = HexPrintStyle::Upper;
86 : else if (Str.consume_front("x+") || Str.consume_front("x"))
87 143 : Style = HexPrintStyle::PrefixLower;
88 : else if (Str.consume_front("X+") || Str.consume_front("X"))
89 5627 : Style = HexPrintStyle::PrefixUpper;
90 : return true;
91 : }
92 :
93 6353 : static size_t consumeNumHexDigits(StringRef &Str, HexPrintStyle Style,
94 : size_t Default) {
95 : Str.consumeInteger(10, Default);
96 6353 : if (isPrefixedHexStyle(Style))
97 5776 : Default += 2;
98 6353 : 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 19592 : static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
133 : HexPrintStyle HS;
134 : size_t Digits = 0;
135 19592 : if (consumeHexStyle(Style, HS)) {
136 6341 : Digits = consumeNumHexDigits(Style, HS, 0);
137 6341 : write_hex(Stream, V, HS, Digits);
138 6341 : 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 13251 : write_integer(Stream, V, Digits, IS);
150 : }
151 164 : };
152 :
153 : /// Implementation of format_provider<T> for integral pointer types.
154 164 : ///
155 2 : /// The options string of a pointer type has the grammar:
156 2 : ///
157 2 : /// 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 162 : /// | x+ / x | Hex + prefix, lower | 0xDEADBEEF | 0xdeadbeef |
169 : /// | X+ / X | Hex + prefix, upper | 0xDEADBEEF | 0xDEADBEEF |
170 10581 : /// | (empty) | Same as X+ / X | | |
171 : /// ==========================================================================
172 : ///
173 10581 : /// The default precision is the number of nibbles in a machine word, and in all
174 5189 : /// cases indicates the minimum number of nibbles to print.
175 5189 : template <typename T>
176 5189 : 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 0 : static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
182 0 : HexPrintStyle HS = HexPrintStyle::PrefixUpper;
183 0 : consumeHexStyle(Style, HS);
184 0 : size_t Digits = consumeNumHexDigits(Style, HS, sizeof(void *) * 2);
185 0 : write_hex(Stream, reinterpret_cast<std::uintptr_t>(V), HS, Digits);
186 0 : }
187 5392 : };
188 :
189 2046 : /// Implementation of format_provider<T> for c-style strings and string
190 : /// objects such as std::string and llvm::StringRef.
191 : ///
192 2046 : /// The options string of a string type has the grammar:
193 7 : ///
194 7 : /// string_options :: [length]
195 7 : ///
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 4496 : static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
204 : size_t N = StringRef::npos;
205 4496 : if (!Style.empty() && Style.getAsInteger(10, N)) {
206 2039 : assert(false && "Style is not a valid integer");
207 : }
208 4176 : llvm::StringRef S = V;
209 4496 : Stream << S.substr(0, N);
210 4496 : }
211 509 : };
212 2 :
213 195 : /// Implementation of format_provider<T> for llvm::Twine.
214 2 : ///
215 : /// This follows the same rules as the string formatter.
216 193 :
217 193 : template <> struct format_provider<Twine> {
218 193 : static void format(const Twine &V, llvm::raw_ostream &Stream,
219 599 : StringRef Style) {
220 : format_provider<std::string>::format(V.str(), Stream, Style);
221 599 : }
222 : };
223 :
224 12 : /// Implementation of format_provider<T> for characters.
225 913 : ///
226 599 : /// The options string of a character type has the grammar:
227 1 : ///
228 : /// char_options :: (empty) | [integer_options]
229 0 : ///
230 1 : /// If `char_options` is empty, the character is displayed as an ASCII
231 1 : /// character. Otherwise, it is treated as an integer options string.
232 1 : ///
233 1 : template <typename T>
234 0 : struct format_provider<
235 : T, typename std::enable_if<detail::use_char_formatter<T>::value>::type> {
236 0 : static void format(const char &V, llvm::raw_ostream &Stream,
237 : StringRef Style) {
238 0 : if (Style.empty())
239 0 : Stream << V;
240 : else {
241 11705 : int X = static_cast<int>(V);
242 0 : format_provider<int>::format(X, Stream, Style);
243 11705 : }
244 0 : }
245 : };
246 6428 :
247 11705 : /// Implementation of format_provider<T> for type `bool`
248 11705 : ///
249 347 : /// The options string of a boolean type has the grammar:
250 1 : ///
251 347 : /// bool_options :: "" | "Y" | "y" | "D" | "d" | "T" | "t"
252 1 : ///
253 : /// ==================================
254 338 : /// | C | Meaning |
255 346 : /// ==================================
256 346 : /// | Y | YES / NO |
257 5150 : /// | y | yes / no |
258 : /// | D / d | Integer 0 or 1 |
259 5150 : /// | T | TRUE / FALSE |
260 14 : /// | t | true / false |
261 : /// | (empty) | Equivalent to 't' |
262 30 : /// ==================================
263 5150 : template <> struct format_provider<bool> {
264 5150 : static void format(const bool &B, llvm::raw_ostream &Stream,
265 285 : StringRef Style) {
266 14 : Stream << StringSwitch<const char *>(Style)
267 146 : .Case("Y", B ? "YES" : "NO")
268 139 : .Case("y", B ? "yes" : "no")
269 67 : .CaseLower("D", B ? "1" : "0")
270 68 : .Case("T", B ? "TRUE" : "FALSE")
271 199 : .Cases("t", "", B ? "true" : "false")
272 267 : .Default(B ? "1" : "0");
273 5 : }
274 135 : };
275 140 :
276 14 : /// Implementation of format_provider<T> for floating point types.
277 : ///
278 14 : /// The options string of a floating point type has the format:
279 378 : ///
280 5 : /// float_options :: [style][precision]
281 387 : /// style :: <see table below>
282 86 : /// precision :: <non-negative integer> 0-99
283 14 : ///
284 361 : /// =====================================================
285 373 : /// | style | Meaning | Example |
286 373 : /// -----------------------------------------------------
287 9 : /// | | | Input | Output |
288 : /// =====================================================
289 9 : /// | P / p | Percentage | 0.05 | 5.00% |
290 0 : /// | F / f | Fixed point | 1.0 | 1.00 |
291 0 : /// | E | Exponential with E | 100000 | 1.0E+05 |
292 0 : /// | e | Exponential with e | 100000 | 1.0e+05 |
293 9 : /// | (empty) | Same as F / f | | |
294 9 : /// =====================================================
295 151 : ///
296 0 : /// The default precision is 6 for exponential (E / e) and 2 for everything
297 151 : /// else.
298 26 :
299 : template <typename T>
300 174 : struct format_provider<
301 151 : T, typename std::enable_if<detail::use_double_formatter<T>::value>::type>
302 151 : : public detail::HelperFunctions {
303 129 : static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
304 26 : FloatStyle S;
305 26 : if (Style.consume_front("P") || Style.consume_front("p"))
306 0 : S = FloatStyle::Percent;
307 0 : else if (Style.consume_front("F") || Style.consume_front("f"))
308 0 : S = FloatStyle::Fixed;
309 0 : else if (Style.consume_front("E"))
310 3 : S = FloatStyle::ExponentUpper;
311 0 : else if (Style.consume_front("e"))
312 3 : S = FloatStyle::Exponent;
313 3 : else
314 38 : S = FloatStyle::Fixed;
315 12 :
316 141 : Optional<size_t> Precision = parseNumericPrecision(Style);
317 115 : if (!Precision.hasValue())
318 113 : Precision = getDefaultPrecision(S);
319 126 :
320 129 : write_double(Stream, static_cast<double>(V), S, Precision);
321 129 : }
322 0 : };
323 :
324 0 : namespace detail {
325 : template <typename IterT>
326 0 : using IterValue = typename std::iterator_traits<IterT>::value_type;
327 :
328 0 : template <typename IterT>
329 0 : struct range_item_has_provider
330 : : public std::integral_constant<
331 : bool, !uses_missing_provider<IterValue<IterT>>::value> {};
332 88 : }
333 88 :
334 88 : /// Implementation of format_provider<T> for ranges.
335 : ///
336 126 : /// This will print an arbitrary range as a delimited sequence of items.
337 88 : ///
338 48 : /// The options string of a range type has the grammar:
339 : ///
340 : /// range_style ::= [separator] [element_style]
341 32 : /// separator ::= "$" delimeted_expr
342 38 : /// element_style ::= "@" delimeted_expr
343 38 : /// delimeted_expr ::= "[" expr "]" | "(" expr ")" | "<" expr ">"
344 1 : /// expr ::= <any string not containing delimeter>
345 14 : ///
346 1 : /// where the separator expression is the string to insert between consecutive
347 14 : /// items in the range and the argument expression is the Style specification to
348 14 : /// be used when formatting the underlying type. The default separator if
349 15 : /// unspecified is ' ' (space). The syntax of the argument expression follows
350 15 : /// whatever grammar is dictated by the format provider or format adapter used
351 15 : /// to format the value type.
352 20 : ///
353 28 : /// Note that attempting to format an `iterator_range<T>` where no format
354 24 : /// provider can be found for T will result in a compile error.
355 0 : ///
356 0 :
357 6 : template <typename IterT> class format_provider<llvm::iterator_range<IterT>> {
358 6 : using value = typename std::iterator_traits<IterT>::value_type;
359 6 : using reference = typename std::iterator_traits<IterT>::reference;
360 25 :
361 0 : static StringRef consumeOneOption(StringRef &Style, char Indicator,
362 29 : StringRef Default) {
363 0 : if (Style.empty())
364 0 : return Default;
365 25 : if (Style.front() != Indicator)
366 25 : return Default;
367 25 : Style = Style.drop_front();
368 6 : if (Style.empty()) {
369 : assert(false && "Invalid range style");
370 8 : return Default;
371 : }
372 186 :
373 : for (const char *D : {"[]", "<>", "()"}) {
374 192 : if (Style.front() != D[0])
375 192 : continue;
376 186 : size_t End = Style.find_first_of(D[1]);
377 186 : if (End == StringRef::npos) {
378 186 : assert(false && "Missing range option end delimeter!");
379 324 : return Default;
380 372 : }
381 186 : 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 138 : assert(Style.empty() && "Unexpected text in range option string!");
393 138 : return std::make_pair(Sep, Args);
394 0 : }
395 :
396 138 : public:
397 138 : 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 0 : StringRef Sep;
402 : StringRef ArgStyle;
403 0 : std::tie(Sep, ArgStyle) = parseOptions(Style);
404 0 : auto Begin = V.begin();
405 : auto End = V.end();
406 0 : if (Begin != End) {
407 0 : auto Adapter =
408 : detail::build_format_adapter(std::forward<reference>(*Begin));
409 0 : 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
|