187ddb9a6Sgabime/*
28192c133SDamien Zammit Formatting library for C++
38192c133SDamien Zammit
48192c133SDamien Zammit Copyright (c) 2012 - 2016, Victor Zverovich
58192c133SDamien Zammit All rights reserved.
68192c133SDamien Zammit
78192c133SDamien Zammit Redistribution and use in source and binary forms, with or without
88192c133SDamien Zammit modification, are permitted provided that the following conditions are met:
98192c133SDamien Zammit
108192c133SDamien Zammit 1. Redistributions of source code must retain the above copyright notice, this
118192c133SDamien Zammit    list of conditions and the following disclaimer.
128192c133SDamien Zammit 2. Redistributions in binary form must reproduce the above copyright notice,
138192c133SDamien Zammit    this list of conditions and the following disclaimer in the documentation
148192c133SDamien Zammit    and/or other materials provided with the distribution.
158192c133SDamien Zammit
168192c133SDamien Zammit THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
178192c133SDamien Zammit ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
188192c133SDamien Zammit WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
198192c133SDamien Zammit DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
208192c133SDamien Zammit ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
218192c133SDamien Zammit (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
228192c133SDamien Zammit LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
238192c133SDamien Zammit ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
248192c133SDamien Zammit (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
258192c133SDamien Zammit SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
268192c133SDamien Zammit */
2787ddb9a6Sgabime
2887ddb9a6Sgabime#ifndef FMT_FORMAT_H_
2987ddb9a6Sgabime#define FMT_FORMAT_H_
3087ddb9a6Sgabime
3187ddb9a6Sgabime#include <cassert>
3287ddb9a6Sgabime#include <clocale>
3387ddb9a6Sgabime#include <cmath>
3487ddb9a6Sgabime#include <cstdio>
3587ddb9a6Sgabime#include <cstring>
3687ddb9a6Sgabime#include <limits>
3787ddb9a6Sgabime#include <memory>
3887ddb9a6Sgabime#include <stdexcept>
3987ddb9a6Sgabime#include <string>
4087ddb9a6Sgabime#include <vector>
41fced34e3Sgabime#include <utility>  // for std::pair
42fced34e3Sgabime
43fced34e3Sgabime// The fmt library version in the form major * 10000 + minor * 100 + patch.
44fced34e3Sgabime#define FMT_VERSION 40000
4587ddb9a6Sgabime
4687ddb9a6Sgabime#ifdef _SECURE_SCL
4787ddb9a6Sgabime# define FMT_SECURE_SCL _SECURE_SCL
4887ddb9a6Sgabime#else
4987ddb9a6Sgabime# define FMT_SECURE_SCL 0
5087ddb9a6Sgabime#endif
5187ddb9a6Sgabime
5287ddb9a6Sgabime#if FMT_SECURE_SCL
5387ddb9a6Sgabime# include <iterator>
5487ddb9a6Sgabime#endif
5587ddb9a6Sgabime
5687ddb9a6Sgabime#ifdef _MSC_VER
5787ddb9a6Sgabime# define FMT_MSC_VER _MSC_VER
5887ddb9a6Sgabime#else
5987ddb9a6Sgabime# define FMT_MSC_VER 0
6087ddb9a6Sgabime#endif
6187ddb9a6Sgabime
6287ddb9a6Sgabime#if FMT_MSC_VER && FMT_MSC_VER <= 1500
6387ddb9a6Sgabimetypedef unsigned __int32 uint32_t;
6487ddb9a6Sgabimetypedef unsigned __int64 uint64_t;
6587ddb9a6Sgabimetypedef __int64          intmax_t;
6687ddb9a6Sgabime#else
6787ddb9a6Sgabime#include <stdint.h>
6887ddb9a6Sgabime#endif
6987ddb9a6Sgabime
7087ddb9a6Sgabime#if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
7187ddb9a6Sgabime# ifdef FMT_EXPORT
7287ddb9a6Sgabime#  define FMT_API __declspec(dllexport)
7387ddb9a6Sgabime# elif defined(FMT_SHARED)
7487ddb9a6Sgabime#  define FMT_API __declspec(dllimport)
7587ddb9a6Sgabime# endif
7687ddb9a6Sgabime#endif
7787ddb9a6Sgabime#ifndef FMT_API
7887ddb9a6Sgabime# define FMT_API
7987ddb9a6Sgabime#endif
8087ddb9a6Sgabime
8187ddb9a6Sgabime#ifdef __GNUC__
8287ddb9a6Sgabime# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
8387ddb9a6Sgabime# define FMT_GCC_EXTENSION __extension__
8487ddb9a6Sgabime# if FMT_GCC_VERSION >= 406
8587ddb9a6Sgabime#  pragma GCC diagnostic push
8687ddb9a6Sgabime// Disable the warning about "long long" which is sometimes reported even
8787ddb9a6Sgabime// when using __extension__.
8887ddb9a6Sgabime#  pragma GCC diagnostic ignored "-Wlong-long"
8987ddb9a6Sgabime// Disable the warning about declaration shadowing because it affects too
9087ddb9a6Sgabime// many valid cases.
9187ddb9a6Sgabime#  pragma GCC diagnostic ignored "-Wshadow"
9287ddb9a6Sgabime// Disable the warning about implicit conversions that may change the sign of
9387ddb9a6Sgabime// an integer; silencing it otherwise would require many explicit casts.
9487ddb9a6Sgabime#  pragma GCC diagnostic ignored "-Wsign-conversion"
9587ddb9a6Sgabime# endif
9687ddb9a6Sgabime# if __cplusplus >= 201103L || defined __GXX_EXPERIMENTAL_CXX0X__
9787ddb9a6Sgabime#  define FMT_HAS_GXX_CXX11 1
9887ddb9a6Sgabime# endif
9987ddb9a6Sgabime#else
10087ddb9a6Sgabime# define FMT_GCC_EXTENSION
10187ddb9a6Sgabime#endif
10287ddb9a6Sgabime
10387ddb9a6Sgabime#if defined(__INTEL_COMPILER)
10487ddb9a6Sgabime# define FMT_ICC_VERSION __INTEL_COMPILER
10587ddb9a6Sgabime#elif defined(__ICL)
10687ddb9a6Sgabime# define FMT_ICC_VERSION __ICL
10787ddb9a6Sgabime#endif
10887ddb9a6Sgabime
10987ddb9a6Sgabime#if defined(__clang__) && !defined(FMT_ICC_VERSION)
110fced34e3Sgabime# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
11187ddb9a6Sgabime# pragma clang diagnostic push
11287ddb9a6Sgabime# pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
11387ddb9a6Sgabime# pragma clang diagnostic ignored "-Wpadded"
11487ddb9a6Sgabime#endif
11587ddb9a6Sgabime
11687ddb9a6Sgabime#ifdef __GNUC_LIBSTD__
11787ddb9a6Sgabime# define FMT_GNUC_LIBSTD_VERSION (__GNUC_LIBSTD__ * 100 + __GNUC_LIBSTD_MINOR__)
11887ddb9a6Sgabime#endif
11987ddb9a6Sgabime
12087ddb9a6Sgabime#ifdef __has_feature
12187ddb9a6Sgabime# define FMT_HAS_FEATURE(x) __has_feature(x)
12287ddb9a6Sgabime#else
12387ddb9a6Sgabime# define FMT_HAS_FEATURE(x) 0
12487ddb9a6Sgabime#endif
12587ddb9a6Sgabime
12687ddb9a6Sgabime#ifdef __has_builtin
12787ddb9a6Sgabime# define FMT_HAS_BUILTIN(x) __has_builtin(x)
12887ddb9a6Sgabime#else
12987ddb9a6Sgabime# define FMT_HAS_BUILTIN(x) 0
13087ddb9a6Sgabime#endif
13187ddb9a6Sgabime
13287ddb9a6Sgabime#ifdef __has_cpp_attribute
13387ddb9a6Sgabime# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
13487ddb9a6Sgabime#else
13587ddb9a6Sgabime# define FMT_HAS_CPP_ATTRIBUTE(x) 0
13687ddb9a6Sgabime#endif
13787ddb9a6Sgabime
13887ddb9a6Sgabime#ifndef FMT_USE_VARIADIC_TEMPLATES
13987ddb9a6Sgabime// Variadic templates are available in GCC since version 4.4
14087ddb9a6Sgabime// (http://gcc.gnu.org/projects/cxx0x.html) and in Visual C++
14187ddb9a6Sgabime// since version 2013.
14287ddb9a6Sgabime# define FMT_USE_VARIADIC_TEMPLATES \
14387ddb9a6Sgabime   (FMT_HAS_FEATURE(cxx_variadic_templates) || \
14487ddb9a6Sgabime       (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800)
14587ddb9a6Sgabime#endif
14687ddb9a6Sgabime
14787ddb9a6Sgabime#ifndef FMT_USE_RVALUE_REFERENCES
14887ddb9a6Sgabime// Don't use rvalue references when compiling with clang and an old libstdc++
14987ddb9a6Sgabime// as the latter doesn't provide std::move.
15087ddb9a6Sgabime# if defined(FMT_GNUC_LIBSTD_VERSION) && FMT_GNUC_LIBSTD_VERSION <= 402
15187ddb9a6Sgabime#  define FMT_USE_RVALUE_REFERENCES 0
15287ddb9a6Sgabime# else
15387ddb9a6Sgabime#  define FMT_USE_RVALUE_REFERENCES \
15487ddb9a6Sgabime    (FMT_HAS_FEATURE(cxx_rvalue_references) || \
15587ddb9a6Sgabime        (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1600)
15687ddb9a6Sgabime# endif
15787ddb9a6Sgabime#endif
15887ddb9a6Sgabime
15987ddb9a6Sgabime// Check if exceptions are disabled.
16087ddb9a6Sgabime#if defined(__GNUC__) && !defined(__EXCEPTIONS)
16187ddb9a6Sgabime# define FMT_EXCEPTIONS 0
16287ddb9a6Sgabime#endif
16387ddb9a6Sgabime#if FMT_MSC_VER && !_HAS_EXCEPTIONS
16487ddb9a6Sgabime# define FMT_EXCEPTIONS 0
16587ddb9a6Sgabime#endif
16687ddb9a6Sgabime#ifndef FMT_EXCEPTIONS
16787ddb9a6Sgabime# define FMT_EXCEPTIONS 1
16887ddb9a6Sgabime#endif
16987ddb9a6Sgabime
17087ddb9a6Sgabime#ifndef FMT_THROW
17187ddb9a6Sgabime# if FMT_EXCEPTIONS
17287ddb9a6Sgabime#  define FMT_THROW(x) throw x
17387ddb9a6Sgabime# else
17487ddb9a6Sgabime#  define FMT_THROW(x) assert(false)
17587ddb9a6Sgabime# endif
17687ddb9a6Sgabime#endif
17787ddb9a6Sgabime
17887ddb9a6Sgabime// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature).
17987ddb9a6Sgabime#ifndef FMT_USE_NOEXCEPT
18087ddb9a6Sgabime# define FMT_USE_NOEXCEPT 0
18187ddb9a6Sgabime#endif
18287ddb9a6Sgabime
183fced34e3Sgabime#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
1848192c133SDamien Zammit    (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
1858192c133SDamien Zammit    FMT_MSC_VER >= 1900
186fced34e3Sgabime# define FMT_DETECTED_NOEXCEPT noexcept
187fced34e3Sgabime#else
188fced34e3Sgabime# define FMT_DETECTED_NOEXCEPT throw()
189fced34e3Sgabime#endif
190fced34e3Sgabime
191fced34e3Sgabime#ifndef FMT_NOEXCEPT
192fced34e3Sgabime# if FMT_EXCEPTIONS
193fced34e3Sgabime#  define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT
19487ddb9a6Sgabime# else
19587ddb9a6Sgabime#  define FMT_NOEXCEPT
19687ddb9a6Sgabime# endif
19787ddb9a6Sgabime#endif
19887ddb9a6Sgabime
199fced34e3Sgabime// This is needed because GCC still uses throw() in its headers when exceptions
200fced34e3Sgabime// are disabled.
201fced34e3Sgabime#if FMT_GCC_VERSION
202fced34e3Sgabime# define FMT_DTOR_NOEXCEPT FMT_DETECTED_NOEXCEPT
203fced34e3Sgabime#else
204fced34e3Sgabime# define FMT_DTOR_NOEXCEPT FMT_NOEXCEPT
205fced34e3Sgabime#endif
206fced34e3Sgabime
20787ddb9a6Sgabime#ifndef FMT_OVERRIDE
208fced34e3Sgabime# if (defined(FMT_USE_OVERRIDE) && FMT_USE_OVERRIDE) || FMT_HAS_FEATURE(cxx_override) || \
20987ddb9a6Sgabime   (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
21087ddb9a6Sgabime   FMT_MSC_VER >= 1900
21187ddb9a6Sgabime#  define FMT_OVERRIDE override
21287ddb9a6Sgabime# else
21387ddb9a6Sgabime#  define FMT_OVERRIDE
21487ddb9a6Sgabime# endif
21587ddb9a6Sgabime#endif
21687ddb9a6Sgabime
217fced34e3Sgabime#ifndef FMT_NULL
218fced34e3Sgabime# if FMT_HAS_FEATURE(cxx_nullptr) || \
219fced34e3Sgabime   (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
220fced34e3Sgabime   FMT_MSC_VER >= 1600
221fced34e3Sgabime#  define FMT_NULL nullptr
222fced34e3Sgabime# else
223fced34e3Sgabime#  define FMT_NULL NULL
224fced34e3Sgabime# endif
225fced34e3Sgabime#endif
22687ddb9a6Sgabime
22787ddb9a6Sgabime// A macro to disallow the copy constructor and operator= functions
22887ddb9a6Sgabime// This should be used in the private: declarations for a class
22987ddb9a6Sgabime#ifndef FMT_USE_DELETED_FUNCTIONS
23087ddb9a6Sgabime# define FMT_USE_DELETED_FUNCTIONS 0
23187ddb9a6Sgabime#endif
23287ddb9a6Sgabime
23387ddb9a6Sgabime#if FMT_USE_DELETED_FUNCTIONS || FMT_HAS_FEATURE(cxx_deleted_functions) || \
23487ddb9a6Sgabime  (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800
23587ddb9a6Sgabime# define FMT_DELETED_OR_UNDEFINED  = delete
23687ddb9a6Sgabime# define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \
23787ddb9a6Sgabime    TypeName(const TypeName&) = delete; \
23887ddb9a6Sgabime    TypeName& operator=(const TypeName&) = delete
23987ddb9a6Sgabime#else
24087ddb9a6Sgabime# define FMT_DELETED_OR_UNDEFINED
24187ddb9a6Sgabime# define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \
24287ddb9a6Sgabime    TypeName(const TypeName&); \
24387ddb9a6Sgabime    TypeName& operator=(const TypeName&)
24487ddb9a6Sgabime#endif
24587ddb9a6Sgabime
246fced34e3Sgabime#ifndef FMT_USE_DEFAULTED_FUNCTIONS
247fced34e3Sgabime# define FMT_USE_DEFAULTED_FUNCTIONS 0
248fced34e3Sgabime#endif
249fced34e3Sgabime
250fced34e3Sgabime#ifndef FMT_DEFAULTED_COPY_CTOR
251fced34e3Sgabime# if FMT_USE_DEFAULTED_FUNCTIONS || FMT_HAS_FEATURE(cxx_defaulted_functions) || \
252fced34e3Sgabime   (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800
253fced34e3Sgabime#  define FMT_DEFAULTED_COPY_CTOR(TypeName) \
254fced34e3Sgabime    TypeName(const TypeName&) = default;
255fced34e3Sgabime# else
256fced34e3Sgabime#  define FMT_DEFAULTED_COPY_CTOR(TypeName)
257fced34e3Sgabime# endif
258fced34e3Sgabime#endif
259fced34e3Sgabime
26087ddb9a6Sgabime#ifndef FMT_USE_USER_DEFINED_LITERALS
26187ddb9a6Sgabime// All compilers which support UDLs also support variadic templates. This
26287ddb9a6Sgabime// makes the fmt::literals implementation easier. However, an explicit check
26387ddb9a6Sgabime// for variadic templates is added here just in case.
26487ddb9a6Sgabime// For Intel's compiler both it and the system gcc/msc must support UDLs.
26587ddb9a6Sgabime# define FMT_USE_USER_DEFINED_LITERALS \
26687ddb9a6Sgabime   FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \
26787ddb9a6Sgabime   (FMT_HAS_FEATURE(cxx_user_literals) || \
26887ddb9a6Sgabime     (FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900) && \
26987ddb9a6Sgabime   (!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500)
27087ddb9a6Sgabime#endif
27187ddb9a6Sgabime
272fced34e3Sgabime#ifndef FMT_USE_EXTERN_TEMPLATES
273fced34e3Sgabime# define FMT_USE_EXTERN_TEMPLATES \
274fced34e3Sgabime    (FMT_CLANG_VERSION >= 209 || (FMT_GCC_VERSION >= 303 && FMT_HAS_GXX_CXX11))
275fced34e3Sgabime#endif
276fced34e3Sgabime
277fced34e3Sgabime#ifdef FMT_HEADER_ONLY
278fced34e3Sgabime// If header only do not use extern templates.
279fced34e3Sgabime# undef FMT_USE_EXTERN_TEMPLATES
280fced34e3Sgabime# define FMT_USE_EXTERN_TEMPLATES 0
281fced34e3Sgabime#endif
282fced34e3Sgabime
28387ddb9a6Sgabime#ifndef FMT_ASSERT
28487ddb9a6Sgabime# define FMT_ASSERT(condition, message) assert((condition) && message)
28587ddb9a6Sgabime#endif
28687ddb9a6Sgabime
287fced34e3Sgabime// __builtin_clz is broken in clang with Microsoft CodeGen:
288fced34e3Sgabime// https://github.com/fmtlib/fmt/issues/519
289fced34e3Sgabime#ifndef _MSC_VER
290fced34e3Sgabime# if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz)
291fced34e3Sgabime#  define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
292fced34e3Sgabime# endif
29387ddb9a6Sgabime
294fced34e3Sgabime# if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll)
295fced34e3Sgabime#  define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
296fced34e3Sgabime# endif
29787ddb9a6Sgabime#endif
29887ddb9a6Sgabime
29987ddb9a6Sgabime// Some compilers masquerade as both MSVC and GCC-likes or
30087ddb9a6Sgabime// otherwise support __builtin_clz and __builtin_clzll, so
30187ddb9a6Sgabime// only define FMT_BUILTIN_CLZ using the MSVC intrinsics
30287ddb9a6Sgabime// if the clz and clzll builtins are not available.
303fced34e3Sgabime#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && !defined(_MANAGED)
30487ddb9a6Sgabime# include <intrin.h>  // _BitScanReverse, _BitScanReverse64
30587ddb9a6Sgabime
306fced34e3Sgabimenamespace fmt {
307fced34e3Sgabimenamespace internal {
30887ddb9a6Sgabime# pragma intrinsic(_BitScanReverse)
309fced34e3Sgabimeinline uint32_t clz(uint32_t x) {
310fced34e3Sgabime  unsigned long r = 0;
311fced34e3Sgabime  _BitScanReverse(&r, x);
312fced34e3Sgabime
313fced34e3Sgabime  assert(x != 0);
314fced34e3Sgabime  // Static analysis complains about using uninitialized data
315fced34e3Sgabime  // "r", but the only way that can happen is if "x" is 0,
316fced34e3Sgabime  // which the callers guarantee to not happen.
31787ddb9a6Sgabime# pragma warning(suppress: 6102)
318fced34e3Sgabime  return 31 - r;
319bd6fe569Sgabime}
32087ddb9a6Sgabime# define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n)
32187ddb9a6Sgabime
32287ddb9a6Sgabime# ifdef _WIN64
32387ddb9a6Sgabime#  pragma intrinsic(_BitScanReverse64)
32487ddb9a6Sgabime# endif
32587ddb9a6Sgabime
326fced34e3Sgabimeinline uint32_t clzll(uint64_t x) {
327fced34e3Sgabime  unsigned long r = 0;
32887ddb9a6Sgabime# ifdef _WIN64
329fced34e3Sgabime  _BitScanReverse64(&r, x);
33087ddb9a6Sgabime# else
331fced34e3Sgabime  // Scan the high 32 bits.
332fced34e3Sgabime  if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
333fced34e3Sgabime    return 63 - (r + 32);
33487ddb9a6Sgabime
335fced34e3Sgabime  // Scan the low 32 bits.
336fced34e3Sgabime  _BitScanReverse(&r, static_cast<uint32_t>(x));
33787ddb9a6Sgabime# endif
33887ddb9a6Sgabime
339fced34e3Sgabime  assert(x != 0);
340fced34e3Sgabime  // Static analysis complains about using uninitialized data
341fced34e3Sgabime  // "r", but the only way that can happen is if "x" is 0,
342fced34e3Sgabime  // which the callers guarantee to not happen.
34387ddb9a6Sgabime# pragma warning(suppress: 6102)
344fced34e3Sgabime  return 63 - r;
345bd6fe569Sgabime}
34687ddb9a6Sgabime# define FMT_BUILTIN_CLZLL(n) fmt::internal::clzll(n)
347bd6fe569Sgabime}
34887ddb9a6Sgabime}
34987ddb9a6Sgabime#endif
35087ddb9a6Sgabime
351fced34e3Sgabimenamespace fmt {
352fced34e3Sgabimenamespace internal {
353fced34e3Sgabimestruct DummyInt {
354fced34e3Sgabime  int data[2];
355fced34e3Sgabime  operator int() const { return 0; }
356bd6fe569Sgabime};
357bd6fe569Sgabimetypedef std::numeric_limits<fmt::internal::DummyInt> FPUtil;
358bd6fe569Sgabime
359bd6fe569Sgabime// Dummy implementations of system functions such as signbit and ecvt called
360bd6fe569Sgabime// if the latter are not available.
361fced34e3Sgabimeinline DummyInt signbit(...) { return DummyInt(); }
362fced34e3Sgabimeinline DummyInt _ecvt_s(...) { return DummyInt(); }
363fced34e3Sgabimeinline DummyInt isinf(...) { return DummyInt(); }
364fced34e3Sgabimeinline DummyInt _finite(...) { return DummyInt(); }
365fced34e3Sgabimeinline DummyInt isnan(...) { return DummyInt(); }
366fced34e3Sgabimeinline DummyInt _isnan(...) { return DummyInt(); }
367bd6fe569Sgabime
368bd6fe569Sgabime// A helper function to suppress bogus "conditional expression is constant"
369bd6fe569Sgabime// warnings.
370bd6fe569Sgabimetemplate <typename T>
371fced34e3Sgabimeinline T const_check(T value) { return value; }
372bd6fe569Sgabime}
37387ddb9a6Sgabime}  // namespace fmt
37487ddb9a6Sgabime
375fced34e3Sgabimenamespace std {
376bd6fe569Sgabime// Standard permits specialization of std::numeric_limits. This specialization
377bd6fe569Sgabime// is used to resolve ambiguity between isinf and std::isinf in glibc:
378bd6fe569Sgabime// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48891
379bd6fe569Sgabime// and the same for isnan and signbit.
380bd6fe569Sgabimetemplate <>
3818192c133SDamien Zammitclass numeric_limits<fmt::internal::DummyInt> :
382fced34e3Sgabime    public std::numeric_limits<int> {
383fced34e3Sgabime public:
384fced34e3Sgabime  // Portable version of isinf.
385fced34e3Sgabime  template <typename T>
386fced34e3Sgabime  static bool isinfinity(T x) {
387fced34e3Sgabime    using namespace fmt::internal;
388fced34e3Sgabime    // The resolution "priority" is:
389fced34e3Sgabime    // isinf macro > std::isinf > ::isinf > fmt::internal::isinf
390fced34e3Sgabime    if (const_check(sizeof(isinf(x)) == sizeof(bool) ||
391fced34e3Sgabime                    sizeof(isinf(x)) == sizeof(int))) {
392fced34e3Sgabime      return isinf(x) != 0;
393fced34e3Sgabime    }
394fced34e3Sgabime    return !_finite(static_cast<double>(x));
395fced34e3Sgabime  }
396bd6fe569Sgabime
397fced34e3Sgabime  // Portable version of isnan.
398fced34e3Sgabime  template <typename T>
399fced34e3Sgabime  static bool isnotanumber(T x) {
400fced34e3Sgabime    using namespace fmt::internal;
401fced34e3Sgabime    if (const_check(sizeof(isnan(x)) == sizeof(bool) ||
402fced34e3Sgabime                    sizeof(isnan(x)) == sizeof(int))) {
403fced34e3Sgabime      return isnan(x) != 0;
404bd6fe569Sgabime    }
405fced34e3Sgabime    return _isnan(static_cast<double>(x)) != 0;
406fced34e3Sgabime  }
407bd6fe569Sgabime
408fced34e3Sgabime  // Portable version of signbit.
409fced34e3Sgabime  static bool isnegative(double x) {
410fced34e3Sgabime    using namespace fmt::internal;
411fced34e3Sgabime    if (const_check(sizeof(signbit(x)) == sizeof(bool) ||
412fced34e3Sgabime                    sizeof(signbit(x)) == sizeof(int))) {
413fced34e3Sgabime      return signbit(x) != 0;
414fced34e3Sgabime    }
415fced34e3Sgabime    if (x < 0) return true;
416fced34e3Sgabime    if (!isnotanumber(x)) return false;
417fced34e3Sgabime    int dec = 0, sign = 0;
418fced34e3Sgabime    char buffer[2];  // The buffer size must be >= 2 or _ecvt_s will fail.
419fced34e3Sgabime    _ecvt_s(buffer, sizeof(buffer), x, 0, &dec, &sign);
420fced34e3Sgabime    return sign != 0;
421fced34e3Sgabime  }
422bd6fe569Sgabime};
42387ddb9a6Sgabime}  // namespace std
42487ddb9a6Sgabime
425fced34e3Sgabimenamespace fmt {
42687ddb9a6Sgabime
427bd6fe569Sgabime// Fix the warning about long long on older versions of GCC
428bd6fe569Sgabime// that don't support the diagnostic pragma.
429bd6fe569SgabimeFMT_GCC_EXTENSION typedef long long LongLong;
430bd6fe569SgabimeFMT_GCC_EXTENSION typedef unsigned long long ULongLong;
43187ddb9a6Sgabime
43287ddb9a6Sgabime#if FMT_USE_RVALUE_REFERENCES
433bd6fe569Sgabimeusing std::move;
43487ddb9a6Sgabime#endif
43587ddb9a6Sgabime
436bd6fe569Sgabimetemplate <typename Char>
437bd6fe569Sgabimeclass BasicWriter;
438bd6fe569Sgabime
439bd6fe569Sgabimetypedef BasicWriter<char> Writer;
440bd6fe569Sgabimetypedef BasicWriter<wchar_t> WWriter;
441bd6fe569Sgabime
442bd6fe569Sgabimetemplate <typename Char>
443bd6fe569Sgabimeclass ArgFormatter;
444bd6fe569Sgabime
445fced34e3Sgabimestruct FormatSpec;
446fced34e3Sgabime
447fced34e3Sgabimetemplate <typename Impl, typename Char, typename Spec = fmt::FormatSpec>
448fced34e3Sgabimeclass BasicPrintfArgFormatter;
449fced34e3Sgabime
450bd6fe569Sgabimetemplate <typename CharType,
4512d873785Sgabime          typename ArgFormatter = fmt::ArgFormatter<CharType> >
452bd6fe569Sgabimeclass BasicFormatter;
453bd6fe569Sgabime
454bd6fe569Sgabime/**
4558192c133SDamien Zammit  \rst
456fced34e3Sgabime  A string reference. It can be constructed from a C string or
457fced34e3Sgabime  ``std::basic_string``.
458bd6fe569Sgabime
4598192c133SDamien Zammit  You can use one of the following typedefs for common character types:
460bd6fe569Sgabime
4618192c133SDamien Zammit  +------------+-------------------------+
4628192c133SDamien Zammit  | Type       | Definition              |
4638192c133SDamien Zammit  +============+=========================+
4648192c133SDamien Zammit  | StringRef  | BasicStringRef<char>    |
4658192c133SDamien Zammit  +------------+-------------------------+
4668192c133SDamien Zammit  | WStringRef | BasicStringRef<wchar_t> |
4678192c133SDamien Zammit  +------------+-------------------------+
468bd6fe569Sgabime
4698192c133SDamien Zammit  This class is most useful as a parameter type to allow passing
4708192c133SDamien Zammit  different types of strings to a function, for example::
471bd6fe569Sgabime
4728192c133SDamien Zammit    template <typename... Args>
4738192c133SDamien Zammit    std::string format(StringRef format_str, const Args & ... args);
474bd6fe569Sgabime
4758192c133SDamien Zammit    format("{}", 42);
4768192c133SDamien Zammit    format(std::string("{}"), 42);
4778192c133SDamien Zammit  \endrst
4788192c133SDamien Zammit */
479bd6fe569Sgabimetemplate <typename Char>
480fced34e3Sgabimeclass BasicStringRef {
481fced34e3Sgabime private:
482fced34e3Sgabime  const Char *data_;
483fced34e3Sgabime  std::size_t size_;
484fced34e3Sgabime
485fced34e3Sgabime public:
486fced34e3Sgabime  /** Constructs a string reference object from a C string and a size. */
487fced34e3Sgabime  BasicStringRef(const Char *s, std::size_t size) : data_(s), size_(size) {}
488fced34e3Sgabime
489fced34e3Sgabime  /**
490fced34e3Sgabime    \rst
491fced34e3Sgabime    Constructs a string reference object from a C string computing
492fced34e3Sgabime    the size with ``std::char_traits<Char>::length``.
493fced34e3Sgabime    \endrst
494fced34e3Sgabime   */
495fced34e3Sgabime  BasicStringRef(const Char *s)
496fced34e3Sgabime    : data_(s), size_(std::char_traits<Char>::length(s)) {}
497fced34e3Sgabime
498fced34e3Sgabime  /**
499fced34e3Sgabime    \rst
500fced34e3Sgabime    Constructs a string reference from a ``std::basic_string`` object.
501fced34e3Sgabime    \endrst
502fced34e3Sgabime   */
503fced34e3Sgabime  template <typename Allocator>
504fced34e3Sgabime  BasicStringRef(
505fced34e3Sgabime      const std::basic_string<Char, std::char_traits<Char>, Allocator> &s)
506fced34e3Sgabime  : data_(s.c_str()), size_(s.size()) {}
507fced34e3Sgabime
508fced34e3Sgabime  /**
509fced34e3Sgabime    \rst
510fced34e3Sgabime    Converts a string reference to an ``std::string`` object.
511fced34e3Sgabime    \endrst
512fced34e3Sgabime   */
513fced34e3Sgabime  std::basic_string<Char> to_string() const {
514fced34e3Sgabime    return std::basic_string<Char>(data_, size_);
515fced34e3Sgabime  }
516bd6fe569Sgabime
517fced34e3Sgabime  /** Returns a pointer to the string data. */
518fced34e3Sgabime  const Char *data() const { return data_; }
519bd6fe569Sgabime
520fced34e3Sgabime  /** Returns the string size. */
521fced34e3Sgabime  std::size_t size() const { return size_; }
522bd6fe569Sgabime
523fced34e3Sgabime  // Lexicographically compare this string reference to other.
524fced34e3Sgabime  int compare(BasicStringRef other) const {
525fced34e3Sgabime    std::size_t size = size_ < other.size_ ? size_ : other.size_;
526fced34e3Sgabime    int result = std::char_traits<Char>::compare(data_, other.data_, size);
527fced34e3Sgabime    if (result == 0)
528fced34e3Sgabime      result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
529fced34e3Sgabime    return result;
530fced34e3Sgabime  }
5310c276beaSgabime
532fced34e3Sgabime  friend bool operator==(BasicStringRef lhs, BasicStringRef rhs) {
533fced34e3Sgabime    return lhs.compare(rhs) == 0;
534fced34e3Sgabime  }
535fced34e3Sgabime  friend bool operator!=(BasicStringRef lhs, BasicStringRef rhs) {
536fced34e3Sgabime    return lhs.compare(rhs) != 0;
537fced34e3Sgabime  }
538fced34e3Sgabime  friend bool operator<(BasicStringRef lhs, BasicStringRef rhs) {
539fced34e3Sgabime    return lhs.compare(rhs) < 0;
540fced34e3Sgabime  }
541fced34e3Sgabime  friend bool operator<=(BasicStringRef lhs, BasicStringRef rhs) {
542fced34e3Sgabime    return lhs.compare(rhs) <= 0;
543fced34e3Sgabime  }
544fced34e3Sgabime  friend bool operator>(BasicStringRef lhs, BasicStringRef rhs) {
545fced34e3Sgabime    return lhs.compare(rhs) > 0;
546fced34e3Sgabime  }
547fced34e3Sgabime  friend bool operator>=(BasicStringRef lhs, BasicStringRef rhs) {
548fced34e3Sgabime    return lhs.compare(rhs) >= 0;
549fced34e3Sgabime  }
550bd6fe569Sgabime};
551bd6fe569Sgabime
552bd6fe569Sgabimetypedef BasicStringRef<char> StringRef;
553bd6fe569Sgabimetypedef BasicStringRef<wchar_t> WStringRef;
554bd6fe569Sgabime
555bd6fe569Sgabime/**
5568192c133SDamien Zammit  \rst
5578192c133SDamien Zammit  A reference to a null terminated string. It can be constructed from a C
558fced34e3Sgabime  string or ``std::basic_string``.
559bd6fe569Sgabime
5608192c133SDamien Zammit  You can use one of the following typedefs for common character types:
561bd6fe569Sgabime
5628192c133SDamien Zammit  +-------------+--------------------------+
5638192c133SDamien Zammit  | Type        | Definition               |
5648192c133SDamien Zammit  +=============+==========================+
5658192c133SDamien Zammit  | CStringRef  | BasicCStringRef<char>    |
5668192c133SDamien Zammit  +-------------+--------------------------+
5678192c133SDamien Zammit  | WCStringRef | BasicCStringRef<wchar_t> |
5688192c133SDamien Zammit  +-------------+--------------------------+
569bd6fe569Sgabime
5708192c133SDamien Zammit  This class is most useful as a parameter type to allow passing
5718192c133SDamien Zammit  different types of strings to a function, for example::
572bd6fe569Sgabime
5738192c133SDamien Zammit    template <typename... Args>
5748192c133SDamien Zammit    std::string format(CStringRef format_str, const Args & ... args);
575bd6fe569Sgabime
5768192c133SDamien Zammit    format("{}", 42);
5778192c133SDamien Zammit    format(std::string("{}"), 42);
5788192c133SDamien Zammit  \endrst
5798192c133SDamien Zammit */
580bd6fe569Sgabimetemplate <typename Char>
581fced34e3Sgabimeclass BasicCStringRef {
582fced34e3Sgabime private:
583fced34e3Sgabime  const Char *data_;
584bd6fe569Sgabime
585fced34e3Sgabime public:
586fced34e3Sgabime  /** Constructs a string reference object from a C string. */
587fced34e3Sgabime  BasicCStringRef(const Char *s) : data_(s) {}
588fced34e3Sgabime
589fced34e3Sgabime  /**
590fced34e3Sgabime    \rst
591fced34e3Sgabime    Constructs a string reference from a ``std::basic_string`` object.
592fced34e3Sgabime    \endrst
593fced34e3Sgabime   */
594fced34e3Sgabime  template <typename Allocator>
595fced34e3Sgabime  BasicCStringRef(
596fced34e3Sgabime      const std::basic_string<Char, std::char_traits<Char>, Allocator> &s)
597fced34e3Sgabime  : data_(s.c_str()) {}
598fced34e3Sgabime
599fced34e3Sgabime  /** Returns the pointer to a C string. */
600fced34e3Sgabime  const Char *c_str() const { return data_; }
601bd6fe569Sgabime};
602bd6fe569Sgabime
603bd6fe569Sgabimetypedef BasicCStringRef<char> CStringRef;
604bd6fe569Sgabimetypedef BasicCStringRef<wchar_t> WCStringRef;
605bd6fe569Sgabime
606bd6fe569Sgabime/** A formatting error such as invalid format string. */
607fced34e3Sgabimeclass FormatError : public std::runtime_error {
608fced34e3Sgabime public:
609fced34e3Sgabime  explicit FormatError(CStringRef message)
610fced34e3Sgabime  : std::runtime_error(message.c_str()) {}
611fced34e3Sgabime  FormatError(const FormatError &ferr) : std::runtime_error(ferr) {}
612fced34e3Sgabime  FMT_API ~FormatError() FMT_DTOR_NOEXCEPT;
613bd6fe569Sgabime};
614bd6fe569Sgabime
615fced34e3Sgabimenamespace internal {
616bd6fe569Sgabime
617bd6fe569Sgabime// MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T.
618bd6fe569Sgabimetemplate <typename T>
619fced34e3Sgabimestruct MakeUnsigned { typedef T Type; };
62087ddb9a6Sgabime
62187ddb9a6Sgabime#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \
62287ddb9a6Sgabime  template <> \
62387ddb9a6Sgabime  struct MakeUnsigned<T> { typedef U Type; }
62487ddb9a6Sgabime
625bd6fe569SgabimeFMT_SPECIALIZE_MAKE_UNSIGNED(char, unsigned char);
626bd6fe569SgabimeFMT_SPECIALIZE_MAKE_UNSIGNED(signed char, unsigned char);
627bd6fe569SgabimeFMT_SPECIALIZE_MAKE_UNSIGNED(short, unsigned short);
628bd6fe569SgabimeFMT_SPECIALIZE_MAKE_UNSIGNED(int, unsigned);
629bd6fe569SgabimeFMT_SPECIALIZE_MAKE_UNSIGNED(long, unsigned long);
630bd6fe569SgabimeFMT_SPECIALIZE_MAKE_UNSIGNED(LongLong, ULongLong);
631bd6fe569Sgabime
632bd6fe569Sgabime// Casts nonnegative integer to unsigned.
633bd6fe569Sgabimetemplate <typename Int>
634fced34e3Sgabimeinline typename MakeUnsigned<Int>::Type to_unsigned(Int value) {
635fced34e3Sgabime  FMT_ASSERT(value >= 0, "negative value");
636fced34e3Sgabime  return static_cast<typename MakeUnsigned<Int>::Type>(value);
637bd6fe569Sgabime}
638bd6fe569Sgabime
639bd6fe569Sgabime// The number of characters to store in the MemoryBuffer object itself
640bd6fe569Sgabime// to avoid dynamic memory allocation.
6418192c133SDamien Zammitenum { INLINE_BUFFER_SIZE = 500 };
64287ddb9a6Sgabime
64387ddb9a6Sgabime#if FMT_SECURE_SCL
644bd6fe569Sgabime// Use checked iterator to avoid warnings on MSVC.
645bd6fe569Sgabimetemplate <typename T>
646fced34e3Sgabimeinline stdext::checked_array_iterator<T*> make_ptr(T *ptr, std::size_t size) {
647fced34e3Sgabime  return stdext::checked_array_iterator<T*>(ptr, size);
648bd6fe569Sgabime}
64987ddb9a6Sgabime#else
650bd6fe569Sgabimetemplate <typename T>
651fced34e3Sgabimeinline T *make_ptr(T *ptr, std::size_t) { return ptr; }
65287ddb9a6Sgabime#endif
653bd6fe569Sgabime}  // namespace internal
654bd6fe569Sgabime
655bd6fe569Sgabime/**
6568192c133SDamien Zammit  \rst
6578192c133SDamien Zammit  A buffer supporting a subset of ``std::vector``'s operations.
6588192c133SDamien Zammit  \endrst
6598192c133SDamien Zammit */
660bd6fe569Sgabimetemplate <typename T>
661fced34e3Sgabimeclass Buffer {
662fced34e3Sgabime private:
663fced34e3Sgabime  FMT_DISALLOW_COPY_AND_ASSIGN(Buffer);
664fced34e3Sgabime
665fced34e3Sgabime protected:
666fced34e3Sgabime  T *ptr_;
667fced34e3Sgabime  std::size_t size_;
668fced34e3Sgabime  std::size_t capacity_;
669fced34e3Sgabime
670fced34e3Sgabime  Buffer(T *ptr = FMT_NULL, std::size_t capacity = 0)
671fced34e3Sgabime    : ptr_(ptr), size_(0), capacity_(capacity) {}
672fced34e3Sgabime
673fced34e3Sgabime  /**
674fced34e3Sgabime    \rst
675fced34e3Sgabime    Increases the buffer capacity to hold at least *size* elements updating
676fced34e3Sgabime    ``ptr_`` and ``capacity_``.
677fced34e3Sgabime    \endrst
678fced34e3Sgabime   */
679fced34e3Sgabime  virtual void grow(std::size_t size) = 0;
680fced34e3Sgabime
681fced34e3Sgabime public:
682fced34e3Sgabime  virtual ~Buffer() {}
683fced34e3Sgabime
684fced34e3Sgabime  /** Returns the size of this buffer. */
685fced34e3Sgabime  std::size_t size() const { return size_; }
686fced34e3Sgabime
687fced34e3Sgabime  /** Returns the capacity of this buffer. */
688fced34e3Sgabime  std::size_t capacity() const { return capacity_; }
689fced34e3Sgabime
690fced34e3Sgabime  /**
691fced34e3Sgabime    Resizes the buffer. If T is a POD type new elements may not be initialized.
692fced34e3Sgabime   */
693fced34e3Sgabime  void resize(std::size_t new_size) {
694fced34e3Sgabime    if (new_size > capacity_)
695fced34e3Sgabime      grow(new_size);
696fced34e3Sgabime    size_ = new_size;
697fced34e3Sgabime  }
6980c276beaSgabime
699fced34e3Sgabime  /**
700fced34e3Sgabime    \rst
701fced34e3Sgabime    Reserves space to store at least *capacity* elements.
702fced34e3Sgabime    \endrst
703fced34e3Sgabime   */
704fced34e3Sgabime  void reserve(std::size_t capacity) {
705fced34e3Sgabime    if (capacity > capacity_)
706fced34e3Sgabime      grow(capacity);
707fced34e3Sgabime  }
7080c276beaSgabime
709fced34e3Sgabime  void clear() FMT_NOEXCEPT { size_ = 0; }
7100c276beaSgabime
711fced34e3Sgabime  void push_back(const T &value) {
712fced34e3Sgabime    if (size_ == capacity_)
713fced34e3Sgabime      grow(size_ + 1);
714fced34e3Sgabime    ptr_[size_++] = value;
715fced34e3Sgabime  }
716bd6fe569Sgabime
717fced34e3Sgabime  /** Appends data to the end of the buffer. */
718fced34e3Sgabime  template <typename U>
719fced34e3Sgabime  void append(const U *begin, const U *end);
720bd6fe569Sgabime
721fced34e3Sgabime  T &operator[](std::size_t index) { return ptr_[index]; }
722fced34e3Sgabime  const T &operator[](std::size_t index) const { return ptr_[index]; }
723bd6fe569Sgabime};
724bd6fe569Sgabime
725bd6fe569Sgabimetemplate <typename T>
726bd6fe569Sgabimetemplate <typename U>
727fced34e3Sgabimevoid Buffer<T>::append(const U *begin, const U *end) {
728fced34e3Sgabime  FMT_ASSERT(end >= begin, "negative value");
729fced34e3Sgabime  std::size_t new_size = size_ + (end - begin);
730fced34e3Sgabime  if (new_size > capacity_)
731fced34e3Sgabime    grow(new_size);
732fced34e3Sgabime  std::uninitialized_copy(begin, end,
733fced34e3Sgabime                          internal::make_ptr(ptr_, capacity_) + size_);
734fced34e3Sgabime  size_ = new_size;
735bd6fe569Sgabime}
736bd6fe569Sgabime
737fced34e3Sgabimenamespace internal {
738bd6fe569Sgabime
739bd6fe569Sgabime// A memory buffer for trivially copyable/constructible types with the first
740bd6fe569Sgabime// SIZE elements stored in the object itself.
741bd6fe569Sgabimetemplate <typename T, std::size_t SIZE, typename Allocator = std::allocator<T> >
742fced34e3Sgabimeclass MemoryBuffer : private Allocator, public Buffer<T> {
743fced34e3Sgabime private:
744fced34e3Sgabime  T data_[SIZE];
745bd6fe569Sgabime
746fced34e3Sgabime  // Deallocate memory allocated by the buffer.
747fced34e3Sgabime  void deallocate() {
748fced34e3Sgabime    if (this->ptr_ != data_) Allocator::deallocate(this->ptr_, this->capacity_);
749fced34e3Sgabime  }
7508192c133SDamien Zammit
751fced34e3Sgabime protected:
752fced34e3Sgabime  void grow(std::size_t size) FMT_OVERRIDE;
753fced34e3Sgabime
754fced34e3Sgabime public:
755fced34e3Sgabime  explicit MemoryBuffer(const Allocator &alloc = Allocator())
756fced34e3Sgabime      : Allocator(alloc), Buffer<T>(data_, SIZE) {}
757fced34e3Sgabime  ~MemoryBuffer() { deallocate(); }
75887ddb9a6Sgabime
75987ddb9a6Sgabime#if FMT_USE_RVALUE_REFERENCES
760fced34e3Sgabime private:
761fced34e3Sgabime  // Move data from other to this buffer.
762fced34e3Sgabime  void move(MemoryBuffer &other) {
763fced34e3Sgabime    Allocator &this_alloc = *this, &other_alloc = other;
764fced34e3Sgabime    this_alloc = std::move(other_alloc);
765fced34e3Sgabime    this->size_ = other.size_;
766fced34e3Sgabime    this->capacity_ = other.capacity_;
767fced34e3Sgabime    if (other.ptr_ == other.data_) {
768fced34e3Sgabime      this->ptr_ = data_;
769fced34e3Sgabime      std::uninitialized_copy(other.data_, other.data_ + this->size_,
770fced34e3Sgabime                              make_ptr(data_, this->capacity_));
771fced34e3Sgabime    } else {
772fced34e3Sgabime      this->ptr_ = other.ptr_;
773fced34e3Sgabime      // Set pointer to the inline array so that delete is not called
774fced34e3Sgabime      // when deallocating.
775fced34e3Sgabime      other.ptr_ = other.data_;
776bd6fe569Sgabime    }
777fced34e3Sgabime  }
778bd6fe569Sgabime
779fced34e3Sgabime public:
780fced34e3Sgabime  MemoryBuffer(MemoryBuffer &&other) {
781fced34e3Sgabime    move(other);
782fced34e3Sgabime  }
783bd6fe569Sgabime
784fced34e3Sgabime  MemoryBuffer &operator=(MemoryBuffer &&other) {
785fced34e3Sgabime    assert(this != &other);
786fced34e3Sgabime    deallocate();
787fced34e3Sgabime    move(other);
788fced34e3Sgabime    return *this;
789fced34e3Sgabime  }
79087ddb9a6Sgabime#endif
79187ddb9a6Sgabime
792fced34e3Sgabime  // Returns a copy of the allocator associated with this buffer.
793fced34e3Sgabime  Allocator get_allocator() const { return *this; }
794bd6fe569Sgabime};
795bd6fe569Sgabime
796bd6fe569Sgabimetemplate <typename T, std::size_t SIZE, typename Allocator>
797fced34e3Sgabimevoid MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size) {
798fced34e3Sgabime  std::size_t new_capacity = this->capacity_ + this->capacity_ / 2;
799fced34e3Sgabime  if (size > new_capacity)
800fced34e3Sgabime      new_capacity = size;
801fced34e3Sgabime  T *new_ptr = this->allocate(new_capacity, FMT_NULL);
802fced34e3Sgabime  // The following code doesn't throw, so the raw pointer above doesn't leak.
803fced34e3Sgabime  std::uninitialized_copy(this->ptr_, this->ptr_ + this->size_,
804fced34e3Sgabime                          make_ptr(new_ptr, new_capacity));
805fced34e3Sgabime  std::size_t old_capacity = this->capacity_;
806fced34e3Sgabime  T *old_ptr = this->ptr_;
807fced34e3Sgabime  this->capacity_ = new_capacity;
808fced34e3Sgabime  this->ptr_ = new_ptr;
809fced34e3Sgabime  // deallocate may throw (at least in principle), but it doesn't matter since
810fced34e3Sgabime  // the buffer already uses the new storage and will deallocate it in case
811fced34e3Sgabime  // of exception.
812fced34e3Sgabime  if (old_ptr != data_)
813fced34e3Sgabime    Allocator::deallocate(old_ptr, old_capacity);
814bd6fe569Sgabime}
815bd6fe569Sgabime
816bd6fe569Sgabime// A fixed-size buffer.
817bd6fe569Sgabimetemplate <typename Char>
818fced34e3Sgabimeclass FixedBuffer : public fmt::Buffer<Char> {
819fced34e3Sgabime public:
820fced34e3Sgabime  FixedBuffer(Char *array, std::size_t size) : fmt::Buffer<Char>(array, size) {}
821bd6fe569Sgabime
822fced34e3Sgabime protected:
823fced34e3Sgabime  FMT_API void grow(std::size_t size) FMT_OVERRIDE;
824bd6fe569Sgabime};
825bd6fe569Sgabime
826bd6fe569Sgabimetemplate <typename Char>
827fced34e3Sgabimeclass BasicCharTraits {
828fced34e3Sgabime public:
82987ddb9a6Sgabime#if FMT_SECURE_SCL
830fced34e3Sgabime  typedef stdext::checked_array_iterator<Char*> CharPtr;
83187ddb9a6Sgabime#else
832fced34e3Sgabime  typedef Char *CharPtr;
833d142f135Sgabime#endif
834fced34e3Sgabime  static Char cast(int value) { return static_cast<Char>(value); }
835bd6fe569Sgabime};
836bd6fe569Sgabime
837bd6fe569Sgabimetemplate <typename Char>
838bd6fe569Sgabimeclass CharTraits;
839bd6fe569Sgabime
840bd6fe569Sgabimetemplate <>
841fced34e3Sgabimeclass CharTraits<char> : public BasicCharTraits<char> {
842fced34e3Sgabime private:
843fced34e3Sgabime  // Conversion from wchar_t to char is not allowed.
844fced34e3Sgabime  static char convert(wchar_t);
845fced34e3Sgabime
846fced34e3Sgabime public:
847fced34e3Sgabime  static char convert(char value) { return value; }
848fced34e3Sgabime
849fced34e3Sgabime  // Formats a floating-point number.
850fced34e3Sgabime  template <typename T>
851fced34e3Sgabime  FMT_API static int format_float(char *buffer, std::size_t size,
852fced34e3Sgabime      const char *format, unsigned width, int precision, T value);
853fced34e3Sgabime};
854fced34e3Sgabime
855fced34e3Sgabime#if FMT_USE_EXTERN_TEMPLATES
856fced34e3Sgabimeextern template int CharTraits<char>::format_float<double>
857fced34e3Sgabime        (char *buffer, std::size_t size,
858fced34e3Sgabime         const char* format, unsigned width, int precision, double value);
859fced34e3Sgabimeextern template int CharTraits<char>::format_float<long double>
860fced34e3Sgabime        (char *buffer, std::size_t size,
861fced34e3Sgabime         const char* format, unsigned width, int precision, long double value);
862fced34e3Sgabime#endif
863d142f135Sgabime
864bd6fe569Sgabimetemplate <>
865fced34e3Sgabimeclass CharTraits<wchar_t> : public BasicCharTraits<wchar_t> {
866fced34e3Sgabime public:
867fced34e3Sgabime  static wchar_t convert(char value) { return value; }
868fced34e3Sgabime  static wchar_t convert(wchar_t value) { return value; }
869fced34e3Sgabime
870fced34e3Sgabime  template <typename T>
871fced34e3Sgabime  FMT_API static int format_float(wchar_t *buffer, std::size_t size,
872fced34e3Sgabime      const wchar_t *format, unsigned width, int precision, T value);
873fced34e3Sgabime};
874fced34e3Sgabime
875fced34e3Sgabime#if FMT_USE_EXTERN_TEMPLATES
876fced34e3Sgabimeextern template int CharTraits<wchar_t>::format_float<double>
877fced34e3Sgabime        (wchar_t *buffer, std::size_t size,
878fced34e3Sgabime         const wchar_t* format, unsigned width, int precision, double value);
879fced34e3Sgabimeextern template int CharTraits<wchar_t>::format_float<long double>
880fced34e3Sgabime        (wchar_t *buffer, std::size_t size,
881fced34e3Sgabime         const wchar_t* format, unsigned width, int precision, long double value);
882fced34e3Sgabime#endif
883d142f135Sgabime
884bd6fe569Sgabime// Checks if a number is negative - used to avoid warnings.
885bd6fe569Sgabimetemplate <bool IsSigned>
886fced34e3Sgabimestruct SignChecker {
887fced34e3Sgabime  template <typename T>
888fced34e3Sgabime  static bool is_negative(T value) { return value < 0; }
889bd6fe569Sgabime};
890bd6fe569Sgabime
891bd6fe569Sgabimetemplate <>
892fced34e3Sgabimestruct SignChecker<false> {
893fced34e3Sgabime  template <typename T>
894fced34e3Sgabime  static bool is_negative(T) { return false; }
895bd6fe569Sgabime};
896bd6fe569Sgabime
897bd6fe569Sgabime// Returns true if value is negative, false otherwise.
898bd6fe569Sgabime// Same as (value < 0) but doesn't produce warnings if T is an unsigned type.
899bd6fe569Sgabimetemplate <typename T>
900fced34e3Sgabimeinline bool is_negative(T value) {
901fced34e3Sgabime  return SignChecker<std::numeric_limits<T>::is_signed>::is_negative(value);
902bd6fe569Sgabime}
903bd6fe569Sgabime
904bd6fe569Sgabime// Selects uint32_t if FitsIn32Bits is true, uint64_t otherwise.
905bd6fe569Sgabimetemplate <bool FitsIn32Bits>
906fced34e3Sgabimestruct TypeSelector { typedef uint32_t Type; };
907bd6fe569Sgabime
908bd6fe569Sgabimetemplate <>
909fced34e3Sgabimestruct TypeSelector<false> { typedef uint64_t Type; };
910bd6fe569Sgabime
911bd6fe569Sgabimetemplate <typename T>
912fced34e3Sgabimestruct IntTraits {
913fced34e3Sgabime  // Smallest of uint32_t and uint64_t that is large enough to represent
914fced34e3Sgabime  // all values of T.
915fced34e3Sgabime  typedef typename
916bd6fe569Sgabime    TypeSelector<std::numeric_limits<T>::digits <= 32>::Type MainType;
917bd6fe569Sgabime};
918bd6fe569Sgabime
919bd6fe569SgabimeFMT_API void report_unknown_type(char code, const char *type);
920bd6fe569Sgabime
921bd6fe569Sgabime// Static data is placed in this class template to allow header-only
922bd6fe569Sgabime// configuration.
923bd6fe569Sgabimetemplate <typename T = void>
924fced34e3Sgabimestruct FMT_API BasicData {
925fced34e3Sgabime  static const uint32_t POWERS_OF_10_32[];
926fced34e3Sgabime  static const uint64_t POWERS_OF_10_64[];
927fced34e3Sgabime  static const char DIGITS[];
928bd6fe569Sgabime};
929d142f135Sgabime
930fced34e3Sgabime#if FMT_USE_EXTERN_TEMPLATES
931bd6fe569Sgabimeextern template struct BasicData<void>;
93287ddb9a6Sgabime#endif
93387ddb9a6Sgabime
934bd6fe569Sgabimetypedef BasicData<> Data;
93587ddb9a6Sgabime
93687ddb9a6Sgabime#ifdef FMT_BUILTIN_CLZLL
937bd6fe569Sgabime// Returns the number of decimal digits in n. Leading zeros are not counted
938bd6fe569Sgabime// except for n == 0 in which case count_digits returns 1.
939fced34e3Sgabimeinline unsigned count_digits(uint64_t n) {
940fced34e3Sgabime  // Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
941fced34e3Sgabime  // and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits.
942fced34e3Sgabime  int t = (64 - FMT_BUILTIN_CLZLL(n | 1)) * 1233 >> 12;
943fced34e3Sgabime  return to_unsigned(t) - (n < Data::POWERS_OF_10_64[t]) + 1;
944bd6fe569Sgabime}
94587ddb9a6Sgabime#else
946bd6fe569Sgabime// Fallback version of count_digits used when __builtin_clz is not available.
947fced34e3Sgabimeinline unsigned count_digits(uint64_t n) {
948fced34e3Sgabime  unsigned count = 1;
949fced34e3Sgabime  for (;;) {
950fced34e3Sgabime    // Integer division is slow so do it for a group of four digits instead
951fced34e3Sgabime    // of for every digit. The idea comes from the talk by Alexandrescu
952fced34e3Sgabime    // "Three Optimization Tips for C++". See speed-test for a comparison.
953fced34e3Sgabime    if (n < 10) return count;
954fced34e3Sgabime    if (n < 100) return count + 1;
955fced34e3Sgabime    if (n < 1000) return count + 2;
956fced34e3Sgabime    if (n < 10000) return count + 3;
957fced34e3Sgabime    n /= 10000u;
958fced34e3Sgabime    count += 4;
959fced34e3Sgabime  }
960bd6fe569Sgabime}
96187ddb9a6Sgabime#endif
96287ddb9a6Sgabime
96387ddb9a6Sgabime#ifdef FMT_BUILTIN_CLZ
964bd6fe569Sgabime// Optional version of count_digits for better performance on 32-bit platforms.
965fced34e3Sgabimeinline unsigned count_digits(uint32_t n) {
966fced34e3Sgabime  int t = (32 - FMT_BUILTIN_CLZ(n | 1)) * 1233 >> 12;
967fced34e3Sgabime  return to_unsigned(t) - (n < Data::POWERS_OF_10_32[t]) + 1;
968bd6fe569Sgabime}
96987ddb9a6Sgabime#endif
97087ddb9a6Sgabime
971bd6fe569Sgabime// A functor that doesn't add a thousands separator.
972fced34e3Sgabimestruct NoThousandsSep {
973fced34e3Sgabime  template <typename Char>
974fced34e3Sgabime  void operator()(Char *) {}
975bd6fe569Sgabime};
976bd6fe569Sgabime
977bd6fe569Sgabime// A functor that adds a thousands separator.
978fced34e3Sgabimeclass ThousandsSep {
979fced34e3Sgabime private:
980fced34e3Sgabime  fmt::StringRef sep_;
981fced34e3Sgabime
982fced34e3Sgabime  // Index of a decimal digit with the least significant digit having index 0.
983fced34e3Sgabime  unsigned digit_index_;
984fced34e3Sgabime
985fced34e3Sgabime public:
986fced34e3Sgabime  explicit ThousandsSep(fmt::StringRef sep) : sep_(sep), digit_index_(0) {}
987fced34e3Sgabime
988fced34e3Sgabime  template <typename Char>
989fced34e3Sgabime  void operator()(Char *&buffer) {
990fced34e3Sgabime    if (++digit_index_ % 3 != 0)
991fced34e3Sgabime      return;
992fced34e3Sgabime    buffer -= sep_.size();
993fced34e3Sgabime    std::uninitialized_copy(sep_.data(), sep_.data() + sep_.size(),
994fced34e3Sgabime                            internal::make_ptr(buffer, sep_.size()));
995fced34e3Sgabime  }
996bd6fe569Sgabime};
997bd6fe569Sgabime
998bd6fe569Sgabime// Formats a decimal unsigned integer value writing into buffer.
999bd6fe569Sgabime// thousands_sep is a functor that is called after writing each char to
1000bd6fe569Sgabime// add a thousands separator if necessary.
1001bd6fe569Sgabimetemplate <typename UInt, typename Char, typename ThousandsSep>
1002bd6fe569Sgabimeinline void format_decimal(Char *buffer, UInt value, unsigned num_digits,
1003fced34e3Sgabime                           ThousandsSep thousands_sep) {
1004fced34e3Sgabime  buffer += num_digits;
1005fced34e3Sgabime  while (value >= 100) {
1006fced34e3Sgabime    // Integer division is slow so do it for a group of two digits instead
1007fced34e3Sgabime    // of for every digit. The idea comes from the talk by Alexandrescu
1008fced34e3Sgabime    // "Three Optimization Tips for C++". See speed-test for a comparison.
1009fced34e3Sgabime    unsigned index = static_cast<unsigned>((value % 100) * 2);
1010fced34e3Sgabime    value /= 100;
1011bd6fe569Sgabime    *--buffer = Data::DIGITS[index + 1];
1012bd6fe569Sgabime    thousands_sep(buffer);
1013bd6fe569Sgabime    *--buffer = Data::DIGITS[index];
1014fced34e3Sgabime    thousands_sep(buffer);
1015fced34e3Sgabime  }
1016fced34e3Sgabime  if (value < 10) {
1017fced34e3Sgabime    *--buffer = static_cast<char>('0' + value);
1018fced34e3Sgabime    return;
1019fced34e3Sgabime  }
1020fced34e3Sgabime  unsigned index = static_cast<unsigned>(value * 2);
1021fced34e3Sgabime  *--buffer = Data::DIGITS[index + 1];
1022fced34e3Sgabime  thousands_sep(buffer);
1023fced34e3Sgabime  *--buffer = Data::DIGITS[index];
1024bd6fe569Sgabime}
1025bd6fe569Sgabime
1026bd6fe569Sgabimetemplate <typename UInt, typename Char>
1027fced34e3Sgabimeinline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
1028fced34e3Sgabime  format_decimal(buffer, value, num_digits, NoThousandsSep());
1029fced34e3Sgabime  return;
1030bd6fe569Sgabime}
103187ddb9a6Sgabime
103287ddb9a6Sgabime#ifndef _WIN32
103387ddb9a6Sgabime# define FMT_USE_WINDOWS_H 0
103487ddb9a6Sgabime#elif !defined(FMT_USE_WINDOWS_H)
103587ddb9a6Sgabime# define FMT_USE_WINDOWS_H 1
103687ddb9a6Sgabime#endif
103787ddb9a6Sgabime
1038bd6fe569Sgabime// Define FMT_USE_WINDOWS_H to 0 to disable use of windows.h.
1039bd6fe569Sgabime// All the functionality that relies on it will be disabled too.
104087ddb9a6Sgabime#if FMT_USE_WINDOWS_H
1041bd6fe569Sgabime// A converter from UTF-8 to UTF-16.
1042bd6fe569Sgabime// It is only provided for Windows since other systems support UTF-8 natively.
1043fced34e3Sgabimeclass UTF8ToUTF16 {
1044fced34e3Sgabime private:
1045fced34e3Sgabime  MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer_;
1046bd6fe569Sgabime
1047fced34e3Sgabime public:
1048fced34e3Sgabime  FMT_API explicit UTF8ToUTF16(StringRef s);
1049fced34e3Sgabime  operator WStringRef() const { return WStringRef(&buffer_[0], size()); }
1050fced34e3Sgabime  size_t size() const { return buffer_.size() - 1; }
1051fced34e3Sgabime  const wchar_t *c_str() const { return &buffer_[0]; }
1052fced34e3Sgabime  std::wstring str() const { return std::wstring(&buffer_[0], size()); }
1053bd6fe569Sgabime};
1054bd6fe569Sgabime
1055bd6fe569Sgabime// A converter from UTF-16 to UTF-8.
1056bd6fe569Sgabime// It is only provided for Windows since other systems support UTF-8 natively.
1057fced34e3Sgabimeclass UTF16ToUTF8 {
1058fced34e3Sgabime private:
1059fced34e3Sgabime  MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer_;
1060bd6fe569Sgabime
1061fced34e3Sgabime public:
1062fced34e3Sgabime  UTF16ToUTF8() {}
1063fced34e3Sgabime  FMT_API explicit UTF16ToUTF8(WStringRef s);
1064fced34e3Sgabime  operator StringRef() const { return StringRef(&buffer_[0], size()); }
1065fced34e3Sgabime  size_t size() const { return buffer_.size() - 1; }
1066fced34e3Sgabime  const char *c_str() const { return &buffer_[0]; }
1067fced34e3Sgabime  std::string str() const { return std::string(&buffer_[0], size()); }
1068bd6fe569Sgabime
1069fced34e3Sgabime  // Performs conversion returning a system error code instead of
1070fced34e3Sgabime  // throwing exception on conversion error. This method may still throw
1071fced34e3Sgabime  // in case of memory allocation error.
1072fced34e3Sgabime  FMT_API int convert(WStringRef s);
1073bd6fe569Sgabime};
1074bd6fe569Sgabime
1075bd6fe569SgabimeFMT_API void format_windows_error(fmt::Writer &out, int error_code,
1076bd6fe569Sgabime                                  fmt::StringRef message) FMT_NOEXCEPT;
107787ddb9a6Sgabime#endif
107887ddb9a6Sgabime
10798192c133SDamien Zammit// A formatting argument value.
1080fced34e3Sgabimestruct Value {
1081fced34e3Sgabime  template <typename Char>
1082fced34e3Sgabime  struct StringValue {
1083fced34e3Sgabime    const Char *value;
1084fced34e3Sgabime    std::size_t size;
1085fced34e3Sgabime  };
1086fced34e3Sgabime
1087fced34e3Sgabime  typedef void (*FormatFunc)(
1088fced34e3Sgabime      void *formatter, const void *arg, void *format_str_ptr);
1089fced34e3Sgabime
1090fced34e3Sgabime  struct CustomValue {
1091fced34e3Sgabime    const void *value;
1092fced34e3Sgabime    FormatFunc format;
1093fced34e3Sgabime  };
1094fced34e3Sgabime
1095fced34e3Sgabime  union {
1096fced34e3Sgabime    int int_value;
1097fced34e3Sgabime    unsigned uint_value;
1098fced34e3Sgabime    LongLong long_long_value;
1099fced34e3Sgabime    ULongLong ulong_long_value;
1100fced34e3Sgabime    double double_value;
1101fced34e3Sgabime    long double long_double_value;
1102fced34e3Sgabime    const void *pointer;
1103fced34e3Sgabime    StringValue<char> string;
1104fced34e3Sgabime    StringValue<signed char> sstring;
1105fced34e3Sgabime    StringValue<unsigned char> ustring;
1106fced34e3Sgabime    StringValue<wchar_t> wstring;
1107fced34e3Sgabime    CustomValue custom;
1108fced34e3Sgabime  };
1109fced34e3Sgabime
1110fced34e3Sgabime  enum Type {
1111fced34e3Sgabime    NONE, NAMED_ARG,
1112fced34e3Sgabime    // Integer types should go first,
1113fced34e3Sgabime    INT, UINT, LONG_LONG, ULONG_LONG, BOOL, CHAR, LAST_INTEGER_TYPE = CHAR,
1114fced34e3Sgabime    // followed by floating-point types.
1115fced34e3Sgabime    DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE,
1116fced34e3Sgabime    CSTRING, STRING, WSTRING, POINTER, CUSTOM
1117fced34e3Sgabime  };
1118bd6fe569Sgabime};
1119bd6fe569Sgabime
1120bd6fe569Sgabime// A formatting argument. It is a trivially copyable/constructible type to
1121bd6fe569Sgabime// allow storage in internal::MemoryBuffer.
1122fced34e3Sgabimestruct Arg : Value {
1123fced34e3Sgabime  Type type;
1124bd6fe569Sgabime};
1125bd6fe569Sgabime
1126bd6fe569Sgabimetemplate <typename Char>
1127bd6fe569Sgabimestruct NamedArg;
1128fced34e3Sgabimetemplate <typename Char, typename T>
1129fced34e3Sgabimestruct NamedArgWithType;
1130bd6fe569Sgabime
1131bd6fe569Sgabimetemplate <typename T = void>
11328192c133SDamien Zammitstruct Null {};
1133bd6fe569Sgabime
1134bd6fe569Sgabime// A helper class template to enable or disable overloads taking wide
1135bd6fe569Sgabime// characters and strings in MakeValue.
1136bd6fe569Sgabimetemplate <typename T, typename Char>
1137fced34e3Sgabimestruct WCharHelper {
1138fced34e3Sgabime  typedef Null<T> Supported;
1139fced34e3Sgabime  typedef T Unsupported;
1140bd6fe569Sgabime};
1141bd6fe569Sgabime
1142bd6fe569Sgabimetemplate <typename T>
1143fced34e3Sgabimestruct WCharHelper<T, wchar_t> {
1144fced34e3Sgabime  typedef T Supported;
1145fced34e3Sgabime  typedef Null<T> Unsupported;
1146bd6fe569Sgabime};
1147bd6fe569Sgabime
1148bd6fe569Sgabimetypedef char Yes[1];
1149bd6fe569Sgabimetypedef char No[2];
1150bd6fe569Sgabime
1151bd6fe569Sgabimetemplate <typename T>
1152bd6fe569SgabimeT &get();
1153bd6fe569Sgabime
1154bd6fe569Sgabime// These are non-members to workaround an overload resolution bug in bcc32.
1155bd6fe569SgabimeYes &convert(fmt::ULongLong);
1156bd6fe569SgabimeNo &convert(...);
1157bd6fe569Sgabime
1158bd6fe569Sgabimetemplate<typename T, bool ENABLE_CONVERSION>
1159fced34e3Sgabimestruct ConvertToIntImpl {
1160fced34e3Sgabime  enum { value = ENABLE_CONVERSION };
1161bd6fe569Sgabime};
1162bd6fe569Sgabime
1163bd6fe569Sgabimetemplate<typename T, bool ENABLE_CONVERSION>
1164fced34e3Sgabimestruct ConvertToIntImpl2 {
1165fced34e3Sgabime  enum { value = false };
1166bd6fe569Sgabime};
1167bd6fe569Sgabime
1168bd6fe569Sgabimetemplate<typename T>
1169fced34e3Sgabimestruct ConvertToIntImpl2<T, true> {
1170fced34e3Sgabime  enum {
1171fced34e3Sgabime    // Don't convert numeric types.
1172fced34e3Sgabime    value = ConvertToIntImpl<T, !std::numeric_limits<T>::is_specialized>::value
1173fced34e3Sgabime  };
1174bd6fe569Sgabime};
1175bd6fe569Sgabime
1176bd6fe569Sgabimetemplate<typename T>
1177fced34e3Sgabimestruct ConvertToInt {
1178fced34e3Sgabime  enum {
1179fced34e3Sgabime    enable_conversion = sizeof(fmt::internal::convert(get<T>())) == sizeof(Yes)
1180fced34e3Sgabime  };
1181fced34e3Sgabime  enum { value = ConvertToIntImpl2<T, enable_conversion>::value };
1182bd6fe569Sgabime};
118387ddb9a6Sgabime
118487ddb9a6Sgabime#define FMT_DISABLE_CONVERSION_TO_INT(Type) \
118587ddb9a6Sgabime  template <> \
118687ddb9a6Sgabime  struct ConvertToInt<Type> {  enum { value = 0 }; }
118787ddb9a6Sgabime
1188bd6fe569Sgabime// Silence warnings about convering float to int.
1189bd6fe569SgabimeFMT_DISABLE_CONVERSION_TO_INT(float);
1190bd6fe569SgabimeFMT_DISABLE_CONVERSION_TO_INT(double);
1191bd6fe569SgabimeFMT_DISABLE_CONVERSION_TO_INT(long double);
1192bd6fe569Sgabime
1193bd6fe569Sgabimetemplate<bool B, class T = void>
11948192c133SDamien Zammitstruct EnableIf {};
1195bd6fe569Sgabime
1196bd6fe569Sgabimetemplate<class T>
1197fced34e3Sgabimestruct EnableIf<true, T> { typedef T type; };
1198bd6fe569