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