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
27namespace llvm {
28namespace detail {
29template <typename T>
30struct 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
36template <typename T>
37struct use_char_formatter
38    : public std::integral_constant<bool, std::is_same<T, char>::value> {};
39
40template <typename T>
41struct is_cstring
42    : public std::integral_constant<bool,
43                                    is_one_of<T, char *, const char *>::value> {
44};
45
46template <typename T>
47struct use_string_formatter
48    : public std::integral_constant<bool,
49                                    std::is_convertible<T, llvm::StringRef>::value> {};
50
51template <typename T>
52struct use_pointer_formatter
53    : public std::integral_constant<bool, std::is_pointer<T>::value &&
54                                              !is_cstring<T>::value> {};
55
56template <typename T>
57struct use_double_formatter
58    : public std::integral_constant<bool, std::is_floating_point<T>::value> {};
59
60class HelperFunctions {
61protected:
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
125template <typename T>
126struct format_provider<
127    T, typename std::enable_if<detail::use_integral_formatter<T>::value>::type>
128    : public detail::HelperFunctions {
129private:
130public:
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.
174template <typename T>
175struct format_provider<
176    T, typename std::enable_if<detail::use_pointer_formatter<T>::value>::type>
177    : public detail::HelperFunctions {
178private:
179public:
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
199template <typename T>
200struct 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
216template <> 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///
232template <typename T>
233struct 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///   ==================================
262template <> 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
298template <typename T>
299struct 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
323namespace detail {
324template <typename IterT>
325using IterValue = typename std::iterator_traits<IterT>::value_type;
326
327template <typename IterT>
328struct 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
356template <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
395public:
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