LCOV - code coverage report
Current view: top level - include/llvm/Support - FormatProviders.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 241 293 82.3 %
Date: 2018-10-17 09:37:48 Functions: 31 33 93.9 %
Legend: Lines: hit not hit

          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       19619 :   static bool consumeHexStyle(StringRef &Str, HexPrintStyle &Style) {
      79       19619 :     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       19607 :   static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
     133             :     HexPrintStyle HS;
     134             :     size_t Digits = 0;
     135       19607 :     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       13266 :     write_integer(Stream, V, Digits, IS);
     150             :   }
     151         125 : };
     152             : 
     153             : /// Implementation of format_provider<T> for integral pointer types.
     154         125 : ///
     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         123 : ///   | x+ / x  | Hex + prefix, lower  |    0xDEADBEEF     |    0xdeadbeef     |
     169             : ///   | X+ / X  | Hex + prefix, upper  |    0xDEADBEEF     |    0xDEADBEEF     |
     170       10633 : ///   | (empty) | Same as X+ / X       |                   |                   |
     171             : ///   ==========================================================================
     172             : ///
     173       10633 : /// 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             :   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        5444 : };
     188             : 
     189        2048 : /// Implementation of format_provider<T> for c-style strings and string
     190             : /// objects such as std::string and llvm::StringRef.
     191             : ///
     192        2048 : /// 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        4855 :   static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
     204             :     size_t N = StringRef::npos;
     205        4855 :     if (!Style.empty() && Style.getAsInteger(10, N)) {
     206        2041 :       assert(false && "Style is not a valid integer");
     207             :     }
     208        4389 :     llvm::StringRef S = V;
     209        4855 :     Stream << S.substr(0, N);
     210        4855 :   }
     211         762 : };
     212           2 : 
     213         448 : /// Implementation of format_provider<T> for llvm::Twine.
     214           2 : ///
     215             : /// This follows the same rules as the string formatter.
     216         446 : 
     217         446 : template <> struct format_provider<Twine> {
     218         446 :   static void format(const Twine &V, llvm::raw_ostream &Stream,
     219         587 :                      StringRef Style) {
     220             :     format_provider<std::string>::format(V.str(), Stream, Style);
     221         587 :   }
     222             : };
     223             : 
     224           0 : /// Implementation of format_provider<T> for characters.
     225         901 : ///
     226         587 : /// The options string of a character type has the grammar:
     227         185 : ///
     228             : ///   char_options :: (empty) | [integer_options]
     229         184 : ///
     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         185 : template <typename T>
     234         184 : struct format_provider<
     235           0 :     T, typename std::enable_if<detail::use_char_formatter<T>::value>::type> {
     236             :   static void format(const char &V, llvm::raw_ostream &Stream,
     237           0 :                      StringRef Style) {
     238             :     if (Style.empty())
     239             :       Stream << V;
     240             :     else {
     241       11239 :       int X = static_cast<int>(V);
     242           0 :       format_provider<int>::format(X, Stream, Style);
     243       11239 :     }
     244           0 :   }
     245             : };
     246        6093 : 
     247       11239 : /// Implementation of format_provider<T> for type `bool`
     248       11239 : ///
     249          26 : /// The options string of a boolean type has the grammar:
     250           1 : ///
     251          26 : ///   bool_options :: "" | "Y" | "y" | "D" | "d" | "T" | "t"
     252           1 : ///
     253             : ///   ==================================
     254          17 : ///   |    C    |     Meaning          |
     255          25 : ///   ==================================
     256          25 : ///   |    Y    |       YES / NO       |
     257        5136 : ///   |    y    |       yes / no       |
     258             : ///   |  D / d  |    Integer 0 or 1    |
     259        5136 : ///   |    T    |     TRUE / FALSE     |
     260          44 : ///   |    t    |     true / false     |
     261             : ///   | (empty) |   Equivalent to 't'  |
     262          46 : ///   ==================================
     263        5136 : template <> struct format_provider<bool> {
     264        5136 :   static void format(const bool &B, llvm::raw_ostream &Stream,
     265         184 :                      StringRef Style) {
     266          44 :     Stream << StringSwitch<const char *>(Style)
     267          45 :                   .Case("Y", B ? "YES" : "NO")
     268         169 :                   .Case("y", B ? "yes" : "no")
     269          67 :                   .CaseLower("D", B ? "1" : "0")
     270          98 :                   .Case("T", B ? "TRUE" : "FALSE")
     271          68 :                   .Cases("t", "", B ? "true" : "false")
     272         136 :                   .Default(B ? "1" : "0");
     273          35 :   }
     274         165 : };
     275         170 : 
     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           0 : ///
     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

Generated by: LCOV version 1.13