format.hh 125 KB
Newer Older
Philip Trettner's avatar
Philip Trettner committed
1
2
3
/*
 Formatting library for C++

4
 Copyright (c) 2012 - 2016, Victor Zverovich
Philip Trettner's avatar
Philip Trettner committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 1. Redistributions of source code must retain the above copyright notice, this
    list of conditions and the following disclaimer.
 2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef FMT_FORMAT_H_
#define FMT_FORMAT_H_

31
#define FMT_INCLUDE
Philip Trettner's avatar
Philip Trettner committed
32
#include <cassert>
33
#include <clocale>
Philip Trettner's avatar
Philip Trettner committed
34
35
#include <cmath>
#include <cstdio>
36
#include <cstring>
Philip Trettner's avatar
Philip Trettner committed
37
#include <limits>
38
#include <memory>
Philip Trettner's avatar
Philip Trettner committed
39
40
#include <stdexcept>
#include <string>
41
42
43
#include <vector>
#include <utility>  // for std::pair
#undef FMT_INCLUDE
Philip Trettner's avatar
Philip Trettner committed
44

45
46
47
48
49
50
51
// The fmt library version in the form major * 10000 + minor * 100 + patch.
#define FMT_VERSION 40001

#if defined(__has_include)
# define FMT_HAS_INCLUDE(x) __has_include(x)
#else
# define FMT_HAS_INCLUDE(x) 0
Philip Trettner's avatar
Philip Trettner committed
52
53
#endif

54
55
56
57
58
59
#if (FMT_HAS_INCLUDE(<string_view>) && __cplusplus > 201402L) || \
    (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
# include <string_view>
# define FMT_HAS_STRING_VIEW 1
#else
# define FMT_HAS_STRING_VIEW 0
Philip Trettner's avatar
Philip Trettner committed
60
61
#endif

62
63
#if defined _SECURE_SCL && _SECURE_SCL
# define FMT_SECURE_SCL _SECURE_SCL
Philip Trettner's avatar
Philip Trettner committed
64
#else
65
# define FMT_SECURE_SCL 0
Philip Trettner's avatar
Philip Trettner committed
66
67
68
#endif

#if FMT_SECURE_SCL
69
# include <iterator>
Philip Trettner's avatar
Philip Trettner committed
70
71
72
#endif

#ifdef _MSC_VER
73
74
75
# define FMT_MSC_VER _MSC_VER
#else
# define FMT_MSC_VER 0
Philip Trettner's avatar
Philip Trettner committed
76
77
#endif

78
79
80
81
#if FMT_MSC_VER && FMT_MSC_VER <= 1500
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
typedef __int64          intmax_t;
Philip Trettner's avatar
Philip Trettner committed
82
#else
83
84
#include <stdint.h>
#endif
Philip Trettner's avatar
Philip Trettner committed
85

86
87
88
89
90
91
#if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
# ifdef FMT_EXPORT
#  define FMT_API __declspec(dllexport)
# elif defined(FMT_SHARED)
#  define FMT_API __declspec(dllimport)
# endif
Philip Trettner's avatar
Philip Trettner committed
92
#endif
93
94
#ifndef FMT_API
# define FMT_API
Philip Trettner's avatar
Philip Trettner committed
95
96
97
#endif

#ifdef __GNUC__
98
99
100
101
# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
# define FMT_GCC_EXTENSION __extension__
# if FMT_GCC_VERSION >= 406
#  pragma GCC diagnostic push
Philip Trettner's avatar
Philip Trettner committed
102
103
// Disable the warning about "long long" which is sometimes reported even
// when using __extension__.
104
#  pragma GCC diagnostic ignored "-Wlong-long"
Philip Trettner's avatar
Philip Trettner committed
105
106
// Disable the warning about declaration shadowing because it affects too
// many valid cases.
107
#  pragma GCC diagnostic ignored "-Wshadow"
Philip Trettner's avatar
Philip Trettner committed
108
109
// Disable the warning about implicit conversions that may change the sign of
// an integer; silencing it otherwise would require many explicit casts.
110
111
112
113
114
#  pragma GCC diagnostic ignored "-Wsign-conversion"
# endif
# if __cplusplus >= 201103L || defined __GXX_EXPERIMENTAL_CXX0X__
#  define FMT_HAS_GXX_CXX11 1
# endif
Philip Trettner's avatar
Philip Trettner committed
115
#else
116
117
118
119
120
121
122
123
124
# define FMT_GCC_VERSION 0
# define FMT_GCC_EXTENSION
# define FMT_HAS_GXX_CXX11 0
#endif

#if defined(__INTEL_COMPILER)
# define FMT_ICC_VERSION __INTEL_COMPILER
#elif defined(__ICL)
# define FMT_ICC_VERSION __ICL
Philip Trettner's avatar
Philip Trettner committed
125
126
#endif

127
128
129
130
131
#if defined(__clang__) && !defined(FMT_ICC_VERSION)
# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
# pragma clang diagnostic ignored "-Wpadded"
Philip Trettner's avatar
Philip Trettner committed
132
133
134
#endif

#ifdef __GNUC_LIBSTD__
135
# define FMT_GNUC_LIBSTD_VERSION (__GNUC_LIBSTD__ * 100 + __GNUC_LIBSTD_MINOR__)
Philip Trettner's avatar
Philip Trettner committed
136
137
138
#endif

#ifdef __has_feature
139
# define FMT_HAS_FEATURE(x) __has_feature(x)
Philip Trettner's avatar
Philip Trettner committed
140
#else
141
# define FMT_HAS_FEATURE(x) 0
Philip Trettner's avatar
Philip Trettner committed
142
143
144
#endif

#ifdef __has_builtin
145
# define FMT_HAS_BUILTIN(x) __has_builtin(x)
Philip Trettner's avatar
Philip Trettner committed
146
#else
147
# define FMT_HAS_BUILTIN(x) 0
Philip Trettner's avatar
Philip Trettner committed
148
149
150
#endif

#ifdef __has_cpp_attribute
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
# define FMT_HAS_CPP_ATTRIBUTE(x) 0
#endif

#if FMT_HAS_CPP_ATTRIBUTE(maybe_unused)
# define FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED
// VC++ 1910 support /std: option and that will set _MSVC_LANG macro
// Clang with Microsoft CodeGen doesn't define _MSVC_LANG macro
#elif defined(_MSVC_LANG) && _MSVC_LANG > 201402
# define FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED
#endif

#ifdef FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED
# define FMT_MAYBE_UNUSED [[maybe_unused]]
// g++/clang++ also support [[gnu::unused]]. However, we don't use it.
#elif defined(__GNUC__)
# define FMT_MAYBE_UNUSED __attribute__((unused))
#else
# define FMT_MAYBE_UNUSED
#endif

// Use the compiler's attribute noreturn
#if defined(__MINGW32__) || defined(__MINGW64__)
# define FMT_NORETURN __attribute__((noreturn))
#elif FMT_HAS_CPP_ATTRIBUTE(noreturn) && __cplusplus >= 201103L
# define FMT_NORETURN [[noreturn]]
Philip Trettner's avatar
Philip Trettner committed
178
#else
179
# define FMT_NORETURN
Philip Trettner's avatar
Philip Trettner committed
180
181
182
183
184
185
#endif

#ifndef FMT_USE_VARIADIC_TEMPLATES
// Variadic templates are available in GCC since version 4.4
// (http://gcc.gnu.org/projects/cxx0x.html) and in Visual C++
// since version 2013.
186
187
188
# define FMT_USE_VARIADIC_TEMPLATES \
   (FMT_HAS_FEATURE(cxx_variadic_templates) || \
       (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800)
Philip Trettner's avatar
Philip Trettner committed
189
190
191
192
193
#endif

#ifndef FMT_USE_RVALUE_REFERENCES
// Don't use rvalue references when compiling with clang and an old libstdc++
// as the latter doesn't provide std::move.
194
195
196
197
198
199
200
201
202
203
204
# if defined(FMT_GNUC_LIBSTD_VERSION) && FMT_GNUC_LIBSTD_VERSION <= 402
#  define FMT_USE_RVALUE_REFERENCES 0
# else
#  define FMT_USE_RVALUE_REFERENCES \
    (FMT_HAS_FEATURE(cxx_rvalue_references) || \
        (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1600)
# endif
#endif

#if __cplusplus >= 201103L || FMT_MSC_VER >= 1700
# define FMT_USE_ALLOCATOR_TRAITS 1
Philip Trettner's avatar
Philip Trettner committed
205
#else
206
207
208
209
210
211
# define FMT_USE_ALLOCATOR_TRAITS 0
#endif

// Check if exceptions are disabled.
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
# define FMT_EXCEPTIONS 0
Philip Trettner's avatar
Philip Trettner committed
212
#endif
213
214
215
216
217
#if FMT_MSC_VER && !_HAS_EXCEPTIONS
# define FMT_EXCEPTIONS 0
#endif
#ifndef FMT_EXCEPTIONS
# define FMT_EXCEPTIONS 1
Philip Trettner's avatar
Philip Trettner committed
218
219
#endif

220
221
222
223
224
225
#ifndef FMT_THROW
# if FMT_EXCEPTIONS
#  define FMT_THROW(x) throw x
# else
#  define FMT_THROW(x) assert(false)
# endif
Philip Trettner's avatar
Philip Trettner committed
226
227
#endif

228
// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature).
Philip Trettner's avatar
Philip Trettner committed
229
#ifndef FMT_USE_NOEXCEPT
230
231
232
233
234
235
236
237
238
# define FMT_USE_NOEXCEPT 0
#endif

#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
    (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
    FMT_MSC_VER >= 1900
# define FMT_DETECTED_NOEXCEPT noexcept
#else
# define FMT_DETECTED_NOEXCEPT throw()
Philip Trettner's avatar
Philip Trettner committed
239
240
241
#endif

#ifndef FMT_NOEXCEPT
242
243
244
245
246
247
248
249
250
251
252
# if FMT_EXCEPTIONS
#  define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT
# else
#  define FMT_NOEXCEPT
# endif
#endif

// This is needed because GCC still uses throw() in its headers when exceptions
// are disabled.
#if FMT_GCC_VERSION
# define FMT_DTOR_NOEXCEPT FMT_DETECTED_NOEXCEPT
Philip Trettner's avatar
Philip Trettner committed
253
#else
254
# define FMT_DTOR_NOEXCEPT FMT_NOEXCEPT
Philip Trettner's avatar
Philip Trettner committed
255
#endif
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274

#ifndef FMT_OVERRIDE
# if (defined(FMT_USE_OVERRIDE) && FMT_USE_OVERRIDE) || FMT_HAS_FEATURE(cxx_override) || \
   (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
   FMT_MSC_VER >= 1900
#  define FMT_OVERRIDE override
# else
#  define FMT_OVERRIDE
# endif
#endif

#ifndef FMT_NULL
# if FMT_HAS_FEATURE(cxx_nullptr) || \
   (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
   FMT_MSC_VER >= 1600
#  define FMT_NULL nullptr
# else
#  define FMT_NULL NULL
# endif
Philip Trettner's avatar
Philip Trettner committed
275
276
277
278
279
#endif

// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
#ifndef FMT_USE_DELETED_FUNCTIONS
280
# define FMT_USE_DELETED_FUNCTIONS 0
Philip Trettner's avatar
Philip Trettner committed
281
282
#endif

283
284
285
286
287
288
#if FMT_USE_DELETED_FUNCTIONS || FMT_HAS_FEATURE(cxx_deleted_functions) || \
  (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800
# define FMT_DELETED_OR_UNDEFINED  = delete
# define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \
    TypeName(const TypeName&) = delete; \
    TypeName& operator=(const TypeName&) = delete
Philip Trettner's avatar
Philip Trettner committed
289
#else
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# define FMT_DELETED_OR_UNDEFINED
# define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \
    TypeName(const TypeName&); \
    TypeName& operator=(const TypeName&)
#endif

#ifndef FMT_USE_DEFAULTED_FUNCTIONS
# define FMT_USE_DEFAULTED_FUNCTIONS 0
#endif

#ifndef FMT_DEFAULTED_COPY_CTOR
# if FMT_USE_DEFAULTED_FUNCTIONS || FMT_HAS_FEATURE(cxx_defaulted_functions) || \
   (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800
#  define FMT_DEFAULTED_COPY_CTOR(TypeName) \
    TypeName(const TypeName&) = default;
# else
#  define FMT_DEFAULTED_COPY_CTOR(TypeName)
# endif
Philip Trettner's avatar
Philip Trettner committed
308
309
310
311
312
313
#endif

#ifndef FMT_USE_USER_DEFINED_LITERALS
// All compilers which support UDLs also support variadic templates. This
// makes the aion_fmt::literals implementation easier. However, an explicit check
// for variadic templates is added here just in case.
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
// For Intel's compiler both it and the system gcc/msc must support UDLs.
# if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \
   (FMT_HAS_FEATURE(cxx_user_literals) || \
     (FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900) && \
   (!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500)
#  define FMT_USE_USER_DEFINED_LITERALS 1
# else
#  define FMT_USE_USER_DEFINED_LITERALS 0
# endif
#endif

#ifndef FMT_USE_EXTERN_TEMPLATES
# define FMT_USE_EXTERN_TEMPLATES \
    (FMT_CLANG_VERSION >= 209 || (FMT_GCC_VERSION >= 303 && FMT_HAS_GXX_CXX11))
#endif

#ifdef FMT_HEADER_ONLY
// If header only do not use extern templates.
# undef FMT_USE_EXTERN_TEMPLATES
# define FMT_USE_EXTERN_TEMPLATES 0
Philip Trettner's avatar
Philip Trettner committed
334
335
336
#endif

#ifndef FMT_ASSERT
337
# define FMT_ASSERT(condition, message) assert((condition) && message)
Philip Trettner's avatar
Philip Trettner committed
338
339
#endif

340
341
342
343
344
345
// __builtin_clz is broken in clang with Microsoft CodeGen:
// https://github.com/fmtlib/fmt/issues/519
#ifndef _MSC_VER
# if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz)
#  define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
# endif
Philip Trettner's avatar
Philip Trettner committed
346

347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
# if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll)
#  define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
# endif
#endif

// Some compilers masquerade as both MSVC and GCC-likes or
// otherwise support __builtin_clz and __builtin_clzll, so
// only define FMT_BUILTIN_CLZ using the MSVC intrinsics
// if the clz and clzll builtins are not available.
#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && !defined(_MANAGED)
# include <intrin.h>  // _BitScanReverse, _BitScanReverse64

namespace aion_fmt {
namespace internal {
// avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning
# ifndef __clang__
#  pragma intrinsic(_BitScanReverse)
# endif
inline uint32_t clz(uint32_t x) {
  unsigned long r = 0;
  _BitScanReverse(&r, x);

  assert(x != 0);
  // Static analysis complains about using uninitialized data
  // "r", but the only way that can happen is if "x" is 0,
  // which the callers guarantee to not happen.
# pragma warning(suppress: 6102)
  return 31 - r;
Philip Trettner's avatar
Philip Trettner committed
375
}
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
# define FMT_BUILTIN_CLZ(n) aion_fmt::internal::clz(n)

// avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning
# if defined(_WIN64) && !defined(__clang__)
#  pragma intrinsic(_BitScanReverse64)
# endif

inline uint32_t clzll(uint64_t x) {
  unsigned long r = 0;
# ifdef _WIN64
  _BitScanReverse64(&r, x);
# else
  // Scan the high 32 bits.
  if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
    return 63 - (r + 32);

  // Scan the low 32 bits.
  _BitScanReverse(&r, static_cast<uint32_t>(x));
# endif

  assert(x != 0);
  // Static analysis complains about using uninitialized data
  // "r", but the only way that can happen is if "x" is 0,
  // which the callers guarantee to not happen.
# pragma warning(suppress: 6102)
  return 63 - r;
Philip Trettner's avatar
Philip Trettner committed
402
}
403
# define FMT_BUILTIN_CLZLL(n) aion_fmt::internal::clzll(n)
Philip Trettner's avatar
Philip Trettner committed
404
405
}
}
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
#endif

namespace aion_fmt {
namespace internal {
struct DummyInt {
  int data[2];
  operator int() const { return 0; }
};
typedef std::numeric_limits<aion_fmt::internal::DummyInt> FPUtil;

// Dummy implementations of system functions such as signbit and ecvt called
// if the latter are not available.
inline DummyInt signbit(...) { return DummyInt(); }
inline DummyInt _ecvt_s(...) { return DummyInt(); }
inline DummyInt isinf(...) { return DummyInt(); }
inline DummyInt _finite(...) { return DummyInt(); }
inline DummyInt isnan(...) { return DummyInt(); }
inline DummyInt _isnan(...) { return DummyInt(); }
Philip Trettner's avatar
Philip Trettner committed
424
425
426
427

// A helper function to suppress bogus "conditional expression is constant"
// warnings.
template <typename T>
428
inline T const_check(T value) { return value; }
Philip Trettner's avatar
Philip Trettner committed
429
}
430
}  // namespace aion_fmt
Philip Trettner's avatar
Philip Trettner committed
431

432
namespace std {
Philip Trettner's avatar
Philip Trettner committed
433
434
435
436
437
// Standard permits specialization of std::numeric_limits. This specialization
// is used to resolve ambiguity between isinf and std::isinf in glibc:
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48891
// and the same for isnan and signbit.
template <>
438
439
440
441
442
443
444
445
446
447
448
449
class numeric_limits<aion_fmt::internal::DummyInt> :
    public std::numeric_limits<int> {
 public:
  // Portable version of isinf.
  template <typename T>
  static bool isinfinity(T x) {
    using namespace aion_fmt::internal;
    // The resolution "priority" is:
    // isinf macro > std::isinf > ::isinf > aion_fmt::internal::isinf
    if (const_check(sizeof(isinf(x)) == sizeof(bool) ||
                    sizeof(isinf(x)) == sizeof(int))) {
      return isinf(x) != 0;
Philip Trettner's avatar
Philip Trettner committed
450
    }
451
452
453
454
455
456
457
458
459
460
    return !_finite(static_cast<double>(x));
  }

  // Portable version of isnan.
  template <typename T>
  static bool isnotanumber(T x) {
    using namespace aion_fmt::internal;
    if (const_check(sizeof(isnan(x)) == sizeof(bool) ||
                    sizeof(isnan(x)) == sizeof(int))) {
      return isnan(x) != 0;
Philip Trettner's avatar
Philip Trettner committed
461
    }
462
463
464
465
466
467
468
469
470
    return _isnan(static_cast<double>(x)) != 0;
  }

  // Portable version of signbit.
  static bool isnegative(double x) {
    using namespace aion_fmt::internal;
    if (const_check(sizeof(signbit(x)) == sizeof(bool) ||
                    sizeof(signbit(x)) == sizeof(int))) {
      return signbit(x) != 0;
Philip Trettner's avatar
Philip Trettner committed
471
    }
472
473
474
475
476
477
478
    if (x < 0) return true;
    if (!isnotanumber(x)) return false;
    int dec = 0, sign = 0;
    char buffer[2];  // The buffer size must be >= 2 or _ecvt_s will fail.
    _ecvt_s(buffer, sizeof(buffer), x, 0, &dec, &sign);
    return sign != 0;
  }
Philip Trettner's avatar
Philip Trettner committed
479
};
480
481
482
}  // namespace std

namespace aion_fmt {
Philip Trettner's avatar
Philip Trettner committed
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499

// Fix the warning about long long on older versions of GCC
// that don't support the diagnostic pragma.
FMT_GCC_EXTENSION typedef long long LongLong;
FMT_GCC_EXTENSION typedef unsigned long long ULongLong;

#if FMT_USE_RVALUE_REFERENCES
using std::move;
#endif

template <typename Char>
class BasicWriter;

typedef BasicWriter<char> Writer;
typedef BasicWriter<wchar_t> WWriter;

template <typename Char>
500
class ArgFormatter;
Philip Trettner's avatar
Philip Trettner committed
501

502
503
504
505
506
507
508
509
struct FormatSpec;

template <typename Impl, typename Char, typename Spec = aion_fmt::FormatSpec>
class BasicPrintfArgFormatter;

template <typename CharType,
          typename ArgFormatter = aion_fmt::ArgFormatter<CharType> >
class BasicFormatter;
Philip Trettner's avatar
Philip Trettner committed
510
511
512

/**
  \rst
513
514
  A string reference. It can be constructed from a C string or
  ``std::basic_string``.
Philip Trettner's avatar
Philip Trettner committed
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536

  You can use one of the following typedefs for common character types:

  +------------+-------------------------+
  | Type       | Definition              |
  +============+=========================+
  | StringRef  | BasicStringRef<char>    |
  +------------+-------------------------+
  | WStringRef | BasicStringRef<wchar_t> |
  +------------+-------------------------+

  This class is most useful as a parameter type to allow passing
  different types of strings to a function, for example::

    template <typename... Args>
    std::string format(StringRef format_str, const Args & ... args);

    format("{}", 42);
    format(std::string("{}"), 42);
  \endrst
 */
template <typename Char>
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
class BasicStringRef {
 private:
  const Char *data_;
  std::size_t size_;

 public:
  /** Constructs a string reference object from a C string and a size. */
  BasicStringRef(const Char *s, std::size_t size) : data_(s), size_(size) {}

  /**
    \rst
    Constructs a string reference object from a C string computing
    the size with ``std::char_traits<Char>::length``.
    \endrst
   */
  BasicStringRef(const Char *s)
    : data_(s), size_(std::char_traits<Char>::length(s)) {}

  /**
    \rst
    Constructs a string reference from a ``std::basic_string`` object.
    \endrst
   */
  template <typename Allocator>
  BasicStringRef(
      const std::basic_string<Char, std::char_traits<Char>, Allocator> &s)
  : data_(s.c_str()), size_(s.size()) {}

#if FMT_HAS_STRING_VIEW
  /**
    \rst
    Constructs a string reference from a ``std::basic_string_view`` object.
    \endrst
   */
  BasicStringRef(
      const std::basic_string_view<Char, std::char_traits<Char>> &s)
  : data_(s.data()), size_(s.size()) {}

  /**
   \rst
   Converts a string reference to an ``std::string_view`` object.
   \endrst
  */
  explicit operator std::basic_string_view<Char>() const FMT_NOEXCEPT {
    return std::basic_string_view<Char>(data_, size_);
  }
#endif
Philip Trettner's avatar
Philip Trettner committed
584

585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
  /**
    \rst
    Converts a string reference to an ``std::string`` object.
    \endrst
   */
  std::basic_string<Char> to_string() const {
    return std::basic_string<Char>(data_, size_);
  }

  /** Returns a pointer to the string data. */
  const Char *data() const { return data_; }

  /** Returns the string size. */
  std::size_t size() const { return size_; }

  // Lexicographically compare this string reference to other.
  int compare(BasicStringRef other) const {
    std::size_t size = size_ < other.size_ ? size_ : other.size_;
    int result = std::char_traits<Char>::compare(data_, other.data_, size);
    if (result == 0)
      result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
    return result;
  }

  friend bool operator==(BasicStringRef lhs, BasicStringRef rhs) {
    return lhs.compare(rhs) == 0;
  }
  friend bool operator!=(BasicStringRef lhs, BasicStringRef rhs) {
    return lhs.compare(rhs) != 0;
  }
  friend bool operator<(BasicStringRef lhs, BasicStringRef rhs) {
    return lhs.compare(rhs) < 0;
  }
  friend bool operator<=(BasicStringRef lhs, BasicStringRef rhs) {
    return lhs.compare(rhs) <= 0;
  }
  friend bool operator>(BasicStringRef lhs, BasicStringRef rhs) {
    return lhs.compare(rhs) > 0;
  }
  friend bool operator>=(BasicStringRef lhs, BasicStringRef rhs) {
    return lhs.compare(rhs) >= 0;
  }
Philip Trettner's avatar
Philip Trettner committed
627
628
629
630
631
632
633
634
};

typedef BasicStringRef<char> StringRef;
typedef BasicStringRef<wchar_t> WStringRef;

/**
  \rst
  A reference to a null terminated string. It can be constructed from a C
635
  string or ``std::basic_string``.
Philip Trettner's avatar
Philip Trettner committed
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657

  You can use one of the following typedefs for common character types:

  +-------------+--------------------------+
  | Type        | Definition               |
  +=============+==========================+
  | CStringRef  | BasicCStringRef<char>    |
  +-------------+--------------------------+
  | WCStringRef | BasicCStringRef<wchar_t> |
  +-------------+--------------------------+

  This class is most useful as a parameter type to allow passing
  different types of strings to a function, for example::

    template <typename... Args>
    std::string format(CStringRef format_str, const Args & ... args);

    format("{}", 42);
    format(std::string("{}"), 42);
  \endrst
 */
template <typename Char>
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
class BasicCStringRef {
 private:
  const Char *data_;

 public:
  /** Constructs a string reference object from a C string. */
  BasicCStringRef(const Char *s) : data_(s) {}

  /**
    \rst
    Constructs a string reference from a ``std::basic_string`` object.
    \endrst
   */
  template <typename Allocator>
  BasicCStringRef(
      const std::basic_string<Char, std::char_traits<Char>, Allocator> &s)
  : data_(s.c_str()) {}

  /** Returns the pointer to a C string. */
  const Char *c_str() const { return data_; }
Philip Trettner's avatar
Philip Trettner committed
678
679
680
681
682
};

typedef BasicCStringRef<char> CStringRef;
typedef BasicCStringRef<wchar_t> WCStringRef;

683
684
685
686
687
688
689
/** A formatting error such as invalid format string. */
class FormatError : public std::runtime_error {
 public:
  explicit FormatError(CStringRef message)
  : std::runtime_error(message.c_str()) {}
  FormatError(const FormatError &ferr) : std::runtime_error(ferr) {}
  FMT_API ~FormatError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE;
Philip Trettner's avatar
Philip Trettner committed
690
691
};

692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
namespace internal {

// MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T.
template <typename T>
struct MakeUnsigned { typedef T Type; };

#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \
  template <> \
  struct MakeUnsigned<T> { typedef U Type; }

FMT_SPECIALIZE_MAKE_UNSIGNED(char, unsigned char);
FMT_SPECIALIZE_MAKE_UNSIGNED(signed char, unsigned char);
FMT_SPECIALIZE_MAKE_UNSIGNED(short, unsigned short);
FMT_SPECIALIZE_MAKE_UNSIGNED(int, unsigned);
FMT_SPECIALIZE_MAKE_UNSIGNED(long, unsigned long);
FMT_SPECIALIZE_MAKE_UNSIGNED(LongLong, ULongLong);

// Casts nonnegative integer to unsigned.
template <typename Int>
inline typename MakeUnsigned<Int>::Type to_unsigned(Int value) {
  FMT_ASSERT(value >= 0, "negative value");
  return static_cast<typename MakeUnsigned<Int>::Type>(value);
}

Philip Trettner's avatar
Philip Trettner committed
716
717
// The number of characters to store in the MemoryBuffer object itself
// to avoid dynamic memory allocation.
718
enum { INLINE_BUFFER_SIZE = 500 };
Philip Trettner's avatar
Philip Trettner committed
719
720
721
722

#if FMT_SECURE_SCL
// Use checked iterator to avoid warnings on MSVC.
template <typename T>
723
724
inline stdext::checked_array_iterator<T*> make_ptr(T *ptr, std::size_t size) {
  return stdext::checked_array_iterator<T*>(ptr, size);
Philip Trettner's avatar
Philip Trettner committed
725
726
727
}
#else
template <typename T>
728
inline T *make_ptr(T *ptr, std::size_t) { return ptr; }
Philip Trettner's avatar
Philip Trettner committed
729
#endif
730
}  // namespace internal
Philip Trettner's avatar
Philip Trettner committed
731
732
733
734
735
736
737

/**
  \rst
  A buffer supporting a subset of ``std::vector``'s operations.
  \endrst
 */
template <typename T>
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
class Buffer {
 private:
  FMT_DISALLOW_COPY_AND_ASSIGN(Buffer);

 protected:
  T *ptr_;
  std::size_t size_;
  std::size_t capacity_;

  Buffer(T *ptr = FMT_NULL, std::size_t capacity = 0)
    : ptr_(ptr), size_(0), capacity_(capacity) {}

  /**
    \rst
    Increases the buffer capacity to hold at least *size* elements updating
    ``ptr_`` and ``capacity_``.
    \endrst
   */
  virtual void grow(std::size_t size) = 0;

 public:
  virtual ~Buffer() {}

  /** Returns the size of this buffer. */
  std::size_t size() const { return size_; }

  /** Returns the capacity of this buffer. */
  std::size_t capacity() const { return capacity_; }

  /**
    Resizes the buffer. If T is a POD type new elements may not be initialized.
   */
  void resize(std::size_t new_size) {
    if (new_size > capacity_)
      grow(new_size);
    size_ = new_size;
  }

  /**
    \rst
    Reserves space to store at least *capacity* elements.
    \endrst
   */
  void reserve(std::size_t capacity) {
    if (capacity > capacity_)
      grow(capacity);
  }

  void clear() FMT_NOEXCEPT { size_ = 0; }

  void push_back(const T &value) {
    if (size_ == capacity_)
      grow(size_ + 1);
    ptr_[size_++] = value;
  }

  /** Appends data to the end of the buffer. */
  template <typename U>
  void append(const U *begin, const U *end);

  T &operator[](std::size_t index) { return ptr_[index]; }
  const T &operator[](std::size_t index) const { return ptr_[index]; }
Philip Trettner's avatar
Philip Trettner committed
800
801
802
803
};

template <typename T>
template <typename U>
804
805
806
807
808
809
810
811
void Buffer<T>::append(const U *begin, const U *end) {
  FMT_ASSERT(end >= begin, "negative value");
  std::size_t new_size = size_ + static_cast<std::size_t>(end - begin);
  if (new_size > capacity_)
    grow(new_size);
  std::uninitialized_copy(begin, end,
                          internal::make_ptr(ptr_, capacity_) + size_);
  size_ = new_size;
Philip Trettner's avatar
Philip Trettner committed
812
813
}

814
namespace internal {
Philip Trettner's avatar
Philip Trettner committed
815

816
817
818
819
820
821
// A memory buffer for trivially copyable/constructible types with the first
// SIZE elements stored in the object itself.
template <typename T, std::size_t SIZE, typename Allocator = std::allocator<T> >
class MemoryBuffer : private Allocator, public Buffer<T> {
 private:
  T data_[SIZE];
Philip Trettner's avatar
Philip Trettner committed
822

823
824
825
826
  // Deallocate memory allocated by the buffer.
  void deallocate() {
    if (this->ptr_ != data_) Allocator::deallocate(this->ptr_, this->capacity_);
  }
Philip Trettner's avatar
Philip Trettner committed
827

828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
 protected:
  void grow(std::size_t size) FMT_OVERRIDE;

 public:
  explicit MemoryBuffer(const Allocator &alloc = Allocator())
      : Allocator(alloc), Buffer<T>(data_, SIZE) {}
  ~MemoryBuffer() FMT_OVERRIDE { deallocate(); }

#if FMT_USE_RVALUE_REFERENCES
 private:
  // Move data from other to this buffer.
  void move(MemoryBuffer &other) {
    Allocator &this_alloc = *this, &other_alloc = other;
    this_alloc = std::move(other_alloc);
    this->size_ = other.size_;
    this->capacity_ = other.capacity_;
    if (other.ptr_ == other.data_) {
      this->ptr_ = data_;
      std::uninitialized_copy(other.data_, other.data_ + this->size_,
                              make_ptr(data_, this->capacity_));
    } else {
      this->ptr_ = other.ptr_;
      // Set pointer to the inline array so that delete is not called
      // when deallocating.
      other.ptr_ = other.data_;
Philip Trettner's avatar
Philip Trettner committed
853
    }
854
855
856
857
858
859
860
861
862
863
864
865
866
  }

 public:
  MemoryBuffer(MemoryBuffer &&other) {
    move(other);
  }

  MemoryBuffer &operator=(MemoryBuffer &&other) {
    assert(this != &other);
    deallocate();
    move(other);
    return *this;
  }
Philip Trettner's avatar
Philip Trettner committed
867
868
#endif

869
870
  // Returns a copy of the allocator associated with this buffer.
  Allocator get_allocator() const { return *this; }
Philip Trettner's avatar
Philip Trettner committed
871
872
873
};

template <typename T, std::size_t SIZE, typename Allocator>
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size) {
  std::size_t new_capacity = this->capacity_ + this->capacity_ / 2;
  if (size > new_capacity)
      new_capacity = size;
#if FMT_USE_ALLOCATOR_TRAITS
  T *new_ptr =
      std::allocator_traits<Allocator>::allocate(*this, new_capacity, FMT_NULL);
#else
  T *new_ptr = this->allocate(new_capacity, FMT_NULL);
#endif
  // The following code doesn't throw, so the raw pointer above doesn't leak.
  std::uninitialized_copy(this->ptr_, this->ptr_ + this->size_,
                          make_ptr(new_ptr, new_capacity));
  std::size_t old_capacity = this->capacity_;
  T *old_ptr = this->ptr_;
  this->capacity_ = new_capacity;
  this->ptr_ = new_ptr;
  // deallocate may throw (at least in principle), but it doesn't matter since
  // the buffer already uses the new storage and will deallocate it in case
  // of exception.
  if (old_ptr != data_)
    Allocator::deallocate(old_ptr, old_capacity);
Philip Trettner's avatar
Philip Trettner committed
896
897
898
899
}

// A fixed-size buffer.
template <typename Char>
900
901
902
903
904
905
class FixedBuffer : public aion_fmt::Buffer<Char> {
 public:
  FixedBuffer(Char *array, std::size_t size) : aion_fmt::Buffer<Char>(array, size) {}

 protected:
  FMT_API void grow(std::size_t size) FMT_OVERRIDE;
Philip Trettner's avatar
Philip Trettner committed
906
907
908
};

template <typename Char>
909
910
class BasicCharTraits {
 public:
Philip Trettner's avatar
Philip Trettner committed
911
#if FMT_SECURE_SCL
912
  typedef stdext::checked_array_iterator<Char*> CharPtr;
Philip Trettner's avatar
Philip Trettner committed
913
#else
914
  typedef Char *CharPtr;
Philip Trettner's avatar
Philip Trettner committed
915
#endif
916
  static Char cast(int value) { return static_cast<Char>(value); }
Philip Trettner's avatar
Philip Trettner committed
917
918
919
920
921
922
};

template <typename Char>
class CharTraits;

template <>
923
924
925
926
927
928
929
930
931
932
933
934
class CharTraits<char> : public BasicCharTraits<char> {
 private:
  // Conversion from wchar_t to char is not allowed.
  static char convert(wchar_t);

 public:
  static char convert(char value) { return value; }

  // Formats a floating-point number.
  template <typename T>
  FMT_API static int format_float(char *buffer, std::size_t size,
      const char *format, unsigned width, int precision, T value);
Philip Trettner's avatar
Philip Trettner committed
935
936
};

937
938
939
940
941
942
943
944
945
#if FMT_USE_EXTERN_TEMPLATES
extern template int CharTraits<char>::format_float<double>
        (char *buffer, std::size_t size,
         const char* format, unsigned width, int precision, double value);
extern template int CharTraits<char>::format_float<long double>
        (char *buffer, std::size_t size,
         const char* format, unsigned width, int precision, long double value);
#endif

Philip Trettner's avatar
Philip Trettner committed
946
template <>
947
948
949
950
951
952
953
954
class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> {
 public:
  static wchar_t convert(char value) { return value; }
  static wchar_t convert(wchar_t value) { return value; }

  template <typename T>
  FMT_API static int format_float(wchar_t *buffer, std::size_t size,
      const wchar_t *format, unsigned width, int precision, T value);
Philip Trettner's avatar
Philip Trettner committed
955
956
};

957
958
959
960
961
962
963
964
965
#if FMT_USE_EXTERN_TEMPLATES
extern template int CharTraits<wchar_t>::format_float<double>
        (wchar_t *buffer, std::size_t size,
         const wchar_t* format, unsigned width, int precision, double value);
extern template int CharTraits<wchar_t>::format_float<long double>
        (wchar_t *buffer, std::size_t size,
         const wchar_t* format, unsigned width, int precision, long double value);
#endif

Philip Trettner's avatar
Philip Trettner committed
966
967
// Checks if a number is negative - used to avoid warnings.
template <bool IsSigned>
968
969
970
struct SignChecker {
  template <typename T>
  static bool is_negative(T value) { return value < 0; }
Philip Trettner's avatar
Philip Trettner committed
971
972
973
};

template <>
974
975
976
struct SignChecker<false> {
  template <typename T>
  static bool is_negative(T) { return false; }
Philip Trettner's avatar
Philip Trettner committed
977
978
979
980
981
};

// Returns true if value is negative, false otherwise.
// Same as (value < 0) but doesn't produce warnings if T is an unsigned type.
template <typename T>
982
983
inline bool is_negative(T value) {
  return SignChecker<std::numeric_limits<T>::is_signed>::is_negative(value);
Philip Trettner's avatar
Philip Trettner committed
984
985
986
987
}

// Selects uint32_t if FitsIn32Bits is true, uint64_t otherwise.
template <bool FitsIn32Bits>
988
struct TypeSelector { typedef uint32_t Type; };
Philip Trettner's avatar
Philip Trettner committed
989
990

template <>
991
struct TypeSelector<false> { typedef uint64_t Type; };
Philip Trettner's avatar
Philip Trettner committed
992
993

template <typename T>
994
995
996
997
998
struct IntTraits {
  // Smallest of uint32_t and uint64_t that is large enough to represent
  // all values of T.
  typedef typename
    TypeSelector<std::numeric_limits<T>::digits <= 32>::Type MainType;
Philip Trettner's avatar
Philip Trettner committed
999
1000
};