git repos / blockattack-game

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

normal view · raw

47fd5c32 Poul Sander 2024-10-05 08:44 1
// Formatting library for C++ - the base API for char/UTF-8
47fd5c32 Poul Sander 2024-10-05 08:44 2
//
47fd5c32 Poul Sander 2024-10-05 08:44 3
// Copyright (c) 2012 - present, 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_BASE_H_
47fd5c32 Poul Sander 2024-10-05 08:44 9
#define FMT_BASE_H_
47fd5c32 Poul Sander 2024-10-05 08:44 10
47fd5c32 Poul Sander 2024-10-05 08:44 11
#if defined(FMT_IMPORT_STD) && !defined(FMT_MODULE)
47fd5c32 Poul Sander 2024-10-05 08:44 12
#  define FMT_MODULE
47fd5c32 Poul Sander 2024-10-05 08:44 13
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 14
47fd5c32 Poul Sander 2024-10-05 08:44 15
#ifndef FMT_MODULE
47fd5c32 Poul Sander 2024-10-05 08:44 16
#  include <limits.h>  // CHAR_BIT
47fd5c32 Poul Sander 2024-10-05 08:44 17
#  include <stdio.h>   // FILE
47fd5c32 Poul Sander 2024-10-05 08:44 18
#  include <string.h>  // strlen
47fd5c32 Poul Sander 2024-10-05 08:44 19
47fd5c32 Poul Sander 2024-10-05 08:44 20
// <cstddef> is also included transitively from <type_traits>.
47fd5c32 Poul Sander 2024-10-05 08:44 21
#  include <cstddef>      // std::byte
47fd5c32 Poul Sander 2024-10-05 08:44 22
#  include <type_traits>  // std::enable_if
47fd5c32 Poul Sander 2024-10-05 08:44 23
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 24
47fd5c32 Poul Sander 2024-10-05 08:44 25
// The fmt library version in the form major * 10000 + minor * 100 + patch.
47fd5c32 Poul Sander 2024-10-05 08:44 26
#define FMT_VERSION 110002
47fd5c32 Poul Sander 2024-10-05 08:44 27
47fd5c32 Poul Sander 2024-10-05 08:44 28
// Detect compiler versions.
47fd5c32 Poul Sander 2024-10-05 08:44 29
#if defined(__clang__) && !defined(__ibmxl__)
47fd5c32 Poul Sander 2024-10-05 08:44 30
#  define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
47fd5c32 Poul Sander 2024-10-05 08:44 31
#else
47fd5c32 Poul Sander 2024-10-05 08:44 32
#  define FMT_CLANG_VERSION 0
47fd5c32 Poul Sander 2024-10-05 08:44 33
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 34
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
47fd5c32 Poul Sander 2024-10-05 08:44 35
#  define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
47fd5c32 Poul Sander 2024-10-05 08:44 36
#else
47fd5c32 Poul Sander 2024-10-05 08:44 37
#  define FMT_GCC_VERSION 0
47fd5c32 Poul Sander 2024-10-05 08:44 38
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 39
#if defined(__ICL)
47fd5c32 Poul Sander 2024-10-05 08:44 40
#  define FMT_ICC_VERSION __ICL
47fd5c32 Poul Sander 2024-10-05 08:44 41
#elif defined(__INTEL_COMPILER)
47fd5c32 Poul Sander 2024-10-05 08:44 42
#  define FMT_ICC_VERSION __INTEL_COMPILER
47fd5c32 Poul Sander 2024-10-05 08:44 43
#else
47fd5c32 Poul Sander 2024-10-05 08:44 44
#  define FMT_ICC_VERSION 0
47fd5c32 Poul Sander 2024-10-05 08:44 45
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 46
#if defined(_MSC_VER)
47fd5c32 Poul Sander 2024-10-05 08:44 47
#  define FMT_MSC_VERSION _MSC_VER
47fd5c32 Poul Sander 2024-10-05 08:44 48
#else
47fd5c32 Poul Sander 2024-10-05 08:44 49
#  define FMT_MSC_VERSION 0
47fd5c32 Poul Sander 2024-10-05 08:44 50
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 51
47fd5c32 Poul Sander 2024-10-05 08:44 52
// Detect standard library versions.
47fd5c32 Poul Sander 2024-10-05 08:44 53
#ifdef _GLIBCXX_RELEASE
47fd5c32 Poul Sander 2024-10-05 08:44 54
#  define FMT_GLIBCXX_RELEASE _GLIBCXX_RELEASE
47fd5c32 Poul Sander 2024-10-05 08:44 55
#else
47fd5c32 Poul Sander 2024-10-05 08:44 56
#  define FMT_GLIBCXX_RELEASE 0
47fd5c32 Poul Sander 2024-10-05 08:44 57
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 58
#ifdef _LIBCPP_VERSION
47fd5c32 Poul Sander 2024-10-05 08:44 59
#  define FMT_LIBCPP_VERSION _LIBCPP_VERSION
47fd5c32 Poul Sander 2024-10-05 08:44 60
#else
47fd5c32 Poul Sander 2024-10-05 08:44 61
#  define FMT_LIBCPP_VERSION 0
47fd5c32 Poul Sander 2024-10-05 08:44 62
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 63
47fd5c32 Poul Sander 2024-10-05 08:44 64
#ifdef _MSVC_LANG
47fd5c32 Poul Sander 2024-10-05 08:44 65
#  define FMT_CPLUSPLUS _MSVC_LANG
47fd5c32 Poul Sander 2024-10-05 08:44 66
#else
47fd5c32 Poul Sander 2024-10-05 08:44 67
#  define FMT_CPLUSPLUS __cplusplus
47fd5c32 Poul Sander 2024-10-05 08:44 68
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 69
47fd5c32 Poul Sander 2024-10-05 08:44 70
// Detect __has_*.
47fd5c32 Poul Sander 2024-10-05 08:44 71
#ifdef __has_feature
47fd5c32 Poul Sander 2024-10-05 08:44 72
#  define FMT_HAS_FEATURE(x) __has_feature(x)
47fd5c32 Poul Sander 2024-10-05 08:44 73
#else
47fd5c32 Poul Sander 2024-10-05 08:44 74
#  define FMT_HAS_FEATURE(x) 0
47fd5c32 Poul Sander 2024-10-05 08:44 75
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 76
#ifdef __has_include
47fd5c32 Poul Sander 2024-10-05 08:44 77
#  define FMT_HAS_INCLUDE(x) __has_include(x)
47fd5c32 Poul Sander 2024-10-05 08:44 78
#else
47fd5c32 Poul Sander 2024-10-05 08:44 79
#  define FMT_HAS_INCLUDE(x) 0
47fd5c32 Poul Sander 2024-10-05 08:44 80
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 81
#ifdef __has_cpp_attribute
47fd5c32 Poul Sander 2024-10-05 08:44 82
#  define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
47fd5c32 Poul Sander 2024-10-05 08:44 83
#else
47fd5c32 Poul Sander 2024-10-05 08:44 84
#  define FMT_HAS_CPP_ATTRIBUTE(x) 0
47fd5c32 Poul Sander 2024-10-05 08:44 85
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 86
47fd5c32 Poul Sander 2024-10-05 08:44 87
#define FMT_HAS_CPP14_ATTRIBUTE(attribute) \
47fd5c32 Poul Sander 2024-10-05 08:44 88
  (FMT_CPLUSPLUS >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute))
47fd5c32 Poul Sander 2024-10-05 08:44 89
47fd5c32 Poul Sander 2024-10-05 08:44 90
#define FMT_HAS_CPP17_ATTRIBUTE(attribute) \
47fd5c32 Poul Sander 2024-10-05 08:44 91
  (FMT_CPLUSPLUS >= 201703L && FMT_HAS_CPP_ATTRIBUTE(attribute))
47fd5c32 Poul Sander 2024-10-05 08:44 92
47fd5c32 Poul Sander 2024-10-05 08:44 93
// Detect C++14 relaxed constexpr.
47fd5c32 Poul Sander 2024-10-05 08:44 94
#ifdef FMT_USE_CONSTEXPR
47fd5c32 Poul Sander 2024-10-05 08:44 95
// Use the provided definition.
47fd5c32 Poul Sander 2024-10-05 08:44 96
#elif FMT_GCC_VERSION >= 600 && FMT_CPLUSPLUS >= 201402L
47fd5c32 Poul Sander 2024-10-05 08:44 97
// GCC only allows throw in constexpr since version 6:
47fd5c32 Poul Sander 2024-10-05 08:44 98
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67371.
47fd5c32 Poul Sander 2024-10-05 08:44 99
#  define FMT_USE_CONSTEXPR 1
47fd5c32 Poul Sander 2024-10-05 08:44 100
#elif FMT_ICC_VERSION
47fd5c32 Poul Sander 2024-10-05 08:44 101
#  define FMT_USE_CONSTEXPR 0  // https://github.com/fmtlib/fmt/issues/1628
47fd5c32 Poul Sander 2024-10-05 08:44 102
#elif FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VERSION >= 1912
47fd5c32 Poul Sander 2024-10-05 08:44 103
#  define FMT_USE_CONSTEXPR 1
47fd5c32 Poul Sander 2024-10-05 08:44 104
#else
47fd5c32 Poul Sander 2024-10-05 08:44 105
#  define FMT_USE_CONSTEXPR 0
47fd5c32 Poul Sander 2024-10-05 08:44 106
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 107
#if FMT_USE_CONSTEXPR
47fd5c32 Poul Sander 2024-10-05 08:44 108
#  define FMT_CONSTEXPR constexpr
47fd5c32 Poul Sander 2024-10-05 08:44 109
#else
47fd5c32 Poul Sander 2024-10-05 08:44 110
#  define FMT_CONSTEXPR
47fd5c32 Poul Sander 2024-10-05 08:44 111
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 112
47fd5c32 Poul Sander 2024-10-05 08:44 113
// Detect consteval, C++20 constexpr extensions and std::is_constant_evaluated.
47fd5c32 Poul Sander 2024-10-05 08:44 114
#if !defined(__cpp_lib_is_constant_evaluated)
47fd5c32 Poul Sander 2024-10-05 08:44 115
#  define FMT_USE_CONSTEVAL 0
47fd5c32 Poul Sander 2024-10-05 08:44 116
#elif FMT_CPLUSPLUS < 201709L
47fd5c32 Poul Sander 2024-10-05 08:44 117
#  define FMT_USE_CONSTEVAL 0
47fd5c32 Poul Sander 2024-10-05 08:44 118
#elif FMT_GLIBCXX_RELEASE && FMT_GLIBCXX_RELEASE < 10
47fd5c32 Poul Sander 2024-10-05 08:44 119
#  define FMT_USE_CONSTEVAL 0
47fd5c32 Poul Sander 2024-10-05 08:44 120
#elif FMT_LIBCPP_VERSION && FMT_LIBCPP_VERSION < 10000
47fd5c32 Poul Sander 2024-10-05 08:44 121
#  define FMT_USE_CONSTEVAL 0
47fd5c32 Poul Sander 2024-10-05 08:44 122
#elif defined(__apple_build_version__) && __apple_build_version__ < 14000029L
47fd5c32 Poul Sander 2024-10-05 08:44 123
#  define FMT_USE_CONSTEVAL 0  // consteval is broken in Apple clang < 14.
47fd5c32 Poul Sander 2024-10-05 08:44 124
#elif FMT_MSC_VERSION && FMT_MSC_VERSION < 1929
47fd5c32 Poul Sander 2024-10-05 08:44 125
#  define FMT_USE_CONSTEVAL 0  // consteval is broken in MSVC VS2019 < 16.10.
47fd5c32 Poul Sander 2024-10-05 08:44 126
#elif defined(__cpp_consteval)
47fd5c32 Poul Sander 2024-10-05 08:44 127
#  define FMT_USE_CONSTEVAL 1
47fd5c32 Poul Sander 2024-10-05 08:44 128
#elif FMT_GCC_VERSION >= 1002 || FMT_CLANG_VERSION >= 1101
47fd5c32 Poul Sander 2024-10-05 08:44 129
#  define FMT_USE_CONSTEVAL 1
47fd5c32 Poul Sander 2024-10-05 08:44 130
#else
47fd5c32 Poul Sander 2024-10-05 08:44 131
#  define FMT_USE_CONSTEVAL 0
47fd5c32 Poul Sander 2024-10-05 08:44 132
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 133
#if FMT_USE_CONSTEVAL
47fd5c32 Poul Sander 2024-10-05 08:44 134
#  define FMT_CONSTEVAL consteval
47fd5c32 Poul Sander 2024-10-05 08:44 135
#  define FMT_CONSTEXPR20 constexpr
47fd5c32 Poul Sander 2024-10-05 08:44 136
#else
47fd5c32 Poul Sander 2024-10-05 08:44 137
#  define FMT_CONSTEVAL
47fd5c32 Poul Sander 2024-10-05 08:44 138
#  define FMT_CONSTEXPR20
47fd5c32 Poul Sander 2024-10-05 08:44 139
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 140
47fd5c32 Poul Sander 2024-10-05 08:44 141
#if defined(FMT_USE_NONTYPE_TEMPLATE_ARGS)
47fd5c32 Poul Sander 2024-10-05 08:44 142
// Use the provided definition.
47fd5c32 Poul Sander 2024-10-05 08:44 143
#elif defined(__NVCOMPILER)
47fd5c32 Poul Sander 2024-10-05 08:44 144
#  define FMT_USE_NONTYPE_TEMPLATE_ARGS 0
47fd5c32 Poul Sander 2024-10-05 08:44 145
#elif FMT_GCC_VERSION >= 903 && FMT_CPLUSPLUS >= 201709L
47fd5c32 Poul Sander 2024-10-05 08:44 146
#  define FMT_USE_NONTYPE_TEMPLATE_ARGS 1
47fd5c32 Poul Sander 2024-10-05 08:44 147
#elif defined(__cpp_nontype_template_args) && \
47fd5c32 Poul Sander 2024-10-05 08:44 148
    __cpp_nontype_template_args >= 201911L
47fd5c32 Poul Sander 2024-10-05 08:44 149
#  define FMT_USE_NONTYPE_TEMPLATE_ARGS 1
47fd5c32 Poul Sander 2024-10-05 08:44 150
#elif FMT_CLANG_VERSION >= 1200 && FMT_CPLUSPLUS >= 202002L
47fd5c32 Poul Sander 2024-10-05 08:44 151
#  define FMT_USE_NONTYPE_TEMPLATE_ARGS 1
47fd5c32 Poul Sander 2024-10-05 08:44 152
#else
47fd5c32 Poul Sander 2024-10-05 08:44 153
#  define FMT_USE_NONTYPE_TEMPLATE_ARGS 0
47fd5c32 Poul Sander 2024-10-05 08:44 154
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 155
47fd5c32 Poul Sander 2024-10-05 08:44 156
#ifdef FMT_USE_CONCEPTS
47fd5c32 Poul Sander 2024-10-05 08:44 157
// Use the provided definition.
47fd5c32 Poul Sander 2024-10-05 08:44 158
#elif defined(__cpp_concepts)
47fd5c32 Poul Sander 2024-10-05 08:44 159
#  define FMT_USE_CONCEPTS 1
47fd5c32 Poul Sander 2024-10-05 08:44 160
#else
47fd5c32 Poul Sander 2024-10-05 08:44 161
#  define FMT_USE_CONCEPTS 0
47fd5c32 Poul Sander 2024-10-05 08:44 162
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 163
47fd5c32 Poul Sander 2024-10-05 08:44 164
// Check if exceptions are disabled.
47fd5c32 Poul Sander 2024-10-05 08:44 165
#ifdef FMT_EXCEPTIONS
47fd5c32 Poul Sander 2024-10-05 08:44 166
// Use the provided definition.
47fd5c32 Poul Sander 2024-10-05 08:44 167
#elif defined(__GNUC__) && !defined(__EXCEPTIONS)
47fd5c32 Poul Sander 2024-10-05 08:44 168
#  define FMT_EXCEPTIONS 0
47fd5c32 Poul Sander 2024-10-05 08:44 169
#elif FMT_MSC_VERSION && !_HAS_EXCEPTIONS
47fd5c32 Poul Sander 2024-10-05 08:44 170
#  define FMT_EXCEPTIONS 0
47fd5c32 Poul Sander 2024-10-05 08:44 171
#else
47fd5c32 Poul Sander 2024-10-05 08:44 172
#  define FMT_EXCEPTIONS 1
47fd5c32 Poul Sander 2024-10-05 08:44 173
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 174
#if FMT_EXCEPTIONS
47fd5c32 Poul Sander 2024-10-05 08:44 175
#  define FMT_TRY try
47fd5c32 Poul Sander 2024-10-05 08:44 176
#  define FMT_CATCH(x) catch (x)
47fd5c32 Poul Sander 2024-10-05 08:44 177
#else
47fd5c32 Poul Sander 2024-10-05 08:44 178
#  define FMT_TRY if (true)
47fd5c32 Poul Sander 2024-10-05 08:44 179
#  define FMT_CATCH(x) if (false)
47fd5c32 Poul Sander 2024-10-05 08:44 180
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 181
47fd5c32 Poul Sander 2024-10-05 08:44 182
#if FMT_HAS_CPP17_ATTRIBUTE(fallthrough)
47fd5c32 Poul Sander 2024-10-05 08:44 183
#  define FMT_FALLTHROUGH [[fallthrough]]
47fd5c32 Poul Sander 2024-10-05 08:44 184
#elif defined(__clang__)
47fd5c32 Poul Sander 2024-10-05 08:44 185
#  define FMT_FALLTHROUGH [[clang::fallthrough]]
47fd5c32 Poul Sander 2024-10-05 08:44 186
#elif FMT_GCC_VERSION >= 700 && \
47fd5c32 Poul Sander 2024-10-05 08:44 187
    (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520)
47fd5c32 Poul Sander 2024-10-05 08:44 188
#  define FMT_FALLTHROUGH [[gnu::fallthrough]]
47fd5c32 Poul Sander 2024-10-05 08:44 189
#else
47fd5c32 Poul Sander 2024-10-05 08:44 190
#  define FMT_FALLTHROUGH
47fd5c32 Poul Sander 2024-10-05 08:44 191
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 192
47fd5c32 Poul Sander 2024-10-05 08:44 193
// Disable [[noreturn]] on MSVC/NVCC because of bogus unreachable code warnings.
47fd5c32 Poul Sander 2024-10-05 08:44 194
#if FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VERSION && !defined(__NVCC__)
47fd5c32 Poul Sander 2024-10-05 08:44 195
#  define FMT_NORETURN [[noreturn]]
47fd5c32 Poul Sander 2024-10-05 08:44 196
#else
47fd5c32 Poul Sander 2024-10-05 08:44 197
#  define FMT_NORETURN
47fd5c32 Poul Sander 2024-10-05 08:44 198
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 199
47fd5c32 Poul Sander 2024-10-05 08:44 200
#ifndef FMT_NODISCARD
47fd5c32 Poul Sander 2024-10-05 08:44 201
#  if FMT_HAS_CPP17_ATTRIBUTE(nodiscard)
47fd5c32 Poul Sander 2024-10-05 08:44 202
#    define FMT_NODISCARD [[nodiscard]]
47fd5c32 Poul Sander 2024-10-05 08:44 203
#  else
47fd5c32 Poul Sander 2024-10-05 08:44 204
#    define FMT_NODISCARD
47fd5c32 Poul Sander 2024-10-05 08:44 205
#  endif
47fd5c32 Poul Sander 2024-10-05 08:44 206
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 207
47fd5c32 Poul Sander 2024-10-05 08:44 208
#ifdef FMT_DEPRECATED
47fd5c32 Poul Sander 2024-10-05 08:44 209
// Use the provided definition.
47fd5c32 Poul Sander 2024-10-05 08:44 210
#elif FMT_HAS_CPP14_ATTRIBUTE(deprecated)
47fd5c32 Poul Sander 2024-10-05 08:44 211
#  define FMT_DEPRECATED [[deprecated]]
47fd5c32 Poul Sander 2024-10-05 08:44 212
#else
47fd5c32 Poul Sander 2024-10-05 08:44 213
#  define FMT_DEPRECATED /* deprecated */
47fd5c32 Poul Sander 2024-10-05 08:44 214
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 215
47fd5c32 Poul Sander 2024-10-05 08:44 216
#ifdef FMT_INLINE
47fd5c32 Poul Sander 2024-10-05 08:44 217
// Use the provided definition.
47fd5c32 Poul Sander 2024-10-05 08:44 218
#elif FMT_GCC_VERSION || FMT_CLANG_VERSION
47fd5c32 Poul Sander 2024-10-05 08:44 219
#  define FMT_ALWAYS_INLINE inline __attribute__((always_inline))
47fd5c32 Poul Sander 2024-10-05 08:44 220
#else
47fd5c32 Poul Sander 2024-10-05 08:44 221
#  define FMT_ALWAYS_INLINE inline
47fd5c32 Poul Sander 2024-10-05 08:44 222
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 223
// A version of FMT_INLINE to prevent code bloat in debug mode.
47fd5c32 Poul Sander 2024-10-05 08:44 224
#ifdef NDEBUG
47fd5c32 Poul Sander 2024-10-05 08:44 225
#  define FMT_INLINE FMT_ALWAYS_INLINE
47fd5c32 Poul Sander 2024-10-05 08:44 226
#else
47fd5c32 Poul Sander 2024-10-05 08:44 227
#  define FMT_INLINE inline
47fd5c32 Poul Sander 2024-10-05 08:44 228
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 229
47fd5c32 Poul Sander 2024-10-05 08:44 230
#if FMT_GCC_VERSION || FMT_CLANG_VERSION
47fd5c32 Poul Sander 2024-10-05 08:44 231
#  define FMT_VISIBILITY(value) __attribute__((visibility(value)))
47fd5c32 Poul Sander 2024-10-05 08:44 232
#else
47fd5c32 Poul Sander 2024-10-05 08:44 233
#  define FMT_VISIBILITY(value)
47fd5c32 Poul Sander 2024-10-05 08:44 234
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 235
47fd5c32 Poul Sander 2024-10-05 08:44 236
#ifndef FMT_GCC_PRAGMA
47fd5c32 Poul Sander 2024-10-05 08:44 237
// Workaround a _Pragma bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59884
47fd5c32 Poul Sander 2024-10-05 08:44 238
// and an nvhpc warning: https://github.com/fmtlib/fmt/pull/2582.
47fd5c32 Poul Sander 2024-10-05 08:44 239
#  if FMT_GCC_VERSION >= 504 && !defined(__NVCOMPILER)
47fd5c32 Poul Sander 2024-10-05 08:44 240
#    define FMT_GCC_PRAGMA(arg) _Pragma(arg)
47fd5c32 Poul Sander 2024-10-05 08:44 241
#  else
47fd5c32 Poul Sander 2024-10-05 08:44 242
#    define FMT_GCC_PRAGMA(arg)
47fd5c32 Poul Sander 2024-10-05 08:44 243
#  endif
47fd5c32 Poul Sander 2024-10-05 08:44 244
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 245
47fd5c32 Poul Sander 2024-10-05 08:44 246
// GCC < 5 requires this-> in decltype.
47fd5c32 Poul Sander 2024-10-05 08:44 247
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500
47fd5c32 Poul Sander 2024-10-05 08:44 248
#  define FMT_DECLTYPE_THIS this->
47fd5c32 Poul Sander 2024-10-05 08:44 249
#else
47fd5c32 Poul Sander 2024-10-05 08:44 250
#  define FMT_DECLTYPE_THIS
47fd5c32 Poul Sander 2024-10-05 08:44 251
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 252
47fd5c32 Poul Sander 2024-10-05 08:44 253
#if FMT_MSC_VERSION
47fd5c32 Poul Sander 2024-10-05 08:44 254
#  define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__))
47fd5c32 Poul Sander 2024-10-05 08:44 255
#  define FMT_UNCHECKED_ITERATOR(It) \
47fd5c32 Poul Sander 2024-10-05 08:44 256
    using _Unchecked_type = It  // Mark iterator as checked.
47fd5c32 Poul Sander 2024-10-05 08:44 257
#else
47fd5c32 Poul Sander 2024-10-05 08:44 258
#  define FMT_MSC_WARNING(...)
47fd5c32 Poul Sander 2024-10-05 08:44 259
#  define FMT_UNCHECKED_ITERATOR(It) using unchecked_type = It
47fd5c32 Poul Sander 2024-10-05 08:44 260
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 261
47fd5c32 Poul Sander 2024-10-05 08:44 262
#ifndef FMT_BEGIN_NAMESPACE
47fd5c32 Poul Sander 2024-10-05 08:44 263
#  define FMT_BEGIN_NAMESPACE \
47fd5c32 Poul Sander 2024-10-05 08:44 264
    namespace fmt {           \
47fd5c32 Poul Sander 2024-10-05 08:44 265
    inline namespace v11 {
47fd5c32 Poul Sander 2024-10-05 08:44 266
#  define FMT_END_NAMESPACE \
47fd5c32 Poul Sander 2024-10-05 08:44 267
    }                       \
47fd5c32 Poul Sander 2024-10-05 08:44 268
    }
47fd5c32 Poul Sander 2024-10-05 08:44 269
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 270
47fd5c32 Poul Sander 2024-10-05 08:44 271
#ifndef FMT_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 272
#  define FMT_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 273
#  define FMT_BEGIN_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 274
#  define FMT_END_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 275
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 276
47fd5c32 Poul Sander 2024-10-05 08:44 277
#if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
47fd5c32 Poul Sander 2024-10-05 08:44 278
#  if defined(FMT_LIB_EXPORT)
47fd5c32 Poul Sander 2024-10-05 08:44 279
#    define FMT_API __declspec(dllexport)
47fd5c32 Poul Sander 2024-10-05 08:44 280
#  elif defined(FMT_SHARED)
47fd5c32 Poul Sander 2024-10-05 08:44 281
#    define FMT_API __declspec(dllimport)
47fd5c32 Poul Sander 2024-10-05 08:44 282
#  endif
47fd5c32 Poul Sander 2024-10-05 08:44 283
#elif defined(FMT_LIB_EXPORT) || defined(FMT_SHARED)
47fd5c32 Poul Sander 2024-10-05 08:44 284
#  define FMT_API FMT_VISIBILITY("default")
47fd5c32 Poul Sander 2024-10-05 08:44 285
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 286
#ifndef FMT_API
47fd5c32 Poul Sander 2024-10-05 08:44 287
#  define FMT_API
47fd5c32 Poul Sander 2024-10-05 08:44 288
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 289
47fd5c32 Poul Sander 2024-10-05 08:44 290
#ifndef FMT_UNICODE
47fd5c32 Poul Sander 2024-10-05 08:44 291
#  define FMT_UNICODE 1
47fd5c32 Poul Sander 2024-10-05 08:44 292
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 293
47fd5c32 Poul Sander 2024-10-05 08:44 294
// Check if rtti is available.
47fd5c32 Poul Sander 2024-10-05 08:44 295
#ifndef FMT_USE_RTTI
47fd5c32 Poul Sander 2024-10-05 08:44 296
// __RTTI is for EDG compilers. _CPPRTTI is for MSVC.
47fd5c32 Poul Sander 2024-10-05 08:44 297
#  if defined(__GXX_RTTI) || FMT_HAS_FEATURE(cxx_rtti) || defined(_CPPRTTI) || \
47fd5c32 Poul Sander 2024-10-05 08:44 298
      defined(__INTEL_RTTI__) || defined(__RTTI)
47fd5c32 Poul Sander 2024-10-05 08:44 299
#    define FMT_USE_RTTI 1
47fd5c32 Poul Sander 2024-10-05 08:44 300
#  else
47fd5c32 Poul Sander 2024-10-05 08:44 301
#    define FMT_USE_RTTI 0
47fd5c32 Poul Sander 2024-10-05 08:44 302
#  endif
47fd5c32 Poul Sander 2024-10-05 08:44 303
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 304
47fd5c32 Poul Sander 2024-10-05 08:44 305
#define FMT_FWD(...) static_cast<decltype(__VA_ARGS__)&&>(__VA_ARGS__)
47fd5c32 Poul Sander 2024-10-05 08:44 306
47fd5c32 Poul Sander 2024-10-05 08:44 307
// Enable minimal optimizations for more compact code in debug mode.
47fd5c32 Poul Sander 2024-10-05 08:44 308
FMT_GCC_PRAGMA("GCC push_options")
47fd5c32 Poul Sander 2024-10-05 08:44 309
#if !defined(__OPTIMIZE__) && !defined(__CUDACC__)
47fd5c32 Poul Sander 2024-10-05 08:44 310
FMT_GCC_PRAGMA("GCC optimize(\"Og\")")
47fd5c32 Poul Sander 2024-10-05 08:44 311
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 312
47fd5c32 Poul Sander 2024-10-05 08:44 313
FMT_BEGIN_NAMESPACE
47fd5c32 Poul Sander 2024-10-05 08:44 314
47fd5c32 Poul Sander 2024-10-05 08:44 315
// Implementations of enable_if_t and other metafunctions for older systems.
47fd5c32 Poul Sander 2024-10-05 08:44 316
template <bool B, typename T = void>
47fd5c32 Poul Sander 2024-10-05 08:44 317
using enable_if_t = typename std::enable_if<B, T>::type;
47fd5c32 Poul Sander 2024-10-05 08:44 318
template <bool B, typename T, typename F>
47fd5c32 Poul Sander 2024-10-05 08:44 319
using conditional_t = typename std::conditional<B, T, F>::type;
47fd5c32 Poul Sander 2024-10-05 08:44 320
template <bool B> using bool_constant = std::integral_constant<bool, B>;
47fd5c32 Poul Sander 2024-10-05 08:44 321
template <typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 322
using remove_reference_t = typename std::remove_reference<T>::type;
47fd5c32 Poul Sander 2024-10-05 08:44 323
template <typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 324
using remove_const_t = typename std::remove_const<T>::type;
47fd5c32 Poul Sander 2024-10-05 08:44 325
template <typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 326
using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type;
47fd5c32 Poul Sander 2024-10-05 08:44 327
template <typename T> struct type_identity {
47fd5c32 Poul Sander 2024-10-05 08:44 328
  using type = T;
47fd5c32 Poul Sander 2024-10-05 08:44 329
};
47fd5c32 Poul Sander 2024-10-05 08:44 330
template <typename T> using type_identity_t = typename type_identity<T>::type;
47fd5c32 Poul Sander 2024-10-05 08:44 331
template <typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 332
using make_unsigned_t = typename std::make_unsigned<T>::type;
47fd5c32 Poul Sander 2024-10-05 08:44 333
template <typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 334
using underlying_t = typename std::underlying_type<T>::type;
47fd5c32 Poul Sander 2024-10-05 08:44 335
47fd5c32 Poul Sander 2024-10-05 08:44 336
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500
47fd5c32 Poul Sander 2024-10-05 08:44 337
// A workaround for gcc 4.8 to make void_t work in a SFINAE context.
47fd5c32 Poul Sander 2024-10-05 08:44 338
template <typename...> struct void_t_impl {
47fd5c32 Poul Sander 2024-10-05 08:44 339
  using type = void;
47fd5c32 Poul Sander 2024-10-05 08:44 340
};
47fd5c32 Poul Sander 2024-10-05 08:44 341
template <typename... T> using void_t = typename void_t_impl<T...>::type;
47fd5c32 Poul Sander 2024-10-05 08:44 342
#else
47fd5c32 Poul Sander 2024-10-05 08:44 343
template <typename...> using void_t = void;
47fd5c32 Poul Sander 2024-10-05 08:44 344
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 345
47fd5c32 Poul Sander 2024-10-05 08:44 346
struct monostate {
47fd5c32 Poul Sander 2024-10-05 08:44 347
  constexpr monostate() {}
47fd5c32 Poul Sander 2024-10-05 08:44 348
};
47fd5c32 Poul Sander 2024-10-05 08:44 349
47fd5c32 Poul Sander 2024-10-05 08:44 350
// An enable_if helper to be used in template parameters which results in much
47fd5c32 Poul Sander 2024-10-05 08:44 351
// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed
47fd5c32 Poul Sander 2024-10-05 08:44 352
// to workaround a bug in MSVC 2019 (see #1140 and #1186).
47fd5c32 Poul Sander 2024-10-05 08:44 353
#ifdef FMT_DOC
47fd5c32 Poul Sander 2024-10-05 08:44 354
#  define FMT_ENABLE_IF(...)
47fd5c32 Poul Sander 2024-10-05 08:44 355
#else
47fd5c32 Poul Sander 2024-10-05 08:44 356
#  define FMT_ENABLE_IF(...) fmt::enable_if_t<(__VA_ARGS__), int> = 0
47fd5c32 Poul Sander 2024-10-05 08:44 357
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 358
47fd5c32 Poul Sander 2024-10-05 08:44 359
// This is defined in base.h instead of format.h to avoid injecting in std.
47fd5c32 Poul Sander 2024-10-05 08:44 360
// It is a template to avoid undesirable implicit conversions to std::byte.
47fd5c32 Poul Sander 2024-10-05 08:44 361
#ifdef __cpp_lib_byte
47fd5c32 Poul Sander 2024-10-05 08:44 362
template <typename T, FMT_ENABLE_IF(std::is_same<T, std::byte>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 363
inline auto format_as(T b) -> unsigned char {
47fd5c32 Poul Sander 2024-10-05 08:44 364
  return static_cast<unsigned char>(b);
47fd5c32 Poul Sander 2024-10-05 08:44 365
}
47fd5c32 Poul Sander 2024-10-05 08:44 366
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 367
47fd5c32 Poul Sander 2024-10-05 08:44 368
namespace detail {
47fd5c32 Poul Sander 2024-10-05 08:44 369
// Suppresses "unused variable" warnings with the method described in
47fd5c32 Poul Sander 2024-10-05 08:44 370
// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/.
47fd5c32 Poul Sander 2024-10-05 08:44 371
// (void)var does not work on many Intel compilers.
47fd5c32 Poul Sander 2024-10-05 08:44 372
template <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {}
47fd5c32 Poul Sander 2024-10-05 08:44 373
47fd5c32 Poul Sander 2024-10-05 08:44 374
constexpr auto is_constant_evaluated(bool default_value = false) noexcept
47fd5c32 Poul Sander 2024-10-05 08:44 375
    -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 376
// Workaround for incompatibility between libstdc++ consteval-based
47fd5c32 Poul Sander 2024-10-05 08:44 377
// std::is_constant_evaluated() implementation and clang-14:
47fd5c32 Poul Sander 2024-10-05 08:44 378
// https://github.com/fmtlib/fmt/issues/3247.
47fd5c32 Poul Sander 2024-10-05 08:44 379
#if FMT_CPLUSPLUS >= 202002L && FMT_GLIBCXX_RELEASE >= 12 && \
47fd5c32 Poul Sander 2024-10-05 08:44 380
    (FMT_CLANG_VERSION >= 1400 && FMT_CLANG_VERSION < 1500)
47fd5c32 Poul Sander 2024-10-05 08:44 381
  ignore_unused(default_value);
47fd5c32 Poul Sander 2024-10-05 08:44 382
  return __builtin_is_constant_evaluated();
47fd5c32 Poul Sander 2024-10-05 08:44 383
#elif defined(__cpp_lib_is_constant_evaluated)
47fd5c32 Poul Sander 2024-10-05 08:44 384
  ignore_unused(default_value);
47fd5c32 Poul Sander 2024-10-05 08:44 385
  return std::is_constant_evaluated();
47fd5c32 Poul Sander 2024-10-05 08:44 386
#else
47fd5c32 Poul Sander 2024-10-05 08:44 387
  return default_value;
47fd5c32 Poul Sander 2024-10-05 08:44 388
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 389
}
47fd5c32 Poul Sander 2024-10-05 08:44 390
47fd5c32 Poul Sander 2024-10-05 08:44 391
// Suppresses "conditional expression is constant" warnings.
47fd5c32 Poul Sander 2024-10-05 08:44 392
template <typename T> constexpr auto const_check(T value) -> T { return value; }
47fd5c32 Poul Sander 2024-10-05 08:44 393
47fd5c32 Poul Sander 2024-10-05 08:44 394
FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
47fd5c32 Poul Sander 2024-10-05 08:44 395
                                      const char* message);
47fd5c32 Poul Sander 2024-10-05 08:44 396
47fd5c32 Poul Sander 2024-10-05 08:44 397
#if defined(FMT_ASSERT)
47fd5c32 Poul Sander 2024-10-05 08:44 398
// Use the provided definition.
47fd5c32 Poul Sander 2024-10-05 08:44 399
#elif defined(NDEBUG)
47fd5c32 Poul Sander 2024-10-05 08:44 400
// FMT_ASSERT is not empty to avoid -Wempty-body.
47fd5c32 Poul Sander 2024-10-05 08:44 401
#  define FMT_ASSERT(condition, message) \
47fd5c32 Poul Sander 2024-10-05 08:44 402
    fmt::detail::ignore_unused((condition), (message))
47fd5c32 Poul Sander 2024-10-05 08:44 403
#else
47fd5c32 Poul Sander 2024-10-05 08:44 404
#  define FMT_ASSERT(condition, message)                                    \
47fd5c32 Poul Sander 2024-10-05 08:44 405
    ((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \
47fd5c32 Poul Sander 2024-10-05 08:44 406
         ? (void)0                                                          \
47fd5c32 Poul Sander 2024-10-05 08:44 407
         : fmt::detail::assert_fail(__FILE__, __LINE__, (message)))
47fd5c32 Poul Sander 2024-10-05 08:44 408
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 409
47fd5c32 Poul Sander 2024-10-05 08:44 410
#ifdef FMT_USE_INT128
47fd5c32 Poul Sander 2024-10-05 08:44 411
// Do nothing.
47fd5c32 Poul Sander 2024-10-05 08:44 412
#elif defined(__SIZEOF_INT128__) && !defined(__NVCC__) && \
47fd5c32 Poul Sander 2024-10-05 08:44 413
    !(FMT_CLANG_VERSION && FMT_MSC_VERSION)
47fd5c32 Poul Sander 2024-10-05 08:44 414
#  define FMT_USE_INT128 1
47fd5c32 Poul Sander 2024-10-05 08:44 415
using int128_opt = __int128_t;  // An optional native 128-bit integer.
47fd5c32 Poul Sander 2024-10-05 08:44 416
using uint128_opt = __uint128_t;
47fd5c32 Poul Sander 2024-10-05 08:44 417
template <typename T> inline auto convert_for_visit(T value) -> T {
47fd5c32 Poul Sander 2024-10-05 08:44 418
  return value;
47fd5c32 Poul Sander 2024-10-05 08:44 419
}
47fd5c32 Poul Sander 2024-10-05 08:44 420
#else
47fd5c32 Poul Sander 2024-10-05 08:44 421
#  define FMT_USE_INT128 0
47fd5c32 Poul Sander 2024-10-05 08:44 422
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 423
#if !FMT_USE_INT128
47fd5c32 Poul Sander 2024-10-05 08:44 424
enum class int128_opt {};
47fd5c32 Poul Sander 2024-10-05 08:44 425
enum class uint128_opt {};
47fd5c32 Poul Sander 2024-10-05 08:44 426
// Reduce template instantiations.
47fd5c32 Poul Sander 2024-10-05 08:44 427
template <typename T> auto convert_for_visit(T) -> monostate { return {}; }
47fd5c32 Poul Sander 2024-10-05 08:44 428
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 429
47fd5c32 Poul Sander 2024-10-05 08:44 430
// Casts a nonnegative integer to unsigned.
47fd5c32 Poul Sander 2024-10-05 08:44 431
template <typename Int>
47fd5c32 Poul Sander 2024-10-05 08:44 432
FMT_CONSTEXPR auto to_unsigned(Int value) -> make_unsigned_t<Int> {
47fd5c32 Poul Sander 2024-10-05 08:44 433
  FMT_ASSERT(std::is_unsigned<Int>::value || value >= 0, "negative value");
47fd5c32 Poul Sander 2024-10-05 08:44 434
  return static_cast<make_unsigned_t<Int>>(value);
47fd5c32 Poul Sander 2024-10-05 08:44 435
}
47fd5c32 Poul Sander 2024-10-05 08:44 436
47fd5c32 Poul Sander 2024-10-05 08:44 437
// A heuristic to detect std::string and std::[experimental::]string_view.
47fd5c32 Poul Sander 2024-10-05 08:44 438
// It is mainly used to avoid dependency on <[experimental/]string_view>.
47fd5c32 Poul Sander 2024-10-05 08:44 439
template <typename T, typename Enable = void>
47fd5c32 Poul Sander 2024-10-05 08:44 440
struct is_std_string_like : std::false_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 441
template <typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 442
struct is_std_string_like<T, void_t<decltype(std::declval<T>().find_first_of(
47fd5c32 Poul Sander 2024-10-05 08:44 443
                                 typename T::value_type(), 0))>>
47fd5c32 Poul Sander 2024-10-05 08:44 444
    : std::is_convertible<decltype(std::declval<T>().data()),
47fd5c32 Poul Sander 2024-10-05 08:44 445
                          const typename T::value_type*> {};
47fd5c32 Poul Sander 2024-10-05 08:44 446
47fd5c32 Poul Sander 2024-10-05 08:44 447
// Returns true iff the literal encoding is UTF-8.
47fd5c32 Poul Sander 2024-10-05 08:44 448
constexpr auto is_utf8_enabled() -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 449
  // Avoid an MSVC sign extension bug: https://github.com/fmtlib/fmt/pull/2297.
47fd5c32 Poul Sander 2024-10-05 08:44 450
  using uchar = unsigned char;
47fd5c32 Poul Sander 2024-10-05 08:44 451
  return sizeof("\u00A7") == 3 && uchar("\u00A7"[0]) == 0xC2 &&
47fd5c32 Poul Sander 2024-10-05 08:44 452
         uchar("\u00A7"[1]) == 0xA7;
47fd5c32 Poul Sander 2024-10-05 08:44 453
}
47fd5c32 Poul Sander 2024-10-05 08:44 454
constexpr auto use_utf8() -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 455
  return !FMT_MSC_VERSION || is_utf8_enabled();
47fd5c32 Poul Sander 2024-10-05 08:44 456
}
47fd5c32 Poul Sander 2024-10-05 08:44 457
47fd5c32 Poul Sander 2024-10-05 08:44 458
static_assert(!FMT_UNICODE || use_utf8(),
47fd5c32 Poul Sander 2024-10-05 08:44 459
              "Unicode support requires compiling with /utf-8");
47fd5c32 Poul Sander 2024-10-05 08:44 460
47fd5c32 Poul Sander 2024-10-05 08:44 461
template <typename Char> FMT_CONSTEXPR auto length(const Char* s) -> size_t {
47fd5c32 Poul Sander 2024-10-05 08:44 462
  size_t len = 0;
47fd5c32 Poul Sander 2024-10-05 08:44 463
  while (*s++) ++len;
47fd5c32 Poul Sander 2024-10-05 08:44 464
  return len;
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
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 468
FMT_CONSTEXPR auto compare(const Char* s1, const Char* s2, std::size_t n)
47fd5c32 Poul Sander 2024-10-05 08:44 469
    -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 470
  if (!is_constant_evaluated() && sizeof(Char) == 1) return memcmp(s1, s2, n);
47fd5c32 Poul Sander 2024-10-05 08:44 471
  for (; n != 0; ++s1, ++s2, --n) {
47fd5c32 Poul Sander 2024-10-05 08:44 472
    if (*s1 < *s2) return -1;
47fd5c32 Poul Sander 2024-10-05 08:44 473
    if (*s1 > *s2) return 1;
47fd5c32 Poul Sander 2024-10-05 08:44 474
  }
47fd5c32 Poul Sander 2024-10-05 08:44 475
  return 0;
47fd5c32 Poul Sander 2024-10-05 08:44 476
}
47fd5c32 Poul Sander 2024-10-05 08:44 477
47fd5c32 Poul Sander 2024-10-05 08:44 478
namespace adl {
47fd5c32 Poul Sander 2024-10-05 08:44 479
using namespace std;
47fd5c32 Poul Sander 2024-10-05 08:44 480
47fd5c32 Poul Sander 2024-10-05 08:44 481
template <typename Container>
47fd5c32 Poul Sander 2024-10-05 08:44 482
auto invoke_back_inserter()
47fd5c32 Poul Sander 2024-10-05 08:44 483
    -> decltype(back_inserter(std::declval<Container&>()));
47fd5c32 Poul Sander 2024-10-05 08:44 484
}  // namespace adl
47fd5c32 Poul Sander 2024-10-05 08:44 485
47fd5c32 Poul Sander 2024-10-05 08:44 486
template <typename It, typename Enable = std::true_type>
47fd5c32 Poul Sander 2024-10-05 08:44 487
struct is_back_insert_iterator : std::false_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 488
47fd5c32 Poul Sander 2024-10-05 08:44 489
template <typename It>
47fd5c32 Poul Sander 2024-10-05 08:44 490
struct is_back_insert_iterator<
47fd5c32 Poul Sander 2024-10-05 08:44 491
    It, bool_constant<std::is_same<
47fd5c32 Poul Sander 2024-10-05 08:44 492
            decltype(adl::invoke_back_inserter<typename It::container_type>()),
47fd5c32 Poul Sander 2024-10-05 08:44 493
            It>::value>> : std::true_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 494
47fd5c32 Poul Sander 2024-10-05 08:44 495
// Extracts a reference to the container from *insert_iterator.
47fd5c32 Poul Sander 2024-10-05 08:44 496
template <typename OutputIt>
47fd5c32 Poul Sander 2024-10-05 08:44 497
inline auto get_container(OutputIt it) -> typename OutputIt::container_type& {
47fd5c32 Poul Sander 2024-10-05 08:44 498
  struct accessor : OutputIt {
47fd5c32 Poul Sander 2024-10-05 08:44 499
    accessor(OutputIt base) : OutputIt(base) {}
47fd5c32 Poul Sander 2024-10-05 08:44 500
    using OutputIt::container;
47fd5c32 Poul Sander 2024-10-05 08:44 501
  };
47fd5c32 Poul Sander 2024-10-05 08:44 502
  return *accessor(it).container;
47fd5c32 Poul Sander 2024-10-05 08:44 503
}
47fd5c32 Poul Sander 2024-10-05 08:44 504
}  // namespace detail
47fd5c32 Poul Sander 2024-10-05 08:44 505
47fd5c32 Poul Sander 2024-10-05 08:44 506
// Checks whether T is a container with contiguous storage.
47fd5c32 Poul Sander 2024-10-05 08:44 507
template <typename T> struct is_contiguous : std::false_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 508
47fd5c32 Poul Sander 2024-10-05 08:44 509
/**
47fd5c32 Poul Sander 2024-10-05 08:44 510
 * An implementation of `std::basic_string_view` for pre-C++17. It provides a
47fd5c32 Poul Sander 2024-10-05 08:44 511
 * subset of the API. `fmt::basic_string_view` is used for format strings even
47fd5c32 Poul Sander 2024-10-05 08:44 512
 * if `std::basic_string_view` is available to prevent issues when a library is
47fd5c32 Poul Sander 2024-10-05 08:44 513
 * compiled with a different `-std` option than the client code (which is not
47fd5c32 Poul Sander 2024-10-05 08:44 514
 * recommended).
47fd5c32 Poul Sander 2024-10-05 08:44 515
 */
47fd5c32 Poul Sander 2024-10-05 08:44 516
FMT_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 517
template <typename Char> class basic_string_view {
47fd5c32 Poul Sander 2024-10-05 08:44 518
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 519
  const Char* data_;
47fd5c32 Poul Sander 2024-10-05 08:44 520
  size_t size_;
47fd5c32 Poul Sander 2024-10-05 08:44 521
47fd5c32 Poul Sander 2024-10-05 08:44 522
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 523
  using value_type = Char;
47fd5c32 Poul Sander 2024-10-05 08:44 524
  using iterator = const Char*;
47fd5c32 Poul Sander 2024-10-05 08:44 525
47fd5c32 Poul Sander 2024-10-05 08:44 526
  constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {}
47fd5c32 Poul Sander 2024-10-05 08:44 527
47fd5c32 Poul Sander 2024-10-05 08:44 528
  /// Constructs a string reference object from a C string and a size.
47fd5c32 Poul Sander 2024-10-05 08:44 529
  constexpr basic_string_view(const Char* s, size_t count) noexcept
47fd5c32 Poul Sander 2024-10-05 08:44 530
      : data_(s), size_(count) {}
47fd5c32 Poul Sander 2024-10-05 08:44 531
47fd5c32 Poul Sander 2024-10-05 08:44 532
  constexpr basic_string_view(std::nullptr_t) = delete;
47fd5c32 Poul Sander 2024-10-05 08:44 533
47fd5c32 Poul Sander 2024-10-05 08:44 534
  /// Constructs a string reference object from a C string.
47fd5c32 Poul Sander 2024-10-05 08:44 535
  FMT_CONSTEXPR20
47fd5c32 Poul Sander 2024-10-05 08:44 536
  basic_string_view(const Char* s)
47fd5c32 Poul Sander 2024-10-05 08:44 537
      : data_(s),
47fd5c32 Poul Sander 2024-10-05 08:44 538
        size_(detail::const_check(std::is_same<Char, char>::value &&
47fd5c32 Poul Sander 2024-10-05 08:44 539
                                  !detail::is_constant_evaluated(false))
47fd5c32 Poul Sander 2024-10-05 08:44 540
                  ? strlen(reinterpret_cast<const char*>(s))
47fd5c32 Poul Sander 2024-10-05 08:44 541
                  : detail::length(s)) {}
47fd5c32 Poul Sander 2024-10-05 08:44 542
47fd5c32 Poul Sander 2024-10-05 08:44 543
  /// Constructs a string reference from a `std::basic_string` or a
47fd5c32 Poul Sander 2024-10-05 08:44 544
  /// `std::basic_string_view` object.
47fd5c32 Poul Sander 2024-10-05 08:44 545
  template <typename S,
47fd5c32 Poul Sander 2024-10-05 08:44 546
            FMT_ENABLE_IF(detail::is_std_string_like<S>::value&& std::is_same<
47fd5c32 Poul Sander 2024-10-05 08:44 547
                          typename S::value_type, Char>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 548
  FMT_CONSTEXPR basic_string_view(const S& s) noexcept
47fd5c32 Poul Sander 2024-10-05 08:44 549
      : data_(s.data()), size_(s.size()) {}
47fd5c32 Poul Sander 2024-10-05 08:44 550
47fd5c32 Poul Sander 2024-10-05 08:44 551
  /// Returns a pointer to the string data.
47fd5c32 Poul Sander 2024-10-05 08:44 552
  constexpr auto data() const noexcept -> const Char* { return data_; }
47fd5c32 Poul Sander 2024-10-05 08:44 553
47fd5c32 Poul Sander 2024-10-05 08:44 554
  /// Returns the string size.
47fd5c32 Poul Sander 2024-10-05 08:44 555
  constexpr auto size() const noexcept -> size_t { return size_; }
47fd5c32 Poul Sander 2024-10-05 08:44 556
47fd5c32 Poul Sander 2024-10-05 08:44 557
  constexpr auto begin() const noexcept -> iterator { return data_; }
47fd5c32 Poul Sander 2024-10-05 08:44 558
  constexpr auto end() const noexcept -> iterator { return data_ + size_; }
47fd5c32 Poul Sander 2024-10-05 08:44 559
47fd5c32 Poul Sander 2024-10-05 08:44 560
  constexpr auto operator[](size_t pos) const noexcept -> const Char& {
47fd5c32 Poul Sander 2024-10-05 08:44 561
    return data_[pos];
47fd5c32 Poul Sander 2024-10-05 08:44 562
  }
47fd5c32 Poul Sander 2024-10-05 08:44 563
47fd5c32 Poul Sander 2024-10-05 08:44 564
  FMT_CONSTEXPR void remove_prefix(size_t n) noexcept {
47fd5c32 Poul Sander 2024-10-05 08:44 565
    data_ += n;
47fd5c32 Poul Sander 2024-10-05 08:44 566
    size_ -= n;
47fd5c32 Poul Sander 2024-10-05 08:44 567
  }
47fd5c32 Poul Sander 2024-10-05 08:44 568
47fd5c32 Poul Sander 2024-10-05 08:44 569
  FMT_CONSTEXPR auto starts_with(basic_string_view<Char> sv) const noexcept
47fd5c32 Poul Sander 2024-10-05 08:44 570
      -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 571
    return size_ >= sv.size_ && detail::compare(data_, sv.data_, sv.size_) == 0;
47fd5c32 Poul Sander 2024-10-05 08:44 572
  }
47fd5c32 Poul Sander 2024-10-05 08:44 573
  FMT_CONSTEXPR auto starts_with(Char c) const noexcept -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 574
    return size_ >= 1 && *data_ == c;
47fd5c32 Poul Sander 2024-10-05 08:44 575
  }
47fd5c32 Poul Sander 2024-10-05 08:44 576
  FMT_CONSTEXPR auto starts_with(const Char* s) const -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 577
    return starts_with(basic_string_view<Char>(s));
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
  // Lexicographically compare this string reference to other.
47fd5c32 Poul Sander 2024-10-05 08:44 581
  FMT_CONSTEXPR auto compare(basic_string_view other) const -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 582
    size_t str_size = size_ < other.size_ ? size_ : other.size_;
47fd5c32 Poul Sander 2024-10-05 08:44 583
    int result = detail::compare(data_, other.data_, str_size);
47fd5c32 Poul Sander 2024-10-05 08:44 584
    if (result == 0)
47fd5c32 Poul Sander 2024-10-05 08:44 585
      result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
47fd5c32 Poul Sander 2024-10-05 08:44 586
    return result;
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
  FMT_CONSTEXPR friend auto operator==(basic_string_view lhs,
47fd5c32 Poul Sander 2024-10-05 08:44 590
                                       basic_string_view rhs) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 591
    return lhs.compare(rhs) == 0;
47fd5c32 Poul Sander 2024-10-05 08:44 592
  }
47fd5c32 Poul Sander 2024-10-05 08:44 593
  friend auto operator!=(basic_string_view lhs, basic_string_view rhs) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 594
    return lhs.compare(rhs) != 0;
47fd5c32 Poul Sander 2024-10-05 08:44 595
  }
47fd5c32 Poul Sander 2024-10-05 08:44 596
  friend auto operator<(basic_string_view lhs, basic_string_view rhs) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 597
    return lhs.compare(rhs) < 0;
47fd5c32 Poul Sander 2024-10-05 08:44 598
  }
47fd5c32 Poul Sander 2024-10-05 08:44 599
  friend auto operator<=(basic_string_view lhs, basic_string_view rhs) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 600
    return lhs.compare(rhs) <= 0;
47fd5c32 Poul Sander 2024-10-05 08:44 601
  }
47fd5c32 Poul Sander 2024-10-05 08:44 602
  friend auto operator>(basic_string_view lhs, basic_string_view rhs) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 603
    return lhs.compare(rhs) > 0;
47fd5c32 Poul Sander 2024-10-05 08:44 604
  }
47fd5c32 Poul Sander 2024-10-05 08:44 605
  friend auto operator>=(basic_string_view lhs, basic_string_view rhs) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 606
    return lhs.compare(rhs) >= 0;
47fd5c32 Poul Sander 2024-10-05 08:44 607
  }
47fd5c32 Poul Sander 2024-10-05 08:44 608
};
47fd5c32 Poul Sander 2024-10-05 08:44 609
47fd5c32 Poul Sander 2024-10-05 08:44 610
FMT_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 611
using string_view = basic_string_view<char>;
47fd5c32 Poul Sander 2024-10-05 08:44 612
47fd5c32 Poul Sander 2024-10-05 08:44 613
/// Specifies if `T` is a character type. Can be specialized by users.
47fd5c32 Poul Sander 2024-10-05 08:44 614
FMT_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 615
template <typename T> struct is_char : std::false_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 616
template <> struct is_char<char> : std::true_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 617
47fd5c32 Poul Sander 2024-10-05 08:44 618
namespace detail {
47fd5c32 Poul Sander 2024-10-05 08:44 619
47fd5c32 Poul Sander 2024-10-05 08:44 620
// Constructs fmt::basic_string_view<Char> from types implicitly convertible
47fd5c32 Poul Sander 2024-10-05 08:44 621
// to it, deducing Char. Explicitly convertible types such as the ones returned
47fd5c32 Poul Sander 2024-10-05 08:44 622
// from FMT_STRING are intentionally excluded.
47fd5c32 Poul Sander 2024-10-05 08:44 623
template <typename Char, FMT_ENABLE_IF(is_char<Char>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 624
constexpr auto to_string_view(const Char* s) -> basic_string_view<Char> {
47fd5c32 Poul Sander 2024-10-05 08:44 625
  return s;
47fd5c32 Poul Sander 2024-10-05 08:44 626
}
47fd5c32 Poul Sander 2024-10-05 08:44 627
template <typename T, FMT_ENABLE_IF(is_std_string_like<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 628
constexpr auto to_string_view(const T& s)
47fd5c32 Poul Sander 2024-10-05 08:44 629
    -> basic_string_view<typename T::value_type> {
47fd5c32 Poul Sander 2024-10-05 08:44 630
  return s;
47fd5c32 Poul Sander 2024-10-05 08:44 631
}
47fd5c32 Poul Sander 2024-10-05 08:44 632
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 633
constexpr auto to_string_view(basic_string_view<Char> s)
47fd5c32 Poul Sander 2024-10-05 08:44 634
    -> basic_string_view<Char> {
47fd5c32 Poul Sander 2024-10-05 08:44 635
  return s;
47fd5c32 Poul Sander 2024-10-05 08:44 636
}
47fd5c32 Poul Sander 2024-10-05 08:44 637
47fd5c32 Poul Sander 2024-10-05 08:44 638
template <typename T, typename Enable = void>
47fd5c32 Poul Sander 2024-10-05 08:44 639
struct has_to_string_view : std::false_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 640
// detail:: is intentional since to_string_view is not an extension point.
47fd5c32 Poul Sander 2024-10-05 08:44 641
template <typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 642
struct has_to_string_view<
47fd5c32 Poul Sander 2024-10-05 08:44 643
    T, void_t<decltype(detail::to_string_view(std::declval<T>()))>>
47fd5c32 Poul Sander 2024-10-05 08:44 644
    : std::true_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 645
47fd5c32 Poul Sander 2024-10-05 08:44 646
template <typename Char, Char... C> struct string_literal {
47fd5c32 Poul Sander 2024-10-05 08:44 647
  static constexpr Char value[sizeof...(C)] = {C...};
47fd5c32 Poul Sander 2024-10-05 08:44 648
  constexpr operator basic_string_view<Char>() const {
47fd5c32 Poul Sander 2024-10-05 08:44 649
    return {value, sizeof...(C)};
47fd5c32 Poul Sander 2024-10-05 08:44 650
  }
47fd5c32 Poul Sander 2024-10-05 08:44 651
};
47fd5c32 Poul Sander 2024-10-05 08:44 652
#if FMT_CPLUSPLUS < 201703L
47fd5c32 Poul Sander 2024-10-05 08:44 653
template <typename Char, Char... C>
47fd5c32 Poul Sander 2024-10-05 08:44 654
constexpr Char string_literal<Char, C...>::value[sizeof...(C)];
47fd5c32 Poul Sander 2024-10-05 08:44 655
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 656
47fd5c32 Poul Sander 2024-10-05 08:44 657
enum class type {
47fd5c32 Poul Sander 2024-10-05 08:44 658
  none_type,
47fd5c32 Poul Sander 2024-10-05 08:44 659
  // Integer types should go first,
47fd5c32 Poul Sander 2024-10-05 08:44 660
  int_type,
47fd5c32 Poul Sander 2024-10-05 08:44 661
  uint_type,
47fd5c32 Poul Sander 2024-10-05 08:44 662
  long_long_type,
47fd5c32 Poul Sander 2024-10-05 08:44 663
  ulong_long_type,
47fd5c32 Poul Sander 2024-10-05 08:44 664
  int128_type,
47fd5c32 Poul Sander 2024-10-05 08:44 665
  uint128_type,
47fd5c32 Poul Sander 2024-10-05 08:44 666
  bool_type,
47fd5c32 Poul Sander 2024-10-05 08:44 667
  char_type,
47fd5c32 Poul Sander 2024-10-05 08:44 668
  last_integer_type = char_type,
47fd5c32 Poul Sander 2024-10-05 08:44 669
  // followed by floating-point types.
47fd5c32 Poul Sander 2024-10-05 08:44 670
  float_type,
47fd5c32 Poul Sander 2024-10-05 08:44 671
  double_type,
47fd5c32 Poul Sander 2024-10-05 08:44 672
  long_double_type,
47fd5c32 Poul Sander 2024-10-05 08:44 673
  last_numeric_type = long_double_type,
47fd5c32 Poul Sander 2024-10-05 08:44 674
  cstring_type,
47fd5c32 Poul Sander 2024-10-05 08:44 675
  string_type,
47fd5c32 Poul Sander 2024-10-05 08:44 676
  pointer_type,
47fd5c32 Poul Sander 2024-10-05 08:44 677
  custom_type
47fd5c32 Poul Sander 2024-10-05 08:44 678
};
47fd5c32 Poul Sander 2024-10-05 08:44 679
47fd5c32 Poul Sander 2024-10-05 08:44 680
// Maps core type T to the corresponding type enum constant.
47fd5c32 Poul Sander 2024-10-05 08:44 681
template <typename T, typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 682
struct type_constant : std::integral_constant<type, type::custom_type> {};
47fd5c32 Poul Sander 2024-10-05 08:44 683
47fd5c32 Poul Sander 2024-10-05 08:44 684
#define FMT_TYPE_CONSTANT(Type, constant) \
47fd5c32 Poul Sander 2024-10-05 08:44 685
  template <typename Char>                \
47fd5c32 Poul Sander 2024-10-05 08:44 686
  struct type_constant<Type, Char>        \
47fd5c32 Poul Sander 2024-10-05 08:44 687
      : std::integral_constant<type, type::constant> {}
47fd5c32 Poul Sander 2024-10-05 08:44 688
47fd5c32 Poul Sander 2024-10-05 08:44 689
FMT_TYPE_CONSTANT(int, int_type);
47fd5c32 Poul Sander 2024-10-05 08:44 690
FMT_TYPE_CONSTANT(unsigned, uint_type);
47fd5c32 Poul Sander 2024-10-05 08:44 691
FMT_TYPE_CONSTANT(long long, long_long_type);
47fd5c32 Poul Sander 2024-10-05 08:44 692
FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type);
47fd5c32 Poul Sander 2024-10-05 08:44 693
FMT_TYPE_CONSTANT(int128_opt, int128_type);
47fd5c32 Poul Sander 2024-10-05 08:44 694
FMT_TYPE_CONSTANT(uint128_opt, uint128_type);
47fd5c32 Poul Sander 2024-10-05 08:44 695
FMT_TYPE_CONSTANT(bool, bool_type);
47fd5c32 Poul Sander 2024-10-05 08:44 696
FMT_TYPE_CONSTANT(Char, char_type);
47fd5c32 Poul Sander 2024-10-05 08:44 697
FMT_TYPE_CONSTANT(float, float_type);
47fd5c32 Poul Sander 2024-10-05 08:44 698
FMT_TYPE_CONSTANT(double, double_type);
47fd5c32 Poul Sander 2024-10-05 08:44 699
FMT_TYPE_CONSTANT(long double, long_double_type);
47fd5c32 Poul Sander 2024-10-05 08:44 700
FMT_TYPE_CONSTANT(const Char*, cstring_type);
47fd5c32 Poul Sander 2024-10-05 08:44 701
FMT_TYPE_CONSTANT(basic_string_view<Char>, string_type);
47fd5c32 Poul Sander 2024-10-05 08:44 702
FMT_TYPE_CONSTANT(const void*, pointer_type);
47fd5c32 Poul Sander 2024-10-05 08:44 703
47fd5c32 Poul Sander 2024-10-05 08:44 704
constexpr auto is_integral_type(type t) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 705
  return t > type::none_type && t <= type::last_integer_type;
47fd5c32 Poul Sander 2024-10-05 08:44 706
}
47fd5c32 Poul Sander 2024-10-05 08:44 707
constexpr auto is_arithmetic_type(type t) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 708
  return t > type::none_type && t <= type::last_numeric_type;
47fd5c32 Poul Sander 2024-10-05 08:44 709
}
47fd5c32 Poul Sander 2024-10-05 08:44 710
47fd5c32 Poul Sander 2024-10-05 08:44 711
constexpr auto set(type rhs) -> int { return 1 << static_cast<int>(rhs); }
47fd5c32 Poul Sander 2024-10-05 08:44 712
constexpr auto in(type t, int set) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 713
  return ((set >> static_cast<int>(t)) & 1) != 0;
47fd5c32 Poul Sander 2024-10-05 08:44 714
}
47fd5c32 Poul Sander 2024-10-05 08:44 715
47fd5c32 Poul Sander 2024-10-05 08:44 716
// Bitsets of types.
47fd5c32 Poul Sander 2024-10-05 08:44 717
enum {
47fd5c32 Poul Sander 2024-10-05 08:44 718
  sint_set =
47fd5c32 Poul Sander 2024-10-05 08:44 719
      set(type::int_type) | set(type::long_long_type) | set(type::int128_type),
47fd5c32 Poul Sander 2024-10-05 08:44 720
  uint_set = set(type::uint_type) | set(type::ulong_long_type) |
47fd5c32 Poul Sander 2024-10-05 08:44 721
             set(type::uint128_type),
47fd5c32 Poul Sander 2024-10-05 08:44 722
  bool_set = set(type::bool_type),
47fd5c32 Poul Sander 2024-10-05 08:44 723
  char_set = set(type::char_type),
47fd5c32 Poul Sander 2024-10-05 08:44 724
  float_set = set(type::float_type) | set(type::double_type) |
47fd5c32 Poul Sander 2024-10-05 08:44 725
              set(type::long_double_type),
47fd5c32 Poul Sander 2024-10-05 08:44 726
  string_set = set(type::string_type),
47fd5c32 Poul Sander 2024-10-05 08:44 727
  cstring_set = set(type::cstring_type),
47fd5c32 Poul Sander 2024-10-05 08:44 728
  pointer_set = set(type::pointer_type)
47fd5c32 Poul Sander 2024-10-05 08:44 729
};
47fd5c32 Poul Sander 2024-10-05 08:44 730
}  // namespace detail
47fd5c32 Poul Sander 2024-10-05 08:44 731
47fd5c32 Poul Sander 2024-10-05 08:44 732
/// Reports a format error at compile time or, via a `format_error` exception,
47fd5c32 Poul Sander 2024-10-05 08:44 733
/// at runtime.
47fd5c32 Poul Sander 2024-10-05 08:44 734
// This function is intentionally not constexpr to give a compile-time error.
47fd5c32 Poul Sander 2024-10-05 08:44 735
FMT_NORETURN FMT_API void report_error(const char* message);
47fd5c32 Poul Sander 2024-10-05 08:44 736
47fd5c32 Poul Sander 2024-10-05 08:44 737
FMT_DEPRECATED FMT_NORETURN inline void throw_format_error(
47fd5c32 Poul Sander 2024-10-05 08:44 738
    const char* message) {
47fd5c32 Poul Sander 2024-10-05 08:44 739
  report_error(message);
47fd5c32 Poul Sander 2024-10-05 08:44 740
}
47fd5c32 Poul Sander 2024-10-05 08:44 741
47fd5c32 Poul Sander 2024-10-05 08:44 742
/// String's character (code unit) type.
47fd5c32 Poul Sander 2024-10-05 08:44 743
template <typename S,
47fd5c32 Poul Sander 2024-10-05 08:44 744
          typename V = decltype(detail::to_string_view(std::declval<S>()))>
47fd5c32 Poul Sander 2024-10-05 08:44 745
using char_t = typename V::value_type;
47fd5c32 Poul Sander 2024-10-05 08:44 746
47fd5c32 Poul Sander 2024-10-05 08:44 747
/**
47fd5c32 Poul Sander 2024-10-05 08:44 748
 * Parsing context consisting of a format string range being parsed and an
47fd5c32 Poul Sander 2024-10-05 08:44 749
 * argument counter for automatic indexing.
47fd5c32 Poul Sander 2024-10-05 08:44 750
 * You can use the `format_parse_context` type alias for `char` instead.
47fd5c32 Poul Sander 2024-10-05 08:44 751
 */
47fd5c32 Poul Sander 2024-10-05 08:44 752
FMT_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 753
template <typename Char> class basic_format_parse_context {
47fd5c32 Poul Sander 2024-10-05 08:44 754
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 755
  basic_string_view<Char> format_str_;
47fd5c32 Poul Sander 2024-10-05 08:44 756
  int next_arg_id_;
47fd5c32 Poul Sander 2024-10-05 08:44 757
47fd5c32 Poul Sander 2024-10-05 08:44 758
  FMT_CONSTEXPR void do_check_arg_id(int id);
47fd5c32 Poul Sander 2024-10-05 08:44 759
47fd5c32 Poul Sander 2024-10-05 08:44 760
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 761
  using char_type = Char;
47fd5c32 Poul Sander 2024-10-05 08:44 762
  using iterator = const Char*;
47fd5c32 Poul Sander 2024-10-05 08:44 763
47fd5c32 Poul Sander 2024-10-05 08:44 764
  explicit constexpr basic_format_parse_context(
47fd5c32 Poul Sander 2024-10-05 08:44 765
      basic_string_view<Char> format_str, int next_arg_id = 0)
47fd5c32 Poul Sander 2024-10-05 08:44 766
      : format_str_(format_str), next_arg_id_(next_arg_id) {}
47fd5c32 Poul Sander 2024-10-05 08:44 767
47fd5c32 Poul Sander 2024-10-05 08:44 768
  /// Returns an iterator to the beginning of the format string range being
47fd5c32 Poul Sander 2024-10-05 08:44 769
  /// parsed.
47fd5c32 Poul Sander 2024-10-05 08:44 770
  constexpr auto begin() const noexcept -> iterator {
47fd5c32 Poul Sander 2024-10-05 08:44 771
    return format_str_.begin();
47fd5c32 Poul Sander 2024-10-05 08:44 772
  }
47fd5c32 Poul Sander 2024-10-05 08:44 773
47fd5c32 Poul Sander 2024-10-05 08:44 774
  /// Returns an iterator past the end of the format string range being parsed.
47fd5c32 Poul Sander 2024-10-05 08:44 775
  constexpr auto end() const noexcept -> iterator { return format_str_.end(); }
47fd5c32 Poul Sander 2024-10-05 08:44 776
47fd5c32 Poul Sander 2024-10-05 08:44 777
  /// Advances the begin iterator to `it`.
47fd5c32 Poul Sander 2024-10-05 08:44 778
  FMT_CONSTEXPR void advance_to(iterator it) {
47fd5c32 Poul Sander 2024-10-05 08:44 779
    format_str_.remove_prefix(detail::to_unsigned(it - begin()));
47fd5c32 Poul Sander 2024-10-05 08:44 780
  }
47fd5c32 Poul Sander 2024-10-05 08:44 781
47fd5c32 Poul Sander 2024-10-05 08:44 782
  /// Reports an error if using the manual argument indexing; otherwise returns
47fd5c32 Poul Sander 2024-10-05 08:44 783
  /// the next argument index and switches to the automatic indexing.
47fd5c32 Poul Sander 2024-10-05 08:44 784
  FMT_CONSTEXPR auto next_arg_id() -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 785
    if (next_arg_id_ < 0) {
47fd5c32 Poul Sander 2024-10-05 08:44 786
      report_error("cannot switch from manual to automatic argument indexing");
47fd5c32 Poul Sander 2024-10-05 08:44 787
      return 0;
47fd5c32 Poul Sander 2024-10-05 08:44 788
    }
47fd5c32 Poul Sander 2024-10-05 08:44 789
    int id = next_arg_id_++;
47fd5c32 Poul Sander 2024-10-05 08:44 790
    do_check_arg_id(id);
47fd5c32 Poul Sander 2024-10-05 08:44 791
    return id;
47fd5c32 Poul Sander 2024-10-05 08:44 792
  }
47fd5c32 Poul Sander 2024-10-05 08:44 793
47fd5c32 Poul Sander 2024-10-05 08:44 794
  /// Reports an error if using the automatic argument indexing; otherwise
47fd5c32 Poul Sander 2024-10-05 08:44 795
  /// switches to the manual indexing.
47fd5c32 Poul Sander 2024-10-05 08:44 796
  FMT_CONSTEXPR void check_arg_id(int id) {
47fd5c32 Poul Sander 2024-10-05 08:44 797
    if (next_arg_id_ > 0) {
47fd5c32 Poul Sander 2024-10-05 08:44 798
      report_error("cannot switch from automatic to manual argument indexing");
47fd5c32 Poul Sander 2024-10-05 08:44 799
      return;
47fd5c32 Poul Sander 2024-10-05 08:44 800
    }
47fd5c32 Poul Sander 2024-10-05 08:44 801
    next_arg_id_ = -1;
47fd5c32 Poul Sander 2024-10-05 08:44 802
    do_check_arg_id(id);
47fd5c32 Poul Sander 2024-10-05 08:44 803
  }
47fd5c32 Poul Sander 2024-10-05 08:44 804
  FMT_CONSTEXPR void check_arg_id(basic_string_view<Char>) {
47fd5c32 Poul Sander 2024-10-05 08:44 805
    next_arg_id_ = -1;
47fd5c32 Poul Sander 2024-10-05 08:44 806
  }
47fd5c32 Poul Sander 2024-10-05 08:44 807
  FMT_CONSTEXPR void check_dynamic_spec(int arg_id);
47fd5c32 Poul Sander 2024-10-05 08:44 808
};
47fd5c32 Poul Sander 2024-10-05 08:44 809
47fd5c32 Poul Sander 2024-10-05 08:44 810
FMT_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 811
using format_parse_context = basic_format_parse_context<char>;
47fd5c32 Poul Sander 2024-10-05 08:44 812
47fd5c32 Poul Sander 2024-10-05 08:44 813
namespace detail {
47fd5c32 Poul Sander 2024-10-05 08:44 814
// A parse context with extra data used only in compile-time checks.
47fd5c32 Poul Sander 2024-10-05 08:44 815
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 816
class compile_parse_context : public basic_format_parse_context<Char> {
47fd5c32 Poul Sander 2024-10-05 08:44 817
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 818
  int num_args_;
47fd5c32 Poul Sander 2024-10-05 08:44 819
  const type* types_;
47fd5c32 Poul Sander 2024-10-05 08:44 820
  using base = basic_format_parse_context<Char>;
47fd5c32 Poul Sander 2024-10-05 08:44 821
47fd5c32 Poul Sander 2024-10-05 08:44 822
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 823
  explicit FMT_CONSTEXPR compile_parse_context(
47fd5c32 Poul Sander 2024-10-05 08:44 824
      basic_string_view<Char> format_str, int num_args, const type* types,
47fd5c32 Poul Sander 2024-10-05 08:44 825
      int next_arg_id = 0)
47fd5c32 Poul Sander 2024-10-05 08:44 826
      : base(format_str, next_arg_id), num_args_(num_args), types_(types) {}
47fd5c32 Poul Sander 2024-10-05 08:44 827
47fd5c32 Poul Sander 2024-10-05 08:44 828
  constexpr auto num_args() const -> int { return num_args_; }
47fd5c32 Poul Sander 2024-10-05 08:44 829
  constexpr auto arg_type(int id) const -> type { return types_[id]; }
47fd5c32 Poul Sander 2024-10-05 08:44 830
47fd5c32 Poul Sander 2024-10-05 08:44 831
  FMT_CONSTEXPR auto next_arg_id() -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 832
    int id = base::next_arg_id();
47fd5c32 Poul Sander 2024-10-05 08:44 833
    if (id >= num_args_) report_error("argument not found");
47fd5c32 Poul Sander 2024-10-05 08:44 834
    return id;
47fd5c32 Poul Sander 2024-10-05 08:44 835
  }
47fd5c32 Poul Sander 2024-10-05 08:44 836
47fd5c32 Poul Sander 2024-10-05 08:44 837
  FMT_CONSTEXPR void check_arg_id(int id) {
47fd5c32 Poul Sander 2024-10-05 08:44 838
    base::check_arg_id(id);
47fd5c32 Poul Sander 2024-10-05 08:44 839
    if (id >= num_args_) report_error("argument not found");
47fd5c32 Poul Sander 2024-10-05 08:44 840
  }
47fd5c32 Poul Sander 2024-10-05 08:44 841
  using base::check_arg_id;
47fd5c32 Poul Sander 2024-10-05 08:44 842
47fd5c32 Poul Sander 2024-10-05 08:44 843
  FMT_CONSTEXPR void check_dynamic_spec(int arg_id) {
47fd5c32 Poul Sander 2024-10-05 08:44 844
    detail::ignore_unused(arg_id);
47fd5c32 Poul Sander 2024-10-05 08:44 845
    if (arg_id < num_args_ && types_ && !is_integral_type(types_[arg_id]))
47fd5c32 Poul Sander 2024-10-05 08:44 846
      report_error("width/precision is not integer");
47fd5c32 Poul Sander 2024-10-05 08:44 847
  }
47fd5c32 Poul Sander 2024-10-05 08:44 848
};
47fd5c32 Poul Sander 2024-10-05 08:44 849
47fd5c32 Poul Sander 2024-10-05 08:44 850
/// A contiguous memory buffer with an optional growing ability. It is an
47fd5c32 Poul Sander 2024-10-05 08:44 851
/// internal class and shouldn't be used directly, only via `memory_buffer`.
47fd5c32 Poul Sander 2024-10-05 08:44 852
template <typename T> class buffer {
47fd5c32 Poul Sander 2024-10-05 08:44 853
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 854
  T* ptr_;
47fd5c32 Poul Sander 2024-10-05 08:44 855
  size_t size_;
47fd5c32 Poul Sander 2024-10-05 08:44 856
  size_t capacity_;
47fd5c32 Poul Sander 2024-10-05 08:44 857
47fd5c32 Poul Sander 2024-10-05 08:44 858
  using grow_fun = void (*)(buffer& buf, size_t capacity);
47fd5c32 Poul Sander 2024-10-05 08:44 859
  grow_fun grow_;
47fd5c32 Poul Sander 2024-10-05 08:44 860
47fd5c32 Poul Sander 2024-10-05 08:44 861
 protected:
47fd5c32 Poul Sander 2024-10-05 08:44 862
  // Don't initialize ptr_ since it is not accessed to save a few cycles.
47fd5c32 Poul Sander 2024-10-05 08:44 863
  FMT_MSC_WARNING(suppress : 26495)
47fd5c32 Poul Sander 2024-10-05 08:44 864
  FMT_CONSTEXPR20 buffer(grow_fun grow, size_t sz) noexcept
47fd5c32 Poul Sander 2024-10-05 08:44 865
      : size_(sz), capacity_(sz), grow_(grow) {}
47fd5c32 Poul Sander 2024-10-05 08:44 866
47fd5c32 Poul Sander 2024-10-05 08:44 867
  constexpr buffer(grow_fun grow, T* p = nullptr, size_t sz = 0,
47fd5c32 Poul Sander 2024-10-05 08:44 868
                   size_t cap = 0) noexcept
47fd5c32 Poul Sander 2024-10-05 08:44 869
      : ptr_(p), size_(sz), capacity_(cap), grow_(grow) {}
47fd5c32 Poul Sander 2024-10-05 08:44 870
47fd5c32 Poul Sander 2024-10-05 08:44 871
  FMT_CONSTEXPR20 ~buffer() = default;
47fd5c32 Poul Sander 2024-10-05 08:44 872
  buffer(buffer&&) = default;
47fd5c32 Poul Sander 2024-10-05 08:44 873
47fd5c32 Poul Sander 2024-10-05 08:44 874
  /// Sets the buffer data and capacity.
47fd5c32 Poul Sander 2024-10-05 08:44 875
  FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) noexcept {
47fd5c32 Poul Sander 2024-10-05 08:44 876
    ptr_ = buf_data;
47fd5c32 Poul Sander 2024-10-05 08:44 877
    capacity_ = buf_capacity;
47fd5c32 Poul Sander 2024-10-05 08:44 878
  }
47fd5c32 Poul Sander 2024-10-05 08:44 879
47fd5c32 Poul Sander 2024-10-05 08:44 880
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 881
  using value_type = T;
47fd5c32 Poul Sander 2024-10-05 08:44 882
  using const_reference = const T&;
47fd5c32 Poul Sander 2024-10-05 08:44 883
47fd5c32 Poul Sander 2024-10-05 08:44 884
  buffer(const buffer&) = delete;
47fd5c32 Poul Sander 2024-10-05 08:44 885
  void operator=(const buffer&) = delete;
47fd5c32 Poul Sander 2024-10-05 08:44 886
47fd5c32 Poul Sander 2024-10-05 08:44 887
  auto begin() noexcept -> T* { return ptr_; }
47fd5c32 Poul Sander 2024-10-05 08:44 888
  auto end() noexcept -> T* { return ptr_ + size_; }
47fd5c32 Poul Sander 2024-10-05 08:44 889
47fd5c32 Poul Sander 2024-10-05 08:44 890
  auto begin() const noexcept -> const T* { return ptr_; }
47fd5c32 Poul Sander 2024-10-05 08:44 891
  auto end() const noexcept -> const T* { return ptr_ + size_; }
47fd5c32 Poul Sander 2024-10-05 08:44 892
47fd5c32 Poul Sander 2024-10-05 08:44 893
  /// Returns the size of this buffer.
47fd5c32 Poul Sander 2024-10-05 08:44 894
  constexpr auto size() const noexcept -> size_t { return size_; }
47fd5c32 Poul Sander 2024-10-05 08:44 895
47fd5c32 Poul Sander 2024-10-05 08:44 896
  /// Returns the capacity of this buffer.
47fd5c32 Poul Sander 2024-10-05 08:44 897
  constexpr auto capacity() const noexcept -> size_t { return capacity_; }
47fd5c32 Poul Sander 2024-10-05 08:44 898
47fd5c32 Poul Sander 2024-10-05 08:44 899
  /// Returns a pointer to the buffer data (not null-terminated).
47fd5c32 Poul Sander 2024-10-05 08:44 900
  FMT_CONSTEXPR auto data() noexcept -> T* { return ptr_; }
47fd5c32 Poul Sander 2024-10-05 08:44 901
  FMT_CONSTEXPR auto data() const noexcept -> const T* { return ptr_; }
47fd5c32 Poul Sander 2024-10-05 08:44 902
47fd5c32 Poul Sander 2024-10-05 08:44 903
  /// Clears this buffer.
47fd5c32 Poul Sander 2024-10-05 08:44 904
  void clear() { size_ = 0; }
47fd5c32 Poul Sander 2024-10-05 08:44 905
47fd5c32 Poul Sander 2024-10-05 08:44 906
  // Tries resizing the buffer to contain `count` elements. If T is a POD type
47fd5c32 Poul Sander 2024-10-05 08:44 907
  // the new elements may not be initialized.
47fd5c32 Poul Sander 2024-10-05 08:44 908
  FMT_CONSTEXPR void try_resize(size_t count) {
47fd5c32 Poul Sander 2024-10-05 08:44 909
    try_reserve(count);
47fd5c32 Poul Sander 2024-10-05 08:44 910
    size_ = count <= capacity_ ? count : capacity_;
47fd5c32 Poul Sander 2024-10-05 08:44 911
  }
47fd5c32 Poul Sander 2024-10-05 08:44 912
47fd5c32 Poul Sander 2024-10-05 08:44 913
  // Tries increasing the buffer capacity to `new_capacity`. It can increase the
47fd5c32 Poul Sander 2024-10-05 08:44 914
  // capacity by a smaller amount than requested but guarantees there is space
47fd5c32 Poul Sander 2024-10-05 08:44 915
  // for at least one additional element either by increasing the capacity or by
47fd5c32 Poul Sander 2024-10-05 08:44 916
  // flushing the buffer if it is full.
47fd5c32 Poul Sander 2024-10-05 08:44 917
  FMT_CONSTEXPR void try_reserve(size_t new_capacity) {
47fd5c32 Poul Sander 2024-10-05 08:44 918
    if (new_capacity > capacity_) grow_(*this, new_capacity);
47fd5c32 Poul Sander 2024-10-05 08:44 919
  }
47fd5c32 Poul Sander 2024-10-05 08:44 920
47fd5c32 Poul Sander 2024-10-05 08:44 921
  FMT_CONSTEXPR void push_back(const T& value) {
47fd5c32 Poul Sander 2024-10-05 08:44 922
    try_reserve(size_ + 1);
47fd5c32 Poul Sander 2024-10-05 08:44 923
    ptr_[size_++] = value;
47fd5c32 Poul Sander 2024-10-05 08:44 924
  }
47fd5c32 Poul Sander 2024-10-05 08:44 925
47fd5c32 Poul Sander 2024-10-05 08:44 926
  /// Appends data to the end of the buffer.
47fd5c32 Poul Sander 2024-10-05 08:44 927
  template <typename U> void append(const U* begin, const U* end) {
47fd5c32 Poul Sander 2024-10-05 08:44 928
    while (begin != end) {
47fd5c32 Poul Sander 2024-10-05 08:44 929
      auto count = to_unsigned(end - begin);
47fd5c32 Poul Sander 2024-10-05 08:44 930
      try_reserve(size_ + count);
47fd5c32 Poul Sander 2024-10-05 08:44 931
      auto free_cap = capacity_ - size_;
47fd5c32 Poul Sander 2024-10-05 08:44 932
      if (free_cap < count) count = free_cap;
47fd5c32 Poul Sander 2024-10-05 08:44 933
      // A loop is faster than memcpy on small sizes.
47fd5c32 Poul Sander 2024-10-05 08:44 934
      T* out = ptr_ + size_;
47fd5c32 Poul Sander 2024-10-05 08:44 935
      for (size_t i = 0; i < count; ++i) out[i] = begin[i];
47fd5c32 Poul Sander 2024-10-05 08:44 936
      size_ += count;
47fd5c32 Poul Sander 2024-10-05 08:44 937
      begin += count;
47fd5c32 Poul Sander 2024-10-05 08:44 938
    }
47fd5c32 Poul Sander 2024-10-05 08:44 939
  }
47fd5c32 Poul Sander 2024-10-05 08:44 940
47fd5c32 Poul Sander 2024-10-05 08:44 941
  template <typename Idx> FMT_CONSTEXPR auto operator[](Idx index) -> T& {
47fd5c32 Poul Sander 2024-10-05 08:44 942
    return ptr_[index];
47fd5c32 Poul Sander 2024-10-05 08:44 943
  }
47fd5c32 Poul Sander 2024-10-05 08:44 944
  template <typename Idx>
47fd5c32 Poul Sander 2024-10-05 08:44 945
  FMT_CONSTEXPR auto operator[](Idx index) const -> const T& {
47fd5c32 Poul Sander 2024-10-05 08:44 946
    return ptr_[index];
47fd5c32 Poul Sander 2024-10-05 08:44 947
  }
47fd5c32 Poul Sander 2024-10-05 08:44 948
};
47fd5c32 Poul Sander 2024-10-05 08:44 949
47fd5c32 Poul Sander 2024-10-05 08:44 950
struct buffer_traits {
47fd5c32 Poul Sander 2024-10-05 08:44 951
  explicit buffer_traits(size_t) {}
47fd5c32 Poul Sander 2024-10-05 08:44 952
  auto count() const -> size_t { return 0; }
47fd5c32 Poul Sander 2024-10-05 08:44 953
  auto limit(size_t size) -> size_t { return size; }
47fd5c32 Poul Sander 2024-10-05 08:44 954
};
47fd5c32 Poul Sander 2024-10-05 08:44 955
47fd5c32 Poul Sander 2024-10-05 08:44 956
class fixed_buffer_traits {
47fd5c32 Poul Sander 2024-10-05 08:44 957
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 958
  size_t count_ = 0;
47fd5c32 Poul Sander 2024-10-05 08:44 959
  size_t limit_;
47fd5c32 Poul Sander 2024-10-05 08:44 960
47fd5c32 Poul Sander 2024-10-05 08:44 961
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 962
  explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
47fd5c32 Poul Sander 2024-10-05 08:44 963
  auto count() const -> size_t { return count_; }
47fd5c32 Poul Sander 2024-10-05 08:44 964
  auto limit(size_t size) -> size_t {
47fd5c32 Poul Sander 2024-10-05 08:44 965
    size_t n = limit_ > count_ ? limit_ - count_ : 0;
47fd5c32 Poul Sander 2024-10-05 08:44 966
    count_ += size;
47fd5c32 Poul Sander 2024-10-05 08:44 967
    return size < n ? size : n;
47fd5c32 Poul Sander 2024-10-05 08:44 968
  }
47fd5c32 Poul Sander 2024-10-05 08:44 969
};
47fd5c32 Poul Sander 2024-10-05 08:44 970
47fd5c32 Poul Sander 2024-10-05 08:44 971
// A buffer that writes to an output iterator when flushed.
47fd5c32 Poul Sander 2024-10-05 08:44 972
template <typename OutputIt, typename T, typename Traits = buffer_traits>
47fd5c32 Poul Sander 2024-10-05 08:44 973
class iterator_buffer : public Traits, public buffer<T> {
47fd5c32 Poul Sander 2024-10-05 08:44 974
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 975
  OutputIt out_;
47fd5c32 Poul Sander 2024-10-05 08:44 976
  enum { buffer_size = 256 };
47fd5c32 Poul Sander 2024-10-05 08:44 977
  T data_[buffer_size];
47fd5c32 Poul Sander 2024-10-05 08:44 978
47fd5c32 Poul Sander 2024-10-05 08:44 979
  static FMT_CONSTEXPR void grow(buffer<T>& buf, size_t) {
47fd5c32 Poul Sander 2024-10-05 08:44 980
    if (buf.size() == buffer_size) static_cast<iterator_buffer&>(buf).flush();
47fd5c32 Poul Sander 2024-10-05 08:44 981
  }
47fd5c32 Poul Sander 2024-10-05 08:44 982
47fd5c32 Poul Sander 2024-10-05 08:44 983
  void flush() {
47fd5c32 Poul Sander 2024-10-05 08:44 984
    auto size = this->size();
47fd5c32 Poul Sander 2024-10-05 08:44 985
    this->clear();
47fd5c32 Poul Sander 2024-10-05 08:44 986
    const T* begin = data_;
47fd5c32 Poul Sander 2024-10-05 08:44 987
    const T* end = begin + this->limit(size);
47fd5c32 Poul Sander 2024-10-05 08:44 988
    while (begin != end) *out_++ = *begin++;
47fd5c32 Poul Sander 2024-10-05 08:44 989
  }
47fd5c32 Poul Sander 2024-10-05 08:44 990
47fd5c32 Poul Sander 2024-10-05 08:44 991
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 992
  explicit iterator_buffer(OutputIt out, size_t n = buffer_size)
47fd5c32 Poul Sander 2024-10-05 08:44 993
      : Traits(n), buffer<T>(grow, data_, 0, buffer_size), out_(out) {}
47fd5c32 Poul Sander 2024-10-05 08:44 994
  iterator_buffer(iterator_buffer&& other) noexcept
47fd5c32 Poul Sander 2024-10-05 08:44 995
      : Traits(other),
47fd5c32 Poul Sander 2024-10-05 08:44 996
        buffer<T>(grow, data_, 0, buffer_size),
47fd5c32 Poul Sander 2024-10-05 08:44 997
        out_(other.out_) {}
47fd5c32 Poul Sander 2024-10-05 08:44 998
  ~iterator_buffer() {
47fd5c32 Poul Sander 2024-10-05 08:44 999
    // Don't crash if flush fails during unwinding.
47fd5c32 Poul Sander 2024-10-05 08:44 1000
    FMT_TRY { flush(); }
47fd5c32 Poul Sander 2024-10-05 08:44 1001
    FMT_CATCH(...) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1002
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1003
47fd5c32 Poul Sander 2024-10-05 08:44 1004
  auto out() -> OutputIt {
47fd5c32 Poul Sander 2024-10-05 08:44 1005
    flush();
47fd5c32 Poul Sander 2024-10-05 08:44 1006
    return out_;
47fd5c32 Poul Sander 2024-10-05 08:44 1007
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1008
  auto count() const -> size_t { return Traits::count() + this->size(); }
47fd5c32 Poul Sander 2024-10-05 08:44 1009
};
47fd5c32 Poul Sander 2024-10-05 08:44 1010
47fd5c32 Poul Sander 2024-10-05 08:44 1011
template <typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 1012
class iterator_buffer<T*, T, fixed_buffer_traits> : public fixed_buffer_traits,
47fd5c32 Poul Sander 2024-10-05 08:44 1013
                                                    public buffer<T> {
47fd5c32 Poul Sander 2024-10-05 08:44 1014
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 1015
  T* out_;
47fd5c32 Poul Sander 2024-10-05 08:44 1016
  enum { buffer_size = 256 };
47fd5c32 Poul Sander 2024-10-05 08:44 1017
  T data_[buffer_size];
47fd5c32 Poul Sander 2024-10-05 08:44 1018
47fd5c32 Poul Sander 2024-10-05 08:44 1019
  static FMT_CONSTEXPR void grow(buffer<T>& buf, size_t) {
47fd5c32 Poul Sander 2024-10-05 08:44 1020
    if (buf.size() == buf.capacity())
47fd5c32 Poul Sander 2024-10-05 08:44 1021
      static_cast<iterator_buffer&>(buf).flush();
47fd5c32 Poul Sander 2024-10-05 08:44 1022
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1023
47fd5c32 Poul Sander 2024-10-05 08:44 1024
  void flush() {
47fd5c32 Poul Sander 2024-10-05 08:44 1025
    size_t n = this->limit(this->size());
47fd5c32 Poul Sander 2024-10-05 08:44 1026
    if (this->data() == out_) {
47fd5c32 Poul Sander 2024-10-05 08:44 1027
      out_ += n;
47fd5c32 Poul Sander 2024-10-05 08:44 1028
      this->set(data_, buffer_size);
47fd5c32 Poul Sander 2024-10-05 08:44 1029
    }
47fd5c32 Poul Sander 2024-10-05 08:44 1030
    this->clear();
47fd5c32 Poul Sander 2024-10-05 08:44 1031
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1032
47fd5c32 Poul Sander 2024-10-05 08:44 1033
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 1034
  explicit iterator_buffer(T* out, size_t n = buffer_size)
47fd5c32 Poul Sander 2024-10-05 08:44 1035
      : fixed_buffer_traits(n), buffer<T>(grow, out, 0, n), out_(out) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1036
  iterator_buffer(iterator_buffer&& other) noexcept
47fd5c32 Poul Sander 2024-10-05 08:44 1037
      : fixed_buffer_traits(other),
47fd5c32 Poul Sander 2024-10-05 08:44 1038
        buffer<T>(static_cast<iterator_buffer&&>(other)),
47fd5c32 Poul Sander 2024-10-05 08:44 1039
        out_(other.out_) {
47fd5c32 Poul Sander 2024-10-05 08:44 1040
    if (this->data() != out_) {
47fd5c32 Poul Sander 2024-10-05 08:44 1041
      this->set(data_, buffer_size);
47fd5c32 Poul Sander 2024-10-05 08:44 1042
      this->clear();
47fd5c32 Poul Sander 2024-10-05 08:44 1043
    }
47fd5c32 Poul Sander 2024-10-05 08:44 1044
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1045
  ~iterator_buffer() { flush(); }
47fd5c32 Poul Sander 2024-10-05 08:44 1046
47fd5c32 Poul Sander 2024-10-05 08:44 1047
  auto out() -> T* {
47fd5c32 Poul Sander 2024-10-05 08:44 1048
    flush();
47fd5c32 Poul Sander 2024-10-05 08:44 1049
    return out_;
47fd5c32 Poul Sander 2024-10-05 08:44 1050
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1051
  auto count() const -> size_t {
47fd5c32 Poul Sander 2024-10-05 08:44 1052
    return fixed_buffer_traits::count() + this->size();
47fd5c32 Poul Sander 2024-10-05 08:44 1053
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1054
};
47fd5c32 Poul Sander 2024-10-05 08:44 1055
47fd5c32 Poul Sander 2024-10-05 08:44 1056
template <typename T> class iterator_buffer<T*, T> : public buffer<T> {
47fd5c32 Poul Sander 2024-10-05 08:44 1057
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 1058
  explicit iterator_buffer(T* out, size_t = 0)
47fd5c32 Poul Sander 2024-10-05 08:44 1059
      : buffer<T>([](buffer<T>&, size_t) {}, out, 0, ~size_t()) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1060
47fd5c32 Poul Sander 2024-10-05 08:44 1061
  auto out() -> T* { return &*this->end(); }
47fd5c32 Poul Sander 2024-10-05 08:44 1062
};
47fd5c32 Poul Sander 2024-10-05 08:44 1063
47fd5c32 Poul Sander 2024-10-05 08:44 1064
// A buffer that writes to a container with the contiguous storage.
47fd5c32 Poul Sander 2024-10-05 08:44 1065
template <typename OutputIt>
47fd5c32 Poul Sander 2024-10-05 08:44 1066
class iterator_buffer<
47fd5c32 Poul Sander 2024-10-05 08:44 1067
    OutputIt,
47fd5c32 Poul Sander 2024-10-05 08:44 1068
    enable_if_t<detail::is_back_insert_iterator<OutputIt>::value &&
47fd5c32 Poul Sander 2024-10-05 08:44 1069
                    is_contiguous<typename OutputIt::container_type>::value,
47fd5c32 Poul Sander 2024-10-05 08:44 1070
                typename OutputIt::container_type::value_type>>
47fd5c32 Poul Sander 2024-10-05 08:44 1071
    : public buffer<typename OutputIt::container_type::value_type> {
47fd5c32 Poul Sander 2024-10-05 08:44 1072
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 1073
  using container_type = typename OutputIt::container_type;
47fd5c32 Poul Sander 2024-10-05 08:44 1074
  using value_type = typename container_type::value_type;
47fd5c32 Poul Sander 2024-10-05 08:44 1075
  container_type& container_;
47fd5c32 Poul Sander 2024-10-05 08:44 1076
47fd5c32 Poul Sander 2024-10-05 08:44 1077
  static FMT_CONSTEXPR void grow(buffer<value_type>& buf, size_t capacity) {
47fd5c32 Poul Sander 2024-10-05 08:44 1078
    auto& self = static_cast<iterator_buffer&>(buf);
47fd5c32 Poul Sander 2024-10-05 08:44 1079
    self.container_.resize(capacity);
47fd5c32 Poul Sander 2024-10-05 08:44 1080
    self.set(&self.container_[0], capacity);
47fd5c32 Poul Sander 2024-10-05 08:44 1081
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1082
47fd5c32 Poul Sander 2024-10-05 08:44 1083
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 1084
  explicit iterator_buffer(container_type& c)
47fd5c32 Poul Sander 2024-10-05 08:44 1085
      : buffer<value_type>(grow, c.size()), container_(c) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1086
  explicit iterator_buffer(OutputIt out, size_t = 0)
47fd5c32 Poul Sander 2024-10-05 08:44 1087
      : iterator_buffer(get_container(out)) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1088
47fd5c32 Poul Sander 2024-10-05 08:44 1089
  auto out() -> OutputIt { return back_inserter(container_); }
47fd5c32 Poul Sander 2024-10-05 08:44 1090
};
47fd5c32 Poul Sander 2024-10-05 08:44 1091
47fd5c32 Poul Sander 2024-10-05 08:44 1092
// A buffer that counts the number of code units written discarding the output.
47fd5c32 Poul Sander 2024-10-05 08:44 1093
template <typename T = char> class counting_buffer : public buffer<T> {
47fd5c32 Poul Sander 2024-10-05 08:44 1094
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 1095
  enum { buffer_size = 256 };
47fd5c32 Poul Sander 2024-10-05 08:44 1096
  T data_[buffer_size];
47fd5c32 Poul Sander 2024-10-05 08:44 1097
  size_t count_ = 0;
47fd5c32 Poul Sander 2024-10-05 08:44 1098
47fd5c32 Poul Sander 2024-10-05 08:44 1099
  static FMT_CONSTEXPR void grow(buffer<T>& buf, size_t) {
47fd5c32 Poul Sander 2024-10-05 08:44 1100
    if (buf.size() != buffer_size) return;
47fd5c32 Poul Sander 2024-10-05 08:44 1101
    static_cast<counting_buffer&>(buf).count_ += buf.size();
47fd5c32 Poul Sander 2024-10-05 08:44 1102
    buf.clear();
47fd5c32 Poul Sander 2024-10-05 08:44 1103
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1104
47fd5c32 Poul Sander 2024-10-05 08:44 1105
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 1106
  counting_buffer() : buffer<T>(grow, data_, 0, buffer_size) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1107
47fd5c32 Poul Sander 2024-10-05 08:44 1108
  auto count() -> size_t { return count_ + this->size(); }
47fd5c32 Poul Sander 2024-10-05 08:44 1109
};
47fd5c32 Poul Sander 2024-10-05 08:44 1110
}  // namespace detail
47fd5c32 Poul Sander 2024-10-05 08:44 1111
47fd5c32 Poul Sander 2024-10-05 08:44 1112
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 1113
FMT_CONSTEXPR void basic_format_parse_context<Char>::do_check_arg_id(int id) {
47fd5c32 Poul Sander 2024-10-05 08:44 1114
  // Argument id is only checked at compile-time during parsing because
47fd5c32 Poul Sander 2024-10-05 08:44 1115
  // formatting has its own validation.
47fd5c32 Poul Sander 2024-10-05 08:44 1116
  if (detail::is_constant_evaluated() &&
47fd5c32 Poul Sander 2024-10-05 08:44 1117
      (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 1200)) {
47fd5c32 Poul Sander 2024-10-05 08:44 1118
    using context = detail::compile_parse_context<Char>;
47fd5c32 Poul Sander 2024-10-05 08:44 1119
    if (id >= static_cast<context*>(this)->num_args())
47fd5c32 Poul Sander 2024-10-05 08:44 1120
      report_error("argument not found");
47fd5c32 Poul Sander 2024-10-05 08:44 1121
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1122
}
47fd5c32 Poul Sander 2024-10-05 08:44 1123
47fd5c32 Poul Sander 2024-10-05 08:44 1124
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 1125
FMT_CONSTEXPR void basic_format_parse_context<Char>::check_dynamic_spec(
47fd5c32 Poul Sander 2024-10-05 08:44 1126
    int arg_id) {
47fd5c32 Poul Sander 2024-10-05 08:44 1127
  if (detail::is_constant_evaluated() &&
47fd5c32 Poul Sander 2024-10-05 08:44 1128
      (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 1200)) {
47fd5c32 Poul Sander 2024-10-05 08:44 1129
    using context = detail::compile_parse_context<Char>;
47fd5c32 Poul Sander 2024-10-05 08:44 1130
    static_cast<context*>(this)->check_dynamic_spec(arg_id);
47fd5c32 Poul Sander 2024-10-05 08:44 1131
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1132
}
47fd5c32 Poul Sander 2024-10-05 08:44 1133
47fd5c32 Poul Sander 2024-10-05 08:44 1134
FMT_EXPORT template <typename Context> class basic_format_arg;
47fd5c32 Poul Sander 2024-10-05 08:44 1135
FMT_EXPORT template <typename Context> class basic_format_args;
47fd5c32 Poul Sander 2024-10-05 08:44 1136
FMT_EXPORT template <typename Context> class dynamic_format_arg_store;
47fd5c32 Poul Sander 2024-10-05 08:44 1137
47fd5c32 Poul Sander 2024-10-05 08:44 1138
// A formatter for objects of type T.
47fd5c32 Poul Sander 2024-10-05 08:44 1139
FMT_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 1140
template <typename T, typename Char = char, typename Enable = void>
47fd5c32 Poul Sander 2024-10-05 08:44 1141
struct formatter {
47fd5c32 Poul Sander 2024-10-05 08:44 1142
  // A deleted default constructor indicates a disabled formatter.
47fd5c32 Poul Sander 2024-10-05 08:44 1143
  formatter() = delete;
47fd5c32 Poul Sander 2024-10-05 08:44 1144
};
47fd5c32 Poul Sander 2024-10-05 08:44 1145
47fd5c32 Poul Sander 2024-10-05 08:44 1146
// Specifies if T has an enabled formatter specialization. A type can be
47fd5c32 Poul Sander 2024-10-05 08:44 1147
// formattable even if it doesn't have a formatter e.g. via a conversion.
47fd5c32 Poul Sander 2024-10-05 08:44 1148
template <typename T, typename Context>
47fd5c32 Poul Sander 2024-10-05 08:44 1149
using has_formatter =
47fd5c32 Poul Sander 2024-10-05 08:44 1150
    std::is_constructible<typename Context::template formatter_type<T>>;
47fd5c32 Poul Sander 2024-10-05 08:44 1151
47fd5c32 Poul Sander 2024-10-05 08:44 1152
// An output iterator that appends to a buffer. It is used instead of
47fd5c32 Poul Sander 2024-10-05 08:44 1153
// back_insert_iterator to reduce symbol sizes and avoid <iterator> dependency.
47fd5c32 Poul Sander 2024-10-05 08:44 1154
template <typename T> class basic_appender {
47fd5c32 Poul Sander 2024-10-05 08:44 1155
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 1156
  detail::buffer<T>* buffer_;
47fd5c32 Poul Sander 2024-10-05 08:44 1157
47fd5c32 Poul Sander 2024-10-05 08:44 1158
  friend auto get_container(basic_appender app) -> detail::buffer<T>& {
47fd5c32 Poul Sander 2024-10-05 08:44 1159
    return *app.buffer_;
47fd5c32 Poul Sander 2024-10-05 08:44 1160
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1161
47fd5c32 Poul Sander 2024-10-05 08:44 1162
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 1163
  using iterator_category = int;
47fd5c32 Poul Sander 2024-10-05 08:44 1164
  using value_type = T;
47fd5c32 Poul Sander 2024-10-05 08:44 1165
  using difference_type = ptrdiff_t;
47fd5c32 Poul Sander 2024-10-05 08:44 1166
  using pointer = T*;
47fd5c32 Poul Sander 2024-10-05 08:44 1167
  using reference = T&;
47fd5c32 Poul Sander 2024-10-05 08:44 1168
  using container_type = detail::buffer<T>;
47fd5c32 Poul Sander 2024-10-05 08:44 1169
  FMT_UNCHECKED_ITERATOR(basic_appender);
47fd5c32 Poul Sander 2024-10-05 08:44 1170
47fd5c32 Poul Sander 2024-10-05 08:44 1171
  FMT_CONSTEXPR basic_appender(detail::buffer<T>& buf) : buffer_(&buf) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1172
47fd5c32 Poul Sander 2024-10-05 08:44 1173
  auto operator=(T c) -> basic_appender& {
47fd5c32 Poul Sander 2024-10-05 08:44 1174
    buffer_->push_back(c);
47fd5c32 Poul Sander 2024-10-05 08:44 1175
    return *this;
47fd5c32 Poul Sander 2024-10-05 08:44 1176
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1177
  auto operator*() -> basic_appender& { return *this; }
47fd5c32 Poul Sander 2024-10-05 08:44 1178
  auto operator++() -> basic_appender& { return *this; }
47fd5c32 Poul Sander 2024-10-05 08:44 1179
  auto operator++(int) -> basic_appender { return *this; }
47fd5c32 Poul Sander 2024-10-05 08:44 1180
};
47fd5c32 Poul Sander 2024-10-05 08:44 1181
47fd5c32 Poul Sander 2024-10-05 08:44 1182
using appender = basic_appender<char>;
47fd5c32 Poul Sander 2024-10-05 08:44 1183
47fd5c32 Poul Sander 2024-10-05 08:44 1184
namespace detail {
47fd5c32 Poul Sander 2024-10-05 08:44 1185
template <typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 1186
struct is_back_insert_iterator<basic_appender<T>> : std::true_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 1187
47fd5c32 Poul Sander 2024-10-05 08:44 1188
template <typename T, typename Enable = void>
47fd5c32 Poul Sander 2024-10-05 08:44 1189
struct locking : std::true_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 1190
template <typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 1191
struct locking<T, void_t<typename formatter<remove_cvref_t<T>>::nonlocking>>
47fd5c32 Poul Sander 2024-10-05 08:44 1192
    : std::false_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 1193
47fd5c32 Poul Sander 2024-10-05 08:44 1194
template <typename T = int> FMT_CONSTEXPR inline auto is_locking() -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 1195
  return locking<T>::value;
47fd5c32 Poul Sander 2024-10-05 08:44 1196
}
47fd5c32 Poul Sander 2024-10-05 08:44 1197
template <typename T1, typename T2, typename... Tail>
47fd5c32 Poul Sander 2024-10-05 08:44 1198
FMT_CONSTEXPR inline auto is_locking() -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 1199
  return locking<T1>::value || is_locking<T2, Tail...>();
47fd5c32 Poul Sander 2024-10-05 08:44 1200
}
47fd5c32 Poul Sander 2024-10-05 08:44 1201
47fd5c32 Poul Sander 2024-10-05 08:44 1202
// An optimized version of std::copy with the output value type (T).
47fd5c32 Poul Sander 2024-10-05 08:44 1203
template <typename T, typename InputIt, typename OutputIt,
47fd5c32 Poul Sander 2024-10-05 08:44 1204
          FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1205
auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
47fd5c32 Poul Sander 2024-10-05 08:44 1206
  get_container(out).append(begin, end);
47fd5c32 Poul Sander 2024-10-05 08:44 1207
  return out;
47fd5c32 Poul Sander 2024-10-05 08:44 1208
}
47fd5c32 Poul Sander 2024-10-05 08:44 1209
47fd5c32 Poul Sander 2024-10-05 08:44 1210
template <typename T, typename InputIt, typename OutputIt,
47fd5c32 Poul Sander 2024-10-05 08:44 1211
          FMT_ENABLE_IF(!is_back_insert_iterator<OutputIt>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1212
FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
47fd5c32 Poul Sander 2024-10-05 08:44 1213
  while (begin != end) *out++ = static_cast<T>(*begin++);
47fd5c32 Poul Sander 2024-10-05 08:44 1214
  return out;
47fd5c32 Poul Sander 2024-10-05 08:44 1215
}
47fd5c32 Poul Sander 2024-10-05 08:44 1216
47fd5c32 Poul Sander 2024-10-05 08:44 1217
template <typename T, typename V, typename OutputIt>
47fd5c32 Poul Sander 2024-10-05 08:44 1218
FMT_CONSTEXPR auto copy(basic_string_view<V> s, OutputIt out) -> OutputIt {
47fd5c32 Poul Sander 2024-10-05 08:44 1219
  return copy<T>(s.begin(), s.end(), out);
47fd5c32 Poul Sander 2024-10-05 08:44 1220
}
47fd5c32 Poul Sander 2024-10-05 08:44 1221
47fd5c32 Poul Sander 2024-10-05 08:44 1222
template <typename Context, typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 1223
constexpr auto has_const_formatter_impl(T*)
47fd5c32 Poul Sander 2024-10-05 08:44 1224
    -> decltype(typename Context::template formatter_type<T>().format(
47fd5c32 Poul Sander 2024-10-05 08:44 1225
                    std::declval<const T&>(), std::declval<Context&>()),
47fd5c32 Poul Sander 2024-10-05 08:44 1226
                true) {
47fd5c32 Poul Sander 2024-10-05 08:44 1227
  return true;
47fd5c32 Poul Sander 2024-10-05 08:44 1228
}
47fd5c32 Poul Sander 2024-10-05 08:44 1229
template <typename Context>
47fd5c32 Poul Sander 2024-10-05 08:44 1230
constexpr auto has_const_formatter_impl(...) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 1231
  return false;
47fd5c32 Poul Sander 2024-10-05 08:44 1232
}
47fd5c32 Poul Sander 2024-10-05 08:44 1233
template <typename T, typename Context>
47fd5c32 Poul Sander 2024-10-05 08:44 1234
constexpr auto has_const_formatter() -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 1235
  return has_const_formatter_impl<Context>(static_cast<T*>(nullptr));
47fd5c32 Poul Sander 2024-10-05 08:44 1236
}
47fd5c32 Poul Sander 2024-10-05 08:44 1237
47fd5c32 Poul Sander 2024-10-05 08:44 1238
template <typename It, typename Enable = std::true_type>
47fd5c32 Poul Sander 2024-10-05 08:44 1239
struct is_buffer_appender : std::false_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 1240
template <typename It>
47fd5c32 Poul Sander 2024-10-05 08:44 1241
struct is_buffer_appender<
47fd5c32 Poul Sander 2024-10-05 08:44 1242
    It, bool_constant<
47fd5c32 Poul Sander 2024-10-05 08:44 1243
            is_back_insert_iterator<It>::value &&
47fd5c32 Poul Sander 2024-10-05 08:44 1244
            std::is_base_of<buffer<typename It::container_type::value_type>,
47fd5c32 Poul Sander 2024-10-05 08:44 1245
                            typename It::container_type>::value>>
47fd5c32 Poul Sander 2024-10-05 08:44 1246
    : std::true_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 1247
47fd5c32 Poul Sander 2024-10-05 08:44 1248
// Maps an output iterator to a buffer.
47fd5c32 Poul Sander 2024-10-05 08:44 1249
template <typename T, typename OutputIt,
47fd5c32 Poul Sander 2024-10-05 08:44 1250
          FMT_ENABLE_IF(!is_buffer_appender<OutputIt>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1251
auto get_buffer(OutputIt out) -> iterator_buffer<OutputIt, T> {
47fd5c32 Poul Sander 2024-10-05 08:44 1252
  return iterator_buffer<OutputIt, T>(out);
47fd5c32 Poul Sander 2024-10-05 08:44 1253
}
47fd5c32 Poul Sander 2024-10-05 08:44 1254
template <typename T, typename OutputIt,
47fd5c32 Poul Sander 2024-10-05 08:44 1255
          FMT_ENABLE_IF(is_buffer_appender<OutputIt>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1256
auto get_buffer(OutputIt out) -> buffer<T>& {
47fd5c32 Poul Sander 2024-10-05 08:44 1257
  return get_container(out);
47fd5c32 Poul Sander 2024-10-05 08:44 1258
}
47fd5c32 Poul Sander 2024-10-05 08:44 1259
47fd5c32 Poul Sander 2024-10-05 08:44 1260
template <typename Buf, typename OutputIt>
47fd5c32 Poul Sander 2024-10-05 08:44 1261
auto get_iterator(Buf& buf, OutputIt) -> decltype(buf.out()) {
47fd5c32 Poul Sander 2024-10-05 08:44 1262
  return buf.out();
47fd5c32 Poul Sander 2024-10-05 08:44 1263
}
47fd5c32 Poul Sander 2024-10-05 08:44 1264
template <typename T, typename OutputIt>
47fd5c32 Poul Sander 2024-10-05 08:44 1265
auto get_iterator(buffer<T>&, OutputIt out) -> OutputIt {
47fd5c32 Poul Sander 2024-10-05 08:44 1266
  return out;
47fd5c32 Poul Sander 2024-10-05 08:44 1267
}
47fd5c32 Poul Sander 2024-10-05 08:44 1268
47fd5c32 Poul Sander 2024-10-05 08:44 1269
struct view {};
47fd5c32 Poul Sander 2024-10-05 08:44 1270
47fd5c32 Poul Sander 2024-10-05 08:44 1271
template <typename Char, typename T> struct named_arg : view {
47fd5c32 Poul Sander 2024-10-05 08:44 1272
  const Char* name;
47fd5c32 Poul Sander 2024-10-05 08:44 1273
  const T& value;
47fd5c32 Poul Sander 2024-10-05 08:44 1274
  named_arg(const Char* n, const T& v) : name(n), value(v) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1275
};
47fd5c32 Poul Sander 2024-10-05 08:44 1276
47fd5c32 Poul Sander 2024-10-05 08:44 1277
template <typename Char> struct named_arg_info {
47fd5c32 Poul Sander 2024-10-05 08:44 1278
  const Char* name;
47fd5c32 Poul Sander 2024-10-05 08:44 1279
  int id;
47fd5c32 Poul Sander 2024-10-05 08:44 1280
};
47fd5c32 Poul Sander 2024-10-05 08:44 1281
47fd5c32 Poul Sander 2024-10-05 08:44 1282
template <typename T> struct is_named_arg : std::false_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 1283
template <typename T> struct is_statically_named_arg : std::false_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 1284
47fd5c32 Poul Sander 2024-10-05 08:44 1285
template <typename T, typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 1286
struct is_named_arg<named_arg<Char, T>> : std::true_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 1287
47fd5c32 Poul Sander 2024-10-05 08:44 1288
template <bool B = false> constexpr auto count() -> size_t { return B ? 1 : 0; }
47fd5c32 Poul Sander 2024-10-05 08:44 1289
template <bool B1, bool B2, bool... Tail> constexpr auto count() -> size_t {
47fd5c32 Poul Sander 2024-10-05 08:44 1290
  return (B1 ? 1 : 0) + count<B2, Tail...>();
47fd5c32 Poul Sander 2024-10-05 08:44 1291
}
47fd5c32 Poul Sander 2024-10-05 08:44 1292
47fd5c32 Poul Sander 2024-10-05 08:44 1293
template <typename... Args> constexpr auto count_named_args() -> size_t {
47fd5c32 Poul Sander 2024-10-05 08:44 1294
  return count<is_named_arg<Args>::value...>();
47fd5c32 Poul Sander 2024-10-05 08:44 1295
}
47fd5c32 Poul Sander 2024-10-05 08:44 1296
47fd5c32 Poul Sander 2024-10-05 08:44 1297
template <typename... Args>
47fd5c32 Poul Sander 2024-10-05 08:44 1298
constexpr auto count_statically_named_args() -> size_t {
47fd5c32 Poul Sander 2024-10-05 08:44 1299
  return count<is_statically_named_arg<Args>::value...>();
47fd5c32 Poul Sander 2024-10-05 08:44 1300
}
47fd5c32 Poul Sander 2024-10-05 08:44 1301
47fd5c32 Poul Sander 2024-10-05 08:44 1302
struct unformattable {};
47fd5c32 Poul Sander 2024-10-05 08:44 1303
struct unformattable_char : unformattable {};
47fd5c32 Poul Sander 2024-10-05 08:44 1304
struct unformattable_pointer : unformattable {};
47fd5c32 Poul Sander 2024-10-05 08:44 1305
47fd5c32 Poul Sander 2024-10-05 08:44 1306
template <typename Char> struct string_value {
47fd5c32 Poul Sander 2024-10-05 08:44 1307
  const Char* data;
47fd5c32 Poul Sander 2024-10-05 08:44 1308
  size_t size;
47fd5c32 Poul Sander 2024-10-05 08:44 1309
};
47fd5c32 Poul Sander 2024-10-05 08:44 1310
47fd5c32 Poul Sander 2024-10-05 08:44 1311
template <typename Char> struct named_arg_value {
47fd5c32 Poul Sander 2024-10-05 08:44 1312
  const named_arg_info<Char>* data;
47fd5c32 Poul Sander 2024-10-05 08:44 1313
  size_t size;
47fd5c32 Poul Sander 2024-10-05 08:44 1314
};
47fd5c32 Poul Sander 2024-10-05 08:44 1315
47fd5c32 Poul Sander 2024-10-05 08:44 1316
template <typename Context> struct custom_value {
47fd5c32 Poul Sander 2024-10-05 08:44 1317
  using parse_context = typename Context::parse_context_type;
47fd5c32 Poul Sander 2024-10-05 08:44 1318
  void* value;
47fd5c32 Poul Sander 2024-10-05 08:44 1319
  void (*format)(void* arg, parse_context& parse_ctx, Context& ctx);
47fd5c32 Poul Sander 2024-10-05 08:44 1320
};
47fd5c32 Poul Sander 2024-10-05 08:44 1321
47fd5c32 Poul Sander 2024-10-05 08:44 1322
// A formatting argument value.
47fd5c32 Poul Sander 2024-10-05 08:44 1323
template <typename Context> class value {
47fd5c32 Poul Sander 2024-10-05 08:44 1324
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 1325
  using char_type = typename Context::char_type;
47fd5c32 Poul Sander 2024-10-05 08:44 1326
47fd5c32 Poul Sander 2024-10-05 08:44 1327
  union {
47fd5c32 Poul Sander 2024-10-05 08:44 1328
    monostate no_value;
47fd5c32 Poul Sander 2024-10-05 08:44 1329
    int int_value;
47fd5c32 Poul Sander 2024-10-05 08:44 1330
    unsigned uint_value;
47fd5c32 Poul Sander 2024-10-05 08:44 1331
    long long long_long_value;
47fd5c32 Poul Sander 2024-10-05 08:44 1332
    unsigned long long ulong_long_value;
47fd5c32 Poul Sander 2024-10-05 08:44 1333
    int128_opt int128_value;
47fd5c32 Poul Sander 2024-10-05 08:44 1334
    uint128_opt uint128_value;
47fd5c32 Poul Sander 2024-10-05 08:44 1335
    bool bool_value;
47fd5c32 Poul Sander 2024-10-05 08:44 1336
    char_type char_value;
47fd5c32 Poul Sander 2024-10-05 08:44 1337
    float float_value;
47fd5c32 Poul Sander 2024-10-05 08:44 1338
    double double_value;
47fd5c32 Poul Sander 2024-10-05 08:44 1339
    long double long_double_value;
47fd5c32 Poul Sander 2024-10-05 08:44 1340
    const void* pointer;
47fd5c32 Poul Sander 2024-10-05 08:44 1341
    string_value<char_type> string;
47fd5c32 Poul Sander 2024-10-05 08:44 1342
    custom_value<Context> custom;
47fd5c32 Poul Sander 2024-10-05 08:44 1343
    named_arg_value<char_type> named_args;
47fd5c32 Poul Sander 2024-10-05 08:44 1344
  };
47fd5c32 Poul Sander 2024-10-05 08:44 1345
47fd5c32 Poul Sander 2024-10-05 08:44 1346
  constexpr FMT_ALWAYS_INLINE value() : no_value() {}
47fd5c32 Poul Sander 2024-10-05 08:44 1347
  constexpr FMT_ALWAYS_INLINE value(int val) : int_value(val) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1348
  constexpr FMT_ALWAYS_INLINE value(unsigned val) : uint_value(val) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1349
  constexpr FMT_ALWAYS_INLINE value(long long val) : long_long_value(val) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1350
  constexpr FMT_ALWAYS_INLINE value(unsigned long long val)
47fd5c32 Poul Sander 2024-10-05 08:44 1351
      : ulong_long_value(val) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1352
  FMT_ALWAYS_INLINE value(int128_opt val) : int128_value(val) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1353
  FMT_ALWAYS_INLINE value(uint128_opt val) : uint128_value(val) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1354
  constexpr FMT_ALWAYS_INLINE value(float val) : float_value(val) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1355
  constexpr FMT_ALWAYS_INLINE value(double val) : double_value(val) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1356
  FMT_ALWAYS_INLINE value(long double val) : long_double_value(val) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1357
  constexpr FMT_ALWAYS_INLINE value(bool val) : bool_value(val) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1358
  constexpr FMT_ALWAYS_INLINE value(char_type val) : char_value(val) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1359
  FMT_CONSTEXPR FMT_ALWAYS_INLINE value(const char_type* val) {
47fd5c32 Poul Sander 2024-10-05 08:44 1360
    string.data = val;
47fd5c32 Poul Sander 2024-10-05 08:44 1361
    if (is_constant_evaluated()) string.size = {};
47fd5c32 Poul Sander 2024-10-05 08:44 1362
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1363
  FMT_CONSTEXPR FMT_ALWAYS_INLINE value(basic_string_view<char_type> val) {
47fd5c32 Poul Sander 2024-10-05 08:44 1364
    string.data = val.data();
47fd5c32 Poul Sander 2024-10-05 08:44 1365
    string.size = val.size();
47fd5c32 Poul Sander 2024-10-05 08:44 1366
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1367
  FMT_ALWAYS_INLINE value(const void* val) : pointer(val) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1368
  FMT_ALWAYS_INLINE value(const named_arg_info<char_type>* args, size_t size)
47fd5c32 Poul Sander 2024-10-05 08:44 1369
      : named_args{args, size} {}
47fd5c32 Poul Sander 2024-10-05 08:44 1370
47fd5c32 Poul Sander 2024-10-05 08:44 1371
  template <typename T> FMT_CONSTEXPR20 FMT_ALWAYS_INLINE value(T& val) {
47fd5c32 Poul Sander 2024-10-05 08:44 1372
    using value_type = remove_const_t<T>;
47fd5c32 Poul Sander 2024-10-05 08:44 1373
    // T may overload operator& e.g. std::vector<bool>::reference in libc++.
47fd5c32 Poul Sander 2024-10-05 08:44 1374
#if defined(__cpp_if_constexpr)
47fd5c32 Poul Sander 2024-10-05 08:44 1375
    if constexpr (std::is_same<decltype(&val), T*>::value)
47fd5c32 Poul Sander 2024-10-05 08:44 1376
      custom.value = const_cast<value_type*>(&val);
47fd5c32 Poul Sander 2024-10-05 08:44 1377
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 1378
    if (!is_constant_evaluated())
47fd5c32 Poul Sander 2024-10-05 08:44 1379
      custom.value = const_cast<char*>(&reinterpret_cast<const char&>(val));
47fd5c32 Poul Sander 2024-10-05 08:44 1380
    // Get the formatter type through the context to allow different contexts
47fd5c32 Poul Sander 2024-10-05 08:44 1381
    // have different extension points, e.g. `formatter<T>` for `format` and
47fd5c32 Poul Sander 2024-10-05 08:44 1382
    // `printf_formatter<T>` for `printf`.
47fd5c32 Poul Sander 2024-10-05 08:44 1383
    custom.format = format_custom_arg<
47fd5c32 Poul Sander 2024-10-05 08:44 1384
        value_type, typename Context::template formatter_type<value_type>>;
47fd5c32 Poul Sander 2024-10-05 08:44 1385
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1386
  value(unformattable);
47fd5c32 Poul Sander 2024-10-05 08:44 1387
  value(unformattable_char);
47fd5c32 Poul Sander 2024-10-05 08:44 1388
  value(unformattable_pointer);
47fd5c32 Poul Sander 2024-10-05 08:44 1389
47fd5c32 Poul Sander 2024-10-05 08:44 1390
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 1391
  // Formats an argument of a custom type, such as a user-defined class.
47fd5c32 Poul Sander 2024-10-05 08:44 1392
  template <typename T, typename Formatter>
47fd5c32 Poul Sander 2024-10-05 08:44 1393
  static void format_custom_arg(void* arg,
47fd5c32 Poul Sander 2024-10-05 08:44 1394
                                typename Context::parse_context_type& parse_ctx,
47fd5c32 Poul Sander 2024-10-05 08:44 1395
                                Context& ctx) {
47fd5c32 Poul Sander 2024-10-05 08:44 1396
    auto f = Formatter();
47fd5c32 Poul Sander 2024-10-05 08:44 1397
    parse_ctx.advance_to(f.parse(parse_ctx));
47fd5c32 Poul Sander 2024-10-05 08:44 1398
    using qualified_type =
47fd5c32 Poul Sander 2024-10-05 08:44 1399
        conditional_t<has_const_formatter<T, Context>(), const T, T>;
47fd5c32 Poul Sander 2024-10-05 08:44 1400
    // format must be const for compatibility with std::format and compilation.
47fd5c32 Poul Sander 2024-10-05 08:44 1401
    const auto& cf = f;
47fd5c32 Poul Sander 2024-10-05 08:44 1402
    ctx.advance_to(cf.format(*static_cast<qualified_type*>(arg), ctx));
47fd5c32 Poul Sander 2024-10-05 08:44 1403
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1404
};
47fd5c32 Poul Sander 2024-10-05 08:44 1405
47fd5c32 Poul Sander 2024-10-05 08:44 1406
// To minimize the number of types we need to deal with, long is translated
47fd5c32 Poul Sander 2024-10-05 08:44 1407
// either to int or to long long depending on its size.
47fd5c32 Poul Sander 2024-10-05 08:44 1408
enum { long_short = sizeof(long) == sizeof(int) };
47fd5c32 Poul Sander 2024-10-05 08:44 1409
using long_type = conditional_t<long_short, int, long long>;
47fd5c32 Poul Sander 2024-10-05 08:44 1410
using ulong_type = conditional_t<long_short, unsigned, unsigned long long>;
47fd5c32 Poul Sander 2024-10-05 08:44 1411
47fd5c32 Poul Sander 2024-10-05 08:44 1412
template <typename T> struct format_as_result {
47fd5c32 Poul Sander 2024-10-05 08:44 1413
  template <typename U,
47fd5c32 Poul Sander 2024-10-05 08:44 1414
            FMT_ENABLE_IF(std::is_enum<U>::value || std::is_class<U>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1415
  static auto map(U*) -> remove_cvref_t<decltype(format_as(std::declval<U>()))>;
47fd5c32 Poul Sander 2024-10-05 08:44 1416
  static auto map(...) -> void;
47fd5c32 Poul Sander 2024-10-05 08:44 1417
47fd5c32 Poul Sander 2024-10-05 08:44 1418
  using type = decltype(map(static_cast<T*>(nullptr)));
47fd5c32 Poul Sander 2024-10-05 08:44 1419
};
47fd5c32 Poul Sander 2024-10-05 08:44 1420
template <typename T> using format_as_t = typename format_as_result<T>::type;
47fd5c32 Poul Sander 2024-10-05 08:44 1421
47fd5c32 Poul Sander 2024-10-05 08:44 1422
template <typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 1423
struct has_format_as
47fd5c32 Poul Sander 2024-10-05 08:44 1424
    : bool_constant<!std::is_same<format_as_t<T>, void>::value> {};
47fd5c32 Poul Sander 2024-10-05 08:44 1425
47fd5c32 Poul Sander 2024-10-05 08:44 1426
#define FMT_MAP_API FMT_CONSTEXPR FMT_ALWAYS_INLINE
47fd5c32 Poul Sander 2024-10-05 08:44 1427
47fd5c32 Poul Sander 2024-10-05 08:44 1428
// Maps formatting arguments to core types.
47fd5c32 Poul Sander 2024-10-05 08:44 1429
// arg_mapper reports errors by returning unformattable instead of using
47fd5c32 Poul Sander 2024-10-05 08:44 1430
// static_assert because it's used in the is_formattable trait.
47fd5c32 Poul Sander 2024-10-05 08:44 1431
template <typename Context> struct arg_mapper {
47fd5c32 Poul Sander 2024-10-05 08:44 1432
  using char_type = typename Context::char_type;
47fd5c32 Poul Sander 2024-10-05 08:44 1433
47fd5c32 Poul Sander 2024-10-05 08:44 1434
  FMT_MAP_API auto map(signed char val) -> int { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1435
  FMT_MAP_API auto map(unsigned char val) -> unsigned { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1436
  FMT_MAP_API auto map(short val) -> int { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1437
  FMT_MAP_API auto map(unsigned short val) -> unsigned { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1438
  FMT_MAP_API auto map(int val) -> int { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1439
  FMT_MAP_API auto map(unsigned val) -> unsigned { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1440
  FMT_MAP_API auto map(long val) -> long_type { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1441
  FMT_MAP_API auto map(unsigned long val) -> ulong_type { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1442
  FMT_MAP_API auto map(long long val) -> long long { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1443
  FMT_MAP_API auto map(unsigned long long val) -> unsigned long long {
47fd5c32 Poul Sander 2024-10-05 08:44 1444
    return val;
47fd5c32 Poul Sander 2024-10-05 08:44 1445
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1446
  FMT_MAP_API auto map(int128_opt val) -> int128_opt { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1447
  FMT_MAP_API auto map(uint128_opt val) -> uint128_opt { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1448
  FMT_MAP_API auto map(bool val) -> bool { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1449
47fd5c32 Poul Sander 2024-10-05 08:44 1450
  template <typename T, FMT_ENABLE_IF(std::is_same<T, char>::value ||
47fd5c32 Poul Sander 2024-10-05 08:44 1451
                                      std::is_same<T, char_type>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1452
  FMT_MAP_API auto map(T val) -> char_type {
47fd5c32 Poul Sander 2024-10-05 08:44 1453
    return val;
47fd5c32 Poul Sander 2024-10-05 08:44 1454
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1455
  template <typename T, enable_if_t<(std::is_same<T, wchar_t>::value ||
47fd5c32 Poul Sander 2024-10-05 08:44 1456
#ifdef __cpp_char8_t
47fd5c32 Poul Sander 2024-10-05 08:44 1457
                                     std::is_same<T, char8_t>::value ||
47fd5c32 Poul Sander 2024-10-05 08:44 1458
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 1459
                                     std::is_same<T, char16_t>::value ||
47fd5c32 Poul Sander 2024-10-05 08:44 1460
                                     std::is_same<T, char32_t>::value) &&
47fd5c32 Poul Sander 2024-10-05 08:44 1461
                                        !std::is_same<T, char_type>::value,
47fd5c32 Poul Sander 2024-10-05 08:44 1462
                                    int> = 0>
47fd5c32 Poul Sander 2024-10-05 08:44 1463
  FMT_MAP_API auto map(T) -> unformattable_char {
47fd5c32 Poul Sander 2024-10-05 08:44 1464
    return {};
47fd5c32 Poul Sander 2024-10-05 08:44 1465
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1466
47fd5c32 Poul Sander 2024-10-05 08:44 1467
  FMT_MAP_API auto map(float val) -> float { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1468
  FMT_MAP_API auto map(double val) -> double { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1469
  FMT_MAP_API auto map(long double val) -> long double { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1470
47fd5c32 Poul Sander 2024-10-05 08:44 1471
  FMT_MAP_API auto map(char_type* val) -> const char_type* { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1472
  FMT_MAP_API auto map(const char_type* val) -> const char_type* { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1473
  template <typename T, typename Char = char_t<T>,
47fd5c32 Poul Sander 2024-10-05 08:44 1474
            FMT_ENABLE_IF(std::is_same<Char, char_type>::value &&
47fd5c32 Poul Sander 2024-10-05 08:44 1475
                          !std::is_pointer<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1476
  FMT_MAP_API auto map(const T& val) -> basic_string_view<Char> {
47fd5c32 Poul Sander 2024-10-05 08:44 1477
    return to_string_view(val);
47fd5c32 Poul Sander 2024-10-05 08:44 1478
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1479
  template <typename T, typename Char = char_t<T>,
47fd5c32 Poul Sander 2024-10-05 08:44 1480
            FMT_ENABLE_IF(!std::is_same<Char, char_type>::value &&
47fd5c32 Poul Sander 2024-10-05 08:44 1481
                          !std::is_pointer<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1482
  FMT_MAP_API auto map(const T&) -> unformattable_char {
47fd5c32 Poul Sander 2024-10-05 08:44 1483
    return {};
47fd5c32 Poul Sander 2024-10-05 08:44 1484
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1485
47fd5c32 Poul Sander 2024-10-05 08:44 1486
  FMT_MAP_API auto map(void* val) -> const void* { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1487
  FMT_MAP_API auto map(const void* val) -> const void* { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1488
  FMT_MAP_API auto map(volatile void* val) -> const void* {
47fd5c32 Poul Sander 2024-10-05 08:44 1489
    return const_cast<const void*>(val);
47fd5c32 Poul Sander 2024-10-05 08:44 1490
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1491
  FMT_MAP_API auto map(const volatile void* val) -> const void* {
47fd5c32 Poul Sander 2024-10-05 08:44 1492
    return const_cast<const void*>(val);
47fd5c32 Poul Sander 2024-10-05 08:44 1493
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1494
  FMT_MAP_API auto map(std::nullptr_t val) -> const void* { return val; }
47fd5c32 Poul Sander 2024-10-05 08:44 1495
47fd5c32 Poul Sander 2024-10-05 08:44 1496
  // Use SFINAE instead of a const T* parameter to avoid a conflict with the
47fd5c32 Poul Sander 2024-10-05 08:44 1497
  // array overload.
47fd5c32 Poul Sander 2024-10-05 08:44 1498
  template <
47fd5c32 Poul Sander 2024-10-05 08:44 1499
      typename T,
47fd5c32 Poul Sander 2024-10-05 08:44 1500
      FMT_ENABLE_IF(
47fd5c32 Poul Sander 2024-10-05 08:44 1501
          std::is_pointer<T>::value || std::is_member_pointer<T>::value ||
47fd5c32 Poul Sander 2024-10-05 08:44 1502
          std::is_function<typename std::remove_pointer<T>::type>::value ||
47fd5c32 Poul Sander 2024-10-05 08:44 1503
          (std::is_array<T>::value &&
47fd5c32 Poul Sander 2024-10-05 08:44 1504
           !std::is_convertible<T, const char_type*>::value))>
47fd5c32 Poul Sander 2024-10-05 08:44 1505
  FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer {
47fd5c32 Poul Sander 2024-10-05 08:44 1506
    return {};
47fd5c32 Poul Sander 2024-10-05 08:44 1507
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1508
47fd5c32 Poul Sander 2024-10-05 08:44 1509
  template <typename T, std::size_t N,
47fd5c32 Poul Sander 2024-10-05 08:44 1510
            FMT_ENABLE_IF(!std::is_same<T, wchar_t>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1511
  FMT_MAP_API auto map(const T (&values)[N]) -> const T (&)[N] {
47fd5c32 Poul Sander 2024-10-05 08:44 1512
    return values;
47fd5c32 Poul Sander 2024-10-05 08:44 1513
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1514
47fd5c32 Poul Sander 2024-10-05 08:44 1515
  // Only map owning types because mapping views can be unsafe.
47fd5c32 Poul Sander 2024-10-05 08:44 1516
  template <typename T, typename U = format_as_t<T>,
47fd5c32 Poul Sander 2024-10-05 08:44 1517
            FMT_ENABLE_IF(std::is_arithmetic<U>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1518
  FMT_MAP_API auto map(const T& val) -> decltype(FMT_DECLTYPE_THIS map(U())) {
47fd5c32 Poul Sander 2024-10-05 08:44 1519
    return map(format_as(val));
47fd5c32 Poul Sander 2024-10-05 08:44 1520
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1521
47fd5c32 Poul Sander 2024-10-05 08:44 1522
  template <typename T, typename U = remove_const_t<T>>
47fd5c32 Poul Sander 2024-10-05 08:44 1523
  struct formattable : bool_constant<has_const_formatter<U, Context>() ||
47fd5c32 Poul Sander 2024-10-05 08:44 1524
                                     (has_formatter<U, Context>::value &&
47fd5c32 Poul Sander 2024-10-05 08:44 1525
                                      !std::is_const<T>::value)> {};
47fd5c32 Poul Sander 2024-10-05 08:44 1526
47fd5c32 Poul Sander 2024-10-05 08:44 1527
  template <typename T, FMT_ENABLE_IF(formattable<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1528
  FMT_MAP_API auto do_map(T& val) -> T& {
47fd5c32 Poul Sander 2024-10-05 08:44 1529
    return val;
47fd5c32 Poul Sander 2024-10-05 08:44 1530
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1531
  template <typename T, FMT_ENABLE_IF(!formattable<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1532
  FMT_MAP_API auto do_map(T&) -> unformattable {
47fd5c32 Poul Sander 2024-10-05 08:44 1533
    return {};
47fd5c32 Poul Sander 2024-10-05 08:44 1534
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1535
47fd5c32 Poul Sander 2024-10-05 08:44 1536
  // is_fundamental is used to allow formatters for extended FP types.
47fd5c32 Poul Sander 2024-10-05 08:44 1537
  template <typename T, typename U = remove_const_t<T>,
47fd5c32 Poul Sander 2024-10-05 08:44 1538
            FMT_ENABLE_IF(
47fd5c32 Poul Sander 2024-10-05 08:44 1539
                (std::is_class<U>::value || std::is_enum<U>::value ||
47fd5c32 Poul Sander 2024-10-05 08:44 1540
                 std::is_union<U>::value || std::is_fundamental<U>::value) &&
47fd5c32 Poul Sander 2024-10-05 08:44 1541
                !has_to_string_view<U>::value && !is_char<U>::value &&
47fd5c32 Poul Sander 2024-10-05 08:44 1542
                !is_named_arg<U>::value && !std::is_integral<U>::value &&
47fd5c32 Poul Sander 2024-10-05 08:44 1543
                !std::is_arithmetic<format_as_t<U>>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1544
  FMT_MAP_API auto map(T& val) -> decltype(FMT_DECLTYPE_THIS do_map(val)) {
47fd5c32 Poul Sander 2024-10-05 08:44 1545
    return do_map(val);
47fd5c32 Poul Sander 2024-10-05 08:44 1546
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1547
47fd5c32 Poul Sander 2024-10-05 08:44 1548
  template <typename T, FMT_ENABLE_IF(is_named_arg<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1549
  FMT_MAP_API auto map(const T& named_arg)
47fd5c32 Poul Sander 2024-10-05 08:44 1550
      -> decltype(FMT_DECLTYPE_THIS map(named_arg.value)) {
47fd5c32 Poul Sander 2024-10-05 08:44 1551
    return map(named_arg.value);
47fd5c32 Poul Sander 2024-10-05 08:44 1552
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1553
47fd5c32 Poul Sander 2024-10-05 08:44 1554
  auto map(...) -> unformattable { return {}; }
47fd5c32 Poul Sander 2024-10-05 08:44 1555
};
47fd5c32 Poul Sander 2024-10-05 08:44 1556
47fd5c32 Poul Sander 2024-10-05 08:44 1557
// A type constant after applying arg_mapper<Context>.
47fd5c32 Poul Sander 2024-10-05 08:44 1558
template <typename T, typename Context>
47fd5c32 Poul Sander 2024-10-05 08:44 1559
using mapped_type_constant =
47fd5c32 Poul Sander 2024-10-05 08:44 1560
    type_constant<decltype(arg_mapper<Context>().map(std::declval<const T&>())),
47fd5c32 Poul Sander 2024-10-05 08:44 1561
                  typename Context::char_type>;
47fd5c32 Poul Sander 2024-10-05 08:44 1562
47fd5c32 Poul Sander 2024-10-05 08:44 1563
enum { packed_arg_bits = 4 };
47fd5c32 Poul Sander 2024-10-05 08:44 1564
// Maximum number of arguments with packed types.
47fd5c32 Poul Sander 2024-10-05 08:44 1565
enum { max_packed_args = 62 / packed_arg_bits };
47fd5c32 Poul Sander 2024-10-05 08:44 1566
enum : unsigned long long { is_unpacked_bit = 1ULL << 63 };
47fd5c32 Poul Sander 2024-10-05 08:44 1567
enum : unsigned long long { has_named_args_bit = 1ULL << 62 };
47fd5c32 Poul Sander 2024-10-05 08:44 1568
47fd5c32 Poul Sander 2024-10-05 08:44 1569
template <typename It, typename T, typename Enable = void>
47fd5c32 Poul Sander 2024-10-05 08:44 1570
struct is_output_iterator : std::false_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 1571
47fd5c32 Poul Sander 2024-10-05 08:44 1572
template <> struct is_output_iterator<appender, char> : std::true_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 1573
47fd5c32 Poul Sander 2024-10-05 08:44 1574
template <typename It, typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 1575
struct is_output_iterator<
47fd5c32 Poul Sander 2024-10-05 08:44 1576
    It, T, void_t<decltype(*std::declval<It&>()++ = std::declval<T>())>>
47fd5c32 Poul Sander 2024-10-05 08:44 1577
    : std::true_type {};
47fd5c32 Poul Sander 2024-10-05 08:44 1578
47fd5c32 Poul Sander 2024-10-05 08:44 1579
// A type-erased reference to an std::locale to avoid a heavy <locale> include.
47fd5c32 Poul Sander 2024-10-05 08:44 1580
class locale_ref {
47fd5c32 Poul Sander 2024-10-05 08:44 1581
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 1582
  const void* locale_;  // A type-erased pointer to std::locale.
47fd5c32 Poul Sander 2024-10-05 08:44 1583
47fd5c32 Poul Sander 2024-10-05 08:44 1584
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 1585
  constexpr locale_ref() : locale_(nullptr) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1586
  template <typename Locale> explicit locale_ref(const Locale& loc);
47fd5c32 Poul Sander 2024-10-05 08:44 1587
47fd5c32 Poul Sander 2024-10-05 08:44 1588
  explicit operator bool() const noexcept { return locale_ != nullptr; }
47fd5c32 Poul Sander 2024-10-05 08:44 1589
47fd5c32 Poul Sander 2024-10-05 08:44 1590
  template <typename Locale> auto get() const -> Locale;
47fd5c32 Poul Sander 2024-10-05 08:44 1591
};
47fd5c32 Poul Sander 2024-10-05 08:44 1592
47fd5c32 Poul Sander 2024-10-05 08:44 1593
template <typename> constexpr auto encode_types() -> unsigned long long {
47fd5c32 Poul Sander 2024-10-05 08:44 1594
  return 0;
47fd5c32 Poul Sander 2024-10-05 08:44 1595
}
47fd5c32 Poul Sander 2024-10-05 08:44 1596
47fd5c32 Poul Sander 2024-10-05 08:44 1597
template <typename Context, typename Arg, typename... Args>
47fd5c32 Poul Sander 2024-10-05 08:44 1598
constexpr auto encode_types() -> unsigned long long {
47fd5c32 Poul Sander 2024-10-05 08:44 1599
  return static_cast<unsigned>(mapped_type_constant<Arg, Context>::value) |
47fd5c32 Poul Sander 2024-10-05 08:44 1600
         (encode_types<Context, Args...>() << packed_arg_bits);
47fd5c32 Poul Sander 2024-10-05 08:44 1601
}
47fd5c32 Poul Sander 2024-10-05 08:44 1602
47fd5c32 Poul Sander 2024-10-05 08:44 1603
template <typename Context, typename... T, size_t NUM_ARGS = sizeof...(T)>
47fd5c32 Poul Sander 2024-10-05 08:44 1604
constexpr unsigned long long make_descriptor() {
47fd5c32 Poul Sander 2024-10-05 08:44 1605
  return NUM_ARGS <= max_packed_args ? encode_types<Context, T...>()
47fd5c32 Poul Sander 2024-10-05 08:44 1606
                                     : is_unpacked_bit | NUM_ARGS;
47fd5c32 Poul Sander 2024-10-05 08:44 1607
}
47fd5c32 Poul Sander 2024-10-05 08:44 1608
47fd5c32 Poul Sander 2024-10-05 08:44 1609
// This type is intentionally undefined, only used for errors.
47fd5c32 Poul Sander 2024-10-05 08:44 1610
template <typename T, typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 1611
#if FMT_CLANG_VERSION && FMT_CLANG_VERSION <= 1500
47fd5c32 Poul Sander 2024-10-05 08:44 1612
// https://github.com/fmtlib/fmt/issues/3796
47fd5c32 Poul Sander 2024-10-05 08:44 1613
struct type_is_unformattable_for {
47fd5c32 Poul Sander 2024-10-05 08:44 1614
};
47fd5c32 Poul Sander 2024-10-05 08:44 1615
#else
47fd5c32 Poul Sander 2024-10-05 08:44 1616
struct type_is_unformattable_for;
47fd5c32 Poul Sander 2024-10-05 08:44 1617
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 1618
47fd5c32 Poul Sander 2024-10-05 08:44 1619
template <bool PACKED, typename Context, typename T, FMT_ENABLE_IF(PACKED)>
47fd5c32 Poul Sander 2024-10-05 08:44 1620
FMT_CONSTEXPR auto make_arg(T& val) -> value<Context> {
47fd5c32 Poul Sander 2024-10-05 08:44 1621
  using arg_type = remove_cvref_t<decltype(arg_mapper<Context>().map(val))>;
47fd5c32 Poul Sander 2024-10-05 08:44 1622
47fd5c32 Poul Sander 2024-10-05 08:44 1623
  // Use enum instead of constexpr because the latter may generate code.
47fd5c32 Poul Sander 2024-10-05 08:44 1624
  enum {
47fd5c32 Poul Sander 2024-10-05 08:44 1625
    formattable_char = !std::is_same<arg_type, unformattable_char>::value
47fd5c32 Poul Sander 2024-10-05 08:44 1626
  };
47fd5c32 Poul Sander 2024-10-05 08:44 1627
  static_assert(formattable_char, "Mixing character types is disallowed.");
47fd5c32 Poul Sander 2024-10-05 08:44 1628
47fd5c32 Poul Sander 2024-10-05 08:44 1629
  // Formatting of arbitrary pointers is disallowed. If you want to format a
47fd5c32 Poul Sander 2024-10-05 08:44 1630
  // pointer cast it to `void*` or `const void*`. In particular, this forbids
47fd5c32 Poul Sander 2024-10-05 08:44 1631
  // formatting of `[const] volatile char*` printed as bool by iostreams.
47fd5c32 Poul Sander 2024-10-05 08:44 1632
  enum {
47fd5c32 Poul Sander 2024-10-05 08:44 1633
    formattable_pointer = !std::is_same<arg_type, unformattable_pointer>::value
47fd5c32 Poul Sander 2024-10-05 08:44 1634
  };
47fd5c32 Poul Sander 2024-10-05 08:44 1635
  static_assert(formattable_pointer,
47fd5c32 Poul Sander 2024-10-05 08:44 1636
                "Formatting of non-void pointers is disallowed.");
47fd5c32 Poul Sander 2024-10-05 08:44 1637
47fd5c32 Poul Sander 2024-10-05 08:44 1638
  enum { formattable = !std::is_same<arg_type, unformattable>::value };
47fd5c32 Poul Sander 2024-10-05 08:44 1639
#if defined(__cpp_if_constexpr)
47fd5c32 Poul Sander 2024-10-05 08:44 1640
  if constexpr (!formattable)
47fd5c32 Poul Sander 2024-10-05 08:44 1641
    type_is_unformattable_for<T, typename Context::char_type> _;
47fd5c32 Poul Sander 2024-10-05 08:44 1642
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 1643
  static_assert(
47fd5c32 Poul Sander 2024-10-05 08:44 1644
      formattable,
47fd5c32 Poul Sander 2024-10-05 08:44 1645
      "Cannot format an argument. To make type T formattable provide a "
47fd5c32 Poul Sander 2024-10-05 08:44 1646
      "formatter<T> specialization: https://fmt.dev/latest/api.html#udt");
47fd5c32 Poul Sander 2024-10-05 08:44 1647
  return {arg_mapper<Context>().map(val)};
47fd5c32 Poul Sander 2024-10-05 08:44 1648
}
47fd5c32 Poul Sander 2024-10-05 08:44 1649
47fd5c32 Poul Sander 2024-10-05 08:44 1650
template <typename Context, typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 1651
FMT_CONSTEXPR auto make_arg(T& val) -> basic_format_arg<Context> {
47fd5c32 Poul Sander 2024-10-05 08:44 1652
  auto arg = basic_format_arg<Context>();
47fd5c32 Poul Sander 2024-10-05 08:44 1653
  arg.type_ = mapped_type_constant<T, Context>::value;
47fd5c32 Poul Sander 2024-10-05 08:44 1654
  arg.value_ = make_arg<true, Context>(val);
47fd5c32 Poul Sander 2024-10-05 08:44 1655
  return arg;
47fd5c32 Poul Sander 2024-10-05 08:44 1656
}
47fd5c32 Poul Sander 2024-10-05 08:44 1657
47fd5c32 Poul Sander 2024-10-05 08:44 1658
template <bool PACKED, typename Context, typename T, FMT_ENABLE_IF(!PACKED)>
47fd5c32 Poul Sander 2024-10-05 08:44 1659
FMT_CONSTEXPR inline auto make_arg(T& val) -> basic_format_arg<Context> {
47fd5c32 Poul Sander 2024-10-05 08:44 1660
  return make_arg<Context>(val);
47fd5c32 Poul Sander 2024-10-05 08:44 1661
}
47fd5c32 Poul Sander 2024-10-05 08:44 1662
47fd5c32 Poul Sander 2024-10-05 08:44 1663
template <typename Context, size_t NUM_ARGS>
47fd5c32 Poul Sander 2024-10-05 08:44 1664
using arg_t = conditional_t<NUM_ARGS <= max_packed_args, value<Context>,
47fd5c32 Poul Sander 2024-10-05 08:44 1665
                            basic_format_arg<Context>>;
47fd5c32 Poul Sander 2024-10-05 08:44 1666
47fd5c32 Poul Sander 2024-10-05 08:44 1667
template <typename Char, typename T, FMT_ENABLE_IF(!is_named_arg<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1668
void init_named_arg(named_arg_info<Char>*, int& arg_index, int&, const T&) {
47fd5c32 Poul Sander 2024-10-05 08:44 1669
  ++arg_index;
47fd5c32 Poul Sander 2024-10-05 08:44 1670
}
47fd5c32 Poul Sander 2024-10-05 08:44 1671
template <typename Char, typename T, FMT_ENABLE_IF(is_named_arg<T>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 1672
void init_named_arg(named_arg_info<Char>* named_args, int& arg_index,
47fd5c32 Poul Sander 2024-10-05 08:44 1673
                    int& named_arg_index, const T& arg) {
47fd5c32 Poul Sander 2024-10-05 08:44 1674
  named_args[named_arg_index++] = {arg.name, arg_index++};
47fd5c32 Poul Sander 2024-10-05 08:44 1675
}
47fd5c32 Poul Sander 2024-10-05 08:44 1676
47fd5c32 Poul Sander 2024-10-05 08:44 1677
// An array of references to arguments. It can be implicitly converted to
47fd5c32 Poul Sander 2024-10-05 08:44 1678
// `fmt::basic_format_args` for passing into type-erased formatting functions
47fd5c32 Poul Sander 2024-10-05 08:44 1679
// such as `fmt::vformat`.
47fd5c32 Poul Sander 2024-10-05 08:44 1680
template <typename Context, size_t NUM_ARGS, size_t NUM_NAMED_ARGS,
47fd5c32 Poul Sander 2024-10-05 08:44 1681
          unsigned long long DESC>
47fd5c32 Poul Sander 2024-10-05 08:44 1682
struct format_arg_store {
47fd5c32 Poul Sander 2024-10-05 08:44 1683
  // args_[0].named_args points to named_args to avoid bloating format_args.
47fd5c32 Poul Sander 2024-10-05 08:44 1684
  // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
47fd5c32 Poul Sander 2024-10-05 08:44 1685
  static constexpr size_t ARGS_ARR_SIZE = 1 + (NUM_ARGS != 0 ? NUM_ARGS : +1);
47fd5c32 Poul Sander 2024-10-05 08:44 1686
47fd5c32 Poul Sander 2024-10-05 08:44 1687
  arg_t<Context, NUM_ARGS> args[ARGS_ARR_SIZE];
47fd5c32 Poul Sander 2024-10-05 08:44 1688
  named_arg_info<typename Context::char_type> named_args[NUM_NAMED_ARGS];
47fd5c32 Poul Sander 2024-10-05 08:44 1689
47fd5c32 Poul Sander 2024-10-05 08:44 1690
  template <typename... T>
47fd5c32 Poul Sander 2024-10-05 08:44 1691
  FMT_MAP_API format_arg_store(T&... values)
47fd5c32 Poul Sander 2024-10-05 08:44 1692
      : args{{named_args, NUM_NAMED_ARGS},
47fd5c32 Poul Sander 2024-10-05 08:44 1693
             make_arg<NUM_ARGS <= max_packed_args, Context>(values)...} {
47fd5c32 Poul Sander 2024-10-05 08:44 1694
    using dummy = int[];
47fd5c32 Poul Sander 2024-10-05 08:44 1695
    int arg_index = 0, named_arg_index = 0;
47fd5c32 Poul Sander 2024-10-05 08:44 1696
    (void)dummy{
47fd5c32 Poul Sander 2024-10-05 08:44 1697
        0,
47fd5c32 Poul Sander 2024-10-05 08:44 1698
        (init_named_arg(named_args, arg_index, named_arg_index, values), 0)...};
47fd5c32 Poul Sander 2024-10-05 08:44 1699
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1700
47fd5c32 Poul Sander 2024-10-05 08:44 1701
  format_arg_store(format_arg_store&& rhs) {
47fd5c32 Poul Sander 2024-10-05 08:44 1702
    args[0] = {named_args, NUM_NAMED_ARGS};
47fd5c32 Poul Sander 2024-10-05 08:44 1703
    for (size_t i = 1; i < ARGS_ARR_SIZE; ++i) args[i] = rhs.args[i];
47fd5c32 Poul Sander 2024-10-05 08:44 1704
    for (size_t i = 0; i < NUM_NAMED_ARGS; ++i)
47fd5c32 Poul Sander 2024-10-05 08:44 1705
      named_args[i] = rhs.named_args[i];
47fd5c32 Poul Sander 2024-10-05 08:44 1706
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1707
47fd5c32 Poul Sander 2024-10-05 08:44 1708
  format_arg_store(const format_arg_store& rhs) = delete;
47fd5c32 Poul Sander 2024-10-05 08:44 1709
  format_arg_store& operator=(const format_arg_store& rhs) = delete;
47fd5c32 Poul Sander 2024-10-05 08:44 1710
  format_arg_store& operator=(format_arg_store&& rhs) = delete;
47fd5c32 Poul Sander 2024-10-05 08:44 1711
};
47fd5c32 Poul Sander 2024-10-05 08:44 1712
47fd5c32 Poul Sander 2024-10-05 08:44 1713
// A specialization of format_arg_store without named arguments.
47fd5c32 Poul Sander 2024-10-05 08:44 1714
// It is a plain struct to reduce binary size in debug mode.
47fd5c32 Poul Sander 2024-10-05 08:44 1715
template <typename Context, size_t NUM_ARGS, unsigned long long DESC>
47fd5c32 Poul Sander 2024-10-05 08:44 1716
struct format_arg_store<Context, NUM_ARGS, 0, DESC> {
47fd5c32 Poul Sander 2024-10-05 08:44 1717
  // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
47fd5c32 Poul Sander 2024-10-05 08:44 1718
  arg_t<Context, NUM_ARGS> args[NUM_ARGS != 0 ? NUM_ARGS : +1];
47fd5c32 Poul Sander 2024-10-05 08:44 1719
};
47fd5c32 Poul Sander 2024-10-05 08:44 1720
47fd5c32 Poul Sander 2024-10-05 08:44 1721
}  // namespace detail
47fd5c32 Poul Sander 2024-10-05 08:44 1722
FMT_BEGIN_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 1723
47fd5c32 Poul Sander 2024-10-05 08:44 1724
// A formatting argument. Context is a template parameter for the compiled API
47fd5c32 Poul Sander 2024-10-05 08:44 1725
// where output can be unbuffered.
47fd5c32 Poul Sander 2024-10-05 08:44 1726
template <typename Context> class basic_format_arg {
47fd5c32 Poul Sander 2024-10-05 08:44 1727
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 1728
  detail::value<Context> value_;
47fd5c32 Poul Sander 2024-10-05 08:44 1729
  detail::type type_;
47fd5c32 Poul Sander 2024-10-05 08:44 1730
47fd5c32 Poul Sander 2024-10-05 08:44 1731
  template <typename ContextType, typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 1732
  friend FMT_CONSTEXPR auto detail::make_arg(T& value)
47fd5c32 Poul Sander 2024-10-05 08:44 1733
      -> basic_format_arg<ContextType>;
47fd5c32 Poul Sander 2024-10-05 08:44 1734
47fd5c32 Poul Sander 2024-10-05 08:44 1735
  friend class basic_format_args<Context>;
47fd5c32 Poul Sander 2024-10-05 08:44 1736
  friend class dynamic_format_arg_store<Context>;
47fd5c32 Poul Sander 2024-10-05 08:44 1737
47fd5c32 Poul Sander 2024-10-05 08:44 1738
  using char_type = typename Context::char_type;
47fd5c32 Poul Sander 2024-10-05 08:44 1739
47fd5c32 Poul Sander 2024-10-05 08:44 1740
  template <typename, size_t, size_t, unsigned long long>
47fd5c32 Poul Sander 2024-10-05 08:44 1741
  friend struct detail::format_arg_store;
47fd5c32 Poul Sander 2024-10-05 08:44 1742
47fd5c32 Poul Sander 2024-10-05 08:44 1743
  basic_format_arg(const detail::named_arg_info<char_type>* args, size_t size)
47fd5c32 Poul Sander 2024-10-05 08:44 1744
      : value_(args, size) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1745
47fd5c32 Poul Sander 2024-10-05 08:44 1746
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 1747
  class handle {
47fd5c32 Poul Sander 2024-10-05 08:44 1748
   public:
47fd5c32 Poul Sander 2024-10-05 08:44 1749
    explicit handle(detail::custom_value<Context> custom) : custom_(custom) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1750
47fd5c32 Poul Sander 2024-10-05 08:44 1751
    void format(typename Context::parse_context_type& parse_ctx,
47fd5c32 Poul Sander 2024-10-05 08:44 1752
                Context& ctx) const {
47fd5c32 Poul Sander 2024-10-05 08:44 1753
      custom_.format(custom_.value, parse_ctx, ctx);
47fd5c32 Poul Sander 2024-10-05 08:44 1754
    }
47fd5c32 Poul Sander 2024-10-05 08:44 1755
47fd5c32 Poul Sander 2024-10-05 08:44 1756
   private:
47fd5c32 Poul Sander 2024-10-05 08:44 1757
    detail::custom_value<Context> custom_;
47fd5c32 Poul Sander 2024-10-05 08:44 1758
  };
47fd5c32 Poul Sander 2024-10-05 08:44 1759
47fd5c32 Poul Sander 2024-10-05 08:44 1760
  constexpr basic_format_arg() : type_(detail::type::none_type) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1761
47fd5c32 Poul Sander 2024-10-05 08:44 1762
  constexpr explicit operator bool() const noexcept {
47fd5c32 Poul Sander 2024-10-05 08:44 1763
    return type_ != detail::type::none_type;
47fd5c32 Poul Sander 2024-10-05 08:44 1764
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1765
47fd5c32 Poul Sander 2024-10-05 08:44 1766
  auto type() const -> detail::type { return type_; }
47fd5c32 Poul Sander 2024-10-05 08:44 1767
47fd5c32 Poul Sander 2024-10-05 08:44 1768
  auto is_integral() const -> bool { return detail::is_integral_type(type_); }
47fd5c32 Poul Sander 2024-10-05 08:44 1769
  auto is_arithmetic() const -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 1770
    return detail::is_arithmetic_type(type_);
47fd5c32 Poul Sander 2024-10-05 08:44 1771
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1772
47fd5c32 Poul Sander 2024-10-05 08:44 1773
  /**
47fd5c32 Poul Sander 2024-10-05 08:44 1774
   * Visits an argument dispatching to the appropriate visit method based on
47fd5c32 Poul Sander 2024-10-05 08:44 1775
   * the argument type. For example, if the argument type is `double` then
47fd5c32 Poul Sander 2024-10-05 08:44 1776
   * `vis(value)` will be called with the value of type `double`.
47fd5c32 Poul Sander 2024-10-05 08:44 1777
   */
47fd5c32 Poul Sander 2024-10-05 08:44 1778
  template <typename Visitor>
47fd5c32 Poul Sander 2024-10-05 08:44 1779
  FMT_CONSTEXPR FMT_INLINE auto visit(Visitor&& vis) const -> decltype(vis(0)) {
47fd5c32 Poul Sander 2024-10-05 08:44 1780
    switch (type_) {
47fd5c32 Poul Sander 2024-10-05 08:44 1781
    case detail::type::none_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1782
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 1783
    case detail::type::int_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1784
      return vis(value_.int_value);
47fd5c32 Poul Sander 2024-10-05 08:44 1785
    case detail::type::uint_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1786
      return vis(value_.uint_value);
47fd5c32 Poul Sander 2024-10-05 08:44 1787
    case detail::type::long_long_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1788
      return vis(value_.long_long_value);
47fd5c32 Poul Sander 2024-10-05 08:44 1789
    case detail::type::ulong_long_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1790
      return vis(value_.ulong_long_value);
47fd5c32 Poul Sander 2024-10-05 08:44 1791
    case detail::type::int128_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1792
      return vis(detail::convert_for_visit(value_.int128_value));
47fd5c32 Poul Sander 2024-10-05 08:44 1793
    case detail::type::uint128_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1794
      return vis(detail::convert_for_visit(value_.uint128_value));
47fd5c32 Poul Sander 2024-10-05 08:44 1795
    case detail::type::bool_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1796
      return vis(value_.bool_value);
47fd5c32 Poul Sander 2024-10-05 08:44 1797
    case detail::type::char_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1798
      return vis(value_.char_value);
47fd5c32 Poul Sander 2024-10-05 08:44 1799
    case detail::type::float_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1800
      return vis(value_.float_value);
47fd5c32 Poul Sander 2024-10-05 08:44 1801
    case detail::type::double_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1802
      return vis(value_.double_value);
47fd5c32 Poul Sander 2024-10-05 08:44 1803
    case detail::type::long_double_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1804
      return vis(value_.long_double_value);
47fd5c32 Poul Sander 2024-10-05 08:44 1805
    case detail::type::cstring_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1806
      return vis(value_.string.data);
47fd5c32 Poul Sander 2024-10-05 08:44 1807
    case detail::type::string_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1808
      using sv = basic_string_view<typename Context::char_type>;
47fd5c32 Poul Sander 2024-10-05 08:44 1809
      return vis(sv(value_.string.data, value_.string.size));
47fd5c32 Poul Sander 2024-10-05 08:44 1810
    case detail::type::pointer_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1811
      return vis(value_.pointer);
47fd5c32 Poul Sander 2024-10-05 08:44 1812
    case detail::type::custom_type:
47fd5c32 Poul Sander 2024-10-05 08:44 1813
      return vis(typename basic_format_arg<Context>::handle(value_.custom));
47fd5c32 Poul Sander 2024-10-05 08:44 1814
    }
47fd5c32 Poul Sander 2024-10-05 08:44 1815
    return vis(monostate());
47fd5c32 Poul Sander 2024-10-05 08:44 1816
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1817
47fd5c32 Poul Sander 2024-10-05 08:44 1818
  auto format_custom(const char_type* parse_begin,
47fd5c32 Poul Sander 2024-10-05 08:44 1819
                     typename Context::parse_context_type& parse_ctx,
47fd5c32 Poul Sander 2024-10-05 08:44 1820
                     Context& ctx) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 1821
    if (type_ != detail::type::custom_type) return false;
47fd5c32 Poul Sander 2024-10-05 08:44 1822
    parse_ctx.advance_to(parse_begin);
47fd5c32 Poul Sander 2024-10-05 08:44 1823
    value_.custom.format(value_.custom.value, parse_ctx, ctx);
47fd5c32 Poul Sander 2024-10-05 08:44 1824
    return true;
47fd5c32 Poul Sander 2024-10-05 08:44 1825
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1826
};
47fd5c32 Poul Sander 2024-10-05 08:44 1827
47fd5c32 Poul Sander 2024-10-05 08:44 1828
template <typename Visitor, typename Context>
47fd5c32 Poul Sander 2024-10-05 08:44 1829
FMT_DEPRECATED FMT_CONSTEXPR auto visit_format_arg(
47fd5c32 Poul Sander 2024-10-05 08:44 1830
    Visitor&& vis, const basic_format_arg<Context>& arg) -> decltype(vis(0)) {
47fd5c32 Poul Sander 2024-10-05 08:44 1831
  return arg.visit(static_cast<Visitor&&>(vis));
47fd5c32 Poul Sander 2024-10-05 08:44 1832
}
47fd5c32 Poul Sander 2024-10-05 08:44 1833
47fd5c32 Poul Sander 2024-10-05 08:44 1834
/**
47fd5c32 Poul Sander 2024-10-05 08:44 1835
 * A view of a collection of formatting arguments. To avoid lifetime issues it
47fd5c32 Poul Sander 2024-10-05 08:44 1836
 * should only be used as a parameter type in type-erased functions such as
47fd5c32 Poul Sander 2024-10-05 08:44 1837
 * `vformat`:
47fd5c32 Poul Sander 2024-10-05 08:44 1838
 *
47fd5c32 Poul Sander 2024-10-05 08:44 1839
 *     void vlog(fmt::string_view fmt, fmt::format_args args);  // OK
47fd5c32 Poul Sander 2024-10-05 08:44 1840
 *     fmt::format_args args = fmt::make_format_args();  // Dangling reference
47fd5c32 Poul Sander 2024-10-05 08:44 1841
 */
47fd5c32 Poul Sander 2024-10-05 08:44 1842
template <typename Context> class basic_format_args {
47fd5c32 Poul Sander 2024-10-05 08:44 1843
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 1844
  using size_type = int;
47fd5c32 Poul Sander 2024-10-05 08:44 1845
  using format_arg = basic_format_arg<Context>;
47fd5c32 Poul Sander 2024-10-05 08:44 1846
47fd5c32 Poul Sander 2024-10-05 08:44 1847
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 1848
  // A descriptor that contains information about formatting arguments.
47fd5c32 Poul Sander 2024-10-05 08:44 1849
  // If the number of arguments is less or equal to max_packed_args then
47fd5c32 Poul Sander 2024-10-05 08:44 1850
  // argument types are passed in the descriptor. This reduces binary code size
47fd5c32 Poul Sander 2024-10-05 08:44 1851
  // per formatting function call.
47fd5c32 Poul Sander 2024-10-05 08:44 1852
  unsigned long long desc_;
47fd5c32 Poul Sander 2024-10-05 08:44 1853
  union {
47fd5c32 Poul Sander 2024-10-05 08:44 1854
    // If is_packed() returns true then argument values are stored in values_;
47fd5c32 Poul Sander 2024-10-05 08:44 1855
    // otherwise they are stored in args_. This is done to improve cache
47fd5c32 Poul Sander 2024-10-05 08:44 1856
    // locality and reduce compiled code size since storing larger objects
47fd5c32 Poul Sander 2024-10-05 08:44 1857
    // may require more code (at least on x86-64) even if the same amount of
47fd5c32 Poul Sander 2024-10-05 08:44 1858
    // data is actually copied to stack. It saves ~10% on the bloat test.
47fd5c32 Poul Sander 2024-10-05 08:44 1859
    const detail::value<Context>* values_;
47fd5c32 Poul Sander 2024-10-05 08:44 1860
    const format_arg* args_;
47fd5c32 Poul Sander 2024-10-05 08:44 1861
  };
47fd5c32 Poul Sander 2024-10-05 08:44 1862
47fd5c32 Poul Sander 2024-10-05 08:44 1863
  constexpr auto is_packed() const -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 1864
    return (desc_ & detail::is_unpacked_bit) == 0;
47fd5c32 Poul Sander 2024-10-05 08:44 1865
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1866
  constexpr auto has_named_args() const -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 1867
    return (desc_ & detail::has_named_args_bit) != 0;
47fd5c32 Poul Sander 2024-10-05 08:44 1868
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1869
47fd5c32 Poul Sander 2024-10-05 08:44 1870
  FMT_CONSTEXPR auto type(int index) const -> detail::type {
47fd5c32 Poul Sander 2024-10-05 08:44 1871
    int shift = index * detail::packed_arg_bits;
47fd5c32 Poul Sander 2024-10-05 08:44 1872
    unsigned int mask = (1 << detail::packed_arg_bits) - 1;
47fd5c32 Poul Sander 2024-10-05 08:44 1873
    return static_cast<detail::type>((desc_ >> shift) & mask);
47fd5c32 Poul Sander 2024-10-05 08:44 1874
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1875
47fd5c32 Poul Sander 2024-10-05 08:44 1876
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 1877
  constexpr basic_format_args() : desc_(0), args_(nullptr) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1878
47fd5c32 Poul Sander 2024-10-05 08:44 1879
  /// Constructs a `basic_format_args` object from `format_arg_store`.
47fd5c32 Poul Sander 2024-10-05 08:44 1880
  template <size_t NUM_ARGS, size_t NUM_NAMED_ARGS, unsigned long long DESC,
47fd5c32 Poul Sander 2024-10-05 08:44 1881
            FMT_ENABLE_IF(NUM_ARGS <= detail::max_packed_args)>
47fd5c32 Poul Sander 2024-10-05 08:44 1882
  constexpr FMT_ALWAYS_INLINE basic_format_args(
47fd5c32 Poul Sander 2024-10-05 08:44 1883
      const detail::format_arg_store<Context, NUM_ARGS, NUM_NAMED_ARGS, DESC>&
47fd5c32 Poul Sander 2024-10-05 08:44 1884
          store)
47fd5c32 Poul Sander 2024-10-05 08:44 1885
      : desc_(DESC), values_(store.args + (NUM_NAMED_ARGS != 0 ? 1 : 0)) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1886
47fd5c32 Poul Sander 2024-10-05 08:44 1887
  template <size_t NUM_ARGS, size_t NUM_NAMED_ARGS, unsigned long long DESC,
47fd5c32 Poul Sander 2024-10-05 08:44 1888
            FMT_ENABLE_IF(NUM_ARGS > detail::max_packed_args)>
47fd5c32 Poul Sander 2024-10-05 08:44 1889
  constexpr basic_format_args(
47fd5c32 Poul Sander 2024-10-05 08:44 1890
      const detail::format_arg_store<Context, NUM_ARGS, NUM_NAMED_ARGS, DESC>&
47fd5c32 Poul Sander 2024-10-05 08:44 1891
          store)
47fd5c32 Poul Sander 2024-10-05 08:44 1892
      : desc_(DESC), args_(store.args + (NUM_NAMED_ARGS != 0 ? 1 : 0)) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1893
47fd5c32 Poul Sander 2024-10-05 08:44 1894
  /// Constructs a `basic_format_args` object from `dynamic_format_arg_store`.
47fd5c32 Poul Sander 2024-10-05 08:44 1895
  constexpr basic_format_args(const dynamic_format_arg_store<Context>& store)
47fd5c32 Poul Sander 2024-10-05 08:44 1896
      : desc_(store.get_types()), args_(store.data()) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1897
47fd5c32 Poul Sander 2024-10-05 08:44 1898
  /// Constructs a `basic_format_args` object from a dynamic list of arguments.
47fd5c32 Poul Sander 2024-10-05 08:44 1899
  constexpr basic_format_args(const format_arg* args, int count)
47fd5c32 Poul Sander 2024-10-05 08:44 1900
      : desc_(detail::is_unpacked_bit | detail::to_unsigned(count)),
47fd5c32 Poul Sander 2024-10-05 08:44 1901
        args_(args) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1902
47fd5c32 Poul Sander 2024-10-05 08:44 1903
  /// Returns the argument with the specified id.
47fd5c32 Poul Sander 2024-10-05 08:44 1904
  FMT_CONSTEXPR auto get(int id) const -> format_arg {
47fd5c32 Poul Sander 2024-10-05 08:44 1905
    format_arg arg;
47fd5c32 Poul Sander 2024-10-05 08:44 1906
    if (!is_packed()) {
47fd5c32 Poul Sander 2024-10-05 08:44 1907
      if (id < max_size()) arg = args_[id];
47fd5c32 Poul Sander 2024-10-05 08:44 1908
      return arg;
47fd5c32 Poul Sander 2024-10-05 08:44 1909
    }
47fd5c32 Poul Sander 2024-10-05 08:44 1910
    if (static_cast<unsigned>(id) >= detail::max_packed_args) return arg;
47fd5c32 Poul Sander 2024-10-05 08:44 1911
    arg.type_ = type(id);
47fd5c32 Poul Sander 2024-10-05 08:44 1912
    if (arg.type_ == detail::type::none_type) return arg;
47fd5c32 Poul Sander 2024-10-05 08:44 1913
    arg.value_ = values_[id];
47fd5c32 Poul Sander 2024-10-05 08:44 1914
    return arg;
47fd5c32 Poul Sander 2024-10-05 08:44 1915
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1916
47fd5c32 Poul Sander 2024-10-05 08:44 1917
  template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 1918
  auto get(basic_string_view<Char> name) const -> format_arg {
47fd5c32 Poul Sander 2024-10-05 08:44 1919
    int id = get_id(name);
47fd5c32 Poul Sander 2024-10-05 08:44 1920
    return id >= 0 ? get(id) : format_arg();
47fd5c32 Poul Sander 2024-10-05 08:44 1921
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1922
47fd5c32 Poul Sander 2024-10-05 08:44 1923
  template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 1924
  FMT_CONSTEXPR auto get_id(basic_string_view<Char> name) const -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 1925
    if (!has_named_args()) return -1;
47fd5c32 Poul Sander 2024-10-05 08:44 1926
    const auto& named_args =
47fd5c32 Poul Sander 2024-10-05 08:44 1927
        (is_packed() ? values_[-1] : args_[-1].value_).named_args;
47fd5c32 Poul Sander 2024-10-05 08:44 1928
    for (size_t i = 0; i < named_args.size; ++i) {
47fd5c32 Poul Sander 2024-10-05 08:44 1929
      if (named_args.data[i].name == name) return named_args.data[i].id;
47fd5c32 Poul Sander 2024-10-05 08:44 1930
    }
47fd5c32 Poul Sander 2024-10-05 08:44 1931
    return -1;
47fd5c32 Poul Sander 2024-10-05 08:44 1932
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1933
47fd5c32 Poul Sander 2024-10-05 08:44 1934
  auto max_size() const -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 1935
    unsigned long long max_packed = detail::max_packed_args;
47fd5c32 Poul Sander 2024-10-05 08:44 1936
    return static_cast<int>(is_packed() ? max_packed
47fd5c32 Poul Sander 2024-10-05 08:44 1937
                                        : desc_ & ~detail::is_unpacked_bit);
47fd5c32 Poul Sander 2024-10-05 08:44 1938
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1939
};
47fd5c32 Poul Sander 2024-10-05 08:44 1940
47fd5c32 Poul Sander 2024-10-05 08:44 1941
// A formatting context.
47fd5c32 Poul Sander 2024-10-05 08:44 1942
class context {
47fd5c32 Poul Sander 2024-10-05 08:44 1943
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 1944
  appender out_;
47fd5c32 Poul Sander 2024-10-05 08:44 1945
  basic_format_args<context> args_;
47fd5c32 Poul Sander 2024-10-05 08:44 1946
  detail::locale_ref loc_;
47fd5c32 Poul Sander 2024-10-05 08:44 1947
47fd5c32 Poul Sander 2024-10-05 08:44 1948
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 1949
  /// The character type for the output.
47fd5c32 Poul Sander 2024-10-05 08:44 1950
  using char_type = char;
47fd5c32 Poul Sander 2024-10-05 08:44 1951
47fd5c32 Poul Sander 2024-10-05 08:44 1952
  using iterator = appender;
47fd5c32 Poul Sander 2024-10-05 08:44 1953
  using format_arg = basic_format_arg<context>;
47fd5c32 Poul Sander 2024-10-05 08:44 1954
  using parse_context_type = basic_format_parse_context<char>;
47fd5c32 Poul Sander 2024-10-05 08:44 1955
  template <typename T> using formatter_type = formatter<T, char>;
47fd5c32 Poul Sander 2024-10-05 08:44 1956
47fd5c32 Poul Sander 2024-10-05 08:44 1957
  /// Constructs a `basic_format_context` object. References to the arguments
47fd5c32 Poul Sander 2024-10-05 08:44 1958
  /// are stored in the object so make sure they have appropriate lifetimes.
47fd5c32 Poul Sander 2024-10-05 08:44 1959
  FMT_CONSTEXPR context(iterator out, basic_format_args<context> ctx_args,
47fd5c32 Poul Sander 2024-10-05 08:44 1960
                        detail::locale_ref loc = {})
47fd5c32 Poul Sander 2024-10-05 08:44 1961
      : out_(out), args_(ctx_args), loc_(loc) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1962
  context(context&&) = default;
47fd5c32 Poul Sander 2024-10-05 08:44 1963
  context(const context&) = delete;
47fd5c32 Poul Sander 2024-10-05 08:44 1964
  void operator=(const context&) = delete;
47fd5c32 Poul Sander 2024-10-05 08:44 1965
47fd5c32 Poul Sander 2024-10-05 08:44 1966
  FMT_CONSTEXPR auto arg(int id) const -> format_arg { return args_.get(id); }
47fd5c32 Poul Sander 2024-10-05 08:44 1967
  auto arg(string_view name) -> format_arg { return args_.get(name); }
47fd5c32 Poul Sander 2024-10-05 08:44 1968
  FMT_CONSTEXPR auto arg_id(string_view name) -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 1969
    return args_.get_id(name);
47fd5c32 Poul Sander 2024-10-05 08:44 1970
  }
47fd5c32 Poul Sander 2024-10-05 08:44 1971
  auto args() const -> const basic_format_args<context>& { return args_; }
47fd5c32 Poul Sander 2024-10-05 08:44 1972
47fd5c32 Poul Sander 2024-10-05 08:44 1973
  // Returns an iterator to the beginning of the output range.
47fd5c32 Poul Sander 2024-10-05 08:44 1974
  FMT_CONSTEXPR auto out() -> iterator { return out_; }
47fd5c32 Poul Sander 2024-10-05 08:44 1975
47fd5c32 Poul Sander 2024-10-05 08:44 1976
  // Advances the begin iterator to `it`.
47fd5c32 Poul Sander 2024-10-05 08:44 1977
  void advance_to(iterator) {}
47fd5c32 Poul Sander 2024-10-05 08:44 1978
47fd5c32 Poul Sander 2024-10-05 08:44 1979
  FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; }
47fd5c32 Poul Sander 2024-10-05 08:44 1980
};
47fd5c32 Poul Sander 2024-10-05 08:44 1981
47fd5c32 Poul Sander 2024-10-05 08:44 1982
template <typename OutputIt, typename Char> class generic_context;
47fd5c32 Poul Sander 2024-10-05 08:44 1983
47fd5c32 Poul Sander 2024-10-05 08:44 1984
// Longer aliases for C++20 compatibility.
47fd5c32 Poul Sander 2024-10-05 08:44 1985
template <typename OutputIt, typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 1986
using basic_format_context =
47fd5c32 Poul Sander 2024-10-05 08:44 1987
    conditional_t<std::is_same<OutputIt, appender>::value, context,
47fd5c32 Poul Sander 2024-10-05 08:44 1988
                  generic_context<OutputIt, Char>>;
47fd5c32 Poul Sander 2024-10-05 08:44 1989
using format_context = context;
47fd5c32 Poul Sander 2024-10-05 08:44 1990
47fd5c32 Poul Sander 2024-10-05 08:44 1991
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 1992
using buffered_context = basic_format_context<basic_appender<Char>, Char>;
47fd5c32 Poul Sander 2024-10-05 08:44 1993
47fd5c32 Poul Sander 2024-10-05 08:44 1994
template <typename T, typename Char = char>
47fd5c32 Poul Sander 2024-10-05 08:44 1995
using is_formattable = bool_constant<!std::is_base_of<
47fd5c32 Poul Sander 2024-10-05 08:44 1996
    detail::unformattable, decltype(detail::arg_mapper<buffered_context<Char>>()
47fd5c32 Poul Sander 2024-10-05 08:44 1997
                                        .map(std::declval<T&>()))>::value>;
47fd5c32 Poul Sander 2024-10-05 08:44 1998
47fd5c32 Poul Sander 2024-10-05 08:44 1999
#if FMT_USE_CONCEPTS
47fd5c32 Poul Sander 2024-10-05 08:44 2000
template <typename T, typename Char = char>
47fd5c32 Poul Sander 2024-10-05 08:44 2001
concept formattable = is_formattable<remove_reference_t<T>, Char>::value;
47fd5c32 Poul Sander 2024-10-05 08:44 2002
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 2003
47fd5c32 Poul Sander 2024-10-05 08:44 2004
/**
47fd5c32 Poul Sander 2024-10-05 08:44 2005
 * Constructs an object that stores references to arguments and can be
47fd5c32 Poul Sander 2024-10-05 08:44 2006
 * implicitly converted to `format_args`. `Context` can be omitted in which case
47fd5c32 Poul Sander 2024-10-05 08:44 2007
 * it defaults to `format_context`. See `arg` for lifetime considerations.
47fd5c32 Poul Sander 2024-10-05 08:44 2008
 */
47fd5c32 Poul Sander 2024-10-05 08:44 2009
// Take arguments by lvalue references to avoid some lifetime issues, e.g.
47fd5c32 Poul Sander 2024-10-05 08:44 2010
//   auto args = make_format_args(std::string());
47fd5c32 Poul Sander 2024-10-05 08:44 2011
template <typename Context = format_context, typename... T,
47fd5c32 Poul Sander 2024-10-05 08:44 2012
          size_t NUM_ARGS = sizeof...(T),
47fd5c32 Poul Sander 2024-10-05 08:44 2013
          size_t NUM_NAMED_ARGS = detail::count_named_args<T...>(),
47fd5c32 Poul Sander 2024-10-05 08:44 2014
          unsigned long long DESC = detail::make_descriptor<Context, T...>(),
47fd5c32 Poul Sander 2024-10-05 08:44 2015
          FMT_ENABLE_IF(NUM_NAMED_ARGS == 0)>
47fd5c32 Poul Sander 2024-10-05 08:44 2016
constexpr FMT_ALWAYS_INLINE auto make_format_args(T&... args)
47fd5c32 Poul Sander 2024-10-05 08:44 2017
    -> detail::format_arg_store<Context, NUM_ARGS, 0, DESC> {
47fd5c32 Poul Sander 2024-10-05 08:44 2018
  return {{detail::make_arg<NUM_ARGS <= detail::max_packed_args, Context>(
47fd5c32 Poul Sander 2024-10-05 08:44 2019
      args)...}};
47fd5c32 Poul Sander 2024-10-05 08:44 2020
}
47fd5c32 Poul Sander 2024-10-05 08:44 2021
47fd5c32 Poul Sander 2024-10-05 08:44 2022
#ifndef FMT_DOC
47fd5c32 Poul Sander 2024-10-05 08:44 2023
template <typename Context = format_context, typename... T,
47fd5c32 Poul Sander 2024-10-05 08:44 2024
          size_t NUM_NAMED_ARGS = detail::count_named_args<T...>(),
47fd5c32 Poul Sander 2024-10-05 08:44 2025
          unsigned long long DESC =
47fd5c32 Poul Sander 2024-10-05 08:44 2026
              detail::make_descriptor<Context, T...>() |
47fd5c32 Poul Sander 2024-10-05 08:44 2027
              static_cast<unsigned long long>(detail::has_named_args_bit),
47fd5c32 Poul Sander 2024-10-05 08:44 2028
          FMT_ENABLE_IF(NUM_NAMED_ARGS != 0)>
47fd5c32 Poul Sander 2024-10-05 08:44 2029
constexpr auto make_format_args(T&... args)
47fd5c32 Poul Sander 2024-10-05 08:44 2030
    -> detail::format_arg_store<Context, sizeof...(T), NUM_NAMED_ARGS, DESC> {
47fd5c32 Poul Sander 2024-10-05 08:44 2031
  return {args...};
47fd5c32 Poul Sander 2024-10-05 08:44 2032
}
47fd5c32 Poul Sander 2024-10-05 08:44 2033
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 2034
47fd5c32 Poul Sander 2024-10-05 08:44 2035
/**
47fd5c32 Poul Sander 2024-10-05 08:44 2036
 * Returns a named argument to be used in a formatting function.
47fd5c32 Poul Sander 2024-10-05 08:44 2037
 * It should only be used in a call to a formatting function or
47fd5c32 Poul Sander 2024-10-05 08:44 2038
 * `dynamic_format_arg_store::push_back`.
47fd5c32 Poul Sander 2024-10-05 08:44 2039
 *
47fd5c32 Poul Sander 2024-10-05 08:44 2040
 * **Example**:
47fd5c32 Poul Sander 2024-10-05 08:44 2041
 *
47fd5c32 Poul Sander 2024-10-05 08:44 2042
 *     fmt::print("The answer is {answer}.", fmt::arg("answer", 42));
47fd5c32 Poul Sander 2024-10-05 08:44 2043
 */
47fd5c32 Poul Sander 2024-10-05 08:44 2044
template <typename Char, typename T>
47fd5c32 Poul Sander 2024-10-05 08:44 2045
inline auto arg(const Char* name, const T& arg) -> detail::named_arg<Char, T> {
47fd5c32 Poul Sander 2024-10-05 08:44 2046
  static_assert(!detail::is_named_arg<T>(), "nested named arguments");
47fd5c32 Poul Sander 2024-10-05 08:44 2047
  return {name, arg};
47fd5c32 Poul Sander 2024-10-05 08:44 2048
}
47fd5c32 Poul Sander 2024-10-05 08:44 2049
FMT_END_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 2050
47fd5c32 Poul Sander 2024-10-05 08:44 2051
/// An alias for `basic_format_args<format_context>`.
47fd5c32 Poul Sander 2024-10-05 08:44 2052
// A separate type would result in shorter symbols but break ABI compatibility
47fd5c32 Poul Sander 2024-10-05 08:44 2053
// between clang and gcc on ARM (#1919).
47fd5c32 Poul Sander 2024-10-05 08:44 2054
FMT_EXPORT using format_args = basic_format_args<format_context>;
47fd5c32 Poul Sander 2024-10-05 08:44 2055
47fd5c32 Poul Sander 2024-10-05 08:44 2056
// We cannot use enum classes as bit fields because of a gcc bug, so we put them
47fd5c32 Poul Sander 2024-10-05 08:44 2057
// in namespaces instead (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414).
47fd5c32 Poul Sander 2024-10-05 08:44 2058
// Additionally, if an underlying type is specified, older gcc incorrectly warns
47fd5c32 Poul Sander 2024-10-05 08:44 2059
// that the type is too small. Both bugs are fixed in gcc 9.3.
47fd5c32 Poul Sander 2024-10-05 08:44 2060
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 903
47fd5c32 Poul Sander 2024-10-05 08:44 2061
#  define FMT_ENUM_UNDERLYING_TYPE(type)
47fd5c32 Poul Sander 2024-10-05 08:44 2062
#else
47fd5c32 Poul Sander 2024-10-05 08:44 2063
#  define FMT_ENUM_UNDERLYING_TYPE(type) : type
47fd5c32 Poul Sander 2024-10-05 08:44 2064
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 2065
namespace align {
47fd5c32 Poul Sander 2024-10-05 08:44 2066
enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, left, right, center,
47fd5c32 Poul Sander 2024-10-05 08:44 2067
                                                  numeric};
47fd5c32 Poul Sander 2024-10-05 08:44 2068
}
47fd5c32 Poul Sander 2024-10-05 08:44 2069
using align_t = align::type;
47fd5c32 Poul Sander 2024-10-05 08:44 2070
namespace sign {
47fd5c32 Poul Sander 2024-10-05 08:44 2071
enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, minus, plus, space};
47fd5c32 Poul Sander 2024-10-05 08:44 2072
}
47fd5c32 Poul Sander 2024-10-05 08:44 2073
using sign_t = sign::type;
47fd5c32 Poul Sander 2024-10-05 08:44 2074
47fd5c32 Poul Sander 2024-10-05 08:44 2075
namespace detail {
47fd5c32 Poul Sander 2024-10-05 08:44 2076
47fd5c32 Poul Sander 2024-10-05 08:44 2077
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 2078
using unsigned_char = typename conditional_t<std::is_integral<Char>::value,
47fd5c32 Poul Sander 2024-10-05 08:44 2079
                                             std::make_unsigned<Char>,
47fd5c32 Poul Sander 2024-10-05 08:44 2080
                                             type_identity<unsigned>>::type;
47fd5c32 Poul Sander 2024-10-05 08:44 2081
47fd5c32 Poul Sander 2024-10-05 08:44 2082
// Character (code unit) type is erased to prevent template bloat.
47fd5c32 Poul Sander 2024-10-05 08:44 2083
struct fill_t {
47fd5c32 Poul Sander 2024-10-05 08:44 2084
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 2085
  enum { max_size = 4 };
47fd5c32 Poul Sander 2024-10-05 08:44 2086
  char data_[max_size] = {' '};
47fd5c32 Poul Sander 2024-10-05 08:44 2087
  unsigned char size_ = 1;
47fd5c32 Poul Sander 2024-10-05 08:44 2088
47fd5c32 Poul Sander 2024-10-05 08:44 2089
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 2090
  template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 2091
  FMT_CONSTEXPR void operator=(basic_string_view<Char> s) {
47fd5c32 Poul Sander 2024-10-05 08:44 2092
    auto size = s.size();
47fd5c32 Poul Sander 2024-10-05 08:44 2093
    size_ = static_cast<unsigned char>(size);
47fd5c32 Poul Sander 2024-10-05 08:44 2094
    if (size == 1) {
47fd5c32 Poul Sander 2024-10-05 08:44 2095
      unsigned uchar = static_cast<unsigned_char<Char>>(s[0]);
47fd5c32 Poul Sander 2024-10-05 08:44 2096
      data_[0] = static_cast<char>(uchar);
47fd5c32 Poul Sander 2024-10-05 08:44 2097
      data_[1] = static_cast<char>(uchar >> 8);
47fd5c32 Poul Sander 2024-10-05 08:44 2098
      return;
47fd5c32 Poul Sander 2024-10-05 08:44 2099
    }
47fd5c32 Poul Sander 2024-10-05 08:44 2100
    FMT_ASSERT(size <= max_size, "invalid fill");
47fd5c32 Poul Sander 2024-10-05 08:44 2101
    for (size_t i = 0; i < size; ++i) data_[i] = static_cast<char>(s[i]);
47fd5c32 Poul Sander 2024-10-05 08:44 2102
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2103
47fd5c32 Poul Sander 2024-10-05 08:44 2104
  FMT_CONSTEXPR void operator=(char c) {
47fd5c32 Poul Sander 2024-10-05 08:44 2105
    data_[0] = c;
47fd5c32 Poul Sander 2024-10-05 08:44 2106
    size_ = 1;
47fd5c32 Poul Sander 2024-10-05 08:44 2107
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2108
47fd5c32 Poul Sander 2024-10-05 08:44 2109
  constexpr auto size() const -> size_t { return size_; }
47fd5c32 Poul Sander 2024-10-05 08:44 2110
47fd5c32 Poul Sander 2024-10-05 08:44 2111
  template <typename Char> constexpr auto get() const -> Char {
47fd5c32 Poul Sander 2024-10-05 08:44 2112
    using uchar = unsigned char;
47fd5c32 Poul Sander 2024-10-05 08:44 2113
    return static_cast<Char>(static_cast<uchar>(data_[0]) |
47fd5c32 Poul Sander 2024-10-05 08:44 2114
                             (static_cast<uchar>(data_[1]) << 8));
47fd5c32 Poul Sander 2024-10-05 08:44 2115
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2116
47fd5c32 Poul Sander 2024-10-05 08:44 2117
  template <typename Char, FMT_ENABLE_IF(std::is_same<Char, char>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 2118
  constexpr auto data() const -> const Char* {
47fd5c32 Poul Sander 2024-10-05 08:44 2119
    return data_;
47fd5c32 Poul Sander 2024-10-05 08:44 2120
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2121
  template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 2122
  constexpr auto data() const -> const Char* {
47fd5c32 Poul Sander 2024-10-05 08:44 2123
    return nullptr;
47fd5c32 Poul Sander 2024-10-05 08:44 2124
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2125
};
47fd5c32 Poul Sander 2024-10-05 08:44 2126
}  // namespace detail
47fd5c32 Poul Sander 2024-10-05 08:44 2127
47fd5c32 Poul Sander 2024-10-05 08:44 2128
enum class presentation_type : unsigned char {
47fd5c32 Poul Sander 2024-10-05 08:44 2129
  // Common specifiers:
47fd5c32 Poul Sander 2024-10-05 08:44 2130
  none = 0,
47fd5c32 Poul Sander 2024-10-05 08:44 2131
  debug = 1,   // '?'
47fd5c32 Poul Sander 2024-10-05 08:44 2132
  string = 2,  // 's' (string, bool)
47fd5c32 Poul Sander 2024-10-05 08:44 2133
47fd5c32 Poul Sander 2024-10-05 08:44 2134
  // Integral, bool and character specifiers:
47fd5c32 Poul Sander 2024-10-05 08:44 2135
  dec = 3,  // 'd'
47fd5c32 Poul Sander 2024-10-05 08:44 2136
  hex,      // 'x' or 'X'
47fd5c32 Poul Sander 2024-10-05 08:44 2137
  oct,      // 'o'
47fd5c32 Poul Sander 2024-10-05 08:44 2138
  bin,      // 'b' or 'B'
47fd5c32 Poul Sander 2024-10-05 08:44 2139
  chr,      // 'c'
47fd5c32 Poul Sander 2024-10-05 08:44 2140
47fd5c32 Poul Sander 2024-10-05 08:44 2141
  // String and pointer specifiers:
47fd5c32 Poul Sander 2024-10-05 08:44 2142
  pointer = 3,  // 'p'
47fd5c32 Poul Sander 2024-10-05 08:44 2143
47fd5c32 Poul Sander 2024-10-05 08:44 2144
  // Floating-point specifiers:
47fd5c32 Poul Sander 2024-10-05 08:44 2145
  exp = 1,  // 'e' or 'E' (1 since there is no FP debug presentation)
47fd5c32 Poul Sander 2024-10-05 08:44 2146
  fixed,    // 'f' or 'F'
47fd5c32 Poul Sander 2024-10-05 08:44 2147
  general,  // 'g' or 'G'
47fd5c32 Poul Sander 2024-10-05 08:44 2148
  hexfloat  // 'a' or 'A'
47fd5c32 Poul Sander 2024-10-05 08:44 2149
};
47fd5c32 Poul Sander 2024-10-05 08:44 2150
47fd5c32 Poul Sander 2024-10-05 08:44 2151
// Format specifiers for built-in and string types.
47fd5c32 Poul Sander 2024-10-05 08:44 2152
struct format_specs {
47fd5c32 Poul Sander 2024-10-05 08:44 2153
  int width;
47fd5c32 Poul Sander 2024-10-05 08:44 2154
  int precision;
47fd5c32 Poul Sander 2024-10-05 08:44 2155
  presentation_type type;
47fd5c32 Poul Sander 2024-10-05 08:44 2156
  align_t align : 4;
47fd5c32 Poul Sander 2024-10-05 08:44 2157
  sign_t sign : 3;
47fd5c32 Poul Sander 2024-10-05 08:44 2158
  bool upper : 1;  // An uppercase version e.g. 'X' for 'x'.
47fd5c32 Poul Sander 2024-10-05 08:44 2159
  bool alt : 1;    // Alternate form ('#').
47fd5c32 Poul Sander 2024-10-05 08:44 2160
  bool localized : 1;
47fd5c32 Poul Sander 2024-10-05 08:44 2161
  detail::fill_t fill;
47fd5c32 Poul Sander 2024-10-05 08:44 2162
47fd5c32 Poul Sander 2024-10-05 08:44 2163
  constexpr format_specs()
47fd5c32 Poul Sander 2024-10-05 08:44 2164
      : width(0),
47fd5c32 Poul Sander 2024-10-05 08:44 2165
        precision(-1),
47fd5c32 Poul Sander 2024-10-05 08:44 2166
        type(presentation_type::none),
47fd5c32 Poul Sander 2024-10-05 08:44 2167
        align(align::none),
47fd5c32 Poul Sander 2024-10-05 08:44 2168
        sign(sign::none),
47fd5c32 Poul Sander 2024-10-05 08:44 2169
        upper(false),
47fd5c32 Poul Sander 2024-10-05 08:44 2170
        alt(false),
47fd5c32 Poul Sander 2024-10-05 08:44 2171
        localized(false) {}
47fd5c32 Poul Sander 2024-10-05 08:44 2172
};
47fd5c32 Poul Sander 2024-10-05 08:44 2173
47fd5c32 Poul Sander 2024-10-05 08:44 2174
namespace detail {
47fd5c32 Poul Sander 2024-10-05 08:44 2175
47fd5c32 Poul Sander 2024-10-05 08:44 2176
enum class arg_id_kind { none, index, name };
47fd5c32 Poul Sander 2024-10-05 08:44 2177
47fd5c32 Poul Sander 2024-10-05 08:44 2178
// An argument reference.
47fd5c32 Poul Sander 2024-10-05 08:44 2179
template <typename Char> struct arg_ref {
47fd5c32 Poul Sander 2024-10-05 08:44 2180
  FMT_CONSTEXPR arg_ref() : kind(arg_id_kind::none), val() {}
47fd5c32 Poul Sander 2024-10-05 08:44 2181
47fd5c32 Poul Sander 2024-10-05 08:44 2182
  FMT_CONSTEXPR explicit arg_ref(int index)
47fd5c32 Poul Sander 2024-10-05 08:44 2183
      : kind(arg_id_kind::index), val(index) {}
47fd5c32 Poul Sander 2024-10-05 08:44 2184
  FMT_CONSTEXPR explicit arg_ref(basic_string_view<Char> name)
47fd5c32 Poul Sander 2024-10-05 08:44 2185
      : kind(arg_id_kind::name), val(name) {}
47fd5c32 Poul Sander 2024-10-05 08:44 2186
47fd5c32 Poul Sander 2024-10-05 08:44 2187
  FMT_CONSTEXPR auto operator=(int idx) -> arg_ref& {
47fd5c32 Poul Sander 2024-10-05 08:44 2188
    kind = arg_id_kind::index;
47fd5c32 Poul Sander 2024-10-05 08:44 2189
    val.index = idx;
47fd5c32 Poul Sander 2024-10-05 08:44 2190
    return *this;
47fd5c32 Poul Sander 2024-10-05 08:44 2191
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2192
47fd5c32 Poul Sander 2024-10-05 08:44 2193
  arg_id_kind kind;
47fd5c32 Poul Sander 2024-10-05 08:44 2194
  union value {
47fd5c32 Poul Sander 2024-10-05 08:44 2195
    FMT_CONSTEXPR value(int idx = 0) : index(idx) {}
47fd5c32 Poul Sander 2024-10-05 08:44 2196
    FMT_CONSTEXPR value(basic_string_view<Char> n) : name(n) {}
47fd5c32 Poul Sander 2024-10-05 08:44 2197
47fd5c32 Poul Sander 2024-10-05 08:44 2198
    int index;
47fd5c32 Poul Sander 2024-10-05 08:44 2199
    basic_string_view<Char> name;
47fd5c32 Poul Sander 2024-10-05 08:44 2200
  } val;
47fd5c32 Poul Sander 2024-10-05 08:44 2201
};
47fd5c32 Poul Sander 2024-10-05 08:44 2202
47fd5c32 Poul Sander 2024-10-05 08:44 2203
// Format specifiers with width and precision resolved at formatting rather
47fd5c32 Poul Sander 2024-10-05 08:44 2204
// than parsing time to allow reusing the same parsed specifiers with
47fd5c32 Poul Sander 2024-10-05 08:44 2205
// different sets of arguments (precompilation of format strings).
47fd5c32 Poul Sander 2024-10-05 08:44 2206
template <typename Char = char> struct dynamic_format_specs : format_specs {
47fd5c32 Poul Sander 2024-10-05 08:44 2207
  arg_ref<Char> width_ref;
47fd5c32 Poul Sander 2024-10-05 08:44 2208
  arg_ref<Char> precision_ref;
47fd5c32 Poul Sander 2024-10-05 08:44 2209
};
47fd5c32 Poul Sander 2024-10-05 08:44 2210
47fd5c32 Poul Sander 2024-10-05 08:44 2211
// Converts a character to ASCII. Returns '\0' on conversion failure.
47fd5c32 Poul Sander 2024-10-05 08:44 2212
template <typename Char, FMT_ENABLE_IF(std::is_integral<Char>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 2213
constexpr auto to_ascii(Char c) -> char {
47fd5c32 Poul Sander 2024-10-05 08:44 2214
  return c <= 0xff ? static_cast<char>(c) : '\0';
47fd5c32 Poul Sander 2024-10-05 08:44 2215
}
47fd5c32 Poul Sander 2024-10-05 08:44 2216
47fd5c32 Poul Sander 2024-10-05 08:44 2217
// Returns the number of code units in a code point or 1 on error.
47fd5c32 Poul Sander 2024-10-05 08:44 2218
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 2219
FMT_CONSTEXPR auto code_point_length(const Char* begin) -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 2220
  if (const_check(sizeof(Char) != 1)) return 1;
47fd5c32 Poul Sander 2024-10-05 08:44 2221
  auto c = static_cast<unsigned char>(*begin);
47fd5c32 Poul Sander 2024-10-05 08:44 2222
  return static_cast<int>((0x3a55000000000000ull >> (2 * (c >> 3))) & 0x3) + 1;
47fd5c32 Poul Sander 2024-10-05 08:44 2223
}
47fd5c32 Poul Sander 2024-10-05 08:44 2224
47fd5c32 Poul Sander 2024-10-05 08:44 2225
// Return the result via the out param to workaround gcc bug 77539.
47fd5c32 Poul Sander 2024-10-05 08:44 2226
template <bool IS_CONSTEXPR, typename T, typename Ptr = const T*>
47fd5c32 Poul Sander 2024-10-05 08:44 2227
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr& out) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 2228
  for (out = first; out != last; ++out) {
47fd5c32 Poul Sander 2024-10-05 08:44 2229
    if (*out == value) return true;
47fd5c32 Poul Sander 2024-10-05 08:44 2230
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2231
  return false;
47fd5c32 Poul Sander 2024-10-05 08:44 2232
}
47fd5c32 Poul Sander 2024-10-05 08:44 2233
47fd5c32 Poul Sander 2024-10-05 08:44 2234
template <>
47fd5c32 Poul Sander 2024-10-05 08:44 2235
inline auto find<false, char>(const char* first, const char* last, char value,
47fd5c32 Poul Sander 2024-10-05 08:44 2236
                              const char*& out) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 2237
  out =
47fd5c32 Poul Sander 2024-10-05 08:44 2238
      static_cast<const char*>(memchr(first, value, to_unsigned(last - first)));
47fd5c32 Poul Sander 2024-10-05 08:44 2239
  return out != nullptr;
47fd5c32 Poul Sander 2024-10-05 08:44 2240
}
47fd5c32 Poul Sander 2024-10-05 08:44 2241
47fd5c32 Poul Sander 2024-10-05 08:44 2242
// Parses the range [begin, end) as an unsigned integer. This function assumes
47fd5c32 Poul Sander 2024-10-05 08:44 2243
// that the range is non-empty and the first character is a digit.
47fd5c32 Poul Sander 2024-10-05 08:44 2244
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 2245
FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end,
47fd5c32 Poul Sander 2024-10-05 08:44 2246
                                         int error_value) noexcept -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 2247
  FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', "");
47fd5c32 Poul Sander 2024-10-05 08:44 2248
  unsigned value = 0, prev = 0;
47fd5c32 Poul Sander 2024-10-05 08:44 2249
  auto p = begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2250
  do {
47fd5c32 Poul Sander 2024-10-05 08:44 2251
    prev = value;
47fd5c32 Poul Sander 2024-10-05 08:44 2252
    value = value * 10 + unsigned(*p - '0');
47fd5c32 Poul Sander 2024-10-05 08:44 2253
    ++p;
47fd5c32 Poul Sander 2024-10-05 08:44 2254
  } while (p != end && '0' <= *p && *p <= '9');
47fd5c32 Poul Sander 2024-10-05 08:44 2255
  auto num_digits = p - begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2256
  begin = p;
47fd5c32 Poul Sander 2024-10-05 08:44 2257
  int digits10 = static_cast<int>(sizeof(int) * CHAR_BIT * 3 / 10);
47fd5c32 Poul Sander 2024-10-05 08:44 2258
  if (num_digits <= digits10) return static_cast<int>(value);
47fd5c32 Poul Sander 2024-10-05 08:44 2259
  // Check for overflow.
47fd5c32 Poul Sander 2024-10-05 08:44 2260
  unsigned max = INT_MAX;
47fd5c32 Poul Sander 2024-10-05 08:44 2261
  return num_digits == digits10 + 1 &&
47fd5c32 Poul Sander 2024-10-05 08:44 2262
                 prev * 10ull + unsigned(p[-1] - '0') <= max
47fd5c32 Poul Sander 2024-10-05 08:44 2263
             ? static_cast<int>(value)
47fd5c32 Poul Sander 2024-10-05 08:44 2264
             : error_value;
47fd5c32 Poul Sander 2024-10-05 08:44 2265
}
47fd5c32 Poul Sander 2024-10-05 08:44 2266
47fd5c32 Poul Sander 2024-10-05 08:44 2267
FMT_CONSTEXPR inline auto parse_align(char c) -> align_t {
47fd5c32 Poul Sander 2024-10-05 08:44 2268
  switch (c) {
47fd5c32 Poul Sander 2024-10-05 08:44 2269
  case '<':
47fd5c32 Poul Sander 2024-10-05 08:44 2270
    return align::left;
47fd5c32 Poul Sander 2024-10-05 08:44 2271
  case '>':
47fd5c32 Poul Sander 2024-10-05 08:44 2272
    return align::right;
47fd5c32 Poul Sander 2024-10-05 08:44 2273
  case '^':
47fd5c32 Poul Sander 2024-10-05 08:44 2274
    return align::center;
47fd5c32 Poul Sander 2024-10-05 08:44 2275
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2276
  return align::none;
47fd5c32 Poul Sander 2024-10-05 08:44 2277
}
47fd5c32 Poul Sander 2024-10-05 08:44 2278
47fd5c32 Poul Sander 2024-10-05 08:44 2279
template <typename Char> constexpr auto is_name_start(Char c) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 2280
  return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '_';
47fd5c32 Poul Sander 2024-10-05 08:44 2281
}
47fd5c32 Poul Sander 2024-10-05 08:44 2282
47fd5c32 Poul Sander 2024-10-05 08:44 2283
template <typename Char, typename Handler>
47fd5c32 Poul Sander 2024-10-05 08:44 2284
FMT_CONSTEXPR auto do_parse_arg_id(const Char* begin, const Char* end,
47fd5c32 Poul Sander 2024-10-05 08:44 2285
                                   Handler&& handler) -> const Char* {
47fd5c32 Poul Sander 2024-10-05 08:44 2286
  Char c = *begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2287
  if (c >= '0' && c <= '9') {
47fd5c32 Poul Sander 2024-10-05 08:44 2288
    int index = 0;
47fd5c32 Poul Sander 2024-10-05 08:44 2289
    if (c != '0')
47fd5c32 Poul Sander 2024-10-05 08:44 2290
      index = parse_nonnegative_int(begin, end, INT_MAX);
47fd5c32 Poul Sander 2024-10-05 08:44 2291
    else
47fd5c32 Poul Sander 2024-10-05 08:44 2292
      ++begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2293
    if (begin == end || (*begin != '}' && *begin != ':'))
47fd5c32 Poul Sander 2024-10-05 08:44 2294
      report_error("invalid format string");
47fd5c32 Poul Sander 2024-10-05 08:44 2295
    else
47fd5c32 Poul Sander 2024-10-05 08:44 2296
      handler.on_index(index);
47fd5c32 Poul Sander 2024-10-05 08:44 2297
    return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2298
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2299
  if (!is_name_start(c)) {
47fd5c32 Poul Sander 2024-10-05 08:44 2300
    report_error("invalid format string");
47fd5c32 Poul Sander 2024-10-05 08:44 2301
    return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2302
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2303
  auto it = begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2304
  do {
47fd5c32 Poul Sander 2024-10-05 08:44 2305
    ++it;
47fd5c32 Poul Sander 2024-10-05 08:44 2306
  } while (it != end && (is_name_start(*it) || ('0' <= *it && *it <= '9')));
47fd5c32 Poul Sander 2024-10-05 08:44 2307
  handler.on_name({begin, to_unsigned(it - begin)});
47fd5c32 Poul Sander 2024-10-05 08:44 2308
  return it;
47fd5c32 Poul Sander 2024-10-05 08:44 2309
}
47fd5c32 Poul Sander 2024-10-05 08:44 2310
47fd5c32 Poul Sander 2024-10-05 08:44 2311
template <typename Char, typename Handler>
47fd5c32 Poul Sander 2024-10-05 08:44 2312
FMT_CONSTEXPR auto parse_arg_id(const Char* begin, const Char* end,
47fd5c32 Poul Sander 2024-10-05 08:44 2313
                                Handler&& handler) -> const Char* {
47fd5c32 Poul Sander 2024-10-05 08:44 2314
  FMT_ASSERT(begin != end, "");
47fd5c32 Poul Sander 2024-10-05 08:44 2315
  Char c = *begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2316
  if (c != '}' && c != ':') return do_parse_arg_id(begin, end, handler);
47fd5c32 Poul Sander 2024-10-05 08:44 2317
  handler.on_auto();
47fd5c32 Poul Sander 2024-10-05 08:44 2318
  return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2319
}
47fd5c32 Poul Sander 2024-10-05 08:44 2320
47fd5c32 Poul Sander 2024-10-05 08:44 2321
template <typename Char> struct dynamic_spec_id_handler {
47fd5c32 Poul Sander 2024-10-05 08:44 2322
  basic_format_parse_context<Char>& ctx;
47fd5c32 Poul Sander 2024-10-05 08:44 2323
  arg_ref<Char>& ref;
47fd5c32 Poul Sander 2024-10-05 08:44 2324
47fd5c32 Poul Sander 2024-10-05 08:44 2325
  FMT_CONSTEXPR void on_auto() {
47fd5c32 Poul Sander 2024-10-05 08:44 2326
    int id = ctx.next_arg_id();
47fd5c32 Poul Sander 2024-10-05 08:44 2327
    ref = arg_ref<Char>(id);
47fd5c32 Poul Sander 2024-10-05 08:44 2328
    ctx.check_dynamic_spec(id);
47fd5c32 Poul Sander 2024-10-05 08:44 2329
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2330
  FMT_CONSTEXPR void on_index(int id) {
47fd5c32 Poul Sander 2024-10-05 08:44 2331
    ref = arg_ref<Char>(id);
47fd5c32 Poul Sander 2024-10-05 08:44 2332
    ctx.check_arg_id(id);
47fd5c32 Poul Sander 2024-10-05 08:44 2333
    ctx.check_dynamic_spec(id);
47fd5c32 Poul Sander 2024-10-05 08:44 2334
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2335
  FMT_CONSTEXPR void on_name(basic_string_view<Char> id) {
47fd5c32 Poul Sander 2024-10-05 08:44 2336
    ref = arg_ref<Char>(id);
47fd5c32 Poul Sander 2024-10-05 08:44 2337
    ctx.check_arg_id(id);
47fd5c32 Poul Sander 2024-10-05 08:44 2338
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2339
};
47fd5c32 Poul Sander 2024-10-05 08:44 2340
47fd5c32 Poul Sander 2024-10-05 08:44 2341
// Parses [integer | "{" [arg_id] "}"].
47fd5c32 Poul Sander 2024-10-05 08:44 2342
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 2343
FMT_CONSTEXPR auto parse_dynamic_spec(const Char* begin, const Char* end,
47fd5c32 Poul Sander 2024-10-05 08:44 2344
                                      int& value, arg_ref<Char>& ref,
47fd5c32 Poul Sander 2024-10-05 08:44 2345
                                      basic_format_parse_context<Char>& ctx)
47fd5c32 Poul Sander 2024-10-05 08:44 2346
    -> const Char* {
47fd5c32 Poul Sander 2024-10-05 08:44 2347
  FMT_ASSERT(begin != end, "");
47fd5c32 Poul Sander 2024-10-05 08:44 2348
  if ('0' <= *begin && *begin <= '9') {
47fd5c32 Poul Sander 2024-10-05 08:44 2349
    int val = parse_nonnegative_int(begin, end, -1);
47fd5c32 Poul Sander 2024-10-05 08:44 2350
    if (val != -1)
47fd5c32 Poul Sander 2024-10-05 08:44 2351
      value = val;
47fd5c32 Poul Sander 2024-10-05 08:44 2352
    else
47fd5c32 Poul Sander 2024-10-05 08:44 2353
      report_error("number is too big");
47fd5c32 Poul Sander 2024-10-05 08:44 2354
  } else if (*begin == '{') {
47fd5c32 Poul Sander 2024-10-05 08:44 2355
    ++begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2356
    auto handler = dynamic_spec_id_handler<Char>{ctx, ref};
47fd5c32 Poul Sander 2024-10-05 08:44 2357
    if (begin != end) begin = parse_arg_id(begin, end, handler);
47fd5c32 Poul Sander 2024-10-05 08:44 2358
    if (begin != end && *begin == '}') return ++begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2359
    report_error("invalid format string");
47fd5c32 Poul Sander 2024-10-05 08:44 2360
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2361
  return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2362
}
47fd5c32 Poul Sander 2024-10-05 08:44 2363
47fd5c32 Poul Sander 2024-10-05 08:44 2364
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 2365
FMT_CONSTEXPR auto parse_precision(const Char* begin, const Char* end,
47fd5c32 Poul Sander 2024-10-05 08:44 2366
                                   int& value, arg_ref<Char>& ref,
47fd5c32 Poul Sander 2024-10-05 08:44 2367
                                   basic_format_parse_context<Char>& ctx)
47fd5c32 Poul Sander 2024-10-05 08:44 2368
    -> const Char* {
47fd5c32 Poul Sander 2024-10-05 08:44 2369
  ++begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2370
  if (begin == end || *begin == '}') {
47fd5c32 Poul Sander 2024-10-05 08:44 2371
    report_error("invalid precision");
47fd5c32 Poul Sander 2024-10-05 08:44 2372
    return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2373
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2374
  return parse_dynamic_spec(begin, end, value, ref, ctx);
47fd5c32 Poul Sander 2024-10-05 08:44 2375
}
47fd5c32 Poul Sander 2024-10-05 08:44 2376
47fd5c32 Poul Sander 2024-10-05 08:44 2377
enum class state { start, align, sign, hash, zero, width, precision, locale };
47fd5c32 Poul Sander 2024-10-05 08:44 2378
47fd5c32 Poul Sander 2024-10-05 08:44 2379
// Parses standard format specifiers.
47fd5c32 Poul Sander 2024-10-05 08:44 2380
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 2381
FMT_CONSTEXPR auto parse_format_specs(const Char* begin, const Char* end,
47fd5c32 Poul Sander 2024-10-05 08:44 2382
                                      dynamic_format_specs<Char>& specs,
47fd5c32 Poul Sander 2024-10-05 08:44 2383
                                      basic_format_parse_context<Char>& ctx,
47fd5c32 Poul Sander 2024-10-05 08:44 2384
                                      type arg_type) -> const Char* {
47fd5c32 Poul Sander 2024-10-05 08:44 2385
  auto c = '\0';
47fd5c32 Poul Sander 2024-10-05 08:44 2386
  if (end - begin > 1) {
47fd5c32 Poul Sander 2024-10-05 08:44 2387
    auto next = to_ascii(begin[1]);
47fd5c32 Poul Sander 2024-10-05 08:44 2388
    c = parse_align(next) == align::none ? to_ascii(*begin) : '\0';
47fd5c32 Poul Sander 2024-10-05 08:44 2389
  } else {
47fd5c32 Poul Sander 2024-10-05 08:44 2390
    if (begin == end) return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2391
    c = to_ascii(*begin);
47fd5c32 Poul Sander 2024-10-05 08:44 2392
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2393
47fd5c32 Poul Sander 2024-10-05 08:44 2394
  struct {
47fd5c32 Poul Sander 2024-10-05 08:44 2395
    state current_state = state::start;
47fd5c32 Poul Sander 2024-10-05 08:44 2396
    FMT_CONSTEXPR void operator()(state s, bool valid = true) {
47fd5c32 Poul Sander 2024-10-05 08:44 2397
      if (current_state >= s || !valid)
47fd5c32 Poul Sander 2024-10-05 08:44 2398
        report_error("invalid format specifier");
47fd5c32 Poul Sander 2024-10-05 08:44 2399
      current_state = s;
47fd5c32 Poul Sander 2024-10-05 08:44 2400
    }
47fd5c32 Poul Sander 2024-10-05 08:44 2401
  } enter_state;
47fd5c32 Poul Sander 2024-10-05 08:44 2402
47fd5c32 Poul Sander 2024-10-05 08:44 2403
  using pres = presentation_type;
47fd5c32 Poul Sander 2024-10-05 08:44 2404
  constexpr auto integral_set = sint_set | uint_set | bool_set | char_set;
47fd5c32 Poul Sander 2024-10-05 08:44 2405
  struct {
47fd5c32 Poul Sander 2024-10-05 08:44 2406
    const Char*& begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2407
    dynamic_format_specs<Char>& specs;
47fd5c32 Poul Sander 2024-10-05 08:44 2408
    type arg_type;
47fd5c32 Poul Sander 2024-10-05 08:44 2409
47fd5c32 Poul Sander 2024-10-05 08:44 2410
    FMT_CONSTEXPR auto operator()(pres pres_type, int set) -> const Char* {
47fd5c32 Poul Sander 2024-10-05 08:44 2411
      if (!in(arg_type, set)) {
47fd5c32 Poul Sander 2024-10-05 08:44 2412
        if (arg_type == type::none_type) return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2413
        report_error("invalid format specifier");
47fd5c32 Poul Sander 2024-10-05 08:44 2414
      }
47fd5c32 Poul Sander 2024-10-05 08:44 2415
      specs.type = pres_type;
47fd5c32 Poul Sander 2024-10-05 08:44 2416
      return begin + 1;
47fd5c32 Poul Sander 2024-10-05 08:44 2417
    }
47fd5c32 Poul Sander 2024-10-05 08:44 2418
  } parse_presentation_type{begin, specs, arg_type};
47fd5c32 Poul Sander 2024-10-05 08:44 2419
47fd5c32 Poul Sander 2024-10-05 08:44 2420
  for (;;) {
47fd5c32 Poul Sander 2024-10-05 08:44 2421
    switch (c) {
47fd5c32 Poul Sander 2024-10-05 08:44 2422
    case '<':
47fd5c32 Poul Sander 2024-10-05 08:44 2423
    case '>':
47fd5c32 Poul Sander 2024-10-05 08:44 2424
    case '^':
47fd5c32 Poul Sander 2024-10-05 08:44 2425
      enter_state(state::align);
47fd5c32 Poul Sander 2024-10-05 08:44 2426
      specs.align = parse_align(c);
47fd5c32 Poul Sander 2024-10-05 08:44 2427
      ++begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2428
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 2429
    case '+':
47fd5c32 Poul Sander 2024-10-05 08:44 2430
    case '-':
47fd5c32 Poul Sander 2024-10-05 08:44 2431
    case ' ':
47fd5c32 Poul Sander 2024-10-05 08:44 2432
      if (arg_type == type::none_type) return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2433
      enter_state(state::sign, in(arg_type, sint_set | float_set));
47fd5c32 Poul Sander 2024-10-05 08:44 2434
      switch (c) {
47fd5c32 Poul Sander 2024-10-05 08:44 2435
      case '+':
47fd5c32 Poul Sander 2024-10-05 08:44 2436
        specs.sign = sign::plus;
47fd5c32 Poul Sander 2024-10-05 08:44 2437
        break;
47fd5c32 Poul Sander 2024-10-05 08:44 2438
      case '-':
47fd5c32 Poul Sander 2024-10-05 08:44 2439
        specs.sign = sign::minus;
47fd5c32 Poul Sander 2024-10-05 08:44 2440
        break;
47fd5c32 Poul Sander 2024-10-05 08:44 2441
      case ' ':
47fd5c32 Poul Sander 2024-10-05 08:44 2442
        specs.sign = sign::space;
47fd5c32 Poul Sander 2024-10-05 08:44 2443
        break;
47fd5c32 Poul Sander 2024-10-05 08:44 2444
      }
47fd5c32 Poul Sander 2024-10-05 08:44 2445
      ++begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2446
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 2447
    case '#':
47fd5c32 Poul Sander 2024-10-05 08:44 2448
      if (arg_type == type::none_type) return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2449
      enter_state(state::hash, is_arithmetic_type(arg_type));
47fd5c32 Poul Sander 2024-10-05 08:44 2450
      specs.alt = true;
47fd5c32 Poul Sander 2024-10-05 08:44 2451
      ++begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2452
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 2453
    case '0':
47fd5c32 Poul Sander 2024-10-05 08:44 2454
      enter_state(state::zero);
47fd5c32 Poul Sander 2024-10-05 08:44 2455
      if (!is_arithmetic_type(arg_type)) {
47fd5c32 Poul Sander 2024-10-05 08:44 2456
        if (arg_type == type::none_type) return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2457
        report_error("format specifier requires numeric argument");
47fd5c32 Poul Sander 2024-10-05 08:44 2458
      }
47fd5c32 Poul Sander 2024-10-05 08:44 2459
      if (specs.align == align::none) {
47fd5c32 Poul Sander 2024-10-05 08:44 2460
        // Ignore 0 if align is specified for compatibility with std::format.
47fd5c32 Poul Sander 2024-10-05 08:44 2461
        specs.align = align::numeric;
47fd5c32 Poul Sander 2024-10-05 08:44 2462
        specs.fill = '0';
47fd5c32 Poul Sander 2024-10-05 08:44 2463
      }
47fd5c32 Poul Sander 2024-10-05 08:44 2464
      ++begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2465
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 2466
    case '1':
47fd5c32 Poul Sander 2024-10-05 08:44 2467
    case '2':
47fd5c32 Poul Sander 2024-10-05 08:44 2468
    case '3':
47fd5c32 Poul Sander 2024-10-05 08:44 2469
    case '4':
47fd5c32 Poul Sander 2024-10-05 08:44 2470
    case '5':
47fd5c32 Poul Sander 2024-10-05 08:44 2471
    case '6':
47fd5c32 Poul Sander 2024-10-05 08:44 2472
    case '7':
47fd5c32 Poul Sander 2024-10-05 08:44 2473
    case '8':
47fd5c32 Poul Sander 2024-10-05 08:44 2474
    case '9':
47fd5c32 Poul Sander 2024-10-05 08:44 2475
    case '{':
47fd5c32 Poul Sander 2024-10-05 08:44 2476
      enter_state(state::width);
47fd5c32 Poul Sander 2024-10-05 08:44 2477
      begin = parse_dynamic_spec(begin, end, specs.width, specs.width_ref, ctx);
47fd5c32 Poul Sander 2024-10-05 08:44 2478
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 2479
    case '.':
47fd5c32 Poul Sander 2024-10-05 08:44 2480
      if (arg_type == type::none_type) return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2481
      enter_state(state::precision,
47fd5c32 Poul Sander 2024-10-05 08:44 2482
                  in(arg_type, float_set | string_set | cstring_set));
47fd5c32 Poul Sander 2024-10-05 08:44 2483
      begin = parse_precision(begin, end, specs.precision, specs.precision_ref,
47fd5c32 Poul Sander 2024-10-05 08:44 2484
                              ctx);
47fd5c32 Poul Sander 2024-10-05 08:44 2485
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 2486
    case 'L':
47fd5c32 Poul Sander 2024-10-05 08:44 2487
      if (arg_type == type::none_type) return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2488
      enter_state(state::locale, is_arithmetic_type(arg_type));
47fd5c32 Poul Sander 2024-10-05 08:44 2489
      specs.localized = true;
47fd5c32 Poul Sander 2024-10-05 08:44 2490
      ++begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2491
      break;
47fd5c32 Poul Sander 2024-10-05 08:44 2492
    case 'd':
47fd5c32 Poul Sander 2024-10-05 08:44 2493
      return parse_presentation_type(pres::dec, integral_set);
47fd5c32 Poul Sander 2024-10-05 08:44 2494
    case 'X':
47fd5c32 Poul Sander 2024-10-05 08:44 2495
      specs.upper = true;
47fd5c32 Poul Sander 2024-10-05 08:44 2496
      FMT_FALLTHROUGH;
47fd5c32 Poul Sander 2024-10-05 08:44 2497
    case 'x':
47fd5c32 Poul Sander 2024-10-05 08:44 2498
      return parse_presentation_type(pres::hex, integral_set);
47fd5c32 Poul Sander 2024-10-05 08:44 2499
    case 'o':
47fd5c32 Poul Sander 2024-10-05 08:44 2500
      return parse_presentation_type(pres::oct, integral_set);
47fd5c32 Poul Sander 2024-10-05 08:44 2501
    case 'B':
47fd5c32 Poul Sander 2024-10-05 08:44 2502
      specs.upper = true;
47fd5c32 Poul Sander 2024-10-05 08:44 2503
      FMT_FALLTHROUGH;
47fd5c32 Poul Sander 2024-10-05 08:44 2504
    case 'b':
47fd5c32 Poul Sander 2024-10-05 08:44 2505
      return parse_presentation_type(pres::bin, integral_set);
47fd5c32 Poul Sander 2024-10-05 08:44 2506
    case 'E':
47fd5c32 Poul Sander 2024-10-05 08:44 2507
      specs.upper = true;
47fd5c32 Poul Sander 2024-10-05 08:44 2508
      FMT_FALLTHROUGH;
47fd5c32 Poul Sander 2024-10-05 08:44 2509
    case 'e':
47fd5c32 Poul Sander 2024-10-05 08:44 2510
      return parse_presentation_type(pres::exp, float_set);
47fd5c32 Poul Sander 2024-10-05 08:44 2511
    case 'F':
47fd5c32 Poul Sander 2024-10-05 08:44 2512
      specs.upper = true;
47fd5c32 Poul Sander 2024-10-05 08:44 2513
      FMT_FALLTHROUGH;
47fd5c32 Poul Sander 2024-10-05 08:44 2514
    case 'f':
47fd5c32 Poul Sander 2024-10-05 08:44 2515
      return parse_presentation_type(pres::fixed, float_set);
47fd5c32 Poul Sander 2024-10-05 08:44 2516
    case 'G':
47fd5c32 Poul Sander 2024-10-05 08:44 2517
      specs.upper = true;
47fd5c32 Poul Sander 2024-10-05 08:44 2518
      FMT_FALLTHROUGH;
47fd5c32 Poul Sander 2024-10-05 08:44 2519
    case 'g':
47fd5c32 Poul Sander 2024-10-05 08:44 2520
      return parse_presentation_type(pres::general, float_set);
47fd5c32 Poul Sander 2024-10-05 08:44 2521
    case 'A':
47fd5c32 Poul Sander 2024-10-05 08:44 2522
      specs.upper = true;
47fd5c32 Poul Sander 2024-10-05 08:44 2523
      FMT_FALLTHROUGH;
47fd5c32 Poul Sander 2024-10-05 08:44 2524
    case 'a':
47fd5c32 Poul Sander 2024-10-05 08:44 2525
      return parse_presentation_type(pres::hexfloat, float_set);
47fd5c32 Poul Sander 2024-10-05 08:44 2526
    case 'c':
47fd5c32 Poul Sander 2024-10-05 08:44 2527
      if (arg_type == type::bool_type) report_error("invalid format specifier");
47fd5c32 Poul Sander 2024-10-05 08:44 2528
      return parse_presentation_type(pres::chr, integral_set);
47fd5c32 Poul Sander 2024-10-05 08:44 2529
    case 's':
47fd5c32 Poul Sander 2024-10-05 08:44 2530
      return parse_presentation_type(pres::string,
47fd5c32 Poul Sander 2024-10-05 08:44 2531
                                     bool_set | string_set | cstring_set);
47fd5c32 Poul Sander 2024-10-05 08:44 2532
    case 'p':
47fd5c32 Poul Sander 2024-10-05 08:44 2533
      return parse_presentation_type(pres::pointer, pointer_set | cstring_set);
47fd5c32 Poul Sander 2024-10-05 08:44 2534
    case '?':
47fd5c32 Poul Sander 2024-10-05 08:44 2535
      return parse_presentation_type(pres::debug,
47fd5c32 Poul Sander 2024-10-05 08:44 2536
                                     char_set | string_set | cstring_set);
47fd5c32 Poul Sander 2024-10-05 08:44 2537
    case '}':
47fd5c32 Poul Sander 2024-10-05 08:44 2538
      return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2539
    default: {
47fd5c32 Poul Sander 2024-10-05 08:44 2540
      if (*begin == '}') return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2541
      // Parse fill and alignment.
47fd5c32 Poul Sander 2024-10-05 08:44 2542
      auto fill_end = begin + code_point_length(begin);
47fd5c32 Poul Sander 2024-10-05 08:44 2543
      if (end - fill_end <= 0) {
47fd5c32 Poul Sander 2024-10-05 08:44 2544
        report_error("invalid format specifier");
47fd5c32 Poul Sander 2024-10-05 08:44 2545
        return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2546
      }
47fd5c32 Poul Sander 2024-10-05 08:44 2547
      if (*begin == '{') {
47fd5c32 Poul Sander 2024-10-05 08:44 2548
        report_error("invalid fill character '{'");
47fd5c32 Poul Sander 2024-10-05 08:44 2549
        return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2550
      }
47fd5c32 Poul Sander 2024-10-05 08:44 2551
      auto align = parse_align(to_ascii(*fill_end));
47fd5c32 Poul Sander 2024-10-05 08:44 2552
      enter_state(state::align, align != align::none);
47fd5c32 Poul Sander 2024-10-05 08:44 2553
      specs.fill =
47fd5c32 Poul Sander 2024-10-05 08:44 2554
          basic_string_view<Char>(begin, to_unsigned(fill_end - begin));
47fd5c32 Poul Sander 2024-10-05 08:44 2555
      specs.align = align;
47fd5c32 Poul Sander 2024-10-05 08:44 2556
      begin = fill_end + 1;
47fd5c32 Poul Sander 2024-10-05 08:44 2557
    }
47fd5c32 Poul Sander 2024-10-05 08:44 2558
    }
47fd5c32 Poul Sander 2024-10-05 08:44 2559
    if (begin == end) return begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2560
    c = to_ascii(*begin);
47fd5c32 Poul Sander 2024-10-05 08:44 2561
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2562
}
47fd5c32 Poul Sander 2024-10-05 08:44 2563
47fd5c32 Poul Sander 2024-10-05 08:44 2564
template <typename Char, typename Handler>
47fd5c32 Poul Sander 2024-10-05 08:44 2565
FMT_CONSTEXPR auto parse_replacement_field(const Char* begin, const Char* end,
47fd5c32 Poul Sander 2024-10-05 08:44 2566
                                           Handler&& handler) -> const Char* {
47fd5c32 Poul Sander 2024-10-05 08:44 2567
  struct id_adapter {
47fd5c32 Poul Sander 2024-10-05 08:44 2568
    Handler& handler;
47fd5c32 Poul Sander 2024-10-05 08:44 2569
    int arg_id;
47fd5c32 Poul Sander 2024-10-05 08:44 2570
47fd5c32 Poul Sander 2024-10-05 08:44 2571
    FMT_CONSTEXPR void on_auto() { arg_id = handler.on_arg_id(); }
47fd5c32 Poul Sander 2024-10-05 08:44 2572
    FMT_CONSTEXPR void on_index(int id) { arg_id = handler.on_arg_id(id); }
47fd5c32 Poul Sander 2024-10-05 08:44 2573
    FMT_CONSTEXPR void on_name(basic_string_view<Char> id) {
47fd5c32 Poul Sander 2024-10-05 08:44 2574
      arg_id = handler.on_arg_id(id);
47fd5c32 Poul Sander 2024-10-05 08:44 2575
    }
47fd5c32 Poul Sander 2024-10-05 08:44 2576
  };
47fd5c32 Poul Sander 2024-10-05 08:44 2577
47fd5c32 Poul Sander 2024-10-05 08:44 2578
  ++begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2579
  if (begin == end) return handler.on_error("invalid format string"), end;
47fd5c32 Poul Sander 2024-10-05 08:44 2580
  if (*begin == '}') {
47fd5c32 Poul Sander 2024-10-05 08:44 2581
    handler.on_replacement_field(handler.on_arg_id(), begin);
47fd5c32 Poul Sander 2024-10-05 08:44 2582
  } else if (*begin == '{') {
47fd5c32 Poul Sander 2024-10-05 08:44 2583
    handler.on_text(begin, begin + 1);
47fd5c32 Poul Sander 2024-10-05 08:44 2584
  } else {
47fd5c32 Poul Sander 2024-10-05 08:44 2585
    auto adapter = id_adapter{handler, 0};
47fd5c32 Poul Sander 2024-10-05 08:44 2586
    begin = parse_arg_id(begin, end, adapter);
47fd5c32 Poul Sander 2024-10-05 08:44 2587
    Char c = begin != end ? *begin : Char();
47fd5c32 Poul Sander 2024-10-05 08:44 2588
    if (c == '}') {
47fd5c32 Poul Sander 2024-10-05 08:44 2589
      handler.on_replacement_field(adapter.arg_id, begin);
47fd5c32 Poul Sander 2024-10-05 08:44 2590
    } else if (c == ':') {
47fd5c32 Poul Sander 2024-10-05 08:44 2591
      begin = handler.on_format_specs(adapter.arg_id, begin + 1, end);
47fd5c32 Poul Sander 2024-10-05 08:44 2592
      if (begin == end || *begin != '}')
47fd5c32 Poul Sander 2024-10-05 08:44 2593
        return handler.on_error("unknown format specifier"), end;
47fd5c32 Poul Sander 2024-10-05 08:44 2594
    } else {
47fd5c32 Poul Sander 2024-10-05 08:44 2595
      return handler.on_error("missing '}' in format string"), end;
47fd5c32 Poul Sander 2024-10-05 08:44 2596
    }
47fd5c32 Poul Sander 2024-10-05 08:44 2597
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2598
  return begin + 1;
47fd5c32 Poul Sander 2024-10-05 08:44 2599
}
47fd5c32 Poul Sander 2024-10-05 08:44 2600
47fd5c32 Poul Sander 2024-10-05 08:44 2601
template <bool IS_CONSTEXPR, typename Char, typename Handler>
47fd5c32 Poul Sander 2024-10-05 08:44 2602
FMT_CONSTEXPR void parse_format_string(basic_string_view<Char> format_str,
47fd5c32 Poul Sander 2024-10-05 08:44 2603
                                       Handler&& handler) {
47fd5c32 Poul Sander 2024-10-05 08:44 2604
  auto begin = format_str.data();
47fd5c32 Poul Sander 2024-10-05 08:44 2605
  auto end = begin + format_str.size();
47fd5c32 Poul Sander 2024-10-05 08:44 2606
  if (end - begin < 32) {
47fd5c32 Poul Sander 2024-10-05 08:44 2607
    // Use a simple loop instead of memchr for small strings.
47fd5c32 Poul Sander 2024-10-05 08:44 2608
    const Char* p = begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2609
    while (p != end) {
47fd5c32 Poul Sander 2024-10-05 08:44 2610
      auto c = *p++;
47fd5c32 Poul Sander 2024-10-05 08:44 2611
      if (c == '{') {
47fd5c32 Poul Sander 2024-10-05 08:44 2612
        handler.on_text(begin, p - 1);
47fd5c32 Poul Sander 2024-10-05 08:44 2613
        begin = p = parse_replacement_field(p - 1, end, handler);
47fd5c32 Poul Sander 2024-10-05 08:44 2614
      } else if (c == '}') {
47fd5c32 Poul Sander 2024-10-05 08:44 2615
        if (p == end || *p != '}')
47fd5c32 Poul Sander 2024-10-05 08:44 2616
          return handler.on_error("unmatched '}' in format string");
47fd5c32 Poul Sander 2024-10-05 08:44 2617
        handler.on_text(begin, p);
47fd5c32 Poul Sander 2024-10-05 08:44 2618
        begin = ++p;
47fd5c32 Poul Sander 2024-10-05 08:44 2619
      }
47fd5c32 Poul Sander 2024-10-05 08:44 2620
    }
47fd5c32 Poul Sander 2024-10-05 08:44 2621
    handler.on_text(begin, end);
47fd5c32 Poul Sander 2024-10-05 08:44 2622
    return;
47fd5c32 Poul Sander 2024-10-05 08:44 2623
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2624
  struct writer {
47fd5c32 Poul Sander 2024-10-05 08:44 2625
    FMT_CONSTEXPR void operator()(const Char* from, const Char* to) {
47fd5c32 Poul Sander 2024-10-05 08:44 2626
      if (from == to) return;
47fd5c32 Poul Sander 2024-10-05 08:44 2627
      for (;;) {
47fd5c32 Poul Sander 2024-10-05 08:44 2628
        const Char* p = nullptr;
47fd5c32 Poul Sander 2024-10-05 08:44 2629
        if (!find<IS_CONSTEXPR>(from, to, Char('}'), p))
47fd5c32 Poul Sander 2024-10-05 08:44 2630
          return handler_.on_text(from, to);
47fd5c32 Poul Sander 2024-10-05 08:44 2631
        ++p;
47fd5c32 Poul Sander 2024-10-05 08:44 2632
        if (p == to || *p != '}')
47fd5c32 Poul Sander 2024-10-05 08:44 2633
          return handler_.on_error("unmatched '}' in format string");
47fd5c32 Poul Sander 2024-10-05 08:44 2634
        handler_.on_text(from, p);
47fd5c32 Poul Sander 2024-10-05 08:44 2635
        from = p + 1;
47fd5c32 Poul Sander 2024-10-05 08:44 2636
      }
47fd5c32 Poul Sander 2024-10-05 08:44 2637
    }
47fd5c32 Poul Sander 2024-10-05 08:44 2638
    Handler& handler_;
47fd5c32 Poul Sander 2024-10-05 08:44 2639
  } write = {handler};
47fd5c32 Poul Sander 2024-10-05 08:44 2640
  while (begin != end) {
47fd5c32 Poul Sander 2024-10-05 08:44 2641
    // Doing two passes with memchr (one for '{' and another for '}') is up to
47fd5c32 Poul Sander 2024-10-05 08:44 2642
    // 2.5x faster than the naive one-pass implementation on big format strings.
47fd5c32 Poul Sander 2024-10-05 08:44 2643
    const Char* p = begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2644
    if (*begin != '{' && !find<IS_CONSTEXPR>(begin + 1, end, Char('{'), p))
47fd5c32 Poul Sander 2024-10-05 08:44 2645
      return write(begin, end);
47fd5c32 Poul Sander 2024-10-05 08:44 2646
    write(begin, p);
47fd5c32 Poul Sander 2024-10-05 08:44 2647
    begin = parse_replacement_field(p, end, handler);
47fd5c32 Poul Sander 2024-10-05 08:44 2648
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2649
}
47fd5c32 Poul Sander 2024-10-05 08:44 2650
47fd5c32 Poul Sander 2024-10-05 08:44 2651
template <typename T, bool = is_named_arg<T>::value> struct strip_named_arg {
47fd5c32 Poul Sander 2024-10-05 08:44 2652
  using type = T;
47fd5c32 Poul Sander 2024-10-05 08:44 2653
};
47fd5c32 Poul Sander 2024-10-05 08:44 2654
template <typename T> struct strip_named_arg<T, true> {
47fd5c32 Poul Sander 2024-10-05 08:44 2655
  using type = remove_cvref_t<decltype(T::value)>;
47fd5c32 Poul Sander 2024-10-05 08:44 2656
};
47fd5c32 Poul Sander 2024-10-05 08:44 2657
47fd5c32 Poul Sander 2024-10-05 08:44 2658
template <typename T, typename ParseContext>
47fd5c32 Poul Sander 2024-10-05 08:44 2659
FMT_VISIBILITY("hidden")  // Suppress an ld warning on macOS (#3769).
47fd5c32 Poul Sander 2024-10-05 08:44 2660
FMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx)
47fd5c32 Poul Sander 2024-10-05 08:44 2661
    -> decltype(ctx.begin()) {
47fd5c32 Poul Sander 2024-10-05 08:44 2662
  using char_type = typename ParseContext::char_type;
47fd5c32 Poul Sander 2024-10-05 08:44 2663
  using context = buffered_context<char_type>;
47fd5c32 Poul Sander 2024-10-05 08:44 2664
  using mapped_type = conditional_t<
47fd5c32 Poul Sander 2024-10-05 08:44 2665
      mapped_type_constant<T, context>::value != type::custom_type,
47fd5c32 Poul Sander 2024-10-05 08:44 2666
      decltype(arg_mapper<context>().map(std::declval<const T&>())),
47fd5c32 Poul Sander 2024-10-05 08:44 2667
      typename strip_named_arg<T>::type>;
47fd5c32 Poul Sander 2024-10-05 08:44 2668
#if defined(__cpp_if_constexpr)
47fd5c32 Poul Sander 2024-10-05 08:44 2669
  if constexpr (std::is_default_constructible<
47fd5c32 Poul Sander 2024-10-05 08:44 2670
                    formatter<mapped_type, char_type>>::value) {
47fd5c32 Poul Sander 2024-10-05 08:44 2671
    return formatter<mapped_type, char_type>().parse(ctx);
47fd5c32 Poul Sander 2024-10-05 08:44 2672
  } else {
47fd5c32 Poul Sander 2024-10-05 08:44 2673
    type_is_unformattable_for<T, char_type> _;
47fd5c32 Poul Sander 2024-10-05 08:44 2674
    return ctx.begin();
47fd5c32 Poul Sander 2024-10-05 08:44 2675
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2676
#else
47fd5c32 Poul Sander 2024-10-05 08:44 2677
  return formatter<mapped_type, char_type>().parse(ctx);
47fd5c32 Poul Sander 2024-10-05 08:44 2678
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 2679
}
47fd5c32 Poul Sander 2024-10-05 08:44 2680
47fd5c32 Poul Sander 2024-10-05 08:44 2681
// Checks char specs and returns true iff the presentation type is char-like.
47fd5c32 Poul Sander 2024-10-05 08:44 2682
FMT_CONSTEXPR inline auto check_char_specs(const format_specs& specs) -> bool {
47fd5c32 Poul Sander 2024-10-05 08:44 2683
  if (specs.type != presentation_type::none &&
47fd5c32 Poul Sander 2024-10-05 08:44 2684
      specs.type != presentation_type::chr &&
47fd5c32 Poul Sander 2024-10-05 08:44 2685
      specs.type != presentation_type::debug) {
47fd5c32 Poul Sander 2024-10-05 08:44 2686
    return false;
47fd5c32 Poul Sander 2024-10-05 08:44 2687
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2688
  if (specs.align == align::numeric || specs.sign != sign::none || specs.alt)
47fd5c32 Poul Sander 2024-10-05 08:44 2689
    report_error("invalid format specifier for char");
47fd5c32 Poul Sander 2024-10-05 08:44 2690
  return true;
47fd5c32 Poul Sander 2024-10-05 08:44 2691
}
47fd5c32 Poul Sander 2024-10-05 08:44 2692
47fd5c32 Poul Sander 2024-10-05 08:44 2693
#if FMT_USE_NONTYPE_TEMPLATE_ARGS
47fd5c32 Poul Sander 2024-10-05 08:44 2694
template <int N, typename T, typename... Args, typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 2695
constexpr auto get_arg_index_by_name(basic_string_view<Char> name) -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 2696
  if constexpr (is_statically_named_arg<T>()) {
47fd5c32 Poul Sander 2024-10-05 08:44 2697
    if (name == T::name) return N;
47fd5c32 Poul Sander 2024-10-05 08:44 2698
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2699
  if constexpr (sizeof...(Args) > 0)
47fd5c32 Poul Sander 2024-10-05 08:44 2700
    return get_arg_index_by_name<N + 1, Args...>(name);
47fd5c32 Poul Sander 2024-10-05 08:44 2701
  (void)name;  // Workaround an MSVC bug about "unused" parameter.
47fd5c32 Poul Sander 2024-10-05 08:44 2702
  return -1;
47fd5c32 Poul Sander 2024-10-05 08:44 2703
}
47fd5c32 Poul Sander 2024-10-05 08:44 2704
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 2705
47fd5c32 Poul Sander 2024-10-05 08:44 2706
template <typename... Args, typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 2707
FMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view<Char> name) -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 2708
#if FMT_USE_NONTYPE_TEMPLATE_ARGS
47fd5c32 Poul Sander 2024-10-05 08:44 2709
  if constexpr (sizeof...(Args) > 0)
47fd5c32 Poul Sander 2024-10-05 08:44 2710
    return get_arg_index_by_name<0, Args...>(name);
47fd5c32 Poul Sander 2024-10-05 08:44 2711
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 2712
  (void)name;
47fd5c32 Poul Sander 2024-10-05 08:44 2713
  return -1;
47fd5c32 Poul Sander 2024-10-05 08:44 2714
}
47fd5c32 Poul Sander 2024-10-05 08:44 2715
47fd5c32 Poul Sander 2024-10-05 08:44 2716
template <typename Char, typename... Args> class format_string_checker {
47fd5c32 Poul Sander 2024-10-05 08:44 2717
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 2718
  using parse_context_type = compile_parse_context<Char>;
47fd5c32 Poul Sander 2024-10-05 08:44 2719
  static constexpr int num_args = sizeof...(Args);
47fd5c32 Poul Sander 2024-10-05 08:44 2720
47fd5c32 Poul Sander 2024-10-05 08:44 2721
  // Format specifier parsing function.
47fd5c32 Poul Sander 2024-10-05 08:44 2722
  // In the future basic_format_parse_context will replace compile_parse_context
47fd5c32 Poul Sander 2024-10-05 08:44 2723
  // here and will use is_constant_evaluated and downcasting to access the data
47fd5c32 Poul Sander 2024-10-05 08:44 2724
  // needed for compile-time checks: https://godbolt.org/z/GvWzcTjh1.
47fd5c32 Poul Sander 2024-10-05 08:44 2725
  using parse_func = const Char* (*)(parse_context_type&);
47fd5c32 Poul Sander 2024-10-05 08:44 2726
47fd5c32 Poul Sander 2024-10-05 08:44 2727
  type types_[num_args > 0 ? static_cast<size_t>(num_args) : 1];
47fd5c32 Poul Sander 2024-10-05 08:44 2728
  parse_context_type context_;
47fd5c32 Poul Sander 2024-10-05 08:44 2729
  parse_func parse_funcs_[num_args > 0 ? static_cast<size_t>(num_args) : 1];
47fd5c32 Poul Sander 2024-10-05 08:44 2730
47fd5c32 Poul Sander 2024-10-05 08:44 2731
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 2732
  explicit FMT_CONSTEXPR format_string_checker(basic_string_view<Char> fmt)
47fd5c32 Poul Sander 2024-10-05 08:44 2733
      : types_{mapped_type_constant<Args, buffered_context<Char>>::value...},
47fd5c32 Poul Sander 2024-10-05 08:44 2734
        context_(fmt, num_args, types_),
47fd5c32 Poul Sander 2024-10-05 08:44 2735
        parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {}
47fd5c32 Poul Sander 2024-10-05 08:44 2736
47fd5c32 Poul Sander 2024-10-05 08:44 2737
  FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
47fd5c32 Poul Sander 2024-10-05 08:44 2738
47fd5c32 Poul Sander 2024-10-05 08:44 2739
  FMT_CONSTEXPR auto on_arg_id() -> int { return context_.next_arg_id(); }
47fd5c32 Poul Sander 2024-10-05 08:44 2740
  FMT_CONSTEXPR auto on_arg_id(int id) -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 2741
    return context_.check_arg_id(id), id;
47fd5c32 Poul Sander 2024-10-05 08:44 2742
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2743
  FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int {
47fd5c32 Poul Sander 2024-10-05 08:44 2744
#if FMT_USE_NONTYPE_TEMPLATE_ARGS
47fd5c32 Poul Sander 2024-10-05 08:44 2745
    auto index = get_arg_index_by_name<Args...>(id);
47fd5c32 Poul Sander 2024-10-05 08:44 2746
    if (index < 0) on_error("named argument is not found");
47fd5c32 Poul Sander 2024-10-05 08:44 2747
    return index;
47fd5c32 Poul Sander 2024-10-05 08:44 2748
#else
47fd5c32 Poul Sander 2024-10-05 08:44 2749
    (void)id;
47fd5c32 Poul Sander 2024-10-05 08:44 2750
    on_error("compile-time checks for named arguments require C++20 support");
47fd5c32 Poul Sander 2024-10-05 08:44 2751
    return 0;
47fd5c32 Poul Sander 2024-10-05 08:44 2752
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 2753
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2754
47fd5c32 Poul Sander 2024-10-05 08:44 2755
  FMT_CONSTEXPR void on_replacement_field(int id, const Char* begin) {
47fd5c32 Poul Sander 2024-10-05 08:44 2756
    on_format_specs(id, begin, begin);  // Call parse() on empty specs.
47fd5c32 Poul Sander 2024-10-05 08:44 2757
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2758
47fd5c32 Poul Sander 2024-10-05 08:44 2759
  FMT_CONSTEXPR auto on_format_specs(int id, const Char* begin, const Char*)
47fd5c32 Poul Sander 2024-10-05 08:44 2760
      -> const Char* {
47fd5c32 Poul Sander 2024-10-05 08:44 2761
    context_.advance_to(begin);
47fd5c32 Poul Sander 2024-10-05 08:44 2762
    // id >= 0 check is a workaround for gcc 10 bug (#2065).
47fd5c32 Poul Sander 2024-10-05 08:44 2763
    return id >= 0 && id < num_args ? parse_funcs_[id](context_) : begin;
47fd5c32 Poul Sander 2024-10-05 08:44 2764
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2765
47fd5c32 Poul Sander 2024-10-05 08:44 2766
  FMT_NORETURN FMT_CONSTEXPR void on_error(const char* message) {
47fd5c32 Poul Sander 2024-10-05 08:44 2767
    report_error(message);
47fd5c32 Poul Sander 2024-10-05 08:44 2768
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2769
};
47fd5c32 Poul Sander 2024-10-05 08:44 2770
47fd5c32 Poul Sander 2024-10-05 08:44 2771
// A base class for compile-time strings.
47fd5c32 Poul Sander 2024-10-05 08:44 2772
struct compile_string {};
47fd5c32 Poul Sander 2024-10-05 08:44 2773
47fd5c32 Poul Sander 2024-10-05 08:44 2774
template <typename S>
47fd5c32 Poul Sander 2024-10-05 08:44 2775
using is_compile_string = std::is_base_of<compile_string, S>;
47fd5c32 Poul Sander 2024-10-05 08:44 2776
47fd5c32 Poul Sander 2024-10-05 08:44 2777
// Reports a compile-time error if S is not a valid format string.
47fd5c32 Poul Sander 2024-10-05 08:44 2778
template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 2779
FMT_ALWAYS_INLINE void check_format_string(const S&) {
47fd5c32 Poul Sander 2024-10-05 08:44 2780
#ifdef FMT_ENFORCE_COMPILE_STRING
47fd5c32 Poul Sander 2024-10-05 08:44 2781
  static_assert(is_compile_string<S>::value,
47fd5c32 Poul Sander 2024-10-05 08:44 2782
                "FMT_ENFORCE_COMPILE_STRING requires all format strings to use "
47fd5c32 Poul Sander 2024-10-05 08:44 2783
                "FMT_STRING.");
47fd5c32 Poul Sander 2024-10-05 08:44 2784
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 2785
}
47fd5c32 Poul Sander 2024-10-05 08:44 2786
template <typename... Args, typename S,
47fd5c32 Poul Sander 2024-10-05 08:44 2787
          FMT_ENABLE_IF(is_compile_string<S>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 2788
void check_format_string(S format_str) {
47fd5c32 Poul Sander 2024-10-05 08:44 2789
  using char_t = typename S::char_type;
47fd5c32 Poul Sander 2024-10-05 08:44 2790
  FMT_CONSTEXPR auto s = basic_string_view<char_t>(format_str);
47fd5c32 Poul Sander 2024-10-05 08:44 2791
  using checker = format_string_checker<char_t, remove_cvref_t<Args>...>;
47fd5c32 Poul Sander 2024-10-05 08:44 2792
  FMT_CONSTEXPR bool error = (parse_format_string<true>(s, checker(s)), true);
47fd5c32 Poul Sander 2024-10-05 08:44 2793
  ignore_unused(error);
47fd5c32 Poul Sander 2024-10-05 08:44 2794
}
47fd5c32 Poul Sander 2024-10-05 08:44 2795
47fd5c32 Poul Sander 2024-10-05 08:44 2796
// Report truncation to prevent silent data loss.
47fd5c32 Poul Sander 2024-10-05 08:44 2797
inline void report_truncation(bool truncated) {
47fd5c32 Poul Sander 2024-10-05 08:44 2798
  if (truncated) report_error("output is truncated");
47fd5c32 Poul Sander 2024-10-05 08:44 2799
}
47fd5c32 Poul Sander 2024-10-05 08:44 2800
47fd5c32 Poul Sander 2024-10-05 08:44 2801
// Use vformat_args and avoid type_identity to keep symbols short and workaround
47fd5c32 Poul Sander 2024-10-05 08:44 2802
// a GCC <= 4.8 bug.
47fd5c32 Poul Sander 2024-10-05 08:44 2803
template <typename Char = char> struct vformat_args {
47fd5c32 Poul Sander 2024-10-05 08:44 2804
  using type = basic_format_args<buffered_context<Char>>;
47fd5c32 Poul Sander 2024-10-05 08:44 2805
};
47fd5c32 Poul Sander 2024-10-05 08:44 2806
template <> struct vformat_args<char> {
47fd5c32 Poul Sander 2024-10-05 08:44 2807
  using type = format_args;
47fd5c32 Poul Sander 2024-10-05 08:44 2808
};
47fd5c32 Poul Sander 2024-10-05 08:44 2809
47fd5c32 Poul Sander 2024-10-05 08:44 2810
template <typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 2811
void vformat_to(buffer<Char>& buf, basic_string_view<Char> fmt,
47fd5c32 Poul Sander 2024-10-05 08:44 2812
                typename vformat_args<Char>::type args, locale_ref loc = {});
47fd5c32 Poul Sander 2024-10-05 08:44 2813
47fd5c32 Poul Sander 2024-10-05 08:44 2814
FMT_API void vprint_mojibake(FILE*, string_view, format_args, bool = false);
47fd5c32 Poul Sander 2024-10-05 08:44 2815
#ifndef _WIN32
47fd5c32 Poul Sander 2024-10-05 08:44 2816
inline void vprint_mojibake(FILE*, string_view, format_args, bool) {}
47fd5c32 Poul Sander 2024-10-05 08:44 2817
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 2818
47fd5c32 Poul Sander 2024-10-05 08:44 2819
template <typename T, typename Char, type TYPE> struct native_formatter {
47fd5c32 Poul Sander 2024-10-05 08:44 2820
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 2821
  dynamic_format_specs<Char> specs_;
47fd5c32 Poul Sander 2024-10-05 08:44 2822
47fd5c32 Poul Sander 2024-10-05 08:44 2823
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 2824
  using nonlocking = void;
47fd5c32 Poul Sander 2024-10-05 08:44 2825
47fd5c32 Poul Sander 2024-10-05 08:44 2826
  template <typename ParseContext>
47fd5c32 Poul Sander 2024-10-05 08:44 2827
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const Char* {
47fd5c32 Poul Sander 2024-10-05 08:44 2828
    if (ctx.begin() == ctx.end() || *ctx.begin() == '}') return ctx.begin();
47fd5c32 Poul Sander 2024-10-05 08:44 2829
    auto end = parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, TYPE);
47fd5c32 Poul Sander 2024-10-05 08:44 2830
    if (const_check(TYPE == type::char_type)) check_char_specs(specs_);
47fd5c32 Poul Sander 2024-10-05 08:44 2831
    return end;
47fd5c32 Poul Sander 2024-10-05 08:44 2832
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2833
47fd5c32 Poul Sander 2024-10-05 08:44 2834
  template <type U = TYPE,
47fd5c32 Poul Sander 2024-10-05 08:44 2835
            FMT_ENABLE_IF(U == type::string_type || U == type::cstring_type ||
47fd5c32 Poul Sander 2024-10-05 08:44 2836
                          U == type::char_type)>
47fd5c32 Poul Sander 2024-10-05 08:44 2837
  FMT_CONSTEXPR void set_debug_format(bool set = true) {
47fd5c32 Poul Sander 2024-10-05 08:44 2838
    specs_.type = set ? presentation_type::debug : presentation_type::none;
47fd5c32 Poul Sander 2024-10-05 08:44 2839
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2840
47fd5c32 Poul Sander 2024-10-05 08:44 2841
  template <typename FormatContext>
47fd5c32 Poul Sander 2024-10-05 08:44 2842
  FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const
47fd5c32 Poul Sander 2024-10-05 08:44 2843
      -> decltype(ctx.out());
47fd5c32 Poul Sander 2024-10-05 08:44 2844
};
47fd5c32 Poul Sander 2024-10-05 08:44 2845
}  // namespace detail
47fd5c32 Poul Sander 2024-10-05 08:44 2846
47fd5c32 Poul Sander 2024-10-05 08:44 2847
FMT_BEGIN_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 2848
47fd5c32 Poul Sander 2024-10-05 08:44 2849
// A formatter specialization for natively supported types.
47fd5c32 Poul Sander 2024-10-05 08:44 2850
template <typename T, typename Char>
47fd5c32 Poul Sander 2024-10-05 08:44 2851
struct formatter<T, Char,
47fd5c32 Poul Sander 2024-10-05 08:44 2852
                 enable_if_t<detail::type_constant<T, Char>::value !=
47fd5c32 Poul Sander 2024-10-05 08:44 2853
                             detail::type::custom_type>>
47fd5c32 Poul Sander 2024-10-05 08:44 2854
    : detail::native_formatter<T, Char, detail::type_constant<T, Char>::value> {
47fd5c32 Poul Sander 2024-10-05 08:44 2855
};
47fd5c32 Poul Sander 2024-10-05 08:44 2856
47fd5c32 Poul Sander 2024-10-05 08:44 2857
template <typename Char = char> struct runtime_format_string {
47fd5c32 Poul Sander 2024-10-05 08:44 2858
  basic_string_view<Char> str;
47fd5c32 Poul Sander 2024-10-05 08:44 2859
};
47fd5c32 Poul Sander 2024-10-05 08:44 2860
47fd5c32 Poul Sander 2024-10-05 08:44 2861
/// A compile-time format string.
47fd5c32 Poul Sander 2024-10-05 08:44 2862
template <typename Char, typename... Args> class basic_format_string {
47fd5c32 Poul Sander 2024-10-05 08:44 2863
 private:
47fd5c32 Poul Sander 2024-10-05 08:44 2864
  basic_string_view<Char> str_;
47fd5c32 Poul Sander 2024-10-05 08:44 2865
47fd5c32 Poul Sander 2024-10-05 08:44 2866
 public:
47fd5c32 Poul Sander 2024-10-05 08:44 2867
  template <
47fd5c32 Poul Sander 2024-10-05 08:44 2868
      typename S,
47fd5c32 Poul Sander 2024-10-05 08:44 2869
      FMT_ENABLE_IF(
47fd5c32 Poul Sander 2024-10-05 08:44 2870
          std::is_convertible<const S&, basic_string_view<Char>>::value ||
47fd5c32 Poul Sander 2024-10-05 08:44 2871
          (detail::is_compile_string<S>::value &&
47fd5c32 Poul Sander 2024-10-05 08:44 2872
           std::is_constructible<basic_string_view<Char>, const S&>::value))>
47fd5c32 Poul Sander 2024-10-05 08:44 2873
  FMT_CONSTEVAL FMT_ALWAYS_INLINE basic_format_string(const S& s) : str_(s) {
47fd5c32 Poul Sander 2024-10-05 08:44 2874
    static_assert(
47fd5c32 Poul Sander 2024-10-05 08:44 2875
        detail::count<
47fd5c32 Poul Sander 2024-10-05 08:44 2876
            (std::is_base_of<detail::view, remove_reference_t<Args>>::value &&
47fd5c32 Poul Sander 2024-10-05 08:44 2877
             std::is_reference<Args>::value)...>() == 0,
47fd5c32 Poul Sander 2024-10-05 08:44 2878
        "passing views as lvalues is disallowed");
47fd5c32 Poul Sander 2024-10-05 08:44 2879
#if FMT_USE_CONSTEVAL
47fd5c32 Poul Sander 2024-10-05 08:44 2880
    if constexpr (detail::count_named_args<Args...>() ==
47fd5c32 Poul Sander 2024-10-05 08:44 2881
                  detail::count_statically_named_args<Args...>()) {
47fd5c32 Poul Sander 2024-10-05 08:44 2882
      using checker =
47fd5c32 Poul Sander 2024-10-05 08:44 2883
          detail::format_string_checker<Char, remove_cvref_t<Args>...>;
47fd5c32 Poul Sander 2024-10-05 08:44 2884
      detail::parse_format_string<true>(str_, checker(s));
47fd5c32 Poul Sander 2024-10-05 08:44 2885
    }
47fd5c32 Poul Sander 2024-10-05 08:44 2886
#else
47fd5c32 Poul Sander 2024-10-05 08:44 2887
    detail::check_format_string<Args...>(s);
47fd5c32 Poul Sander 2024-10-05 08:44 2888
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 2889
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2890
  basic_format_string(runtime_format_string<Char> fmt) : str_(fmt.str) {}
47fd5c32 Poul Sander 2024-10-05 08:44 2891
47fd5c32 Poul Sander 2024-10-05 08:44 2892
  FMT_ALWAYS_INLINE operator basic_string_view<Char>() const { return str_; }
47fd5c32 Poul Sander 2024-10-05 08:44 2893
  auto get() const -> basic_string_view<Char> { return str_; }
47fd5c32 Poul Sander 2024-10-05 08:44 2894
};
47fd5c32 Poul Sander 2024-10-05 08:44 2895
47fd5c32 Poul Sander 2024-10-05 08:44 2896
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
47fd5c32 Poul Sander 2024-10-05 08:44 2897
// Workaround broken conversion on older gcc.
47fd5c32 Poul Sander 2024-10-05 08:44 2898
template <typename...> using format_string = string_view;
47fd5c32 Poul Sander 2024-10-05 08:44 2899
inline auto runtime(string_view s) -> string_view { return s; }
47fd5c32 Poul Sander 2024-10-05 08:44 2900
#else
47fd5c32 Poul Sander 2024-10-05 08:44 2901
template <typename... Args>
47fd5c32 Poul Sander 2024-10-05 08:44 2902
using format_string = basic_format_string<char, type_identity_t<Args>...>;
47fd5c32 Poul Sander 2024-10-05 08:44 2903
/**
47fd5c32 Poul Sander 2024-10-05 08:44 2904
 * Creates a runtime format string.
47fd5c32 Poul Sander 2024-10-05 08:44 2905
 *
47fd5c32 Poul Sander 2024-10-05 08:44 2906
 * **Example**:
47fd5c32 Poul Sander 2024-10-05 08:44 2907
 *
47fd5c32 Poul Sander 2024-10-05 08:44 2908
 *     // Check format string at runtime instead of compile-time.
47fd5c32 Poul Sander 2024-10-05 08:44 2909
 *     fmt::print(fmt::runtime("{:d}"), "I am not a number");
47fd5c32 Poul Sander 2024-10-05 08:44 2910
 */
47fd5c32 Poul Sander 2024-10-05 08:44 2911
inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; }
47fd5c32 Poul Sander 2024-10-05 08:44 2912
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 2913
47fd5c32 Poul Sander 2024-10-05 08:44 2914
/// Formats a string and writes the output to `out`.
47fd5c32 Poul Sander 2024-10-05 08:44 2915
template <typename OutputIt,
47fd5c32 Poul Sander 2024-10-05 08:44 2916
          FMT_ENABLE_IF(detail::is_output_iterator<remove_cvref_t<OutputIt>,
47fd5c32 Poul Sander 2024-10-05 08:44 2917
                                                   char>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 2918
auto vformat_to(OutputIt&& out, string_view fmt, format_args args)
47fd5c32 Poul Sander 2024-10-05 08:44 2919
    -> remove_cvref_t<OutputIt> {
47fd5c32 Poul Sander 2024-10-05 08:44 2920
  auto&& buf = detail::get_buffer<char>(out);
47fd5c32 Poul Sander 2024-10-05 08:44 2921
  detail::vformat_to(buf, fmt, args, {});
47fd5c32 Poul Sander 2024-10-05 08:44 2922
  return detail::get_iterator(buf, out);
47fd5c32 Poul Sander 2024-10-05 08:44 2923
}
47fd5c32 Poul Sander 2024-10-05 08:44 2924
47fd5c32 Poul Sander 2024-10-05 08:44 2925
/**
47fd5c32 Poul Sander 2024-10-05 08:44 2926
 * Formats `args` according to specifications in `fmt`, writes the result to
47fd5c32 Poul Sander 2024-10-05 08:44 2927
 * the output iterator `out` and returns the iterator past the end of the output
47fd5c32 Poul Sander 2024-10-05 08:44 2928
 * range. `format_to` does not append a terminating null character.
47fd5c32 Poul Sander 2024-10-05 08:44 2929
 *
47fd5c32 Poul Sander 2024-10-05 08:44 2930
 * **Example**:
47fd5c32 Poul Sander 2024-10-05 08:44 2931
 *
47fd5c32 Poul Sander 2024-10-05 08:44 2932
 *     auto out = std::vector<char>();
47fd5c32 Poul Sander 2024-10-05 08:44 2933
 *     fmt::format_to(std::back_inserter(out), "{}", 42);
47fd5c32 Poul Sander 2024-10-05 08:44 2934
 */
47fd5c32 Poul Sander 2024-10-05 08:44 2935
template <typename OutputIt, typename... T,
47fd5c32 Poul Sander 2024-10-05 08:44 2936
          FMT_ENABLE_IF(detail::is_output_iterator<remove_cvref_t<OutputIt>,
47fd5c32 Poul Sander 2024-10-05 08:44 2937
                                                   char>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 2938
FMT_INLINE auto format_to(OutputIt&& out, format_string<T...> fmt, T&&... args)
47fd5c32 Poul Sander 2024-10-05 08:44 2939
    -> remove_cvref_t<OutputIt> {
47fd5c32 Poul Sander 2024-10-05 08:44 2940
  return vformat_to(FMT_FWD(out), fmt, fmt::make_format_args(args...));
47fd5c32 Poul Sander 2024-10-05 08:44 2941
}
47fd5c32 Poul Sander 2024-10-05 08:44 2942
47fd5c32 Poul Sander 2024-10-05 08:44 2943
template <typename OutputIt> struct format_to_n_result {
47fd5c32 Poul Sander 2024-10-05 08:44 2944
  /// Iterator past the end of the output range.
47fd5c32 Poul Sander 2024-10-05 08:44 2945
  OutputIt out;
47fd5c32 Poul Sander 2024-10-05 08:44 2946
  /// Total (not truncated) output size.
47fd5c32 Poul Sander 2024-10-05 08:44 2947
  size_t size;
47fd5c32 Poul Sander 2024-10-05 08:44 2948
};
47fd5c32 Poul Sander 2024-10-05 08:44 2949
47fd5c32 Poul Sander 2024-10-05 08:44 2950
template <typename OutputIt, typename... T,
47fd5c32 Poul Sander 2024-10-05 08:44 2951
          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 2952
auto vformat_to_n(OutputIt out, size_t n, string_view fmt, format_args args)
47fd5c32 Poul Sander 2024-10-05 08:44 2953
    -> format_to_n_result<OutputIt> {
47fd5c32 Poul Sander 2024-10-05 08:44 2954
  using traits = detail::fixed_buffer_traits;
47fd5c32 Poul Sander 2024-10-05 08:44 2955
  auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n);
47fd5c32 Poul Sander 2024-10-05 08:44 2956
  detail::vformat_to(buf, fmt, args, {});
47fd5c32 Poul Sander 2024-10-05 08:44 2957
  return {buf.out(), buf.count()};
47fd5c32 Poul Sander 2024-10-05 08:44 2958
}
47fd5c32 Poul Sander 2024-10-05 08:44 2959
47fd5c32 Poul Sander 2024-10-05 08:44 2960
/**
47fd5c32 Poul Sander 2024-10-05 08:44 2961
 * Formats `args` according to specifications in `fmt`, writes up to `n`
47fd5c32 Poul Sander 2024-10-05 08:44 2962
 * characters of the result to the output iterator `out` and returns the total
47fd5c32 Poul Sander 2024-10-05 08:44 2963
 * (not truncated) output size and the iterator past the end of the output
47fd5c32 Poul Sander 2024-10-05 08:44 2964
 * range. `format_to_n` does not append a terminating null character.
47fd5c32 Poul Sander 2024-10-05 08:44 2965
 */
47fd5c32 Poul Sander 2024-10-05 08:44 2966
template <typename OutputIt, typename... T,
47fd5c32 Poul Sander 2024-10-05 08:44 2967
          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
47fd5c32 Poul Sander 2024-10-05 08:44 2968
FMT_INLINE auto format_to_n(OutputIt out, size_t n, format_string<T...> fmt,
47fd5c32 Poul Sander 2024-10-05 08:44 2969
                            T&&... args) -> format_to_n_result<OutputIt> {
47fd5c32 Poul Sander 2024-10-05 08:44 2970
  return vformat_to_n(out, n, fmt, fmt::make_format_args(args...));
47fd5c32 Poul Sander 2024-10-05 08:44 2971
}
47fd5c32 Poul Sander 2024-10-05 08:44 2972
47fd5c32 Poul Sander 2024-10-05 08:44 2973
template <typename OutputIt, typename Sentinel = OutputIt>
47fd5c32 Poul Sander 2024-10-05 08:44 2974
struct format_to_result {
47fd5c32 Poul Sander 2024-10-05 08:44 2975
  /// Iterator pointing to just after the last successful write in the range.
47fd5c32 Poul Sander 2024-10-05 08:44 2976
  OutputIt out;
47fd5c32 Poul Sander 2024-10-05 08:44 2977
  /// Specifies if the output was truncated.
47fd5c32 Poul Sander 2024-10-05 08:44 2978
  bool truncated;
47fd5c32 Poul Sander 2024-10-05 08:44 2979
47fd5c32 Poul Sander 2024-10-05 08:44 2980
  FMT_CONSTEXPR operator OutputIt&() & {
47fd5c32 Poul Sander 2024-10-05 08:44 2981
    detail::report_truncation(truncated);
47fd5c32 Poul Sander 2024-10-05 08:44 2982
    return out;
47fd5c32 Poul Sander 2024-10-05 08:44 2983
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2984
  FMT_CONSTEXPR operator const OutputIt&() const& {
47fd5c32 Poul Sander 2024-10-05 08:44 2985
    detail::report_truncation(truncated);
47fd5c32 Poul Sander 2024-10-05 08:44 2986
    return out;
47fd5c32 Poul Sander 2024-10-05 08:44 2987
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2988
  FMT_CONSTEXPR operator OutputIt&&() && {
47fd5c32 Poul Sander 2024-10-05 08:44 2989
    detail::report_truncation(truncated);
47fd5c32 Poul Sander 2024-10-05 08:44 2990
    return static_cast<OutputIt&&>(out);
47fd5c32 Poul Sander 2024-10-05 08:44 2991
  }
47fd5c32 Poul Sander 2024-10-05 08:44 2992
};
47fd5c32 Poul Sander 2024-10-05 08:44 2993
47fd5c32 Poul Sander 2024-10-05 08:44 2994
template <size_t N>
47fd5c32 Poul Sander 2024-10-05 08:44 2995
auto vformat_to(char (&out)[N], string_view fmt, format_args args)
47fd5c32 Poul Sander 2024-10-05 08:44 2996
    -> format_to_result<char*> {
47fd5c32 Poul Sander 2024-10-05 08:44 2997
  auto result = vformat_to_n(out, N, fmt, args);
47fd5c32 Poul Sander 2024-10-05 08:44 2998
  return {result.out, result.size > N};
47fd5c32 Poul Sander 2024-10-05 08:44 2999
}
47fd5c32 Poul Sander 2024-10-05 08:44 3000
47fd5c32 Poul Sander 2024-10-05 08:44 3001
template <size_t N, typename... T>
47fd5c32 Poul Sander 2024-10-05 08:44 3002
FMT_INLINE auto format_to(char (&out)[N], format_string<T...> fmt, T&&... args)
47fd5c32 Poul Sander 2024-10-05 08:44 3003
    -> format_to_result<char*> {
47fd5c32 Poul Sander 2024-10-05 08:44 3004
  auto result = fmt::format_to_n(out, N, fmt, static_cast<T&&>(args)...);
47fd5c32 Poul Sander 2024-10-05 08:44 3005
  return {result.out, result.size > N};
47fd5c32 Poul Sander 2024-10-05 08:44 3006
}
47fd5c32 Poul Sander 2024-10-05 08:44 3007
47fd5c32 Poul Sander 2024-10-05 08:44 3008
/// Returns the number of chars in the output of `format(fmt, args...)`.
47fd5c32 Poul Sander 2024-10-05 08:44 3009
template <typename... T>
47fd5c32 Poul Sander 2024-10-05 08:44 3010
FMT_NODISCARD FMT_INLINE auto formatted_size(format_string<T...> fmt,
47fd5c32 Poul Sander 2024-10-05 08:44 3011
                                             T&&... args) -> size_t {
47fd5c32 Poul Sander 2024-10-05 08:44 3012
  auto buf = detail::counting_buffer<>();
47fd5c32 Poul Sander 2024-10-05 08:44 3013
  detail::vformat_to<char>(buf, fmt, fmt::make_format_args(args...), {});
47fd5c32 Poul Sander 2024-10-05 08:44 3014
  return buf.count();
47fd5c32 Poul Sander 2024-10-05 08:44 3015
}
47fd5c32 Poul Sander 2024-10-05 08:44 3016
47fd5c32 Poul Sander 2024-10-05 08:44 3017
FMT_API void vprint(string_view fmt, format_args args);
47fd5c32 Poul Sander 2024-10-05 08:44 3018
FMT_API void vprint(FILE* f, string_view fmt, format_args args);
47fd5c32 Poul Sander 2024-10-05 08:44 3019
FMT_API void vprint_buffered(FILE* f, string_view fmt, format_args args);
47fd5c32 Poul Sander 2024-10-05 08:44 3020
FMT_API void vprintln(FILE* f, string_view fmt, format_args args);
47fd5c32 Poul Sander 2024-10-05 08:44 3021
47fd5c32 Poul Sander 2024-10-05 08:44 3022
/**
47fd5c32 Poul Sander 2024-10-05 08:44 3023
 * Formats `args` according to specifications in `fmt` and writes the output
47fd5c32 Poul Sander 2024-10-05 08:44 3024
 * to `stdout`.
47fd5c32 Poul Sander 2024-10-05 08:44 3025
 *
47fd5c32 Poul Sander 2024-10-05 08:44 3026
 * **Example**:
47fd5c32 Poul Sander 2024-10-05 08:44 3027
 *
47fd5c32 Poul Sander 2024-10-05 08:44 3028
 *     fmt::print("The answer is {}.", 42);
47fd5c32 Poul Sander 2024-10-05 08:44 3029
 */
47fd5c32 Poul Sander 2024-10-05 08:44 3030
template <typename... T>
47fd5c32 Poul Sander 2024-10-05 08:44 3031
FMT_INLINE void print(format_string<T...> fmt, T&&... args) {
47fd5c32 Poul Sander 2024-10-05 08:44 3032
  const auto& vargs = fmt::make_format_args(args...);
47fd5c32 Poul Sander 2024-10-05 08:44 3033
  if (!detail::use_utf8()) return detail::vprint_mojibake(stdout, fmt, vargs);
47fd5c32 Poul Sander 2024-10-05 08:44 3034
  return detail::is_locking<T...>() ? vprint_buffered(stdout, fmt, vargs)
47fd5c32 Poul Sander 2024-10-05 08:44 3035
                                    : vprint(fmt, vargs);
47fd5c32 Poul Sander 2024-10-05 08:44 3036
}
47fd5c32 Poul Sander 2024-10-05 08:44 3037
47fd5c32 Poul Sander 2024-10-05 08:44 3038
/**
47fd5c32 Poul Sander 2024-10-05 08:44 3039
 * Formats `args` according to specifications in `fmt` and writes the
47fd5c32 Poul Sander 2024-10-05 08:44 3040
 * output to the file `f`.
47fd5c32 Poul Sander 2024-10-05 08:44 3041
 *
47fd5c32 Poul Sander 2024-10-05 08:44 3042
 * **Example**:
47fd5c32 Poul Sander 2024-10-05 08:44 3043
 *
47fd5c32 Poul Sander 2024-10-05 08:44 3044
 *     fmt::print(stderr, "Don't {}!", "panic");
47fd5c32 Poul Sander 2024-10-05 08:44 3045
 */
47fd5c32 Poul Sander 2024-10-05 08:44 3046
template <typename... T>
47fd5c32 Poul Sander 2024-10-05 08:44 3047
FMT_INLINE void print(FILE* f, format_string<T...> fmt, T&&... args) {
47fd5c32 Poul Sander 2024-10-05 08:44 3048
  const auto& vargs = fmt::make_format_args(args...);
47fd5c32 Poul Sander 2024-10-05 08:44 3049
  if (!detail::use_utf8()) return detail::vprint_mojibake(f, fmt, vargs);
47fd5c32 Poul Sander 2024-10-05 08:44 3050
  return detail::is_locking<T...>() ? vprint_buffered(f, fmt, vargs)
47fd5c32 Poul Sander 2024-10-05 08:44 3051
                                    : vprint(f, fmt, vargs);
47fd5c32 Poul Sander 2024-10-05 08:44 3052
}
47fd5c32 Poul Sander 2024-10-05 08:44 3053
47fd5c32 Poul Sander 2024-10-05 08:44 3054
/// Formats `args` according to specifications in `fmt` and writes the output
47fd5c32 Poul Sander 2024-10-05 08:44 3055
/// to the file `f` followed by a newline.
47fd5c32 Poul Sander 2024-10-05 08:44 3056
template <typename... T>
47fd5c32 Poul Sander 2024-10-05 08:44 3057
FMT_INLINE void println(FILE* f, format_string<T...> fmt, T&&... args) {
47fd5c32 Poul Sander 2024-10-05 08:44 3058
  const auto& vargs = fmt::make_format_args(args...);
47fd5c32 Poul Sander 2024-10-05 08:44 3059
  return detail::use_utf8() ? vprintln(f, fmt, vargs)
47fd5c32 Poul Sander 2024-10-05 08:44 3060
                            : detail::vprint_mojibake(f, fmt, vargs, true);
47fd5c32 Poul Sander 2024-10-05 08:44 3061
}
47fd5c32 Poul Sander 2024-10-05 08:44 3062
47fd5c32 Poul Sander 2024-10-05 08:44 3063
/// Formats `args` according to specifications in `fmt` and writes the output
47fd5c32 Poul Sander 2024-10-05 08:44 3064
/// to `stdout` followed by a newline.
47fd5c32 Poul Sander 2024-10-05 08:44 3065
template <typename... T>
47fd5c32 Poul Sander 2024-10-05 08:44 3066
FMT_INLINE void println(format_string<T...> fmt, T&&... args) {
47fd5c32 Poul Sander 2024-10-05 08:44 3067
  return fmt::println(stdout, fmt, static_cast<T&&>(args)...);
47fd5c32 Poul Sander 2024-10-05 08:44 3068
}
47fd5c32 Poul Sander 2024-10-05 08:44 3069
47fd5c32 Poul Sander 2024-10-05 08:44 3070
FMT_END_EXPORT
47fd5c32 Poul Sander 2024-10-05 08:44 3071
FMT_GCC_PRAGMA("GCC pop_options")
47fd5c32 Poul Sander 2024-10-05 08:44 3072
FMT_END_NAMESPACE
47fd5c32 Poul Sander 2024-10-05 08:44 3073
47fd5c32 Poul Sander 2024-10-05 08:44 3074
#ifdef FMT_HEADER_ONLY
47fd5c32 Poul Sander 2024-10-05 08:44 3075
#  include "format.h"
47fd5c32 Poul Sander 2024-10-05 08:44 3076
#endif
47fd5c32 Poul Sander 2024-10-05 08:44 3077
#endif  // FMT_BASE_H_
1970-01-01 00:00 3078