llvm.org GIT mirror llvm / 97dac2b
[Support] Introduce llvm::formatv() function. This introduces a new type-safe general purpose formatting library. It provides compile-time type safety, does not require a format specifier (since the type is deduced), and provides mechanisms for extending the format capability to user defined types, and overriding the formatting behavior for existing types. This patch additionally adds documentation for the API to the LLVM programmer's manual. Mailing List Thread: http://lists.llvm.org/pipermail/llvm-dev/2016-October/105836.html Differential Revision: https://reviews.llvm.org/D25587 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286682 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 3 years ago
17 changed file(s) with 1898 addition(s) and 52 deletion(s). Raw diff Collapse all Expand all
261261 almost never be stored or mentioned directly. They are intended solely for use
262262 when defining a function which should be able to efficiently accept concatenated
263263 strings.
264
265 .. _formatting_strings:
266
267 Formatting strings (the ``formatv`` function)
268 ---------------------------------------------
269 While LLVM doesn't necessarily do a lot of string manipulation and parsing, it
270 does do a lot of string formatting. From diagnostic messages, to llvm tool
271 outputs such as ``llvm-readobj`` to printing verbose disassembly listings and
272 LLDB runtime logging, the need for string formatting is pervasive.
273
274 The ``formatv`` is similar in spirit to ``printf``, but uses a different syntax
275 which borrows heavily from Python and C#. Unlike ``printf`` it deduces the type
276 to be formatted at compile time, so it does not need a format specifier such as
277 ``%d``. This reduces the mental overhead of trying to construct portable format
278 strings, especially for platform-specific types like ``size_t`` or pointer types.
279 Unlike both ``printf`` and Python, it additionally fails to compile if LLVM does
280 not know how to format the type. These two properties ensure that the function
281 is both safer and simpler to use than traditional formatting methods such as
282 the ``printf`` family of functions.
283
284 Simple formatting
285 ^^^^^^^^^^^^^^^^^
286
287 A call to ``formatv`` involves a single **format string** consisting of 0 or more
288 **replacement sequences**, followed by a variable length list of **replacement values**.
289 A replacement sequence is a string of the form ``{N[[,align]:style]}``.
290
291 ``N`` refers to the 0-based index of the argument from the list of replacement
292 values. Note that this means it is possible to reference the same parameter
293 multiple times, possibly with different style and/or alignment options, in any order.
294
295 ``align`` is an optional string specifying the width of the field to format
296 the value into, and the alignment of the value within the field. It is specified as
297 an optional **alignment style** followed by a positive integral **field width**. The
298 alignment style can be one of the characters ``-`` (left align), ``=`` (center align),
299 or ``+`` (right align). The default is right aligned.
300
301 ``style`` is an optional string consisting of a type specific that controls the
302 formatting of the value. For example, to format a floating point value as a percentage,
303 you can use the style option ``P``.
304
305 Custom formatting
306 ^^^^^^^^^^^^^^^^^
307
308 There are two ways to customize the formatting behavior for a type.
309
310 1. Provide a template specialization of ``llvm::format_provider`` for your
311 type ``T`` with the appropriate static format method.
312
313 .. code-block:: c++
314
315 namespace llvm {
316 template<>
317 struct format_provider {
318 static void format(const MyFooBar &V, raw_ostream &Stream, StringRef Style) {
319 // Do whatever is necessary to format `V` into `Stream`
320 }
321 };
322 void foo() {
323 MyFooBar X;
324 std::string S = formatv("{0}", X);
325 }
326 }
327
328 This is a useful extensibility mechanism for adding support for formatting your own
329 custom types with your own custom Style options. But it does not help when you want
330 to extend the mechanism for formatting a type that the library already knows how to
331 format. For that, we need something else.
332
333 2. Provide a **format adapter** with a non-static format method.
334
335 .. code-block:: c++
336
337 namespace anything {
338 struct format_int_custom {
339 int N;
340 explicit format_int_custom(int N) : N(N) {}
341 void format(llvm::raw_ostream &Stream, StringRef Style) {
342 // Do whatever is necessary to format ``N`` into ``Stream``
343 }
344 };
345 }
346 namespace llvm {
347 void foo() {
348 std::string S = formatv("{0}", anything::format_int_custom(42));
349 }
350 }
351
352 If the search for a specialization of ``format_provider`` for the given type
353 fails, ``formatv`` will subsequently check the argument for an instance method
354 named ``format`` with the signature described above. If so, it will call the
355 ``format`` method on the argument passing in the specified style. This allows
356 one to provide custom formatting of any type, including one which already has
357 a builtin format provider.
358
359 ``formatv`` Examples
360 ^^^^^^^^^^^^^^^^^^^^
361 Below is intended to provide an incomplete set of examples demonstrating
362 the usage of ``formatv``. More information can be found by reading the
363 doxygen documentation or by looking at the unit test suite.
364
365
366 .. code-block:: c++
367
368 std::string S;
369 // Simple formatting of basic types and implicit string conversion.
370 S = formatv("{0} ({1:P})", 7, 0.35); // S == "7 (35.00%)"
371
372 // Out-of-order referencing and multi-referencing
373 outs() << formatv("{0} {2} {1} {0}", 1, "test", 3); // prints "1 3 test 1"
374
375 // Left, right, and center alignment
376 S = formatv("{0,7}", 'a'); // S == " a";
377 S = formatv("{0,-7}", 'a'); // S == "a ";
378 S = formatv("{0,=7}", 'a'); // S == " a ";
379 S = formatv("{0,+7}", 'a'); // S == " a";
380
381 // Custom styles
382 S = formatv("{0:N} - {0:x} - {1:E}", 12345, 123908342); // S == "12,345 - 0x3039 - 1.24E8"
383
384 // Adapters
385 S = formatv("{0}", fmt_align(42, AlignStyle::Center, 7)); // S == " 42 "
386 S = formatv("{0}", fmt_repeat("hi", 3)); // S == "hihihi"
387 S = formatv("{0}", fmt_pad("hi", 2, 6)); // S == " hi "
388
389 // Ranges
390 std::vector V = {8, 9, 10};
391 S = formatv("{0}", make_range(V.begin(), V.end())); // S == "8, 9, 10"
392 S = formatv("{0:$[+]}", make_range(V.begin(), V.end())); // S == "8+9+10"
393 S = formatv("{0:$[ + ]@[x]}", make_range(V.begin(), V.end())); // S == "0x8 + 0x9 + 0xA"
264394
265395 .. _error_apis:
266396
3232 #include "llvm/Support/Compiler.h"
3333
3434 namespace llvm {
35
36 // Only used by compiler if both template types are the same. Useful when
37 // using SFINAE to test for the existence of member functions.
38 template struct SameType;
39
3540 namespace detail {
3641
3742 template
476481 template struct rank : rank {};
477482 template <> struct rank<0> {};
478483
484 /// \brief traits class for checking whether type T is one of any of the given
485 /// types in the variadic list.
486 template struct is_one_of {
487 static const bool value = false;
488 };
489
490 template
491 struct is_one_of {
492 static const bool value =
493 std::is_same::value || is_one_of::value;
494 };
495
479496 //===----------------------------------------------------------------------===//
480497 // Extra additions for arrays
481498 //===----------------------------------------------------------------------===//
0 //===- FormatAdapters.h - Formatters for common LLVM types -----*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_SUPPORT_FORMATADAPTERS_H
10 #define LLVM_SUPPORT_FORMATADAPTERS_H
11
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/Support/FormatCommon.h"
15 #include "llvm/Support/FormatVariadicDetails.h"
16 #include "llvm/Support/raw_ostream.h"
17
18 namespace llvm {
19 template class AdapterBase {
20 protected:
21 explicit AdapterBase(T &&Item) : Item(Item) {}
22
23 T Item;
24 static_assert(!detail::uses_missing_provider::value,
25 "Item does not have a format provider!");
26 };
27
28 namespace detail {
29 template class AlignAdapter : public AdapterBase {
30 AlignStyle Where;
31 size_t Amount;
32
33 public:
34 AlignAdapter(T &&Item, AlignStyle Where, size_t Amount)
35 : AdapterBase(std::forward(Item)), Where(Where), Amount(Amount) {}
36
37 void format(llvm::raw_ostream &Stream, StringRef Style) {
38 auto Wrapper = detail::build_format_wrapper(std::forward(Item));
39 FmtAlign(Wrapper, Where, Amount).format(Stream, Style);
40 }
41 };
42
43 template class PadAdapter : public AdapterBase {
44 size_t Left;
45 size_t Right;
46
47 public:
48 PadAdapter(T &&Item, size_t Left, size_t Right)
49 : AdapterBase(std::forward(Item)), Left(Left), Right(Right) {}
50
51 void format(llvm::raw_ostream &Stream, StringRef Style) {
52 auto Wrapper = detail::build_format_wrapper(std::forward(Item));
53 Stream.indent(Left);
54 Wrapper.format(Stream, Style);
55 Stream.indent(Right);
56 }
57 };
58
59 template class RepeatAdapter : public AdapterBase {
60 size_t Count;
61
62 public:
63 RepeatAdapter(T &&Item, size_t Count)
64 : AdapterBase(std::forward(Item)), Count(Count) {}
65
66 void format(llvm::raw_ostream &Stream, StringRef Style) {
67 auto Wrapper = detail::build_format_wrapper(std::forward(Item));
68 for (size_t I = 0; I < Count; ++I) {
69 Wrapper.format(Stream, Style);
70 }
71 }
72 };
73 }
74
75 template
76 detail::AlignAdapter fmt_align(T &&Item, AlignStyle Where, size_t Amount) {
77 return detail::AlignAdapter(std::forward(Item), Where, Amount);
78 }
79
80 template
81 detail::PadAdapter fmt_pad(T &&Item, size_t Left, size_t Right) {
82 return detail::PadAdapter(std::forward(Item), Left, Right);
83 }
84
85 template
86 detail::RepeatAdapter fmt_repeat(T &&Item, size_t Count) {
87 return detail::RepeatAdapter(std::forward(Item), Count);
88 }
89 }
90
91 #endif
0 //===- FormatAdapters.h - Formatters for common LLVM types -----*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_SUPPORT_FORMATCOMMON_H
10 #define LLVM_SUPPORT_FORMATCOMMON_H
11
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/Support/FormatVariadicDetails.h"
14 #include "llvm/Support/raw_ostream.h"
15
16 namespace llvm {
17 enum class AlignStyle { Left, Center, Right };
18
19 struct FmtAlign {
20 detail::format_wrapper &Wrapper;
21 AlignStyle Where;
22 size_t Amount;
23
24 FmtAlign(detail::format_wrapper &Wrapper, AlignStyle Where, size_t Amount)
25 : Wrapper(Wrapper), Where(Where), Amount(Amount) {}
26
27 void format(raw_ostream &S, StringRef Options) {
28 // If we don't need to align, we can format straight into the underlying
29 // stream. Otherwise we have to go through an intermediate stream first
30 // in order to calculate how long the output is so we can align it.
31 // TODO: Make the format method return the number of bytes written, that
32 // way we can also skip the intermediate stream for left-aligned output.
33 if (Amount == 0) {
34 Wrapper.format(S, Options);
35 return;
36 }
37 SmallString<64> Item;
38 raw_svector_ostream Stream(Item);
39
40 Wrapper.format(Stream, Options);
41 if (Amount <= Item.size()) {
42 S << Item;
43 return;
44 }
45
46 size_t PadAmount = Amount - Item.size();
47 switch (Where) {
48 case AlignStyle::Left:
49 S << Item;
50 S.indent(PadAmount);
51 break;
52 case AlignStyle::Center: {
53 size_t X = PadAmount / 2;
54 S.indent(X);
55 S << Item;
56 S.indent(PadAmount - X);
57 break;
58 }
59 default:
60 S.indent(PadAmount);
61 S << Item;
62 break;
63 }
64 }
65 };
66 }
67
68 #endif
0 //===- FormatProviders.h - Formatters for common LLVM types -----*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
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/Support/FormatVariadicDetails.h"
21 #include "llvm/Support/NativeFormatting.h"
22
23 #include
24
25 namespace llvm {
26 namespace detail {
27 template
28 struct use_integral_formatter
29 : public std::integral_constant<
30 bool, is_one_of
31 int64_t, uint64_t>::value> {};
32
33 template
34 struct use_char_formatter
35 : public std::integral_constant::value> {};
36
37 template
38 struct is_cstring
39 : public std::integral_constant
40 is_one_of::value> {
41 };
42
43 template
44 struct use_string_formatter
45 : public std::integral_constant<
46 bool, is_one_of::value ||
47 is_cstring::value> {};
48
49 template
50 struct use_pointer_formatter
51 : public std::integral_constant::value &&
52 !is_cstring::value> {};
53
54 template
55 struct use_double_formatter
56 : public std::integral_constant::value> {};
57
58 class HelperFunctions {
59 protected:
60 static Optional parseNumericPrecision(StringRef Str) {
61 size_t Prec;
62 Optional Result;
63 if (Str.empty())
64 Result = None;
65 else if (Str.getAsInteger(10, Prec)) {
66 assert(false && "Invalid precision specifier");
67 Result = None;
68 } else {
69 assert(Prec < 100 && "Precision out of range");
70 Result = std::min(99u, Prec);
71 }
72 return Result;
73 }
74
75 static bool consumeHexStyle(StringRef &Str, HexPrintStyle &Style) {
76 if (!Str.startswith_lower("x"))
77 return false;
78
79 if (Str.consume_front("x-"))
80 Style = HexPrintStyle::Lower;
81 else if (Str.consume_front("X-"))
82 Style = HexPrintStyle::Upper;
83 else if (Str.consume_front("x+") || Str.consume_front("x"))
84 Style = HexPrintStyle::PrefixLower;
85 else if (Str.consume_front("X+") || Str.consume_front("X"))
86 Style = HexPrintStyle::PrefixUpper;
87 return true;
88 }
89
90 static size_t consumeNumHexDigits(StringRef &Str, HexPrintStyle Style,
91 size_t Default) {
92 Str.consumeInteger(10, Default);
93 if (isPrefixedHexStyle(Style))
94 Default += 2;
95 return Default;
96 }
97 };
98 }
99
100 /// Implementation of format_provider for integral arithmetic types.
101 ///
102 /// The options string of an integral type has the grammar:
103 ///
104 /// integer_options :: [style][digits]
105 /// style ::
106 /// digits :: 0-99
107 ///
108 /// ==========================================================================
109 /// | style | Meaning | Example | Digits Meaning |
110 /// --------------------------------------------------------------------------
111 /// | | | Input | Output | |
112 /// ==========================================================================
113 /// | x- | Hex no prefix, lower | 42 | 2a | Minimum # digits |
114 /// | X- | Hex no prefix, upper | 42 | 2A | Minimum # digits |
115 /// | x+ / x | Hex + prefix, lower | 42 | 0x2a | Minimum # digits |
116 /// | X+ / X | Hex + prefix, upper | 42 | 0x2A | Minimum # digits |
117 /// | N / n | Digit grouped number | 123456 | 123,456 | Ignored |
118 /// | D / d | Integer | 100000 | 100000 | Ignored |
119 /// | (empty) | Same as D / d | | | |
120 /// ==========================================================================
121 ///
122
123 template
124 struct format_provider<
125 T, typename std::enable_if::value>::type>
126 : public detail::HelperFunctions {
127 private:
128 public:
129 static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
130 HexPrintStyle HS;
131 size_t Digits = 0;
132 if (consumeHexStyle(Style, HS)) {
133 Digits = consumeNumHexDigits(Style, HS, 0);
134 write_hex(Stream, V, HS, Digits);
135 return;
136 }
137
138 IntegerStyle IS = IntegerStyle::Integer;
139 if (Style.consume_front("N") || Style.consume_front("n"))
140 IS = IntegerStyle::Number;
141 else if (Style.consume_front("D") || Style.consume_front("d"))
142 IS = IntegerStyle::Integer;
143
144 Style.consumeInteger(10, Digits);
145 assert(Style.empty() && "Invalid integral format style!");
146 write_integer(Stream, V, Digits, IS);
147 }
148 };
149
150 /// Implementation of format_provider for integral pointer types.
151 ///
152 /// The options string of a pointer type has the grammar:
153 ///
154 /// pointer_options :: [style][precision]
155 /// style ::
156 /// digits :: 0-sizeof(void*)
157 ///
158 /// ==========================================================================
159 /// | S | Meaning | Example |
160 /// --------------------------------------------------------------------------
161 /// | | | Input | Output |
162 /// ==========================================================================
163 /// | x- | Hex no prefix, lower | 0xDEADBEEF | deadbeef |
164 /// | X- | Hex no prefix, upper | 0xDEADBEEF | DEADBEEF |
165 /// | x+ / x | Hex + prefix, lower | 0xDEADBEEF | 0xdeadbeef |
166 /// | X+ / X | Hex + prefix, upper | 0xDEADBEEF | 0xDEADBEEF |
167 /// | (empty) | Same as X+ / X | | |
168 /// ==========================================================================
169 ///
170 /// The default precision is the number of nibbles in a machine word, and in all
171 /// cases indicates the minimum number of nibbles to print.
172 template
173 struct format_provider<
174 T, typename std::enable_if::value>::type>
175 : public detail::HelperFunctions {
176 private:
177 public:
178 static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
179 HexPrintStyle HS = HexPrintStyle::PrefixUpper;
180 consumeHexStyle(Style, HS);
181 size_t Digits = consumeNumHexDigits(Style, HS, sizeof(void *) * 2);
182 write_hex(Stream, reinterpret_cast(V), HS, Digits);
183 }
184 };
185
186 /// Implementation of format_provider for c-style strings and string
187 /// objects such as std::string and llvm::StringRef.
188 ///
189 /// The options string of a string type has the grammar:
190 ///
191 /// string_options :: [length]
192 ///
193 /// where `length` is an optional integer specifying the maximum number of
194 /// characters in the string to print. If `length` is omitted, the string is
195 /// printed up to the null terminator.
196
197 template
198 struct format_provider<
199 T, typename std::enable_if::value>::type> {
200 static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
201 size_t N = StringRef::npos;
202 if (!Style.empty() && Style.getAsInteger(10, N)) {
203 assert(false && "Style is not a valid integer");
204 }
205 llvm::StringRef S(V);
206 Stream << S.substr(0, N);
207 }
208 };
209
210 /// Implementation of format_provider for characters.
211 ///
212 /// The options string of a character type has the grammar:
213 ///
214 /// char_options :: (empty) | [integer_options]
215 ///
216 /// If `char_options` is empty, the character is displayed as an ASCII
217 /// character. Otherwise, it is treated as an integer options string.
218 ///
219 template
220 struct format_provider<
221 T, typename std::enable_if::value>::type> {
222 static void format(const char &V, llvm::raw_ostream &Stream,
223 StringRef Style) {
224 if (Style.empty())
225 Stream << V;
226 else {
227 int X = static_cast(V);
228 format_provider::format(X, Stream, Style);
229 }
230 }
231 };
232
233 /// Implementation of format_provider for type `bool`
234 ///
235 /// The options string of a boolean type has the grammar:
236 ///
237 /// bool_options :: "" | "Y" | "y" | "D" | "d" | "T" | "t"
238 ///
239 /// ==================================
240 /// | C | Meaning |
241 /// ==================================
242 /// | Y | YES / NO |
243 /// | y | yes / no |
244 /// | D / d | Integer 0 or 1 |
245 /// | T | TRUE / FALSE |
246 /// | t | true / false |
247 /// | (empty) | Equivalent to 't' |
248 /// ==================================
249 template <> struct format_provider {
250 static void format(const bool &B, llvm::raw_ostream &Stream,
251 StringRef Style) {
252 Stream << StringSwitch(Style)
253 .Case("Y", B ? "YES" : "NO")
254 .Case("y", B ? "yes" : "no")
255 .CaseLower("D", B ? "1" : "0")
256 .Case("T", B ? "TRUE" : "FALSE")
257 .Cases("t", "", B ? "true" : "false")
258 .Default(B ? "1" : "0");
259 }
260 };
261
262 /// Implementation of format_provider for floating point types.
263 ///
264 /// The options string of a floating point type has the format:
265 ///
266 /// float_options :: [style][precision]
267 /// style ::
268 /// precision :: 0-99
269 ///
270 /// =====================================================
271 /// | style | Meaning | Example |
272 /// -----------------------------------------------------
273 /// | | | Input | Output |
274 /// =====================================================
275 /// | P / p | Percentage | 0.05 | 5.00% |
276 /// | F / f | Fixed point | 1.0 | 1.00 |
277 /// | E | Exponential with E | 100000 | 1.0E+05 |
278 /// | e | Exponential with e | 100000 | 1.0e+05 |
279 /// | (empty) | Same as F / f | | |
280 /// =====================================================
281 ///
282 /// The default precision is 6 for exponential (E / e) and 2 for everything
283 /// else.
284
285 template
286 struct format_provider<
287 T, typename std::enable_if::value>::type>
288 : public detail::HelperFunctions {
289 static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
290 FloatStyle S;
291 if (Style.consume_front("P") || Style.consume_front("p"))
292 S = FloatStyle::Percent;
293 else if (Style.consume_front("F") || Style.consume_front("f"))
294 S = FloatStyle::Fixed;
295 else if (Style.consume_front("E"))
296 S = FloatStyle::ExponentUpper;
297 else if (Style.consume_front("e"))
298 S = FloatStyle::Exponent;
299 else
300 S = FloatStyle::Fixed;
301
302 Optional Precision = parseNumericPrecision(Style);
303 if (!Precision.hasValue())
304 Precision = getDefaultPrecision(S);
305
306 write_double(Stream, static_cast(V), S, Precision);
307 }
308 };
309
310 namespace detail {
311 template
312 using IterValue = typename std::iterator_traits::value_type;
313
314 template
315 struct range_item_has_provider
316 : public std::integral_constant<
317 bool, !uses_missing_provider>::value> {};
318 }
319
320 /// Implementation of format_provider for ranges.
321 ///
322 /// This will print an arbitrary range as a delimited sequence of items.
323 ///
324 /// The options string of a range type has the grammar:
325 ///
326 /// range_style ::= [separator] [element_style]
327 /// separator ::= "$" delimeted_expr
328 /// element_style ::= "@" delimeted_expr
329 /// delimeted_expr ::= "[" expr "]" | "(" expr ")" | "<" expr ">"
330 /// expr ::=
331 ///
332 /// where the separator expression is the string to insert between consecutive
333 /// items in the range and the argument expression is the Style specification to
334 /// be used when formatting the underlying type. The default separator if
335 /// unspecified is ' ' (space). The syntax of the argument expression follows
336 /// whatever grammar is dictated by the format provider or format adapter used
337 /// to format the value type.
338 ///
339 /// Note that attempting to format an `iterator_range` where no format
340 /// provider can be found for T will result in a compile error.
341 ///
342
343 template class format_provider> {
344 using value = typename std::iterator_traits::value_type;
345 using reference = typename std::iterator_traits::reference;
346
347 static StringRef consumeOneOption(StringRef &Style, char Indicator,
348 StringRef Default) {
349 if (Style.empty())
350 return Default;
351 if (Style.front() != Indicator)
352 return Default;
353 Style = Style.drop_front();
354 if (Style.empty()) {
355 assert(false && "Invalid range style");
356 return Default;
357 }
358
359 std::vector Delims = {"[]", "<>", "()"};
360 for (const char *D : Delims) {
361 if (Style.front() != D[0])
362 continue;
363 size_t End = Style.find_first_of(D[1]);
364 if (End == StringRef::npos) {
365 assert(false && "Missing range option end delimeter!");
366 return Default;
367 }
368 StringRef Result = Style.slice(1, End);
369 Style = Style.drop_front(End + 1);
370 return Result;
371 }
372 assert(false && "Invalid range style!");
373 return Default;
374 }
375
376 static std::pair parseOptions(StringRef Style) {
377 StringRef Sep = consumeOneOption(Style, '$', ", ");
378 StringRef Args = consumeOneOption(Style, '@', "");
379 assert(Style.empty() && "Unexpected text in range option string!");
380 return std::make_pair(Sep, Args);
381 }
382
383 public:
384 static_assert(detail::range_item_has_provider::value,
385 "Range value_type does not have a format provider!");
386 static void format(const llvm::iterator_range &V,
387 llvm::raw_ostream &Stream, StringRef Style) {
388 StringRef Sep;
389 StringRef ArgStyle;
390 std::tie(Sep, ArgStyle) = parseOptions(Style);
391 auto Begin = V.begin();
392 auto End = V.end();
393 if (Begin != End) {
394 auto Wrapper =
395 detail::build_format_wrapper(std::forward(*Begin));
396 Wrapper.format(Stream, ArgStyle);
397 ++Begin;
398 }
399 while (Begin != End) {
400 Stream << Sep;
401 auto Wrapper =
402 detail::build_format_wrapper(std::forward(*Begin));
403 Wrapper.format(Stream, ArgStyle);
404 ++Begin;
405 }
406 }
407 };
408 }
409
410 #endif
0 //===- FormatVariadic.h - Efficient type-safe string formatting --*- C++-*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the formatv() function which can be used with other LLVM
10 // subsystems to provide printf-like formatting, but with improved safety and
11 // flexibility. The result of `formatv` is an object which can be streamed to
12 // a raw_ostream or converted to a std::string or llvm::SmallString.
13 //
14 // // Convert to std::string.
15 // std::string S = formatv("{0} {1}", 1234.412, "test").str();
16 //
17 // // Convert to llvm::SmallString
18 // SmallString<8> S = formatv("{0} {1}", 1234.412, "test").sstr<8>();
19 //
20 // // Stream to an existing raw_ostream.
21 // OS << formatv("{0} {1}", 1234.412, "test");
22 //
23 //===----------------------------------------------------------------------===//
24
25 #ifndef LLVM_SUPPORT_FORMATVARIADIC_H
26 #define LLVM_SUPPORT_FORMATVARIADIC_H
27
28 #include "llvm/ADT/STLExtras.h"
29 #include "llvm/ADT/SmallString.h"
30 #include "llvm/ADT/StringRef.h"
31 #include "llvm/Support/DataTypes.h"
32 #include "llvm/Support/FormatCommon.h"
33 #include "llvm/Support/FormatProviders.h"
34 #include "llvm/Support/FormatVariadicDetails.h"
35 #include "llvm/Support/raw_ostream.h"
36
37 #include
38 #include
39 #include
40
41 namespace llvm {
42
43 enum class ReplacementType { Empty, Format, Literal };
44
45 struct ReplacementItem {
46 ReplacementItem() {}
47 explicit ReplacementItem(StringRef Literal)
48 : Type(ReplacementType::Literal), Spec(Literal) {}
49 ReplacementItem(StringRef Spec, size_t Index, size_t Align, AlignStyle Where,
50 char Pad, StringRef Options)
51 : Type(ReplacementType::Format), Spec(Spec), Index(Index), Align(Align),
52 Where(Where), Pad(Pad), Options(Options) {}
53 ReplacementType Type = ReplacementType::Empty;
54 StringRef Spec;
55 size_t Index = 0;
56 size_t Align = 0;
57 AlignStyle Where = AlignStyle::Right;
58 char Pad;
59 StringRef Options;
60 };
61
62 class formatv_object_base {
63 protected:
64 // The parameters are stored in a std::tuple, which does not provide runtime
65 // indexing capabilities. In order to enable runtime indexing, we use this
66 // structure to put the parameters into a std::vector. Since the parameters
67 // are not all the same type, we use some type-erasure by wrapping the
68 // parameters in a template class that derives from a non-template superclass.
69 // Essentially, we are converting a std::tuple> to a
70 // std::vector.
71 struct create_wrappers {
72 template
73 std::vector operator()(Ts &... Items) {
74 return std::vector{&Items...};
75 }
76 };
77
78 StringRef Fmt;
79 std::vector Wrappers;
80 std::vector Replacements;
81
82 static bool consumeFieldLayout(StringRef &Spec, AlignStyle &Where,
83 size_t &Align, char &Pad);
84
85 static std::pair
86 splitLiteralAndReplacement(StringRef Fmt);
87
88 public:
89 formatv_object_base(StringRef Fmt, std::size_t ParamCount)
90 : Fmt(Fmt), Replacements(parseFormatString(Fmt)) {
91 Wrappers.reserve(ParamCount);
92 return;
93 }
94
95 void format(raw_ostream &S) const {
96 for (auto &R : Replacements) {
97 if (R.Type == ReplacementType::Empty)
98 continue;
99 if (R.Type == ReplacementType::Literal) {
100 S << R.Spec;
101 continue;
102 }
103 if (R.Index >= Wrappers.size()) {
104 S << R.Spec;
105 continue;
106 }
107
108 auto W = Wrappers[R.Index];
109
110 FmtAlign Align(*W, R.Where, R.Align);
111 Align.format(S, R.Options);
112 }
113 }
114 static std::vector parseFormatString(StringRef Fmt);
115
116 static Optional parseReplacementItem(StringRef Spec);
117
118 std::string str() const {
119 std::string Result;
120 raw_string_ostream Stream(Result);
121 Stream << *this;
122 Stream.flush();
123 return Result;
124 }
125
126 template llvm::SmallString sstr() const {
127 SmallString Result;
128 raw_svector_ostream Stream(Result);
129 Stream << *this;
130 return Result;
131 }
132
133 template operator SmallString() const { return sstr(); }
134
135 operator std::string() const { return str(); }
136 };
137
138 template class formatv_object : public formatv_object_base {
139 // Storage for the parameter wrappers. Since the base class erases the type
140 // of the parameters, we have to own the storage for the parameters here, and
141 // have the base class store type-erased pointers into this tuple.
142 Tuple Parameters;
143
144 public:
145 formatv_object(StringRef Fmt, Tuple &&Params)
146 : formatv_object_base(Fmt, std::tuple_size::value),
147 Parameters(std::move(Params)) {
148 Wrappers = apply_tuple(create_wrappers(), Parameters);
149 }
150 };
151
152 // \brief Format text given a format string and replacement parameters.
153 //
154 // ===General Description===
155 //
156 // Formats textual output. `Fmt` is a string consisting of one or more
157 // replacement sequences with the following grammar:
158 //
159 // rep_field ::= "{" [index] ["," layout] [":" format] "}"
160 // index ::=
161 // layout ::= [[[char]loc]width]
162 // format ::=
163 // char ::=
164 // loc ::= "-" | "=" | "+"
165 // width ::=
166 //
167 // index - A non-negative integer specifying the index of the item in the
168 // parameter pack to print. Any other value is invalid.
169 // layout - A string controlling how the field is laid out within the available
170 // space.
171 // format - A type-dependent string used to provide additional options to
172 // the formatting operation. Refer to the documentation of the
173 // various individual format providers for per-type options.
174 // char - The padding character. Defaults to ' ' (space). Only valid if
175 // `loc` is also specified.
176 // loc - Where to print the formatted text within the field. Only valid if
177 // `width` is also specified.
178 // '-' : The field is left aligned within the available space.
179 // '=' : The field is centered within the available space.
180 // '+' : The field is right aligned within the available space (this
181 // is the default).
182 // width - The width of the field within which to print the formatted text.
183 // If this is less than the required length then the `char` and `loc`
184 // fields are ignored, and the field is printed with no leading or
185 // trailing padding. If this is greater than the required length,
186 // then the text is output according to the value of `loc`, and padded
187 // as appropriate on the left and/or right by `char`.
188 //
189 // ===Special Characters===
190 //
191 // The characters '{' and '}' are reserved and cannot appear anywhere within a
192 // replacement sequence. Outside of a replacement sequence, in order to print
193 // a literal '{' or '}' it must be doubled -- "{{" to print a literal '{' and
194 // "}}" to print a literal '}'.
195 //
196 // ===Parameter Indexing===
197 // `index` specifies the index of the paramter in the parameter pack to format
198 // into the output. Note that it is possible to refer to the same parameter
199 // index multiple times in a given format string. This makes it possible to
200 // output the same value multiple times without passing it multiple times to the
201 // function. For example:
202 //
203 // formatv("{0} {1} {0}", "a", "bb")
204 //
205 // would yield the string "abba". This can be convenient when it is expensive
206 // to compute the value of the parameter, and you would otherwise have had to
207 // save it to a temporary.
208 //
209 // ===Formatter Search===
210 //
211 // For a given parameter of type T, the following steps are executed in order
212 // until a match is found:
213 //
214 // 1. If the parameter is of class type, and contains a method
215 // void format(raw_ostream &Stream, StringRef Options)
216 // Then this method is invoked to produce the formatted output. The
217 // implementation should write the formatted text into `Stream`.
218 // 2. If there is a suitable template specialization of format_provider<>
219 // for type T containing a method whose signature is:
220 // void format(const T &Obj, raw_ostream &Stream, StringRef Options)
221 // Then this method is invoked as described in Step 1.
222 //
223 // If a match cannot be found through either of the above methods, a compiler
224 // error is generated.
225 //
226 // ===Invalid Format String Handling===
227 //
228 // In the case of a format string which does not match the grammar described
229 // above, the output is undefined. With asserts enabled, LLVM will trigger an
230 // assertion. Otherwise, it will try to do something reasonable, but in general
231 // the details of what that is are undefined.
232 //
233 template
234 inline auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object
235 std::make_tuple(detail::build_format_wrapper(std::forward(Vals))...))> {
236 using ParamTuple = decltype(
237 std::make_tuple(detail::build_format_wrapper(std::forward(Vals))...));
238 return formatv_object(
239 Fmt,
240 std::make_tuple(detail::build_format_wrapper(std::forward(Vals))...));
241 }
242
243 } // end namespace llvm
244
245 #endif
0 //===- FormatVariadicDetails.h - Helpers for FormatVariadic.h ----*- C++-*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_SUPPORT_FORMATVARIADIC_DETAILS_H
10 #define LLVM_SUPPORT_FORMATVARIADIC_DETAILS_H
11
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/Support/raw_ostream.h"
14
15 #include
16
17 namespace llvm {
18 template struct format_provider {};
19
20 namespace detail {
21
22 class format_wrapper {
23 protected:
24 ~format_wrapper() {}
25
26 public:
27 virtual void format(llvm::raw_ostream &S, StringRef Options) = 0;
28 };
29
30 template class member_format_wrapper : public format_wrapper {
31 T Item;
32
33 public:
34 explicit member_format_wrapper(T &&Item) : Item(Item) {}
35
36 void format(llvm::raw_ostream &S, StringRef Options) override {
37 Item.format(S, Options);
38 }
39 };
40
41 template class provider_format_wrapper : public format_wrapper {
42 T Item;
43
44 public:
45 explicit provider_format_wrapper(T &&Item) : Item(Item) {}
46
47 void format(llvm::raw_ostream &S, StringRef Options) override {
48 format_provider::type>::format(Item, S, Options);
49 }
50 };
51
52 template class missing_format_wrapper : public format_wrapper {
53 public:
54 missing_format_wrapper() {
55 static_assert(false, "T does not have a format_provider");
56 }
57 void format(llvm::raw_ostream &S, StringRef Options) override {}
58 };
59
60 // Test if T is a class that contains a member function with the signature:
61 //
62 // void format(raw_ostream &, StringRef);
63 //
64 template class has_FormatMember {
65 public:
66 static bool const value = false;
67 };
68
69 template
70 class has_FormatMember
71 typename std::enable_if::value>::type> {
72 using Signature_format = void (T::*)(llvm::raw_ostream &S, StringRef Options);
73
74 template
75 static char test2(SameType *);
76
77 template static double test2(...);
78
79 public:
80 static bool const value = (sizeof(test2(nullptr)) == 1);
81 };
82
83 // Test if format_provider is defined on T and contains a member function
84 // with the signature:
85 // static void format(const T&, raw_stream &, StringRef);
86 //
87 template class has_FormatProvider {
88 public:
89 using Decayed = typename std::decay::type;
90 typedef void (*Signature_format)(const Decayed &, llvm::raw_ostream &,
91 StringRef);
92
93 template
94 static char test(SameType *);
95
96 template static double test(...);
97
98 static bool const value =
99 (sizeof(test>(nullptr)) == 1);
100 };
101
102 // Simple template that decides whether a type T should use the member-function
103 // based format() invocation.
104 template
105 struct uses_format_member
106 : public std::integral_constant::value> {};
107
108 // Simple template that decides whether a type T should use the format_provider
109 // based format() invocation. The member function takes priority, so this test
110 // will only be true if there is not ALSO a format member.
111 template
112 struct uses_format_provider
113 : public std::integral_constant::value &&
114 has_FormatProvider::value> {};
115
116 // Simple template that decides whether a type T has neither a member-function
117 // nor format_provider based implementation that it can use. Mostly used so
118 // that the compiler spits out a nice diagnostic when a type with no format
119 // implementation can be located.
120 template
121 struct uses_missing_provider
122 : public std::integral_constant::value &&
123 !has_FormatProvider::value> {};
124
125 template
126 typename std::enable_if::value,
127 member_format_wrapper>::type
128 build_format_wrapper(T &&Item) {
129 return member_format_wrapper(std::forward(Item));
130 }
131
132 template
133 typename std::enable_if::value,
134 provider_format_wrapper>::type
135 build_format_wrapper(T &&Item) {
136 return provider_format_wrapper(std::forward(Item));
137 }
138
139 template
140 typename std::enable_if::value,
141 missing_format_wrapper>::type
142 build_format_wrapper(T &&Item) {
143 return missing_format_wrapper();
144 }
145 }
146 }
147
148 #endif
2424
2525 size_t getDefaultPrecision(FloatStyle Style);
2626
27 void write_integer(raw_ostream &S, unsigned int N, IntegerStyle Style);
28 void write_integer(raw_ostream &S, int N, IntegerStyle Style);
29 void write_integer(raw_ostream &S, unsigned long N, IntegerStyle Style);
30 void write_integer(raw_ostream &S, long N, IntegerStyle Style);
31 void write_integer(raw_ostream &S, unsigned long long N, IntegerStyle Style);
32 void write_integer(raw_ostream &S, long long N, IntegerStyle Style);
27 bool isPrefixedHexStyle(HexPrintStyle S);
28
29 void write_integer(raw_ostream &S, unsigned int N, size_t MinDigits,
30 IntegerStyle Style);
31 void write_integer(raw_ostream &S, int N, size_t MinDigits, IntegerStyle Style);
32 void write_integer(raw_ostream &S, unsigned long N, size_t MinDigits,
33 IntegerStyle Style);
34 void write_integer(raw_ostream &S, long N, size_t MinDigits,
35 IntegerStyle Style);
36 void write_integer(raw_ostream &S, unsigned long long N, size_t MinDigits,
37 IntegerStyle Style);
38 void write_integer(raw_ostream &S, long long N, size_t MinDigits,
39 IntegerStyle Style);
3340
3441 void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style,
3542 Optional Width = None);
1010 #define LLVM_SUPPORT_YAMLTRAITS_H
1111
1212 #include "llvm/ADT/Optional.h"
13 #include "llvm/ADT/STLExtras.h"
1314 #include "llvm/ADT/SmallVector.h"
1415 #include "llvm/ADT/StringMap.h"
1516 #include "llvm/ADT/StringRef.h"
200201 // static T::value_type& element(IO &io, T &seq, size_t index);
201202 };
202203
203 // Only used by compiler if both template types are the same
204 template
205 struct SameType;
206
207204 // Only used for better diagnostics of missing traits
208205 template
209206 struct MissingTrait;
1919 #include
2020
2121 namespace llvm {
22 class formatv_object_base;
2223 class format_object_base;
2324 class FormattedString;
2425 class FormattedNumber;
221222
222223 // Formatted output, see the formatHex() function in Support/Format.h.
223224 raw_ostream &operator<<(const FormattedNumber &);
225
226 // Formatted output, see the formatv() function in Support/FormatVariadic.h.
227 raw_ostream &operator<<(const formatv_object_base &);
224228
225229 // Formatted output, see the format_bytes() function in Support/Format.h.
226230 raw_ostream &operator<<(const FormattedBytes &);
5454 FileOutputBuffer.cpp
5555 FoldingSet.cpp
5656 FormattedStream.cpp
57 FormatVariadic.cpp
5758 GraphWriter.cpp
5859 Hashing.cpp
5960 IntEqClasses.cpp
0 //===- FormatVariadic.cpp - Format string parsing and analysis ----*-C++-*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
7
8 #include "llvm/Support/FormatVariadic.h"
9
10 using namespace llvm;
11
12 static Optional translateLocChar(char C) {
13 switch (C) {
14 case '-':
15 return AlignStyle::Left;
16 case '=':
17 return AlignStyle::Center;
18 case '+':
19 return AlignStyle::Right;
20 default:
21 return None;
22 }
23 LLVM_BUILTIN_UNREACHABLE;
24 }
25
26 bool formatv_object_base::consumeFieldLayout(StringRef &Spec, AlignStyle &Where,
27 size_t &Align, char &Pad) {
28 Where = AlignStyle::Right;
29 Align = 0;
30 Pad = ' ';
31 if (Spec.empty())
32 return true;
33
34 if (Spec.size() > 1) {
35 // A maximum of 2 characters at the beginning can be used for something
36 // other
37 // than the width.
38 // If Spec[1] is a loc char, then Spec[0] is a pad char and Spec[2:...]
39 // contains the width.
40 // Otherwise, if Spec[0] is a loc char, then Spec[1:...] contains the width.
41 // Otherwise, Spec[0:...] contains the width.
42 if (auto Loc = translateLocChar(Spec[1])) {
43 Pad = Spec[0];
44 Where = *Loc;
45 Spec = Spec.drop_front(2);
46 } else if (auto Loc = translateLocChar(Spec[0])) {
47 Where = *Loc;
48 Spec = Spec.drop_front(1);
49 }
50 }
51
52 bool Failed = Spec.consumeInteger(0, Align);
53 return !Failed;
54 }
55
56 Optional
57 formatv_object_base::parseReplacementItem(StringRef Spec) {
58 StringRef RepString = Spec.trim("{}");
59
60 // If the replacement sequence does not start with a non-negative integer,
61 // this is an error.
62 char Pad = ' ';
63 std::size_t Align = 0;
64 AlignStyle Where = AlignStyle::Right;
65 StringRef Options;
66 size_t Index = 0;
67 RepString = RepString.trim();
68 if (RepString.consumeInteger(0, Index)) {
69 assert(false && "Invalid replacement sequence index!");
70 return ReplacementItem{};
71 }
72 RepString = RepString.trim();
73 if (!RepString.empty() && RepString.front() == ',') {
74 RepString = RepString.drop_front();
75 if (!consumeFieldLayout(RepString, Where, Align, Pad))
76 assert(false && "Invalid replacement field layout specification!");
77 }
78 RepString = RepString.trim();
79 if (!RepString.empty() && RepString.front() == ':') {
80 Options = RepString.drop_front().trim();
81 RepString = StringRef();
82 }
83 RepString = RepString.trim();
84 if (!RepString.empty()) {
85 assert(false && "Unexpected characters found in replacement string!");
86 }
87
88 return ReplacementItem{Spec, Index, Align, Where, Pad, Options};
89 }
90
91 std::pair
92 formatv_object_base::splitLiteralAndReplacement(StringRef Fmt) {
93 StringRef Rep;
94 StringRef Remainder;
95 std::size_t From = 0;
96 while (From < Fmt.size() && From != StringRef::npos) {
97 std::size_t BO = Fmt.find_first_of('{', From);
98 // Everything up until the first brace is a literal.
99 if (BO != 0)
100 return std::make_pair(ReplacementItem{Fmt.substr(0, BO)}, Fmt.substr(BO));
101
102 StringRef Braces =
103 Fmt.drop_front(BO).take_while([](char C) { return C == '{'; });
104 // If there is more than one brace, then some of them are escaped. Treat
105 // these as replacements.
106 if (Braces.size() > 1) {
107 size_t NumEscapedBraces = Braces.size() / 2;
108 StringRef Middle = Fmt.substr(BO, NumEscapedBraces);
109 StringRef Right = Fmt.drop_front(BO + NumEscapedBraces * 2);
110 return std::make_pair(ReplacementItem{Middle}, Right);
111 }
112 // An unterminated open brace is undefined. We treat the rest of the string
113 // as a literal replacement, but we assert to indicate that this is
114 // undefined and that we consider it an error.
115 std::size_t BC = Fmt.find_first_of('}', BO);
116 if (BC == StringRef::npos) {
117 assert(
118 false &&
119 "Unterminated brace sequence. Escape with {{ for a literal brace.");
120 return std::make_pair(ReplacementItem{Fmt}, StringRef());
121 }
122
123 // Even if there is a closing brace, if there is another open brace before
124 // this closing brace, treat this portion as literal, and try again with the
125 // next one.
126 std::size_t BO2 = Fmt.find_first_of('{', BO + 1);
127 if (BO2 < BC)
128 return std::make_pair(ReplacementItem{Fmt.substr(0, BO2)},
129 Fmt.substr(BO2));
130
131 StringRef Spec = Fmt.slice(BO + 1, BC);
132 StringRef Right = Fmt.substr(BC + 1);
133
134 auto RI = parseReplacementItem(Spec);
135 if (RI.hasValue())
136 return std::make_pair(*RI, Right);
137
138 // If there was an error parsing the replacement item, treat it as an
139 // invalid replacement spec, and just continue.
140 From = BC + 1;
141 }
142 return std::make_pair(ReplacementItem{Fmt}, StringRef());
143 }
144
145 std::vector
146 formatv_object_base::parseFormatString(StringRef Fmt) {
147 std::vector Replacements;
148 ReplacementItem I;
149 while (!Fmt.empty()) {
150 std::tie(I, Fmt) = splitLiteralAndReplacement(Fmt);
151 if (I.Type != ReplacementType::Empty)
152 Replacements.push_back(I);
153 }
154 return Replacements;
155 }
4646 }
4747
4848 template
49 static void write_unsigned_impl(raw_ostream &S, T N, IntegerStyle Style,
50 bool IsNegative) {
49 static void write_unsigned_impl(raw_ostream &S, T N, size_t MinDigits,
50 IntegerStyle Style, bool IsNegative) {
5151 static_assert(std::is_unsigned::value, "Value is not unsigned!");
5252
5353 char NumberBuffer[128];
5858
5959 if (IsNegative)
6060 S << '-';
61
62 if (Len < MinDigits && Style != IntegerStyle::Number) {
63 for (size_t I = Len; I < MinDigits; ++I)
64 S << '0';
65 }
66
6167 if (Style == IntegerStyle::Number) {
6268 writeWithCommas(S, ArrayRef(std::end(NumberBuffer) - Len, Len));
6369 } else {
6672 }
6773
6874 template
69 static void write_unsigned(raw_ostream &S, T N, IntegerStyle Style,
70 bool IsNegative = false) {
75 static void write_unsigned(raw_ostream &S, T N, size_t MinDigits,
76 IntegerStyle Style, bool IsNegative = false) {
7177 // Output using 32-bit div/mod if possible.
7278 if (N == static_cast(N))
73 write_unsigned_impl(S, static_cast(N), Style, IsNegative);
79 write_unsigned_impl(S, static_cast(N), MinDigits, Style,
80 IsNegative);
7481 else
75 write_unsigned_impl(S, N, Style, IsNegative);
82 write_unsigned_impl(S, N, MinDigits, Style, IsNegative);
7683 }
7784
7885 template
79 static void write_signed(raw_ostream &S, T N, IntegerStyle Style) {
86 static void write_signed(raw_ostream &S, T N, size_t MinDigits,
87 IntegerStyle Style) {
8088 static_assert(std::is_signed::value, "Value is not signed!");
8189
8290 using UnsignedT = typename std::make_unsigned::type;
8391
8492 if (N >= 0) {
85 write_unsigned(S, static_cast(N), Style);
93 write_unsigned(S, static_cast(N), MinDigits, Style);
8694 return;
8795 }
8896
8997 UnsignedT UN = -(UnsignedT)N;
90 write_unsigned(S, UN, Style, true);
91 }
92
93 void llvm::write_integer(raw_ostream &S, unsigned int N, IntegerStyle Style) {
94 write_unsigned(S, N, Style);
95 }
96
97 void llvm::write_integer(raw_ostream &S, int N, IntegerStyle Style) {
98 write_signed(S, N, Style);
99 }
100
101 void llvm::write_integer(raw_ostream &S, unsigned long N, IntegerStyle Style) {
102 write_unsigned(S, N, Style);
103 }
104
105 void llvm::write_integer(raw_ostream &S, long N, IntegerStyle Style) {
106 write_signed(S, N, Style);
107 }
108
109 void llvm::write_integer(raw_ostream &S, unsigned long long N,
110 IntegerStyle Style) {
111 write_unsigned(S, N, Style);
112 }
113
114 void llvm::write_integer(raw_ostream &S, long long N, IntegerStyle Style) {
115 write_signed(S, N, Style);
98 write_unsigned(S, UN, MinDigits, Style, true);
99 }
100
101 void llvm::write_integer(raw_ostream &S, unsigned int N, size_t MinDigits,
102 IntegerStyle Style) {
103 write_unsigned(S, N, MinDigits, Style);
104 }
105
106 void llvm::write_integer(raw_ostream &S, int N, size_t MinDigits,
107 IntegerStyle Style) {
108 write_signed(S, N, MinDigits, Style);
109 }
110
111 void llvm::write_integer(raw_ostream &S, unsigned long N, size_t MinDigits,
112 IntegerStyle Style) {
113 write_unsigned(S, N, MinDigits, Style);
114 }
115
116 void llvm::write_integer(raw_ostream &S, long N, size_t MinDigits,
117 IntegerStyle Style) {
118 write_signed(S, N, MinDigits, Style);
119 }
120
121 void llvm::write_integer(raw_ostream &S, unsigned long long N, size_t MinDigits,
122 IntegerStyle Style) {
123 write_unsigned(S, N, MinDigits, Style);
124 }
125
126 void llvm::write_integer(raw_ostream &S, long long N, size_t MinDigits,
127 IntegerStyle Style) {
128 write_signed(S, N, MinDigits, Style);
116129 }
117130
118131 void llvm::write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style,
177190 #if defined(__MINGW32__)
178191 // FIXME: It should be generic to C++11.
179192 if (N == 0.0 && std::signbit(N)) {
180 const char *NegativeZero = "-0.000000e+00";
193 char NegativeZero[] = "-0.000000e+00";
194 if (Style == FloatStyle::ExponentUpper)
195 NegativeZero[strlen(NegativeZero) - 4] = 'E';
181196 S << NegativeZero;
182197 return;
183198 }
186201
187202 // negative zero
188203 if (fpcl == _FPCLASS_NZ) {
189 const char *NegativeZero = "-0.000000e+00";
204 char NegativeZero[] = "-0.000000e+00";
205 if (Style == FloatStyle::ExponentUpper)
206 NegativeZero[strlen(NegativeZero) - 4] = 'E';
190207 S << NegativeZero;
191208 return;
192209 }
230247 S << '%';
231248 }
232249
250 bool llvm::isPrefixedHexStyle(HexPrintStyle S) {
251 return (S == HexPrintStyle::PrefixLower || S == HexPrintStyle::PrefixUpper);
252 }
253
233254 size_t llvm::getDefaultPrecision(FloatStyle Style) {
234255 switch (Style) {
235256 case FloatStyle::Exponent:
1919 #include "llvm/Support/ErrorHandling.h"
2020 #include "llvm/Support/FileSystem.h"
2121 #include "llvm/Support/Format.h"
22 #include "llvm/Support/FormatVariadic.h"
2223 #include "llvm/Support/MathExtras.h"
2324 #include "llvm/Support/NativeFormatting.h"
2425 #include "llvm/Support/Process.h"
113114 }
114115
115116 raw_ostream &raw_ostream::operator<<(unsigned long N) {
116 write_integer(*this, static_cast(N), IntegerStyle::Integer);
117 write_integer(*this, static_cast(N), 0, IntegerStyle::Integer);
117118 return *this;
118119 }
119120
120121 raw_ostream &raw_ostream::operator<<(long N) {
121 write_integer(*this, static_cast(N), IntegerStyle::Integer);
122 write_integer(*this, static_cast(N), 0, IntegerStyle::Integer);
122123 return *this;
123124 }
124125
125126 raw_ostream &raw_ostream::operator<<(unsigned long long N) {
126 write_integer(*this, static_cast(N), IntegerStyle::Integer);
127 write_integer(*this, static_cast(N), 0, IntegerStyle::Integer);
127128 return *this;
128129 }
129130
130131 raw_ostream &raw_ostream::operator<<(long long N) {
131 write_integer(*this, static_cast(N), IntegerStyle::Integer);
132 write_integer(*this, static_cast(N), 0, IntegerStyle::Integer);
132133 return *this;
133134 }
134135
317318 }
318319 }
319320
321 raw_ostream &raw_ostream::operator<<(const formatv_object_base &Obj) {
322 SmallString<128> S;
323 Obj.format(*this);
324 return *this;
325 }
326
320327 raw_ostream &raw_ostream::operator<<(const FormattedString &FS) {
321328 unsigned Len = FS.Str.size();
322329 int PadAmount = FS.Width - Len;
343350 } else {
344351 llvm::SmallString<16> Buffer;
345352 llvm::raw_svector_ostream Stream(Buffer);
346 llvm::write_integer(Stream, FN.DecValue, IntegerStyle::Integer);
353 llvm::write_integer(Stream, FN.DecValue, 0, IntegerStyle::Integer);
347354 if (Buffer.size() < FN.Width)
348355 indent(FN.Width - Buffer.size());
349356 (*this) << Buffer;
1919 ErrorTest.cpp
2020 ErrorOrTest.cpp
2121 FileOutputBufferTest.cpp
22 FormatVariadicTest.cpp
2223 Host.cpp
2324 LEB128Test.cpp
2425 LineIteratorTest.cpp
0 //===- FormatVariadicTest.cpp - Unit tests for string formatting ----------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Support/FormatAdapters.h"
10 #include "llvm/Support/FormatVariadic.h"
11 #include "gtest/gtest.h"
12
13 using namespace llvm;
14
15 TEST(FormatVariadicTest, EmptyFormatString) {
16 auto Replacements = formatv_object_base::parseFormatString("");
17 EXPECT_EQ(0U, Replacements.size());
18 }
19
20 TEST(FormatVariadicTest, NoReplacements) {
21 const StringRef kFormatString = "This is a test";
22 auto Replacements = formatv_object_base::parseFormatString(kFormatString);
23 ASSERT_EQ(1U, Replacements.size());
24 EXPECT_EQ(kFormatString, Replacements[0].Spec);
25 EXPECT_EQ(ReplacementType::Literal, Replacements[0].Type);
26 }
27
28 TEST(FormatVariadicTest, EscapedBrace) {
29 // {{ should be replaced with {
30 auto Replacements = formatv_object_base::parseFormatString("{{");
31 ASSERT_EQ(1u, Replacements.size());
32 EXPECT_EQ("{", Replacements[0].Spec);
33 EXPECT_EQ(ReplacementType::Literal, Replacements[0].Type);
34
35 // An even number N of braces should be replaced with N/2 braces.
36 Replacements = formatv_object_base::parseFormatString("{{{{{{");
37 ASSERT_EQ(1u, Replacements.size());
38 EXPECT_EQ("{{{", Replacements[0].Spec);
39 EXPECT_EQ(ReplacementType::Literal, Replacements[0].Type);
40 }
41
42 TEST(FormatVariadicTest, ValidReplacementSequence) {
43 // 1. Simple replacement - parameter index only
44 auto Replacements = formatv_object_base::parseFormatString("{0}");
45 ASSERT_EQ(1u, Replacements.size());
46 EXPECT_EQ(ReplacementType::Format, Replacements[0].Type);
47 EXPECT_EQ(0u, Replacements[0].Index);
48 EXPECT_EQ(0u, Replacements[0].Align);
49 EXPECT_EQ("", Replacements[0].Options);
50
51 Replacements = formatv_object_base::parseFormatString("{1}");
52 ASSERT_EQ(1u, Replacements.size());
53 EXPECT_EQ(ReplacementType::Format, Replacements[0].Type);
54 EXPECT_EQ(1u, Replacements[0].Index);
55 EXPECT_EQ(0u, Replacements[0].Align);
56 EXPECT_EQ(AlignStyle::Right, Replacements[0].Where);
57 EXPECT_EQ("", Replacements[0].Options);
58
59 // 2. Parameter index with right alignment
60 Replacements = formatv_object_base::parseFormatString("{0,3}");
61 ASSERT_EQ(1u, Replacements.size());
62 EXPECT_EQ(ReplacementType::Format, Replacements[0].Type);
63 EXPECT_EQ(0u, Replacements[0].Index);
64 EXPECT_EQ(3u, Replacements[0].Align);
65 EXPECT_EQ(AlignStyle::Right, Replacements[0].Where);
66 EXPECT_EQ("", Replacements[0].Options);
67
68 // 3. And left alignment
69 Replacements = formatv_object_base::parseFormatString("{0,-3}");
70 ASSERT_EQ(1u, Replacements.size());
71 EXPECT_EQ(ReplacementType::Format, Replacements[0].Type);
72 EXPECT_EQ(0u, Replacements[0].Index);
73 EXPECT_EQ(3u, Replacements[0].Align);
74 EXPECT_EQ(AlignStyle::Left, Replacements[0].Where);
75 EXPECT_EQ("", Replacements[0].Options);
76
77 // 4. And center alignment
78 Replacements = formatv_object_base::parseFormatString("{0,=3}");
79 ASSERT_EQ(1u, Replacements.size());
80 EXPECT_EQ(ReplacementType::Format, Replacements[0].Type);
81 EXPECT_EQ(0u, Replacements[0].Index);
82 EXPECT_EQ(3u, Replacements[0].Align);
83 EXPECT_EQ(AlignStyle::Center, Replacements[0].Where);
84 EXPECT_EQ("", Replacements[0].Options);
85
86 // 4. Parameter index with option string
87 Replacements = formatv_object_base::parseFormatString("{0:foo}");
88 ASSERT_EQ(1u, Replacements.size());
89 EXPECT_EQ(ReplacementType::Format, Replacements[0].Type);
90 EXPECT_EQ(0u, Replacements[0].Index);
91 EXPECT_EQ(0u, Replacements[0].Align);
92 EXPECT_EQ(AlignStyle::Right, Replacements[0].Where);
93 EXPECT_EQ("foo", Replacements[0].Options);
94
95 // 5. Parameter index with alignment before option string
96 Replacements = formatv_object_base::parseFormatString("{0,-3:foo}");
97 ASSERT_EQ(1u, Replacements.size());
98 EXPECT_EQ(ReplacementType::Format, Replacements[0].Type);
99 EXPECT_EQ(0u, Replacements[0].Index);
100 EXPECT_EQ(3u, Replacements[0].Align);
101 EXPECT_EQ(AlignStyle::Left, Replacements[0].Where);
102 EXPECT_EQ("foo", Replacements[0].Options);
103
104 // 7. Parameter indices, options, and alignment can all have whitespace.
105 Replacements = formatv_object_base::parseFormatString("{ 0, -3 : foo }");
106 ASSERT_EQ(1u, Replacements.size());
107 EXPECT_EQ(ReplacementType::Format, Replacements[0].Type);
108 EXPECT_EQ(0u, Replacements[0].Index);
109 EXPECT_EQ(3u, Replacements[0].Align);
110 EXPECT_EQ(AlignStyle::Left, Replacements[0].Where);
111 EXPECT_EQ("foo", Replacements[0].Options);
112
113 // 8. Everything after the first option specifier is part of the style, even
114 // if it contains another option specifier.
115 Replacements = formatv_object_base::parseFormatString("{0:0:1}");
116 ASSERT_EQ(1u, Replacements.size());
117 EXPECT_EQ("0:0:1", Replacements[0].Spec);
118 EXPECT_EQ(ReplacementType::Format, Replacements[0].Type);
119 EXPECT_EQ(0u, Replacements[0].Index);
120 EXPECT_EQ(0u, Replacements[0].Align);
121 EXPECT_EQ(AlignStyle::Right, Replacements[0].Where);
122 EXPECT_EQ("0:1", Replacements[0].Options);
123 }
124
125 TEST(FormatVariadicTest, DefaultReplacementValues) {
126 // 2. If options string is missing, it defaults to empty.
127 auto Replacements = formatv_object_base::parseFormatString("{0,3}");
128 ASSERT_EQ(1u, Replacements.size());
129 EXPECT_EQ(ReplacementType::Format, Replacements[0].Type);
130 EXPECT_EQ(0u, Replacements[0].Index);
131 EXPECT_EQ(3u, Replacements[0].Align);
132 EXPECT_EQ("", Replacements[0].Options);
133
134 // Including if the colon is present but contains no text.
135 Replacements = formatv_object_base::parseFormatString("{0,3:}");
136 ASSERT_EQ(1u, Replacements.size());
137 EXPECT_EQ(ReplacementType::Format, Replacements[0].Type);
138 EXPECT_EQ(0u, Replacements[0].Index);
139 EXPECT_EQ(3u, Replacements[0].Align);
140 EXPECT_EQ("", Replacements[0].Options);
141
142 // 3. If alignment is missing, it defaults to 0, right, space
143 Replacements = formatv_object_base::parseFormatString("{0:foo}");
144 ASSERT_EQ(1u, Replacements.size());
145 EXPECT_EQ(ReplacementType::Format, Replacements[0].Type);
146 EXPECT_EQ(AlignStyle::Right, Replacements[0].Where);
147 EXPECT_EQ(' ', Replacements[0].Pad);
148 EXPECT_EQ(0u, Replacements[0].Index);
149 EXPECT_EQ(0u, Replacements[0].Align);
150 EXPECT_EQ("foo", Replacements[0].Options);
151 }
152
153 TEST(FormatVariadicTest, MultipleReplacements) {
154 auto Replacements =
155 formatv_object_base::parseFormatString("{0} {1:foo}-{2,-3:bar}");
156 ASSERT_EQ(5u, Replacements.size());
157 // {0}
158 EXPECT_EQ(ReplacementType::Format, Replacements[0].Type);
159 EXPECT_EQ(0u, Replacements[0].Index);
160 EXPECT_EQ(0u, Replacements[0].Align);
161 EXPECT_EQ(AlignStyle::Right, Replacements[0].Where);
162 EXPECT_EQ("", Replacements[0].Options);
163
164 // " "
165 EXPECT_EQ(ReplacementType::Literal, Replacements[1].Type);
166 EXPECT_EQ(" ", Replacements[1].Spec);
167
168 // {1:foo} - Options=foo
169 EXPECT_EQ(ReplacementType::Format, Replacements[2].Type);
170 EXPECT_EQ(1u, Replacements[2].Index);
171 EXPECT_EQ(0u, Replacements[2].Align);
172 EXPECT_EQ(AlignStyle::Right, Replacements[2].Where);
173 EXPECT_EQ("foo", Replacements[2].Options);
174
175 // "-"
176 EXPECT_EQ(ReplacementType::Literal, Replacements[3].Type);
177 EXPECT_EQ("-", Replacements[3].Spec);
178
179 // {2:bar,-3} - Options=bar, Align=-3
180 EXPECT_EQ(ReplacementType::Format, Replacements[4].Type);
181 EXPECT_EQ(2u, Replacements[4].Index);
182 EXPECT_EQ(3u, Replacements[4].Align);
183 EXPECT_EQ(AlignStyle::Left, Replacements[4].Where);
184 EXPECT_EQ("bar", Replacements[4].Options);
185 }
186
187 TEST(FormatVariadicTest, FormatNoReplacements) {
188 EXPECT_EQ("", formatv("").str());
189 EXPECT_EQ("Test", formatv("Test").str());
190 }
191
192 TEST(FormatVariadicTest, FormatBasicTypesOneReplacement) {
193 EXPECT_EQ("1", formatv("{0}", 1).str());
194 EXPECT_EQ("c", formatv("{0}", 'c').str());
195 EXPECT_EQ("-3", formatv("{0}", -3).str());
196 EXPECT_EQ("Test", formatv("{0}", "Test").str());
197 EXPECT_EQ("Test2", formatv("{0}", StringRef("Test2")).str());
198 EXPECT_EQ("Test3", formatv("{0}", std::string("Test3")).str());
199 }
200
201 TEST(FormatVariadicTest, IntegralHexFormatting) {
202 // 1. Trivial cases. Make sure hex is not the default.
203 EXPECT_EQ("0", formatv("{0}", 0).str());
204 EXPECT_EQ("2748", formatv("{0}", 0xABC).str());
205 EXPECT_EQ("-2748", formatv("{0}", -0xABC).str());
206
207 // 3. various hex prefixes.
208 EXPECT_EQ("0xFF", formatv("{0:X}", 255).str());
209 EXPECT_EQ("0xFF", formatv("{0:X+}", 255).str());
210 EXPECT_EQ("0xff", formatv("{0:x}", 255).str());
211 EXPECT_EQ("0xff", formatv("{0:x+}", 255).str());
212 EXPECT_EQ("FF", formatv("{0:X-}", 255).str());
213 EXPECT_EQ("ff", formatv("{0:x-}", 255).str());
214
215 // 5. Precision pads left of the most significant digit but right of the
216 // prefix (if one exists).
217 EXPECT_EQ("0xFF", formatv("{0:X2}", 255).str());
218 EXPECT_EQ("0xFF", formatv("{0:X+2}", 255).str());
219 EXPECT_EQ("0x0ff", formatv("{0:x3}", 255).str());
220 EXPECT_EQ("0x0ff", formatv("{0:x+3}", 255).str());
221 EXPECT_EQ("00FF", formatv("{0:X-4}", 255).str());
222 EXPECT_EQ("00ff", formatv("{0:x-4}", 255).str());
223
224 // 6. Try some larger types.
225 EXPECT_EQ("0xDEADBEEFDEADBEEF",
226 formatv("{0:X16}", -2401053088876216593LL).str());
227 EXPECT_EQ("0xFEEBDAEDFEEBDAED",
228 formatv("{0:X16}", 0xFEEBDAEDFEEBDAEDULL).str());
229 EXPECT_EQ("0x00000000DEADBEEF", formatv("{0:X16}", 0xDEADBEEF).str());
230
231 // 7. Padding should take into account the prefix
232 EXPECT_EQ("0xff", formatv("{0,4:x}", 255).str());
233 EXPECT_EQ(" 0xff", formatv("{0,5:x+}", 255).str());
234 EXPECT_EQ(" FF", formatv("{0,4:X-}", 255).str());
235 EXPECT_EQ(" ff", formatv("{0,5:x-}", 255).str());
236
237 // 8. Including when it's been zero-padded
238 EXPECT_EQ(" 0x0ff", formatv("{0,7:x3}", 255).str());
239 EXPECT_EQ(" 0x00ff", formatv("{0,7:x+4}", 255).str());
240 EXPECT_EQ(" 000FF", formatv("{0,7:X-5}", 255).str());
241 EXPECT_EQ(" 0000ff", formatv("{0,7:x-6}", 255).str());
242
243 // 9. Precision with default format specifier should work too
244 EXPECT_EQ(" 255", formatv("{0,7:3}", 255).str());
245 EXPECT_EQ(" 0255", formatv("{0,7:4}", 255).str());
246 EXPECT_EQ(" 00255", formatv("{0,7:5}", 255).str());
247 EXPECT_EQ(" 000255", formatv("{0,7:6}", 255).str());
248 }
249
250 TEST(FormatVariadicTest, PointerFormatting) {
251 // 1. Trivial cases. Hex is default. Default Precision is pointer width.
252 if (sizeof(void *) == 4) {
253 EXPECT_EQ("0x00000000", formatv("{0}", (void *)0).str());
254 EXPECT_EQ("0x00000ABC", formatv("{0}", (void *)0xABC).str());
255 } else {
256 EXPECT_EQ("0x0000000000000000", formatv("{0}", (void *)0).str());
257 EXPECT_EQ("0x0000000000000ABC", formatv("{0}", (void *)0xABC).str());
258 }
259
260 // 2. But we can reduce the precision explicitly.
261 EXPECT_EQ("0x0", formatv("{0:0}", (void *)0).str());
262 EXPECT_EQ("0xABC", formatv("{0:0}", (void *)0xABC).str());
263 EXPECT_EQ("0x0000", formatv("{0:4}", (void *)0).str());
264 EXPECT_EQ("0x0ABC", formatv("{0:4}", (void *)0xABC).str());
265
266 // 3. various hex prefixes.
267 EXPECT_EQ("0x0ABC", formatv("{0:X4}", (void *)0xABC).str());
268 EXPECT_EQ("0x0abc", formatv("{0:x4}", (void *)0xABC).str());
269 EXPECT_EQ("0ABC", formatv("{0:X-4}", (void *)0xABC).str());
270 EXPECT_EQ("0abc", formatv("{0:x-4}", (void *)0xABC).str());
271 }
272
273 TEST(FormatVariadicTest, IntegralNumberFormatting) {
274 // 1. Test comma grouping with default widths and precisions.
275 EXPECT_EQ("0", formatv("{0:N}", 0).str());
276 EXPECT_EQ("10", formatv("{0:N}", 10).str());
277 EXPECT_EQ("100", formatv("{0:N}", 100).str());
278 EXPECT_EQ("1,000", formatv("{0:N}", 1000).str());
279 EXPECT_EQ("1,234,567,890", formatv("{0:N}", 1234567890).str());
280 EXPECT_EQ("-10", formatv("{0:N}", -10).str());
281 EXPECT_EQ("-100", formatv("{0:N}", -100).str());
282 EXPECT_EQ("-1,000", formatv("{0:N}", -1000).str());
283 EXPECT_EQ("-1,234,567,890", formatv("{0:N}", -1234567890).str());
284
285 // 2. If there is no comma, width and precision pad to the same absolute
286 // size.
287 EXPECT_EQ(" 1", formatv("{0,2:N}", 1).str());
288
289 // 3. But if there is a comma or negative sign, width factors them in but
290 // precision doesn't.
291 EXPECT_EQ(" 1,000", formatv("{0,6:N}", 1000).str());
292 EXPECT_EQ(" -1,000", formatv("{0,7:N}", -1000).str());
293
294 // 4. Large widths all line up.
295 EXPECT_EQ(" 1,000", formatv("{0,11:N}", 1000).str());
296 EXPECT_EQ(" -1,000", formatv("{0,11:N}", -1000).str());
297 EXPECT_EQ(" -100,000", formatv("{0,11:N}", -100000).str());
298 }
299
300 TEST(FormatVariadicTest, StringFormatting) {
301 const char FooArray[] = "FooArray";
302 const char *FooPtr = "FooPtr";
303 llvm::StringRef FooRef("FooRef");
304 std::string FooString("FooString");
305 // 1. Test that we can print various types of strings.
306 EXPECT_EQ(FooArray, formatv("{0}", FooArray).str());
307 EXPECT_EQ(FooPtr, formatv("{0}", FooPtr).str());
308 EXPECT_EQ(FooRef, formatv("{0}", FooRef).str());
309 EXPECT_EQ(FooString, formatv("{0}", FooString).str());
310
311 // 2. Test that the precision specifier prints the correct number of
312 // characters.
313 EXPECT_EQ("FooA", formatv("{0:4}", FooArray).str());
314 EXPECT_EQ("FooP", formatv("{0:4}", FooPtr).str());
315 EXPECT_EQ("FooR", formatv("{0:4}", FooRef).str());
316 EXPECT_EQ("FooS", formatv("{0:4}", FooString).str());
317
318 // 3. And that padding works.
319 EXPECT_EQ(" FooA", formatv("{0,6:4}", FooArray).str());
320 EXPECT_EQ(" FooP", formatv("{0,6:4}", FooPtr).str());
321 EXPECT_EQ(" FooR", formatv("{0,6:4}", FooRef).str());
322 EXPECT_EQ(" FooS", formatv("{0,6:4}", FooString).str());
323 }
324
325 TEST(FormatVariadicTest, CharFormatting) {
326 // 1. Not much to see here. Just print a char with and without padding.
327 EXPECT_EQ("C", formatv("{0}", 'C').str());
328 EXPECT_EQ(" C", formatv("{0,3}", 'C').str());
329
330 // 2. char is really an integral type though, where the only difference is
331 // that the "default" is to print the ASCII. So if a non-default presentation
332 // specifier exists, it should print as an integer.
333 EXPECT_EQ("37", formatv("{0:D}", (char)37).str());
334 EXPECT_EQ(" 037", formatv("{0,5:D3}", (char)37).str());
335 }
336
337 TEST(FormatVariadicTest, BoolTest) {
338 // 1. Default style is lowercase text (same as 't')
339 EXPECT_EQ("true", formatv("{0}", true).str());
340 EXPECT_EQ("false", formatv("{0}", false).str());
341 EXPECT_EQ("true", formatv("{0:t}", true).str());
342 EXPECT_EQ("false", formatv("{0:t}", false).str());
343
344 // 2. T - uppercase text
345 EXPECT_EQ("TRUE", formatv("{0:T}", true).str());
346 EXPECT_EQ("FALSE", formatv("{0:T}", false).str());
347
348 // 3. D / d - integral
349 EXPECT_EQ("1", formatv("{0:D}", true).str());
350 EXPECT_EQ("0", formatv("{0:D}", false).str());
351 EXPECT_EQ("1", formatv("{0:d}", true).str());
352 EXPECT_EQ("0", formatv("{0:d}", false).str());
353
354 // 4. Y - uppercase yes/no
355 EXPECT_EQ("YES", formatv("{0:Y}", true).str());
356 EXPECT_EQ("NO", formatv("{0:Y}", false).str());
357
358 // 5. y - lowercase yes/no
359 EXPECT_EQ("yes", formatv("{0:y}", true).str());
360 EXPECT_EQ("no", formatv("{0:y}", false).str());
361 }
362
363 TEST(FormatVariadicTest, DoubleFormatting) {
364 // Test exponents, fixed point, and percent formatting.
365
366 // 1. Signed, unsigned, and zero exponent format.
367 EXPECT_EQ("0.000000E+00", formatv("{0:E}", 0.0).str());
368 EXPECT_EQ("-0.000000E+00", formatv("{0:E}", -0.0).str());
369 EXPECT_EQ("1.100000E+00", formatv("{0:E}", 1.1).str());
370 EXPECT_EQ("-1.100000E+00", formatv("{0:E}", -1.1).str());
371 EXPECT_EQ("1.234568E+03", formatv("{0:E}", 1234.5678).str());
372 EXPECT_EQ("-1.234568E+03", formatv("{0:E}", -1234.5678).str());
373 EXPECT_EQ("1.234568E-03", formatv("{0:E}", .0012345678).str());
374 EXPECT_EQ("-1.234568E-03", formatv("{0:E}", -.0012345678).str());
375
376 // 2. With padding and precision.
377 EXPECT_EQ(" 0.000E+00", formatv("{0,11:E3}", 0.0).str());
378 EXPECT_EQ(" -1.100E+00", formatv("{0,11:E3}", -1.1).str());
379 EXPECT_EQ(" 1.235E+03", formatv("{0,11:E3}", 1234.5678).str());
380 EXPECT_EQ(" -1.235E-03", formatv("{0,11:E3}", -.0012345678).str());
381
382 // 3. Signed, unsigned, and zero fixed point format.
383 EXPECT_EQ("0.00", formatv("{0:F}", 0.0).str());
384 EXPECT_EQ("-0.00", formatv("{0:F}", -0.0).str());
385 EXPECT_EQ("1.10", formatv("{0:F}", 1.1).str());
386 EXPECT_EQ("-1.10", formatv("{0:F}", -1.1).str());
387 EXPECT_EQ("1234.57", formatv("{0:F}", 1234.5678).str());
388 EXPECT_EQ("-1234.57", formatv("{0:F}", -1234.5678).str());
389 EXPECT_EQ("0.00", formatv("{0:F}", .0012345678).str());
390 EXPECT_EQ("-0.00", formatv("{0:F}", -.0012345678).str());
391
392 // 2. With padding and precision.
393 EXPECT_EQ(" 0.000", formatv("{0,8:F3}", 0.0).str());
394 EXPECT_EQ(" -1.100", formatv("{0,8:F3}", -1.1).str());
395 EXPECT_EQ("1234.568", formatv("{0,8:F3}", 1234.5678).str());
396 EXPECT_EQ(" -0.001", formatv("{0,8:F3}", -.0012345678).str());
397 }
398
399 struct format_tuple {
400 const char *Fmt;
401 explicit format_tuple(const char *Fmt) : Fmt(Fmt) {}
402
403 template
404 auto operator()(Ts &&... Values) const
405 -> decltype(formatv(Fmt, std::forward(Values)...)) {
406 return formatv(Fmt, std::forward(Values)...);
407 }
408 };
409
410 TEST(FormatVariadicTest, BigTest) {
411 using Tuple =
412 std::tuple
413 void *, int, double, int64_t, uint64_t, double, uint8_t>;
414 Tuple Ts[] = {
415 Tuple('a', 1, "Str", StringRef(), std::string(), 3.14159, -.17532f,
416 (void *)nullptr, 123456, 6.02E23, -908234908423, 908234908422234,
417 std::numeric_limits::quiet_NaN(), 0xAB),
418 Tuple('x', 0xDDB5B, "LongerStr", "StringRef", "std::string", -2.7,
419 .08215f, (void *)nullptr, 0, 6.62E-34, -908234908423,
420 908234908422234, std::numeric_limits::infinity(), 0x0)};
421 // Test long string formatting with many edge cases combined.
422 const char *Intro =
423 "There are {{{0}} items in the tuple, and {{{1}} tuple(s) in the array.";
424 const char *Header =
425 "{0,6}|{1,8}|{2,=10}|{3,=10}|{4,=13}|{5,7}|{6,7}|{7,10}|{8,"
426 "-7}|{9,10}|{10,16}|{11,17}|{12,6}|{13,4}";
427 const char *Line =
428 "{0,6}|{1,8:X}|{2,=10}|{3,=10:5}|{4,=13}|{5,7:3}|{6,7:P2}|{7,"
429 "10:X8}|{8,-7:N}|{9,10:E4}|{10,16:N}|{11,17:D}|{12,6}|{13,"
430 "4:X}";
431
432 std::string S;
433 llvm::raw_string_ostream Stream(S);
434 Stream << formatv(Intro, std::tuple_size::value,
435 llvm::array_lengthof(Ts))
436 << "\n";
437 Stream << formatv(Header, "Char", "HexInt", "Str", "Ref", "std::str",
438 "double", "float", "pointer", "comma", "exp", "bigint",
439 "bigint2", "limit", "byte")
440 << "\n";
441 for (auto &Item : Ts) {
442 Stream << llvm::apply_tuple(format_tuple(Line), Item) << "\n";
443 }
444 Stream.flush();
445 const char *Expected =
446 R"foo(There are {14} items in the tuple, and {2} tuple(s) in the array.
447 Char| HexInt| Str | Ref | std::str | double| float| pointer|comma | exp| bigint| bigint2| limit|byte
448 a| 0x1| Str | | | 3.142|-17.53%|0x00000000|123,456|6.0200E+23|-908,234,908,423| 908234908422234| nan|0xAB
449 x| 0xDDB5B|LongerStr | Strin | std::string | -2.700| 8.21%|0x00000000|0 |6.6200E-34|-908,234,908,423| 908234908422234| INF| 0x0
450 )foo";
451
452 EXPECT_EQ(Expected, S);
453 }
454
455 TEST(FormatVariadicTest, Range) {
456 std::vector IntRange = {1, 1, 2, 3, 5, 8, 13};
457
458 // 1. Simple range with default separator and element style.
459 EXPECT_EQ("1, 1, 2, 3, 5, 8, 13",
460 formatv("{0}", make_range(IntRange.begin(), IntRange.end())).str());
461 EXPECT_EQ("1, 2, 3, 5, 8",
462 formatv("{0}", make_range(IntRange.begin() + 1, IntRange.end() - 1))
463 .str());
464
465 // 2. Non-default separator
466 EXPECT_EQ(
467 "1/1/2/3/5/8/13",
468 formatv("{0:$[/]}", make_range(IntRange.begin(), IntRange.end())).str());
469
470 // 3. Default separator, non-default element style.
471 EXPECT_EQ(
472 "0x1, 0x1, 0x2, 0x3, 0x5, 0x8, 0xd",
473 formatv("{0:@[x]}", make_range(IntRange.begin(), IntRange.end())).str());
474
475 // 4. Non-default separator and element style.
476 EXPECT_EQ(
477 "0x1 + 0x1 + 0x2 + 0x3 + 0x5 + 0x8 + 0xd",
478 formatv("{0:$[ + ]@[x]}", make_range(IntRange.begin(), IntRange.end()))
479 .str());
480
481 // 5. Element style and/or separator using alternate delimeters to allow using
482 // delimeter characters as part of the separator.
483 EXPECT_EQ(
484 "<0x1><0x1><0x2><0x3><0x5><0x8><0xd>",
485 formatv("<{0:$[><]@(x)}>", make_range(IntRange.begin(), IntRange.end()))
486 .str());
487 EXPECT_EQ(
488 "[0x1][0x1][0x2][0x3][0x5][0x8][0xd]",
489 formatv("[{0:$(][)@[x]}]", make_range(IntRange.begin(), IntRange.end()))
490 .str());
491 EXPECT_EQ(
492 "(0x1)(0x1)(0x2)(0x3)(0x5)(0x8)(0xd)",
493 formatv("({0:$<)(>@})", make_range(IntRange.begin(), IntRange.end()))
494 .str());
495
496 // 5. Empty range.
497 EXPECT_EQ("", formatv("{0:$[+]@[x]}",
498 make_range(IntRange.begin(), IntRange.begin()))
499 .str());
500
501 // 6. Empty separator and style.
502 EXPECT_EQ("11235813",
503 formatv("{0:$[]@<>}", make_range(IntRange.begin(), IntRange.end()))
504 .str());
505 }
506
507 TEST(FormatVariadicTest, Adapter) {
508 class Negative {
509 int N;
510
511 public:
512 explicit Negative(int N) : N(N) {}
513 void format(raw_ostream &S, StringRef Options) { S << -N; }
514 };
515
516 EXPECT_EQ("-7", formatv("{0}", Negative(7)).str());
517
518 int N = 171;
519
520 EXPECT_EQ(" 171 ",
521 formatv("{0}", fmt_align(N, AlignStyle::Center, 7)).str());
522 EXPECT_EQ(" 171 ", formatv("{0}", fmt_pad(N, 1, 3)).str());
523 EXPECT_EQ("171171171171171", formatv("{0}", fmt_repeat(N, 5)).str());
524
525 EXPECT_EQ(" ABABABABAB ",
526 formatv("{0:X-}", fmt_pad(fmt_repeat(N, 5), 1, 3)).str());
527 EXPECT_EQ(" AB AB AB AB AB ",
528 formatv("{0,=34:X-}", fmt_repeat(fmt_pad(N, 1, 3), 5)).str());
529 }
530
531 TEST(FormatVariadicTest, ImplicitConversions) {
532 std::string S = formatv("{0} {1}", 1, 2);
533 EXPECT_EQ("1 2", S);
534
535 SmallString<4> S2 = formatv("{0} {1}", 1, 2);
536 EXPECT_EQ("1 2", S2);
537 }
2020 template std::string format_number(T N, IntegerStyle Style) {
2121 std::string S;
2222 llvm::raw_string_ostream Str(S);
23 write_integer(Str, N, Style);
23 write_integer(Str, N, 0, Style);
2424 Str.flush();
2525 return S;
2626 }