llvm/llvm/include/llvm/Support/FormatProviders.h

//===- 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