1 //===- FormatProviders.h - Formatters for common LLVM types -----*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements format providers for many common LLVM types, for example
10 // allowing precision and width specifiers for scalar and string types.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_SUPPORT_FORMATPROVIDERS_H
15 #define LLVM_SUPPORT_FORMATPROVIDERS_H
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"
24 #include <type_traits>
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
> {};
37 struct use_char_formatter
38 : public std::integral_constant
<bool, std::is_same
<T
, char>::value
> {};
42 : public std::integral_constant
<bool,
43 is_one_of
<T
, char *, const char *>::value
> {
47 struct use_string_formatter
48 : public std::integral_constant
<bool,
49 std::is_convertible
<T
, llvm::StringRef
>::value
> {};
52 struct use_pointer_formatter
53 : public std::integral_constant
<bool, std::is_pointer
<T
>::value
&&
54 !is_cstring
<T
>::value
> {};
57 struct use_double_formatter
58 : public std::integral_constant
<bool, std::is_floating_point
<T
>::value
> {};
60 class HelperFunctions
{
62 static Optional
<size_t> parseNumericPrecision(StringRef Str
) {
64 Optional
<size_t> Result
;
67 else if (Str
.getAsInteger(10, Prec
)) {
68 assert(false && "Invalid precision specifier");
71 assert(Prec
< 100 && "Precision out of range");
72 Result
= std::min
<size_t>(99u, Prec
);
77 static bool consumeHexStyle(StringRef
&Str
, HexPrintStyle
&Style
) {
78 if (!Str
.startswith_lower("x"))
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
;
92 static size_t consumeNumHexDigits(StringRef
&Str
, HexPrintStyle Style
,
94 Str
.consumeInteger(10, Default
);
95 if (isPrefixedHexStyle(Style
))
102 /// Implementation of format_provider<T> for integral arithmetic types.
104 /// The options string of an integral type has the grammar:
106 /// integer_options :: [style][digits]
107 /// style :: <see table below>
108 /// digits :: <non-negative integer> 0-99
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 /// ==========================================================================
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
{
131 static void format(const T
&V
, llvm::raw_ostream
&Stream
, StringRef Style
) {
134 if (consumeHexStyle(Style
, HS
)) {
135 Digits
= consumeNumHexDigits(Style
, HS
, 0);
136 write_hex(Stream
, V
, HS
, Digits
);
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
;
146 Style
.consumeInteger(10, Digits
);
147 assert(Style
.empty() && "Invalid integral format style!");
148 write_integer(Stream
, V
, Digits
, IS
);
152 /// Implementation of format_provider<T> for integral pointer types.
154 /// The options string of a pointer type has the grammar:
156 /// pointer_options :: [style][precision]
157 /// style :: <see table below>
158 /// digits :: <non-negative integer> 0-sizeof(void*)
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 /// ==========================================================================
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
{
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
);
188 /// Implementation of format_provider<T> for c-style strings and string
189 /// objects such as std::string and llvm::StringRef.
191 /// The options string of a string type has the grammar:
193 /// string_options :: [length]
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.
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");
207 llvm::StringRef S
= V
;
208 Stream
<< S
.substr(0, N
);
212 /// Implementation of format_provider<T> for llvm::Twine.
214 /// This follows the same rules as the string formatter.
216 template <> struct format_provider
<Twine
> {
217 static void format(const Twine
&V
, llvm::raw_ostream
&Stream
,
219 format_provider
<std::string
>::format(V
.str(), Stream
, Style
);
223 /// Implementation of format_provider<T> for characters.
225 /// The options string of a character type has the grammar:
227 /// char_options :: (empty) | [integer_options]
229 /// If `char_options` is empty, the character is displayed as an ASCII
230 /// character. Otherwise, it is treated as an integer options string.
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
,
240 int X
= static_cast<int>(V
);
241 format_provider
<int>::format(X
, Stream
, Style
);
246 /// Implementation of format_provider<T> for type `bool`
248 /// The options string of a boolean type has the grammar:
250 /// bool_options :: "" | "Y" | "y" | "D" | "d" | "T" | "t"
252 /// ==================================
254 /// ==================================
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
,
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");
275 /// Implementation of format_provider<T> for floating point types.
277 /// The options string of a floating point type has the format:
279 /// float_options :: [style][precision]
280 /// style :: <see table below>
281 /// precision :: <non-negative integer> 0-99
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 /// =====================================================
295 /// The default precision is 6 for exponential (E / e) and 2 for everything
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
) {
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
;
313 S
= FloatStyle::Fixed
;
315 Optional
<size_t> Precision
= parseNumericPrecision(Style
);
316 if (!Precision
.hasValue())
317 Precision
= getDefaultPrecision(S
);
319 write_double(Stream
, static_cast<double>(V
), S
, Precision
);
324 template <typename IterT
>
325 using IterValue
= typename
std::iterator_traits
<IterT
>::value_type
;
327 template <typename IterT
>
328 struct range_item_has_provider
329 : public std::integral_constant
<
330 bool, !uses_missing_provider
<IterValue
<IterT
>>::value
> {};
333 /// Implementation of format_provider<T> for ranges.
335 /// This will print an arbitrary range as a delimited sequence of items.
337 /// The options string of a range type has the grammar:
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>
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.
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.
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
;
360 static StringRef
consumeOneOption(StringRef
&Style
, char Indicator
,
364 if (Style
.front() != Indicator
)
366 Style
= Style
.drop_front();
368 assert(false && "Invalid range style");
372 for (const char *D
: {"[]", "<>", "()"}) {
373 if (Style
.front() != D
[0])
375 size_t End
= Style
.find_first_of(D
[1]);
376 if (End
== StringRef::npos
) {
377 assert(false && "Missing range option end delimeter!");
380 StringRef Result
= Style
.slice(1, End
);
381 Style
= Style
.drop_front(End
+ 1);
384 assert(false && "Invalid range style!");
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
);
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
) {
402 std::tie(Sep
, ArgStyle
) = parseOptions(Style
);
403 auto Begin
= V
.begin();
407 detail::build_format_adapter(std::forward
<reference
>(*Begin
));
408 Adapter
.format(Stream
, ArgStyle
);
411 while (Begin
!= End
) {
414 detail::build_format_adapter(std::forward
<reference
>(*Begin
));
415 Adapter
.format(Stream
, ArgStyle
);