| 1 | /* |
| 2 | Formatting library for C++ |
| 3 | |
| 4 | Copyright (c) 2012 - 2014, Victor Zverovich |
| 5 | All rights reserved. |
| 6 | |
| 7 | Redistribution and use in source and binary forms, with or without |
| 8 | modification, are permitted provided that the following conditions are met: |
| 9 | |
| 10 | 1. Redistributions of source code must retain the above copyright notice, this |
| 11 | list of conditions and the following disclaimer. |
| 12 | 2. Redistributions in binary form must reproduce the above copyright notice, |
| 13 | this list of conditions and the following disclaimer in the documentation |
| 14 | and/or other materials provided with the distribution. |
| 15 | |
| 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR |
| 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 | */ |
| 27 | |
| 28 | #ifndef FMT_FORMAT_H_ |
| 29 | #define FMT_FORMAT_H_ |
| 30 | |
| 31 | #include <stdint.h> |
| 32 | |
| 33 | #include <cassert> |
| 34 | #include <cstddef> // for std::ptrdiff_t |
| 35 | #include <cstdio> |
| 36 | #include <algorithm> |
| 37 | #include <limits> |
| 38 | #include <stdexcept> |
| 39 | #include <string> |
| 40 | #include <sstream> |
| 41 | |
| 42 | #if _SECURE_SCL |
| 43 | # include <iterator> |
| 44 | #endif |
| 45 | |
| 46 | #ifdef __GNUC__ |
| 47 | # define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) |
| 48 | # define FMT_GCC_EXTENSION __extension__ |
| 49 | // Disable warning about "long long" which is sometimes reported even |
| 50 | // when using __extension__. |
| 51 | # if FMT_GCC_VERSION >= 406 |
| 52 | # pragma GCC diagnostic push |
| 53 | # pragma GCC diagnostic ignored "-Wlong-long" |
| 54 | # endif |
| 55 | #else |
| 56 | # define FMT_GCC_EXTENSION |
| 57 | #endif |
| 58 | |
| 59 | #ifdef __GNUC_LIBSTD__ |
| 60 | # define FMT_GNUC_LIBSTD_VERSION (__GNUC_LIBSTD__ * 100 + __GNUC_LIBSTD_MINOR__) |
| 61 | #endif |
| 62 | |
| 63 | #ifdef __has_feature |
| 64 | # define FMT_HAS_FEATURE(x) __has_feature(x) |
| 65 | #else |
| 66 | # define FMT_HAS_FEATURE(x) 0 |
| 67 | #endif |
| 68 | |
| 69 | #ifdef __has_builtin |
| 70 | # define FMT_HAS_BUILTIN(x) __has_builtin(x) |
| 71 | #else |
| 72 | # define FMT_HAS_BUILTIN(x) 0 |
| 73 | #endif |
| 74 | |
| 75 | #ifndef FMT_USE_VARIADIC_TEMPLATES |
| 76 | // Variadic templates are available in GCC since version 4.4 |
| 77 | // (http://gcc.gnu.org/projects/cxx0x.html) and in Visual C++ |
| 78 | // since version 2013. |
| 79 | # define FMT_USE_VARIADIC_TEMPLATES \ |
| 80 | (FMT_HAS_FEATURE(cxx_variadic_templates) || \ |
| 81 | (FMT_GCC_VERSION >= 404 && __cplusplus >= 201103) || _MSC_VER >= 1800) |
| 82 | #endif |
| 83 | |
| 84 | #ifndef FMT_USE_RVALUE_REFERENCES |
| 85 | // Don't use rvalue references when compiling with clang and an old libstdc++ |
| 86 | // as the latter doesn't provide std::move. |
| 87 | # if defined(FMT_GNUC_LIBSTD_VERSION) && FMT_GNUC_LIBSTD_VERSION <= 402 |
| 88 | # define FMT_USE_RVALUE_REFERENCES 0 |
| 89 | # else |
| 90 | # define FMT_USE_RVALUE_REFERENCES \ |
| 91 | (FMT_HAS_FEATURE(cxx_rvalue_references) || \ |
| 92 | (FMT_GCC_VERSION >= 403 && __cplusplus >= 201103) || _MSC_VER >= 1600) |
| 93 | # endif |
| 94 | #endif |
| 95 | |
| 96 | #if FMT_USE_RVALUE_REFERENCES |
| 97 | # include <utility> // for std::move |
| 98 | #endif |
| 99 | |
| 100 | // Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature). |
| 101 | #if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ |
| 102 | (FMT_GCC_VERSION >= 408 && __cplusplus >= 201103) |
| 103 | # define FMT_NOEXCEPT(expr) noexcept(expr) |
| 104 | #else |
| 105 | # define FMT_NOEXCEPT(expr) |
| 106 | #endif |
| 107 | |
| 108 | // A macro to disallow the copy constructor and operator= functions |
| 109 | // This should be used in the private: declarations for a class |
| 110 | #define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \ |
| 111 | TypeName(const TypeName&); \ |
| 112 | void operator=(const TypeName&) |
| 113 | |
| 114 | namespace fmt { |
| 115 | |
| 116 | // Fix the warning about long long on older versions of GCC |
| 117 | // that don't support the diagnostic pragma. |
| 118 | FMT_GCC_EXTENSION typedef long long LongLong; |
| 119 | FMT_GCC_EXTENSION typedef unsigned long long ULongLong; |
| 120 | |
| 121 | #if FMT_USE_RVALUE_REFERENCES |
| 122 | using std::move; |
| 123 | #endif |
| 124 | |
| 125 | template <typename Char> |
| 126 | class BasicWriter; |
| 127 | |
| 128 | typedef BasicWriter<char> Writer; |
| 129 | typedef BasicWriter<wchar_t> WWriter; |
| 130 | |
| 131 | template <typename Char> |
| 132 | class BasicFormatter; |
| 133 | |
| 134 | template <typename Char, typename T> |
| 135 | void format(BasicFormatter<Char> &f, const Char *format_str, const T &value); |
| 136 | |
| 137 | /** |
| 138 | \rst |
| 139 | A string reference. It can be constructed from a C string or |
| 140 | ``std::string``. |
| 141 | |
| 142 | You can use one of the following typedefs for common character types: |
| 143 | |
| 144 | +------------+-------------------------+ |
| 145 | | Type | Definition | |
| 146 | +============+=========================+ |
| 147 | | StringRef | BasicStringRef<char> | |
| 148 | +------------+-------------------------+ |
| 149 | | WStringRef | BasicStringRef<wchar_t> | |
| 150 | +------------+-------------------------+ |
| 151 | |
| 152 | This class is most useful as a parameter type to allow passing |
| 153 | different types of strings to a function, for example:: |
| 154 | |
| 155 | template<typename... Args> |
| 156 | std::string format(StringRef format, const Args & ... args); |
| 157 | |
| 158 | format("{}", 42); |
| 159 | format(std::string("{}"), 42); |
| 160 | \endrst |
| 161 | */ |
| 162 | template <typename Char> |
| 163 | class BasicStringRef { |
| 164 | private: |
| 165 | const Char *data_; |
| 166 | mutable std::size_t size_; |
| 167 | |
| 168 | public: |
| 169 | /** |
| 170 | Constructs a string reference object from a C string and a size. |
| 171 | If *size* is zero, which is the default, the size is computed |
| 172 | automatically. |
| 173 | */ |
| 174 | BasicStringRef(const Char *s, std::size_t size = 0) : data_(s), size_(size) {} |
| 175 | |
| 176 | /** |
| 177 | Constructs a string reference from an `std::string` object. |
| 178 | */ |
| 179 | BasicStringRef(const std::basic_string<Char> &s) |
| 180 | : data_(s.c_str()), size_(s.size()) {} |
| 181 | |
| 182 | /** |
| 183 | Converts a string reference to an `std::string` object. |
| 184 | */ |
| 185 | operator std::basic_string<Char>() const { |
| 186 | return std::basic_string<Char>(data_, size()); |
| 187 | } |
| 188 | |
| 189 | /** |
| 190 | Returns the pointer to a C string. |
| 191 | */ |
| 192 | const Char *c_str() const { return data_; } |
| 193 | |
| 194 | /** |
| 195 | Returns the string size. |
| 196 | */ |
| 197 | std::size_t size() const { |
| 198 | if (size_ == 0 && data_) size_ = std::char_traits<Char>::length(data_); |
| 199 | return size_; |
| 200 | } |
| 201 | |
| 202 | friend bool operator==(BasicStringRef lhs, BasicStringRef rhs) { |
| 203 | return lhs.data_ == rhs.data_; |
| 204 | } |
| 205 | friend bool operator!=(BasicStringRef lhs, BasicStringRef rhs) { |
| 206 | return lhs.data_ != rhs.data_; |
| 207 | } |
| 208 | }; |
| 209 | |
| 210 | typedef BasicStringRef<char> StringRef; |
| 211 | typedef BasicStringRef<wchar_t> WStringRef; |
| 212 | |
| 213 | /** |
| 214 | A formatting error such as invalid format string. |
| 215 | */ |
| 216 | class FormatError : public std::runtime_error { |
| 217 | public: |
| 218 | explicit FormatError(const std::string &message) |
| 219 | : std::runtime_error(message) {} |
| 220 | }; |
| 221 | |
| 222 | namespace internal { |
| 223 | |
| 224 | // The number of characters to store in the Array object, representing the |
| 225 | // output buffer, itself to avoid dynamic memory allocation. |
| 226 | enum { INLINE_BUFFER_SIZE = 500 }; |
| 227 | |
| 228 | #if _SECURE_SCL |
| 229 | // Use checked iterator to avoid warnings on MSVC. |
| 230 | template <typename T> |
| 231 | inline stdext::checked_array_iterator<T*> make_ptr(T *ptr, std::size_t size) { |
| 232 | return stdext::checked_array_iterator<T*>(ptr, size); |
| 233 | } |
| 234 | #else |
| 235 | template <typename T> |
| 236 | inline T *make_ptr(T *ptr, std::size_t) { return ptr; } |
| 237 | #endif |
| 238 | |
| 239 | // A simple array for POD types with the first SIZE elements stored in |
| 240 | // the object itself. It supports a subset of std::vector's operations. |
| 241 | template <typename T, std::size_t SIZE> |
| 242 | class Array { |
| 243 | private: |
| 244 | std::size_t size_; |
| 245 | std::size_t capacity_; |
| 246 | T *ptr_; |
| 247 | T data_[SIZE]; |
| 248 | |
| 249 | void grow(std::size_t size); |
| 250 | |
| 251 | // Free memory allocated by the array. |
| 252 | void free() { |
| 253 | if (ptr_ != data_) delete [] ptr_; |
| 254 | } |
| 255 | |
| 256 | // Move data from other to this array. |
| 257 | void move(Array &other) { |
| 258 | size_ = other.size_; |
| 259 | capacity_ = other.capacity_; |
| 260 | if (other.ptr_ == other.data_) { |
| 261 | ptr_ = data_; |
| 262 | std::copy(other.data_, other.data_ + size_, make_ptr(data_, capacity_)); |
| 263 | } else { |
| 264 | ptr_ = other.ptr_; |
| 265 | // Set pointer to the inline array so that delete is not called |
| 266 | // when freeing. |
| 267 | other.ptr_ = other.data_; |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | FMT_DISALLOW_COPY_AND_ASSIGN(Array); |
| 272 | |
| 273 | public: |
| 274 | explicit Array(std::size_t size = 0) |
| 275 | : size_(size), capacity_(SIZE), ptr_(data_) {} |
| 276 | ~Array() { free(); } |
| 277 | |
| 278 | #if FMT_USE_RVALUE_REFERENCES |
| 279 | Array(Array &&other) { |
| 280 | move(other); |
| 281 | } |
| 282 | |
| 283 | Array& operator=(Array &&other) { |
| 284 | assert(this != &other); |
| 285 | free(); |
| 286 | move(other); |
| 287 | return *this; |
| 288 | } |
| 289 | #endif |
| 290 | |
| 291 | // Returns the size of this array. |
| 292 | std::size_t size() const { return size_; } |
| 293 | |
| 294 | // Returns the capacity of this array. |
| 295 | std::size_t capacity() const { return capacity_; } |
| 296 | |
| 297 | // Resizes the array. If T is a POD type new elements are not initialized. |
| 298 | void resize(std::size_t new_size) { |
| 299 | if (new_size > capacity_) |
| 300 | grow(new_size); |
| 301 | size_ = new_size; |
| 302 | } |
| 303 | |
| 304 | // Reserves space to store at least capacity elements. |
| 305 | void reserve(std::size_t capacity) { |
| 306 | if (capacity > capacity_) |
| 307 | grow(capacity); |
| 308 | } |
| 309 | |
| 310 | void clear() { size_ = 0; } |
| 311 | |
| 312 | void push_back(const T &value) { |
| 313 | if (size_ == capacity_) |
| 314 | grow(size_ + 1); |
| 315 | ptr_[size_++] = value; |
| 316 | } |
| 317 | |
| 318 | // Appends data to the end of the array. |
| 319 | void append(const T *begin, const T *end); |
| 320 | |
| 321 | T &operator[](std::size_t index) { return ptr_[index]; } |
| 322 | const T &operator[](std::size_t index) const { return ptr_[index]; } |
| 323 | }; |
| 324 | |
| 325 | template <typename T, std::size_t SIZE> |
| 326 | void Array<T, SIZE>::grow(std::size_t size) { |
| 327 | capacity_ = (std::max)(size, capacity_ + capacity_ / 2); |
| 328 | T *p = new T[capacity_]; |
| 329 | std::copy(ptr_, ptr_ + size_, make_ptr(p, capacity_)); |
| 330 | if (ptr_ != data_) |
| 331 | delete [] ptr_; |
| 332 | ptr_ = p; |
| 333 | } |
| 334 | |
| 335 | template <typename T, std::size_t SIZE> |
| 336 | void Array<T, SIZE>::append(const T *begin, const T *end) { |
| 337 | std::ptrdiff_t num_elements = end - begin; |
| 338 | if (size_ + num_elements > capacity_) |
| 339 | grow(size_ + num_elements); |
| 340 | std::copy(begin, end, make_ptr(ptr_, capacity_) + size_); |
| 341 | size_ += num_elements; |
| 342 | } |
| 343 | |
| 344 | template <typename Char> |
| 345 | class BasicCharTraits { |
| 346 | public: |
| 347 | #if _SECURE_SCL |
| 348 | typedef stdext::checked_array_iterator<Char*> CharPtr; |
| 349 | #else |
| 350 | typedef Char *CharPtr; |
| 351 | #endif |
| 352 | }; |
| 353 | |
| 354 | template <typename Char> |
| 355 | class CharTraits; |
| 356 | |
| 357 | template <> |
| 358 | class CharTraits<char> : public BasicCharTraits<char> { |
| 359 | private: |
| 360 | // Conversion from wchar_t to char is not allowed. |
| 361 | static char convert(wchar_t); |
| 362 | |
| 363 | public: |
| 364 | typedef const wchar_t *UnsupportedStrType; |
| 365 | |
| 366 | static char convert(char value) { return value; } |
| 367 | |
| 368 | // Formats a floating-point number. |
| 369 | template <typename T> |
| 370 | static int format_float(char *buffer, std::size_t size, |
| 371 | const char *format, unsigned width, int precision, T value); |
| 372 | }; |
| 373 | |
| 374 | template <> |
| 375 | class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> { |
| 376 | public: |
| 377 | typedef const char *UnsupportedStrType; |
| 378 | |
| 379 | static wchar_t convert(char value) { return value; } |
| 380 | static wchar_t convert(wchar_t value) { return value; } |
| 381 | |
| 382 | template <typename T> |
| 383 | static int format_float(wchar_t *buffer, std::size_t size, |
| 384 | const wchar_t *format, unsigned width, int precision, T value); |
| 385 | }; |
| 386 | |
| 387 | // Selects uint32_t if FitsIn32Bits is true, uint64_t otherwise. |
| 388 | template <bool FitsIn32Bits> |
| 389 | struct TypeSelector { typedef uint32_t Type; }; |
| 390 | |
| 391 | template <> |
| 392 | struct TypeSelector<false> { typedef uint64_t Type; }; |
| 393 | |
| 394 | // Checks if a number is negative - used to avoid warnings. |
| 395 | template <bool IsSigned> |
| 396 | struct SignChecker { |
| 397 | template <typename T> |
| 398 | static bool is_negative(T) { return false; } |
| 399 | }; |
| 400 | |
| 401 | template <> |
| 402 | struct SignChecker<true> { |
| 403 | template <typename T> |
| 404 | static bool is_negative(T value) { return value < 0; } |
| 405 | }; |
| 406 | |
| 407 | // Returns true if value is negative, false otherwise. |
| 408 | // Same as (value < 0) but doesn't produce warnings if T is an unsigned type. |
| 409 | template <typename T> |
| 410 | inline bool is_negative(T value) { |
| 411 | return SignChecker<std::numeric_limits<T>::is_signed>::is_negative(value); |
| 412 | } |
| 413 | |
| 414 | template <typename T> |
| 415 | struct IntTraits { |
| 416 | // Smallest of uint32_t and uint64_t that is large enough to represent |
| 417 | // all values of T. |
| 418 | typedef typename |
| 419 | TypeSelector<std::numeric_limits<T>::digits <= 32>::Type MainType; |
| 420 | }; |
| 421 | |
| 422 | // MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T. |
| 423 | template <typename T> |
| 424 | struct MakeUnsigned { typedef T Type; }; |
| 425 | |
| 426 | #define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \ |
| 427 | template <> \ |
| 428 | struct MakeUnsigned<T> { typedef U Type; } |
| 429 | |
| 430 | FMT_SPECIALIZE_MAKE_UNSIGNED(char, unsigned char); |
| 431 | FMT_SPECIALIZE_MAKE_UNSIGNED(signed char, unsigned char); |
| 432 | FMT_SPECIALIZE_MAKE_UNSIGNED(short, unsigned short); |
| 433 | FMT_SPECIALIZE_MAKE_UNSIGNED(int, unsigned); |
| 434 | FMT_SPECIALIZE_MAKE_UNSIGNED(long, unsigned long); |
| 435 | FMT_SPECIALIZE_MAKE_UNSIGNED(LongLong, ULongLong); |
| 436 | |
| 437 | void report_unknown_type(char code, const char *type); |
| 438 | |
| 439 | extern const uint32_t POWERS_OF_10_32[]; |
| 440 | extern const uint64_t POWERS_OF_10_64[]; |
| 441 | |
| 442 | #if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll) |
| 443 | // Returns the number of decimal digits in n. Leading zeros are not counted |
| 444 | // except for n == 0 in which case count_digits returns 1. |
| 445 | inline unsigned count_digits(uint64_t n) { |
| 446 | // Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 |
| 447 | // and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits. |
| 448 | unsigned t = (64 - __builtin_clzll(n | 1)) * 1233 >> 12; |
| 449 | return t - (n < POWERS_OF_10_64[t]) + 1; |
| 450 | } |
| 451 | # if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz) |
| 452 | // Optional version of count_digits for better performance on 32-bit platforms. |
| 453 | inline unsigned count_digits(uint32_t n) { |
| 454 | uint32_t t = (32 - __builtin_clz(n | 1)) * 1233 >> 12; |
| 455 | return t - (n < POWERS_OF_10_32[t]) + 1; |
| 456 | } |
| 457 | # endif |
| 458 | #else |
| 459 | // Slower version of count_digits used when __builtin_clz is not available. |
| 460 | inline unsigned count_digits(uint64_t n) { |
| 461 | unsigned count = 1; |
| 462 | for (;;) { |
| 463 | // Integer division is slow so do it for a group of four digits instead |
| 464 | // of for every digit. The idea comes from the talk by Alexandrescu |
| 465 | // "Three Optimization Tips for C++". See speed-test for a comparison. |
| 466 | if (n < 10) return count; |
| 467 | if (n < 100) return count + 1; |
| 468 | if (n < 1000) return count + 2; |
| 469 | if (n < 10000) return count + 3; |
| 470 | n /= 10000u; |
| 471 | count += 4; |
| 472 | } |
| 473 | } |
| 474 | #endif |
| 475 | |
| 476 | extern const char DIGITS[]; |
| 477 | |
| 478 | // Formats a decimal unsigned integer value writing into buffer. |
| 479 | template <typename UInt, typename Char> |
| 480 | inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { |
| 481 | --num_digits; |
| 482 | while (value >= 100) { |
| 483 | // Integer division is slow so do it for a group of two digits instead |
| 484 | // of for every digit. The idea comes from the talk by Alexandrescu |
| 485 | // "Three Optimization Tips for C++". See speed-test for a comparison. |
| 486 | unsigned index = (value % 100) * 2; |
| 487 | value /= 100; |
| 488 | buffer[num_digits] = DIGITS[index + 1]; |
| 489 | buffer[num_digits - 1] = DIGITS[index]; |
| 490 | num_digits -= 2; |
| 491 | } |
| 492 | if (value < 10) { |
| 493 | *buffer = static_cast<char>('0' + value); |
| 494 | return; |
| 495 | } |
| 496 | unsigned index = static_cast<unsigned>(value * 2); |
| 497 | buffer[1] = DIGITS[index + 1]; |
| 498 | buffer[0] = DIGITS[index]; |
| 499 | } |
| 500 | |
| 501 | #ifdef _WIN32 |
| 502 | // A converter from UTF-8 to UTF-16. |
| 503 | // It is only provided for Windows since other systems use UTF-8. |
| 504 | class UTF8ToUTF16 { |
| 505 | private: |
| 506 | Array<wchar_t, INLINE_BUFFER_SIZE> buffer_; |
| 507 | |
| 508 | public: |
| 509 | explicit UTF8ToUTF16(StringRef s); |
| 510 | operator WStringRef() const { return WStringRef(&buffer_[0], size()); } |
| 511 | size_t size() const { return buffer_.size() - 1; } |
| 512 | const wchar_t *c_str() const { return &buffer_[0]; } |
| 513 | std::wstring str() const { return std::wstring(&buffer_[0], size()); } |
| 514 | }; |
| 515 | |
| 516 | // A converter from UTF-16 to UTF-8. |
| 517 | // It is only provided for Windows since other systems use UTF-8. |
| 518 | class UTF16ToUTF8 { |
| 519 | private: |
| 520 | Array<char, INLINE_BUFFER_SIZE> buffer_; |
| 521 | |
| 522 | public: |
| 523 | UTF16ToUTF8() {} |
| 524 | explicit UTF16ToUTF8(WStringRef s); |
| 525 | operator StringRef() const { return StringRef(&buffer_[0], size()); } |
| 526 | size_t size() const { return buffer_.size() - 1; } |
| 527 | const char *c_str() const { return &buffer_[0]; } |
| 528 | std::string str() const { return std::string(&buffer_[0], size()); } |
| 529 | |
| 530 | // Performs conversion returning a system error code instead of |
| 531 | // throwing exception on error. |
| 532 | int convert(WStringRef s); |
| 533 | }; |
| 534 | #endif |
| 535 | |
| 536 | // Portable thread-safe version of strerror. |
| 537 | // Sets buffer to point to a string describing the error code. |
| 538 | // This can be either a pointer to a string stored in buffer, |
| 539 | // or a pointer to some static immutable string. |
| 540 | // Returns one of the following values: |
| 541 | // 0 - success |
| 542 | // ERANGE - buffer is not large enough to store the error message |
| 543 | // other - failure |
| 544 | // Buffer should be at least of size 1. |
| 545 | int safe_strerror(int error_code, |
| 546 | char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT(true); |
| 547 | |
| 548 | void format_system_error( |
| 549 | fmt::Writer &out, int error_code, fmt::StringRef message); |
| 550 | |
| 551 | #ifdef _WIN32 |
| 552 | void format_windows_error( |
| 553 | fmt::Writer &out, int error_code, fmt::StringRef message); |
| 554 | #endif |
| 555 | |
| 556 | // Throws Exception(message) if format contains '}', otherwise throws |
| 557 | // FormatError reporting unmatched '{'. The idea is that unmatched '{' |
| 558 | // should override other errors. |
| 559 | template <typename Char> |
| 560 | struct FormatErrorReporter { |
| 561 | int num_open_braces; |
| 562 | void operator()(const Char *s, fmt::StringRef message) const; |
| 563 | }; |
| 564 | |
| 565 | // Computes max(Arg, 1) at compile time. It is used to avoid errors about |
| 566 | // allocating an array of 0 size. |
| 567 | template <unsigned Arg> |
| 568 | struct NonZero { |
| 569 | enum { VALUE = Arg }; |
| 570 | }; |
| 571 | |
| 572 | template <> |
| 573 | struct NonZero<0> { |
| 574 | enum { VALUE = 1 }; |
| 575 | }; |
| 576 | |
| 577 | // A formatting argument. It is a POD type to allow storage in internal::Array. |
| 578 | struct Arg { |
| 579 | enum Type { |
| 580 | // Integer types should go first, |
| 581 | INT, UINT, LONG_LONG, ULONG_LONG, CHAR, LAST_INTEGER_TYPE = CHAR, |
| 582 | // followed by floating-point types. |
| 583 | DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE, |
| 584 | STRING, WSTRING, POINTER, CUSTOM |
| 585 | }; |
| 586 | Type type; |
| 587 | |
| 588 | template <typename Char> |
| 589 | struct StringValue { |
| 590 | const Char *value; |
| 591 | std::size_t size; |
| 592 | }; |
| 593 | |
| 594 | typedef void (*FormatFunc)( |
| 595 | void *formatter, const void *arg, const void *format_str); |
| 596 | |
| 597 | struct CustomValue { |
| 598 | const void *value; |
| 599 | FormatFunc format; |
| 600 | }; |
| 601 | |
| 602 | union { |
| 603 | int int_value; |
| 604 | unsigned uint_value; |
| 605 | LongLong long_long_value; |
| 606 | ULongLong ulong_long_value; |
| 607 | double double_value; |
| 608 | long double long_double_value; |
| 609 | const void *pointer_value; |
| 610 | StringValue<char> string; |
| 611 | StringValue<wchar_t> wstring; |
| 612 | CustomValue custom; |
| 613 | }; |
| 614 | }; |
| 615 | |
| 616 | // Makes an Arg object from any type. |
| 617 | template <typename Char> |
| 618 | class MakeArg : public Arg { |
| 619 | private: |
| 620 | // The following two methods are private to disallow formatting of |
| 621 | // arbitrary pointers. If you want to output a pointer cast it to |
| 622 | // "void *" or "const void *". In particular, this forbids formatting |
| 623 | // of "[const] volatile char *" which is printed as bool by iostreams. |
| 624 | // Do not implement! |
| 625 | template <typename T> |
| 626 | MakeArg(const T *value); |
| 627 | template <typename T> |
| 628 | MakeArg(T *value); |
| 629 | |
| 630 | void set_string(StringRef str) { |
| 631 | type = STRING; |
| 632 | string.value = str.c_str(); |
| 633 | string.size = str.size(); |
| 634 | } |
| 635 | |
| 636 | void set_string(WStringRef str) { |
| 637 | type = WSTRING; |
| 638 | CharTraits<Char>::convert(wchar_t()); |
| 639 | wstring.value = str.c_str(); |
| 640 | wstring.size = str.size(); |
| 641 | } |
| 642 | |
| 643 | // Formats an argument of a custom type, such as a user-defined class. |
| 644 | template <typename T> |
| 645 | static void format_custom_arg( |
| 646 | void *formatter, const void *arg, const void *format_str) { |
| 647 | format(*static_cast<BasicFormatter<Char>*>(formatter), |
| 648 | static_cast<const Char*>(format_str), *static_cast<const T*>(arg)); |
| 649 | } |
| 650 | |
| 651 | public: |
| 652 | MakeArg() {} |
| 653 | MakeArg(bool value) { type = INT; int_value = value; } |
| 654 | MakeArg(short value) { type = INT; int_value = value; } |
| 655 | MakeArg(unsigned short value) { type = UINT; uint_value = value; } |
| 656 | MakeArg(int value) { type = INT; int_value = value; } |
| 657 | MakeArg(unsigned value) { type = UINT; uint_value = value; } |
| 658 | MakeArg(long value) { |
| 659 | // To minimize the number of types we need to deal with, long is |
| 660 | // translated either to int or to long long depending on its size. |
| 661 | if (sizeof(long) == sizeof(int)) { |
| 662 | type = INT; |
| 663 | int_value = static_cast<int>(value); |
| 664 | } else { |
| 665 | type = LONG_LONG; |
| 666 | long_long_value = value; |
| 667 | } |
| 668 | } |
| 669 | MakeArg(unsigned long value) { |
| 670 | if (sizeof(unsigned long) == sizeof(unsigned)) { |
| 671 | type = UINT; |
| 672 | uint_value = static_cast<unsigned>(value); |
| 673 | } else { |
| 674 | type = ULONG_LONG; |
| 675 | ulong_long_value = value; |
| 676 | } |
| 677 | } |
| 678 | MakeArg(LongLong value) { type = LONG_LONG; long_long_value = value; } |
| 679 | MakeArg(ULongLong value) { type = ULONG_LONG; ulong_long_value = value; } |
| 680 | MakeArg(float value) { type = DOUBLE; double_value = value; } |
| 681 | MakeArg(double value) { type = DOUBLE; double_value = value; } |
| 682 | MakeArg(long double value) { type = LONG_DOUBLE; long_double_value = value; } |
| 683 | MakeArg(signed char value) { type = CHAR; int_value = value; } |
| 684 | MakeArg(unsigned char value) { type = CHAR; int_value = value; } |
| 685 | MakeArg(char value) { type = CHAR; int_value = value; } |
| 686 | MakeArg(wchar_t value) { |
| 687 | type = CHAR; |
| 688 | int_value = internal::CharTraits<Char>::convert(value); |
| 689 | } |
| 690 | |
| 691 | MakeArg(char *value) { set_string(value); } |
| 692 | MakeArg(const char *value) { set_string(value); } |
| 693 | MakeArg(const std::string &value) { set_string(value); } |
| 694 | MakeArg(StringRef value) { set_string(value); } |
| 695 | |
| 696 | MakeArg(wchar_t *value) { set_string(value); } |
| 697 | MakeArg(const wchar_t *value) { set_string(value); } |
| 698 | MakeArg(const std::wstring &value) { set_string(value); } |
| 699 | MakeArg(WStringRef value) { set_string(value); } |
| 700 | |
| 701 | MakeArg(void *value) { type = POINTER; pointer_value = value; } |
| 702 | MakeArg(const void *value) { type = POINTER; pointer_value = value; } |
| 703 | |
| 704 | template <typename T> |
| 705 | MakeArg(const T &value) { |
| 706 | type = CUSTOM; |
| 707 | custom.value = &value; |
| 708 | custom.format = &format_custom_arg<T>; |
| 709 | } |
| 710 | }; |
| 711 | |
| 712 | #define FMT_DISPATCH(call) static_cast<Impl*>(this)->call |
| 713 | |
| 714 | // An argument visitor. |
| 715 | // To use ArgVisitor define a subclass that implements some or all of the |
| 716 | // visit methods with the same signatures as the methods in ArgVisitor, |
| 717 | // for example, visit_int(int). |
| 718 | // Specify the subclass name as the Impl template parameter. Then calling |
| 719 | // ArgVisitor::visit for some argument will dispatch to a visit method |
| 720 | // specific to the argument type. For example, if the argument type is |
| 721 | // double then visit_double(double) method of a subclass will be called. |
| 722 | // If the subclass doesn't contain a method with this signature, then |
| 723 | // a corresponding method of ArgVisitor will be called. |
| 724 | // |
| 725 | // Example: |
| 726 | // class MyArgVisitor : public ArgVisitor<MyArgVisitor, void> { |
| 727 | // public: |
| 728 | // void visit_int(int value) { print("{}", value); } |
| 729 | // void visit_double(double value) { print("{}", value ); } |
| 730 | // }; |
| 731 | // |
| 732 | // ArgVisitor uses the curiously recurring template pattern: |
| 733 | // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern |
| 734 | template <typename Impl, typename Result> |
| 735 | class ArgVisitor { |
| 736 | public: |
| 737 | Result visit_unhandled_arg() { return Result(); } |
| 738 | |
| 739 | Result visit_int(int value) { |
| 740 | return FMT_DISPATCH(visit_any_int(value)); |
| 741 | } |
| 742 | Result visit_long_long(LongLong value) { |
| 743 | return FMT_DISPATCH(visit_any_int(value)); |
| 744 | } |
| 745 | Result visit_uint(unsigned value) { |
| 746 | return FMT_DISPATCH(visit_any_int(value)); |
| 747 | } |
| 748 | Result visit_ulong_long(ULongLong value) { |
| 749 | return FMT_DISPATCH(visit_any_int(value)); |
| 750 | } |
| 751 | Result visit_char(int value) { |
| 752 | return FMT_DISPATCH(visit_any_int(value)); |
| 753 | } |
| 754 | template <typename T> |
| 755 | Result visit_any_int(T) { |
| 756 | return FMT_DISPATCH(visit_unhandled_arg()); |
| 757 | } |
| 758 | |
| 759 | Result visit_double(double value) { |
| 760 | return FMT_DISPATCH(visit_any_double(value)); |
| 761 | } |
| 762 | Result visit_long_double(long double value) { |
| 763 | return FMT_DISPATCH(visit_any_double(value)); |
| 764 | } |
| 765 | template <typename T> |
| 766 | Result visit_any_double(T) { |
| 767 | return FMT_DISPATCH(visit_unhandled_arg()); |
| 768 | } |
| 769 | |
| 770 | Result visit_string(Arg::StringValue<char>) { |
| 771 | return FMT_DISPATCH(visit_unhandled_arg()); |
| 772 | } |
| 773 | Result visit_wstring(Arg::StringValue<wchar_t>) { |
| 774 | return FMT_DISPATCH(visit_unhandled_arg()); |
| 775 | } |
| 776 | Result visit_pointer(const void *) { |
| 777 | return FMT_DISPATCH(visit_unhandled_arg()); |
| 778 | } |
| 779 | Result visit_custom(Arg::CustomValue) { |
| 780 | return FMT_DISPATCH(visit_unhandled_arg()); |
| 781 | } |
| 782 | |
| 783 | Result visit(const Arg &arg) { |
| 784 | switch (arg.type) { |
| 785 | default: |
| 786 | assert(false); |
| 787 | // Fall through. |
| 788 | case Arg::INT: |
| 789 | return FMT_DISPATCH(visit_int(arg.int_value)); |
| 790 | case Arg::UINT: |
| 791 | return FMT_DISPATCH(visit_uint(arg.uint_value)); |
| 792 | case Arg::LONG_LONG: |
| 793 | return FMT_DISPATCH(visit_long_long(arg.long_long_value)); |
| 794 | case Arg::ULONG_LONG: |
| 795 | return FMT_DISPATCH(visit_ulong_long(arg.ulong_long_value)); |
| 796 | case Arg::DOUBLE: |
| 797 | return FMT_DISPATCH(visit_double(arg.double_value)); |
| 798 | case Arg::LONG_DOUBLE: |
| 799 | return FMT_DISPATCH(visit_long_double(arg.long_double_value)); |
| 800 | case Arg::CHAR: |
| 801 | return FMT_DISPATCH(visit_char(arg.int_value)); |
| 802 | case Arg::STRING: |
| 803 | return FMT_DISPATCH(visit_string(arg.string)); |
| 804 | case Arg::WSTRING: |
| 805 | return FMT_DISPATCH(visit_wstring(arg.wstring)); |
| 806 | case Arg::POINTER: |
| 807 | return FMT_DISPATCH(visit_pointer(arg.pointer_value)); |
| 808 | case Arg::CUSTOM: |
| 809 | return FMT_DISPATCH(visit_custom(arg.custom)); |
| 810 | } |
| 811 | } |
| 812 | }; |
| 813 | |
| 814 | class RuntimeError : public std::runtime_error { |
| 815 | protected: |
| 816 | RuntimeError() : std::runtime_error("") {} |
| 817 | }; |
| 818 | |
| 819 | template <typename Char> |
| 820 | class ArgFormatter; |
| 821 | } // namespace internal |
| 822 | |
| 823 | /** |
| 824 | An argument list. |
| 825 | */ |
| 826 | class ArgList { |
| 827 | private: |
| 828 | const internal::Arg *args_; |
| 829 | std::size_t size_; |
| 830 | |
| 831 | public: |
| 832 | ArgList() : size_(0) {} |
| 833 | ArgList(const internal::Arg *args, std::size_t size) |
| 834 | : args_(args), size_(size) {} |
| 835 | |
| 836 | /** |
| 837 | Returns the list size (the number of arguments). |
| 838 | */ |
| 839 | std::size_t size() const { return size_; } |
| 840 | |
| 841 | /** |
| 842 | Returns the argument at specified index. |
| 843 | */ |
| 844 | const internal::Arg &operator[](std::size_t index) const { |
| 845 | return args_[index]; |
| 846 | } |
| 847 | }; |
| 848 | |
| 849 | struct FormatSpec; |
| 850 | |
| 851 | namespace internal { |
| 852 | |
| 853 | class FormatterBase { |
| 854 | protected: |
| 855 | ArgList args_; |
| 856 | int next_arg_index_; |
| 857 | const char *error_; |
| 858 | |
| 859 | FormatterBase() : error_(0) {} |
| 860 | |
| 861 | const Arg &next_arg(); |
| 862 | |
| 863 | const Arg &handle_arg_index(unsigned arg_index); |
| 864 | |
| 865 | template <typename Char> |
| 866 | void write(BasicWriter<Char> &w, const Char *start, const Char *end) { |
| 867 | if (start != end) |
| 868 | w << BasicStringRef<Char>(start, end - start); |
| 869 | } |
| 870 | |
| 871 | // TODO |
| 872 | }; |
| 873 | |
| 874 | // A printf formatter. |
| 875 | template <typename Char> |
| 876 | class PrintfFormatter : private FormatterBase { |
| 877 | private: |
| 878 | void parse_flags(FormatSpec &spec, const Char *&s); |
| 879 | |
| 880 | // Parses argument index, flags and width and returns the parsed |
| 881 | // argument index. |
| 882 | unsigned parse_header(const Char *&s, FormatSpec &spec); |
| 883 | |
| 884 | public: |
| 885 | void format(BasicWriter<Char> &writer, |
| 886 | BasicStringRef<Char> format, const ArgList &args); |
| 887 | }; |
| 888 | } // namespace internal |
| 889 | |
| 890 | // A formatter. |
| 891 | template <typename Char> |
| 892 | class BasicFormatter : private internal::FormatterBase { |
| 893 | private: |
| 894 | BasicWriter<Char> &writer_; |
| 895 | const Char *start_; |
| 896 | internal::FormatErrorReporter<Char> report_error_; |
| 897 | |
| 898 | // Parses argument index and returns an argument with this index. |
| 899 | const internal::Arg &parse_arg_index(const Char *&s); |
| 900 | |
| 901 | void check_sign(const Char *&s, const internal::Arg &arg); |
| 902 | |
| 903 | public: |
| 904 | explicit BasicFormatter(BasicWriter<Char> &w) : writer_(w) {} |
| 905 | |
| 906 | BasicWriter<Char> &writer() { return writer_; } |
| 907 | |
| 908 | void format(BasicStringRef<Char> format_str, const ArgList &args); |
| 909 | |
| 910 | const Char *format(const Char *format_str, const internal::Arg &arg); |
| 911 | }; |
| 912 | |
| 913 | enum Alignment { |
| 914 | ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC |
| 915 | }; |
| 916 | |
| 917 | // Flags. |
| 918 | enum { |
| 919 | SIGN_FLAG = 1, PLUS_FLAG = 2, MINUS_FLAG = 4, HASH_FLAG = 8, |
| 920 | CHAR_FLAG = 0x10 // Argument has char type - used in error reporting. |
| 921 | }; |
| 922 | |
| 923 | // An empty format specifier. |
| 924 | struct EmptySpec {}; |
| 925 | |
| 926 | // A type specifier. |
| 927 | template <char TYPE> |
| 928 | struct TypeSpec : EmptySpec { |
| 929 | Alignment align() const { return ALIGN_DEFAULT; } |
| 930 | unsigned width() const { return 0; } |
| 931 | int precision() const { return -1; } |
| 932 | bool flag(unsigned) const { return false; } |
| 933 | char type() const { return TYPE; } |
| 934 | char fill() const { return ' '; } |
| 935 | }; |
| 936 | |
| 937 | // A width specifier. |
| 938 | struct WidthSpec { |
| 939 | unsigned width_; |
| 940 | // Fill is always wchar_t and cast to char if necessary to avoid having |
| 941 | // two specialization of WidthSpec and its subclasses. |
| 942 | wchar_t fill_; |
| 943 | |
| 944 | WidthSpec(unsigned width, wchar_t fill) : width_(width), fill_(fill) {} |
| 945 | |
| 946 | unsigned width() const { return width_; } |
| 947 | wchar_t fill() const { return fill_; } |
| 948 | }; |
| 949 | |
| 950 | // An alignment specifier. |
| 951 | struct AlignSpec : WidthSpec { |
| 952 | Alignment align_; |
| 953 | |
| 954 | AlignSpec(unsigned width, wchar_t fill, Alignment align = ALIGN_DEFAULT) |
| 955 | : WidthSpec(width, fill), align_(align) {} |
| 956 | |
| 957 | Alignment align() const { return align_; } |
| 958 | |
| 959 | int precision() const { return -1; } |
| 960 | }; |
| 961 | |
| 962 | // An alignment and type specifier. |
| 963 | template <char TYPE> |
| 964 | struct AlignTypeSpec : AlignSpec { |
| 965 | AlignTypeSpec(unsigned width, wchar_t fill) : AlignSpec(width, fill) {} |
| 966 | |
| 967 | bool flag(unsigned) const { return false; } |
| 968 | char type() const { return TYPE; } |
| 969 | }; |
| 970 | |
| 971 | // A full format specifier. |
| 972 | struct FormatSpec : AlignSpec { |
| 973 | unsigned flags_; |
| 974 | int precision_; |
| 975 | char type_; |
| 976 | |
| 977 | FormatSpec( |
| 978 | unsigned width = 0, char type = 0, wchar_t fill = ' ') |
| 979 | : AlignSpec(width, fill), flags_(0), precision_(-1), type_(type) {} |
| 980 | |
| 981 | bool flag(unsigned f) const { return (flags_ & f) != 0; } |
| 982 | int precision() const { return precision_; } |
| 983 | char type() const { return type_; } |
| 984 | }; |
| 985 | |
| 986 | // An integer format specifier. |
| 987 | template <typename T, typename SpecT = TypeSpec<0>, typename Char = char> |
| 988 | class IntFormatSpec : public SpecT { |
| 989 | private: |
| 990 | T value_; |
| 991 | |
| 992 | public: |
| 993 | IntFormatSpec(T value, const SpecT &spec = SpecT()) |
| 994 | : SpecT(spec), value_(value) {} |
| 995 | |
| 996 | T value() const { return value_; } |
| 997 | }; |
| 998 | |
| 999 | // A string format specifier. |
| 1000 | template <typename T> |
| 1001 | class StrFormatSpec : public AlignSpec { |
| 1002 | private: |
| 1003 | const T *str_; |
| 1004 | |
| 1005 | public: |
| 1006 | StrFormatSpec(const T *str, unsigned width, wchar_t fill) |
| 1007 | : AlignSpec(width, fill), str_(str) {} |
| 1008 | |
| 1009 | const T *str() const { return str_; } |
| 1010 | }; |
| 1011 | |
| 1012 | /** |
| 1013 | Returns an integer format specifier to format the value in base 2. |
| 1014 | */ |
| 1015 | IntFormatSpec<int, TypeSpec<'b'> > bin(int value); |
| 1016 | |
| 1017 | /** |
| 1018 | Returns an integer format specifier to format the value in base 8. |
| 1019 | */ |
| 1020 | IntFormatSpec<int, TypeSpec<'o'> > oct(int value); |
| 1021 | |
| 1022 | /** |
| 1023 | Returns an integer format specifier to format the value in base 16 using |
| 1024 | lower-case letters for the digits above 9. |
| 1025 | */ |
| 1026 | IntFormatSpec<int, TypeSpec<'x'> > hex(int value); |
| 1027 | |
| 1028 | /** |
| 1029 | Returns an integer formatter format specifier to format in base 16 using |
| 1030 | upper-case letters for the digits above 9. |
| 1031 | */ |
| 1032 | IntFormatSpec<int, TypeSpec<'X'> > hexu(int value); |
| 1033 | |
| 1034 | /** |
| 1035 | \rst |
| 1036 | Returns an integer format specifier to pad the formatted argument with the |
| 1037 | fill character to the specified width using the default (right) numeric |
| 1038 | alignment. |
| 1039 | |
| 1040 | **Example**:: |
| 1041 | |
| 1042 | Writer out; |
| 1043 | out << pad(hex(0xcafe), 8, '0'); |
| 1044 | // out.str() == "0000cafe" |
| 1045 | |
| 1046 | \endrst |
| 1047 | */ |
| 1048 | template <char TYPE_CODE, typename Char> |
| 1049 | IntFormatSpec<int, AlignTypeSpec<TYPE_CODE>, Char> pad( |
| 1050 | int value, unsigned width, Char fill = ' '); |
| 1051 | |
| 1052 | #define FMT_DEFINE_INT_FORMATTERS(TYPE) \ |
| 1053 | inline IntFormatSpec<TYPE, TypeSpec<'b'> > bin(TYPE value) { \ |
| 1054 | return IntFormatSpec<TYPE, TypeSpec<'b'> >(value, TypeSpec<'b'>()); \ |
| 1055 | } \ |
| 1056 | \ |
| 1057 | inline IntFormatSpec<TYPE, TypeSpec<'o'> > oct(TYPE value) { \ |
| 1058 | return IntFormatSpec<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \ |
| 1059 | } \ |
| 1060 | \ |
| 1061 | inline IntFormatSpec<TYPE, TypeSpec<'x'> > hex(TYPE value) { \ |
| 1062 | return IntFormatSpec<TYPE, TypeSpec<'x'> >(value, TypeSpec<'x'>()); \ |
| 1063 | } \ |
| 1064 | \ |
| 1065 | inline IntFormatSpec<TYPE, TypeSpec<'X'> > hexu(TYPE value) { \ |
| 1066 | return IntFormatSpec<TYPE, TypeSpec<'X'> >(value, TypeSpec<'X'>()); \ |
| 1067 | } \ |
| 1068 | \ |
| 1069 | template <char TYPE_CODE> \ |
| 1070 | inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> > pad( \ |
| 1071 | IntFormatSpec<TYPE, TypeSpec<TYPE_CODE> > f, unsigned width) { \ |
| 1072 | return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> >( \ |
| 1073 | f.value(), AlignTypeSpec<TYPE_CODE>(width, ' ')); \ |
| 1074 | } \ |
| 1075 | \ |
| 1076 | /* For compatibility with older compilers we provide two overloads for pad, */ \ |
| 1077 | /* one that takes a fill character and one that doesn't. In the future this */ \ |
| 1078 | /* can be replaced with one overload making the template argument Char */ \ |
| 1079 | /* default to char (C++11). */ \ |
| 1080 | template <char TYPE_CODE, typename Char> \ |
| 1081 | inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char> pad( \ |
| 1082 | IntFormatSpec<TYPE, TypeSpec<TYPE_CODE>, Char> f, \ |
| 1083 | unsigned width, Char fill) { \ |
| 1084 | return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char>( \ |
| 1085 | f.value(), AlignTypeSpec<TYPE_CODE>(width, fill)); \ |
| 1086 | } \ |
| 1087 | \ |
| 1088 | inline IntFormatSpec<TYPE, AlignTypeSpec<0> > pad( \ |
| 1089 | TYPE value, unsigned width) { \ |
| 1090 | return IntFormatSpec<TYPE, AlignTypeSpec<0> >( \ |
| 1091 | value, AlignTypeSpec<0>(width, ' ')); \ |
| 1092 | } \ |
| 1093 | \ |
| 1094 | template <typename Char> \ |
| 1095 | inline IntFormatSpec<TYPE, AlignTypeSpec<0>, Char> pad( \ |
| 1096 | TYPE value, unsigned width, Char fill) { \ |
| 1097 | return IntFormatSpec<TYPE, AlignTypeSpec<0>, Char>( \ |
| 1098 | value, AlignTypeSpec<0>(width, fill)); \ |
| 1099 | } |
| 1100 | |
| 1101 | FMT_DEFINE_INT_FORMATTERS(int) |
| 1102 | FMT_DEFINE_INT_FORMATTERS(long) |
| 1103 | FMT_DEFINE_INT_FORMATTERS(unsigned) |
| 1104 | FMT_DEFINE_INT_FORMATTERS(unsigned long) |
| 1105 | FMT_DEFINE_INT_FORMATTERS(LongLong) |
| 1106 | FMT_DEFINE_INT_FORMATTERS(ULongLong) |
| 1107 | |
| 1108 | /** |
| 1109 | \rst |
| 1110 | Returns a string formatter that pads the formatted argument with the fill |
| 1111 | character to the specified width using the default (left) string alignment. |
| 1112 | |
| 1113 | **Example**:: |
| 1114 | |
| 1115 | std::string s = str(Writer() << pad("abc", 8)); |
| 1116 | // s == "abc " |
| 1117 | |
| 1118 | \endrst |
| 1119 | */ |
| 1120 | template <typename Char> |
| 1121 | inline StrFormatSpec<Char> pad( |
| 1122 | const Char *str, unsigned width, Char fill = ' ') { |
| 1123 | return StrFormatSpec<Char>(str, width, fill); |
| 1124 | } |
| 1125 | |
| 1126 | inline StrFormatSpec<wchar_t> pad( |
| 1127 | const wchar_t *str, unsigned width, char fill = ' ') { |
| 1128 | return StrFormatSpec<wchar_t>(str, width, fill); |
| 1129 | } |
| 1130 | |
| 1131 | // Generates a comma-separated list with results of applying f to numbers 0..n-1. |
| 1132 | # define FMT_GEN(n, f) FMT_GEN##n(f) |
| 1133 | # define FMT_GEN1(f) f(0) |
| 1134 | # define FMT_GEN2(f) FMT_GEN1(f), f(1) |
| 1135 | # define FMT_GEN3(f) FMT_GEN2(f), f(2) |
| 1136 | # define FMT_GEN4(f) FMT_GEN3(f), f(3) |
| 1137 | # define FMT_GEN5(f) FMT_GEN4(f), f(4) |
| 1138 | # define FMT_GEN6(f) FMT_GEN5(f), f(5) |
| 1139 | # define FMT_GEN7(f) FMT_GEN6(f), f(6) |
| 1140 | # define FMT_GEN8(f) FMT_GEN7(f), f(7) |
| 1141 | # define FMT_GEN9(f) FMT_GEN8(f), f(8) |
| 1142 | # define FMT_GEN10(f) FMT_GEN9(f), f(9) |
| 1143 | |
| 1144 | # define FMT_MAKE_TEMPLATE_ARG(n) typename T##n |
| 1145 | # define FMT_MAKE_ARG(n) const T##n &v##n |
| 1146 | # define FMT_MAKE_REF_char(n) fmt::internal::MakeArg<char>(v##n) |
| 1147 | # define FMT_MAKE_REF_wchar_t(n) fmt::internal::MakeArg<wchar_t>(v##n) |
| 1148 | |
| 1149 | #if FMT_USE_VARIADIC_TEMPLATES |
| 1150 | // Defines a variadic function returning void. |
| 1151 | # define FMT_VARIADIC_VOID(func, arg_type) \ |
| 1152 | template<typename... Args> \ |
| 1153 | void func(arg_type arg1, const Args & ... args) { \ |
| 1154 | using fmt::internal::Arg; \ |
| 1155 | const Arg arg_array[fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \ |
| 1156 | fmt::internal::MakeArg<Char>(args)... \ |
| 1157 | }; \ |
| 1158 | func(arg1, ArgList(arg_array, sizeof...(Args))); \ |
| 1159 | } |
| 1160 | |
| 1161 | // Defines a variadic constructor. |
| 1162 | # define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \ |
| 1163 | template<typename... Args> \ |
| 1164 | ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \ |
| 1165 | using fmt::internal::Arg; \ |
| 1166 | const Arg arg_array[fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \ |
| 1167 | fmt::internal::MakeArg<Char>(args)... \ |
| 1168 | }; \ |
| 1169 | func(arg0, arg1, ArgList(arg_array, sizeof...(Args))); \ |
| 1170 | } |
| 1171 | |
| 1172 | #else |
| 1173 | |
| 1174 | # define FMT_MAKE_REF(n) fmt::internal::MakeArg<Char>(v##n) |
| 1175 | // Defines a wrapper for a function taking one argument of type arg_type |
| 1176 | // and n additional arguments of arbitrary types. |
| 1177 | # define FMT_WRAP1(func, arg_type, n) \ |
| 1178 | template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \ |
| 1179 | inline void func(arg_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \ |
| 1180 | const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \ |
| 1181 | func(arg1, fmt::ArgList(args, sizeof(args) / sizeof(*args))); \ |
| 1182 | } |
| 1183 | |
| 1184 | // Emulates a variadic function returning void on a pre-C++11 compiler. |
| 1185 | # define FMT_VARIADIC_VOID(func, arg_type) \ |
| 1186 | FMT_WRAP1(func, arg_type, 1) FMT_WRAP1(func, arg_type, 2) \ |
| 1187 | FMT_WRAP1(func, arg_type, 3) FMT_WRAP1(func, arg_type, 4) \ |
| 1188 | FMT_WRAP1(func, arg_type, 5) FMT_WRAP1(func, arg_type, 6) \ |
| 1189 | FMT_WRAP1(func, arg_type, 7) FMT_WRAP1(func, arg_type, 8) \ |
| 1190 | FMT_WRAP1(func, arg_type, 9) FMT_WRAP1(func, arg_type, 10) |
| 1191 | |
| 1192 | # define FMT_CTOR(ctor, func, arg0_type, arg1_type, n) \ |
| 1193 | template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \ |
| 1194 | ctor(arg0_type arg0, arg1_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \ |
| 1195 | const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \ |
| 1196 | func(arg0, arg1, fmt::ArgList(args, sizeof(args) / sizeof(*args))); \ |
| 1197 | } |
| 1198 | |
| 1199 | // Emulates a variadic constructor on a pre-C++11 compiler. |
| 1200 | # define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \ |
| 1201 | FMT_CTOR(ctor, func, arg0_type, arg1_type, 1) \ |
| 1202 | FMT_CTOR(ctor, func, arg0_type, arg1_type, 2) \ |
| 1203 | FMT_CTOR(ctor, func, arg0_type, arg1_type, 3) \ |
| 1204 | FMT_CTOR(ctor, func, arg0_type, arg1_type, 4) \ |
| 1205 | FMT_CTOR(ctor, func, arg0_type, arg1_type, 5) \ |
| 1206 | FMT_CTOR(ctor, func, arg0_type, arg1_type, 6) \ |
| 1207 | FMT_CTOR(ctor, func, arg0_type, arg1_type, 7) \ |
| 1208 | FMT_CTOR(ctor, func, arg0_type, arg1_type, 8) \ |
| 1209 | FMT_CTOR(ctor, func, arg0_type, arg1_type, 9) \ |
| 1210 | FMT_CTOR(ctor, func, arg0_type, arg1_type, 10) |
| 1211 | #endif |
| 1212 | |
| 1213 | // Generates a comma-separated list with results of applying f to pairs |
| 1214 | // (argument, index). |
| 1215 | #define FMT_FOR_EACH1(f, x0) f(x0, 0) |
| 1216 | #define FMT_FOR_EACH2(f, x0, x1) \ |
| 1217 | FMT_FOR_EACH1(f, x0), f(x1, 1) |
| 1218 | #define FMT_FOR_EACH3(f, x0, x1, x2) \ |
| 1219 | FMT_FOR_EACH2(f, x0 ,x1), f(x2, 2) |
| 1220 | #define FMT_FOR_EACH4(f, x0, x1, x2, x3) \ |
| 1221 | FMT_FOR_EACH3(f, x0, x1, x2), f(x3, 3) |
| 1222 | #define FMT_FOR_EACH5(f, x0, x1, x2, x3, x4) \ |
| 1223 | FMT_FOR_EACH4(f, x0, x1, x2, x3), f(x4, 4) |
| 1224 | #define FMT_FOR_EACH6(f, x0, x1, x2, x3, x4, x5) \ |
| 1225 | FMT_FOR_EACH5(f, x0, x1, x2, x3, x4), f(x5, 5) |
| 1226 | #define FMT_FOR_EACH7(f, x0, x1, x2, x3, x4, x5, x6) \ |
| 1227 | FMT_FOR_EACH6(f, x0, x1, x2, x3, x4, x5), f(x6, 6) |
| 1228 | #define FMT_FOR_EACH8(f, x0, x1, x2, x3, x4, x5, x6, x7) \ |
| 1229 | FMT_FOR_EACH7(f, x0, x1, x2, x3, x4, x5, x6), f(x7, 7) |
| 1230 | #define FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8) \ |
| 1231 | FMT_FOR_EACH8(f, x0, x1, x2, x3, x4, x5, x6, x7), f(x8, 8) |
| 1232 | #define FMT_FOR_EACH10(f, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) \ |
| 1233 | FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8), f(x9, 9) |
| 1234 | |
| 1235 | /** |
| 1236 | An error returned by an operating system or a language runtime, |
| 1237 | for example a file opening error. |
| 1238 | */ |
| 1239 | class SystemError : public internal::RuntimeError { |
| 1240 | private: |
| 1241 | void init(int error_code, StringRef format_str, const ArgList &args); |
| 1242 | |
| 1243 | protected: |
| 1244 | int error_code_; |
| 1245 | |
| 1246 | typedef char Char; // For FMT_VARIADIC_CTOR. |
| 1247 | |
| 1248 | SystemError() {} |
| 1249 | |
| 1250 | public: |
| 1251 | /** |
| 1252 | \rst |
| 1253 | Constructs a :cpp:class:`fmt::SystemError` object with the description |
| 1254 | of the form "*<message>*: *<system-message>*", where *<message>* is the |
| 1255 | formatted message and *<system-message>* is the system message corresponding |
| 1256 | to the error code. |
| 1257 | *error_code* is a system error code as given by ``errno``. |
| 1258 | \endrst |
| 1259 | */ |
| 1260 | SystemError(int error_code, StringRef message) { |
| 1261 | init(error_code, message, ArgList()); |
| 1262 | } |
| 1263 | FMT_VARIADIC_CTOR(SystemError, init, int, StringRef) |
| 1264 | |
| 1265 | int error_code() const { return error_code_; } |
| 1266 | }; |
| 1267 | |
| 1268 | /** |
| 1269 | \rst |
| 1270 | This template provides operations for formatting and writing data into |
| 1271 | a character stream. The output is stored in a memory buffer that grows |
| 1272 | dynamically. |
| 1273 | |
| 1274 | You can use one of the following typedefs for common character types: |
| 1275 | |
| 1276 | +---------+----------------------+ |
| 1277 | | Type | Definition | |
| 1278 | +=========+======================+ |
| 1279 | | Writer | BasicWriter<char> | |
| 1280 | +---------+----------------------+ |
| 1281 | | WWriter | BasicWriter<wchar_t> | |
| 1282 | +---------+----------------------+ |
| 1283 | |
| 1284 | **Example**:: |
| 1285 | |
| 1286 | Writer out; |
| 1287 | out << "The answer is " << 42 << "\n"; |
| 1288 | out.write("({:+f}, {:+f})", -3.14, 3.14); |
| 1289 | |
| 1290 | This will write the following output to the ``out`` object: |
| 1291 | |
| 1292 | .. code-block:: none |
| 1293 | |
| 1294 | The answer is 42 |
| 1295 | (-3.140000, +3.140000) |
| 1296 | |
| 1297 | The output can be converted to an ``std::string`` with ``out.str()`` or |
| 1298 | accessed as a C string with ``out.c_str()``. |
| 1299 | \endrst |
| 1300 | */ |
| 1301 | template <typename Char> |
| 1302 | class BasicWriter { |
| 1303 | private: |
| 1304 | // Output buffer. |
| 1305 | mutable internal::Array<Char, internal::INLINE_BUFFER_SIZE> buffer_; |
| 1306 | |
| 1307 | typedef typename internal::CharTraits<Char>::CharPtr CharPtr; |
| 1308 | |
| 1309 | #if _SECURE_SCL |
| 1310 | // Returns pointer value. |
| 1311 | static Char *get(CharPtr p) { return p.base(); } |
| 1312 | #else |
| 1313 | static Char *get(Char *p) { return p; } |
| 1314 | #endif |
| 1315 | |
| 1316 | static CharPtr fill_padding(CharPtr buffer, |
| 1317 | unsigned total_size, std::size_t content_size, wchar_t fill); |
| 1318 | |
| 1319 | // Grows the buffer by n characters and returns a pointer to the newly |
| 1320 | // allocated area. |
| 1321 | CharPtr grow_buffer(std::size_t n) { |
| 1322 | std::size_t size = buffer_.size(); |
| 1323 | buffer_.resize(size + n); |
| 1324 | return internal::make_ptr(&buffer_[size], n); |
| 1325 | } |
| 1326 | |
| 1327 | // Prepare a buffer for integer formatting. |
| 1328 | CharPtr prepare_int_buffer(unsigned num_digits, |
| 1329 | const EmptySpec &, const char *prefix, unsigned prefix_size) { |
| 1330 | unsigned size = prefix_size + num_digits; |
| 1331 | CharPtr p = grow_buffer(size); |
| 1332 | std::copy(prefix, prefix + prefix_size, p); |
| 1333 | return p + size - 1; |
| 1334 | } |
| 1335 | |
| 1336 | template <typename Spec> |
| 1337 | CharPtr prepare_int_buffer(unsigned num_digits, |
| 1338 | const Spec &spec, const char *prefix, unsigned prefix_size); |
| 1339 | |
| 1340 | // Formats an integer. |
| 1341 | template <typename T, typename Spec> |
| 1342 | void write_int(T value, const Spec &spec); |
| 1343 | |
| 1344 | // Formats a floating-point number (double or long double). |
| 1345 | template <typename T> |
| 1346 | void write_double(T value, const FormatSpec &spec); |
| 1347 | |
| 1348 | // Writes a formatted string. |
| 1349 | template <typename StrChar> |
| 1350 | CharPtr write_str( |
| 1351 | const StrChar *s, std::size_t size, const AlignSpec &spec); |
| 1352 | |
| 1353 | template <typename StrChar> |
| 1354 | void write_str( |
| 1355 | const internal::Arg::StringValue<StrChar> &str, const FormatSpec &spec); |
| 1356 | |
| 1357 | // This method is private to disallow writing a wide string to a |
| 1358 | // char stream and vice versa. If you want to print a wide string |
| 1359 | // as a pointer as std::ostream does, cast it to const void*. |
| 1360 | // Do not implement! |
| 1361 | void operator<<(typename internal::CharTraits<Char>::UnsupportedStrType); |
| 1362 | |
| 1363 | friend class internal::ArgFormatter<Char>; |
| 1364 | friend class internal::PrintfFormatter<Char>; |
| 1365 | |
| 1366 | public: |
| 1367 | /** |
| 1368 | Constructs a ``BasicWriter`` object. |
| 1369 | */ |
| 1370 | BasicWriter() {} |
| 1371 | |
| 1372 | #if FMT_USE_RVALUE_REFERENCES |
| 1373 | /** |
| 1374 | Constructs a ``BasicWriter`` object moving the content of the other |
| 1375 | object to it. |
| 1376 | */ |
| 1377 | BasicWriter(BasicWriter &&other) : buffer_(std::move(other.buffer_)) {} |
| 1378 | |
| 1379 | /** |
| 1380 | Moves the content of the other ``BasicWriter`` object to this one. |
| 1381 | */ |
| 1382 | BasicWriter& operator=(BasicWriter &&other) { |
| 1383 | assert(this != &other); |
| 1384 | buffer_ = std::move(other.buffer_); |
| 1385 | return *this; |
| 1386 | } |
| 1387 | #endif |
| 1388 | |
| 1389 | /** |
| 1390 | Returns the total number of characters written. |
| 1391 | */ |
| 1392 | std::size_t size() const { return buffer_.size(); } |
| 1393 | |
| 1394 | /** |
| 1395 | Returns a pointer to the output buffer content. No terminating null |
| 1396 | character is appended. |
| 1397 | */ |
| 1398 | const Char *data() const { return &buffer_[0]; } |
| 1399 | |
| 1400 | /** |
| 1401 | Returns a pointer to the output buffer content with terminating null |
| 1402 | character appended. |
| 1403 | */ |
| 1404 | const Char *c_str() const { |
| 1405 | std::size_t size = buffer_.size(); |
| 1406 | buffer_.reserve(size + 1); |
| 1407 | buffer_[size] = '\0'; |
| 1408 | return &buffer_[0]; |
| 1409 | } |
| 1410 | |
| 1411 | /** |
| 1412 | Returns the content of the output buffer as an `std::string`. |
| 1413 | */ |
| 1414 | std::basic_string<Char> str() const { |
| 1415 | return std::basic_string<Char>(&buffer_[0], buffer_.size()); |
| 1416 | } |
| 1417 | |
| 1418 | /** |
| 1419 | \rst |
| 1420 | Writes formatted data. |
| 1421 | |
| 1422 | *args* is an argument list representing arbitrary arguments. |
| 1423 | |
| 1424 | **Example**:: |
| 1425 | |
| 1426 | Writer out; |
| 1427 | out.write("Current point:\n"); |
| 1428 | out.write("({:+f}, {:+f})", -3.14, 3.14); |
| 1429 | |
| 1430 | This will write the following output to the ``out`` object: |
| 1431 | |
| 1432 | .. code-block:: none |
| 1433 | |
| 1434 | Current point: |
| 1435 | (-3.140000, +3.140000) |
| 1436 | |
| 1437 | The output can be accessed using :meth:`data`, :meth:`c_str` or :meth:`str` |
| 1438 | methods. |
| 1439 | |
| 1440 | See also `Format String Syntax`_. |
| 1441 | \endrst |
| 1442 | */ |
| 1443 | void write(BasicStringRef<Char> format, const ArgList &args) { |
| 1444 | BasicFormatter<Char>(*this).format(format, args); |
| 1445 | } |
| 1446 | FMT_VARIADIC_VOID(write, fmt::BasicStringRef<Char>) |
| 1447 | |
| 1448 | BasicWriter &operator<<(int value) { |
| 1449 | return *this << IntFormatSpec<int>(value); |
| 1450 | } |
| 1451 | BasicWriter &operator<<(unsigned value) { |
| 1452 | return *this << IntFormatSpec<unsigned>(value); |
| 1453 | } |
| 1454 | BasicWriter &operator<<(long value) { |
| 1455 | return *this << IntFormatSpec<long>(value); |
| 1456 | } |
| 1457 | BasicWriter &operator<<(unsigned long value) { |
| 1458 | return *this << IntFormatSpec<unsigned long>(value); |
| 1459 | } |
| 1460 | BasicWriter &operator<<(LongLong value) { |
| 1461 | return *this << IntFormatSpec<LongLong>(value); |
| 1462 | } |
| 1463 | |
| 1464 | /** |
| 1465 | Formats *value* and writes it to the stream. |
| 1466 | */ |
| 1467 | BasicWriter &operator<<(ULongLong value) { |
| 1468 | return *this << IntFormatSpec<ULongLong>(value); |
| 1469 | } |
| 1470 | |
| 1471 | BasicWriter &operator<<(double value) { |
| 1472 | write_double(value, FormatSpec()); |
| 1473 | return *this; |
| 1474 | } |
| 1475 | |
| 1476 | /** |
| 1477 | Formats *value* using the general format for floating-point numbers |
| 1478 | (``'g'``) and writes it to the stream. |
| 1479 | */ |
| 1480 | BasicWriter &operator<<(long double value) { |
| 1481 | write_double(value, FormatSpec()); |
| 1482 | return *this; |
| 1483 | } |
| 1484 | |
| 1485 | /** |
| 1486 | Writes a character to the stream. |
| 1487 | */ |
| 1488 | BasicWriter &operator<<(char value) { |
| 1489 | buffer_.push_back(value); |
| 1490 | return *this; |
| 1491 | } |
| 1492 | |
| 1493 | BasicWriter &operator<<(wchar_t value) { |
| 1494 | buffer_.push_back(internal::CharTraits<Char>::convert(value)); |
| 1495 | return *this; |
| 1496 | } |
| 1497 | |
| 1498 | /** |
| 1499 | Writes *value* to the stream. |
| 1500 | */ |
| 1501 | BasicWriter &operator<<(fmt::BasicStringRef<Char> value) { |
| 1502 | const Char *str = value.c_str(); |
| 1503 | buffer_.append(str, str + value.size()); |
| 1504 | return *this; |
| 1505 | } |
| 1506 | |
| 1507 | template <typename T, typename Spec, typename FillChar> |
| 1508 | BasicWriter &operator<<(const IntFormatSpec<T, Spec, FillChar> &spec) { |
| 1509 | internal::CharTraits<Char>::convert(FillChar()); |
| 1510 | write_int(spec.value(), spec); |
| 1511 | return *this; |
| 1512 | } |
| 1513 | |
| 1514 | template <typename StrChar> |
| 1515 | BasicWriter &operator<<(const StrFormatSpec<StrChar> &spec) { |
| 1516 | const StrChar *s = spec.str(); |
| 1517 | // TODO: error if fill is not convertible to Char |
| 1518 | write_str(s, std::char_traits<Char>::length(s), spec); |
| 1519 | return *this; |
| 1520 | } |
| 1521 | |
| 1522 | void clear() { buffer_.clear(); } |
| 1523 | }; |
| 1524 | |
| 1525 | template <typename Char> |
| 1526 | template <typename StrChar> |
| 1527 | typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str( |
| 1528 | const StrChar *s, std::size_t size, const AlignSpec &spec) { |
| 1529 | CharPtr out = CharPtr(); |
| 1530 | if (spec.width() > size) { |
| 1531 | out = grow_buffer(spec.width()); |
| 1532 | Char fill = static_cast<Char>(spec.fill()); |
| 1533 | if (spec.align() == ALIGN_RIGHT) { |
| 1534 | std::fill_n(out, spec.width() - size, fill); |
| 1535 | out += spec.width() - size; |
| 1536 | } else if (spec.align() == ALIGN_CENTER) { |
| 1537 | out = fill_padding(out, spec.width(), size, fill); |
| 1538 | } else { |
| 1539 | std::fill_n(out + size, spec.width() - size, fill); |
| 1540 | } |
| 1541 | } else { |
| 1542 | out = grow_buffer(size); |
| 1543 | } |
| 1544 | std::copy(s, s + size, out); |
| 1545 | return out; |
| 1546 | } |
| 1547 | |
| 1548 | template <typename Char> |
| 1549 | template <typename Spec> |
| 1550 | typename fmt::BasicWriter<Char>::CharPtr |
| 1551 | fmt::BasicWriter<Char>::prepare_int_buffer( |
| 1552 | unsigned num_digits, const Spec &spec, |
| 1553 | const char *prefix, unsigned prefix_size) { |
| 1554 | unsigned width = spec.width(); |
| 1555 | Alignment align = spec.align(); |
| 1556 | Char fill = static_cast<Char>(spec.fill()); |
| 1557 | if (spec.precision() > static_cast<int>(num_digits)) { |
| 1558 | // Octal prefix '0' is counted as a digit, so ignore it if precision |
| 1559 | // is specified. |
| 1560 | if (prefix_size > 0 && prefix[prefix_size - 1] == '0') |
| 1561 | --prefix_size; |
| 1562 | unsigned number_size = prefix_size + spec.precision(); |
| 1563 | AlignSpec subspec(number_size, '0', ALIGN_NUMERIC); |
| 1564 | if (number_size >= width) |
| 1565 | return prepare_int_buffer(num_digits, subspec, prefix, prefix_size); |
| 1566 | buffer_.reserve(width); |
| 1567 | unsigned fill_size = width - number_size; |
| 1568 | if (align != ALIGN_LEFT) { |
| 1569 | CharPtr p = grow_buffer(fill_size); |
| 1570 | std::fill(p, p + fill_size, fill); |
| 1571 | } |
| 1572 | CharPtr result = prepare_int_buffer( |
| 1573 | num_digits, subspec, prefix, prefix_size); |
| 1574 | if (align == ALIGN_LEFT) { |
| 1575 | CharPtr p = grow_buffer(fill_size); |
| 1576 | std::fill(p, p + fill_size, fill); |
| 1577 | } |
| 1578 | return result; |
| 1579 | } |
| 1580 | unsigned size = prefix_size + num_digits; |
| 1581 | if (width <= size) { |
| 1582 | CharPtr p = grow_buffer(size); |
| 1583 | std::copy(prefix, prefix + prefix_size, p); |
| 1584 | return p + size - 1; |
| 1585 | } |
| 1586 | CharPtr p = grow_buffer(width); |
| 1587 | CharPtr end = p + width; |
| 1588 | if (align == ALIGN_LEFT) { |
| 1589 | std::copy(prefix, prefix + prefix_size, p); |
| 1590 | p += size; |
| 1591 | std::fill(p, end, fill); |
| 1592 | } else if (align == ALIGN_CENTER) { |
| 1593 | p = fill_padding(p, width, size, fill); |
| 1594 | std::copy(prefix, prefix + prefix_size, p); |
| 1595 | p += size; |
| 1596 | } else { |
| 1597 | if (align == ALIGN_NUMERIC) { |
| 1598 | if (prefix_size != 0) { |
| 1599 | p = std::copy(prefix, prefix + prefix_size, p); |
| 1600 | size -= prefix_size; |
| 1601 | } |
| 1602 | } else { |
| 1603 | std::copy(prefix, prefix + prefix_size, end - size); |
| 1604 | } |
| 1605 | std::fill(p, end - size, fill); |
| 1606 | p = end; |
| 1607 | } |
| 1608 | return p - 1; |
| 1609 | } |
| 1610 | |
| 1611 | template <typename Char> |
| 1612 | template <typename T, typename Spec> |
| 1613 | void BasicWriter<Char>::write_int(T value, const Spec &spec) { |
| 1614 | unsigned prefix_size = 0; |
| 1615 | typedef typename internal::IntTraits<T>::MainType UnsignedType; |
| 1616 | UnsignedType abs_value = value; |
| 1617 | char prefix[4] = ""; |
| 1618 | if (internal::is_negative(value)) { |
| 1619 | prefix[0] = '-'; |
| 1620 | ++prefix_size; |
| 1621 | abs_value = 0 - abs_value; |
| 1622 | } else if (spec.flag(SIGN_FLAG)) { |
| 1623 | prefix[0] = spec.flag(PLUS_FLAG) ? '+' : ' '; |
| 1624 | ++prefix_size; |
| 1625 | } |
| 1626 | switch (spec.type()) { |
| 1627 | case 0: case 'd': { |
| 1628 | unsigned num_digits = internal::count_digits(abs_value); |
| 1629 | CharPtr p = prepare_int_buffer( |
| 1630 | num_digits, spec, prefix, prefix_size) + 1 - num_digits; |
| 1631 | internal::format_decimal(get(p), abs_value, num_digits); |
| 1632 | break; |
| 1633 | } |
| 1634 | case 'x': case 'X': { |
| 1635 | UnsignedType n = abs_value; |
| 1636 | if (spec.flag(HASH_FLAG)) { |
| 1637 | prefix[prefix_size++] = '0'; |
| 1638 | prefix[prefix_size++] = spec.type(); |
| 1639 | } |
| 1640 | unsigned num_digits = 0; |
| 1641 | do { |
| 1642 | ++num_digits; |
| 1643 | } while ((n >>= 4) != 0); |
| 1644 | Char *p = get(prepare_int_buffer( |
| 1645 | num_digits, spec, prefix, prefix_size)); |
| 1646 | n = abs_value; |
| 1647 | const char *digits = spec.type() == 'x' ? |
| 1648 | "0123456789abcdef" : "0123456789ABCDEF"; |
| 1649 | do { |
| 1650 | *p-- = digits[n & 0xf]; |
| 1651 | } while ((n >>= 4) != 0); |
| 1652 | break; |
| 1653 | } |
| 1654 | case 'b': case 'B': { |
| 1655 | UnsignedType n = abs_value; |
| 1656 | if (spec.flag(HASH_FLAG)) { |
| 1657 | prefix[prefix_size++] = '0'; |
| 1658 | prefix[prefix_size++] = spec.type(); |
| 1659 | } |
| 1660 | unsigned num_digits = 0; |
| 1661 | do { |
| 1662 | ++num_digits; |
| 1663 | } while ((n >>= 1) != 0); |
| 1664 | Char *p = get(prepare_int_buffer(num_digits, spec, prefix, prefix_size)); |
| 1665 | n = abs_value; |
| 1666 | do { |
| 1667 | *p-- = '0' + (n & 1); |
| 1668 | } while ((n >>= 1) != 0); |
| 1669 | break; |
| 1670 | } |
| 1671 | case 'o': { |
| 1672 | UnsignedType n = abs_value; |
| 1673 | if (spec.flag(HASH_FLAG)) |
| 1674 | prefix[prefix_size++] = '0'; |
| 1675 | unsigned num_digits = 0; |
| 1676 | do { |
| 1677 | ++num_digits; |
| 1678 | } while ((n >>= 3) != 0); |
| 1679 | Char *p = get(prepare_int_buffer(num_digits, spec, prefix, prefix_size)); |
| 1680 | n = abs_value; |
| 1681 | do { |
| 1682 | *p-- = '0' + (n & 7); |
| 1683 | } while ((n >>= 3) != 0); |
| 1684 | break; |
| 1685 | } |
| 1686 | default: |
| 1687 | internal::report_unknown_type( |
| 1688 | spec.type(), spec.flag(CHAR_FLAG) ? "char" : "integer"); |
| 1689 | break; |
| 1690 | } |
| 1691 | } |
| 1692 | |
| 1693 | // Formats a value. |
| 1694 | template <typename Char, typename T> |
| 1695 | void format(BasicFormatter<Char> &f, const Char *format_str, const T &value) { |
| 1696 | std::basic_ostringstream<Char> os; |
| 1697 | os << value; |
| 1698 | f.format(format_str, internal::MakeArg<Char>(os.str())); |
| 1699 | } |
| 1700 | |
| 1701 | // Reports a system error without throwing an exception. |
| 1702 | // Can be used to report errors from destructors. |
| 1703 | void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT(true); |
| 1704 | |
| 1705 | #ifdef _WIN32 |
| 1706 | |
| 1707 | /** |
| 1708 | A Windows error. |
| 1709 | */ |
| 1710 | class WindowsError : public SystemError { |
| 1711 | private: |
| 1712 | void init(int error_code, StringRef format_str, const ArgList &args); |
| 1713 | |
| 1714 | public: |
| 1715 | /** |
| 1716 | \rst |
| 1717 | Constructs a :cpp:class:`fmt::WindowsError` object with the description |
| 1718 | of the form "*<message>*: *<system-message>*", where *<message>* is the |
| 1719 | formatted message and *<system-message>* is the system message corresponding |
| 1720 | to the error code. |
| 1721 | *error_code* is a Windows error code as given by ``GetLastError``. |
| 1722 | \endrst |
| 1723 | */ |
| 1724 | WindowsError(int error_code, StringRef message) { |
| 1725 | init(error_code, message, ArgList()); |
| 1726 | } |
| 1727 | FMT_VARIADIC_CTOR(WindowsError, init, int, StringRef) |
| 1728 | }; |
| 1729 | |
| 1730 | // Reports a Windows error without throwing an exception. |
| 1731 | // Can be used to report errors from destructors. |
| 1732 | void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT(true); |
| 1733 | |
| 1734 | #endif |
| 1735 | |
| 1736 | enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE }; |
| 1737 | |
| 1738 | /** |
| 1739 | Formats a string and prints it to stdout using ANSI escape sequences |
| 1740 | to specify color (experimental). |
| 1741 | Example: |
| 1742 | PrintColored(fmt::RED, "Elapsed time: {0:.2f} seconds") << 1.23; |
| 1743 | */ |
| 1744 | void print_colored(Color c, StringRef format, const ArgList &args); |
| 1745 | |
| 1746 | /** |
| 1747 | \rst |
| 1748 | Formats arguments and returns the result as a string. |
| 1749 | |
| 1750 | **Example**:: |
| 1751 | |
| 1752 | std::string message = format("The answer is {}", 42); |
| 1753 | \endrst |
| 1754 | */ |
| 1755 | inline std::string format(StringRef format_str, const ArgList &args) { |
| 1756 | Writer w; |
| 1757 | w.write(format_str, args); |
| 1758 | return w.str(); |
| 1759 | } |
| 1760 | |
| 1761 | inline std::wstring format(WStringRef format_str, const ArgList &args) { |
| 1762 | WWriter w; |
| 1763 | w.write(format_str, args); |
| 1764 | return w.str(); |
| 1765 | } |
| 1766 | |
| 1767 | /** |
| 1768 | \rst |
| 1769 | Prints formatted data to the file *f*. |
| 1770 | |
| 1771 | **Example**:: |
| 1772 | |
| 1773 | print(stderr, "Don't {}!", "panic"); |
| 1774 | \endrst |
| 1775 | */ |
| 1776 | void print(std::FILE *f, StringRef format_str, const ArgList &args); |
| 1777 | |
| 1778 | /** |
| 1779 | \rst |
| 1780 | Prints formatted data to ``stdout``. |
| 1781 | |
| 1782 | **Example**:: |
| 1783 | |
| 1784 | print("Elapsed time: {0:.2f} seconds", 1.23); |
| 1785 | \endrst |
| 1786 | */ |
| 1787 | inline void print(StringRef format_str, const ArgList &args) { |
| 1788 | print(stdout, format_str, args); |
| 1789 | } |
| 1790 | |
| 1791 | /** |
| 1792 | \rst |
| 1793 | Prints formatted data to the stream *os*. |
| 1794 | |
| 1795 | **Example**:: |
| 1796 | |
| 1797 | print(cerr, "Don't {}!", "panic"); |
| 1798 | \endrst |
| 1799 | */ |
| 1800 | void print(std::ostream &os, StringRef format_str, const ArgList &args); |
| 1801 | |
| 1802 | template <typename Char> |
| 1803 | void printf(BasicWriter<Char> &w, |
| 1804 | BasicStringRef<Char> format, const ArgList &args) { |
| 1805 | internal::PrintfFormatter<Char>().format(w, format, args); |
| 1806 | } |
| 1807 | |
| 1808 | /** |
| 1809 | \rst |
| 1810 | Formats arguments and returns the result as a string. |
| 1811 | |
| 1812 | **Example**:: |
| 1813 | |
| 1814 | std::string message = fmt::sprintf("The answer is %d", 42); |
| 1815 | \endrst |
| 1816 | */ |
| 1817 | inline std::string sprintf(StringRef format, const ArgList &args) { |
| 1818 | Writer w; |
| 1819 | printf(w, format, args); |
| 1820 | return w.str(); |
| 1821 | } |
| 1822 | |
| 1823 | /** |
| 1824 | \rst |
| 1825 | Prints formatted data to the file *f*. |
| 1826 | |
| 1827 | **Example**:: |
| 1828 | |
| 1829 | fmt::fprintf(stderr, "Don't %s!", "panic"); |
| 1830 | \endrst |
| 1831 | */ |
| 1832 | int fprintf(std::FILE *f, StringRef format, const ArgList &args); |
| 1833 | |
| 1834 | /** |
| 1835 | \rst |
| 1836 | Prints formatted data to ``stdout``. |
| 1837 | |
| 1838 | **Example**:: |
| 1839 | |
| 1840 | fmt::printf("Elapsed time: %.2f seconds", 1.23); |
| 1841 | \endrst |
| 1842 | */ |
| 1843 | inline int printf(StringRef format, const ArgList &args) { |
| 1844 | return fprintf(stdout, format, args); |
| 1845 | } |
| 1846 | |
| 1847 | /** |
| 1848 | Fast integer formatter. |
| 1849 | */ |
| 1850 | class FormatInt { |
| 1851 | private: |
| 1852 | // Buffer should be large enough to hold all digits (digits10 + 1), |
| 1853 | // a sign and a null character. |
| 1854 | enum {BUFFER_SIZE = std::numeric_limits<ULongLong>::digits10 + 3}; |
| 1855 | mutable char buffer_[BUFFER_SIZE]; |
| 1856 | char *str_; |
| 1857 | |
| 1858 | // Formats value in reverse and returns the number of digits. |
| 1859 | char *format_decimal(ULongLong value) { |
| 1860 | char *buffer_end = buffer_ + BUFFER_SIZE - 1; |
| 1861 | while (value >= 100) { |
| 1862 | // Integer division is slow so do it for a group of two digits instead |
| 1863 | // of for every digit. The idea comes from the talk by Alexandrescu |
| 1864 | // "Three Optimization Tips for C++". See speed-test for a comparison. |
| 1865 | unsigned index = (value % 100) * 2; |
| 1866 | value /= 100; |
| 1867 | *--buffer_end = internal::DIGITS[index + 1]; |
| 1868 | *--buffer_end = internal::DIGITS[index]; |
| 1869 | } |
| 1870 | if (value < 10) { |
| 1871 | *--buffer_end = static_cast<char>('0' + value); |
| 1872 | return buffer_end; |
| 1873 | } |
| 1874 | unsigned index = static_cast<unsigned>(value * 2); |
| 1875 | *--buffer_end = internal::DIGITS[index + 1]; |
| 1876 | *--buffer_end = internal::DIGITS[index]; |
| 1877 | return buffer_end; |
| 1878 | } |
| 1879 | |
| 1880 | void FormatSigned(LongLong value) { |
| 1881 | ULongLong abs_value = static_cast<ULongLong>(value); |
| 1882 | bool negative = value < 0; |
| 1883 | if (negative) |
| 1884 | abs_value = 0 - abs_value; |
| 1885 | str_ = format_decimal(abs_value); |
| 1886 | if (negative) |
| 1887 | *--str_ = '-'; |
| 1888 | } |
| 1889 | |
| 1890 | public: |
| 1891 | explicit FormatInt(int value) { FormatSigned(value); } |
| 1892 | explicit FormatInt(long value) { FormatSigned(value); } |
| 1893 | explicit FormatInt(LongLong value) { FormatSigned(value); } |
| 1894 | explicit FormatInt(unsigned value) : str_(format_decimal(value)) {} |
| 1895 | explicit FormatInt(unsigned long value) : str_(format_decimal(value)) {} |
| 1896 | explicit FormatInt(ULongLong value) : str_(format_decimal(value)) {} |
| 1897 | |
| 1898 | /** |
| 1899 | Returns the number of characters written to the output buffer. |
| 1900 | */ |
| 1901 | std::size_t size() const { return buffer_ - str_ + BUFFER_SIZE - 1; } |
| 1902 | |
| 1903 | /** |
| 1904 | Returns a pointer to the output buffer content. No terminating null |
| 1905 | character is appended. |
| 1906 | */ |
| 1907 | const char *data() const { return str_; } |
| 1908 | |
| 1909 | /** |
| 1910 | Returns a pointer to the output buffer content with terminating null |
| 1911 | character appended. |
| 1912 | */ |
| 1913 | const char *c_str() const { |
| 1914 | buffer_[BUFFER_SIZE - 1] = '\0'; |
| 1915 | return str_; |
| 1916 | } |
| 1917 | |
| 1918 | /** |
| 1919 | Returns the content of the output buffer as an `std::string`. |
| 1920 | */ |
| 1921 | std::string str() const { return std::string(str_, size()); } |
| 1922 | }; |
| 1923 | |
| 1924 | // Formats a decimal integer value writing into buffer and returns |
| 1925 | // a pointer to the end of the formatted string. This function doesn't |
| 1926 | // write a terminating null character. |
| 1927 | template <typename T> |
| 1928 | inline void format_decimal(char *&buffer, T value) { |
| 1929 | typename internal::IntTraits<T>::MainType abs_value = value; |
| 1930 | if (internal::is_negative(value)) { |
| 1931 | *buffer++ = '-'; |
| 1932 | abs_value = 0 - abs_value; |
| 1933 | } |
| 1934 | if (abs_value < 100) { |
| 1935 | if (abs_value < 10) { |
| 1936 | *buffer++ = static_cast<char>('0' + abs_value); |
| 1937 | return; |
| 1938 | } |
| 1939 | unsigned index = static_cast<unsigned>(abs_value * 2); |
| 1940 | *buffer++ = internal::DIGITS[index]; |
| 1941 | *buffer++ = internal::DIGITS[index + 1]; |
| 1942 | return; |
| 1943 | } |
| 1944 | unsigned num_digits = internal::count_digits(abs_value); |
| 1945 | internal::format_decimal(buffer, abs_value, num_digits); |
| 1946 | buffer += num_digits; |
| 1947 | } |
| 1948 | } |
| 1949 | |
| 1950 | #if FMT_GCC_VERSION |
| 1951 | // Use the system_header pragma to suppress warnings about variadic macros |
| 1952 | // because suppressing -Wvariadic-macros with the diagnostic pragma doesn't |
| 1953 | // work. It is used at the end because we want to suppress as little warnings |
| 1954 | // as possible. |
| 1955 | # pragma GCC system_header |
| 1956 | #endif |
| 1957 | |
| 1958 | // This is used to work around VC++ bugs in handling variadic macros. |
| 1959 | #define FMT_EXPAND(args) args |
| 1960 | |
| 1961 | // Returns the number of arguments. |
| 1962 | // Based on https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s. |
| 1963 | #define FMT_NARG(...) FMT_NARG_(__VA_ARGS__, FMT_RSEQ_N()) |
| 1964 | #define FMT_NARG_(...) FMT_EXPAND(FMT_ARG_N(__VA_ARGS__)) |
| 1965 | #define FMT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N |
| 1966 | #define FMT_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 |
| 1967 | |
| 1968 | #define FMT_CONCAT(a, b) a##b |
| 1969 | #define FMT_FOR_EACH_(N, f, ...) \ |
| 1970 | FMT_EXPAND(FMT_CONCAT(FMT_FOR_EACH, N)(f, __VA_ARGS__)) |
| 1971 | #define FMT_FOR_EACH(f, ...) \ |
| 1972 | FMT_EXPAND(FMT_FOR_EACH_(FMT_NARG(__VA_ARGS__), f, __VA_ARGS__)) |
| 1973 | |
| 1974 | #define FMT_ADD_ARG_NAME(type, index) type arg##index |
| 1975 | #define FMT_GET_ARG_NAME(type, index) arg##index |
| 1976 | |
| 1977 | #if FMT_USE_VARIADIC_TEMPLATES |
| 1978 | # define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \ |
| 1979 | template<typename... Args> \ |
| 1980 | ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ |
| 1981 | const Args & ... args) { \ |
| 1982 | using fmt::internal::Arg; \ |
| 1983 | const Arg array[fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \ |
| 1984 | fmt::internal::MakeArg<Char>(args)... \ |
| 1985 | }; \ |
| 1986 | call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \ |
| 1987 | fmt::ArgList(array, sizeof...(Args))); \ |
| 1988 | } |
| 1989 | #else |
| 1990 | // Defines a wrapper for a function taking __VA_ARGS__ arguments |
| 1991 | // and n additional arguments of arbitrary types. |
| 1992 | # define FMT_WRAP(Char, ReturnType, func, call, n, ...) \ |
| 1993 | template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \ |
| 1994 | inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ |
| 1995 | FMT_GEN(n, FMT_MAKE_ARG)) { \ |
| 1996 | const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF_##Char)}; \ |
| 1997 | call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \ |
| 1998 | fmt::ArgList(args, sizeof(args) / sizeof(*args))); \ |
| 1999 | } |
| 2000 | |
| 2001 | # define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \ |
| 2002 | inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) { \ |
| 2003 | call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList()); \ |
| 2004 | } \ |
| 2005 | FMT_WRAP(Char, ReturnType, func, call, 1, __VA_ARGS__) \ |
| 2006 | FMT_WRAP(Char, ReturnType, func, call, 2, __VA_ARGS__) \ |
| 2007 | FMT_WRAP(Char, ReturnType, func, call, 3, __VA_ARGS__) \ |
| 2008 | FMT_WRAP(Char, ReturnType, func, call, 4, __VA_ARGS__) \ |
| 2009 | FMT_WRAP(Char, ReturnType, func, call, 5, __VA_ARGS__) \ |
| 2010 | FMT_WRAP(Char, ReturnType, func, call, 6, __VA_ARGS__) \ |
| 2011 | FMT_WRAP(Char, ReturnType, func, call, 7, __VA_ARGS__) \ |
| 2012 | FMT_WRAP(Char, ReturnType, func, call, 8, __VA_ARGS__) \ |
| 2013 | FMT_WRAP(Char, ReturnType, func, call, 9, __VA_ARGS__) \ |
| 2014 | FMT_WRAP(Char, ReturnType, func, call, 10, __VA_ARGS__) |
| 2015 | #endif // FMT_USE_VARIADIC_TEMPLATES |
| 2016 | |
| 2017 | /** |
| 2018 | \rst |
| 2019 | Defines a variadic function with the specified return type, function name |
| 2020 | and argument types passed as variable arguments to this macro. |
| 2021 | |
| 2022 | **Example**:: |
| 2023 | |
| 2024 | void print_error(const char *file, int line, const char *format, |
| 2025 | const fmt::ArgList &args) { |
| 2026 | fmt::print("{}: {}: ", file, line); |
| 2027 | fmt::print(format, args); |
| 2028 | } |
| 2029 | FMT_VARIADIC(void, print_error, const char *, int, const char *) |
| 2030 | |
| 2031 | ``FMT_VARIADIC`` is used for compatibility with legacy C++ compilers that |
| 2032 | don't implement variadic templates. You don't have to use this macro if |
| 2033 | you don't need legacy compiler support and can use variadic templates |
| 2034 | directly:: |
| 2035 | |
| 2036 | template<typename... Args> |
| 2037 | void print_error(const char *file, int line, const char *format, |
| 2038 | const Args & ... args) { |
| 2039 | fmt::print("{}: {}: ", file, line); |
| 2040 | fmt::print(format, args...); |
| 2041 | } |
| 2042 | \endrst |
| 2043 | */ |
| 2044 | #define FMT_VARIADIC(ReturnType, func, ...) \ |
| 2045 | FMT_VARIADIC_(char, ReturnType, func, return func, __VA_ARGS__) |
| 2046 | |
| 2047 | #define FMT_VARIADIC_W(ReturnType, func, ...) \ |
| 2048 | FMT_VARIADIC_(wchar_t, ReturnType, func, return func, __VA_ARGS__) |
| 2049 | |
| 2050 | namespace fmt { |
| 2051 | FMT_VARIADIC(std::string, format, StringRef) |
| 2052 | FMT_VARIADIC_W(std::wstring, format, WStringRef) |
| 2053 | FMT_VARIADIC(void, print, StringRef) |
| 2054 | FMT_VARIADIC(void, print, std::FILE *, StringRef) |
| 2055 | FMT_VARIADIC(void, print, std::ostream &, StringRef) |
| 2056 | FMT_VARIADIC(void, print_colored, Color, StringRef) |
| 2057 | FMT_VARIADIC(std::string, sprintf, StringRef) |
| 2058 | FMT_VARIADIC(int, printf, StringRef) |
| 2059 | FMT_VARIADIC(int, fprintf, std::FILE *, StringRef) |
| 2060 | } |
| 2061 | |
| 2062 | // Restore warnings. |
| 2063 | #if FMT_GCC_VERSION >= 406 |
| 2064 | # pragma GCC diagnostic pop |
| 2065 | #endif |
| 2066 | |
| 2067 | #endif // FMT_FORMAT_H_ |