| 1 | // Formatting library for C++ - the core API |
|---|
| 2 | // |
|---|
| 3 | // Copyright (c) 2012 - present, Victor Zverovich |
|---|
| 4 | // All rights reserved. |
|---|
| 5 | // |
|---|
| 6 | // For the license information refer to format.h. |
|---|
| 7 | |
|---|
| 8 | #ifndef FMT_CORE_H_ |
|---|
| 9 | #define FMT_CORE_H_ |
|---|
| 10 | |
|---|
| 11 | #include <cassert> |
|---|
| 12 | #include <cstdio> // std::FILE |
|---|
| 13 | #include <cstring> |
|---|
| 14 | #include <iterator> |
|---|
| 15 | #include <string> |
|---|
| 16 | #include <type_traits> |
|---|
| 17 | |
|---|
| 18 | // The fmt library version in the form major * 10000 + minor * 100 + patch. |
|---|
| 19 | #define FMT_VERSION 50300 |
|---|
| 20 | |
|---|
| 21 | #ifdef __has_feature |
|---|
| 22 | # define FMT_HAS_FEATURE(x) __has_feature(x) |
|---|
| 23 | #else |
|---|
| 24 | # define FMT_HAS_FEATURE(x) 0 |
|---|
| 25 | #endif |
|---|
| 26 | |
|---|
| 27 | #if defined(__has_include) && !defined(__INTELLISENSE__) && \ |
|---|
| 28 | !(defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1600) |
|---|
| 29 | # define FMT_HAS_INCLUDE(x) __has_include(x) |
|---|
| 30 | #else |
|---|
| 31 | # define FMT_HAS_INCLUDE(x) 0 |
|---|
| 32 | #endif |
|---|
| 33 | |
|---|
| 34 | #ifdef __has_cpp_attribute |
|---|
| 35 | # define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) |
|---|
| 36 | #else |
|---|
| 37 | # define FMT_HAS_CPP_ATTRIBUTE(x) 0 |
|---|
| 38 | #endif |
|---|
| 39 | |
|---|
| 40 | #if defined(__GNUC__) && !defined(__clang__) |
|---|
| 41 | # define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) |
|---|
| 42 | #else |
|---|
| 43 | # define FMT_GCC_VERSION 0 |
|---|
| 44 | #endif |
|---|
| 45 | |
|---|
| 46 | #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) |
|---|
| 47 | # define FMT_HAS_GXX_CXX11 FMT_GCC_VERSION |
|---|
| 48 | #else |
|---|
| 49 | # define FMT_HAS_GXX_CXX11 0 |
|---|
| 50 | #endif |
|---|
| 51 | |
|---|
| 52 | #ifdef _MSC_VER |
|---|
| 53 | # define FMT_MSC_VER _MSC_VER |
|---|
| 54 | #else |
|---|
| 55 | # define FMT_MSC_VER 0 |
|---|
| 56 | #endif |
|---|
| 57 | |
|---|
| 58 | // Check if relaxed C++14 constexpr is supported. |
|---|
| 59 | // GCC doesn't allow throw in constexpr until version 6 (bug 67371). |
|---|
| 60 | #ifndef FMT_USE_CONSTEXPR |
|---|
| 61 | # define FMT_USE_CONSTEXPR \ |
|---|
| 62 | (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1910 || \ |
|---|
| 63 | (FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L)) |
|---|
| 64 | #endif |
|---|
| 65 | #if FMT_USE_CONSTEXPR |
|---|
| 66 | # define FMT_CONSTEXPR constexpr |
|---|
| 67 | # define FMT_CONSTEXPR_DECL constexpr |
|---|
| 68 | #else |
|---|
| 69 | # define FMT_CONSTEXPR inline |
|---|
| 70 | # define FMT_CONSTEXPR_DECL |
|---|
| 71 | #endif |
|---|
| 72 | |
|---|
| 73 | #ifndef FMT_USE_CONSTEXPR11 |
|---|
| 74 | # define FMT_USE_CONSTEXPR11 \ |
|---|
| 75 | (FMT_USE_CONSTEXPR || FMT_GCC_VERSION >= 406 || FMT_MSC_VER >= 1900) |
|---|
| 76 | #endif |
|---|
| 77 | #if FMT_USE_CONSTEXPR11 |
|---|
| 78 | # define FMT_CONSTEXPR11 constexpr |
|---|
| 79 | #else |
|---|
| 80 | # define FMT_CONSTEXPR11 |
|---|
| 81 | #endif |
|---|
| 82 | |
|---|
| 83 | #ifndef FMT_OVERRIDE |
|---|
| 84 | # if FMT_HAS_FEATURE(cxx_override) || \ |
|---|
| 85 | (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900 |
|---|
| 86 | # define FMT_OVERRIDE override |
|---|
| 87 | # else |
|---|
| 88 | # define FMT_OVERRIDE |
|---|
| 89 | # endif |
|---|
| 90 | #endif |
|---|
| 91 | |
|---|
| 92 | #if FMT_HAS_FEATURE(cxx_explicit_conversions) || \ |
|---|
| 93 | FMT_GCC_VERSION >= 405 || FMT_MSC_VER >= 1800 |
|---|
| 94 | # define FMT_USE_EXPLICIT 1 |
|---|
| 95 | # define FMT_EXPLICIT explicit |
|---|
| 96 | #else |
|---|
| 97 | # define FMT_USE_EXPLICIT 0 |
|---|
| 98 | # define FMT_EXPLICIT |
|---|
| 99 | #endif |
|---|
| 100 | |
|---|
| 101 | #ifndef FMT_NULL |
|---|
| 102 | # if FMT_HAS_FEATURE(cxx_nullptr) || \ |
|---|
| 103 | (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1600 |
|---|
| 104 | # define FMT_NULL nullptr |
|---|
| 105 | # define FMT_USE_NULLPTR 1 |
|---|
| 106 | # else |
|---|
| 107 | # define FMT_NULL NULL |
|---|
| 108 | # endif |
|---|
| 109 | #endif |
|---|
| 110 | #ifndef FMT_USE_NULLPTR |
|---|
| 111 | # define FMT_USE_NULLPTR 0 |
|---|
| 112 | #endif |
|---|
| 113 | |
|---|
| 114 | // Check if exceptions are disabled. |
|---|
| 115 | #ifndef FMT_EXCEPTIONS |
|---|
| 116 | # if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \ |
|---|
| 117 | FMT_MSC_VER && !_HAS_EXCEPTIONS |
|---|
| 118 | # define FMT_EXCEPTIONS 0 |
|---|
| 119 | # else |
|---|
| 120 | # define FMT_EXCEPTIONS 1 |
|---|
| 121 | # endif |
|---|
| 122 | #endif |
|---|
| 123 | |
|---|
| 124 | // Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature). |
|---|
| 125 | #ifndef FMT_USE_NOEXCEPT |
|---|
| 126 | # define FMT_USE_NOEXCEPT 0 |
|---|
| 127 | #endif |
|---|
| 128 | |
|---|
| 129 | #if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ |
|---|
| 130 | (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900 |
|---|
| 131 | # define FMT_DETECTED_NOEXCEPT noexcept |
|---|
| 132 | # define FMT_HAS_CXX11_NOEXCEPT 1 |
|---|
| 133 | #else |
|---|
| 134 | # define FMT_DETECTED_NOEXCEPT throw() |
|---|
| 135 | # define FMT_HAS_CXX11_NOEXCEPT 0 |
|---|
| 136 | #endif |
|---|
| 137 | |
|---|
| 138 | #ifndef FMT_NOEXCEPT |
|---|
| 139 | # if FMT_EXCEPTIONS || FMT_HAS_CXX11_NOEXCEPT |
|---|
| 140 | # define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT |
|---|
| 141 | # else |
|---|
| 142 | # define FMT_NOEXCEPT |
|---|
| 143 | # endif |
|---|
| 144 | #endif |
|---|
| 145 | |
|---|
| 146 | #ifndef FMT_BEGIN_NAMESPACE |
|---|
| 147 | # if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || \ |
|---|
| 148 | FMT_MSC_VER >= 1900 |
|---|
| 149 | # define FMT_INLINE_NAMESPACE inline namespace |
|---|
| 150 | # define FMT_END_NAMESPACE }} |
|---|
| 151 | # else |
|---|
| 152 | # define FMT_INLINE_NAMESPACE namespace |
|---|
| 153 | # define FMT_END_NAMESPACE } using namespace v5; } |
|---|
| 154 | # endif |
|---|
| 155 | # define FMT_BEGIN_NAMESPACE namespace fmt { FMT_INLINE_NAMESPACE v5 { |
|---|
| 156 | #endif |
|---|
| 157 | |
|---|
| 158 | #if !defined(FMT_HEADER_ONLY) && defined(_WIN32) |
|---|
| 159 | # ifdef FMT_EXPORT |
|---|
| 160 | # define FMT_API __declspec(dllexport) |
|---|
| 161 | # elif defined(FMT_SHARED) |
|---|
| 162 | # define FMT_API __declspec(dllimport) |
|---|
| 163 | # endif |
|---|
| 164 | #endif |
|---|
| 165 | #ifndef FMT_API |
|---|
| 166 | # define FMT_API |
|---|
| 167 | #endif |
|---|
| 168 | |
|---|
| 169 | #ifndef FMT_ASSERT |
|---|
| 170 | # define FMT_ASSERT(condition, message) assert((condition) && message) |
|---|
| 171 | #endif |
|---|
| 172 | |
|---|
| 173 | // libc++ supports string_view in pre-c++17. |
|---|
| 174 | #if (FMT_HAS_INCLUDE(<string_view>) && \ |
|---|
| 175 | (__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \ |
|---|
| 176 | (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) |
|---|
| 177 | # include <string_view> |
|---|
| 178 | # define FMT_STRING_VIEW std::basic_string_view |
|---|
| 179 | #elif FMT_HAS_INCLUDE(<experimental/string_view>) && __cplusplus >= 201402L |
|---|
| 180 | # include <experimental/string_view> |
|---|
| 181 | # define FMT_STRING_VIEW std::experimental::basic_string_view |
|---|
| 182 | #endif |
|---|
| 183 | |
|---|
| 184 | // std::result_of is defined in <functional> in gcc 4.4. |
|---|
| 185 | #if FMT_GCC_VERSION && FMT_GCC_VERSION <= 404 |
|---|
| 186 | # include <functional> |
|---|
| 187 | #endif |
|---|
| 188 | |
|---|
| 189 | FMT_BEGIN_NAMESPACE |
|---|
| 190 | namespace internal { |
|---|
| 191 | |
|---|
| 192 | // An implementation of declval for pre-C++11 compilers such as gcc 4. |
|---|
| 193 | template <typename T> |
|---|
| 194 | typename std::add_rvalue_reference<T>::type declval() FMT_NOEXCEPT; |
|---|
| 195 | |
|---|
| 196 | template <typename> |
|---|
| 197 | struct result_of; |
|---|
| 198 | |
|---|
| 199 | template <typename F, typename... Args> |
|---|
| 200 | struct result_of<F(Args...)> { |
|---|
| 201 | // A workaround for gcc 4.4 that doesn't allow F to be a reference. |
|---|
| 202 | typedef typename std::result_of< |
|---|
| 203 | typename std::remove_reference<F>::type(Args...)>::type type; |
|---|
| 204 | }; |
|---|
| 205 | |
|---|
| 206 | // Casts nonnegative integer to unsigned. |
|---|
| 207 | template <typename Int> |
|---|
| 208 | FMT_CONSTEXPR typename std::make_unsigned<Int>::type to_unsigned(Int value) { |
|---|
| 209 | FMT_ASSERT(value >= 0, "negative value"); |
|---|
| 210 | return static_cast<typename std::make_unsigned<Int>::type>(value); |
|---|
| 211 | } |
|---|
| 212 | |
|---|
| 213 | /** A contiguous memory buffer with an optional growing ability. */ |
|---|
| 214 | template <typename T> |
|---|
| 215 | class basic_buffer { |
|---|
| 216 | private: |
|---|
| 217 | basic_buffer(const basic_buffer &) = delete; |
|---|
| 218 | void operator=(const basic_buffer &) = delete; |
|---|
| 219 | |
|---|
| 220 | T *ptr_; |
|---|
| 221 | std::size_t size_; |
|---|
| 222 | std::size_t capacity_; |
|---|
| 223 | |
|---|
| 224 | protected: |
|---|
| 225 | // Don't initialize ptr_ since it is not accessed to save a few cycles. |
|---|
| 226 | basic_buffer(std::size_t sz) FMT_NOEXCEPT: size_(sz), capacity_(sz) {} |
|---|
| 227 | |
|---|
| 228 | basic_buffer(T *p = FMT_NULL, std::size_t sz = 0, std::size_t cap = 0) |
|---|
| 229 | FMT_NOEXCEPT: ptr_(p), size_(sz), capacity_(cap) {} |
|---|
| 230 | |
|---|
| 231 | /** Sets the buffer data and capacity. */ |
|---|
| 232 | void set(T *buf_data, std::size_t buf_capacity) FMT_NOEXCEPT { |
|---|
| 233 | ptr_ = buf_data; |
|---|
| 234 | capacity_ = buf_capacity; |
|---|
| 235 | } |
|---|
| 236 | |
|---|
| 237 | /** Increases the buffer capacity to hold at least *capacity* elements. */ |
|---|
| 238 | virtual void grow(std::size_t capacity) = 0; |
|---|
| 239 | |
|---|
| 240 | public: |
|---|
| 241 | typedef T value_type; |
|---|
| 242 | typedef const T &const_reference; |
|---|
| 243 | |
|---|
| 244 | virtual ~basic_buffer() {} |
|---|
| 245 | |
|---|
| 246 | T *begin() FMT_NOEXCEPT { return ptr_; } |
|---|
| 247 | T *end() FMT_NOEXCEPT { return ptr_ + size_; } |
|---|
| 248 | |
|---|
| 249 | /** Returns the size of this buffer. */ |
|---|
| 250 | std::size_t size() const FMT_NOEXCEPT { return size_; } |
|---|
| 251 | |
|---|
| 252 | /** Returns the capacity of this buffer. */ |
|---|
| 253 | std::size_t capacity() const FMT_NOEXCEPT { return capacity_; } |
|---|
| 254 | |
|---|
| 255 | /** Returns a pointer to the buffer data. */ |
|---|
| 256 | T *data() FMT_NOEXCEPT { return ptr_; } |
|---|
| 257 | |
|---|
| 258 | /** Returns a pointer to the buffer data. */ |
|---|
| 259 | const T *data() const FMT_NOEXCEPT { return ptr_; } |
|---|
| 260 | |
|---|
| 261 | /** |
|---|
| 262 | Resizes the buffer. If T is a POD type new elements may not be initialized. |
|---|
| 263 | */ |
|---|
| 264 | void resize(std::size_t new_size) { |
|---|
| 265 | reserve(new_size); |
|---|
| 266 | size_ = new_size; |
|---|
| 267 | } |
|---|
| 268 | |
|---|
| 269 | /** Clears this buffer. */ |
|---|
| 270 | void clear() { size_ = 0; } |
|---|
| 271 | |
|---|
| 272 | /** Reserves space to store at least *capacity* elements. */ |
|---|
| 273 | void reserve(std::size_t new_capacity) { |
|---|
| 274 | if (new_capacity > capacity_) |
|---|
| 275 | grow(new_capacity); |
|---|
| 276 | } |
|---|
| 277 | |
|---|
| 278 | void push_back(const T &value) { |
|---|
| 279 | reserve(size_ + 1); |
|---|
| 280 | ptr_[size_++] = value; |
|---|
| 281 | } |
|---|
| 282 | |
|---|
| 283 | /** Appends data to the end of the buffer. */ |
|---|
| 284 | template <typename U> |
|---|
| 285 | void append(const U *begin, const U *end); |
|---|
| 286 | |
|---|
| 287 | T &operator[](std::size_t index) { return ptr_[index]; } |
|---|
| 288 | const T &operator[](std::size_t index) const { return ptr_[index]; } |
|---|
| 289 | }; |
|---|
| 290 | |
|---|
| 291 | typedef basic_buffer<char> buffer; |
|---|
| 292 | typedef basic_buffer<wchar_t> wbuffer; |
|---|
| 293 | |
|---|
| 294 | // A container-backed buffer. |
|---|
| 295 | template <typename Container> |
|---|
| 296 | class container_buffer : public basic_buffer<typename Container::value_type> { |
|---|
| 297 | private: |
|---|
| 298 | Container &container_; |
|---|
| 299 | |
|---|
| 300 | protected: |
|---|
| 301 | void grow(std::size_t capacity) FMT_OVERRIDE { |
|---|
| 302 | container_.resize(capacity); |
|---|
| 303 | this->set(&container_[0], capacity); |
|---|
| 304 | } |
|---|
| 305 | |
|---|
| 306 | public: |
|---|
| 307 | explicit container_buffer(Container &c) |
|---|
| 308 | : basic_buffer<typename Container::value_type>(c.size()), container_(c) {} |
|---|
| 309 | }; |
|---|
| 310 | |
|---|
| 311 | // Extracts a reference to the container from back_insert_iterator. |
|---|
| 312 | template <typename Container> |
|---|
| 313 | inline Container &get_container(std::back_insert_iterator<Container> it) { |
|---|
| 314 | typedef std::back_insert_iterator<Container> bi_iterator; |
|---|
| 315 | struct accessor: bi_iterator { |
|---|
| 316 | accessor(bi_iterator iter) : bi_iterator(iter) {} |
|---|
| 317 | using bi_iterator::container; |
|---|
| 318 | }; |
|---|
| 319 | return *accessor(it).container; |
|---|
| 320 | } |
|---|
| 321 | |
|---|
| 322 | struct error_handler { |
|---|
| 323 | FMT_CONSTEXPR error_handler() {} |
|---|
| 324 | FMT_CONSTEXPR error_handler(const error_handler &) {} |
|---|
| 325 | |
|---|
| 326 | // This function is intentionally not constexpr to give a compile-time error. |
|---|
| 327 | FMT_API void on_error(const char *message); |
|---|
| 328 | }; |
|---|
| 329 | |
|---|
| 330 | template <typename T> |
|---|
| 331 | struct no_formatter_error : std::false_type {}; |
|---|
| 332 | } // namespace internal |
|---|
| 333 | |
|---|
| 334 | #if FMT_GCC_VERSION && FMT_GCC_VERSION < 405 |
|---|
| 335 | template <typename... T> |
|---|
| 336 | struct is_constructible: std::false_type {}; |
|---|
| 337 | #else |
|---|
| 338 | template <typename... T> |
|---|
| 339 | struct is_constructible : std::is_constructible<T...> {}; |
|---|
| 340 | #endif |
|---|
| 341 | |
|---|
| 342 | /** |
|---|
| 343 | An implementation of ``std::basic_string_view`` for pre-C++17. It provides a |
|---|
| 344 | subset of the API. ``fmt::basic_string_view`` is used for format strings even |
|---|
| 345 | if ``std::string_view`` is available to prevent issues when a library is |
|---|
| 346 | compiled with a different ``-std`` option than the client code (which is not |
|---|
| 347 | recommended). |
|---|
| 348 | */ |
|---|
| 349 | template <typename Char> |
|---|
| 350 | class basic_string_view { |
|---|
| 351 | private: |
|---|
| 352 | const Char *data_; |
|---|
| 353 | size_t size_; |
|---|
| 354 | |
|---|
| 355 | public: |
|---|
| 356 | typedef Char char_type; |
|---|
| 357 | typedef const Char *iterator; |
|---|
| 358 | |
|---|
| 359 | FMT_CONSTEXPR basic_string_view() FMT_NOEXCEPT : data_(FMT_NULL), size_(0) {} |
|---|
| 360 | |
|---|
| 361 | /** Constructs a string reference object from a C string and a size. */ |
|---|
| 362 | FMT_CONSTEXPR basic_string_view(const Char *s, size_t count) FMT_NOEXCEPT |
|---|
| 363 | : data_(s), size_(count) {} |
|---|
| 364 | |
|---|
| 365 | /** |
|---|
| 366 | \rst |
|---|
| 367 | Constructs a string reference object from a C string computing |
|---|
| 368 | the size with ``std::char_traits<Char>::length``. |
|---|
| 369 | \endrst |
|---|
| 370 | */ |
|---|
| 371 | basic_string_view(const Char *s) |
|---|
| 372 | : data_(s), size_(std::char_traits<Char>::length(s)) {} |
|---|
| 373 | |
|---|
| 374 | /** Constructs a string reference from a ``std::basic_string`` object. */ |
|---|
| 375 | template <typename Alloc> |
|---|
| 376 | FMT_CONSTEXPR basic_string_view( |
|---|
| 377 | const std::basic_string<Char, Alloc> &s) FMT_NOEXCEPT |
|---|
| 378 | : data_(s.data()), size_(s.size()) {} |
|---|
| 379 | |
|---|
| 380 | #ifdef FMT_STRING_VIEW |
|---|
| 381 | FMT_CONSTEXPR basic_string_view(FMT_STRING_VIEW<Char> s) FMT_NOEXCEPT |
|---|
| 382 | : data_(s.data()), size_(s.size()) {} |
|---|
| 383 | #endif |
|---|
| 384 | |
|---|
| 385 | /** Returns a pointer to the string data. */ |
|---|
| 386 | FMT_CONSTEXPR const Char *data() const { return data_; } |
|---|
| 387 | |
|---|
| 388 | /** Returns the string size. */ |
|---|
| 389 | FMT_CONSTEXPR size_t size() const { return size_; } |
|---|
| 390 | |
|---|
| 391 | FMT_CONSTEXPR iterator begin() const { return data_; } |
|---|
| 392 | FMT_CONSTEXPR iterator end() const { return data_ + size_; } |
|---|
| 393 | |
|---|
| 394 | FMT_CONSTEXPR void remove_prefix(size_t n) { |
|---|
| 395 | data_ += n; |
|---|
| 396 | size_ -= n; |
|---|
| 397 | } |
|---|
| 398 | |
|---|
| 399 | // Lexicographically compare this string reference to other. |
|---|
| 400 | int compare(basic_string_view other) const { |
|---|
| 401 | size_t str_size = size_ < other.size_ ? size_ : other.size_; |
|---|
| 402 | int result = std::char_traits<Char>::compare(data_, other.data_, str_size); |
|---|
| 403 | if (result == 0) |
|---|
| 404 | result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1); |
|---|
| 405 | return result; |
|---|
| 406 | } |
|---|
| 407 | |
|---|
| 408 | friend bool operator==(basic_string_view lhs, basic_string_view rhs) { |
|---|
| 409 | return lhs.compare(rhs) == 0; |
|---|
| 410 | } |
|---|
| 411 | friend bool operator!=(basic_string_view lhs, basic_string_view rhs) { |
|---|
| 412 | return lhs.compare(rhs) != 0; |
|---|
| 413 | } |
|---|
| 414 | friend bool operator<(basic_string_view lhs, basic_string_view rhs) { |
|---|
| 415 | return lhs.compare(rhs) < 0; |
|---|
| 416 | } |
|---|
| 417 | friend bool operator<=(basic_string_view lhs, basic_string_view rhs) { |
|---|
| 418 | return lhs.compare(rhs) <= 0; |
|---|
| 419 | } |
|---|
| 420 | friend bool operator>(basic_string_view lhs, basic_string_view rhs) { |
|---|
| 421 | return lhs.compare(rhs) > 0; |
|---|
| 422 | } |
|---|
| 423 | friend bool operator>=(basic_string_view lhs, basic_string_view rhs) { |
|---|
| 424 | return lhs.compare(rhs) >= 0; |
|---|
| 425 | } |
|---|
| 426 | }; |
|---|
| 427 | |
|---|
| 428 | typedef basic_string_view<char> string_view; |
|---|
| 429 | typedef basic_string_view<wchar_t> wstring_view; |
|---|
| 430 | |
|---|
| 431 | /** |
|---|
| 432 | \rst |
|---|
| 433 | The function ``to_string_view`` adapts non-intrusively any kind of string or |
|---|
| 434 | string-like type if the user provides a (possibly templated) overload of |
|---|
| 435 | ``to_string_view`` which takes an instance of the string class |
|---|
| 436 | ``StringType<Char>`` and returns a ``fmt::basic_string_view<Char>``. |
|---|
| 437 | The conversion function must live in the very same namespace as |
|---|
| 438 | ``StringType<Char>`` to be picked up by ADL. Non-templated string types |
|---|
| 439 | like f.e. QString must return a ``basic_string_view`` with a fixed matching |
|---|
| 440 | char type. |
|---|
| 441 | |
|---|
| 442 | **Example**:: |
|---|
| 443 | |
|---|
| 444 | namespace my_ns { |
|---|
| 445 | inline string_view to_string_view(const my_string &s) { |
|---|
| 446 | return {s.data(), s.length()}; |
|---|
| 447 | } |
|---|
| 448 | } |
|---|
| 449 | |
|---|
| 450 | std::string message = fmt::format(my_string("The answer is {}"), 42); |
|---|
| 451 | \endrst |
|---|
| 452 | */ |
|---|
| 453 | template <typename Char> |
|---|
| 454 | inline basic_string_view<Char> |
|---|
| 455 | to_string_view(basic_string_view<Char> s) { return s; } |
|---|
| 456 | |
|---|
| 457 | template <typename Char> |
|---|
| 458 | inline basic_string_view<Char> |
|---|
| 459 | to_string_view(const std::basic_string<Char> &s) { return s; } |
|---|
| 460 | |
|---|
| 461 | template <typename Char> |
|---|
| 462 | inline basic_string_view<Char> to_string_view(const Char *s) { return s; } |
|---|
| 463 | |
|---|
| 464 | #ifdef FMT_STRING_VIEW |
|---|
| 465 | template <typename Char> |
|---|
| 466 | inline basic_string_view<Char> |
|---|
| 467 | to_string_view(FMT_STRING_VIEW<Char> s) { return s; } |
|---|
| 468 | #endif |
|---|
| 469 | |
|---|
| 470 | // A base class for compile-time strings. It is defined in the fmt namespace to |
|---|
| 471 | // make formatting functions visible via ADL, e.g. format(fmt("{}"), 42). |
|---|
| 472 | struct compile_string {}; |
|---|
| 473 | |
|---|
| 474 | template <typename S> |
|---|
| 475 | struct is_compile_string : std::is_base_of<compile_string, S> {}; |
|---|
| 476 | |
|---|
| 477 | template < |
|---|
| 478 | typename S, |
|---|
| 479 | typename Enable = typename std::enable_if<is_compile_string<S>::value>::type> |
|---|
| 480 | FMT_CONSTEXPR basic_string_view<typename S::char_type> |
|---|
| 481 | to_string_view(const S &s) { return s; } |
|---|
| 482 | |
|---|
| 483 | template <typename Context> |
|---|
| 484 | class basic_format_arg; |
|---|
| 485 | |
|---|
| 486 | template <typename Context> |
|---|
| 487 | class basic_format_args; |
|---|
| 488 | |
|---|
| 489 | // A formatter for objects of type T. |
|---|
| 490 | template <typename T, typename Char = char, typename Enable = void> |
|---|
| 491 | struct formatter { |
|---|
| 492 | static_assert(internal::no_formatter_error<T>::value, |
|---|
| 493 | "don't know how to format the type, include fmt/ostream.h if it provides " |
|---|
| 494 | "an operator<< that should be used"); |
|---|
| 495 | |
|---|
| 496 | // The following functions are not defined intentionally. |
|---|
| 497 | template <typename ParseContext> |
|---|
| 498 | typename ParseContext::iterator parse(ParseContext &); |
|---|
| 499 | template <typename FormatContext> |
|---|
| 500 | auto format(const T &val, FormatContext &ctx) -> decltype(ctx.out()); |
|---|
| 501 | }; |
|---|
| 502 | |
|---|
| 503 | template <typename T, typename Char, typename Enable = void> |
|---|
| 504 | struct convert_to_int: std::integral_constant< |
|---|
| 505 | bool, !std::is_arithmetic<T>::value && std::is_convertible<T, int>::value> {}; |
|---|
| 506 | |
|---|
| 507 | namespace internal { |
|---|
| 508 | |
|---|
| 509 | struct dummy_string_view { typedef void char_type; }; |
|---|
| 510 | dummy_string_view to_string_view(...); |
|---|
| 511 | using fmt::v5::to_string_view; |
|---|
| 512 | |
|---|
| 513 | // Specifies whether S is a string type convertible to fmt::basic_string_view. |
|---|
| 514 | template <typename S> |
|---|
| 515 | struct is_string : std::integral_constant<bool, !std::is_same< |
|---|
| 516 | dummy_string_view, decltype(to_string_view(declval<S>()))>::value> {}; |
|---|
| 517 | |
|---|
| 518 | template <typename S> |
|---|
| 519 | struct char_t { |
|---|
| 520 | typedef decltype(to_string_view(declval<S>())) result; |
|---|
| 521 | typedef typename result::char_type type; |
|---|
| 522 | }; |
|---|
| 523 | |
|---|
| 524 | template <typename Char> |
|---|
| 525 | struct named_arg_base; |
|---|
| 526 | |
|---|
| 527 | template <typename T, typename Char> |
|---|
| 528 | struct named_arg; |
|---|
| 529 | |
|---|
| 530 | enum type { |
|---|
| 531 | none_type, named_arg_type, |
|---|
| 532 | // Integer types should go first, |
|---|
| 533 | int_type, uint_type, long_long_type, ulong_long_type, bool_type, char_type, |
|---|
| 534 | last_integer_type = char_type, |
|---|
| 535 | // followed by floating-point types. |
|---|
| 536 | double_type, long_double_type, last_numeric_type = long_double_type, |
|---|
| 537 | cstring_type, string_type, pointer_type, custom_type |
|---|
| 538 | }; |
|---|
| 539 | |
|---|
| 540 | FMT_CONSTEXPR bool is_integral(type t) { |
|---|
| 541 | FMT_ASSERT(t != internal::named_arg_type, "invalid argument type"); |
|---|
| 542 | return t > internal::none_type && t <= internal::last_integer_type; |
|---|
| 543 | } |
|---|
| 544 | |
|---|
| 545 | FMT_CONSTEXPR bool is_arithmetic(type t) { |
|---|
| 546 | FMT_ASSERT(t != internal::named_arg_type, "invalid argument type"); |
|---|
| 547 | return t > internal::none_type && t <= internal::last_numeric_type; |
|---|
| 548 | } |
|---|
| 549 | |
|---|
| 550 | template <typename Char> |
|---|
| 551 | struct string_value { |
|---|
| 552 | const Char *value; |
|---|
| 553 | std::size_t size; |
|---|
| 554 | }; |
|---|
| 555 | |
|---|
| 556 | template <typename Context> |
|---|
| 557 | struct custom_value { |
|---|
| 558 | const void *value; |
|---|
| 559 | void (*format)(const void *arg, Context &ctx); |
|---|
| 560 | }; |
|---|
| 561 | |
|---|
| 562 | // A formatting argument value. |
|---|
| 563 | template <typename Context> |
|---|
| 564 | class value { |
|---|
| 565 | public: |
|---|
| 566 | typedef typename Context::char_type char_type; |
|---|
| 567 | |
|---|
| 568 | union { |
|---|
| 569 | int int_value; |
|---|
| 570 | unsigned uint_value; |
|---|
| 571 | long long long_long_value; |
|---|
| 572 | unsigned long long ulong_long_value; |
|---|
| 573 | double double_value; |
|---|
| 574 | long double long_double_value; |
|---|
| 575 | const void *pointer; |
|---|
| 576 | string_value<char_type> string; |
|---|
| 577 | string_value<signed char> sstring; |
|---|
| 578 | string_value<unsigned char> ustring; |
|---|
| 579 | custom_value<Context> custom; |
|---|
| 580 | }; |
|---|
| 581 | |
|---|
| 582 | FMT_CONSTEXPR value(int val = 0) : int_value(val) {} |
|---|
| 583 | value(unsigned val) { uint_value = val; } |
|---|
| 584 | value(long long val) { long_long_value = val; } |
|---|
| 585 | value(unsigned long long val) { ulong_long_value = val; } |
|---|
| 586 | value(double val) { double_value = val; } |
|---|
| 587 | value(long double val) { long_double_value = val; } |
|---|
| 588 | value(const char_type *val) { string.value = val; } |
|---|
| 589 | value(const signed char *val) { |
|---|
| 590 | static_assert(std::is_same<char, char_type>::value, |
|---|
| 591 | "incompatible string types"); |
|---|
| 592 | sstring.value = val; |
|---|
| 593 | } |
|---|
| 594 | value(const unsigned char *val) { |
|---|
| 595 | static_assert(std::is_same<char, char_type>::value, |
|---|
| 596 | "incompatible string types"); |
|---|
| 597 | ustring.value = val; |
|---|
| 598 | } |
|---|
| 599 | value(basic_string_view<char_type> val) { |
|---|
| 600 | string.value = val.data(); |
|---|
| 601 | string.size = val.size(); |
|---|
| 602 | } |
|---|
| 603 | value(const void *val) { pointer = val; } |
|---|
| 604 | |
|---|
| 605 | template <typename T> |
|---|
| 606 | explicit value(const T &val) { |
|---|
| 607 | custom.value = &val; |
|---|
| 608 | custom.format = &format_custom_arg<T>; |
|---|
| 609 | } |
|---|
| 610 | |
|---|
| 611 | const named_arg_base<char_type> &as_named_arg() { |
|---|
| 612 | return *static_cast<const named_arg_base<char_type>*>(pointer); |
|---|
| 613 | } |
|---|
| 614 | |
|---|
| 615 | private: |
|---|
| 616 | // Formats an argument of a custom type, such as a user-defined class. |
|---|
| 617 | template <typename T> |
|---|
| 618 | static void format_custom_arg(const void *arg, Context &ctx) { |
|---|
| 619 | // Get the formatter type through the context to allow different contexts |
|---|
| 620 | // have different extension points, e.g. `formatter<T>` for `format` and |
|---|
| 621 | // `printf_formatter<T>` for `printf`. |
|---|
| 622 | typename Context::template formatter_type<T>::type f; |
|---|
| 623 | auto &&parse_ctx = ctx.parse_context(); |
|---|
| 624 | parse_ctx.advance_to(f.parse(parse_ctx)); |
|---|
| 625 | ctx.advance_to(f.format(*static_cast<const T*>(arg), ctx)); |
|---|
| 626 | } |
|---|
| 627 | }; |
|---|
| 628 | |
|---|
| 629 | // Value initializer used to delay conversion to value and reduce memory churn. |
|---|
| 630 | template <typename Context, typename T, type TYPE> |
|---|
| 631 | struct init { |
|---|
| 632 | T val; |
|---|
| 633 | static const type type_tag = TYPE; |
|---|
| 634 | |
|---|
| 635 | FMT_CONSTEXPR init(const T &v) : val(v) {} |
|---|
| 636 | FMT_CONSTEXPR operator value<Context>() const { return value<Context>(val); } |
|---|
| 637 | }; |
|---|
| 638 | |
|---|
| 639 | template <typename Context, typename T> |
|---|
| 640 | FMT_CONSTEXPR basic_format_arg<Context> make_arg(const T &value); |
|---|
| 641 | |
|---|
| 642 | #define FMT_MAKE_VALUE(TAG, ArgType, ValueType) \ |
|---|
| 643 | template <typename C> \ |
|---|
| 644 | FMT_CONSTEXPR init<C, ValueType, TAG> make_value(ArgType val) { \ |
|---|
| 645 | return static_cast<ValueType>(val); \ |
|---|
| 646 | } |
|---|
| 647 | |
|---|
| 648 | #define FMT_MAKE_VALUE_SAME(TAG, Type) \ |
|---|
| 649 | template <typename C> \ |
|---|
| 650 | FMT_CONSTEXPR init<C, Type, TAG> make_value(Type val) { return val; } |
|---|
| 651 | |
|---|
| 652 | FMT_MAKE_VALUE(bool_type, bool, int) |
|---|
| 653 | FMT_MAKE_VALUE(int_type, short, int) |
|---|
| 654 | FMT_MAKE_VALUE(uint_type, unsigned short, unsigned) |
|---|
| 655 | FMT_MAKE_VALUE_SAME(int_type, int) |
|---|
| 656 | FMT_MAKE_VALUE_SAME(uint_type, unsigned) |
|---|
| 657 | |
|---|
| 658 | // To minimize the number of types we need to deal with, long is translated |
|---|
| 659 | // either to int or to long long depending on its size. |
|---|
| 660 | typedef std::conditional<sizeof(long) == sizeof(int), int, long long>::type |
|---|
| 661 | long_type; |
|---|
| 662 | FMT_MAKE_VALUE( |
|---|
| 663 | (sizeof(long) == sizeof(int) ? int_type : long_long_type), long, long_type) |
|---|
| 664 | typedef std::conditional<sizeof(unsigned long) == sizeof(unsigned), |
|---|
| 665 | unsigned, unsigned long long>::type ulong_type; |
|---|
| 666 | FMT_MAKE_VALUE( |
|---|
| 667 | (sizeof(unsigned long) == sizeof(unsigned) ? uint_type : ulong_long_type), |
|---|
| 668 | unsigned long, ulong_type) |
|---|
| 669 | |
|---|
| 670 | FMT_MAKE_VALUE_SAME(long_long_type, long long) |
|---|
| 671 | FMT_MAKE_VALUE_SAME(ulong_long_type, unsigned long long) |
|---|
| 672 | FMT_MAKE_VALUE(int_type, signed char, int) |
|---|
| 673 | FMT_MAKE_VALUE(uint_type, unsigned char, unsigned) |
|---|
| 674 | |
|---|
| 675 | // This doesn't use FMT_MAKE_VALUE because of ambiguity in gcc 4.4. |
|---|
| 676 | template <typename C, typename Char> |
|---|
| 677 | FMT_CONSTEXPR typename std::enable_if< |
|---|
| 678 | std::is_same<typename C::char_type, Char>::value, |
|---|
| 679 | init<C, int, char_type>>::type make_value(Char val) { return val; } |
|---|
| 680 | |
|---|
| 681 | template <typename C> |
|---|
| 682 | FMT_CONSTEXPR typename std::enable_if< |
|---|
| 683 | !std::is_same<typename C::char_type, char>::value, |
|---|
| 684 | init<C, int, char_type>>::type make_value(char val) { return val; } |
|---|
| 685 | |
|---|
| 686 | FMT_MAKE_VALUE(double_type, float, double) |
|---|
| 687 | FMT_MAKE_VALUE_SAME(double_type, double) |
|---|
| 688 | FMT_MAKE_VALUE_SAME(long_double_type, long double) |
|---|
| 689 | |
|---|
| 690 | // Formatting of wide strings into a narrow buffer and multibyte strings |
|---|
| 691 | // into a wide buffer is disallowed (https://github.com/fmtlib/fmt/pull/606). |
|---|
| 692 | FMT_MAKE_VALUE(cstring_type, typename C::char_type*, |
|---|
| 693 | const typename C::char_type*) |
|---|
| 694 | FMT_MAKE_VALUE(cstring_type, const typename C::char_type*, |
|---|
| 695 | const typename C::char_type*) |
|---|
| 696 | |
|---|
| 697 | FMT_MAKE_VALUE(cstring_type, signed char*, const signed char*) |
|---|
| 698 | FMT_MAKE_VALUE_SAME(cstring_type, const signed char*) |
|---|
| 699 | FMT_MAKE_VALUE(cstring_type, unsigned char*, const unsigned char*) |
|---|
| 700 | FMT_MAKE_VALUE_SAME(cstring_type, const unsigned char*) |
|---|
| 701 | FMT_MAKE_VALUE_SAME(string_type, basic_string_view<typename C::char_type>) |
|---|
| 702 | FMT_MAKE_VALUE(string_type, |
|---|
| 703 | typename basic_string_view<typename C::char_type>::type, |
|---|
| 704 | basic_string_view<typename C::char_type>) |
|---|
| 705 | FMT_MAKE_VALUE(string_type, const std::basic_string<typename C::char_type>&, |
|---|
| 706 | basic_string_view<typename C::char_type>) |
|---|
| 707 | FMT_MAKE_VALUE(pointer_type, void*, const void*) |
|---|
| 708 | FMT_MAKE_VALUE_SAME(pointer_type, const void*) |
|---|
| 709 | |
|---|
| 710 | #if FMT_USE_NULLPTR |
|---|
| 711 | FMT_MAKE_VALUE(pointer_type, std::nullptr_t, const void*) |
|---|
| 712 | #endif |
|---|
| 713 | |
|---|
| 714 | // Formatting of arbitrary pointers is disallowed. If you want to output a |
|---|
| 715 | // pointer cast it to "void *" or "const void *". In particular, this forbids |
|---|
| 716 | // formatting of "[const] volatile char *" which is printed as bool by |
|---|
| 717 | // iostreams. |
|---|
| 718 | template <typename C, typename T> |
|---|
| 719 | typename std::enable_if<!std::is_same<T, typename C::char_type>::value>::type |
|---|
| 720 | make_value(const T *) { |
|---|
| 721 | static_assert(!sizeof(T), "formatting of non-void pointers is disallowed"); |
|---|
| 722 | } |
|---|
| 723 | |
|---|
| 724 | template <typename C, typename T> |
|---|
| 725 | inline typename std::enable_if< |
|---|
| 726 | std::is_enum<T>::value && convert_to_int<T, typename C::char_type>::value, |
|---|
| 727 | init<C, int, int_type>>::type |
|---|
| 728 | make_value(const T &val) { return static_cast<int>(val); } |
|---|
| 729 | |
|---|
| 730 | template <typename C, typename T, typename Char = typename C::char_type> |
|---|
| 731 | inline typename std::enable_if< |
|---|
| 732 | is_constructible<basic_string_view<Char>, T>::value && |
|---|
| 733 | !internal::is_string<T>::value, |
|---|
| 734 | init<C, basic_string_view<Char>, string_type>>::type |
|---|
| 735 | make_value(const T &val) { return basic_string_view<Char>(val); } |
|---|
| 736 | |
|---|
| 737 | template <typename C, typename T, typename Char = typename C::char_type> |
|---|
| 738 | inline typename std::enable_if< |
|---|
| 739 | !convert_to_int<T, Char>::value && !std::is_same<T, Char>::value && |
|---|
| 740 | !std::is_convertible<T, basic_string_view<Char>>::value && |
|---|
| 741 | !is_constructible<basic_string_view<Char>, T>::value && |
|---|
| 742 | !internal::is_string<T>::value, |
|---|
| 743 | // Implicit conversion to std::string is not handled here because it's |
|---|
| 744 | // unsafe: https://github.com/fmtlib/fmt/issues/729 |
|---|
| 745 | init<C, const T &, custom_type>>::type |
|---|
| 746 | make_value(const T &val) { return val; } |
|---|
| 747 | |
|---|
| 748 | template <typename C, typename T> |
|---|
| 749 | init<C, const void*, named_arg_type> |
|---|
| 750 | make_value(const named_arg<T, typename C::char_type> &val) { |
|---|
| 751 | basic_format_arg<C> arg = make_arg<C>(val.value); |
|---|
| 752 | std::memcpy(val.data, &arg, sizeof(arg)); |
|---|
| 753 | return static_cast<const void*>(&val); |
|---|
| 754 | } |
|---|
| 755 | |
|---|
| 756 | template <typename C, typename S> |
|---|
| 757 | FMT_CONSTEXPR11 typename std::enable_if< |
|---|
| 758 | internal::is_string<S>::value, |
|---|
| 759 | init<C, basic_string_view<typename C::char_type>, string_type>>::type |
|---|
| 760 | make_value(const S &val) { |
|---|
| 761 | // Handle adapted strings. |
|---|
| 762 | static_assert(std::is_same< |
|---|
| 763 | typename C::char_type, typename internal::char_t<S>::type>::value, |
|---|
| 764 | "mismatch between char-types of context and argument"); |
|---|
| 765 | return to_string_view(val); |
|---|
| 766 | } |
|---|
| 767 | |
|---|
| 768 | // Maximum number of arguments with packed types. |
|---|
| 769 | enum { max_packed_args = 15 }; |
|---|
| 770 | enum : unsigned long long { is_unpacked_bit = 1ull << 63 }; |
|---|
| 771 | |
|---|
| 772 | template <typename Context> |
|---|
| 773 | class arg_map; |
|---|
| 774 | } // namespace internal |
|---|
| 775 | |
|---|
| 776 | // A formatting argument. It is a trivially copyable/constructible type to |
|---|
| 777 | // allow storage in basic_memory_buffer. |
|---|
| 778 | template <typename Context> |
|---|
| 779 | class basic_format_arg { |
|---|
| 780 | private: |
|---|
| 781 | internal::value<Context> value_; |
|---|
| 782 | internal::type type_; |
|---|
| 783 | |
|---|
| 784 | template <typename ContextType, typename T> |
|---|
| 785 | friend FMT_CONSTEXPR basic_format_arg<ContextType> |
|---|
| 786 | internal::make_arg(const T &value); |
|---|
| 787 | |
|---|
| 788 | template <typename Visitor, typename Ctx> |
|---|
| 789 | friend FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type |
|---|
| 790 | visit_format_arg(Visitor &&vis, const basic_format_arg<Ctx> &arg); |
|---|
| 791 | |
|---|
| 792 | friend class basic_format_args<Context>; |
|---|
| 793 | friend class internal::arg_map<Context>; |
|---|
| 794 | |
|---|
| 795 | typedef typename Context::char_type char_type; |
|---|
| 796 | |
|---|
| 797 | public: |
|---|
| 798 | class handle { |
|---|
| 799 | public: |
|---|
| 800 | explicit handle(internal::custom_value<Context> custom): custom_(custom) {} |
|---|
| 801 | |
|---|
| 802 | void format(Context &ctx) const { custom_.format(custom_.value, ctx); } |
|---|
| 803 | |
|---|
| 804 | private: |
|---|
| 805 | internal::custom_value<Context> custom_; |
|---|
| 806 | }; |
|---|
| 807 | |
|---|
| 808 | FMT_CONSTEXPR basic_format_arg() : type_(internal::none_type) {} |
|---|
| 809 | |
|---|
| 810 | FMT_EXPLICIT operator bool() const FMT_NOEXCEPT { |
|---|
| 811 | return type_ != internal::none_type; |
|---|
| 812 | } |
|---|
| 813 | |
|---|
| 814 | internal::type type() const { return type_; } |
|---|
| 815 | |
|---|
| 816 | bool is_integral() const { return internal::is_integral(type_); } |
|---|
| 817 | bool is_arithmetic() const { return internal::is_arithmetic(type_); } |
|---|
| 818 | }; |
|---|
| 819 | |
|---|
| 820 | struct monostate {}; |
|---|
| 821 | |
|---|
| 822 | /** |
|---|
| 823 | \rst |
|---|
| 824 | Visits an argument dispatching to the appropriate visit method based on |
|---|
| 825 | the argument type. For example, if the argument type is ``double`` then |
|---|
| 826 | ``vis(value)`` will be called with the value of type ``double``. |
|---|
| 827 | \endrst |
|---|
| 828 | */ |
|---|
| 829 | template <typename Visitor, typename Context> |
|---|
| 830 | FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type |
|---|
| 831 | visit_format_arg(Visitor &&vis, const basic_format_arg<Context> &arg) { |
|---|
| 832 | typedef typename Context::char_type char_type; |
|---|
| 833 | switch (arg.type_) { |
|---|
| 834 | case internal::none_type: |
|---|
| 835 | break; |
|---|
| 836 | case internal::named_arg_type: |
|---|
| 837 | FMT_ASSERT(false, "invalid argument type"); |
|---|
| 838 | break; |
|---|
| 839 | case internal::int_type: |
|---|
| 840 | return vis(arg.value_.int_value); |
|---|
| 841 | case internal::uint_type: |
|---|
| 842 | return vis(arg.value_.uint_value); |
|---|
| 843 | case internal::long_long_type: |
|---|
| 844 | return vis(arg.value_.long_long_value); |
|---|
| 845 | case internal::ulong_long_type: |
|---|
| 846 | return vis(arg.value_.ulong_long_value); |
|---|
| 847 | case internal::bool_type: |
|---|
| 848 | return vis(arg.value_.int_value != 0); |
|---|
| 849 | case internal::char_type: |
|---|
| 850 | return vis(static_cast<char_type>(arg.value_.int_value)); |
|---|
| 851 | case internal::double_type: |
|---|
| 852 | return vis(arg.value_.double_value); |
|---|
| 853 | case internal::long_double_type: |
|---|
| 854 | return vis(arg.value_.long_double_value); |
|---|
| 855 | case internal::cstring_type: |
|---|
| 856 | return vis(arg.value_.string.value); |
|---|
| 857 | case internal::string_type: |
|---|
| 858 | return vis(basic_string_view<char_type>( |
|---|
| 859 | arg.value_.string.value, arg.value_.string.size)); |
|---|
| 860 | case internal::pointer_type: |
|---|
| 861 | return vis(arg.value_.pointer); |
|---|
| 862 | case internal::custom_type: |
|---|
| 863 | return vis(typename basic_format_arg<Context>::handle(arg.value_.custom)); |
|---|
| 864 | } |
|---|
| 865 | return vis(monostate()); |
|---|
| 866 | } |
|---|
| 867 | |
|---|
| 868 | // DEPRECATED! |
|---|
| 869 | template <typename Visitor, typename Context> |
|---|
| 870 | FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type |
|---|
| 871 | visit(Visitor &&vis, const basic_format_arg<Context> &arg) { |
|---|
| 872 | return visit_format_arg(std::forward<Visitor>(vis), arg); |
|---|
| 873 | } |
|---|
| 874 | |
|---|
| 875 | // Parsing context consisting of a format string range being parsed and an |
|---|
| 876 | // argument counter for automatic indexing. |
|---|
| 877 | template <typename Char, typename ErrorHandler = internal::error_handler> |
|---|
| 878 | class basic_parse_context : private ErrorHandler { |
|---|
| 879 | private: |
|---|
| 880 | basic_string_view<Char> format_str_; |
|---|
| 881 | int next_arg_id_; |
|---|
| 882 | |
|---|
| 883 | public: |
|---|
| 884 | typedef Char char_type; |
|---|
| 885 | typedef typename basic_string_view<Char>::iterator iterator; |
|---|
| 886 | |
|---|
| 887 | explicit FMT_CONSTEXPR basic_parse_context( |
|---|
| 888 | basic_string_view<Char> format_str, ErrorHandler eh = ErrorHandler()) |
|---|
| 889 | : ErrorHandler(eh), format_str_(format_str), next_arg_id_(0) {} |
|---|
| 890 | |
|---|
| 891 | // Returns an iterator to the beginning of the format string range being |
|---|
| 892 | // parsed. |
|---|
| 893 | FMT_CONSTEXPR iterator begin() const FMT_NOEXCEPT { |
|---|
| 894 | return format_str_.begin(); |
|---|
| 895 | } |
|---|
| 896 | |
|---|
| 897 | // Returns an iterator past the end of the format string range being parsed. |
|---|
| 898 | FMT_CONSTEXPR iterator end() const FMT_NOEXCEPT { return format_str_.end(); } |
|---|
| 899 | |
|---|
| 900 | // Advances the begin iterator to ``it``. |
|---|
| 901 | FMT_CONSTEXPR void advance_to(iterator it) { |
|---|
| 902 | format_str_.remove_prefix(internal::to_unsigned(it - begin())); |
|---|
| 903 | } |
|---|
| 904 | |
|---|
| 905 | // Returns the next argument index. |
|---|
| 906 | FMT_CONSTEXPR unsigned next_arg_id(); |
|---|
| 907 | |
|---|
| 908 | FMT_CONSTEXPR bool check_arg_id(unsigned) { |
|---|
| 909 | if (next_arg_id_ > 0) { |
|---|
| 910 | on_error("cannot switch from automatic to manual argument indexing"); |
|---|
| 911 | return false; |
|---|
| 912 | } |
|---|
| 913 | next_arg_id_ = -1; |
|---|
| 914 | return true; |
|---|
| 915 | } |
|---|
| 916 | void check_arg_id(basic_string_view<Char>) {} |
|---|
| 917 | |
|---|
| 918 | FMT_CONSTEXPR void on_error(const char *message) { |
|---|
| 919 | ErrorHandler::on_error(message); |
|---|
| 920 | } |
|---|
| 921 | |
|---|
| 922 | FMT_CONSTEXPR ErrorHandler error_handler() const { return *this; } |
|---|
| 923 | }; |
|---|
| 924 | |
|---|
| 925 | typedef basic_parse_context<char> format_parse_context; |
|---|
| 926 | typedef basic_parse_context<wchar_t> wformat_parse_context; |
|---|
| 927 | |
|---|
| 928 | // DEPRECATED! |
|---|
| 929 | typedef basic_parse_context<char> parse_context; |
|---|
| 930 | typedef basic_parse_context<wchar_t> wparse_context; |
|---|
| 931 | |
|---|
| 932 | namespace internal { |
|---|
| 933 | // A map from argument names to their values for named arguments. |
|---|
| 934 | template <typename Context> |
|---|
| 935 | class arg_map { |
|---|
| 936 | private: |
|---|
| 937 | arg_map(const arg_map &) = delete; |
|---|
| 938 | void operator=(const arg_map &) = delete; |
|---|
| 939 | |
|---|
| 940 | typedef typename Context::char_type char_type; |
|---|
| 941 | |
|---|
| 942 | struct entry { |
|---|
| 943 | basic_string_view<char_type> name; |
|---|
| 944 | basic_format_arg<Context> arg; |
|---|
| 945 | }; |
|---|
| 946 | |
|---|
| 947 | entry *map_; |
|---|
| 948 | unsigned size_; |
|---|
| 949 | |
|---|
| 950 | void push_back(value<Context> val) { |
|---|
| 951 | const internal::named_arg_base<char_type> &named = val.as_named_arg(); |
|---|
| 952 | map_[size_] = entry{named.name, named.template deserialize<Context>()}; |
|---|
| 953 | ++size_; |
|---|
| 954 | } |
|---|
| 955 | |
|---|
| 956 | public: |
|---|
| 957 | arg_map() : map_(FMT_NULL), size_(0) {} |
|---|
| 958 | void init(const basic_format_args<Context> &args); |
|---|
| 959 | ~arg_map() { delete [] map_; } |
|---|
| 960 | |
|---|
| 961 | basic_format_arg<Context> find(basic_string_view<char_type> name) const { |
|---|
| 962 | // The list is unsorted, so just return the first matching name. |
|---|
| 963 | for (entry *it = map_, *end = map_ + size_; it != end; ++it) { |
|---|
| 964 | if (it->name == name) |
|---|
| 965 | return it->arg; |
|---|
| 966 | } |
|---|
| 967 | return {}; |
|---|
| 968 | } |
|---|
| 969 | }; |
|---|
| 970 | |
|---|
| 971 | // A type-erased reference to an std::locale to avoid heavy <locale> include. |
|---|
| 972 | class locale_ref { |
|---|
| 973 | private: |
|---|
| 974 | const void *locale_; // A type-erased pointer to std::locale. |
|---|
| 975 | friend class locale; |
|---|
| 976 | |
|---|
| 977 | public: |
|---|
| 978 | locale_ref() : locale_(FMT_NULL) {} |
|---|
| 979 | |
|---|
| 980 | template <typename Locale> |
|---|
| 981 | explicit locale_ref(const Locale &loc); |
|---|
| 982 | |
|---|
| 983 | template <typename Locale> |
|---|
| 984 | Locale get() const; |
|---|
| 985 | }; |
|---|
| 986 | |
|---|
| 987 | template <typename OutputIt, typename Context, typename Char> |
|---|
| 988 | class context_base { |
|---|
| 989 | public: |
|---|
| 990 | typedef OutputIt iterator; |
|---|
| 991 | |
|---|
| 992 | private: |
|---|
| 993 | basic_parse_context<Char> parse_context_; |
|---|
| 994 | iterator out_; |
|---|
| 995 | basic_format_args<Context> args_; |
|---|
| 996 | locale_ref loc_; |
|---|
| 997 | |
|---|
| 998 | protected: |
|---|
| 999 | typedef Char char_type; |
|---|
| 1000 | typedef basic_format_arg<Context> format_arg; |
|---|
| 1001 | |
|---|
| 1002 | context_base(OutputIt out, basic_string_view<char_type> format_str, |
|---|
| 1003 | basic_format_args<Context> ctx_args, |
|---|
| 1004 | locale_ref loc = locale_ref()) |
|---|
| 1005 | : parse_context_(format_str), out_(out), args_(ctx_args), loc_(loc) {} |
|---|
| 1006 | |
|---|
| 1007 | // Returns the argument with specified index. |
|---|
| 1008 | format_arg do_get_arg(unsigned arg_id) { |
|---|
| 1009 | format_arg arg = args_.get(arg_id); |
|---|
| 1010 | if (!arg) |
|---|
| 1011 | parse_context_.on_error("argument index out of range"); |
|---|
| 1012 | return arg; |
|---|
| 1013 | } |
|---|
| 1014 | |
|---|
| 1015 | // Checks if manual indexing is used and returns the argument with |
|---|
| 1016 | // specified index. |
|---|
| 1017 | format_arg get_arg(unsigned arg_id) { |
|---|
| 1018 | return this->parse_context().check_arg_id(arg_id) ? |
|---|
| 1019 | this->do_get_arg(arg_id) : format_arg(); |
|---|
| 1020 | } |
|---|
| 1021 | |
|---|
| 1022 | public: |
|---|
| 1023 | basic_parse_context<char_type> &parse_context() { return parse_context_; } |
|---|
| 1024 | basic_format_args<Context> args() const { return args_; } // DEPRECATED! |
|---|
| 1025 | basic_format_arg<Context> arg(unsigned id) const { return args_.get(id); } |
|---|
| 1026 | |
|---|
| 1027 | internal::error_handler error_handler() { |
|---|
| 1028 | return parse_context_.error_handler(); |
|---|
| 1029 | } |
|---|
| 1030 | |
|---|
| 1031 | void on_error(const char *message) { parse_context_.on_error(message); } |
|---|
| 1032 | |
|---|
| 1033 | // Returns an iterator to the beginning of the output range. |
|---|
| 1034 | iterator out() { return out_; } |
|---|
| 1035 | iterator begin() { return out_; } // deprecated |
|---|
| 1036 | |
|---|
| 1037 | // Advances the begin iterator to ``it``. |
|---|
| 1038 | void advance_to(iterator it) { out_ = it; } |
|---|
| 1039 | |
|---|
| 1040 | locale_ref locale() { return loc_; } |
|---|
| 1041 | }; |
|---|
| 1042 | |
|---|
| 1043 | template <typename Context, typename T> |
|---|
| 1044 | struct get_type { |
|---|
| 1045 | typedef decltype(make_value<Context>( |
|---|
| 1046 | declval<typename std::decay<T>::type&>())) value_type; |
|---|
| 1047 | static const type value = value_type::type_tag; |
|---|
| 1048 | }; |
|---|
| 1049 | |
|---|
| 1050 | template <typename Context> |
|---|
| 1051 | FMT_CONSTEXPR11 unsigned long long get_types() { return 0; } |
|---|
| 1052 | |
|---|
| 1053 | template <typename Context, typename Arg, typename... Args> |
|---|
| 1054 | FMT_CONSTEXPR11 unsigned long long get_types() { |
|---|
| 1055 | return get_type<Context, Arg>::value | (get_types<Context, Args...>() << 4); |
|---|
| 1056 | } |
|---|
| 1057 | |
|---|
| 1058 | template <typename Context, typename T> |
|---|
| 1059 | FMT_CONSTEXPR basic_format_arg<Context> make_arg(const T &value) { |
|---|
| 1060 | basic_format_arg<Context> arg; |
|---|
| 1061 | arg.type_ = get_type<Context, T>::value; |
|---|
| 1062 | arg.value_ = make_value<Context>(value); |
|---|
| 1063 | return arg; |
|---|
| 1064 | } |
|---|
| 1065 | |
|---|
| 1066 | template <bool IS_PACKED, typename Context, typename T> |
|---|
| 1067 | inline typename std::enable_if<IS_PACKED, value<Context>>::type |
|---|
| 1068 | make_arg(const T &value) { |
|---|
| 1069 | return make_value<Context>(value); |
|---|
| 1070 | } |
|---|
| 1071 | |
|---|
| 1072 | template <bool IS_PACKED, typename Context, typename T> |
|---|
| 1073 | inline typename std::enable_if<!IS_PACKED, basic_format_arg<Context>>::type |
|---|
| 1074 | make_arg(const T &value) { |
|---|
| 1075 | return make_arg<Context>(value); |
|---|
| 1076 | } |
|---|
| 1077 | } // namespace internal |
|---|
| 1078 | |
|---|
| 1079 | // Formatting context. |
|---|
| 1080 | template <typename OutputIt, typename Char> |
|---|
| 1081 | class basic_format_context : |
|---|
| 1082 | public internal::context_base< |
|---|
| 1083 | OutputIt, basic_format_context<OutputIt, Char>, Char> { |
|---|
| 1084 | public: |
|---|
| 1085 | /** The character type for the output. */ |
|---|
| 1086 | typedef Char char_type; |
|---|
| 1087 | |
|---|
| 1088 | // using formatter_type = formatter<T, char_type>; |
|---|
| 1089 | template <typename T> |
|---|
| 1090 | struct formatter_type { typedef formatter<T, char_type> type; }; |
|---|
| 1091 | |
|---|
| 1092 | private: |
|---|
| 1093 | internal::arg_map<basic_format_context> map_; |
|---|
| 1094 | |
|---|
| 1095 | basic_format_context(const basic_format_context &) = delete; |
|---|
| 1096 | void operator=(const basic_format_context &) = delete; |
|---|
| 1097 | |
|---|
| 1098 | typedef internal::context_base<OutputIt, basic_format_context, Char> base; |
|---|
| 1099 | typedef typename base::format_arg format_arg; |
|---|
| 1100 | using base::get_arg; |
|---|
| 1101 | |
|---|
| 1102 | public: |
|---|
| 1103 | using typename base::iterator; |
|---|
| 1104 | |
|---|
| 1105 | /** |
|---|
| 1106 | Constructs a ``basic_format_context`` object. References to the arguments are |
|---|
| 1107 | stored in the object so make sure they have appropriate lifetimes. |
|---|
| 1108 | */ |
|---|
| 1109 | basic_format_context(OutputIt out, basic_string_view<char_type> format_str, |
|---|
| 1110 | basic_format_args<basic_format_context> ctx_args, |
|---|
| 1111 | internal::locale_ref loc = internal::locale_ref()) |
|---|
| 1112 | : base(out, format_str, ctx_args, loc) {} |
|---|
| 1113 | |
|---|
| 1114 | format_arg next_arg() { |
|---|
| 1115 | return this->do_get_arg(this->parse_context().next_arg_id()); |
|---|
| 1116 | } |
|---|
| 1117 | format_arg get_arg(unsigned arg_id) { return this->do_get_arg(arg_id); } |
|---|
| 1118 | |
|---|
| 1119 | // Checks if manual indexing is used and returns the argument with the |
|---|
| 1120 | // specified name. |
|---|
| 1121 | format_arg get_arg(basic_string_view<char_type> name); |
|---|
| 1122 | }; |
|---|
| 1123 | |
|---|
| 1124 | template <typename Char> |
|---|
| 1125 | struct buffer_context { |
|---|
| 1126 | typedef basic_format_context< |
|---|
| 1127 | std::back_insert_iterator<internal::basic_buffer<Char>>, Char> type; |
|---|
| 1128 | }; |
|---|
| 1129 | typedef buffer_context<char>::type format_context; |
|---|
| 1130 | typedef buffer_context<wchar_t>::type wformat_context; |
|---|
| 1131 | |
|---|
| 1132 | /** |
|---|
| 1133 | \rst |
|---|
| 1134 | An array of references to arguments. It can be implicitly converted into |
|---|
| 1135 | `~fmt::basic_format_args` for passing into type-erased formatting functions |
|---|
| 1136 | such as `~fmt::vformat`. |
|---|
| 1137 | \endrst |
|---|
| 1138 | */ |
|---|
| 1139 | template <typename Context, typename ...Args> |
|---|
| 1140 | class format_arg_store { |
|---|
| 1141 | private: |
|---|
| 1142 | static const size_t NUM_ARGS = sizeof...(Args); |
|---|
| 1143 | |
|---|
| 1144 | // Packed is a macro on MinGW so use IS_PACKED instead. |
|---|
| 1145 | static const bool IS_PACKED = NUM_ARGS < internal::max_packed_args; |
|---|
| 1146 | |
|---|
| 1147 | typedef typename std::conditional<IS_PACKED, |
|---|
| 1148 | internal::value<Context>, basic_format_arg<Context>>::type value_type; |
|---|
| 1149 | |
|---|
| 1150 | // If the arguments are not packed, add one more element to mark the end. |
|---|
| 1151 | static const size_t DATA_SIZE = |
|---|
| 1152 | NUM_ARGS + (IS_PACKED && NUM_ARGS != 0 ? 0 : 1); |
|---|
| 1153 | value_type data_[DATA_SIZE]; |
|---|
| 1154 | |
|---|
| 1155 | friend class basic_format_args<Context>; |
|---|
| 1156 | |
|---|
| 1157 | static FMT_CONSTEXPR11 unsigned long long get_types() { |
|---|
| 1158 | return IS_PACKED ? |
|---|
| 1159 | internal::get_types<Context, Args...>() : |
|---|
| 1160 | internal::is_unpacked_bit | NUM_ARGS; |
|---|
| 1161 | } |
|---|
| 1162 | |
|---|
| 1163 | public: |
|---|
| 1164 | #if FMT_USE_CONSTEXPR11 |
|---|
| 1165 | static FMT_CONSTEXPR11 unsigned long long TYPES = get_types(); |
|---|
| 1166 | #else |
|---|
| 1167 | static const unsigned long long TYPES; |
|---|
| 1168 | #endif |
|---|
| 1169 | |
|---|
| 1170 | #if (FMT_GCC_VERSION && FMT_GCC_VERSION <= 405) || \ |
|---|
| 1171 | (FMT_MSC_VER && FMT_MSC_VER <= 1800) |
|---|
| 1172 | // Workaround array initialization issues in gcc <= 4.5 and MSVC <= 2013. |
|---|
| 1173 | format_arg_store(const Args &... args) { |
|---|
| 1174 | value_type init[DATA_SIZE] = |
|---|
| 1175 | {internal::make_arg<IS_PACKED, Context>(args)...}; |
|---|
| 1176 | std::memcpy(data_, init, sizeof(init)); |
|---|
| 1177 | } |
|---|
| 1178 | #else |
|---|
| 1179 | format_arg_store(const Args &... args) |
|---|
| 1180 | : data_{internal::make_arg<IS_PACKED, Context>(args)...} {} |
|---|
| 1181 | #endif |
|---|
| 1182 | }; |
|---|
| 1183 | |
|---|
| 1184 | #if !FMT_USE_CONSTEXPR11 |
|---|
| 1185 | template <typename Context, typename ...Args> |
|---|
| 1186 | const unsigned long long format_arg_store<Context, Args...>::TYPES = |
|---|
| 1187 | get_types(); |
|---|
| 1188 | #endif |
|---|
| 1189 | |
|---|
| 1190 | /** |
|---|
| 1191 | \rst |
|---|
| 1192 | Constructs an `~fmt::format_arg_store` object that contains references to |
|---|
| 1193 | arguments and can be implicitly converted to `~fmt::format_args`. `Context` |
|---|
| 1194 | can be omitted in which case it defaults to `~fmt::context`. |
|---|
| 1195 | \endrst |
|---|
| 1196 | */ |
|---|
| 1197 | template <typename Context = format_context, typename ...Args> |
|---|
| 1198 | inline format_arg_store<Context, Args...> |
|---|
| 1199 | make_format_args(const Args &... args) { return {args...}; } |
|---|
| 1200 | |
|---|
| 1201 | /** Formatting arguments. */ |
|---|
| 1202 | template <typename Context> |
|---|
| 1203 | class basic_format_args { |
|---|
| 1204 | public: |
|---|
| 1205 | typedef unsigned size_type; |
|---|
| 1206 | typedef basic_format_arg<Context> format_arg; |
|---|
| 1207 | |
|---|
| 1208 | private: |
|---|
| 1209 | // To reduce compiled code size per formatting function call, types of first |
|---|
| 1210 | // max_packed_args arguments are passed in the types_ field. |
|---|
| 1211 | unsigned long long types_; |
|---|
| 1212 | union { |
|---|
| 1213 | // If the number of arguments is less than max_packed_args, the argument |
|---|
| 1214 | // values are stored in values_, otherwise they are stored in args_. |
|---|
| 1215 | // This is done to reduce compiled code size as storing larger objects |
|---|
| 1216 | // may require more code (at least on x86-64) even if the same amount of |
|---|
| 1217 | // data is actually copied to stack. It saves ~10% on the bloat test. |
|---|
| 1218 | const internal::value<Context> *values_; |
|---|
| 1219 | const format_arg *args_; |
|---|
| 1220 | }; |
|---|
| 1221 | |
|---|
| 1222 | bool is_packed() const { return (types_ & internal::is_unpacked_bit) == 0; } |
|---|
| 1223 | |
|---|
| 1224 | typename internal::type type(unsigned index) const { |
|---|
| 1225 | unsigned shift = index * 4; |
|---|
| 1226 | return static_cast<typename internal::type>( |
|---|
| 1227 | (types_ & (0xfull << shift)) >> shift); |
|---|
| 1228 | } |
|---|
| 1229 | |
|---|
| 1230 | friend class internal::arg_map<Context>; |
|---|
| 1231 | |
|---|
| 1232 | void set_data(const internal::value<Context> *values) { values_ = values; } |
|---|
| 1233 | void set_data(const format_arg *args) { args_ = args; } |
|---|
| 1234 | |
|---|
| 1235 | format_arg do_get(size_type index) const { |
|---|
| 1236 | format_arg arg; |
|---|
| 1237 | if (!is_packed()) { |
|---|
| 1238 | auto num_args = max_size(); |
|---|
| 1239 | if (index < num_args) |
|---|
| 1240 | arg = args_[index]; |
|---|
| 1241 | return arg; |
|---|
| 1242 | } |
|---|
| 1243 | if (index > internal::max_packed_args) |
|---|
| 1244 | return arg; |
|---|
| 1245 | arg.type_ = type(index); |
|---|
| 1246 | if (arg.type_ == internal::none_type) |
|---|
| 1247 | return arg; |
|---|
| 1248 | internal::value<Context> &val = arg.value_; |
|---|
| 1249 | val = values_[index]; |
|---|
| 1250 | return arg; |
|---|
| 1251 | } |
|---|
| 1252 | |
|---|
| 1253 | public: |
|---|
| 1254 | basic_format_args() : types_(0) {} |
|---|
| 1255 | |
|---|
| 1256 | /** |
|---|
| 1257 | \rst |
|---|
| 1258 | Constructs a `basic_format_args` object from `~fmt::format_arg_store`. |
|---|
| 1259 | \endrst |
|---|
| 1260 | */ |
|---|
| 1261 | template <typename... Args> |
|---|
| 1262 | basic_format_args(const format_arg_store<Context, Args...> &store) |
|---|
| 1263 | : types_(static_cast<unsigned long long>(store.TYPES)) { |
|---|
| 1264 | set_data(store.data_); |
|---|
| 1265 | } |
|---|
| 1266 | |
|---|
| 1267 | /** |
|---|
| 1268 | \rst |
|---|
| 1269 | Constructs a `basic_format_args` object from a dynamic set of arguments. |
|---|
| 1270 | \endrst |
|---|
| 1271 | */ |
|---|
| 1272 | basic_format_args(const format_arg *args, size_type count) |
|---|
| 1273 | : types_(internal::is_unpacked_bit | count) { |
|---|
| 1274 | set_data(args); |
|---|
| 1275 | } |
|---|
| 1276 | |
|---|
| 1277 | /** Returns the argument at specified index. */ |
|---|
| 1278 | format_arg get(size_type index) const { |
|---|
| 1279 | format_arg arg = do_get(index); |
|---|
| 1280 | if (arg.type_ == internal::named_arg_type) |
|---|
| 1281 | arg = arg.value_.as_named_arg().template deserialize<Context>(); |
|---|
| 1282 | return arg; |
|---|
| 1283 | } |
|---|
| 1284 | |
|---|
| 1285 | size_type max_size() const { |
|---|
| 1286 | unsigned long long max_packed = internal::max_packed_args; |
|---|
| 1287 | return static_cast<size_type>( |
|---|
| 1288 | is_packed() ? max_packed : types_ & ~internal::is_unpacked_bit); |
|---|
| 1289 | } |
|---|
| 1290 | }; |
|---|
| 1291 | |
|---|
| 1292 | /** An alias to ``basic_format_args<context>``. */ |
|---|
| 1293 | // It is a separate type rather than a typedef to make symbols readable. |
|---|
| 1294 | struct format_args : basic_format_args<format_context> { |
|---|
| 1295 | template <typename ...Args> |
|---|
| 1296 | format_args(Args &&... arg) |
|---|
| 1297 | : basic_format_args<format_context>(std::forward<Args>(arg)...) {} |
|---|
| 1298 | }; |
|---|
| 1299 | struct wformat_args : basic_format_args<wformat_context> { |
|---|
| 1300 | template <typename ...Args> |
|---|
| 1301 | wformat_args(Args &&... arg) |
|---|
| 1302 | : basic_format_args<wformat_context>(std::forward<Args>(arg)...) {} |
|---|
| 1303 | }; |
|---|
| 1304 | |
|---|
| 1305 | #define FMT_ENABLE_IF_T(B, T) typename std::enable_if<B, T>::type |
|---|
| 1306 | |
|---|
| 1307 | #ifndef FMT_USE_ALIAS_TEMPLATES |
|---|
| 1308 | # define FMT_USE_ALIAS_TEMPLATES FMT_HAS_FEATURE(cxx_alias_templates) |
|---|
| 1309 | #endif |
|---|
| 1310 | #if FMT_USE_ALIAS_TEMPLATES |
|---|
| 1311 | /** String's character type. */ |
|---|
| 1312 | template <typename S> |
|---|
| 1313 | using char_t = FMT_ENABLE_IF_T( |
|---|
| 1314 | internal::is_string<S>::value, typename internal::char_t<S>::type); |
|---|
| 1315 | #define FMT_CHAR(S) fmt::char_t<S> |
|---|
| 1316 | #else |
|---|
| 1317 | template <typename S> |
|---|
| 1318 | struct char_t : std::enable_if< |
|---|
| 1319 | internal::is_string<S>::value, typename internal::char_t<S>::type> {}; |
|---|
| 1320 | #define FMT_CHAR(S) typename char_t<S>::type |
|---|
| 1321 | #endif |
|---|
| 1322 | |
|---|
| 1323 | namespace internal { |
|---|
| 1324 | template <typename Char> |
|---|
| 1325 | struct named_arg_base { |
|---|
| 1326 | basic_string_view<Char> name; |
|---|
| 1327 | |
|---|
| 1328 | // Serialized value<context>. |
|---|
| 1329 | mutable char data[ |
|---|
| 1330 | sizeof(basic_format_arg<typename buffer_context<Char>::type>)]; |
|---|
| 1331 | |
|---|
| 1332 | named_arg_base(basic_string_view<Char> nm) : name(nm) {} |
|---|
| 1333 | |
|---|
| 1334 | template <typename Context> |
|---|
| 1335 | basic_format_arg<Context> deserialize() const { |
|---|
| 1336 | basic_format_arg<Context> arg; |
|---|
| 1337 | std::memcpy(&arg, data, sizeof(basic_format_arg<Context>)); |
|---|
| 1338 | return arg; |
|---|
| 1339 | } |
|---|
| 1340 | }; |
|---|
| 1341 | |
|---|
| 1342 | template <typename T, typename Char> |
|---|
| 1343 | struct named_arg : named_arg_base<Char> { |
|---|
| 1344 | const T &value; |
|---|
| 1345 | |
|---|
| 1346 | named_arg(basic_string_view<Char> name, const T &val) |
|---|
| 1347 | : named_arg_base<Char>(name), value(val) {} |
|---|
| 1348 | }; |
|---|
| 1349 | |
|---|
| 1350 | template <typename... Args, typename S> |
|---|
| 1351 | inline typename std::enable_if<!is_compile_string<S>::value>::type |
|---|
| 1352 | check_format_string(const S &) {} |
|---|
| 1353 | template <typename... Args, typename S> |
|---|
| 1354 | typename std::enable_if<is_compile_string<S>::value>::type |
|---|
| 1355 | check_format_string(S); |
|---|
| 1356 | |
|---|
| 1357 | template <typename S, typename... Args> |
|---|
| 1358 | struct checked_args : format_arg_store< |
|---|
| 1359 | typename buffer_context<FMT_CHAR(S)>::type, Args...> { |
|---|
| 1360 | typedef typename buffer_context<FMT_CHAR(S)>::type context; |
|---|
| 1361 | |
|---|
| 1362 | checked_args(const S &format_str, const Args &... args): |
|---|
| 1363 | format_arg_store<context, Args...>(args...) { |
|---|
| 1364 | internal::check_format_string<Args...>(format_str); |
|---|
| 1365 | } |
|---|
| 1366 | |
|---|
| 1367 | basic_format_args<context> operator*() const { return *this; } |
|---|
| 1368 | }; |
|---|
| 1369 | |
|---|
| 1370 | template <typename Char> |
|---|
| 1371 | std::basic_string<Char> vformat( |
|---|
| 1372 | basic_string_view<Char> format_str, |
|---|
| 1373 | basic_format_args<typename buffer_context<Char>::type> args); |
|---|
| 1374 | |
|---|
| 1375 | template <typename Char> |
|---|
| 1376 | typename buffer_context<Char>::type::iterator vformat_to( |
|---|
| 1377 | internal::basic_buffer<Char> &buf, basic_string_view<Char> format_str, |
|---|
| 1378 | basic_format_args<typename buffer_context<Char>::type> args); |
|---|
| 1379 | } |
|---|
| 1380 | |
|---|
| 1381 | /** |
|---|
| 1382 | \rst |
|---|
| 1383 | Returns a named argument to be used in a formatting function. |
|---|
| 1384 | |
|---|
| 1385 | **Example**:: |
|---|
| 1386 | |
|---|
| 1387 | fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23)); |
|---|
| 1388 | \endrst |
|---|
| 1389 | */ |
|---|
| 1390 | template <typename T> |
|---|
| 1391 | inline internal::named_arg<T, char> arg(string_view name, const T &arg) { |
|---|
| 1392 | return {name, arg}; |
|---|
| 1393 | } |
|---|
| 1394 | |
|---|
| 1395 | template <typename T> |
|---|
| 1396 | inline internal::named_arg<T, wchar_t> arg(wstring_view name, const T &arg) { |
|---|
| 1397 | return {name, arg}; |
|---|
| 1398 | } |
|---|
| 1399 | |
|---|
| 1400 | // Disable nested named arguments, e.g. ``arg("a", arg("b", 42))``. |
|---|
| 1401 | template <typename S, typename T, typename Char> |
|---|
| 1402 | void arg(S, internal::named_arg<T, Char>) = delete; |
|---|
| 1403 | |
|---|
| 1404 | template <typename Container> |
|---|
| 1405 | struct is_contiguous: std::false_type {}; |
|---|
| 1406 | |
|---|
| 1407 | template <typename Char> |
|---|
| 1408 | struct is_contiguous<std::basic_string<Char> >: std::true_type {}; |
|---|
| 1409 | |
|---|
| 1410 | template <typename Char> |
|---|
| 1411 | struct is_contiguous<internal::basic_buffer<Char> >: std::true_type {}; |
|---|
| 1412 | |
|---|
| 1413 | /** Formats a string and writes the output to ``out``. */ |
|---|
| 1414 | template <typename Container, typename S> |
|---|
| 1415 | typename std::enable_if< |
|---|
| 1416 | is_contiguous<Container>::value, std::back_insert_iterator<Container>>::type |
|---|
| 1417 | vformat_to( |
|---|
| 1418 | std::back_insert_iterator<Container> out, |
|---|
| 1419 | const S &format_str, |
|---|
| 1420 | basic_format_args<typename buffer_context<FMT_CHAR(S)>::type> args) { |
|---|
| 1421 | internal::container_buffer<Container> buf(internal::get_container(out)); |
|---|
| 1422 | internal::vformat_to(buf, to_string_view(format_str), args); |
|---|
| 1423 | return out; |
|---|
| 1424 | } |
|---|
| 1425 | |
|---|
| 1426 | template <typename Container, typename S, typename... Args> |
|---|
| 1427 | inline typename std::enable_if< |
|---|
| 1428 | is_contiguous<Container>::value && internal::is_string<S>::value, |
|---|
| 1429 | std::back_insert_iterator<Container>>::type |
|---|
| 1430 | format_to(std::back_insert_iterator<Container> out, const S &format_str, |
|---|
| 1431 | const Args &... args) { |
|---|
| 1432 | internal::checked_args<S, Args...> ca(format_str, args...); |
|---|
| 1433 | return vformat_to(out, to_string_view(format_str), *ca); |
|---|
| 1434 | } |
|---|
| 1435 | |
|---|
| 1436 | template <typename S, typename Char = FMT_CHAR(S)> |
|---|
| 1437 | inline std::basic_string<Char> vformat( |
|---|
| 1438 | const S &format_str, |
|---|
| 1439 | basic_format_args<typename buffer_context<Char>::type> args) { |
|---|
| 1440 | return internal::vformat(to_string_view(format_str), args); |
|---|
| 1441 | } |
|---|
| 1442 | |
|---|
| 1443 | /** |
|---|
| 1444 | \rst |
|---|
| 1445 | Formats arguments and returns the result as a string. |
|---|
| 1446 | |
|---|
| 1447 | **Example**:: |
|---|
| 1448 | |
|---|
| 1449 | #include <fmt/core.h> |
|---|
| 1450 | std::string message = fmt::format("The answer is {}", 42); |
|---|
| 1451 | \endrst |
|---|
| 1452 | */ |
|---|
| 1453 | template <typename S, typename... Args> |
|---|
| 1454 | inline std::basic_string<FMT_CHAR(S)> format( |
|---|
| 1455 | const S &format_str, const Args &... args) { |
|---|
| 1456 | return internal::vformat( |
|---|
| 1457 | to_string_view(format_str), |
|---|
| 1458 | *internal::checked_args<S, Args...>(format_str, args...)); |
|---|
| 1459 | } |
|---|
| 1460 | |
|---|
| 1461 | FMT_API void vprint(std::FILE *f, string_view format_str, format_args args); |
|---|
| 1462 | FMT_API void vprint(std::FILE *f, wstring_view format_str, wformat_args args); |
|---|
| 1463 | |
|---|
| 1464 | /** |
|---|
| 1465 | \rst |
|---|
| 1466 | Prints formatted data to the file *f*. For wide format strings, |
|---|
| 1467 | *f* should be in wide-oriented mode set via ``fwide(f, 1)`` or |
|---|
| 1468 | ``_setmode(_fileno(f), _O_U8TEXT)`` on Windows. |
|---|
| 1469 | |
|---|
| 1470 | **Example**:: |
|---|
| 1471 | |
|---|
| 1472 | fmt::print(stderr, "Don't {}!", "panic"); |
|---|
| 1473 | \endrst |
|---|
| 1474 | */ |
|---|
| 1475 | template <typename S, typename... Args> |
|---|
| 1476 | inline FMT_ENABLE_IF_T(internal::is_string<S>::value, void) |
|---|
| 1477 | print(std::FILE *f, const S &format_str, const Args &... args) { |
|---|
| 1478 | vprint(f, to_string_view(format_str), |
|---|
| 1479 | internal::checked_args<S, Args...>(format_str, args...)); |
|---|
| 1480 | } |
|---|
| 1481 | |
|---|
| 1482 | FMT_API void vprint(string_view format_str, format_args args); |
|---|
| 1483 | FMT_API void vprint(wstring_view format_str, wformat_args args); |
|---|
| 1484 | |
|---|
| 1485 | /** |
|---|
| 1486 | \rst |
|---|
| 1487 | Prints formatted data to ``stdout``. |
|---|
| 1488 | |
|---|
| 1489 | **Example**:: |
|---|
| 1490 | |
|---|
| 1491 | fmt::print("Elapsed time: {0:.2f} seconds", 1.23); |
|---|
| 1492 | \endrst |
|---|
| 1493 | */ |
|---|
| 1494 | template <typename S, typename... Args> |
|---|
| 1495 | inline FMT_ENABLE_IF_T(internal::is_string<S>::value, void) |
|---|
| 1496 | print(const S &format_str, const Args &... args) { |
|---|
| 1497 | vprint(to_string_view(format_str), |
|---|
| 1498 | internal::checked_args<S, Args...>(format_str, args...)); |
|---|
| 1499 | } |
|---|
| 1500 | FMT_END_NAMESPACE |
|---|
| 1501 | |
|---|
| 1502 | #endif // FMT_CORE_H_ |
|---|