//===- FormatProviders.h - Formatters for common LLVM types -----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements format providers for many common LLVM types, for example // allowing precision and width specifiers for scalar and string types. // //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_FORMATPROVIDERS_H #define LLVM_SUPPORT_FORMATPROVIDERS_H #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/FormatVariadicDetails.h" #include "llvm/Support/NativeFormatting.h" #include <array> #include <optional> #include <type_traits> namespace llvm { namespace support { namespace detail { template <typename T> struct use_integral_formatter : public std::integral_constant< bool, is_one_of<T, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, int, unsigned, long, unsigned long, long long, unsigned long long>::value> { … }; template <typename T> struct use_char_formatter : public std::integral_constant<bool, std::is_same_v<T, char>> { … }; template <typename T> struct is_cstring : public std::integral_constant<bool, is_one_of<T, char *, const char *>::value> { … }; template <typename T> struct use_string_formatter : public std::integral_constant<bool, std::is_convertible_v<T, llvm::StringRef>> { … }; template <typename T> struct use_pointer_formatter : public std::integral_constant<bool, std::is_pointer_v<T> && !is_cstring<T>::value> { … }; template <typename T> struct use_double_formatter : public std::integral_constant<bool, std::is_floating_point_v<T>> { … }; class HelperFunctions { … }; } // namespace detail } // namespace support /// Implementation of format_provider<T> for integral arithmetic types. /// /// The options string of an integral type has the grammar: /// /// integer_options :: [style][digits] /// style :: <see table below> /// digits :: <non-negative integer> 0-99 /// /// ========================================================================== /// | style | Meaning | Example | Digits Meaning | /// -------------------------------------------------------------------------- /// | | | Input | Output | | /// ========================================================================== /// | x- | Hex no prefix, lower | 42 | 2a | Minimum # digits | /// | X- | Hex no prefix, upper | 42 | 2A | Minimum # digits | /// | x+ / x | Hex + prefix, lower | 42 | 0x2a | Minimum # digits | /// | X+ / X | Hex + prefix, upper | 42 | 0x2A | Minimum # digits | /// | N / n | Digit grouped number | 123456 | 123,456 | Ignored | /// | D / d | Integer | 100000 | 100000 | Ignored | /// | (empty) | Same as D / d | | | | /// ========================================================================== /// format_provider<T, std::enable_if_t<support::detail::use_integral_formatter<T>::value>>; /// Implementation of format_provider<T> for integral pointer types. /// /// The options string of a pointer type has the grammar: /// /// pointer_options :: [style][precision] /// style :: <see table below> /// digits :: <non-negative integer> 0-sizeof(void*) /// /// ========================================================================== /// | S | Meaning | Example | /// -------------------------------------------------------------------------- /// | | | Input | Output | /// ========================================================================== /// | x- | Hex no prefix, lower | 0xDEADBEEF | deadbeef | /// | X- | Hex no prefix, upper | 0xDEADBEEF | DEADBEEF | /// | x+ / x | Hex + prefix, lower | 0xDEADBEEF | 0xdeadbeef | /// | X+ / X | Hex + prefix, upper | 0xDEADBEEF | 0xDEADBEEF | /// | (empty) | Same as X+ / X | | | /// ========================================================================== /// /// The default precision is the number of nibbles in a machine word, and in all /// cases indicates the minimum number of nibbles to print. format_provider<T, std::enable_if_t<support::detail::use_pointer_formatter<T>::value>>; /// Implementation of format_provider<T> for c-style strings and string /// objects such as std::string and llvm::StringRef. /// /// The options string of a string type has the grammar: /// /// string_options :: [length] /// /// where `length` is an optional integer specifying the maximum number of /// characters in the string to print. If `length` is omitted, the string is /// printed up to the null terminator. format_provider<T, std::enable_if_t<support::detail::use_string_formatter<T>::value>>; /// Implementation of format_provider<T> for llvm::Twine. /// /// This follows the same rules as the string formatter. template <> struct format_provider<Twine> { … }; /// Implementation of format_provider<T> for characters. /// /// The options string of a character type has the grammar: /// /// char_options :: (empty) | [integer_options] /// /// If `char_options` is empty, the character is displayed as an ASCII /// character. Otherwise, it is treated as an integer options string. /// format_provider<T, std::enable_if_t<support::detail::use_char_formatter<T>::value>>; /// Implementation of format_provider<T> for type `bool` /// /// The options string of a boolean type has the grammar: /// /// bool_options :: "" | "Y" | "y" | "D" | "d" | "T" | "t" /// /// ================================== /// | C | Meaning | /// ================================== /// | Y | YES / NO | /// | y | yes / no | /// | D / d | Integer 0 or 1 | /// | T | TRUE / FALSE | /// | t | true / false | /// | (empty) | Equivalent to 't' | /// ================================== template <> struct format_provider<bool> { … }; /// Implementation of format_provider<T> for floating point types. /// /// The options string of a floating point type has the format: /// /// float_options :: [style][precision] /// style :: <see table below> /// precision :: <non-negative integer> 0-99 /// /// ===================================================== /// | style | Meaning | Example | /// ----------------------------------------------------- /// | | | Input | Output | /// ===================================================== /// | P / p | Percentage | 0.05 | 5.00% | /// | F / f | Fixed point | 1.0 | 1.00 | /// | E | Exponential with E | 100000 | 1.0E+05 | /// | e | Exponential with e | 100000 | 1.0e+05 | /// | (empty) | Same as F / f | | | /// ===================================================== /// /// The default precision is 6 for exponential (E / e) and 2 for everything /// else. format_provider<T, std::enable_if_t<support::detail::use_double_formatter<T>::value>>; namespace support { namespace detail { IterValue; template <typename IterT> struct range_item_has_provider : public std::integral_constant< bool, !support::detail::uses_missing_provider<IterValue<IterT>>::value> { … }; } // namespace detail } // namespace support /// Implementation of format_provider<T> for ranges. /// /// This will print an arbitrary range as a delimited sequence of items. /// /// The options string of a range type has the grammar: /// /// range_style ::= [separator] [element_style] /// separator ::= "$" delimeted_expr /// element_style ::= "@" delimeted_expr /// delimeted_expr ::= "[" expr "]" | "(" expr ")" | "<" expr ">" /// expr ::= <any string not containing delimeter> /// /// where the separator expression is the string to insert between consecutive /// items in the range and the argument expression is the Style specification to /// be used when formatting the underlying type. The default separator if /// unspecified is ' ' (space). The syntax of the argument expression follows /// whatever grammar is dictated by the format provider or format adapter used /// to format the value type. /// /// Note that attempting to format an `iterator_range<T>` where no format /// provider can be found for T will result in a compile error. /// format_provider<llvm::iterator_range<IterT>>; } // namespace llvm #endif