git repos / blockattack-game

blame: source/misc/embedded_libs/fmt-11.0.2/include/fmt/printf.h

normal view · raw

47fd5c32 Poul Sander 2024-10-05 08:44 1
// Formatting library for C++ - legacy printf implementation
47fd5c32 Poul Sander 2024-10-05 08:44 2
//
47fd5c32 Poul Sander 2024-10-05 08:44 3
// Copyright (c) 2012 - 2016, Victor Zverovich
47fd5c32 Poul Sander 2024-10-05 08:44 4
// All rights reserved.
47fd5c32 Poul Sander 2024-10-05 08:44 5
//
47fd5c32 Poul Sander 2024-10-05 08:44 6
// For the license information refer to format.h.
47fd5c32 Poul Sander 2024-10-05 08:44 7
47fd5c32 Poul Sander 2024-10-05 08:44 8
#ifndef FMT_PRINTF_H_
47fd5c32 Poul Sander 2024-10-05 08:44 9
#define FMT_PRINTF_H_
47fd5c32 Poul Sander 2024-10-05 08:44 10
47fd5c32 Poul Sander 2024-10-05 08:44 11
#ifndef FMT_MODULE
47fd5c32 Poul Sander 2024-10-05 08:44 12
#  include <algorithm>  // std::max
47fd5c32 Poul Sander 2024-10-05 08:44 13
#  include <limits>     // std::numeric_limits
47fd5c32 Poul Sander 2024-10-05 08:44 14
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 15
47fd5c32 Poul Sander 2024-10-05 08:44 16
#include "format.h"
47fd5c32 Poul Sander 2024-10-05 08:44 17
47fd5c32 Poul Sander 2024-10-05 08:44 18
FMT_BEGIN_NAMESPACE
47fd5c32 Poul Sander 2024-10-05 08:44 19
FMT_BEGIN_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 20
47fd5c32 Poul Sander 2024-10-05 08:44 21
template <typename T> struct printf_formatter {
47fd5c32 Poul Sander 2024-10-05 08:44 22
  printf_formatter() = delete;
47fd5c32 Poul Sander 2024-10-05 08:44 23
};
47fd5c32 Poul Sander 2024-10-05 08:44 24
47fd5c32 Poul Sander 2024-10-05 08:44 25
template <typename Char> class basic_printf_context {
47fd5c32 Poul Sander 2024-10-05 08:44 26
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 27
  basic_appender<Char> out_;
47fd5c32 Poul Sander 2024-10-05 08:44 28
  basic_format_args<basic_printf_context> args_;
47fd5c32 Poul Sander 2024-10-05 08:44 29
47fd5c32 Poul Sander 2024-10-05 08:44 30
  static_assert(std::is_same<Char, char>::value ||
47fd5c32 Poul Sander 2024-10-05 08:44 31
                    std::is_same<Char, wchar_t>::value,
47fd5c32 Poul Sander 2024-10-05 08:44 32
                "Unsupported code unit type.");
47fd5c32 Poul Sander 2024-10-05 08:44 33
47fd5c32 Poul Sander 2024-10-05 08:44 34
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 35
  using char_type = Char;
47fd5c32 Poul Sander 2024-10-05 08:44 36
  using parse_context_type = basic_format_parse_context<Char>;
47fd5c32 Poul Sander 2024-10-05 08:44 37
  template <typename T> using formatter_type = printf_formatter<T>;
47fd5c32 Poul Sander 2024-10-05 08:44 38
47fd5c32 Poul Sander 2024-10-05 08:44 39
  /// Constructs a `printf_context` object. References to the arguments are
47fd5c32 Poul Sander 2024-10-05 08:44 40
  /// stored in the context object so make sure they have appropriate lifetimes.
47fd5c32 Poul Sander 2024-10-05 08:44 41
  basic_printf_context(basic_appender<Char> out,
47fd5c32 Poul Sander 2024-10-05 08:44 42
                       basic_format_args<basic_printf_context> args)
47fd5c32 Poul Sander 2024-10-05 08:44 43
      : out_(out), args_(args) {}
47fd5c32 Poul Sander 2024-10-05 08:44 44
47fd5c32 Poul Sander 2024-10-05 08:44 45
  auto out() -> basic_appender<Char> { return out_; }
47fd5c32 Poul Sander 2024-10-05 08:44 46
  void advance_to(basic_appender<Char>) {}
47fd5c32 Poul Sander 2024-10-05 08:44 47
47fd5c32 Poul Sander 2024-10-05 08:44 48
  auto locale() -> detail::locale_ref { return {}; }
47fd5c32 Poul Sander 2024-10-05 08:44 49
47fd5c32 Poul Sander 2024-10-05 08:44 50
  auto arg(int id) const -> basic_format_arg<basic_printf_context> {
47fd5c32 Poul Sander 2024-10-05 08:44 51
    return args_.get(id);
47fd5c32 Poul Sander 2024-10-05 08:44 52
  }
47fd5c32 Poul Sander 2024-10-05 08:44 53
};
47fd5c32 Poul Sander 2024-10-05 08:44 54
47fd5c32 Poul Sander 2024-10-05 08:44 55
namespace detail {
47fd5c32 Poul Sander 2024-10-05 08:44 56
47fd5c32 Poul Sander 2024-10-05 08:44 57
// Checks if a value fits in int - used to avoid warnings about comparing
47fd5c32 Poul Sander 2024-10-05 08:44 58
// signed and unsigned integers.
47fd5c32 Poul Sander 2024-10-05 08:44 59
template <bool IsSigned> struct int_checker {
47fd5c32 Poul Sander 2024-10-05 08:44 60
  template <typename T> static auto fits_in_int(T value) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 61
    unsigned max = to_unsigned(max_value<int>());
47fd5c32 Poul Sander 2024-10-05 08:44 62
    return value <= max;
47fd5c32 Poul Sander 2024-10-05 08:44 63
  }
47fd5c32 Poul Sander 2024-10-05 08:44 64
  static auto fits_in_int(bool) -> bool { return true; }
47fd5c32 Poul Sander 2024-10-05 08:44 65
};
47fd5c32 Poul Sander 2024-10-05 08:44 66
47fd5c32 Poul Sander 2024-10-05 08:44 67
template <> struct int_checker<true> {
47fd5c32 Poul Sander 2024-10-05 08:44 68
  template <typename T> static auto fits_in_int(T value) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 69
    return value >= (std::numeric_limits<int>::min)() &&
47fd5c32 Poul Sander 2024-10-05 08:44 70
           value <= max_value<int>();
47fd5c32 Poul Sander 2024-10-05 08:44 71
  }
47fd5c32 Poul Sander 2024-10-05 08:44 72
  static auto fits_in_int(int) -> bool { return true; }
47fd5c32 Poul Sander 2024-10-05 08:44 73
};
47fd5c32 Poul Sander 2024-10-05 08:44 74
47fd5c32 Poul Sander 2024-10-05 08:44 75
struct printf_precision_handler {
47fd5c32 Poul Sander 2024-10-05 08:44 76
  template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 77
  auto operator()(T value) -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 78
    if (!int_checker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
47fd5c32 Poul Sander 2024-10-05 08:44 79
      report_error("number is too big");
47fd5c32 Poul Sander 2024-10-05 08:44 80
    return (std::max)(static_cast<int>(value), 0);
47fd5c32 Poul Sander 2024-10-05 08:44 81
  }
47fd5c32 Poul Sander 2024-10-05 08:44 82
47fd5c32 Poul Sander 2024-10-05 08:44 83
  template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 84
  auto operator()(T) -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 85
    report_error("precision is not integer");
47fd5c32 Poul Sander 2024-10-05 08:44 86
    return 0;
47fd5c32 Poul Sander 2024-10-05 08:44 87
  }
47fd5c32 Poul Sander 2024-10-05 08:44 88
};
47fd5c32 Poul Sander 2024-10-05 08:44 89
47fd5c32 Poul Sander 2024-10-05 08:44 90
// An argument visitor that returns true iff arg is a zero integer.
47fd5c32 Poul Sander 2024-10-05 08:44 91
struct is_zero_int {
47fd5c32 Poul Sander 2024-10-05 08:44 92
  template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 93
  auto operator()(T value) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 94
    return value == 0;
47fd5c32 Poul Sander 2024-10-05 08:44 95
  }
47fd5c32 Poul Sander 2024-10-05 08:44 96
47fd5c32 Poul Sander 2024-10-05 08:44 97
  template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 98
  auto operator()(T) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 99
    return false;
47fd5c32 Poul Sander 2024-10-05 08:44 100
  }
47fd5c32 Poul Sander 2024-10-05 08:44 101
};
47fd5c32 Poul Sander 2024-10-05 08:44 102
47fd5c32 Poul Sander 2024-10-05 08:44 103
template <typename T> struct make_unsigned_or_bool : std::make_unsigned<T> {};
47fd5c32 Poul Sander 2024-10-05 08:44 104
47fd5c32 Poul Sander 2024-10-05 08:44 105
template <> struct make_unsigned_or_bool<bool> {
47fd5c32 Poul Sander 2024-10-05 08:44 106
  using type = bool;
47fd5c32 Poul Sander 2024-10-05 08:44 107
};
47fd5c32 Poul Sander 2024-10-05 08:44 108
47fd5c32 Poul Sander 2024-10-05 08:44 109
template <typename T, typename Context> class arg_converter {
47fd5c32 Poul Sander 2024-10-05 08:44 110
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 111
  using char_type = typename Context::char_type;
47fd5c32 Poul Sander 2024-10-05 08:44 112
47fd5c32 Poul Sander 2024-10-05 08:44 113
  basic_format_arg<Context>& arg_;
47fd5c32 Poul Sander 2024-10-05 08:44 114
  char_type type_;
47fd5c32 Poul Sander 2024-10-05 08:44 115
47fd5c32 Poul Sander 2024-10-05 08:44 116
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 117
  arg_converter(basic_format_arg<Context>& arg, char_type type)
47fd5c32 Poul Sander 2024-10-05 08:44 118
      : arg_(arg), type_(type) {}
47fd5c32 Poul Sander 2024-10-05 08:44 119
47fd5c32 Poul Sander 2024-10-05 08:44 120
  void operator()(bool value) {
47fd5c32 Poul Sander 2024-10-05 08:44 121
    if (type_ != 's') operator()<bool>(value);
47fd5c32 Poul Sander 2024-10-05 08:44 122
  }
47fd5c32 Poul Sander 2024-10-05 08:44 123
47fd5c32 Poul Sander 2024-10-05 08:44 124
  template <typename U, FMT_ENABLE_IF(std::is_integral<U>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 125
  void operator()(U value) {
47fd5c32 Poul Sander 2024-10-05 08:44 126
    bool is_signed = type_ == 'd' || type_ == 'i';
47fd5c32 Poul Sander 2024-10-05 08:44 127
    using target_type = conditional_t<std::is_same<T, void>::value, U, T>;
47fd5c32 Poul Sander 2024-10-05 08:44 128
    if (const_check(sizeof(target_type) <= sizeof(int))) {
47fd5c32 Poul Sander 2024-10-05 08:44 129
      // Extra casts are used to silence warnings.
47fd5c32 Poul Sander 2024-10-05 08:44 130
      if (is_signed) {
47fd5c32 Poul Sander 2024-10-05 08:44 131
        auto n = static_cast<int>(static_cast<target_type>(value));
47fd5c32 Poul Sander 2024-10-05 08:44 132
        arg_ = detail::make_arg<Context>(n);
47fd5c32 Poul Sander 2024-10-05 08:44 133
      } else {
47fd5c32 Poul Sander 2024-10-05 08:44 134
        using unsigned_type = typename make_unsigned_or_bool<target_type>::type;
47fd5c32 Poul Sander 2024-10-05 08:44 135
        auto n = static_cast<unsigned>(static_cast<unsigned_type>(value));
47fd5c32 Poul Sander 2024-10-05 08:44 136
        arg_ = detail::make_arg<Context>(n);
47fd5c32 Poul Sander 2024-10-05 08:44 137
      }
47fd5c32 Poul Sander 2024-10-05 08:44 138
    } else {
47fd5c32 Poul Sander 2024-10-05 08:44 139
      if (is_signed) {
47fd5c32 Poul Sander 2024-10-05 08:44 140
        // glibc's printf doesn't sign extend arguments of smaller types:
47fd5c32 Poul Sander 2024-10-05 08:44 141
        //   std::printf("%lld", -42);  // prints "4294967254"
47fd5c32 Poul Sander 2024-10-05 08:44 142
        // but we don't have to do the same because it's a UB.
47fd5c32 Poul Sander 2024-10-05 08:44 143
        auto n = static_cast<long long>(value);
47fd5c32 Poul Sander 2024-10-05 08:44 144
        arg_ = detail::make_arg<Context>(n);
47fd5c32 Poul Sander 2024-10-05 08:44 145
      } else {
47fd5c32 Poul Sander 2024-10-05 08:44 146
        auto n = static_cast<typename make_unsigned_or_bool<U>::type>(value);
47fd5c32 Poul Sander 2024-10-05 08:44 147
        arg_ = detail::make_arg<Context>(n);
47fd5c32 Poul Sander 2024-10-05 08:44 148
      }
47fd5c32 Poul Sander 2024-10-05 08:44 149
    }
47fd5c32 Poul Sander 2024-10-05 08:44 150
  }
47fd5c32 Poul Sander 2024-10-05 08:44 151
47fd5c32 Poul Sander 2024-10-05 08:44 152
  template <typename U, FMT_ENABLE_IF(!std::is_integral<U>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 153
  void operator()(U) {}  // No conversion needed for non-integral types.
47fd5c32 Poul Sander 2024-10-05 08:44 154
};
47fd5c32 Poul Sander 2024-10-05 08:44 155
47fd5c32 Poul Sander 2024-10-05 08:44 156
// Converts an integer argument to T for printf, if T is an integral type.
47fd5c32 Poul Sander 2024-10-05 08:44 157
// If T is void, the argument is converted to corresponding signed or unsigned
47fd5c32 Poul Sander 2024-10-05 08:44 158
// type depending on the type specifier: 'd' and 'i' - signed, other -
47fd5c32 Poul Sander 2024-10-05 08:44 159
// unsigned).
47fd5c32 Poul Sander 2024-10-05 08:44 160
template <typename T, typename Context, typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 161
void convert_arg(basic_format_arg<Context>& arg, Char type) {
47fd5c32 Poul Sander 2024-10-05 08:44 162
  arg.visit(arg_converter<T, Context>(arg, type));
47fd5c32 Poul Sander 2024-10-05 08:44 163
}
47fd5c32 Poul Sander 2024-10-05 08:44 164
47fd5c32 Poul Sander 2024-10-05 08:44 165
// Converts an integer argument to char for printf.
47fd5c32 Poul Sander 2024-10-05 08:44 166
template <typename Context> class char_converter {
47fd5c32 Poul Sander 2024-10-05 08:44 167
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 168
  basic_format_arg<Context>& arg_;
47fd5c32 Poul Sander 2024-10-05 08:44 169
47fd5c32 Poul Sander 2024-10-05 08:44 170
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 171
  explicit char_converter(basic_format_arg<Context>& arg) : arg_(arg) {}
47fd5c32 Poul Sander 2024-10-05 08:44 172
47fd5c32 Poul Sander 2024-10-05 08:44 173
  template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 174
  void operator()(T value) {
47fd5c32 Poul Sander 2024-10-05 08:44 175
    auto c = static_cast<typename Context::char_type>(value);
47fd5c32 Poul Sander 2024-10-05 08:44 176
    arg_ = detail::make_arg<Context>(c);
47fd5c32 Poul Sander 2024-10-05 08:44 177
  }
47fd5c32 Poul Sander 2024-10-05 08:44 178
47fd5c32 Poul Sander 2024-10-05 08:44 179
  template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 180
  void operator()(T) {}  // No conversion needed for non-integral types.
47fd5c32 Poul Sander 2024-10-05 08:44 181
};
47fd5c32 Poul Sander 2024-10-05 08:44 182
47fd5c32 Poul Sander 2024-10-05 08:44 183
// An argument visitor that return a pointer to a C string if argument is a
47fd5c32 Poul Sander 2024-10-05 08:44 184
// string or null otherwise.
47fd5c32 Poul Sander 2024-10-05 08:44 185
template <typename Char> struct get_cstring {
47fd5c32 Poul Sander 2024-10-05 08:44 186
  template <typename T> auto operator()(T) -> const Char* { return nullptr; }
47fd5c32 Poul Sander 2024-10-05 08:44 187
  auto operator()(const Char* s) -> const Char* { return s; }
47fd5c32 Poul Sander 2024-10-05 08:44 188
};
47fd5c32 Poul Sander 2024-10-05 08:44 189
47fd5c32 Poul Sander 2024-10-05 08:44 190
// Checks if an argument is a valid printf width specifier and sets
47fd5c32 Poul Sander 2024-10-05 08:44 191
// left alignment if it is negative.
47fd5c32 Poul Sander 2024-10-05 08:44 192
class printf_width_handler {
47fd5c32 Poul Sander 2024-10-05 08:44 193
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 194
  format_specs& specs_;
47fd5c32 Poul Sander 2024-10-05 08:44 195
47fd5c32 Poul Sander 2024-10-05 08:44 196
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 197
  explicit printf_width_handler(format_specs& specs) : specs_(specs) {}
47fd5c32 Poul Sander 2024-10-05 08:44 198
47fd5c32 Poul Sander 2024-10-05 08:44 199
  template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 200
  auto operator()(T value) -> unsigned {
47fd5c32 Poul Sander 2024-10-05 08:44 201
    auto width = static_cast<uint32_or_64_or_128_t<T>>(value);
47fd5c32 Poul Sander 2024-10-05 08:44 202
    if (detail::is_negative(value)) {
47fd5c32 Poul Sander 2024-10-05 08:44 203
      specs_.align = align::left;
47fd5c32 Poul Sander 2024-10-05 08:44 204
      width = 0 - width;
47fd5c32 Poul Sander 2024-10-05 08:44 205
    }
47fd5c32 Poul Sander 2024-10-05 08:44 206
    unsigned int_max = to_unsigned(max_value<int>());
47fd5c32 Poul Sander 2024-10-05 08:44 207
    if (width > int_max) report_error("number is too big");
47fd5c32 Poul Sander 2024-10-05 08:44 208
    return static_cast<unsigned>(width);
47fd5c32 Poul Sander 2024-10-05 08:44 209
  }
47fd5c32 Poul Sander 2024-10-05 08:44 210
47fd5c32 Poul Sander 2024-10-05 08:44 211
  template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 212
  auto operator()(T) -> unsigned {
47fd5c32 Poul Sander 2024-10-05 08:44 213
    report_error("width is not integer");
47fd5c32 Poul Sander 2024-10-05 08:44 214
    return 0;
47fd5c32 Poul Sander 2024-10-05 08:44 215
  }
47fd5c32 Poul Sander 2024-10-05 08:44 216
};
47fd5c32 Poul Sander 2024-10-05 08:44 217
47fd5c32 Poul Sander 2024-10-05 08:44 218
// Workaround for a bug with the XL compiler when initializing
47fd5c32 Poul Sander 2024-10-05 08:44 219
// printf_arg_formatter's base class.
47fd5c32 Poul Sander 2024-10-05 08:44 220
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 221
auto make_arg_formatter(basic_appender<Char> iter, format_specs& s)
47fd5c32 Poul Sander 2024-10-05 08:44 222
    -> arg_formatter<Char> {
47fd5c32 Poul Sander 2024-10-05 08:44 223
  return {iter, s, locale_ref()};
47fd5c32 Poul Sander 2024-10-05 08:44 224
}
47fd5c32 Poul Sander 2024-10-05 08:44 225
47fd5c32 Poul Sander 2024-10-05 08:44 226
// The `printf` argument formatter.
47fd5c32 Poul Sander 2024-10-05 08:44 227
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 228
class printf_arg_formatter : public arg_formatter<Char> {
47fd5c32 Poul Sander 2024-10-05 08:44 229
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 230
  using base = arg_formatter<Char>;
47fd5c32 Poul Sander 2024-10-05 08:44 231
  using context_type = basic_printf_context<Char>;
47fd5c32 Poul Sander 2024-10-05 08:44 232
47fd5c32 Poul Sander 2024-10-05 08:44 233
  context_type& context_;
47fd5c32 Poul Sander 2024-10-05 08:44 234
47fd5c32 Poul Sander 2024-10-05 08:44 235
  void write_null_pointer(bool is_string = false) {
47fd5c32 Poul Sander 2024-10-05 08:44 236
    auto s = this->specs;
47fd5c32 Poul Sander 2024-10-05 08:44 237
    s.type = presentation_type::none;
47fd5c32 Poul Sander 2024-10-05 08:44 238
    write_bytes<Char>(this->out, is_string ? "(null)" : "(nil)", s);
47fd5c32 Poul Sander 2024-10-05 08:44 239
  }
47fd5c32 Poul Sander 2024-10-05 08:44 240
47fd5c32 Poul Sander 2024-10-05 08:44 241
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 242
  printf_arg_formatter(basic_appender<Char> iter, format_specs& s,
47fd5c32 Poul Sander 2024-10-05 08:44 243
                       context_type& ctx)
47fd5c32 Poul Sander 2024-10-05 08:44 244
      : base(make_arg_formatter(iter, s)), context_(ctx) {}
47fd5c32 Poul Sander 2024-10-05 08:44 245
47fd5c32 Poul Sander 2024-10-05 08:44 246
  void operator()(monostate value) { base::operator()(value); }
47fd5c32 Poul Sander 2024-10-05 08:44 247
47fd5c32 Poul Sander 2024-10-05 08:44 248
  template <typename T, FMT_ENABLE_IF(detail::is_integral<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 249
  void operator()(T value) {
47fd5c32 Poul Sander 2024-10-05 08:44 250
    // MSVC2013 fails to compile separate overloads for bool and Char so use
47fd5c32 Poul Sander 2024-10-05 08:44 251
    // std::is_same instead.
47fd5c32 Poul Sander 2024-10-05 08:44 252
    if (!std::is_same<T, Char>::value) {
47fd5c32 Poul Sander 2024-10-05 08:44 253
      base::operator()(value);
47fd5c32 Poul Sander 2024-10-05 08:44 254
      return;
47fd5c32 Poul Sander 2024-10-05 08:44 255
    }
47fd5c32 Poul Sander 2024-10-05 08:44 256
    format_specs s = this->specs;
47fd5c32 Poul Sander 2024-10-05 08:44 257
    if (s.type != presentation_type::none && s.type != presentation_type::chr) {
47fd5c32 Poul Sander 2024-10-05 08:44 258
      return (*this)(static_cast<int>(value));
47fd5c32 Poul Sander 2024-10-05 08:44 259
    }
47fd5c32 Poul Sander 2024-10-05 08:44 260
    s.sign = sign::none;
47fd5c32 Poul Sander 2024-10-05 08:44 261
    s.alt = false;
47fd5c32 Poul Sander 2024-10-05 08:44 262
    s.fill = ' ';  // Ignore '0' flag for char types.
47fd5c32 Poul Sander 2024-10-05 08:44 263
    // align::numeric needs to be overwritten here since the '0' flag is
47fd5c32 Poul Sander 2024-10-05 08:44 264
    // ignored for non-numeric types
47fd5c32 Poul Sander 2024-10-05 08:44 265
    if (s.align == align::none || s.align == align::numeric)
47fd5c32 Poul Sander 2024-10-05 08:44 266
      s.align = align::right;
47fd5c32 Poul Sander 2024-10-05 08:44 267
    write<Char>(this->out, static_cast<Char>(value), s);
47fd5c32 Poul Sander 2024-10-05 08:44 268
  }
47fd5c32 Poul Sander 2024-10-05 08:44 269
47fd5c32 Poul Sander 2024-10-05 08:44 270
  template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 271
  void operator()(T value) {
47fd5c32 Poul Sander 2024-10-05 08:44 272
    base::operator()(value);
47fd5c32 Poul Sander 2024-10-05 08:44 273
  }
47fd5c32 Poul Sander 2024-10-05 08:44 274
47fd5c32 Poul Sander 2024-10-05 08:44 275
  void operator()(const char* value) {
47fd5c32 Poul Sander 2024-10-05 08:44 276
    if (value)
47fd5c32 Poul Sander 2024-10-05 08:44 277
      base::operator()(value);
47fd5c32 Poul Sander 2024-10-05 08:44 278
    else
47fd5c32 Poul Sander 2024-10-05 08:44 279
      write_null_pointer(this->specs.type != presentation_type::pointer);
47fd5c32 Poul Sander 2024-10-05 08:44 280
  }
47fd5c32 Poul Sander 2024-10-05 08:44 281
47fd5c32 Poul Sander 2024-10-05 08:44 282
  void operator()(const wchar_t* value) {
47fd5c32 Poul Sander 2024-10-05 08:44 283
    if (value)
47fd5c32 Poul Sander 2024-10-05 08:44 284
      base::operator()(value);
47fd5c32 Poul Sander 2024-10-05 08:44 285
    else
47fd5c32 Poul Sander 2024-10-05 08:44 286
      write_null_pointer(this->specs.type != presentation_type::pointer);
47fd5c32 Poul Sander 2024-10-05 08:44 287
  }
47fd5c32 Poul Sander 2024-10-05 08:44 288
47fd5c32 Poul Sander 2024-10-05 08:44 289
  void operator()(basic_string_view<Char> value) { base::operator()(value); }
47fd5c32 Poul Sander 2024-10-05 08:44 290
47fd5c32 Poul Sander 2024-10-05 08:44 291
  void operator()(const void* value) {
47fd5c32 Poul Sander 2024-10-05 08:44 292
    if (value)
47fd5c32 Poul Sander 2024-10-05 08:44 293
      base::operator()(value);
47fd5c32 Poul Sander 2024-10-05 08:44 294
    else
47fd5c32 Poul Sander 2024-10-05 08:44 295
      write_null_pointer();
47fd5c32 Poul Sander 2024-10-05 08:44 296
  }
47fd5c32 Poul Sander 2024-10-05 08:44 297
47fd5c32 Poul Sander 2024-10-05 08:44 298
  void operator()(typename basic_format_arg<context_type>::handle handle) {
47fd5c32 Poul Sander 2024-10-05 08:44 299
    auto parse_ctx = basic_format_parse_context<Char>({});
47fd5c32 Poul Sander 2024-10-05 08:44 300
    handle.format(parse_ctx, context_);
47fd5c32 Poul Sander 2024-10-05 08:44 301
  }
47fd5c32 Poul Sander 2024-10-05 08:44 302
};
47fd5c32 Poul Sander 2024-10-05 08:44 303
47fd5c32 Poul Sander 2024-10-05 08:44 304
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 305
void parse_flags(format_specs& specs, const Char*& it, const Char* end) {
47fd5c32 Poul Sander 2024-10-05 08:44 306
  for (; it != end; ++it) {
47fd5c32 Poul Sander 2024-10-05 08:44 307
    switch (*it) {
47fd5c32 Poul Sander 2024-10-05 08:44 308
    case '-':
47fd5c32 Poul Sander 2024-10-05 08:44 309
      specs.align = align::left;
47fd5c32 Poul Sander 2024-10-05 08:44 310
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 311
    case '+':
47fd5c32 Poul Sander 2024-10-05 08:44 312
      specs.sign = sign::plus;
47fd5c32 Poul Sander 2024-10-05 08:44 313
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 314
    case '0':
47fd5c32 Poul Sander 2024-10-05 08:44 315
      specs.fill = '0';
47fd5c32 Poul Sander 2024-10-05 08:44 316
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 317
    case ' ':
47fd5c32 Poul Sander 2024-10-05 08:44 318
      if (specs.sign != sign::plus) specs.sign = sign::space;
47fd5c32 Poul Sander 2024-10-05 08:44 319
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 320
    case '#':
47fd5c32 Poul Sander 2024-10-05 08:44 321
      specs.alt = true;
47fd5c32 Poul Sander 2024-10-05 08:44 322
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 323
    default:
47fd5c32 Poul Sander 2024-10-05 08:44 324
      return;
47fd5c32 Poul Sander 2024-10-05 08:44 325
    }
47fd5c32 Poul Sander 2024-10-05 08:44 326
  }
47fd5c32 Poul Sander 2024-10-05 08:44 327
}
47fd5c32 Poul Sander 2024-10-05 08:44 328
47fd5c32 Poul Sander 2024-10-05 08:44 329
template <typename Char, typename GetArg>
47fd5c32 Poul Sander 2024-10-05 08:44 330
auto parse_header(const Char*& it, const Char* end, format_specs& specs,
47fd5c32 Poul Sander 2024-10-05 08:44 331
                  GetArg get_arg) -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 332
  int arg_index = -1;
47fd5c32 Poul Sander 2024-10-05 08:44 333
  Char c = *it;
47fd5c32 Poul Sander 2024-10-05 08:44 334
  if (c >= '0' && c <= '9') {
47fd5c32 Poul Sander 2024-10-05 08:44 335
    // Parse an argument index (if followed by '$') or a width possibly
47fd5c32 Poul Sander 2024-10-05 08:44 336
    // preceded with '0' flag(s).
47fd5c32 Poul Sander 2024-10-05 08:44 337
    int value = parse_nonnegative_int(it, end, -1);
47fd5c32 Poul Sander 2024-10-05 08:44 338
    if (it != end && *it == '$') {  // value is an argument index
47fd5c32 Poul Sander 2024-10-05 08:44 339
      ++it;
47fd5c32 Poul Sander 2024-10-05 08:44 340
      arg_index = value != -1 ? value : max_value<int>();
47fd5c32 Poul Sander 2024-10-05 08:44 341
    } else {
47fd5c32 Poul Sander 2024-10-05 08:44 342
      if (c == '0') specs.fill = '0';
47fd5c32 Poul Sander 2024-10-05 08:44 343
      if (value != 0) {
47fd5c32 Poul Sander 2024-10-05 08:44 344
        // Nonzero value means that we parsed width and don't need to
47fd5c32 Poul Sander 2024-10-05 08:44 345
        // parse it or flags again, so return now.
47fd5c32 Poul Sander 2024-10-05 08:44 346
        if (value == -1) report_error("number is too big");
47fd5c32 Poul Sander 2024-10-05 08:44 347
        specs.width = value;
47fd5c32 Poul Sander 2024-10-05 08:44 348
        return arg_index;
47fd5c32 Poul Sander 2024-10-05 08:44 349
      }
47fd5c32 Poul Sander 2024-10-05 08:44 350
    }
47fd5c32 Poul Sander 2024-10-05 08:44 351
  }
47fd5c32 Poul Sander 2024-10-05 08:44 352
  parse_flags(specs, it, end);
47fd5c32 Poul Sander 2024-10-05 08:44 353
  // Parse width.
47fd5c32 Poul Sander 2024-10-05 08:44 354
  if (it != end) {
47fd5c32 Poul Sander 2024-10-05 08:44 355
    if (*it >= '0' && *it <= '9') {
47fd5c32 Poul Sander 2024-10-05 08:44 356
      specs.width = parse_nonnegative_int(it, end, -1);
47fd5c32 Poul Sander 2024-10-05 08:44 357
      if (specs.width == -1) report_error("number is too big");
47fd5c32 Poul Sander 2024-10-05 08:44 358
    } else if (*it == '*') {
47fd5c32 Poul Sander 2024-10-05 08:44 359
      ++it;
47fd5c32 Poul Sander 2024-10-05 08:44 360
      specs.width = static_cast<int>(
47fd5c32 Poul Sander 2024-10-05 08:44 361
          get_arg(-1).visit(detail::printf_width_handler(specs)));
47fd5c32 Poul Sander 2024-10-05 08:44 362
    }
47fd5c32 Poul Sander 2024-10-05 08:44 363
  }
47fd5c32 Poul Sander 2024-10-05 08:44 364
  return arg_index;
47fd5c32 Poul Sander 2024-10-05 08:44 365
}
47fd5c32 Poul Sander 2024-10-05 08:44 366
47fd5c32 Poul Sander 2024-10-05 08:44 367
inline auto parse_printf_presentation_type(char c, type t, bool& upper)
47fd5c32 Poul Sander 2024-10-05 08:44 368
    -> presentation_type {
47fd5c32 Poul Sander 2024-10-05 08:44 369
  using pt = presentation_type;
47fd5c32 Poul Sander 2024-10-05 08:44 370
  constexpr auto integral_set = sint_set | uint_set | bool_set | char_set;
47fd5c32 Poul Sander 2024-10-05 08:44 371
  switch (c) {
47fd5c32 Poul Sander 2024-10-05 08:44 372
  case 'd':
47fd5c32 Poul Sander 2024-10-05 08:44 373
    return in(t, integral_set) ? pt::dec : pt::none;
47fd5c32 Poul Sander 2024-10-05 08:44 374
  case 'o':
47fd5c32 Poul Sander 2024-10-05 08:44 375
    return in(t, integral_set) ? pt::oct : pt::none;
47fd5c32 Poul Sander 2024-10-05 08:44 376
  case 'X':
47fd5c32 Poul Sander 2024-10-05 08:44 377
    upper = true;
47fd5c32 Poul Sander 2024-10-05 08:44 378
    FMT_FALLTHROUGH;
47fd5c32 Poul Sander 2024-10-05 08:44 379
  case 'x':
47fd5c32 Poul Sander 2024-10-05 08:44 380
    return in(t, integral_set) ? pt::hex : pt::none;
47fd5c32 Poul Sander 2024-10-05 08:44 381
  case 'E':
47fd5c32 Poul Sander 2024-10-05 08:44 382
    upper = true;
47fd5c32 Poul Sander 2024-10-05 08:44 383
    FMT_FALLTHROUGH;
47fd5c32 Poul Sander 2024-10-05 08:44 384
  case 'e':
47fd5c32 Poul Sander 2024-10-05 08:44 385
    return in(t, float_set) ? pt::exp : pt::none;
47fd5c32 Poul Sander 2024-10-05 08:44 386
  case 'F':
47fd5c32 Poul Sander 2024-10-05 08:44 387
    upper = true;
47fd5c32 Poul Sander 2024-10-05 08:44 388
    FMT_FALLTHROUGH;
47fd5c32 Poul Sander 2024-10-05 08:44 389
  case 'f':
47fd5c32 Poul Sander 2024-10-05 08:44 390
    return in(t, float_set) ? pt::fixed : pt::none;
47fd5c32 Poul Sander 2024-10-05 08:44 391
  case 'G':
47fd5c32 Poul Sander 2024-10-05 08:44 392
    upper = true;
47fd5c32 Poul Sander 2024-10-05 08:44 393
    FMT_FALLTHROUGH;
47fd5c32 Poul Sander 2024-10-05 08:44 394
  case 'g':
47fd5c32 Poul Sander 2024-10-05 08:44 395
    return in(t, float_set) ? pt::general : pt::none;
47fd5c32 Poul Sander 2024-10-05 08:44 396
  case 'A':
47fd5c32 Poul Sander 2024-10-05 08:44 397
    upper = true;
47fd5c32 Poul Sander 2024-10-05 08:44 398
    FMT_FALLTHROUGH;
47fd5c32 Poul Sander 2024-10-05 08:44 399
  case 'a':
47fd5c32 Poul Sander 2024-10-05 08:44 400
    return in(t, float_set) ? pt::hexfloat : pt::none;
47fd5c32 Poul Sander 2024-10-05 08:44 401
  case 'c':
47fd5c32 Poul Sander 2024-10-05 08:44 402
    return in(t, integral_set) ? pt::chr : pt::none;
47fd5c32 Poul Sander 2024-10-05 08:44 403
  case 's':
47fd5c32 Poul Sander 2024-10-05 08:44 404
    return in(t, string_set | cstring_set) ? pt::string : pt::none;
47fd5c32 Poul Sander 2024-10-05 08:44 405
  case 'p':
47fd5c32 Poul Sander 2024-10-05 08:44 406
    return in(t, pointer_set | cstring_set) ? pt::pointer : pt::none;
47fd5c32 Poul Sander 2024-10-05 08:44 407
  default:
47fd5c32 Poul Sander 2024-10-05 08:44 408
    return pt::none;
47fd5c32 Poul Sander 2024-10-05 08:44 409
  }
47fd5c32 Poul Sander 2024-10-05 08:44 410
}
47fd5c32 Poul Sander 2024-10-05 08:44 411
47fd5c32 Poul Sander 2024-10-05 08:44 412
template <typename Char, typename Context>
47fd5c32 Poul Sander 2024-10-05 08:44 413
void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
47fd5c32 Poul Sander 2024-10-05 08:44 414
             basic_format_args<Context> args) {
47fd5c32 Poul Sander 2024-10-05 08:44 415
  using iterator = basic_appender<Char>;
47fd5c32 Poul Sander 2024-10-05 08:44 416
  auto out = iterator(buf);
47fd5c32 Poul Sander 2024-10-05 08:44 417
  auto context = basic_printf_context<Char>(out, args);
47fd5c32 Poul Sander 2024-10-05 08:44 418
  auto parse_ctx = basic_format_parse_context<Char>(format);
47fd5c32 Poul Sander 2024-10-05 08:44 419
47fd5c32 Poul Sander 2024-10-05 08:44 420
  // Returns the argument with specified index or, if arg_index is -1, the next
47fd5c32 Poul Sander 2024-10-05 08:44 421
  // argument.
47fd5c32 Poul Sander 2024-10-05 08:44 422
  auto get_arg = [&](int arg_index) {
47fd5c32 Poul Sander 2024-10-05 08:44 423
    if (arg_index < 0)
47fd5c32 Poul Sander 2024-10-05 08:44 424
      arg_index = parse_ctx.next_arg_id();
47fd5c32 Poul Sander 2024-10-05 08:44 425
    else
47fd5c32 Poul Sander 2024-10-05 08:44 426
      parse_ctx.check_arg_id(--arg_index);
47fd5c32 Poul Sander 2024-10-05 08:44 427
    return detail::get_arg(context, arg_index);
47fd5c32 Poul Sander 2024-10-05 08:44 428
  };
47fd5c32 Poul Sander 2024-10-05 08:44 429
47fd5c32 Poul Sander 2024-10-05 08:44 430
  const Char* start = parse_ctx.begin();
47fd5c32 Poul Sander 2024-10-05 08:44 431
  const Char* end = parse_ctx.end();
47fd5c32 Poul Sander 2024-10-05 08:44 432
  auto it = start;
47fd5c32 Poul Sander 2024-10-05 08:44 433
  while (it != end) {
47fd5c32 Poul Sander 2024-10-05 08:44 434
    if (!find<false, Char>(it, end, '%', it)) {
47fd5c32 Poul Sander 2024-10-05 08:44 435
      it = end;  // find leaves it == nullptr if it doesn't find '%'.
47fd5c32 Poul Sander 2024-10-05 08:44 436
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 437
    }
47fd5c32 Poul Sander 2024-10-05 08:44 438
    Char c = *it++;
47fd5c32 Poul Sander 2024-10-05 08:44 439
    if (it != end && *it == c) {
47fd5c32 Poul Sander 2024-10-05 08:44 440
      write(out, basic_string_view<Char>(start, to_unsigned(it - start)));
47fd5c32 Poul Sander 2024-10-05 08:44 441
      start = ++it;
47fd5c32 Poul Sander 2024-10-05 08:44 442
      continue;
47fd5c32 Poul Sander 2024-10-05 08:44 443
    }
47fd5c32 Poul Sander 2024-10-05 08:44 444
    write(out, basic_string_view<Char>(start, to_unsigned(it - 1 - start)));
47fd5c32 Poul Sander 2024-10-05 08:44 445
47fd5c32 Poul Sander 2024-10-05 08:44 446
    auto specs = format_specs();
47fd5c32 Poul Sander 2024-10-05 08:44 447
    specs.align = align::right;
47fd5c32 Poul Sander 2024-10-05 08:44 448
47fd5c32 Poul Sander 2024-10-05 08:44 449
    // Parse argument index, flags and width.
47fd5c32 Poul Sander 2024-10-05 08:44 450
    int arg_index = parse_header(it, end, specs, get_arg);
47fd5c32 Poul Sander 2024-10-05 08:44 451
    if (arg_index == 0) report_error("argument not found");
47fd5c32 Poul Sander 2024-10-05 08:44 452
47fd5c32 Poul Sander 2024-10-05 08:44 453
    // Parse precision.
47fd5c32 Poul Sander 2024-10-05 08:44 454
    if (it != end && *it == '.') {
47fd5c32 Poul Sander 2024-10-05 08:44 455
      ++it;
47fd5c32 Poul Sander 2024-10-05 08:44 456
      c = it != end ? *it : 0;
47fd5c32 Poul Sander 2024-10-05 08:44 457
      if ('0' <= c && c <= '9') {
47fd5c32 Poul Sander 2024-10-05 08:44 458
        specs.precision = parse_nonnegative_int(it, end, 0);
47fd5c32 Poul Sander 2024-10-05 08:44 459
      } else if (c == '*') {
47fd5c32 Poul Sander 2024-10-05 08:44 460
        ++it;
47fd5c32 Poul Sander 2024-10-05 08:44 461
        specs.precision =
47fd5c32 Poul Sander 2024-10-05 08:44 462
            static_cast<int>(get_arg(-1).visit(printf_precision_handler()));
47fd5c32 Poul Sander 2024-10-05 08:44 463
      } else {
47fd5c32 Poul Sander 2024-10-05 08:44 464
        specs.precision = 0;
47fd5c32 Poul Sander 2024-10-05 08:44 465
      }
47fd5c32 Poul Sander 2024-10-05 08:44 466
    }
47fd5c32 Poul Sander 2024-10-05 08:44 467
47fd5c32 Poul Sander 2024-10-05 08:44 468
    auto arg = get_arg(arg_index);
47fd5c32 Poul Sander 2024-10-05 08:44 469
    // For d, i, o, u, x, and X conversion specifiers, if a precision is
47fd5c32 Poul Sander 2024-10-05 08:44 470
    // specified, the '0' flag is ignored
47fd5c32 Poul Sander 2024-10-05 08:44 471
    if (specs.precision >= 0 && arg.is_integral()) {
47fd5c32 Poul Sander 2024-10-05 08:44 472
      // Ignore '0' for non-numeric types or if '-' present.
47fd5c32 Poul Sander 2024-10-05 08:44 473
      specs.fill = ' ';
47fd5c32 Poul Sander 2024-10-05 08:44 474
    }
47fd5c32 Poul Sander 2024-10-05 08:44 475
    if (specs.precision >= 0 && arg.type() == type::cstring_type) {
47fd5c32 Poul Sander 2024-10-05 08:44 476
      auto str = arg.visit(get_cstring<Char>());
47fd5c32 Poul Sander 2024-10-05 08:44 477
      auto str_end = str + specs.precision;
47fd5c32 Poul Sander 2024-10-05 08:44 478
      auto nul = std::find(str, str_end, Char());
47fd5c32 Poul Sander 2024-10-05 08:44 479
      auto sv = basic_string_view<Char>(
47fd5c32 Poul Sander 2024-10-05 08:44 480
          str, to_unsigned(nul != str_end ? nul - str : specs.precision));
47fd5c32 Poul Sander 2024-10-05 08:44 481
      arg = make_arg<basic_printf_context<Char>>(sv);
47fd5c32 Poul Sander 2024-10-05 08:44 482
    }
47fd5c32 Poul Sander 2024-10-05 08:44 483
    if (specs.alt && arg.visit(is_zero_int())) specs.alt = false;
47fd5c32 Poul Sander 2024-10-05 08:44 484
    if (specs.fill.template get<Char>() == '0') {
47fd5c32 Poul Sander 2024-10-05 08:44 485
      if (arg.is_arithmetic() && specs.align != align::left)
47fd5c32 Poul Sander 2024-10-05 08:44 486
        specs.align = align::numeric;
47fd5c32 Poul Sander 2024-10-05 08:44 487
      else
47fd5c32 Poul Sander 2024-10-05 08:44 488
        specs.fill = ' ';  // Ignore '0' flag for non-numeric types or if '-'
47fd5c32 Poul Sander 2024-10-05 08:44 489
                           // flag is also present.
47fd5c32 Poul Sander 2024-10-05 08:44 490
    }
47fd5c32 Poul Sander 2024-10-05 08:44 491
47fd5c32 Poul Sander 2024-10-05 08:44 492
    // Parse length and convert the argument to the required type.
47fd5c32 Poul Sander 2024-10-05 08:44 493
    c = it != end ? *it++ : 0;
47fd5c32 Poul Sander 2024-10-05 08:44 494
    Char t = it != end ? *it : 0;
47fd5c32 Poul Sander 2024-10-05 08:44 495
    switch (c) {
47fd5c32 Poul Sander 2024-10-05 08:44 496
    case 'h':
47fd5c32 Poul Sander 2024-10-05 08:44 497
      if (t == 'h') {
47fd5c32 Poul Sander 2024-10-05 08:44 498
        ++it;
47fd5c32 Poul Sander 2024-10-05 08:44 499
        t = it != end ? *it : 0;
47fd5c32 Poul Sander 2024-10-05 08:44 500
        convert_arg<signed char>(arg, t);
47fd5c32 Poul Sander 2024-10-05 08:44 501
      } else {
47fd5c32 Poul Sander 2024-10-05 08:44 502
        convert_arg<short>(arg, t);
47fd5c32 Poul Sander 2024-10-05 08:44 503
      }
47fd5c32 Poul Sander 2024-10-05 08:44 504
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 505
    case 'l':
47fd5c32 Poul Sander 2024-10-05 08:44 506
      if (t == 'l') {
47fd5c32 Poul Sander 2024-10-05 08:44 507
        ++it;
47fd5c32 Poul Sander 2024-10-05 08:44 508
        t = it != end ? *it : 0;
47fd5c32 Poul Sander 2024-10-05 08:44 509
        convert_arg<long long>(arg, t);
47fd5c32 Poul Sander 2024-10-05 08:44 510
      } else {
47fd5c32 Poul Sander 2024-10-05 08:44 511
        convert_arg<long>(arg, t);
47fd5c32 Poul Sander 2024-10-05 08:44 512
      }
47fd5c32 Poul Sander 2024-10-05 08:44 513
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 514
    case 'j':
47fd5c32 Poul Sander 2024-10-05 08:44 515
      convert_arg<intmax_t>(arg, t);
47fd5c32 Poul Sander 2024-10-05 08:44 516
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 517
    case 'z':
47fd5c32 Poul Sander 2024-10-05 08:44 518
      convert_arg<size_t>(arg, t);
47fd5c32 Poul Sander 2024-10-05 08:44 519
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 520
    case 't':
47fd5c32 Poul Sander 2024-10-05 08:44 521
      convert_arg<std::ptrdiff_t>(arg, t);
47fd5c32 Poul Sander 2024-10-05 08:44 522
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 523
    case 'L':
47fd5c32 Poul Sander 2024-10-05 08:44 524
      // printf produces garbage when 'L' is omitted for long double, no
47fd5c32 Poul Sander 2024-10-05 08:44 525
      // need to do the same.
47fd5c32 Poul Sander 2024-10-05 08:44 526
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 527
    default:
47fd5c32 Poul Sander 2024-10-05 08:44 528
      --it;
47fd5c32 Poul Sander 2024-10-05 08:44 529
      convert_arg<void>(arg, c);
47fd5c32 Poul Sander 2024-10-05 08:44 530
    }
47fd5c32 Poul Sander 2024-10-05 08:44 531
47fd5c32 Poul Sander 2024-10-05 08:44 532
    // Parse type.
47fd5c32 Poul Sander 2024-10-05 08:44 533
    if (it == end) report_error("invalid format string");
47fd5c32 Poul Sander 2024-10-05 08:44 534
    char type = static_cast<char>(*it++);
47fd5c32 Poul Sander 2024-10-05 08:44 535
    if (arg.is_integral()) {
47fd5c32 Poul Sander 2024-10-05 08:44 536
      // Normalize type.
47fd5c32 Poul Sander 2024-10-05 08:44 537
      switch (type) {
47fd5c32 Poul Sander 2024-10-05 08:44 538
      case 'i':
47fd5c32 Poul Sander 2024-10-05 08:44 539
      case 'u':
47fd5c32 Poul Sander 2024-10-05 08:44 540
        type = 'd';
47fd5c32 Poul Sander 2024-10-05 08:44 541
        break;
47fd5c32 Poul Sander 2024-10-05 08:44 542
      case 'c':
47fd5c32 Poul Sander 2024-10-05 08:44 543
        arg.visit(char_converter<basic_printf_context<Char>>(arg));
47fd5c32 Poul Sander 2024-10-05 08:44 544
        break;
47fd5c32 Poul Sander 2024-10-05 08:44 545
      }
47fd5c32 Poul Sander 2024-10-05 08:44 546
    }
47fd5c32 Poul Sander 2024-10-05 08:44 547
    bool upper = false;
47fd5c32 Poul Sander 2024-10-05 08:44 548
    specs.type = parse_printf_presentation_type(type, arg.type(), upper);
47fd5c32 Poul Sander 2024-10-05 08:44 549
    if (specs.type == presentation_type::none)
47fd5c32 Poul Sander 2024-10-05 08:44 550
      report_error("invalid format specifier");
47fd5c32 Poul Sander 2024-10-05 08:44 551
    specs.upper = upper;
47fd5c32 Poul Sander 2024-10-05 08:44 552
47fd5c32 Poul Sander 2024-10-05 08:44 553
    start = it;
47fd5c32 Poul Sander 2024-10-05 08:44 554
47fd5c32 Poul Sander 2024-10-05 08:44 555
    // Format argument.
47fd5c32 Poul Sander 2024-10-05 08:44 556
    arg.visit(printf_arg_formatter<Char>(out, specs, context));
47fd5c32 Poul Sander 2024-10-05 08:44 557
  }
47fd5c32 Poul Sander 2024-10-05 08:44 558
  write(out, basic_string_view<Char>(start, to_unsigned(it - start)));
47fd5c32 Poul Sander 2024-10-05 08:44 559
}
47fd5c32 Poul Sander 2024-10-05 08:44 560
}  // namespace detail
47fd5c32 Poul Sander 2024-10-05 08:44 561
47fd5c32 Poul Sander 2024-10-05 08:44 562
using printf_context = basic_printf_context<char>;
47fd5c32 Poul Sander 2024-10-05 08:44 563
using wprintf_context = basic_printf_context<wchar_t>;
47fd5c32 Poul Sander 2024-10-05 08:44 564
47fd5c32 Poul Sander 2024-10-05 08:44 565
using printf_args = basic_format_args<printf_context>;
47fd5c32 Poul Sander 2024-10-05 08:44 566
using wprintf_args = basic_format_args<wprintf_context>;
47fd5c32 Poul Sander 2024-10-05 08:44 567
47fd5c32 Poul Sander 2024-10-05 08:44 568
/// Constructs an `format_arg_store` object that contains references to
47fd5c32 Poul Sander 2024-10-05 08:44 569
/// arguments and can be implicitly converted to `printf_args`.
47fd5c32 Poul Sander 2024-10-05 08:44 570
template <typename Char = char, typename... T>
47fd5c32 Poul Sander 2024-10-05 08:44 571
inline auto make_printf_args(T&... args)
47fd5c32 Poul Sander 2024-10-05 08:44 572
    -> decltype(fmt::make_format_args<basic_printf_context<Char>>(args...)) {
47fd5c32 Poul Sander 2024-10-05 08:44 573
  return fmt::make_format_args<basic_printf_context<Char>>(args...);
47fd5c32 Poul Sander 2024-10-05 08:44 574
}
47fd5c32 Poul Sander 2024-10-05 08:44 575
47fd5c32 Poul Sander 2024-10-05 08:44 576
template <typename Char> struct vprintf_args {
47fd5c32 Poul Sander 2024-10-05 08:44 577
  using type = basic_format_args<basic_printf_context<Char>>;
47fd5c32 Poul Sander 2024-10-05 08:44 578
};
47fd5c32 Poul Sander 2024-10-05 08:44 579
47fd5c32 Poul Sander 2024-10-05 08:44 580
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 581
inline auto vsprintf(basic_string_view<Char> fmt,
47fd5c32 Poul Sander 2024-10-05 08:44 582
                     typename vprintf_args<Char>::type args)
47fd5c32 Poul Sander 2024-10-05 08:44 583
    -> std::basic_string<Char> {
47fd5c32 Poul Sander 2024-10-05 08:44 584
  auto buf = basic_memory_buffer<Char>();
47fd5c32 Poul Sander 2024-10-05 08:44 585
  detail::vprintf(buf, fmt, args);
47fd5c32 Poul Sander 2024-10-05 08:44 586
  return to_string(buf);
47fd5c32 Poul Sander 2024-10-05 08:44 587
}
47fd5c32 Poul Sander 2024-10-05 08:44 588
47fd5c32 Poul Sander 2024-10-05 08:44 589
/**
47fd5c32 Poul Sander 2024-10-05 08:44 590
 * Formats `args` according to specifications in `fmt` and returns the result
47fd5c32 Poul Sander 2024-10-05 08:44 591
 * as as string.
47fd5c32 Poul Sander 2024-10-05 08:44 592
 *
47fd5c32 Poul Sander 2024-10-05 08:44 593
 * **Example**:
47fd5c32 Poul Sander 2024-10-05 08:44 594
 *
47fd5c32 Poul Sander 2024-10-05 08:44 595
 *     std::string message = fmt::sprintf("The answer is %d", 42);
47fd5c32 Poul Sander 2024-10-05 08:44 596
 */
47fd5c32 Poul Sander 2024-10-05 08:44 597
template <typename S, typename... T, typename Char = char_t<S>>
47fd5c32 Poul Sander 2024-10-05 08:44 598
inline auto sprintf(const S& fmt, const T&... args) -> std::basic_string<Char> {
47fd5c32 Poul Sander 2024-10-05 08:44 599
  return vsprintf(detail::to_string_view(fmt),
47fd5c32 Poul Sander 2024-10-05 08:44 600
                  fmt::make_format_args<basic_printf_context<Char>>(args...));
47fd5c32 Poul Sander 2024-10-05 08:44 601
}
47fd5c32 Poul Sander 2024-10-05 08:44 602
47fd5c32 Poul Sander 2024-10-05 08:44 603
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 604
inline auto vfprintf(std::FILE* f, basic_string_view<Char> fmt,
47fd5c32 Poul Sander 2024-10-05 08:44 605
                     typename vprintf_args<Char>::type args) -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 606
  auto buf = basic_memory_buffer<Char>();
47fd5c32 Poul Sander 2024-10-05 08:44 607
  detail::vprintf(buf, fmt, args);
47fd5c32 Poul Sander 2024-10-05 08:44 608
  size_t size = buf.size();
47fd5c32 Poul Sander 2024-10-05 08:44 609
  return std::fwrite(buf.data(), sizeof(Char), size, f) < size
47fd5c32 Poul Sander 2024-10-05 08:44 610
             ? -1
47fd5c32 Poul Sander 2024-10-05 08:44 611
             : static_cast<int>(size);
47fd5c32 Poul Sander 2024-10-05 08:44 612
}
47fd5c32 Poul Sander 2024-10-05 08:44 613
47fd5c32 Poul Sander 2024-10-05 08:44 614
/**
47fd5c32 Poul Sander 2024-10-05 08:44 615
 * Formats `args` according to specifications in `fmt` and writes the output
47fd5c32 Poul Sander 2024-10-05 08:44 616
 * to `f`.
47fd5c32 Poul Sander 2024-10-05 08:44 617
 *
47fd5c32 Poul Sander 2024-10-05 08:44 618
 * **Example**:
47fd5c32 Poul Sander 2024-10-05 08:44 619
 *
47fd5c32 Poul Sander 2024-10-05 08:44 620
 *     fmt::fprintf(stderr, "Don't %s!", "panic");
47fd5c32 Poul Sander 2024-10-05 08:44 621
 */
47fd5c32 Poul Sander 2024-10-05 08:44 622
template <typename S, typename... T, typename Char = char_t<S>>
47fd5c32 Poul Sander 2024-10-05 08:44 623
inline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 624
  return vfprintf(f, detail::to_string_view(fmt),
47fd5c32 Poul Sander 2024-10-05 08:44 625
                  make_printf_args<Char>(args...));
47fd5c32 Poul Sander 2024-10-05 08:44 626
}
47fd5c32 Poul Sander 2024-10-05 08:44 627
47fd5c32 Poul Sander 2024-10-05 08:44 628
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 629
FMT_DEPRECATED inline auto vprintf(basic_string_view<Char> fmt,
47fd5c32 Poul Sander 2024-10-05 08:44 630
                                   typename vprintf_args<Char>::type args)
47fd5c32 Poul Sander 2024-10-05 08:44 631
    -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 632
  return vfprintf(stdout, fmt, args);
47fd5c32 Poul Sander 2024-10-05 08:44 633
}
47fd5c32 Poul Sander 2024-10-05 08:44 634
47fd5c32 Poul Sander 2024-10-05 08:44 635
/**
47fd5c32 Poul Sander 2024-10-05 08:44 636
 * Formats `args` according to specifications in `fmt` and writes the output
47fd5c32 Poul Sander 2024-10-05 08:44 637
 * to `stdout`.
47fd5c32 Poul Sander 2024-10-05 08:44 638
 *
47fd5c32 Poul Sander 2024-10-05 08:44 639
 * **Example**:
47fd5c32 Poul Sander 2024-10-05 08:44 640
 *
47fd5c32 Poul Sander 2024-10-05 08:44 641
 *   fmt::printf("Elapsed time: %.2f seconds", 1.23);
47fd5c32 Poul Sander 2024-10-05 08:44 642
 */
47fd5c32 Poul Sander 2024-10-05 08:44 643
template <typename... T>
47fd5c32 Poul Sander 2024-10-05 08:44 644
inline auto printf(string_view fmt, const T&... args) -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 645
  return vfprintf(stdout, fmt, make_printf_args(args...));
47fd5c32 Poul Sander 2024-10-05 08:44 646
}
47fd5c32 Poul Sander 2024-10-05 08:44 647
template <typename... T>
47fd5c32 Poul Sander 2024-10-05 08:44 648
FMT_DEPRECATED inline auto printf(basic_string_view<wchar_t> fmt,
47fd5c32 Poul Sander 2024-10-05 08:44 649
                                  const T&... args) -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 650
  return vfprintf(stdout, fmt, make_printf_args<wchar_t>(args...));
47fd5c32 Poul Sander 2024-10-05 08:44 651
}
47fd5c32 Poul Sander 2024-10-05 08:44 652
47fd5c32 Poul Sander 2024-10-05 08:44 653
FMT_END_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 654
FMT_END_NAMESPACE
47fd5c32 Poul Sander 2024-10-05 08:44 655
47fd5c32 Poul Sander 2024-10-05 08:44 656
#endif  // FMT_PRINTF_H_
1970-01-01 00:00 657