Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
spdlog
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
spdlog
Commits
3f438a80
Commit
3f438a80
authored
Jun 13, 2018
by
gabime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added bundled fmt 5.x
parent
f2a88479
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
8934 additions
and
0 deletions
+8934
-0
include/spdlog/fmt/bundled/colors.h
include/spdlog/fmt/bundled/colors.h
+257
-0
include/spdlog/fmt/bundled/core.h
include/spdlog/fmt/bundled/core.h
+1574
-0
include/spdlog/fmt/bundled/format-inl.h
include/spdlog/fmt/bundled/format-inl.h
+534
-0
include/spdlog/fmt/bundled/format.cc
include/spdlog/fmt/bundled/format.cc
+46
-0
include/spdlog/fmt/bundled/format.h
include/spdlog/fmt/bundled/format.h
+4514
-0
include/spdlog/fmt/bundled/locale.h
include/spdlog/fmt/bundled/locale.h
+27
-0
include/spdlog/fmt/bundled/ostream.h
include/spdlog/fmt/bundled/ostream.h
+171
-0
include/spdlog/fmt/bundled/posix.h
include/spdlog/fmt/bundled/posix.h
+484
-0
include/spdlog/fmt/bundled/printf.h
include/spdlog/fmt/bundled/printf.h
+786
-0
include/spdlog/fmt/bundled/ranges.h
include/spdlog/fmt/bundled/ranges.h
+342
-0
include/spdlog/fmt/bundled/time.h
include/spdlog/fmt/bundled/time.h
+199
-0
No files found.
include/spdlog/fmt/bundled/colors.h
0 → 100644
View file @
3f438a80
// Formatting library for C++ - the core API
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
//
// Copyright (c) 2018 - present, Remotion (Igor Schulz)
// All Rights Reserved
// {fmt} support for rgb color output.
#ifndef FMT_COLORS_H_
#define FMT_COLORS_H_
#include "format.h"
FMT_BEGIN_NAMESPACE
// rgb is a struct for red, green and blue colors.
// We use rgb as name because some editors will show it as color direct in the
// editor.
struct
rgb
{
FMT_CONSTEXPR_DECL
rgb
()
:
r
(
0
)
,
g
(
0
)
,
b
(
0
)
{
}
FMT_CONSTEXPR_DECL
rgb
(
uint8_t
r_
,
uint8_t
g_
,
uint8_t
b_
)
:
r
(
r_
)
,
g
(
g_
)
,
b
(
b_
)
{
}
FMT_CONSTEXPR_DECL
rgb
(
uint32_t
hex
)
:
r
((
hex
>>
16
)
&
0xFF
)
,
g
((
hex
>>
8
)
&
0xFF
)
,
b
((
hex
)
&
0xFF
)
{
}
uint8_t
r
;
uint8_t
g
;
uint8_t
b
;
};
namespace
internal
{
FMT_CONSTEXPR
inline
void
to_esc
(
uint8_t
c
,
char
out
[],
int
offset
)
{
out
[
offset
+
0
]
=
static_cast
<
char
>
(
'0'
+
c
/
100
);
out
[
offset
+
1
]
=
static_cast
<
char
>
(
'0'
+
c
/
10
%
10
);
out
[
offset
+
2
]
=
static_cast
<
char
>
(
'0'
+
c
%
10
);
}
}
// namespace internal
FMT_FUNC
void
vprint_rgb
(
rgb
fd
,
string_view
format
,
format_args
args
)
{
char
escape_fd
[]
=
"
\x1b
[38;2;000;000;000m"
;
static
FMT_CONSTEXPR_DECL
const
char
RESET_COLOR
[]
=
"
\x1b
[0m"
;
internal
::
to_esc
(
fd
.
r
,
escape_fd
,
7
);
internal
::
to_esc
(
fd
.
g
,
escape_fd
,
11
);
internal
::
to_esc
(
fd
.
b
,
escape_fd
,
15
);
std
::
fputs
(
escape_fd
,
stdout
);
vprint
(
format
,
args
);
std
::
fputs
(
RESET_COLOR
,
stdout
);
}
FMT_FUNC
void
vprint_rgb
(
rgb
fd
,
rgb
bg
,
string_view
format
,
format_args
args
)
{
char
escape_fd
[]
=
"
\x1b
[38;2;000;000;000m"
;
// foreground color
char
escape_bg
[]
=
"
\x1b
[48;2;000;000;000m"
;
// background color
static
FMT_CONSTEXPR_DECL
const
char
RESET_COLOR
[]
=
"
\x1b
[0m"
;
internal
::
to_esc
(
fd
.
r
,
escape_fd
,
7
);
internal
::
to_esc
(
fd
.
g
,
escape_fd
,
11
);
internal
::
to_esc
(
fd
.
b
,
escape_fd
,
15
);
internal
::
to_esc
(
bg
.
r
,
escape_bg
,
7
);
internal
::
to_esc
(
bg
.
g
,
escape_bg
,
11
);
internal
::
to_esc
(
bg
.
b
,
escape_bg
,
15
);
std
::
fputs
(
escape_fd
,
stdout
);
std
::
fputs
(
escape_bg
,
stdout
);
vprint
(
format
,
args
);
std
::
fputs
(
RESET_COLOR
,
stdout
);
}
template
<
typename
...
Args
>
inline
void
print_rgb
(
rgb
fd
,
string_view
format_str
,
const
Args
&
...
args
)
{
vprint_rgb
(
fd
,
format_str
,
make_format_args
(
args
...));
}
// rgb foreground color
template
<
typename
...
Args
>
inline
void
print
(
rgb
fd
,
string_view
format_str
,
const
Args
&
...
args
)
{
vprint_rgb
(
fd
,
format_str
,
make_format_args
(
args
...));
}
// rgb foreground color and background color
template
<
typename
...
Args
>
inline
void
print
(
rgb
fd
,
rgb
bg
,
string_view
format_str
,
const
Args
&
...
args
)
{
vprint_rgb
(
fd
,
bg
,
format_str
,
make_format_args
(
args
...));
}
enum
class
color
:
uint32_t
{
alice_blue
=
0xF0F8FF
,
// rgb(240,248,255)
antique_white
=
0xFAEBD7
,
// rgb(250,235,215)
aqua
=
0x00FFFF
,
// rgb(0,255,255)
aquamarine
=
0x7FFFD4
,
// rgb(127,255,212)
azure
=
0xF0FFFF
,
// rgb(240,255,255)
beige
=
0xF5F5DC
,
// rgb(245,245,220)
bisque
=
0xFFE4C4
,
// rgb(255,228,196)
black
=
0x000000
,
// rgb(0,0,0)
blanched_almond
=
0xFFEBCD
,
// rgb(255,235,205)
blue
=
0x0000FF
,
// rgb(0,0,255)
blue_violet
=
0x8A2BE2
,
// rgb(138,43,226)
brown
=
0xA52A2A
,
// rgb(165,42,42)
burly_wood
=
0xDEB887
,
// rgb(222,184,135)
cadet_blue
=
0x5F9EA0
,
// rgb(95,158,160)
chartreuse
=
0x7FFF00
,
// rgb(127,255,0)
chocolate
=
0xD2691E
,
// rgb(210,105,30)
coral
=
0xFF7F50
,
// rgb(255,127,80)
cornflower_blue
=
0x6495ED
,
// rgb(100,149,237)
cornsilk
=
0xFFF8DC
,
// rgb(255,248,220)
crimson
=
0xDC143C
,
// rgb(220,20,60)
cyan
=
0x00FFFF
,
// rgb(0,255,255)
dark_blue
=
0x00008B
,
// rgb(0,0,139)
dark_cyan
=
0x008B8B
,
// rgb(0,139,139)
dark_golden_rod
=
0xB8860B
,
// rgb(184,134,11)
dark_gray
=
0xA9A9A9
,
// rgb(169,169,169)
dark_green
=
0x006400
,
// rgb(0,100,0)
dark_khaki
=
0xBDB76B
,
// rgb(189,183,107)
dark_magenta
=
0x8B008B
,
// rgb(139,0,139)
dark_olive_green
=
0x556B2F
,
// rgb(85,107,47)
dark_orange
=
0xFF8C00
,
// rgb(255,140,0)
dark_orchid
=
0x9932CC
,
// rgb(153,50,204)
dark_red
=
0x8B0000
,
// rgb(139,0,0)
dark_salmon
=
0xE9967A
,
// rgb(233,150,122)
dark_sea_green
=
0x8FBC8F
,
// rgb(143,188,143)
dark_slate_blue
=
0x483D8B
,
// rgb(72,61,139)
dark_slate_gray
=
0x2F4F4F
,
// rgb(47,79,79)
dark_turquoise
=
0x00CED1
,
// rgb(0,206,209)
dark_violet
=
0x9400D3
,
// rgb(148,0,211)
deep_pink
=
0xFF1493
,
// rgb(255,20,147)
deep_sky_blue
=
0x00BFFF
,
// rgb(0,191,255)
dim_gray
=
0x696969
,
// rgb(105,105,105)
dodger_blue
=
0x1E90FF
,
// rgb(30,144,255)
fire_brick
=
0xB22222
,
// rgb(178,34,34)
floral_white
=
0xFFFAF0
,
// rgb(255,250,240)
forest_green
=
0x228B22
,
// rgb(34,139,34)
fuchsia
=
0xFF00FF
,
// rgb(255,0,255)
gainsboro
=
0xDCDCDC
,
// rgb(220,220,220)
ghost_white
=
0xF8F8FF
,
// rgb(248,248,255)
gold
=
0xFFD700
,
// rgb(255,215,0)
golden_rod
=
0xDAA520
,
// rgb(218,165,32)
gray
=
0x808080
,
// rgb(128,128,128)
green
=
0x008000
,
// rgb(0,128,0)
green_yellow
=
0xADFF2F
,
// rgb(173,255,47)
honey_dew
=
0xF0FFF0
,
// rgb(240,255,240)
hot_pink
=
0xFF69B4
,
// rgb(255,105,180)
indian_red
=
0xCD5C5C
,
// rgb(205,92,92)
indigo
=
0x4B0082
,
// rgb(75,0,130)
ivory
=
0xFFFFF0
,
// rgb(255,255,240)
khaki
=
0xF0E68C
,
// rgb(240,230,140)
lavender
=
0xE6E6FA
,
// rgb(230,230,250)
lavender_blush
=
0xFFF0F5
,
// rgb(255,240,245)
lawn_green
=
0x7CFC00
,
// rgb(124,252,0)
lemon_chiffon
=
0xFFFACD
,
// rgb(255,250,205)
light_blue
=
0xADD8E6
,
// rgb(173,216,230)
light_coral
=
0xF08080
,
// rgb(240,128,128)
light_cyan
=
0xE0FFFF
,
// rgb(224,255,255)
light_golden_rod_yellow
=
0xFAFAD2
,
// rgb(250,250,210)
light_gray
=
0xD3D3D3
,
// rgb(211,211,211)
light_green
=
0x90EE90
,
// rgb(144,238,144)
light_pink
=
0xFFB6C1
,
// rgb(255,182,193)
light_salmon
=
0xFFA07A
,
// rgb(255,160,122)
light_sea_green
=
0x20B2AA
,
// rgb(32,178,170)
light_sky_blue
=
0x87CEFA
,
// rgb(135,206,250)
light_slate_gray
=
0x778899
,
// rgb(119,136,153)
light_steel_blue
=
0xB0C4DE
,
// rgb(176,196,222)
light_yellow
=
0xFFFFE0
,
// rgb(255,255,224)
lime
=
0x00FF00
,
// rgb(0,255,0)
lime_green
=
0x32CD32
,
// rgb(50,205,50)
linen
=
0xFAF0E6
,
// rgb(250,240,230)
magenta
=
0xFF00FF
,
// rgb(255,0,255)
maroon
=
0x800000
,
// rgb(128,0,0)
medium_aqua_marine
=
0x66CDAA
,
// rgb(102,205,170)
medium_blue
=
0x0000CD
,
// rgb(0,0,205)
medium_orchid
=
0xBA55D3
,
// rgb(186,85,211)
medium_purple
=
0x9370DB
,
// rgb(147,112,219)
medium_sea_green
=
0x3CB371
,
// rgb(60,179,113)
medium_slate_blue
=
0x7B68EE
,
// rgb(123,104,238)
medium_spring_green
=
0x00FA9A
,
// rgb(0,250,154)
medium_turquoise
=
0x48D1CC
,
// rgb(72,209,204)
medium_violet_red
=
0xC71585
,
// rgb(199,21,133)
midnight_blue
=
0x191970
,
// rgb(25,25,112)
mint_cream
=
0xF5FFFA
,
// rgb(245,255,250)
misty_rose
=
0xFFE4E1
,
// rgb(255,228,225)
moccasin
=
0xFFE4B5
,
// rgb(255,228,181)
navajo_white
=
0xFFDEAD
,
// rgb(255,222,173)
navy
=
0x000080
,
// rgb(0,0,128)
old_lace
=
0xFDF5E6
,
// rgb(253,245,230)
olive
=
0x808000
,
// rgb(128,128,0)
olive_drab
=
0x6B8E23
,
// rgb(107,142,35)
orange
=
0xFFA500
,
// rgb(255,165,0)
orange_red
=
0xFF4500
,
// rgb(255,69,0)
orchid
=
0xDA70D6
,
// rgb(218,112,214)
pale_golden_rod
=
0xEEE8AA
,
// rgb(238,232,170)
pale_green
=
0x98FB98
,
// rgb(152,251,152)
pale_turquoise
=
0xAFEEEE
,
// rgb(175,238,238)
pale_violet_red
=
0xDB7093
,
// rgb(219,112,147)
papaya_whip
=
0xFFEFD5
,
// rgb(255,239,213)
peach_puff
=
0xFFDAB9
,
// rgb(255,218,185)
peru
=
0xCD853F
,
// rgb(205,133,63)
pink
=
0xFFC0CB
,
// rgb(255,192,203)
plum
=
0xDDA0DD
,
// rgb(221,160,221)
powder_blue
=
0xB0E0E6
,
// rgb(176,224,230)
purple
=
0x800080
,
// rgb(128,0,128)
rebecca_purple
=
0x663399
,
// rgb(102,51,153)
red
=
0xFF0000
,
// rgb(255,0,0)
rosy_brown
=
0xBC8F8F
,
// rgb(188,143,143)
royal_blue
=
0x4169E1
,
// rgb(65,105,225)
saddle_brown
=
0x8B4513
,
// rgb(139,69,19)
salmon
=
0xFA8072
,
// rgb(250,128,114)
sandy_brown
=
0xF4A460
,
// rgb(244,164,96)
sea_green
=
0x2E8B57
,
// rgb(46,139,87)
sea_shell
=
0xFFF5EE
,
// rgb(255,245,238)
sienna
=
0xA0522D
,
// rgb(160,82,45)
silver
=
0xC0C0C0
,
// rgb(192,192,192)
sky_blue
=
0x87CEEB
,
// rgb(135,206,235)
slate_blue
=
0x6A5ACD
,
// rgb(106,90,205)
slate_gray
=
0x708090
,
// rgb(112,128,144)
snow
=
0xFFFAFA
,
// rgb(255,250,250)
spring_green
=
0x00FF7F
,
// rgb(0,255,127)
steel_blue
=
0x4682B4
,
// rgb(70,130,180)
tan
=
0xD2B48C
,
// rgb(210,180,140)
teal
=
0x008080
,
// rgb(0,128,128)
thistle
=
0xD8BFD8
,
// rgb(216,191,216)
tomato
=
0xFF6347
,
// rgb(255,99,71)
turquoise
=
0x40E0D0
,
// rgb(64,224,208)
violet
=
0xEE82EE
,
// rgb(238,130,238)
wheat
=
0xF5DEB3
,
// rgb(245,222,179)
white
=
0xFFFFFF
,
// rgb(255,255,255)
white_smoke
=
0xF5F5F5
,
// rgb(245,245,245)
yellow
=
0xFFFF00
,
// rgb(255,255,0)
yellow_green
=
0x9ACD32
,
// rgb(154,205,50)
};
// enum class colors
FMT_END_NAMESPACE
#endif // FMT_COLORS_H_
include/spdlog/fmt/bundled/core.h
0 → 100644
View file @
3f438a80
// Formatting library for C++ - the core API
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_CORE_H_
#define FMT_CORE_H_
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iterator>
#include <string>
#include <type_traits>
// The fmt library version in the form major * 10000 + minor * 100 + patch.
#define FMT_VERSION 50100
#ifdef __has_feature
#define FMT_HAS_FEATURE(x) __has_feature(x)
#else
#define FMT_HAS_FEATURE(x) 0
#endif
#ifdef __has_include
#define FMT_HAS_INCLUDE(x) __has_include(x)
#else
#define FMT_HAS_INCLUDE(x) 0
#endif
#ifdef __has_cpp_attribute
#define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
#define FMT_HAS_CPP_ATTRIBUTE(x) 0
#endif
#if defined(__GNUC__) && !defined(__clang__)
#define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#else
#define FMT_GCC_VERSION 0
#endif
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
#define FMT_HAS_GXX_CXX11 FMT_GCC_VERSION
#else
#define FMT_HAS_GXX_CXX11 0
#endif
#ifdef _MSC_VER
#define FMT_MSC_VER _MSC_VER
#else
#define FMT_MSC_VER 0
#endif
// Check if relaxed c++14 constexpr is supported.
// GCC doesn't allow throw in constexpr until version 6 (bug 67371).
#ifndef FMT_USE_CONSTEXPR
#define FMT_USE_CONSTEXPR \
(FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1910 || (FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L))
#endif
#if FMT_USE_CONSTEXPR
#define FMT_CONSTEXPR constexpr
#define FMT_CONSTEXPR_DECL constexpr
#else
#define FMT_CONSTEXPR inline
#define FMT_CONSTEXPR_DECL
#endif
#ifndef FMT_OVERRIDE
#if 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
#if FMT_HAS_FEATURE(cxx_explicit_conversions) || FMT_MSC_VER >= 1800
#define FMT_EXPLICIT explicit
#else
#define FMT_EXPLICIT
#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
#define FMT_USE_NULLPTR 1
#else
#define FMT_NULL NULL
#endif
#endif
#ifndef FMT_USE_NULLPTR
#define FMT_USE_NULLPTR 0
#endif
#if FMT_HAS_CPP_ATTRIBUTE(noreturn)
#define FMT_NORETURN [[noreturn]]
#else
#define FMT_NORETURN
#endif
// Check if exceptions are disabled.
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
#define FMT_EXCEPTIONS 0
#elif FMT_MSC_VER && !_HAS_EXCEPTIONS
#define FMT_EXCEPTIONS 0
#endif
#ifndef FMT_EXCEPTIONS
#define FMT_EXCEPTIONS 1
#endif
// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature).
#ifndef FMT_USE_NOEXCEPT
#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()
#endif
#ifndef FMT_NOEXCEPT
#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
#else
#define FMT_DTOR_NOEXCEPT FMT_NOEXCEPT
#endif
#ifndef FMT_BEGIN_NAMESPACE
#if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || FMT_MSC_VER >= 1900
#define FMT_INLINE_NAMESPACE inline namespace
#define FMT_END_NAMESPACE \
} \
}
#else
#define FMT_INLINE_NAMESPACE namespace
#define FMT_END_NAMESPACE \
} \
using namespace v5; \
}
#endif
#define FMT_BEGIN_NAMESPACE \
namespace fmt { \
FMT_INLINE_NAMESPACE v5 \
{
#endif
#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
#endif
#ifndef FMT_API
#define FMT_API
#endif
#ifndef FMT_ASSERT
#define FMT_ASSERT(condition, message) assert((condition) && message)
#endif
#define FMT_DELETED = delete
// A macro to disallow the copy construction and assignment.
#define FMT_DISALLOW_COPY_AND_ASSIGN(Type) \
Type(const Type &) FMT_DELETED; \
void operator=(const Type &) FMT_DELETED
// libc++ supports string_view in pre-c++17.
#if (FMT_HAS_INCLUDE(<string_view>) && (__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \
(defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
#include <string_view>
#define FMT_USE_STD_STRING_VIEW
#elif (FMT_HAS_INCLUDE(<experimental / string_view>) && __cplusplus >= 201402L)
#include <experimental/string_view>
#define FMT_USE_EXPERIMENTAL_STRING_VIEW
#endif
// std::result_of is defined in <functional> in gcc 4.4.
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 404
#include <functional>
#endif
FMT_BEGIN_NAMESPACE
// An implementation of declval for pre-C++11 compilers such as gcc 4.
namespace
internal
{
template
<
typename
T
>
typename
std
::
add_rvalue_reference
<
T
>::
type
declval
()
FMT_NOEXCEPT
;
}
/**
An implementation of ``std::basic_string_view`` for pre-C++17. It provides a
subset of the API. ``fmt::basic_string_view`` is used for format strings even
if ``std::string_view`` is available to prevent issues when a library is
compiled with a different ``-std`` option than the client code (which is not
recommended).
*/
template
<
typename
Char
>
class
basic_string_view
{
private:
const
Char
*
data_
;
size_t
size_
;
public:
typedef
Char
char_type
;
typedef
const
Char
*
iterator
;
// Standard basic_string_view type.
#if defined(FMT_USE_STD_STRING_VIEW)
typedef
std
::
basic_string_view
<
Char
>
type
;
#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)
typedef
std
::
experimental
::
basic_string_view
<
Char
>
type
;
#else
struct
type
{
const
char
*
data
()
const
{
return
FMT_NULL
;
}
size_t
size
()
const
{
return
0
;
}
};
#endif
FMT_CONSTEXPR
basic_string_view
()
FMT_NOEXCEPT
:
data_
(
FMT_NULL
),
size_
(
0
)
{}
/** Constructs a string reference object from a C string and a size. */
FMT_CONSTEXPR
basic_string_view
(
const
Char
*
s
,
size_t
str_size
)
FMT_NOEXCEPT
:
data_
(
s
),
size_
(
str_size
)
{}
/**
\rst
Constructs a string reference object from a C string computing
the size with ``std::char_traits<Char>::length``.
\endrst
*/
basic_string_view
(
const
Char
*
s
)
:
data_
(
s
)
,
size_
(
std
::
char_traits
<
Char
>::
length
(
s
))
{
}
/** Constructs a string reference from a ``std::basic_string`` object. */
template
<
typename
Alloc
>
FMT_CONSTEXPR
basic_string_view
(
const
std
::
basic_string
<
Char
,
Alloc
>
&
s
)
FMT_NOEXCEPT
:
data_
(
s
.
c_str
()),
size_
(
s
.
size
())
{
}
FMT_CONSTEXPR
basic_string_view
(
type
s
)
FMT_NOEXCEPT
:
data_
(
s
.
data
()),
size_
(
s
.
size
())
{}
/** Returns a pointer to the string data. */
const
Char
*
data
()
const
{
return
data_
;
}
/** Returns the string size. */
FMT_CONSTEXPR
size_t
size
()
const
{
return
size_
;
}
FMT_CONSTEXPR
iterator
begin
()
const
{
return
data_
;
}
FMT_CONSTEXPR
iterator
end
()
const
{
return
data_
+
size_
;
}
FMT_CONSTEXPR
void
remove_prefix
(
size_t
n
)
{
data_
+=
n
;
size_
-=
n
;
}
// Lexicographically compare this string reference to other.
int
compare
(
basic_string_view
other
)
const
{
size_t
str_size
=
size_
<
other
.
size_
?
size_
:
other
.
size_
;
int
result
=
std
::
char_traits
<
Char
>::
compare
(
data_
,
other
.
data_
,
str_size
);
if
(
result
==
0
)
result
=
size_
==
other
.
size_
?
0
:
(
size_
<
other
.
size_
?
-
1
:
1
);
return
result
;
}
friend
bool
operator
==
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
return
lhs
.
compare
(
rhs
)
==
0
;
}
friend
bool
operator
!=
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
return
lhs
.
compare
(
rhs
)
!=
0
;
}
friend
bool
operator
<
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
return
lhs
.
compare
(
rhs
)
<
0
;
}
friend
bool
operator
<=
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
return
lhs
.
compare
(
rhs
)
<=
0
;
}
friend
bool
operator
>
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
return
lhs
.
compare
(
rhs
)
>
0
;
}
friend
bool
operator
>=
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
return
lhs
.
compare
(
rhs
)
>=
0
;
}
};
typedef
basic_string_view
<
char
>
string_view
;
typedef
basic_string_view
<
wchar_t
>
wstring_view
;
template
<
typename
Context
>
class
basic_format_arg
;
template
<
typename
Context
>
class
basic_format_args
;
// A formatter for objects of type T.
template
<
typename
T
,
typename
Char
=
char
,
typename
Enable
=
void
>
struct
formatter
;
namespace
internal
{
/** A contiguous memory buffer with an optional growing ability. */
template
<
typename
T
>
class
basic_buffer
{
private:
FMT_DISALLOW_COPY_AND_ASSIGN
(
basic_buffer
);
T
*
ptr_
;
std
::
size_t
size_
;
std
::
size_t
capacity_
;
protected:
basic_buffer
(
T
*
p
=
FMT_NULL
,
std
::
size_t
buf_size
=
0
,
std
::
size_t
buf_capacity
=
0
)
FMT_NOEXCEPT
:
ptr_
(
p
),
size_
(
buf_size
),
capacity_
(
buf_capacity
)
{
}
/** Sets the buffer data and capacity. */
void
set
(
T
*
buf_data
,
std
::
size_t
buf_capacity
)
FMT_NOEXCEPT
{
ptr_
=
buf_data
;
capacity_
=
buf_capacity
;
}
/** Increases the buffer capacity to hold at least *capacity* elements. */
virtual
void
grow
(
std
::
size_t
capacity
)
=
0
;
public:
typedef
T
value_type
;
typedef
const
T
&
const_reference
;
virtual
~
basic_buffer
()
{}
T
*
begin
()
FMT_NOEXCEPT
{
return
ptr_
;
}
T
*
end
()
FMT_NOEXCEPT
{
return
ptr_
+
size_
;
}
/** Returns the size of this buffer. */
std
::
size_t
size
()
const
FMT_NOEXCEPT
{
return
size_
;
}
/** Returns the capacity of this buffer. */
std
::
size_t
capacity
()
const
FMT_NOEXCEPT
{
return
capacity_
;
}
/** Returns a pointer to the buffer data. */
T
*
data
()
FMT_NOEXCEPT
{
return
ptr_
;
}
/** Returns a pointer to the buffer data. */
const
T
*
data
()
const
FMT_NOEXCEPT
{
return
ptr_
;
}
/**
Resizes the buffer. If T is a POD type new elements may not be initialized.
*/
void
resize
(
std
::
size_t
new_size
)
{
reserve
(
new_size
);
size_
=
new_size
;
}
/** Reserves space to store at least *buf_capacity* elements. */
void
reserve
(
std
::
size_t
buf_capacity
)
{
if
(
buf_capacity
>
capacity_
)
grow
(
buf_capacity
);
}
void
push_back
(
const
T
&
value
)
{
reserve
(
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
];
}
};
typedef
basic_buffer
<
char
>
buffer
;
typedef
basic_buffer
<
wchar_t
>
wbuffer
;
// A container-backed buffer.
template
<
typename
Container
>
class
container_buffer
:
public
basic_buffer
<
typename
Container
::
value_type
>
{
private:
Container
&
container_
;
protected:
void
grow
(
std
::
size_t
capacity
)
FMT_OVERRIDE
{
container_
.
resize
(
capacity
);
this
->
set
(
&
container_
[
0
],
capacity
);
}
public:
explicit
container_buffer
(
Container
&
c
)
:
basic_buffer
<
typename
Container
::
value_type
>
(
&
c
[
0
],
c
.
size
(),
c
.
size
())
,
container_
(
c
)
{
}
};
struct
error_handler
{
FMT_CONSTEXPR
error_handler
()
{}
FMT_CONSTEXPR
error_handler
(
const
error_handler
&
)
{}
// This function is intentionally not constexpr to give a compile-time error.
FMT_API
void
on_error
(
const
char
*
message
);
};
// Formatting of wide characters and strings into a narrow output is disallowed:
// fmt::format("{}", L"test"); // error
// To fix this, use a wide format string:
// fmt::format(L"{}", L"test");
template
<
typename
Char
>
inline
void
require_wchar
()
{
static_assert
(
std
::
is_same
<
wchar_t
,
Char
>::
value
,
"formatting of wide characters into a narrow output is disallowed"
);
}
template
<
typename
Char
>
struct
named_arg_base
;
template
<
typename
T
,
typename
Char
>
struct
named_arg
;
template
<
typename
T
>
struct
is_named_arg
:
std
::
false_type
{
};
template
<
typename
T
,
typename
Char
>
struct
is_named_arg
<
named_arg
<
T
,
Char
>>
:
std
::
true_type
{
};
enum
type
{
none_type
,
named_arg_type
,
// Integer types should go first,
int_type
,
uint_type
,
long_long_type
,
ulong_long_type
,
bool_type
,
char_type
,
last_integer_type
=
char_type
,
// followed by floating-point types.
double_type
,
long_double_type
,
last_numeric_type
=
long_double_type
,
cstring_type
,
string_type
,
pointer_type
,
custom_type
};
FMT_CONSTEXPR
bool
is_integral
(
type
t
)
{
FMT_ASSERT
(
t
!=
internal
::
named_arg_type
,
"invalid argument type"
);
return
t
>
internal
::
none_type
&&
t
<=
internal
::
last_integer_type
;
}
FMT_CONSTEXPR
bool
is_arithmetic
(
type
t
)
{
FMT_ASSERT
(
t
!=
internal
::
named_arg_type
,
"invalid argument type"
);
return
t
>
internal
::
none_type
&&
t
<=
internal
::
last_numeric_type
;
}
template
<
typename
T
,
typename
Char
,
bool
ENABLE
=
true
>
struct
convert_to_int
{
enum
{
value
=
!
std
::
is_arithmetic
<
T
>::
value
&&
std
::
is_convertible
<
T
,
int
>::
value
};
};
template
<
typename
Char
>
struct
string_value
{
const
Char
*
value
;
std
::
size_t
size
;
};
template
<
typename
Context
>
struct
custom_value
{
const
void
*
value
;
void
(
*
format
)(
const
void
*
arg
,
Context
&
ctx
);
};
// A formatting argument value.
template
<
typename
Context
>
class
value
{
public:
typedef
typename
Context
::
char_type
char_type
;
union
{
int
int_value
;
unsigned
uint_value
;
long
long
long_long_value
;
unsigned
long
long
ulong_long_value
;
double
double_value
;
long
double
long_double_value
;
const
void
*
pointer
;
string_value
<
char_type
>
string
;
string_value
<
signed
char
>
sstring
;
string_value
<
unsigned
char
>
ustring
;
custom_value
<
Context
>
custom
;
};
FMT_CONSTEXPR
value
(
int
val
=
0
)
:
int_value
(
val
)
{
}
value
(
unsigned
val
)
{
uint_value
=
val
;
}
value
(
long
long
val
)
{
long_long_value
=
val
;
}
value
(
unsigned
long
long
val
)
{
ulong_long_value
=
val
;
}
value
(
double
val
)
{
double_value
=
val
;
}
value
(
long
double
val
)
{
long_double_value
=
val
;
}
value
(
const
char_type
*
val
)
{
string
.
value
=
val
;
}
value
(
const
signed
char
*
val
)
{
static_assert
(
std
::
is_same
<
char
,
char_type
>::
value
,
"incompatible string types"
);
sstring
.
value
=
val
;
}
value
(
const
unsigned
char
*
val
)
{
static_assert
(
std
::
is_same
<
char
,
char_type
>::
value
,
"incompatible string types"
);
ustring
.
value
=
val
;
}
value
(
basic_string_view
<
char_type
>
val
)
{
string
.
value
=
val
.
data
();
string
.
size
=
val
.
size
();
}
value
(
const
void
*
val
)
{
pointer
=
val
;
}
template
<
typename
T
>
explicit
value
(
const
T
&
val
)
{
custom
.
value
=
&
val
;
custom
.
format
=
&
format_custom_arg
<
T
>
;
}
const
named_arg_base
<
char_type
>
&
as_named_arg
()
{
return
*
static_cast
<
const
named_arg_base
<
char_type
>
*>
(
pointer
);
}
private:
// Formats an argument of a custom type, such as a user-defined class.
template
<
typename
T
>
static
void
format_custom_arg
(
const
void
*
arg
,
Context
&
ctx
)
{
// Get the formatter type through the context to allow different contexts
// have different extension points, e.g. `formatter<T>` for `format` and
// `printf_formatter<T>` for `printf`.
typename
Context
::
template
formatter_type
<
T
>
::
type
f
;
auto
&&
parse_ctx
=
ctx
.
parse_context
();
parse_ctx
.
advance_to
(
f
.
parse
(
parse_ctx
));
ctx
.
advance_to
(
f
.
format
(
*
static_cast
<
const
T
*>
(
arg
),
ctx
));
}
};
template
<
typename
Context
,
type
TYPE
>
struct
typed_value
:
value
<
Context
>
{
static
const
type
type_tag
=
TYPE
;
template
<
typename
T
>
FMT_CONSTEXPR
typed_value
(
const
T
&
val
)
:
value
<
Context
>
(
val
)
{
}
};
template
<
typename
Context
,
typename
T
>
FMT_CONSTEXPR
basic_format_arg
<
Context
>
make_arg
(
const
T
&
value
);
#define FMT_MAKE_VALUE(TAG, ArgType, ValueType) \
template<typename C> \
FMT_CONSTEXPR typed_value<C, TAG> make_value(ArgType val) \
{ \
return static_cast<ValueType>(val); \
}
#define FMT_MAKE_VALUE_SAME(TAG, Type) \
template<typename C> \
FMT_CONSTEXPR typed_value<C, TAG> make_value(Type val) \
{ \
return val; \
}
FMT_MAKE_VALUE
(
bool_type
,
bool
,
int
)
FMT_MAKE_VALUE
(
int_type
,
short
,
int
)
FMT_MAKE_VALUE
(
uint_type
,
unsigned
short
,
unsigned
)
FMT_MAKE_VALUE_SAME
(
int_type
,
int
)
FMT_MAKE_VALUE_SAME
(
uint_type
,
unsigned
)
// To minimize the number of types we need to deal with, long is translated
// either to int or to long long depending on its size.
typedef
std
::
conditional
<
sizeof
(
long
)
==
sizeof
(
int
),
int
,
long
long
>::
type
long_type
;
FMT_MAKE_VALUE
((
sizeof
(
long
)
==
sizeof
(
int
)
?
int_type
:
long_long_type
),
long
,
long_type
)
typedef
std
::
conditional
<
sizeof
(
unsigned
long
)
==
sizeof
(
unsigned
),
unsigned
,
unsigned
long
long
>::
type
ulong_type
;
FMT_MAKE_VALUE
((
sizeof
(
unsigned
long
)
==
sizeof
(
unsigned
)
?
uint_type
:
ulong_long_type
),
unsigned
long
,
ulong_type
)
FMT_MAKE_VALUE_SAME
(
long_long_type
,
long
long
)
FMT_MAKE_VALUE_SAME
(
ulong_long_type
,
unsigned
long
long
)
FMT_MAKE_VALUE
(
int_type
,
signed
char
,
int
)
FMT_MAKE_VALUE
(
uint_type
,
unsigned
char
,
unsigned
)
FMT_MAKE_VALUE
(
char_type
,
char
,
int
)
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
template
<
typename
C
>
inline
typed_value
<
C
,
char_type
>
make_value
(
wchar_t
val
)
{
require_wchar
<
typename
C
::
char_type
>
();
return
static_cast
<
int
>
(
val
);
}
#endif
FMT_MAKE_VALUE
(
double_type
,
float
,
double
)
FMT_MAKE_VALUE_SAME
(
double_type
,
double
)
FMT_MAKE_VALUE_SAME
(
long_double_type
,
long
double
)
// Formatting of wide strings into a narrow buffer and multibyte strings
// into a wide buffer is disallowed (https://github.com/fmtlib/fmt/pull/606).
FMT_MAKE_VALUE
(
cstring_type
,
typename
C
::
char_type
*
,
const
typename
C
::
char_type
*
)
FMT_MAKE_VALUE
(
cstring_type
,
const
typename
C
::
char_type
*
,
const
typename
C
::
char_type
*
)
FMT_MAKE_VALUE
(
cstring_type
,
signed
char
*
,
const
signed
char
*
)
FMT_MAKE_VALUE_SAME
(
cstring_type
,
const
signed
char
*
)
FMT_MAKE_VALUE
(
cstring_type
,
unsigned
char
*
,
const
unsigned
char
*
)
FMT_MAKE_VALUE_SAME
(
cstring_type
,
const
unsigned
char
*
)
FMT_MAKE_VALUE_SAME
(
string_type
,
basic_string_view
<
typename
C
::
char_type
>
)
FMT_MAKE_VALUE
(
string_type
,
typename
basic_string_view
<
typename
C
::
char_type
>::
type
,
basic_string_view
<
typename
C
::
char_type
>
)
FMT_MAKE_VALUE
(
string_type
,
const
std
::
basic_string
<
typename
C
::
char_type
>
&
,
basic_string_view
<
typename
C
::
char_type
>
)
FMT_MAKE_VALUE
(
pointer_type
,
void
*
,
const
void
*
)
FMT_MAKE_VALUE_SAME
(
pointer_type
,
const
void
*
)
#if FMT_USE_NULLPTR
FMT_MAKE_VALUE
(
pointer_type
,
std
::
nullptr_t
,
const
void
*
)
#endif
// Formatting of arbitrary pointers is disallowed. If you want to output a
// pointer cast it to "void *" or "const void *". In particular, this forbids
// formatting of "[const] volatile char *" which is printed as bool by
// iostreams.
template
<
typename
C
,
typename
T
>
typename
std
::
enable_if
<!
std
::
is_same
<
T
,
typename
C
::
char_type
>::
value
>::
type
make_value
(
const
T
*
)
{
static_assert
(
!
sizeof
(
T
),
"formatting of non-void pointers is disallowed"
);
}
template
<
typename
C
,
typename
T
>
inline
typename
std
::
enable_if
<
std
::
is_enum
<
T
>::
value
&&
convert_to_int
<
T
,
typename
C
::
char_type
>::
value
,
typed_value
<
C
,
int_type
>>::
type
make_value
(
const
T
&
val
)
{
return
static_cast
<
int
>
(
val
);
}
template
<
typename
C
,
typename
T
,
typename
Char
=
typename
C
::
char_type
>
inline
typename
std
::
enable_if
<!
convert_to_int
<
T
,
Char
>::
value
&&
!
std
::
is_convertible
<
T
,
basic_string_view
<
Char
>>::
value
,
// Implicit conversion to std::string is not handled here because it's
// unsafe: https://github.com/fmtlib/fmt/issues/729
typed_value
<
C
,
custom_type
>>::
type
make_value
(
const
T
&
val
)
{
return
val
;
}
template
<
typename
C
,
typename
T
>
typed_value
<
C
,
named_arg_type
>
make_value
(
const
named_arg
<
T
,
typename
C
::
char_type
>
&
val
)
{
basic_format_arg
<
C
>
arg
=
make_arg
<
C
>
(
val
.
value
);
std
::
memcpy
(
val
.
data
,
&
arg
,
sizeof
(
arg
));
return
static_cast
<
const
void
*>
(
&
val
);
}
// Maximum number of arguments with packed types.
enum
{
max_packed_args
=
15
};
template
<
typename
Context
>
class
arg_map
;
template
<
typename
>
struct
result_of
;
template
<
typename
F
,
typename
...
Args
>
struct
result_of
<
F
(
Args
...)
>
{
// A workaround for gcc 4.4 that doesn't allow F to be a reference.
typedef
typename
std
::
result_of
<
typename
std
::
remove_reference
<
F
>::
type
(
Args
...)
>::
type
type
;
};
}
// namespace internal
// A formatting argument. It is a trivially copyable/constructible type to
// allow storage in basic_memory_buffer.
template
<
typename
Context
>
class
basic_format_arg
{
private:
internal
::
value
<
Context
>
value_
;
internal
::
type
type_
;
template
<
typename
ContextType
,
typename
T
>
friend
FMT_CONSTEXPR
basic_format_arg
<
ContextType
>
internal
::
make_arg
(
const
T
&
value
);
template
<
typename
Visitor
,
typename
Ctx
>
friend
FMT_CONSTEXPR
typename
internal
::
result_of
<
Visitor
(
int
)
>::
type
visit
(
Visitor
&&
vis
,
basic_format_arg
<
Ctx
>
arg
);
friend
class
basic_format_args
<
Context
>
;
friend
class
internal
::
arg_map
<
Context
>
;
typedef
typename
Context
::
char_type
char_type
;
public:
class
handle
{
public:
explicit
handle
(
internal
::
custom_value
<
Context
>
custom
)
:
custom_
(
custom
)
{
}
void
format
(
Context
&
ctx
)
const
{
custom_
.
format
(
custom_
.
value
,
ctx
);
}
private:
internal
::
custom_value
<
Context
>
custom_
;
};
FMT_CONSTEXPR
basic_format_arg
()
:
type_
(
internal
::
none_type
)
{
}
FMT_EXPLICIT
operator
bool
()
const
FMT_NOEXCEPT
{
return
type_
!=
internal
::
none_type
;
}
internal
::
type
type
()
const
{
return
type_
;
}
bool
is_integral
()
const
{
return
internal
::
is_integral
(
type_
);
}
bool
is_arithmetic
()
const
{
return
internal
::
is_arithmetic
(
type_
);
}
};
// Parsing context consisting of a format string range being parsed and an
// argument counter for automatic indexing.
template
<
typename
Char
,
typename
ErrorHandler
=
internal
::
error_handler
>
class
basic_parse_context
:
private
ErrorHandler
{
private:
basic_string_view
<
Char
>
format_str_
;
int
next_arg_id_
;
public:
typedef
Char
char_type
;
typedef
typename
basic_string_view
<
Char
>::
iterator
iterator
;
explicit
FMT_CONSTEXPR
basic_parse_context
(
basic_string_view
<
Char
>
format_str
,
ErrorHandler
eh
=
ErrorHandler
())
:
ErrorHandler
(
eh
)
,
format_str_
(
format_str
)
,
next_arg_id_
(
0
)
{
}
// Returns an iterator to the beginning of the format string range being
// parsed.
FMT_CONSTEXPR
iterator
begin
()
const
FMT_NOEXCEPT
{
return
format_str_
.
begin
();
}
// Returns an iterator past the end of the format string range being parsed.
FMT_CONSTEXPR
iterator
end
()
const
FMT_NOEXCEPT
{
return
format_str_
.
end
();
}
// Advances the begin iterator to ``it``.
FMT_CONSTEXPR
void
advance_to
(
iterator
it
)
{
format_str_
.
remove_prefix
(
it
-
begin
());
}
// Returns the next argument index.
FMT_CONSTEXPR
unsigned
next_arg_id
();
FMT_CONSTEXPR
bool
check_arg_id
(
unsigned
)
{
if
(
next_arg_id_
>
0
)
{
on_error
(
"cannot switch from automatic to manual argument indexing"
);
return
false
;
}
next_arg_id_
=
-
1
;
return
true
;
}
void
check_arg_id
(
basic_string_view
<
Char
>
)
{}
FMT_CONSTEXPR
void
on_error
(
const
char
*
message
)
{
ErrorHandler
::
on_error
(
message
);
}
FMT_CONSTEXPR
ErrorHandler
error_handler
()
const
{
return
*
this
;
}
};
typedef
basic_parse_context
<
char
>
parse_context
;
typedef
basic_parse_context
<
wchar_t
>
wparse_context
;
namespace
internal
{
// A map from argument names to their values for named arguments.
template
<
typename
Context
>
class
arg_map
{
private:
FMT_DISALLOW_COPY_AND_ASSIGN
(
arg_map
);
typedef
typename
Context
::
char_type
char_type
;
struct
entry
{
basic_string_view
<
char_type
>
name
;
basic_format_arg
<
Context
>
arg
;
};
entry
*
map_
;
unsigned
size_
;
void
push_back
(
value
<
Context
>
val
)
{
const
internal
::
named_arg_base
<
char_type
>
&
named
=
val
.
as_named_arg
();
map_
[
size_
]
=
entry
{
named
.
name
,
named
.
template
deserialize
<
Context
>()};
++
size_
;
}
public:
arg_map
()
:
map_
(
FMT_NULL
)
,
size_
(
0
)
{
}
void
init
(
const
basic_format_args
<
Context
>
&
args
);
~
arg_map
()
{
delete
[]
map_
;
}
basic_format_arg
<
Context
>
find
(
basic_string_view
<
char_type
>
name
)
const
{
// The list is unsorted, so just return the first matching name.
for
(
entry
*
it
=
map_
,
*
end
=
map_
+
size_
;
it
!=
end
;
++
it
)
{
if
(
it
->
name
==
name
)
return
it
->
arg
;
}
return
basic_format_arg
<
Context
>
();
}
};
template
<
typename
OutputIt
,
typename
Context
,
typename
Char
>
class
context_base
{
public:
typedef
OutputIt
iterator
;
private:
basic_parse_context
<
Char
>
parse_context_
;
iterator
out_
;
basic_format_args
<
Context
>
args_
;
protected:
typedef
Char
char_type
;
typedef
basic_format_arg
<
Context
>
format_arg
;
context_base
(
OutputIt
out
,
basic_string_view
<
char_type
>
format_str
,
basic_format_args
<
Context
>
ctx_args
)
:
parse_context_
(
format_str
)
,
out_
(
out
)
,
args_
(
ctx_args
)
{
}
// Returns the argument with specified index.
format_arg
do_get_arg
(
unsigned
arg_id
)
{
format_arg
arg
=
args_
.
get
(
arg_id
);
if
(
!
arg
)
parse_context_
.
on_error
(
"argument index out of range"
);
return
arg
;
}
// Checks if manual indexing is used and returns the argument with
// specified index.
format_arg
get_arg
(
unsigned
arg_id
)
{
return
this
->
parse_context
().
check_arg_id
(
arg_id
)
?
this
->
do_get_arg
(
arg_id
)
:
format_arg
();
}
public:
basic_parse_context
<
char_type
>
&
parse_context
()
{
return
parse_context_
;
}
internal
::
error_handler
error_handler
()
{
return
parse_context_
.
error_handler
();
}
void
on_error
(
const
char
*
message
)
{
parse_context_
.
on_error
(
message
);
}
// Returns an iterator to the beginning of the output range.
iterator
out
()
{
return
out_
;
}
iterator
begin
()
{
return
out_
;
}
// deprecated
// Advances the begin iterator to ``it``.
void
advance_to
(
iterator
it
)
{
out_
=
it
;
}
basic_format_args
<
Context
>
args
()
const
{
return
args_
;
}
};
// Extracts a reference to the container from back_insert_iterator.
template
<
typename
Container
>
inline
Container
&
get_container
(
std
::
back_insert_iterator
<
Container
>
it
)
{
typedef
std
::
back_insert_iterator
<
Container
>
bi_iterator
;
struct
accessor
:
bi_iterator
{
accessor
(
bi_iterator
iter
)
:
bi_iterator
(
iter
)
{
}
using
bi_iterator
::
container
;
};
return
*
accessor
(
it
).
container
;
}
}
// namespace internal
// Formatting context.
template
<
typename
OutputIt
,
typename
Char
>
class
basic_format_context
:
public
internal
::
context_base
<
OutputIt
,
basic_format_context
<
OutputIt
,
Char
>
,
Char
>
{
public:
/** The character type for the output. */
typedef
Char
char_type
;
// using formatter_type = formatter<T, char_type>;
template
<
typename
T
>
struct
formatter_type
{
typedef
formatter
<
T
,
char_type
>
type
;
};
private:
internal
::
arg_map
<
basic_format_context
>
map_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
basic_format_context
);
typedef
internal
::
context_base
<
OutputIt
,
basic_format_context
,
Char
>
base
;
typedef
typename
base
::
format_arg
format_arg
;
using
base
::
get_arg
;
public:
using
typename
base
::
iterator
;
/**
Constructs a ``basic_format_context`` object. References to the arguments are
stored in the object so make sure they have appropriate lifetimes.
*/
basic_format_context
(
OutputIt
out
,
basic_string_view
<
char_type
>
format_str
,
basic_format_args
<
basic_format_context
>
ctx_args
)
:
base
(
out
,
format_str
,
ctx_args
)
{
}
format_arg
next_arg
()
{
return
this
->
do_get_arg
(
this
->
parse_context
().
next_arg_id
());
}
format_arg
get_arg
(
unsigned
arg_id
)
{
return
this
->
do_get_arg
(
arg_id
);
}
// Checks if manual indexing is used and returns the argument with the
// specified name.
format_arg
get_arg
(
basic_string_view
<
char_type
>
name
);
};
template
<
typename
Char
>
struct
buffer_context
{
typedef
basic_format_context
<
std
::
back_insert_iterator
<
internal
::
basic_buffer
<
Char
>>
,
Char
>
type
;
};
typedef
buffer_context
<
char
>::
type
format_context
;
typedef
buffer_context
<
wchar_t
>::
type
wformat_context
;
namespace
internal
{
template
<
typename
Context
,
typename
T
>
struct
get_type
{
typedef
decltype
(
make_value
<
Context
>
(
declval
<
typename
std
::
decay
<
T
>::
type
&>
()))
value_type
;
static
const
type
value
=
value_type
::
type_tag
;
};
template
<
typename
Context
>
FMT_CONSTEXPR
uint64_t
get_types
()
{
return
0
;
}
template
<
typename
Context
,
typename
Arg
,
typename
...
Args
>
FMT_CONSTEXPR
uint64_t
get_types
()
{
return
get_type
<
Context
,
Arg
>::
value
|
(
get_types
<
Context
,
Args
...
>
()
<<
4
);
}
template
<
typename
Context
,
typename
T
>
FMT_CONSTEXPR
basic_format_arg
<
Context
>
make_arg
(
const
T
&
value
)
{
basic_format_arg
<
Context
>
arg
;
arg
.
type_
=
get_type
<
Context
,
T
>::
value
;
arg
.
value_
=
make_value
<
Context
>
(
value
);
return
arg
;
}
template
<
bool
IS_PACKED
,
typename
Context
,
typename
T
>
inline
typename
std
::
enable_if
<
IS_PACKED
,
value
<
Context
>>::
type
make_arg
(
const
T
&
value
)
{
return
make_value
<
Context
>
(
value
);
}
template
<
bool
IS_PACKED
,
typename
Context
,
typename
T
>
inline
typename
std
::
enable_if
<!
IS_PACKED
,
basic_format_arg
<
Context
>>::
type
make_arg
(
const
T
&
value
)
{
return
make_arg
<
Context
>
(
value
);
}
}
// namespace internal
/**
\rst
An array of references to arguments. It can be implicitly converted into
`~fmt::basic_format_args` for passing into type-erased formatting functions
such as `~fmt::vformat`.
\endrst
*/
template
<
typename
Context
,
typename
...
Args
>
class
format_arg_store
{
private:
static
const
size_t
NUM_ARGS
=
sizeof
...(
Args
);
// Packed is a macro on MinGW so use IS_PACKED instead.
static
const
bool
IS_PACKED
=
NUM_ARGS
<
internal
::
max_packed_args
;
typedef
typename
std
::
conditional
<
IS_PACKED
,
internal
::
value
<
Context
>
,
basic_format_arg
<
Context
>>::
type
value_type
;
// If the arguments are not packed, add one more element to mark the end.
value_type
data_
[
NUM_ARGS
+
(
IS_PACKED
&&
NUM_ARGS
!=
0
?
0
:
1
)];
friend
class
basic_format_args
<
Context
>
;
static
FMT_CONSTEXPR
int64_t
get_types
()
{
return
IS_PACKED
?
static_cast
<
int64_t
>
(
internal
::
get_types
<
Context
,
Args
...
>
())
:
-
static_cast
<
int64_t
>
(
NUM_ARGS
);
}
public:
#if FMT_USE_CONSTEXPR
static
constexpr
int64_t
TYPES
=
get_types
();
#else
static
const
int64_t
TYPES
;
#endif
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 405
// Workaround an array initialization bug in gcc 4.5 and earlier.
format_arg_store
(
const
Args
&
...
args
)
{
data_
=
{
internal
::
make_arg
<
IS_PACKED
,
Context
>
(
args
)...};
}
#else
format_arg_store
(
const
Args
&
...
args
)
:
data_
{
internal
::
make_arg
<
IS_PACKED
,
Context
>
(
args
)...}
{
}
#endif
};
#if !FMT_USE_CONSTEXPR
template
<
typename
Context
,
typename
...
Args
>
const
int64_t
format_arg_store
<
Context
,
Args
...
>::
TYPES
=
get_types
();
#endif
/**
\rst
Constructs an `~fmt::format_arg_store` object that contains references to
arguments and can be implicitly converted to `~fmt::format_args`. `Context` can
be omitted in which case it defaults to `~fmt::context`.
\endrst
*/
template
<
typename
Context
,
typename
...
Args
>
inline
format_arg_store
<
Context
,
Args
...
>
make_format_args
(
const
Args
&
...
args
)
{
return
format_arg_store
<
Context
,
Args
...
>
(
args
...);
}
template
<
typename
...
Args
>
inline
format_arg_store
<
format_context
,
Args
...
>
make_format_args
(
const
Args
&
...
args
)
{
return
format_arg_store
<
format_context
,
Args
...
>
(
args
...);
}
/** Formatting arguments. */
template
<
typename
Context
>
class
basic_format_args
{
public:
typedef
unsigned
size_type
;
typedef
basic_format_arg
<
Context
>
format_arg
;
private:
// To reduce compiled code size per formatting function call, types of first
// max_packed_args arguments are passed in the types_ field.
uint64_t
types_
;
union
{
// If the number of arguments is less than max_packed_args, the argument
// values are stored in values_, otherwise they are stored in args_.
// This is done to reduce compiled code size as storing larger objects
// may require more code (at least on x86-64) even if the same amount of
// data is actually copied to stack. It saves ~10% on the bloat test.
const
internal
::
value
<
Context
>
*
values_
;
const
format_arg
*
args_
;
};
typename
internal
::
type
type
(
unsigned
index
)
const
{
unsigned
shift
=
index
*
4
;
uint64_t
mask
=
0xf
;
return
static_cast
<
typename
internal
::
type
>
((
types_
&
(
mask
<<
shift
))
>>
shift
);
}
friend
class
internal
::
arg_map
<
Context
>
;
void
set_data
(
const
internal
::
value
<
Context
>
*
values
)
{
values_
=
values
;
}
void
set_data
(
const
format_arg
*
args
)
{
args_
=
args
;
}
format_arg
do_get
(
size_type
index
)
const
{
int64_t
signed_types
=
static_cast
<
int64_t
>
(
types_
);
if
(
signed_types
<
0
)
{
uint64_t
num_args
=
-
signed_types
;
return
index
<
num_args
?
args_
[
index
]
:
format_arg
();
}
format_arg
arg
;
if
(
index
>
internal
::
max_packed_args
)
return
arg
;
arg
.
type_
=
type
(
index
);
if
(
arg
.
type_
==
internal
::
none_type
)
return
arg
;
internal
::
value
<
Context
>
&
val
=
arg
.
value_
;
val
=
values_
[
index
];
return
arg
;
}
public:
basic_format_args
()
:
types_
(
0
)
{
}
/**
\rst
Constructs a `basic_format_args` object from `~fmt::format_arg_store`.
\endrst
*/
template
<
typename
...
Args
>
basic_format_args
(
const
format_arg_store
<
Context
,
Args
...
>
&
store
)
:
types_
(
store
.
TYPES
)
{
set_data
(
store
.
data_
);
}
/** Returns the argument at specified index. */
format_arg
get
(
size_type
index
)
const
{
format_arg
arg
=
do_get
(
index
);
return
arg
.
type_
==
internal
::
named_arg_type
?
arg
.
value_
.
as_named_arg
().
template
deserialize
<
Context
>()
:
arg
;
}
unsigned
max_size
()
const
{
int64_t
signed_types
=
static_cast
<
int64_t
>
(
types_
);
return
static_cast
<
unsigned
>
(
signed_types
<
0
?
-
signed_types
:
static_cast
<
int64_t
>
(
internal
::
max_packed_args
));
}
};
/** An alias to ``basic_format_args<context>``. */
// It is a separate type rather than a typedef to make symbols readable.
struct
format_args
:
basic_format_args
<
format_context
>
{
template
<
typename
...
Args
>
format_args
(
Args
&&
...
arg
)
:
basic_format_args
<
format_context
>
(
std
::
forward
<
Args
>
(
arg
)...)
{
}
};
struct
wformat_args
:
basic_format_args
<
wformat_context
>
{
template
<
typename
...
Args
>
wformat_args
(
Args
&&
...
arg
)
:
basic_format_args
<
wformat_context
>
(
std
::
forward
<
Args
>
(
arg
)...)
{
}
};
namespace
internal
{
template
<
typename
Char
>
struct
named_arg_base
{
basic_string_view
<
Char
>
name
;
// Serialized value<context>.
mutable
char
data
[
sizeof
(
basic_format_arg
<
format_context
>
)];
named_arg_base
(
basic_string_view
<
Char
>
nm
)
:
name
(
nm
)
{
}
template
<
typename
Context
>
basic_format_arg
<
Context
>
deserialize
()
const
{
basic_format_arg
<
Context
>
arg
;
std
::
memcpy
(
&
arg
,
data
,
sizeof
(
basic_format_arg
<
Context
>
));
return
arg
;
}
};
template
<
typename
T
,
typename
Char
>
struct
named_arg
:
named_arg_base
<
Char
>
{
const
T
&
value
;
named_arg
(
basic_string_view
<
Char
>
name
,
const
T
&
val
)
:
named_arg_base
<
Char
>
(
name
)
,
value
(
val
)
{
}
};
}
// namespace internal
/**
\rst
Returns a named argument to be used in a formatting function.
**Example**::
fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23));
\endrst
*/
template
<
typename
T
>
inline
internal
::
named_arg
<
T
,
char
>
arg
(
string_view
name
,
const
T
&
arg
)
{
return
internal
::
named_arg
<
T
,
char
>
(
name
,
arg
);
}
template
<
typename
T
>
inline
internal
::
named_arg
<
T
,
wchar_t
>
arg
(
wstring_view
name
,
const
T
&
arg
)
{
return
internal
::
named_arg
<
T
,
wchar_t
>
(
name
,
arg
);
}
// This function template is deleted intentionally to disable nested named
// arguments as in ``format("{}", arg("a", arg("b", 42)))``.
template
<
typename
S
,
typename
T
,
typename
Char
>
void
arg
(
S
,
internal
::
named_arg
<
T
,
Char
>
)
FMT_DELETED
;
enum
color
{
black
,
red
,
green
,
yellow
,
blue
,
magenta
,
cyan
,
white
};
FMT_API
void
vprint_colored
(
color
c
,
string_view
format
,
format_args
args
);
FMT_API
void
vprint_colored
(
color
c
,
wstring_view
format
,
wformat_args
args
);
/**
Formats a string and prints it to stdout using ANSI escape sequences to
specify color (experimental).
Example:
fmt::print_colored(fmt::RED, "Elapsed time: {0:.2f} seconds", 1.23);
*/
template
<
typename
...
Args
>
inline
void
print_colored
(
color
c
,
string_view
format_str
,
const
Args
&
...
args
)
{
vprint_colored
(
c
,
format_str
,
make_format_args
(
args
...));
}
template
<
typename
...
Args
>
inline
void
print_colored
(
color
c
,
wstring_view
format_str
,
const
Args
&
...
args
)
{
vprint_colored
(
c
,
format_str
,
make_format_args
<
wformat_context
>
(
args
...));
}
format_context
::
iterator
vformat_to
(
internal
::
buffer
&
buf
,
string_view
format_str
,
format_args
args
);
wformat_context
::
iterator
vformat_to
(
internal
::
wbuffer
&
buf
,
wstring_view
format_str
,
wformat_args
args
);
template
<
typename
Container
>
struct
is_contiguous
:
std
::
false_type
{
};
template
<
typename
Char
>
struct
is_contiguous
<
std
::
basic_string
<
Char
>>
:
std
::
true_type
{
};
template
<
typename
Char
>
struct
is_contiguous
<
internal
::
basic_buffer
<
Char
>>
:
std
::
true_type
{
};
/** Formats a string and writes the output to ``out``. */
template
<
typename
Container
>
typename
std
::
enable_if
<
is_contiguous
<
Container
>::
value
,
std
::
back_insert_iterator
<
Container
>>::
type
vformat_to
(
std
::
back_insert_iterator
<
Container
>
out
,
string_view
format_str
,
format_args
args
)
{
auto
&
container
=
internal
::
get_container
(
out
);
internal
::
container_buffer
<
Container
>
buf
(
container
);
vformat_to
(
buf
,
format_str
,
args
);
return
std
::
back_inserter
(
container
);
}
template
<
typename
Container
>
typename
std
::
enable_if
<
is_contiguous
<
Container
>::
value
,
std
::
back_insert_iterator
<
Container
>>::
type
vformat_to
(
std
::
back_insert_iterator
<
Container
>
out
,
wstring_view
format_str
,
wformat_args
args
)
{
auto
&
container
=
internal
::
get_container
(
out
);
internal
::
container_buffer
<
Container
>
buf
(
container
);
vformat_to
(
buf
,
format_str
,
args
);
return
std
::
back_inserter
(
container
);
}
std
::
string
vformat
(
string_view
format_str
,
format_args
args
);
std
::
wstring
vformat
(
wstring_view
format_str
,
wformat_args
args
);
/**
\rst
Formats arguments and returns the result as a string.
**Example**::
#include <fmt/core.h>
std::string message = fmt::format("The answer is {}", 42);
\endrst
*/
template
<
typename
...
Args
>
inline
std
::
string
format
(
string_view
format_str
,
const
Args
&
...
args
)
{
// This should be just
// return vformat(format_str, make_format_args(args...));
// but gcc has trouble optimizing the latter, so break it down.
format_arg_store
<
format_context
,
Args
...
>
as
{
args
...};
return
vformat
(
format_str
,
as
);
}
template
<
typename
...
Args
>
inline
std
::
wstring
format
(
wstring_view
format_str
,
const
Args
&
...
args
)
{
format_arg_store
<
wformat_context
,
Args
...
>
as
{
args
...};
return
vformat
(
format_str
,
as
);
}
FMT_API
void
vprint
(
std
::
FILE
*
f
,
string_view
format_str
,
format_args
args
);
FMT_API
void
vprint
(
std
::
FILE
*
f
,
wstring_view
format_str
,
wformat_args
args
);
/**
\rst
Prints formatted data to the file *f*.
**Example**::
fmt::print(stderr, "Don't {}!", "panic");
\endrst
*/
template
<
typename
...
Args
>
inline
void
print
(
std
::
FILE
*
f
,
string_view
format_str
,
const
Args
&
...
args
)
{
format_arg_store
<
format_context
,
Args
...
>
as
(
args
...);
vprint
(
f
,
format_str
,
as
);
}
/**
Prints formatted data to the file *f* which should be in wide-oriented mode set
via ``fwide(f, 1)`` or ``_setmode(_fileno(f), _O_U8TEXT)`` on Windows.
*/
template
<
typename
...
Args
>
inline
void
print
(
std
::
FILE
*
f
,
wstring_view
format_str
,
const
Args
&
...
args
)
{
format_arg_store
<
wformat_context
,
Args
...
>
as
(
args
...);
vprint
(
f
,
format_str
,
as
);
}
FMT_API
void
vprint
(
string_view
format_str
,
format_args
args
);
FMT_API
void
vprint
(
wstring_view
format_str
,
wformat_args
args
);
/**
\rst
Prints formatted data to ``stdout``.
**Example**::
fmt::print("Elapsed time: {0:.2f} seconds", 1.23);
\endrst
*/
template
<
typename
...
Args
>
inline
void
print
(
string_view
format_str
,
const
Args
&
...
args
)
{
format_arg_store
<
format_context
,
Args
...
>
as
{
args
...};
vprint
(
format_str
,
as
);
}
template
<
typename
...
Args
>
inline
void
print
(
wstring_view
format_str
,
const
Args
&
...
args
)
{
format_arg_store
<
wformat_context
,
Args
...
>
as
(
args
...);
vprint
(
format_str
,
as
);
}
FMT_END_NAMESPACE
#endif // FMT_CORE_H_
include/spdlog/fmt/bundled/format-inl.h
0 → 100644
View file @
3f438a80
// Formatting library for C++
//
// Copyright (c) 2012 - 2016, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_FORMAT_INL_H_
#define FMT_FORMAT_INL_H_
#include "format.h"
#include <string.h>
#include <cctype>
#include <cerrno>
#include <climits>
#include <cmath>
#include <cstdarg>
#include <cstddef> // for std::ptrdiff_t
#include <locale>
#if defined(_WIN32) && defined(__MINGW32__)
#include <cstring>
#endif
#if FMT_USE_WINDOWS_H
#if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
#include <windows.h>
#else
#define NOMINMAX
#include <windows.h>
#undef NOMINMAX
#endif
#endif
#if FMT_EXCEPTIONS
#define FMT_TRY try
#define FMT_CATCH(x) catch (x)
#else
#define FMT_TRY if (true)
#define FMT_CATCH(x) if (false)
#endif
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4702) // unreachable code
// Disable deprecation warning for strerror. The latter is not called but
// MSVC fails to detect it.
#pragma warning(disable : 4996)
#endif
// Dummy implementations of strerror_r and strerror_s called if corresponding
// system functions are not available.
inline
fmt
::
internal
::
null
<>
strerror_r
(
int
,
char
*
,
...)
{
return
fmt
::
internal
::
null
<>
();
}
inline
fmt
::
internal
::
null
<>
strerror_s
(
char
*
,
std
::
size_t
,
...)
{
return
fmt
::
internal
::
null
<>
();
}
FMT_BEGIN_NAMESPACE
namespace
{
#ifndef _MSC_VER
#define FMT_SNPRINTF snprintf
#else // _MSC_VER
inline
int
fmt_snprintf
(
char
*
buffer
,
size_t
size
,
const
char
*
format
,
...)
{
va_list
args
;
va_start
(
args
,
format
);
int
result
=
vsnprintf_s
(
buffer
,
size
,
_TRUNCATE
,
format
,
args
);
va_end
(
args
);
return
result
;
}
#define FMT_SNPRINTF fmt_snprintf
#endif // _MSC_VER
#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
#define FMT_SWPRINTF snwprintf
#else
#define FMT_SWPRINTF swprintf
#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
const
char
RESET_COLOR
[]
=
"
\x1b
[0m"
;
const
wchar_t
WRESET_COLOR
[]
=
L"
\x1b
[0m"
;
typedef
void
(
*
FormatFunc
)(
internal
::
buffer
&
,
int
,
string_view
);
// Portable thread-safe version of strerror.
// Sets buffer to point to a string describing the error code.
// This can be either a pointer to a string stored in buffer,
// or a pointer to some static immutable string.
// Returns one of the following values:
// 0 - success
// ERANGE - buffer is not large enough to store the error message
// other - failure
// Buffer should be at least of size 1.
int
safe_strerror
(
int
error_code
,
char
*&
buffer
,
std
::
size_t
buffer_size
)
FMT_NOEXCEPT
{
FMT_ASSERT
(
buffer
!=
FMT_NULL
&&
buffer_size
!=
0
,
"invalid buffer"
);
class
dispatcher
{
private:
int
error_code_
;
char
*&
buffer_
;
std
::
size_t
buffer_size_
;
// A noop assignment operator to avoid bogus warnings.
void
operator
=
(
const
dispatcher
&
)
{}
// Handle the result of XSI-compliant version of strerror_r.
int
handle
(
int
result
)
{
// glibc versions before 2.13 return result in errno.
return
result
==
-
1
?
errno
:
result
;
}
// Handle the result of GNU-specific version of strerror_r.
int
handle
(
char
*
message
)
{
// If the buffer is full then the message is probably truncated.
if
(
message
==
buffer_
&&
strlen
(
buffer_
)
==
buffer_size_
-
1
)
return
ERANGE
;
buffer_
=
message
;
return
0
;
}
// Handle the case when strerror_r is not available.
int
handle
(
internal
::
null
<>
)
{
return
fallback
(
strerror_s
(
buffer_
,
buffer_size_
,
error_code_
));
}
// Fallback to strerror_s when strerror_r is not available.
int
fallback
(
int
result
)
{
// If the buffer is full then the message is probably truncated.
return
result
==
0
&&
strlen
(
buffer_
)
==
buffer_size_
-
1
?
ERANGE
:
result
;
}
// Fallback to strerror if strerror_r and strerror_s are not available.
int
fallback
(
internal
::
null
<>
)
{
errno
=
0
;
buffer_
=
strerror
(
error_code_
);
return
errno
;
}
public:
dispatcher
(
int
err_code
,
char
*&
buf
,
std
::
size_t
buf_size
)
:
error_code_
(
err_code
)
,
buffer_
(
buf
)
,
buffer_size_
(
buf_size
)
{
}
int
run
()
{
return
handle
(
strerror_r
(
error_code_
,
buffer_
,
buffer_size_
));
}
};
return
dispatcher
(
error_code
,
buffer
,
buffer_size
).
run
();
}
void
format_error_code
(
internal
::
buffer
&
out
,
int
error_code
,
string_view
message
)
FMT_NOEXCEPT
{
// Report error code making sure that the output fits into
// inline_buffer_size to avoid dynamic memory allocation and potential
// bad_alloc.
out
.
resize
(
0
);
static
const
char
SEP
[]
=
": "
;
static
const
char
ERROR_STR
[]
=
"error "
;
// Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
std
::
size_t
error_code_size
=
sizeof
(
SEP
)
+
sizeof
(
ERROR_STR
)
-
2
;
typedef
internal
::
int_traits
<
int
>::
main_type
main_type
;
main_type
abs_value
=
static_cast
<
main_type
>
(
error_code
);
if
(
internal
::
is_negative
(
error_code
))
{
abs_value
=
0
-
abs_value
;
++
error_code_size
;
}
error_code_size
+=
internal
::
count_digits
(
abs_value
);
writer
w
(
out
);
if
(
message
.
size
()
<=
inline_buffer_size
-
error_code_size
)
{
w
.
write
(
message
);
w
.
write
(
SEP
);
}
w
.
write
(
ERROR_STR
);
w
.
write
(
error_code
);
assert
(
out
.
size
()
<=
inline_buffer_size
);
}
void
report_error
(
FormatFunc
func
,
int
error_code
,
string_view
message
)
FMT_NOEXCEPT
{
memory_buffer
full_message
;
func
(
full_message
,
error_code
,
message
);
// Use Writer::data instead of Writer::c_str to avoid potential memory
// allocation.
std
::
fwrite
(
full_message
.
data
(),
full_message
.
size
(),
1
,
stderr
);
std
::
fputc
(
'\n'
,
stderr
);
}
}
// namespace
class
locale
{
private:
std
::
locale
locale_
;
public:
explicit
locale
(
std
::
locale
loc
=
std
::
locale
())
:
locale_
(
loc
)
{
}
std
::
locale
get
()
{
return
locale_
;
}
};
template
<
typename
Char
>
FMT_FUNC
Char
internal
::
thousands_sep
(
locale_provider
*
lp
)
{
std
::
locale
loc
=
lp
?
lp
->
locale
().
get
()
:
std
::
locale
();
return
std
::
use_facet
<
std
::
numpunct
<
Char
>>
(
loc
).
thousands_sep
();
}
FMT_FUNC
void
system_error
::
init
(
int
err_code
,
string_view
format_str
,
format_args
args
)
{
error_code_
=
err_code
;
memory_buffer
buffer
;
format_system_error
(
buffer
,
err_code
,
vformat
(
format_str
,
args
));
std
::
runtime_error
&
base
=
*
this
;
base
=
std
::
runtime_error
(
to_string
(
buffer
));
}
namespace
internal
{
template
<
typename
T
>
int
char_traits
<
char
>::
format_float
(
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
int
precision
,
T
value
)
{
return
precision
<
0
?
FMT_SNPRINTF
(
buffer
,
size
,
format
,
value
)
:
FMT_SNPRINTF
(
buffer
,
size
,
format
,
precision
,
value
);
}
template
<
typename
T
>
int
char_traits
<
wchar_t
>::
format_float
(
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
int
precision
,
T
value
)
{
return
precision
<
0
?
FMT_SWPRINTF
(
buffer
,
size
,
format
,
value
)
:
FMT_SWPRINTF
(
buffer
,
size
,
format
,
precision
,
value
);
}
template
<
typename
T
>
const
char
basic_data
<
T
>::
DIGITS
[]
=
"0001020304050607080910111213141516171819"
"2021222324252627282930313233343536373839"
"4041424344454647484950515253545556575859"
"6061626364656667686970717273747576777879"
"8081828384858687888990919293949596979899"
;
#define FMT_POWERS_OF_10(factor) \
factor * 10, factor * 100, factor * 1000, factor * 10000, factor * 100000, factor * 1000000, factor * 10000000, factor * 100000000, \
factor * 1000000000
template
<
typename
T
>
const
uint32_t
basic_data
<
T
>::
POWERS_OF_10_32
[]
=
{
0
,
FMT_POWERS_OF_10
(
1
)};
template
<
typename
T
>
const
uint64_t
basic_data
<
T
>::
POWERS_OF_10_64
[]
=
{
0
,
FMT_POWERS_OF_10
(
1
),
FMT_POWERS_OF_10
(
1000000000ull
),
10000000000000000000ull
};
// Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.
// These are generated by support/compute-powers.py.
template
<
typename
T
>
const
uint64_t
basic_data
<
T
>::
POW10_SIGNIFICANDS
[]
=
{
0xfa8fd5a0081c0288
,
0xbaaee17fa23ebf76
,
0x8b16fb203055ac76
,
0xcf42894a5dce35ea
,
0x9a6bb0aa55653b2d
,
0xe61acf033d1a45df
,
0xab70fe17c79ac6ca
,
0xff77b1fcbebcdc4f
,
0xbe5691ef416bd60c
,
0x8dd01fad907ffc3c
,
0xd3515c2831559a83
,
0x9d71ac8fada6c9b5
,
0xea9c227723ee8bcb
,
0xaecc49914078536d
,
0x823c12795db6ce57
,
0xc21094364dfb5637
,
0x9096ea6f3848984f
,
0xd77485cb25823ac7
,
0xa086cfcd97bf97f4
,
0xef340a98172aace5
,
0xb23867fb2a35b28e
,
0x84c8d4dfd2c63f3b
,
0xc5dd44271ad3cdba
,
0x936b9fcebb25c996
,
0xdbac6c247d62a584
,
0xa3ab66580d5fdaf6
,
0xf3e2f893dec3f126
,
0xb5b5ada8aaff80b8
,
0x87625f056c7c4a8b
,
0xc9bcff6034c13053
,
0x964e858c91ba2655
,
0xdff9772470297ebd
,
0xa6dfbd9fb8e5b88f
,
0xf8a95fcf88747d94
,
0xb94470938fa89bcf
,
0x8a08f0f8bf0f156b
,
0xcdb02555653131b6
,
0x993fe2c6d07b7fac
,
0xe45c10c42a2b3b06
,
0xaa242499697392d3
,
0xfd87b5f28300ca0e
,
0xbce5086492111aeb
,
0x8cbccc096f5088cc
,
0xd1b71758e219652c
,
0x9c40000000000000
,
0xe8d4a51000000000
,
0xad78ebc5ac620000
,
0x813f3978f8940984
,
0xc097ce7bc90715b3
,
0x8f7e32ce7bea5c70
,
0xd5d238a4abe98068
,
0x9f4f2726179a2245
,
0xed63a231d4c4fb27
,
0xb0de65388cc8ada8
,
0x83c7088e1aab65db
,
0xc45d1df942711d9a
,
0x924d692ca61be758
,
0xda01ee641a708dea
,
0xa26da3999aef774a
,
0xf209787bb47d6b85
,
0xb454e4a179dd1877
,
0x865b86925b9bc5c2
,
0xc83553c5c8965d3d
,
0x952ab45cfa97a0b3
,
0xde469fbd99a05fe3
,
0xa59bc234db398c25
,
0xf6c69a72a3989f5c
,
0xb7dcbf5354e9bece
,
0x88fcf317f22241e2
,
0xcc20ce9bd35c78a5
,
0x98165af37b2153df
,
0xe2a0b5dc971f303a
,
0xa8d9d1535ce3b396
,
0xfb9b7cd9a4a7443c
,
0xbb764c4ca7a44410
,
0x8bab8eefb6409c1a
,
0xd01fef10a657842c
,
0x9b10a4e5e9913129
,
0xe7109bfba19c0c9d
,
0xac2820d9623bf429
,
0x80444b5e7aa7cf85
,
0xbf21e44003acdd2d
,
0x8e679c2f5e44ff8f
,
0xd433179d9c8cb841
,
0x9e19db92b4e31ba9
,
0xeb96bf6ebadf77d9
,
0xaf87023b9bf0ee6b
};
// Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding
// to significands above.
template
<
typename
T
>
const
int16_t
basic_data
<
T
>::
POW10_EXPONENTS
[]
=
{
-
1220
,
-
1193
,
-
1166
,
-
1140
,
-
1113
,
-
1087
,
-
1060
,
-
1034
,
-
1007
,
-
980
,
-
954
,
-
927
,
-
901
,
-
874
,
-
847
,
-
821
,
-
794
,
-
768
,
-
741
,
-
715
,
-
688
,
-
661
,
-
635
,
-
608
,
-
582
,
-
555
,
-
529
,
-
502
,
-
475
,
-
449
,
-
422
,
-
396
,
-
369
,
-
343
,
-
316
,
-
289
,
-
263
,
-
236
,
-
210
,
-
183
,
-
157
,
-
130
,
-
103
,
-
77
,
-
50
,
-
24
,
3
,
30
,
56
,
83
,
109
,
136
,
162
,
189
,
216
,
242
,
269
,
295
,
322
,
348
,
375
,
402
,
428
,
455
,
481
,
508
,
534
,
561
,
588
,
614
,
641
,
667
,
694
,
720
,
747
,
774
,
800
,
827
,
853
,
880
,
907
,
933
,
960
,
986
,
1013
,
1039
,
1066
};
FMT_FUNC
fp
operator
*
(
fp
x
,
fp
y
)
{
// Multiply 32-bit parts of significands.
uint64_t
mask
=
(
1ULL
<<
32
)
-
1
;
uint64_t
a
=
x
.
f
>>
32
,
b
=
x
.
f
&
mask
;
uint64_t
c
=
y
.
f
>>
32
,
d
=
y
.
f
&
mask
;
uint64_t
ac
=
a
*
c
,
bc
=
b
*
c
,
ad
=
a
*
d
,
bd
=
b
*
d
;
// Compute mid 64-bit of result and round.
uint64_t
mid
=
(
bd
>>
32
)
+
(
ad
&
mask
)
+
(
bc
&
mask
)
+
(
1U
<<
31
);
return
fp
(
ac
+
(
ad
>>
32
)
+
(
bc
>>
32
)
+
(
mid
>>
32
),
x
.
e
+
y
.
e
+
64
);
}
FMT_FUNC
fp
get_cached_power
(
int
min_exponent
,
int
&
pow10_exponent
)
{
const
double
one_over_log2_10
=
0.30102999566398114
;
// 1 / log2(10)
int
index
=
static_cast
<
int
>
(
std
::
ceil
((
min_exponent
+
fp
::
significand_size
-
1
)
*
one_over_log2_10
));
// Decimal exponent of the first (smallest) cached power of 10.
const
int
first_dec_exp
=
-
348
;
// Difference between two consecutive decimal exponents in cached powers of 10.
const
int
dec_exp_step
=
8
;
index
=
(
index
-
first_dec_exp
-
1
)
/
dec_exp_step
+
1
;
pow10_exponent
=
first_dec_exp
+
index
*
dec_exp_step
;
return
fp
(
data
::
POW10_SIGNIFICANDS
[
index
],
data
::
POW10_EXPONENTS
[
index
]);
}
}
// namespace internal
#if FMT_USE_WINDOWS_H
FMT_FUNC
internal
::
utf8_to_utf16
::
utf8_to_utf16
(
string_view
s
)
{
static
const
char
ERROR_MSG
[]
=
"cannot convert string from UTF-8 to UTF-16"
;
if
(
s
.
size
()
>
INT_MAX
)
FMT_THROW
(
windows_error
(
ERROR_INVALID_PARAMETER
,
ERROR_MSG
));
int
s_size
=
static_cast
<
int
>
(
s
.
size
());
if
(
s_size
==
0
)
{
// MultiByteToWideChar does not support zero length, handle separately.
buffer_
.
resize
(
1
);
buffer_
[
0
]
=
0
;
return
;
}
int
length
=
MultiByteToWideChar
(
CP_UTF8
,
MB_ERR_INVALID_CHARS
,
s
.
data
(),
s_size
,
FMT_NULL
,
0
);
if
(
length
==
0
)
FMT_THROW
(
windows_error
(
GetLastError
(),
ERROR_MSG
));
buffer_
.
resize
(
length
+
1
);
length
=
MultiByteToWideChar
(
CP_UTF8
,
MB_ERR_INVALID_CHARS
,
s
.
data
(),
s_size
,
&
buffer_
[
0
],
length
);
if
(
length
==
0
)
FMT_THROW
(
windows_error
(
GetLastError
(),
ERROR_MSG
));
buffer_
[
length
]
=
0
;
}
FMT_FUNC
internal
::
utf16_to_utf8
::
utf16_to_utf8
(
wstring_view
s
)
{
if
(
int
error_code
=
convert
(
s
))
{
FMT_THROW
(
windows_error
(
error_code
,
"cannot convert string from UTF-16 to UTF-8"
));
}
}
FMT_FUNC
int
internal
::
utf16_to_utf8
::
convert
(
wstring_view
s
)
{
if
(
s
.
size
()
>
INT_MAX
)
return
ERROR_INVALID_PARAMETER
;
int
s_size
=
static_cast
<
int
>
(
s
.
size
());
if
(
s_size
==
0
)
{
// WideCharToMultiByte does not support zero length, handle separately.
buffer_
.
resize
(
1
);
buffer_
[
0
]
=
0
;
return
0
;
}
int
length
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
s
.
data
(),
s_size
,
FMT_NULL
,
0
,
FMT_NULL
,
FMT_NULL
);
if
(
length
==
0
)
return
GetLastError
();
buffer_
.
resize
(
length
+
1
);
length
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
s
.
data
(),
s_size
,
&
buffer_
[
0
],
length
,
FMT_NULL
,
FMT_NULL
);
if
(
length
==
0
)
return
GetLastError
();
buffer_
[
length
]
=
0
;
return
0
;
}
FMT_FUNC
void
windows_error
::
init
(
int
err_code
,
string_view
format_str
,
format_args
args
)
{
error_code_
=
err_code
;
memory_buffer
buffer
;
internal
::
format_windows_error
(
buffer
,
err_code
,
vformat
(
format_str
,
args
));
std
::
runtime_error
&
base
=
*
this
;
base
=
std
::
runtime_error
(
to_string
(
buffer
));
}
FMT_FUNC
void
internal
::
format_windows_error
(
internal
::
buffer
&
out
,
int
error_code
,
string_view
message
)
FMT_NOEXCEPT
{
FMT_TRY
{
wmemory_buffer
buf
;
buf
.
resize
(
inline_buffer_size
);
for
(;;)
{
wchar_t
*
system_message
=
&
buf
[
0
];
int
result
=
FormatMessageW
(
FORMAT_MESSAGE_FROM_SYSTEM
|
FORMAT_MESSAGE_IGNORE_INSERTS
,
FMT_NULL
,
error_code
,
MAKELANGID
(
LANG_NEUTRAL
,
SUBLANG_DEFAULT
),
system_message
,
static_cast
<
uint32_t
>
(
buf
.
size
()),
FMT_NULL
);
if
(
result
!=
0
)
{
utf16_to_utf8
utf8_message
;
if
(
utf8_message
.
convert
(
system_message
)
==
ERROR_SUCCESS
)
{
writer
w
(
out
);
w
.
write
(
message
);
w
.
write
(
": "
);
w
.
write
(
utf8_message
);
return
;
}
break
;
}
if
(
GetLastError
()
!=
ERROR_INSUFFICIENT_BUFFER
)
break
;
// Can't get error message, report error code instead.
buf
.
resize
(
buf
.
size
()
*
2
);
}
}
FMT_CATCH
(...)
{}
format_error_code
(
out
,
error_code
,
message
);
}
#endif // FMT_USE_WINDOWS_H
FMT_FUNC
void
format_system_error
(
internal
::
buffer
&
out
,
int
error_code
,
string_view
message
)
FMT_NOEXCEPT
{
FMT_TRY
{
memory_buffer
buf
;
buf
.
resize
(
inline_buffer_size
);
for
(;;)
{
char
*
system_message
=
&
buf
[
0
];
int
result
=
safe_strerror
(
error_code
,
system_message
,
buf
.
size
());
if
(
result
==
0
)
{
writer
w
(
out
);
w
.
write
(
message
);
w
.
write
(
": "
);
w
.
write
(
system_message
);
return
;
}
if
(
result
!=
ERANGE
)
break
;
// Can't get error message, report error code instead.
buf
.
resize
(
buf
.
size
()
*
2
);
}
}
FMT_CATCH
(...)
{}
format_error_code
(
out
,
error_code
,
message
);
}
template
<
typename
Char
>
void
basic_fixed_buffer
<
Char
>::
grow
(
std
::
size_t
)
{
FMT_THROW
(
std
::
runtime_error
(
"buffer overflow"
));
}
FMT_FUNC
void
internal
::
error_handler
::
on_error
(
const
char
*
message
)
{
FMT_THROW
(
format_error
(
message
));
}
FMT_FUNC
void
report_system_error
(
int
error_code
,
fmt
::
string_view
message
)
FMT_NOEXCEPT
{
report_error
(
format_system_error
,
error_code
,
message
);
}
#if FMT_USE_WINDOWS_H
FMT_FUNC
void
report_windows_error
(
int
error_code
,
fmt
::
string_view
message
)
FMT_NOEXCEPT
{
report_error
(
internal
::
format_windows_error
,
error_code
,
message
);
}
#endif
FMT_FUNC
void
vprint
(
std
::
FILE
*
f
,
string_view
format_str
,
format_args
args
)
{
memory_buffer
buffer
;
vformat_to
(
buffer
,
format_str
,
args
);
std
::
fwrite
(
buffer
.
data
(),
1
,
buffer
.
size
(),
f
);
}
FMT_FUNC
void
vprint
(
std
::
FILE
*
f
,
wstring_view
format_str
,
wformat_args
args
)
{
wmemory_buffer
buffer
;
vformat_to
(
buffer
,
format_str
,
args
);
std
::
fwrite
(
buffer
.
data
(),
sizeof
(
wchar_t
),
buffer
.
size
(),
f
);
}
FMT_FUNC
void
vprint
(
string_view
format_str
,
format_args
args
)
{
vprint
(
stdout
,
format_str
,
args
);
}
FMT_FUNC
void
vprint
(
wstring_view
format_str
,
wformat_args
args
)
{
vprint
(
stdout
,
format_str
,
args
);
}
FMT_FUNC
void
vprint_colored
(
color
c
,
string_view
format
,
format_args
args
)
{
char
escape
[]
=
"
\x1b
[30m"
;
escape
[
3
]
=
static_cast
<
char
>
(
'0'
+
c
);
std
::
fputs
(
escape
,
stdout
);
vprint
(
format
,
args
);
std
::
fputs
(
RESET_COLOR
,
stdout
);
}
FMT_FUNC
void
vprint_colored
(
color
c
,
wstring_view
format
,
wformat_args
args
)
{
wchar_t
escape
[]
=
L"
\x1b
[30m"
;
escape
[
3
]
=
static_cast
<
wchar_t
>
(
'0'
+
c
);
std
::
fputws
(
escape
,
stdout
);
vprint
(
format
,
args
);
std
::
fputws
(
WRESET_COLOR
,
stdout
);
}
FMT_FUNC
locale
locale_provider
::
locale
()
{
return
fmt
::
locale
();
}
FMT_END_NAMESPACE
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif // FMT_FORMAT_INL_H_
include/spdlog/fmt/bundled/format.cc
0 → 100644
View file @
3f438a80
// Formatting library for C++
//
// Copyright (c) 2012 - 2016, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#include "fmt/format-inl.h"
namespace
fmt
{
template
struct
internal
::
basic_data
<
void
>;
// Explicit instantiations for char.
template
FMT_API
char
internal
::
thousands_sep
(
locale_provider
*
lp
);
template
void
basic_fixed_buffer
<
char
>
::
grow
(
std
::
size_t
);
template
void
internal
::
arg_map
<
format_context
>
::
init
(
const
basic_format_args
<
format_context
>
&
args
);
template
FMT_API
int
internal
::
char_traits
<
char
>
::
format_float
(
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
unsigned
width
,
int
precision
,
double
value
);
template
FMT_API
int
internal
::
char_traits
<
char
>
::
format_float
(
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
unsigned
width
,
int
precision
,
long
double
value
);
// Explicit instantiations for wchar_t.
template
FMT_API
wchar_t
internal
::
thousands_sep
(
locale_provider
*
lp
);
template
void
basic_fixed_buffer
<
wchar_t
>
::
grow
(
std
::
size_t
);
template
void
internal
::
arg_map
<
wformat_context
>
::
init
(
const
wformat_args
&
args
);
template
FMT_API
int
internal
::
char_traits
<
wchar_t
>
::
format_float
(
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
unsigned
width
,
int
precision
,
double
value
);
template
FMT_API
int
internal
::
char_traits
<
wchar_t
>
::
format_float
(
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
unsigned
width
,
int
precision
,
long
double
value
);
}
// namespace fmt
include/spdlog/fmt/bundled/format.h
0 → 100644
View file @
3f438a80
This source diff could not be displayed because it is too large. You can
view the blob
instead.
include/spdlog/fmt/bundled/locale.h
0 → 100644
View file @
3f438a80
// Formatting library for C++ - locale support
//
// Copyright (c) 2012 - 2016, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#include "format.h"
#include <locale>
namespace
fmt
{
class
locale
{
private:
std
::
locale
locale_
;
public:
explicit
locale
(
std
::
locale
loc
=
std
::
locale
())
:
locale_
(
loc
)
{
}
std
::
locale
get
()
{
return
locale_
;
}
};
}
// namespace fmt
include/spdlog/fmt/bundled/ostream.h
0 → 100644
View file @
3f438a80
// Formatting library for C++ - std::ostream support
//
// Copyright (c) 2012 - 2016, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_OSTREAM_H_
#define FMT_OSTREAM_H_
#include "format.h"
#include <ostream>
FMT_BEGIN_NAMESPACE
namespace
internal
{
template
<
class
Char
>
class
formatbuf
:
public
std
::
basic_streambuf
<
Char
>
{
private:
typedef
typename
std
::
basic_streambuf
<
Char
>::
int_type
int_type
;
typedef
typename
std
::
basic_streambuf
<
Char
>::
traits_type
traits_type
;
basic_buffer
<
Char
>
&
buffer_
;
public:
formatbuf
(
basic_buffer
<
Char
>
&
buffer
)
:
buffer_
(
buffer
)
{
}
protected:
// The put-area is actually always empty. This makes the implementation
// simpler and has the advantage that the streambuf and the buffer are always
// in sync and sputc never writes into uninitialized memory. The obvious
// disadvantage is that each call to sputc always results in a (virtual) call
// to overflow. There is no disadvantage here for sputn since this always
// results in a call to xsputn.
int_type
overflow
(
int_type
ch
=
traits_type
::
eof
())
FMT_OVERRIDE
{
if
(
!
traits_type
::
eq_int_type
(
ch
,
traits_type
::
eof
()))
buffer_
.
push_back
(
static_cast
<
Char
>
(
ch
));
return
ch
;
}
std
::
streamsize
xsputn
(
const
Char
*
s
,
std
::
streamsize
count
)
FMT_OVERRIDE
{
buffer_
.
append
(
s
,
s
+
count
);
return
count
;
}
};
template
<
typename
Char
>
struct
test_stream
:
std
::
basic_ostream
<
Char
>
{
private:
struct
null
;
// Hide all operator<< from std::basic_ostream<Char>.
void
operator
<<
(
null
);
};
// Checks if T has a user-defined operator<< (e.g. not a member of std::ostream).
template
<
typename
T
,
typename
Char
>
class
is_streamable
{
private:
template
<
typename
U
>
static
decltype
(
internal
::
declval
<
test_stream
<
Char
>
&>
()
<<
internal
::
declval
<
U
>
(),
std
::
true_type
())
test
(
int
);
template
<
typename
>
static
std
::
false_type
test
(...);
typedef
decltype
(
test
<
T
>
(
0
))
result
;
public:
// std::string operator<< is not considered user-defined because we handle strings
// specially.
static
const
bool
value
=
result
::
value
&&
!
std
::
is_same
<
T
,
std
::
string
>::
value
;
};
// Disable conversion to int if T has an overloaded operator<< which is a free
// function (not a member of std::ostream).
template
<
typename
T
,
typename
Char
>
class
convert_to_int
<
T
,
Char
,
true
>
{
public:
static
const
bool
value
=
convert_to_int
<
T
,
Char
,
false
>::
value
&&
!
is_streamable
<
T
,
Char
>::
value
;
};
// Write the content of buf to os.
template
<
typename
Char
>
void
write
(
std
::
basic_ostream
<
Char
>
&
os
,
basic_buffer
<
Char
>
&
buf
)
{
const
Char
*
data
=
buf
.
data
();
typedef
std
::
make_unsigned
<
std
::
streamsize
>::
type
UnsignedStreamSize
;
UnsignedStreamSize
size
=
buf
.
size
();
UnsignedStreamSize
max_size
=
internal
::
to_unsigned
((
std
::
numeric_limits
<
std
::
streamsize
>::
max
)());
do
{
UnsignedStreamSize
n
=
size
<=
max_size
?
size
:
max_size
;
os
.
write
(
data
,
static_cast
<
std
::
streamsize
>
(
n
));
data
+=
n
;
size
-=
n
;
}
while
(
size
!=
0
);
}
template
<
typename
Char
,
typename
T
>
void
format_value
(
basic_buffer
<
Char
>
&
buffer
,
const
T
&
value
)
{
internal
::
formatbuf
<
Char
>
format_buf
(
buffer
);
std
::
basic_ostream
<
Char
>
output
(
&
format_buf
);
output
.
exceptions
(
std
::
ios_base
::
failbit
|
std
::
ios_base
::
badbit
);
output
<<
value
;
buffer
.
resize
(
buffer
.
size
());
}
// Disable builtin formatting of enums and use operator<< instead.
template
<
typename
T
>
struct
format_enum
<
T
,
typename
std
::
enable_if
<
std
::
is_enum
<
T
>::
value
>::
type
>
:
std
::
false_type
{
};
}
// namespace internal
// Formats an object of type T that has an overloaded ostream operator<<.
template
<
typename
T
,
typename
Char
>
struct
formatter
<
T
,
Char
,
typename
std
::
enable_if
<
internal
::
is_streamable
<
T
,
Char
>::
value
>::
type
>
:
formatter
<
basic_string_view
<
Char
>
,
Char
>
{
template
<
typename
Context
>
auto
format
(
const
T
&
value
,
Context
&
ctx
)
->
decltype
(
ctx
.
out
())
{
basic_memory_buffer
<
Char
>
buffer
;
internal
::
format_value
(
buffer
,
value
);
basic_string_view
<
Char
>
str
(
buffer
.
data
(),
buffer
.
size
());
formatter
<
basic_string_view
<
Char
>
,
Char
>::
format
(
str
,
ctx
);
return
ctx
.
out
();
}
};
template
<
typename
Char
>
inline
void
vprint
(
std
::
basic_ostream
<
Char
>
&
os
,
basic_string_view
<
Char
>
format_str
,
basic_format_args
<
typename
buffer_context
<
Char
>::
type
>
args
)
{
basic_memory_buffer
<
Char
>
buffer
;
vformat_to
(
buffer
,
format_str
,
args
);
internal
::
write
(
os
,
buffer
);
}
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fmt::print(cerr, "Don't {}!", "panic");
\endrst
*/
template
<
typename
...
Args
>
inline
void
print
(
std
::
ostream
&
os
,
string_view
format_str
,
const
Args
&
...
args
)
{
vprint
<
char
>
(
os
,
format_str
,
make_format_args
<
format_context
>
(
args
...));
}
template
<
typename
...
Args
>
inline
void
print
(
std
::
wostream
&
os
,
wstring_view
format_str
,
const
Args
&
...
args
)
{
vprint
<
wchar_t
>
(
os
,
format_str
,
make_format_args
<
wformat_context
>
(
args
...));
}
FMT_END_NAMESPACE
#endif // FMT_OSTREAM_H_
include/spdlog/fmt/bundled/posix.h
0 → 100644
View file @
3f438a80
// A C++ interface to POSIX functions.
//
// Copyright (c) 2012 - 2016, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_POSIX_H_
#define FMT_POSIX_H_
#if defined(__MINGW32__) || defined(__CYGWIN__)
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
#undef __STRICT_ANSI__
#endif
#include <errno.h>
#include <fcntl.h> // for O_RDONLY
#include <locale.h> // for locale_t
#include <stdio.h>
#include <stdlib.h> // for strtod_l
#include <cstddef>
#if defined __APPLE__ || defined(__FreeBSD__)
#include <xlocale.h> // for LC_NUMERIC_MASK on OS X
#endif
#include "format.h"
#ifndef FMT_POSIX
#if defined(_WIN32) && !defined(__MINGW32__)
// Fix warnings about deprecated symbols.
#define FMT_POSIX(call) _##call
#else
#define FMT_POSIX(call) call
#endif
#endif
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
#ifdef FMT_SYSTEM
#define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
#else
#define FMT_SYSTEM(call) call
#ifdef _WIN32
// Fix warnings about deprecated symbols.
#define FMT_POSIX_CALL(call) ::_##call
#else
#define FMT_POSIX_CALL(call) ::call
#endif
#endif
// Retries the expression while it evaluates to error_result and errno
// equals to EINTR.
#ifndef _WIN32
#define FMT_RETRY_VAL(result, expression, error_result) \
do \
{ \
result = (expression); \
} while (result == error_result && errno == EINTR)
#else
#define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#endif
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
FMT_BEGIN_NAMESPACE
/**
\rst
A reference to a null-terminated string. It can be constructed from a C
string or ``std::string``.
You can use one of the following typedefs for common character types:
+---------------+-----------------------------+
| Type | Definition |
+===============+=============================+
| cstring_view | basic_cstring_view<char> |
+---------------+-----------------------------+
| wcstring_view | basic_cstring_view<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(cstring_view format_str, const Args & ... args);
format("{}", 42);
format(std::string("{}"), 42);
\endrst
*/
template
<
typename
Char
>
class
basic_cstring_view
{
private:
const
Char
*
data_
;
public:
/** Constructs a string reference object from a C string. */
basic_cstring_view
(
const
Char
*
s
)
:
data_
(
s
)
{
}
/**
\rst
Constructs a string reference from an ``std::string`` object.
\endrst
*/
basic_cstring_view
(
const
std
::
basic_string
<
Char
>
&
s
)
:
data_
(
s
.
c_str
())
{
}
/** Returns the pointer to a C string. */
const
Char
*
c_str
()
const
{
return
data_
;
}
};
typedef
basic_cstring_view
<
char
>
cstring_view
;
typedef
basic_cstring_view
<
wchar_t
>
wcstring_view
;
// An error code.
class
error_code
{
private:
int
value_
;
public:
explicit
error_code
(
int
value
=
0
)
FMT_NOEXCEPT
:
value_
(
value
)
{}
int
get
()
const
FMT_NOEXCEPT
{
return
value_
;
}
};
// A buffered file.
class
buffered_file
{
private:
FILE
*
file_
;
friend
class
file
;
explicit
buffered_file
(
FILE
*
f
)
:
file_
(
f
)
{
}
public:
// Constructs a buffered_file object which doesn't represent any file.
buffered_file
()
FMT_NOEXCEPT
:
file_
(
FMT_NULL
)
{}
// Destroys the object closing the file it represents if any.
FMT_API
~
buffered_file
()
FMT_DTOR_NOEXCEPT
;
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
private:
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
struct
Proxy
{
FILE
*
file
;
};
public:
// A "move constructor" for moving from a temporary.
buffered_file
(
Proxy
p
)
FMT_NOEXCEPT
:
file_
(
p
.
file
)
{}
// A "move constructor" for moving from an lvalue.
buffered_file
(
buffered_file
&
f
)
FMT_NOEXCEPT
:
file_
(
f
.
file_
)
{
f
.
file_
=
FMT_NULL
;
}
// A "move assignment operator" for moving from a temporary.
buffered_file
&
operator
=
(
Proxy
p
)
{
close
();
file_
=
p
.
file
;
return
*
this
;
}
// A "move assignment operator" for moving from an lvalue.
buffered_file
&
operator
=
(
buffered_file
&
other
)
{
close
();
file_
=
other
.
file_
;
other
.
file_
=
FMT_NULL
;
return
*
this
;
}
// Returns a proxy object for moving from a temporary:
// buffered_file file = buffered_file(...);
operator
Proxy
()
FMT_NOEXCEPT
{
Proxy
p
=
{
file_
};
file_
=
FMT_NULL
;
return
p
;
}
#else
private:
FMT_DISALLOW_COPY_AND_ASSIGN
(
buffered_file
);
public:
buffered_file
(
buffered_file
&&
other
)
FMT_NOEXCEPT
:
file_
(
other
.
file_
)
{
other
.
file_
=
FMT_NULL
;
}
buffered_file
&
operator
=
(
buffered_file
&&
other
)
{
close
();
file_
=
other
.
file_
;
other
.
file_
=
FMT_NULL
;
return
*
this
;
}
#endif
// Opens a file.
FMT_API
buffered_file
(
cstring_view
filename
,
cstring_view
mode
);
// Closes the file.
FMT_API
void
close
();
// Returns the pointer to a FILE object representing this file.
FILE
*
get
()
const
FMT_NOEXCEPT
{
return
file_
;
}
// We place parentheses around fileno to workaround a bug in some versions
// of MinGW that define fileno as a macro.
FMT_API
int
(
fileno
)()
const
;
void
vprint
(
string_view
format_str
,
format_args
args
)
{
fmt
::
vprint
(
file_
,
format_str
,
args
);
}
template
<
typename
...
Args
>
inline
void
print
(
string_view
format_str
,
const
Args
&
...
args
)
{
vprint
(
format_str
,
make_format_args
(
args
...));
}
};
// A file. Closed file is represented by a file object with descriptor -1.
// Methods that are not declared with FMT_NOEXCEPT may throw
// fmt::system_error in case of failure. Note that some errors such as
// closing the file multiple times will cause a crash on Windows rather
// than an exception. You can get standard behavior by overriding the
// invalid parameter handler with _set_invalid_parameter_handler.
class
file
{
private:
int
fd_
;
// File descriptor.
// Constructs a file object with a given descriptor.
explicit
file
(
int
fd
)
:
fd_
(
fd
)
{
}
public:
// Possible values for the oflag argument to the constructor.
enum
{
RDONLY
=
FMT_POSIX
(
O_RDONLY
),
// Open for reading only.
WRONLY
=
FMT_POSIX
(
O_WRONLY
),
// Open for writing only.
RDWR
=
FMT_POSIX
(
O_RDWR
)
// Open for reading and writing.
};
// Constructs a file object which doesn't represent any file.
file
()
FMT_NOEXCEPT
:
fd_
(
-
1
)
{}
// Opens a file and constructs a file object representing this file.
FMT_API
file
(
cstring_view
path
,
int
oflag
);
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
private:
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
struct
Proxy
{
int
fd
;
};
public:
// A "move constructor" for moving from a temporary.
file
(
Proxy
p
)
FMT_NOEXCEPT
:
fd_
(
p
.
fd
)
{}
// A "move constructor" for moving from an lvalue.
file
(
file
&
other
)
FMT_NOEXCEPT
:
fd_
(
other
.
fd_
)
{
other
.
fd_
=
-
1
;
}
// A "move assignment operator" for moving from a temporary.
file
&
operator
=
(
Proxy
p
)
{
close
();
fd_
=
p
.
fd
;
return
*
this
;
}
// A "move assignment operator" for moving from an lvalue.
file
&
operator
=
(
file
&
other
)
{
close
();
fd_
=
other
.
fd_
;
other
.
fd_
=
-
1
;
return
*
this
;
}
// Returns a proxy object for moving from a temporary:
// file f = file(...);
operator
Proxy
()
FMT_NOEXCEPT
{
Proxy
p
=
{
fd_
};
fd_
=
-
1
;
return
p
;
}
#else
private:
FMT_DISALLOW_COPY_AND_ASSIGN
(
file
);
public:
file
(
file
&&
other
)
FMT_NOEXCEPT
:
fd_
(
other
.
fd_
)
{
other
.
fd_
=
-
1
;
}
file
&
operator
=
(
file
&&
other
)
{
close
();
fd_
=
other
.
fd_
;
other
.
fd_
=
-
1
;
return
*
this
;
}
#endif
// Destroys the object closing the file it represents if any.
FMT_API
~
file
()
FMT_DTOR_NOEXCEPT
;
// Returns the file descriptor.
int
descriptor
()
const
FMT_NOEXCEPT
{
return
fd_
;
}
// Closes the file.
FMT_API
void
close
();
// Returns the file size. The size has signed type for consistency with
// stat::st_size.
FMT_API
long
long
size
()
const
;
// Attempts to read count bytes from the file into the specified buffer.
FMT_API
std
::
size_t
read
(
void
*
buffer
,
std
::
size_t
count
);
// Attempts to write count bytes from the specified buffer to the file.
FMT_API
std
::
size_t
write
(
const
void
*
buffer
,
std
::
size_t
count
);
// Duplicates a file descriptor with the dup function and returns
// the duplicate as a file object.
FMT_API
static
file
dup
(
int
fd
);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
FMT_API
void
dup2
(
int
fd
);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
FMT_API
void
dup2
(
int
fd
,
error_code
&
ec
)
FMT_NOEXCEPT
;
// Creates a pipe setting up read_end and write_end file objects for reading
// and writing respectively.
FMT_API
static
void
pipe
(
file
&
read_end
,
file
&
write_end
);
// Creates a buffered_file object associated with this file and detaches
// this file object from the file.
FMT_API
buffered_file
fdopen
(
const
char
*
mode
);
};
// Returns the memory page size.
long
getpagesize
();
#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && !defined(__ANDROID__) && !defined(__CYGWIN__) && !defined(__OpenBSD__)
#define FMT_LOCALE
#endif
#ifdef FMT_LOCALE
// A "C" numeric locale.
class
Locale
{
private:
#ifdef _MSC_VER
typedef
_locale_t
locale_t
;
enum
{
LC_NUMERIC_MASK
=
LC_NUMERIC
};
static
locale_t
newlocale
(
int
category_mask
,
const
char
*
locale
,
locale_t
)
{
return
_create_locale
(
category_mask
,
locale
);
}
static
void
freelocale
(
locale_t
locale
)
{
_free_locale
(
locale
);
}
static
double
strtod_l
(
const
char
*
nptr
,
char
**
endptr
,
_locale_t
locale
)
{
return
_strtod_l
(
nptr
,
endptr
,
locale
);
}
#endif
locale_t
locale_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
Locale
);
public:
typedef
locale_t
Type
;
Locale
()
:
locale_
(
newlocale
(
LC_NUMERIC_MASK
,
"C"
,
FMT_NULL
))
{
if
(
!
locale_
)
FMT_THROW
(
system_error
(
errno
,
"cannot create locale"
));
}
~
Locale
()
{
freelocale
(
locale_
);
}
Type
get
()
const
{
return
locale_
;
}
// Converts string to floating-point number and advances str past the end
// of the parsed input.
double
strtod
(
const
char
*&
str
)
const
{
char
*
end
=
FMT_NULL
;
double
result
=
strtod_l
(
str
,
&
end
,
locale_
);
str
=
end
;
return
result
;
}
};
#endif // FMT_LOCALE
FMT_END_NAMESPACE
#if !FMT_USE_RVALUE_REFERENCES
namespace
std
{
// For compatibility with C++98.
inline
fmt
::
buffered_file
&
move
(
fmt
::
buffered_file
&
f
)
{
return
f
;
}
inline
fmt
::
file
&
move
(
fmt
::
file
&
f
)
{
return
f
;
}
}
// namespace std
#endif
#endif // FMT_POSIX_H_
include/spdlog/fmt/bundled/printf.h
0 → 100644
View file @
3f438a80
// Formatting library for C++
//
// Copyright (c) 2012 - 2016, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_PRINTF_H_
#define FMT_PRINTF_H_
#include <algorithm> // std::fill_n
#include <limits> // std::numeric_limits
#include "ostream.h"
FMT_BEGIN_NAMESPACE
namespace
internal
{
// Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers.
template
<
bool
IsSigned
>
struct
int_checker
{
template
<
typename
T
>
static
bool
fits_in_int
(
T
value
)
{
unsigned
max
=
std
::
numeric_limits
<
int
>::
max
();
return
value
<=
max
;
}
static
bool
fits_in_int
(
bool
)
{
return
true
;
}
};
template
<
>
struct
int_checker
<
true
>
{
template
<
typename
T
>
static
bool
fits_in_int
(
T
value
)
{
return
value
>=
std
::
numeric_limits
<
int
>::
min
()
&&
value
<=
std
::
numeric_limits
<
int
>::
max
();
}
static
bool
fits_in_int
(
int
)
{
return
true
;
}
};
class
printf_precision_handler
:
public
function
<
int
>
{
public:
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
int
>::
type
operator
()(
T
value
)
{
if
(
!
int_checker
<
std
::
numeric_limits
<
T
>::
is_signed
>::
fits_in_int
(
value
))
FMT_THROW
(
format_error
(
"number is too big"
));
return
static_cast
<
int
>
(
value
);
}
template
<
typename
T
>
typename
std
::
enable_if
<!
std
::
is_integral
<
T
>::
value
,
int
>::
type
operator
()(
T
)
{
FMT_THROW
(
format_error
(
"precision is not integer"
));
return
0
;
}
};
// An argument visitor that returns true iff arg is a zero integer.
class
is_zero_int
:
public
function
<
bool
>
{
public:
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
bool
>::
type
operator
()(
T
value
)
{
return
value
==
0
;
}
template
<
typename
T
>
typename
std
::
enable_if
<!
std
::
is_integral
<
T
>::
value
,
bool
>::
type
operator
()(
T
)
{
return
false
;
}
};
template
<
typename
T
>
struct
make_unsigned_or_bool
:
std
::
make_unsigned
<
T
>
{
};
template
<
>
struct
make_unsigned_or_bool
<
bool
>
{
typedef
bool
type
;
};
template
<
typename
T
,
typename
Context
>
class
arg_converter
:
public
function
<
void
>
{
private:
typedef
typename
Context
::
char_type
Char
;
basic_format_arg
<
Context
>
&
arg_
;
typename
Context
::
char_type
type_
;
public:
arg_converter
(
basic_format_arg
<
Context
>
&
arg
,
Char
type
)
:
arg_
(
arg
)
,
type_
(
type
)
{
}
void
operator
()(
bool
value
)
{
if
(
type_
!=
's'
)
operator
()
<
bool
>
(
value
);
}
template
<
typename
U
>
typename
std
::
enable_if
<
std
::
is_integral
<
U
>::
value
>::
type
operator
()(
U
value
)
{
bool
is_signed
=
type_
==
'd'
||
type_
==
'i'
;
typedef
typename
std
::
conditional
<
std
::
is_same
<
T
,
void
>::
value
,
U
,
T
>::
type
TargetType
;
if
(
const_check
(
sizeof
(
TargetType
)
<=
sizeof
(
int
)))
{
// Extra casts are used to silence warnings.
if
(
is_signed
)
{
arg_
=
internal
::
make_arg
<
Context
>
(
static_cast
<
int
>
(
static_cast
<
TargetType
>
(
value
)));
}
else
{
typedef
typename
make_unsigned_or_bool
<
TargetType
>::
type
Unsigned
;
arg_
=
internal
::
make_arg
<
Context
>
(
static_cast
<
unsigned
>
(
static_cast
<
Unsigned
>
(
value
)));
}
}
else
{
if
(
is_signed
)
{
// glibc's printf doesn't sign extend arguments of smaller types:
// std::printf("%lld", -42); // prints "4294967254"
// but we don't have to do the same because it's a UB.
arg_
=
internal
::
make_arg
<
Context
>
(
static_cast
<
long
long
>
(
value
));
}
else
{
arg_
=
internal
::
make_arg
<
Context
>
(
static_cast
<
typename
make_unsigned_or_bool
<
U
>::
type
>
(
value
));
}
}
}
template
<
typename
U
>
typename
std
::
enable_if
<!
std
::
is_integral
<
U
>::
value
>::
type
operator
()(
U
)
{
// No coversion needed for non-integral types.
}
};
// Converts an integer argument to T for printf, if T is an integral type.
// If T is void, the argument is converted to corresponding signed or unsigned
// type depending on the type specifier: 'd' and 'i' - signed, other -
// unsigned).
template
<
typename
T
,
typename
Context
,
typename
Char
>
void
convert_arg
(
basic_format_arg
<
Context
>
&
arg
,
Char
type
)
{
visit
(
arg_converter
<
T
,
Context
>
(
arg
,
type
),
arg
);
}
// Converts an integer argument to char for printf.
template
<
typename
Context
>
class
char_converter
:
public
function
<
void
>
{
private:
basic_format_arg
<
Context
>
&
arg_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
char_converter
);
public:
explicit
char_converter
(
basic_format_arg
<
Context
>
&
arg
)
:
arg_
(
arg
)
{
}
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
>::
type
operator
()(
T
value
)
{
typedef
typename
Context
::
char_type
Char
;
arg_
=
internal
::
make_arg
<
Context
>
(
static_cast
<
Char
>
(
value
));
}
template
<
typename
T
>
typename
std
::
enable_if
<!
std
::
is_integral
<
T
>::
value
>::
type
operator
()(
T
)
{
// No coversion needed for non-integral types.
}
};
// Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative.
template
<
typename
Char
>
class
printf_width_handler
:
public
function
<
unsigned
>
{
private:
typedef
basic_format_specs
<
Char
>
format_specs
;
format_specs
&
spec_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
printf_width_handler
);
public:
explicit
printf_width_handler
(
format_specs
&
spec
)
:
spec_
(
spec
)
{
}
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
unsigned
>::
type
operator
()(
T
value
)
{
typedef
typename
internal
::
int_traits
<
T
>::
main_type
UnsignedType
;
UnsignedType
width
=
static_cast
<
UnsignedType
>
(
value
);
if
(
internal
::
is_negative
(
value
))
{
spec_
.
align_
=
ALIGN_LEFT
;
width
=
0
-
width
;
}
unsigned
int_max
=
std
::
numeric_limits
<
int
>::
max
();
if
(
width
>
int_max
)
FMT_THROW
(
format_error
(
"number is too big"
));
return
static_cast
<
unsigned
>
(
width
);
}
template
<
typename
T
>
typename
std
::
enable_if
<!
std
::
is_integral
<
T
>::
value
,
unsigned
>::
type
operator
()(
T
)
{
FMT_THROW
(
format_error
(
"width is not integer"
));
return
0
;
}
};
}
// namespace internal
template
<
typename
Range
>
class
printf_arg_formatter
;
template
<
typename
OutputIt
,
typename
Char
,
typename
ArgFormatter
=
printf_arg_formatter
<
back_insert_range
<
internal
::
basic_buffer
<
Char
>
>>>
class
basic_printf_context
;
/**
\rst
The ``printf`` argument formatter.
\endrst
*/
template
<
typename
Range
>
class
printf_arg_formatter
:
public
internal
::
function
<
typename
internal
::
arg_formatter_base
<
Range
>::
iterator
>
,
public
internal
::
arg_formatter_base
<
Range
>
{
private:
typedef
typename
Range
::
value_type
char_type
;
typedef
decltype
(
internal
::
declval
<
Range
>
().
begin
())
iterator
;
typedef
internal
::
arg_formatter_base
<
Range
>
base
;
typedef
basic_printf_context
<
iterator
,
char_type
>
context_type
;
context_type
&
context_
;
void
write_null_pointer
(
char
)
{
this
->
spec
().
type_
=
0
;
this
->
write
(
"(nil)"
);
}
void
write_null_pointer
(
wchar_t
)
{
this
->
spec
().
type_
=
0
;
this
->
write
(
L"(nil)"
);
}
public:
typedef
typename
base
::
format_specs
format_specs
;
/**
\rst
Constructs an argument formatter object.
*buffer* is a reference to the output buffer and *spec* contains format
specifier information for standard argument types.
\endrst
*/
printf_arg_formatter
(
internal
::
basic_buffer
<
char_type
>
&
buffer
,
format_specs
&
spec
,
context_type
&
ctx
)
:
base
(
back_insert_range
<
internal
::
basic_buffer
<
char_type
>>
(
buffer
),
spec
)
,
context_
(
ctx
)
{
}
using
base
::
operator
();
/** Formats an argument of type ``bool``. */
iterator
operator
()(
bool
value
)
{
format_specs
&
fmt_spec
=
this
->
spec
();
if
(
fmt_spec
.
type_
!=
's'
)
return
(
*
this
)(
value
?
1
:
0
);
fmt_spec
.
type_
=
0
;
this
->
write
(
value
);
return
this
->
out
();
}
/** Formats a character. */
iterator
operator
()(
char_type
value
)
{
format_specs
&
fmt_spec
=
this
->
spec
();
if
(
fmt_spec
.
type_
&&
fmt_spec
.
type_
!=
'c'
)
return
(
*
this
)(
static_cast
<
int
>
(
value
));
fmt_spec
.
flags_
=
0
;
fmt_spec
.
align_
=
ALIGN_RIGHT
;
return
base
::
operator
()(
value
);
}
/** Formats a null-terminated C string. */
iterator
operator
()(
const
char
*
value
)
{
if
(
value
)
base
::
operator
()(
value
);
else
if
(
this
->
spec
().
type_
==
'p'
)
write_null_pointer
(
char_type
());
else
this
->
write
(
"(null)"
);
return
this
->
out
();
}
/** Formats a null-terminated wide C string. */
iterator
operator
()(
const
wchar_t
*
value
)
{
if
(
value
)
base
::
operator
()(
value
);
else
if
(
this
->
spec
().
type_
==
'p'
)
write_null_pointer
(
char_type
());
else
this
->
write
(
L"(null)"
);
return
this
->
out
();
}
/** Formats a pointer. */
iterator
operator
()(
const
void
*
value
)
{
if
(
value
)
return
base
::
operator
()(
value
);
this
->
spec
().
type_
=
0
;
write_null_pointer
(
char_type
());
return
this
->
out
();
}
/** Formats an argument of a custom (user-defined) type. */
iterator
operator
()(
typename
basic_format_arg
<
context_type
>::
handle
handle
)
{
handle
.
format
(
context_
);
return
this
->
out
();
}
};
template
<
typename
T
>
struct
printf_formatter
{
template
<
typename
ParseContext
>
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
{
return
ctx
.
begin
();
}
template
<
typename
FormatContext
>
auto
format
(
const
T
&
value
,
FormatContext
&
ctx
)
->
decltype
(
ctx
.
out
())
{
internal
::
format_value
(
internal
::
get_container
(
ctx
.
out
()),
value
);
return
ctx
.
out
();
}
};
/** This template formats data and writes the output to a writer. */
template
<
typename
OutputIt
,
typename
Char
,
typename
ArgFormatter
>
class
basic_printf_context
:
private
internal
::
context_base
<
OutputIt
,
basic_printf_context
<
OutputIt
,
Char
,
ArgFormatter
>
,
Char
>
{
public:
/** The character type for the output. */
typedef
Char
char_type
;
template
<
typename
T
>
struct
formatter_type
{
typedef
printf_formatter
<
T
>
type
;
};
private:
typedef
internal
::
context_base
<
OutputIt
,
basic_printf_context
,
Char
>
base
;
typedef
typename
base
::
format_arg
format_arg
;
typedef
basic_format_specs
<
char_type
>
format_specs
;
typedef
internal
::
null_terminating_iterator
<
char_type
>
iterator
;
void
parse_flags
(
format_specs
&
spec
,
iterator
&
it
);
// Returns the argument with specified index or, if arg_index is equal
// to the maximum unsigned value, the next argument.
format_arg
get_arg
(
iterator
it
,
unsigned
arg_index
=
(
std
::
numeric_limits
<
unsigned
>::
max
)());
// Parses argument index, flags and width and returns the argument index.
unsigned
parse_header
(
iterator
&
it
,
format_specs
&
spec
);
public:
/**
\rst
Constructs a ``printf_context`` object. References to the arguments and
the writer are stored in the context object so make sure they have
appropriate lifetimes.
\endrst
*/
basic_printf_context
(
OutputIt
out
,
basic_string_view
<
char_type
>
format_str
,
basic_format_args
<
basic_printf_context
>
args
)
:
base
(
out
,
format_str
,
args
)
{
}
using
base
::
advance_to
;
using
base
::
out
;
using
base
::
parse_context
;
/** Formats stored arguments and writes the output to the range. */
void
format
();
};
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
void
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
parse_flags
(
format_specs
&
spec
,
iterator
&
it
)
{
for
(;;)
{
switch
(
*
it
++
)
{
case
'-'
:
spec
.
align_
=
ALIGN_LEFT
;
break
;
case
'+'
:
spec
.
flags_
|=
SIGN_FLAG
|
PLUS_FLAG
;
break
;
case
'0'
:
spec
.
fill_
=
'0'
;
break
;
case
' '
:
spec
.
flags_
|=
SIGN_FLAG
;
break
;
case
'#'
:
spec
.
flags_
|=
HASH_FLAG
;
break
;
default:
--
it
;
return
;
}
}
}
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
typename
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
format_arg
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
get_arg
(
iterator
it
,
unsigned
arg_index
)
{
(
void
)
it
;
if
(
arg_index
==
std
::
numeric_limits
<
unsigned
>::
max
())
return
this
->
do_get_arg
(
this
->
parse_context
().
next_arg_id
());
return
base
::
get_arg
(
arg_index
-
1
);
}
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
unsigned
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
parse_header
(
iterator
&
it
,
format_specs
&
spec
)
{
unsigned
arg_index
=
std
::
numeric_limits
<
unsigned
>::
max
();
char_type
c
=
*
it
;
if
(
c
>=
'0'
&&
c
<=
'9'
)
{
// Parse an argument index (if followed by '$') or a width possibly
// preceded with '0' flag(s).
internal
::
error_handler
eh
;
unsigned
value
=
parse_nonnegative_int
(
it
,
eh
);
if
(
*
it
==
'$'
)
{
// value is an argument index
++
it
;
arg_index
=
value
;
}
else
{
if
(
c
==
'0'
)
spec
.
fill_
=
'0'
;
if
(
value
!=
0
)
{
// Nonzero value means that we parsed width and don't need to
// parse it or flags again, so return now.
spec
.
width_
=
value
;
return
arg_index
;
}
}
}
parse_flags
(
spec
,
it
);
// Parse width.
if
(
*
it
>=
'0'
&&
*
it
<=
'9'
)
{
internal
::
error_handler
eh
;
spec
.
width_
=
parse_nonnegative_int
(
it
,
eh
);
}
else
if
(
*
it
==
'*'
)
{
++
it
;
spec
.
width_
=
visit
(
internal
::
printf_width_handler
<
char_type
>
(
spec
),
get_arg
(
it
));
}
return
arg_index
;
}
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
void
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
format
()
{
auto
&
buffer
=
internal
::
get_container
(
this
->
out
());
auto
start
=
iterator
(
this
->
parse_context
());
auto
it
=
start
;
using
internal
::
pointer_from
;
while
(
*
it
)
{
char_type
c
=
*
it
++
;
if
(
c
!=
'%'
)
continue
;
if
(
*
it
==
c
)
{
buffer
.
append
(
pointer_from
(
start
),
pointer_from
(
it
));
start
=
++
it
;
continue
;
}
buffer
.
append
(
pointer_from
(
start
),
pointer_from
(
it
)
-
1
);
format_specs
spec
;
spec
.
align_
=
ALIGN_RIGHT
;
// Parse argument index, flags and width.
unsigned
arg_index
=
parse_header
(
it
,
spec
);
// Parse precision.
if
(
*
it
==
'.'
)
{
++
it
;
if
(
'0'
<=
*
it
&&
*
it
<=
'9'
)
{
internal
::
error_handler
eh
;
spec
.
precision_
=
static_cast
<
int
>
(
parse_nonnegative_int
(
it
,
eh
));
}
else
if
(
*
it
==
'*'
)
{
++
it
;
spec
.
precision_
=
visit
(
internal
::
printf_precision_handler
(),
get_arg
(
it
));
}
else
{
spec
.
precision_
=
0
;
}
}
format_arg
arg
=
get_arg
(
it
,
arg_index
);
if
(
spec
.
flag
(
HASH_FLAG
)
&&
visit
(
internal
::
is_zero_int
(),
arg
))
spec
.
flags_
&=
~
internal
::
to_unsigned
<
int
>
(
HASH_FLAG
);
if
(
spec
.
fill_
==
'0'
)
{
if
(
arg
.
is_arithmetic
())
spec
.
align_
=
ALIGN_NUMERIC
;
else
spec
.
fill_
=
' '
;
// Ignore '0' flag for non-numeric types.
}
// Parse length and convert the argument to the required type.
using
internal
::
convert_arg
;
switch
(
*
it
++
)
{
case
'h'
:
if
(
*
it
==
'h'
)
convert_arg
<
signed
char
>
(
arg
,
*++
it
);
else
convert_arg
<
short
>
(
arg
,
*
it
);
break
;
case
'l'
:
if
(
*
it
==
'l'
)
convert_arg
<
long
long
>
(
arg
,
*++
it
);
else
convert_arg
<
long
>
(
arg
,
*
it
);
break
;
case
'j'
:
convert_arg
<
intmax_t
>
(
arg
,
*
it
);
break
;
case
'z'
:
convert_arg
<
std
::
size_t
>
(
arg
,
*
it
);
break
;
case
't'
:
convert_arg
<
std
::
ptrdiff_t
>
(
arg
,
*
it
);
break
;
case
'L'
:
// printf produces garbage when 'L' is omitted for long double, no
// need to do the same.
break
;
default:
--
it
;
convert_arg
<
void
>
(
arg
,
*
it
);
}
// Parse type.
if
(
!*
it
)
FMT_THROW
(
format_error
(
"invalid format string"
));
spec
.
type_
=
static_cast
<
char
>
(
*
it
++
);
if
(
arg
.
is_integral
())
{
// Normalize type.
switch
(
spec
.
type_
)
{
case
'i'
:
case
'u'
:
spec
.
type_
=
'd'
;
break
;
case
'c'
:
// TODO: handle wchar_t better?
visit
(
internal
::
char_converter
<
basic_printf_context
>
(
arg
),
arg
);
break
;
}
}
start
=
it
;
// Format argument.
visit
(
AF
(
buffer
,
spec
,
*
this
),
arg
);
}
buffer
.
append
(
pointer_from
(
start
),
pointer_from
(
it
));
}
template
<
typename
Char
,
typename
Context
>
void
printf
(
internal
::
basic_buffer
<
Char
>
&
buf
,
basic_string_view
<
Char
>
format
,
basic_format_args
<
Context
>
args
)
{
Context
(
std
::
back_inserter
(
buf
),
format
,
args
).
format
();
}
template
<
typename
Buffer
>
struct
printf_context
{
typedef
basic_printf_context
<
std
::
back_insert_iterator
<
Buffer
>
,
typename
Buffer
::
value_type
>
type
;
};
template
<
typename
...
Args
>
inline
format_arg_store
<
printf_context
<
internal
::
buffer
>::
type
,
Args
...
>
make_printf_args
(
const
Args
&
...
args
)
{
return
format_arg_store
<
printf_context
<
internal
::
buffer
>::
type
,
Args
...
>
(
args
...);
}
typedef
basic_format_args
<
printf_context
<
internal
::
buffer
>::
type
>
printf_args
;
typedef
basic_format_args
<
printf_context
<
internal
::
wbuffer
>::
type
>
wprintf_args
;
inline
std
::
string
vsprintf
(
string_view
format
,
printf_args
args
)
{
memory_buffer
buffer
;
printf
(
buffer
,
format
,
args
);
return
to_string
(
buffer
);
}
/**
\rst
Formats arguments and returns the result as a string.
**Example**::
std::string message = fmt::sprintf("The answer is %d", 42);
\endrst
*/
template
<
typename
...
Args
>
inline
std
::
string
sprintf
(
string_view
format_str
,
const
Args
&
...
args
)
{
return
vsprintf
(
format_str
,
make_format_args
<
typename
printf_context
<
internal
::
buffer
>::
type
>
(
args
...));
}
inline
std
::
wstring
vsprintf
(
wstring_view
format
,
wprintf_args
args
)
{
wmemory_buffer
buffer
;
printf
(
buffer
,
format
,
args
);
return
to_string
(
buffer
);
}
template
<
typename
...
Args
>
inline
std
::
wstring
sprintf
(
wstring_view
format_str
,
const
Args
&
...
args
)
{
return
vsprintf
(
format_str
,
make_format_args
<
typename
printf_context
<
internal
::
wbuffer
>::
type
>
(
args
...));
}
template
<
typename
Char
>
inline
int
vfprintf
(
std
::
FILE
*
f
,
basic_string_view
<
Char
>
format
,
basic_format_args
<
typename
printf_context
<
internal
::
basic_buffer
<
Char
>>::
type
>
args
)
{
basic_memory_buffer
<
Char
>
buffer
;
printf
(
buffer
,
format
,
args
);
std
::
size_t
size
=
buffer
.
size
();
return
std
::
fwrite
(
buffer
.
data
(),
sizeof
(
Char
),
size
,
f
)
<
size
?
-
1
:
static_cast
<
int
>
(
size
);
}
/**
\rst
Prints formatted data to the file *f*.
**Example**::
fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst
*/
template
<
typename
...
Args
>
inline
int
fprintf
(
std
::
FILE
*
f
,
string_view
format_str
,
const
Args
&
...
args
)
{
auto
vargs
=
make_format_args
<
typename
printf_context
<
internal
::
buffer
>::
type
>
(
args
...);
return
vfprintf
<
char
>
(
f
,
format_str
,
vargs
);
}
template
<
typename
...
Args
>
inline
int
fprintf
(
std
::
FILE
*
f
,
wstring_view
format_str
,
const
Args
&
...
args
)
{
return
vfprintf
(
f
,
format_str
,
make_format_args
<
typename
printf_context
<
internal
::
wbuffer
>::
type
>
(
args
...));
}
inline
int
vprintf
(
string_view
format
,
printf_args
args
)
{
return
vfprintf
(
stdout
,
format
,
args
);
}
inline
int
vprintf
(
wstring_view
format
,
wprintf_args
args
)
{
return
vfprintf
(
stdout
,
format
,
args
);
}
/**
\rst
Prints formatted data to ``stdout``.
**Example**::
fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst
*/
template
<
typename
...
Args
>
inline
int
printf
(
string_view
format_str
,
const
Args
&
...
args
)
{
return
vprintf
(
format_str
,
make_format_args
<
typename
printf_context
<
internal
::
buffer
>::
type
>
(
args
...));
}
template
<
typename
...
Args
>
inline
int
printf
(
wstring_view
format_str
,
const
Args
&
...
args
)
{
return
vprintf
(
format_str
,
make_format_args
<
typename
printf_context
<
internal
::
wbuffer
>::
type
>
(
args
...));
}
inline
int
vfprintf
(
std
::
ostream
&
os
,
string_view
format_str
,
printf_args
args
)
{
memory_buffer
buffer
;
printf
(
buffer
,
format_str
,
args
);
internal
::
write
(
os
,
buffer
);
return
static_cast
<
int
>
(
buffer
.
size
());
}
inline
int
vfprintf
(
std
::
wostream
&
os
,
wstring_view
format_str
,
wprintf_args
args
)
{
wmemory_buffer
buffer
;
printf
(
buffer
,
format_str
,
args
);
internal
::
write
(
os
,
buffer
);
return
static_cast
<
int
>
(
buffer
.
size
());
}
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fmt::fprintf(cerr, "Don't %s!", "panic");
\endrst
*/
template
<
typename
...
Args
>
inline
int
fprintf
(
std
::
ostream
&
os
,
string_view
format_str
,
const
Args
&
...
args
)
{
auto
vargs
=
make_format_args
<
typename
printf_context
<
internal
::
buffer
>::
type
>
(
args
...);
return
vfprintf
(
os
,
format_str
,
vargs
);
}
template
<
typename
...
Args
>
inline
int
fprintf
(
std
::
wostream
&
os
,
wstring_view
format_str
,
const
Args
&
...
args
)
{
auto
vargs
=
make_format_args
<
typename
printf_context
<
internal
::
buffer
>::
type
>
(
args
...);
return
vfprintf
(
os
,
format_str
,
vargs
);
}
FMT_END_NAMESPACE
#endif // FMT_PRINTF_H_
include/spdlog/fmt/bundled/ranges.h
0 → 100644
View file @
3f438a80
// Formatting library for C++ - the core API
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
//
// Copyright (c) 2018 - present, Remotion (Igor Schulz)
// All Rights Reserved
// {fmt} support for ranges, containers and types tuple interface.
#ifndef FMT_RANGES_H_
#define FMT_RANGES_H_
#include "format.h"
#include <type_traits>
// output only up to N items from the range.
#ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT
#define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256
#endif
FMT_BEGIN_NAMESPACE
template
<
typename
Char
>
struct
formatting_base
{
template
<
typename
ParseContext
>
FMT_CONSTEXPR
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
{
return
ctx
.
begin
();
}
};
template
<
typename
Char
,
typename
Enable
=
void
>
struct
formatting_range
:
formatting_base
<
Char
>
{
static
FMT_CONSTEXPR_DECL
const
std
::
size_t
range_length_limit
=
FMT_RANGE_OUTPUT_LENGTH_LIMIT
;
// output only up to N items from the range.
Char
prefix
;
Char
delimiter
;
Char
postfix
;
formatting_range
()
:
prefix
(
'{'
)
,
delimiter
(
','
)
,
postfix
(
'}'
)
{
}
static
FMT_CONSTEXPR_DECL
const
bool
add_delimiter_spaces
=
true
;
static
FMT_CONSTEXPR_DECL
const
bool
add_prepostfix_space
=
false
;
};
template
<
typename
Char
,
typename
Enable
=
void
>
struct
formatting_tuple
:
formatting_base
<
Char
>
{
Char
prefix
;
Char
delimiter
;
Char
postfix
;
formatting_tuple
()
:
prefix
(
'('
)
,
delimiter
(
','
)
,
postfix
(
')'
)
{
}
static
FMT_CONSTEXPR_DECL
const
bool
add_delimiter_spaces
=
true
;
static
FMT_CONSTEXPR_DECL
const
bool
add_prepostfix_space
=
false
;
};
namespace
internal
{
template
<
typename
RangeT
,
typename
OutputIterator
>
void
copy
(
const
RangeT
&
range
,
OutputIterator
out
)
{
for
(
auto
it
=
range
.
begin
(),
end
=
range
.
end
();
it
!=
end
;
++
it
)
*
out
++
=
*
it
;
}
template
<
typename
OutputIterator
>
void
copy
(
const
char
*
str
,
OutputIterator
out
)
{
const
char
*
p_curr
=
str
;
while
(
*
p_curr
)
{
*
out
++
=
*
p_curr
++
;
}
}
template
<
typename
OutputIterator
>
void
copy
(
char
ch
,
OutputIterator
out
)
{
*
out
++
=
ch
;
}
/// Return true value if T has std::string interface, like std::string_view.
template
<
typename
T
>
class
is_like_std_string
{
template
<
typename
U
>
static
auto
check
(
U
*
p
)
->
decltype
(
p
->
find
(
'a'
),
p
->
length
(),
p
->
data
(),
int
());
template
<
typename
>
static
void
check
(...);
public:
static
FMT_CONSTEXPR_DECL
const
bool
value
=
!
std
::
is_void
<
decltype
(
check
<
T
>
(
FMT_NULL
))
>::
value
;
};
template
<
typename
...
Ts
>
struct
conditional_helper
{
};
template
<
typename
T
,
typename
_
=
void
>
struct
is_range_
:
std
::
false_type
{
};
template
<
typename
T
>
struct
is_range_
<
T
,
typename
std
::
conditional
<
false
,
conditional_helper
<
decltype
(
internal
::
declval
<
T
>
().
begin
()),
decltype
(
internal
::
declval
<
T
>
().
end
())
>
,
void
>::
type
>
:
std
::
true_type
{
};
/// tuple_size and tuple_element check.
template
<
typename
T
>
class
is_tuple_like_
{
template
<
typename
U
>
static
auto
check
(
U
*
p
)
->
decltype
(
std
::
tuple_size
<
U
>::
value
,
internal
::
declval
<
typename
std
::
tuple_element
<
0
,
U
>::
type
>
(),
int
());
template
<
typename
>
static
void
check
(...);
public:
static
FMT_CONSTEXPR_DECL
const
bool
value
=
!
std
::
is_void
<
decltype
(
check
<
T
>
(
FMT_NULL
))
>::
value
;
};
// Check for integer_sequence
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
template
<
typename
T
,
T
...
N
>
using
integer_sequence
=
std
::
integer_sequence
<
T
,
N
...
>
;
template
<
std
::
size_t
...
N
>
using
index_sequence
=
std
::
index_sequence
<
N
...
>
;
template
<
std
::
size_t
N
>
using
make_index_sequence
=
std
::
make_index_sequence
<
N
>
;
#else
template
<
typename
T
,
T
...
N
>
struct
integer_sequence
{
typedef
T
value_type
;
static
FMT_CONSTEXPR
std
::
size_t
size
()
{
return
sizeof
...(
N
);
}
};
template
<
std
::
size_t
...
N
>
using
index_sequence
=
integer_sequence
<
std
::
size_t
,
N
...
>
;
template
<
typename
T
,
std
::
size_t
N
,
T
...
Ns
>
struct
make_integer_sequence
:
make_integer_sequence
<
T
,
N
-
1
,
N
-
1
,
Ns
...
>
{
};
template
<
typename
T
,
T
...
Ns
>
struct
make_integer_sequence
<
T
,
0
,
Ns
...
>
:
integer_sequence
<
T
,
Ns
...
>
{
};
template
<
std
::
size_t
N
>
using
make_index_sequence
=
make_integer_sequence
<
std
::
size_t
,
N
>
;
#endif
template
<
class
Tuple
,
class
F
,
size_t
...
Is
>
void
for_each
(
index_sequence
<
Is
...
>
,
Tuple
&&
tup
,
F
&&
f
)
noexcept
{
using
std
::
get
;
// using free function get<I>(T) now.
const
int
_
[]
=
{
0
,
((
void
)
f
(
get
<
Is
>
(
tup
)),
0
)...};
(
void
)
_
;
// blocks warnings
}
template
<
class
T
>
FMT_CONSTEXPR
make_index_sequence
<
std
::
tuple_size
<
T
>::
value
>
get_indexes
(
T
const
&
)
{
return
{};
}
template
<
class
Tuple
,
class
F
>
void
for_each
(
Tuple
&&
tup
,
F
&&
f
)
{
const
auto
indexes
=
get_indexes
(
tup
);
for_each
(
indexes
,
std
::
forward
<
Tuple
>
(
tup
),
std
::
forward
<
F
>
(
f
));
}
template
<
typename
Arg
>
FMT_CONSTEXPR
const
char
*
format_str_quoted
(
bool
add_space
,
const
Arg
&
,
typename
std
::
enable_if
<!
is_like_std_string
<
typename
std
::
decay
<
Arg
>::
type
>::
value
>::
type
*
=
nullptr
)
{
return
add_space
?
" {}"
:
"{}"
;
}
template
<
typename
Arg
>
FMT_CONSTEXPR
const
char
*
format_str_quoted
(
bool
add_space
,
const
Arg
&
,
typename
std
::
enable_if
<
is_like_std_string
<
typename
std
::
decay
<
Arg
>::
type
>::
value
>::
type
*
=
nullptr
)
{
return
add_space
?
"
\"
{}
\"
"
:
"
\"
{}
\"
"
;
}
FMT_CONSTEXPR
const
char
*
format_str_quoted
(
bool
add_space
,
const
char
*
)
{
return
add_space
?
"
\"
{}
\"
"
:
"
\"
{}
\"
"
;
}
FMT_CONSTEXPR
const
wchar_t
*
format_str_quoted
(
bool
add_space
,
const
wchar_t
*
)
{
return
add_space
?
L"
\"
{}
\"
"
:
L"
\"
{}
\"
"
;
}
FMT_CONSTEXPR
const
char
*
format_str_quoted
(
bool
add_space
,
const
char
)
{
return
add_space
?
" '{}'"
:
"'{}'"
;
}
FMT_CONSTEXPR
const
wchar_t
*
format_str_quoted
(
bool
add_space
,
const
wchar_t
)
{
return
add_space
?
L" '{}'"
:
L"'{}'"
;
}
}
// namespace internal
template
<
typename
T
>
struct
is_tuple_like
{
static
FMT_CONSTEXPR_DECL
const
bool
value
=
internal
::
is_tuple_like_
<
T
>::
value
&&
!
internal
::
is_range_
<
T
>::
value
;
};
template
<
typename
TupleT
,
typename
Char
>
struct
formatter
<
TupleT
,
Char
,
typename
std
::
enable_if
<
fmt
::
is_tuple_like
<
TupleT
>::
value
>::
type
>
{
private:
// C++11 generic lambda for format()
template
<
typename
FormatContext
>
struct
format_each
{
template
<
typename
T
>
void
operator
()(
const
T
&
v
)
{
if
(
i
>
0
)
{
if
(
formatting
.
add_prepostfix_space
)
{
*
out
++
=
' '
;
}
internal
::
copy
(
formatting
.
delimiter
,
out
);
}
format_to
(
out
,
internal
::
format_str_quoted
((
formatting
.
add_delimiter_spaces
&&
i
>
0
),
v
),
v
);
++
i
;
}
formatting_tuple
<
Char
>
&
formatting
;
std
::
size_t
&
i
;
typename
std
::
add_lvalue_reference
<
decltype
(
std
::
declval
<
FormatContext
>
().
out
())
>::
type
out
;
};
public:
formatting_tuple
<
Char
>
formatting
;
template
<
typename
ParseContext
>
FMT_CONSTEXPR
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
{
return
formatting
.
parse
(
ctx
);
}
template
<
typename
FormatContext
=
format_context
>
auto
format
(
const
TupleT
&
values
,
FormatContext
&
ctx
)
->
decltype
(
ctx
.
out
())
{
auto
out
=
ctx
.
out
();
std
::
size_t
i
=
0
;
internal
::
copy
(
formatting
.
prefix
,
out
);
internal
::
for_each
(
values
,
format_each
<
FormatContext
>
{
formatting
,
i
,
out
});
if
(
formatting
.
add_prepostfix_space
)
{
*
out
++
=
' '
;
}
internal
::
copy
(
formatting
.
postfix
,
out
);
return
ctx
.
out
();
}
};
template
<
typename
T
>
struct
is_range
{
static
FMT_CONSTEXPR_DECL
const
bool
value
=
internal
::
is_range_
<
T
>::
value
&&
!
internal
::
is_like_std_string
<
T
>::
value
;
};
template
<
typename
RangeT
,
typename
Char
>
struct
formatter
<
RangeT
,
Char
,
typename
std
::
enable_if
<
fmt
::
is_range
<
RangeT
>::
value
>::
type
>
{
formatting_range
<
Char
>
formatting
;
template
<
typename
ParseContext
>
FMT_CONSTEXPR
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
{
return
formatting
.
parse
(
ctx
);
}
template
<
typename
FormatContext
>
typename
FormatContext
::
iterator
format
(
const
RangeT
&
values
,
FormatContext
&
ctx
)
{
auto
out
=
ctx
.
out
();
internal
::
copy
(
formatting
.
prefix
,
out
);
std
::
size_t
i
=
0
;
for
(
auto
it
=
values
.
begin
(),
end
=
values
.
end
();
it
!=
end
;
++
it
)
{
if
(
i
>
0
)
{
if
(
formatting
.
add_prepostfix_space
)
{
*
out
++
=
' '
;
}
internal
::
copy
(
formatting
.
delimiter
,
out
);
}
format_to
(
out
,
internal
::
format_str_quoted
((
formatting
.
add_delimiter_spaces
&&
i
>
0
),
*
it
),
*
it
);
if
(
++
i
>
formatting
.
range_length_limit
)
{
format_to
(
out
,
" ... <other elements>"
);
break
;
}
}
if
(
formatting
.
add_prepostfix_space
)
{
*
out
++
=
' '
;
}
internal
::
copy
(
formatting
.
postfix
,
out
);
return
ctx
.
out
();
}
};
FMT_END_NAMESPACE
#endif // FMT_RANGES_H_
include/spdlog/fmt/bundled/time.h
0 → 100644
View file @
3f438a80
// Formatting library for C++ - time formatting
//
// Copyright (c) 2012 - 2016, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_TIME_H_
#define FMT_TIME_H_
#include "format.h"
#include <ctime>
FMT_BEGIN_NAMESPACE
namespace
internal
{
inline
null
<>
localtime_r
(...)
{
return
null
<>
();
}
inline
null
<>
localtime_s
(...)
{
return
null
<>
();
}
inline
null
<>
gmtime_r
(...)
{
return
null
<>
();
}
inline
null
<>
gmtime_s
(...)
{
return
null
<>
();
}
}
// namespace internal
// Thread-safe replacement for std::localtime
inline
std
::
tm
localtime
(
std
::
time_t
time
)
{
struct
dispatcher
{
std
::
time_t
time_
;
std
::
tm
tm_
;
dispatcher
(
std
::
time_t
t
)
:
time_
(
t
)
{
}
bool
run
()
{
using
namespace
fmt
::
internal
;
return
handle
(
localtime_r
(
&
time_
,
&
tm_
));
}
bool
handle
(
std
::
tm
*
tm
)
{
return
tm
!=
FMT_NULL
;
}
bool
handle
(
internal
::
null
<>
)
{
using
namespace
fmt
::
internal
;
return
fallback
(
localtime_s
(
&
tm_
,
&
time_
));
}
bool
fallback
(
int
res
)
{
return
res
==
0
;
}
bool
fallback
(
internal
::
null
<>
)
{
using
namespace
fmt
::
internal
;
std
::
tm
*
tm
=
std
::
localtime
(
&
time_
);
if
(
tm
)
tm_
=
*
tm
;
return
tm
!=
FMT_NULL
;
}
};
dispatcher
lt
(
time
);
if
(
lt
.
run
())
return
lt
.
tm_
;
// Too big time values may be unsupported.
FMT_THROW
(
format_error
(
"time_t value out of range"
));
}
// Thread-safe replacement for std::gmtime
inline
std
::
tm
gmtime
(
std
::
time_t
time
)
{
struct
dispatcher
{
std
::
time_t
time_
;
std
::
tm
tm_
;
dispatcher
(
std
::
time_t
t
)
:
time_
(
t
)
{
}
bool
run
()
{
using
namespace
fmt
::
internal
;
return
handle
(
gmtime_r
(
&
time_
,
&
tm_
));
}
bool
handle
(
std
::
tm
*
tm
)
{
return
tm
!=
FMT_NULL
;
}
bool
handle
(
internal
::
null
<>
)
{
using
namespace
fmt
::
internal
;
return
fallback
(
gmtime_s
(
&
tm_
,
&
time_
));
}
bool
fallback
(
int
res
)
{
return
res
==
0
;
}
bool
fallback
(
internal
::
null
<>
)
{
std
::
tm
*
tm
=
std
::
gmtime
(
&
time_
);
if
(
tm
)
tm_
=
*
tm
;
return
tm
!=
FMT_NULL
;
}
};
dispatcher
gt
(
time
);
if
(
gt
.
run
())
return
gt
.
tm_
;
// Too big time values may be unsupported.
FMT_THROW
(
format_error
(
"time_t value out of range"
));
}
namespace
internal
{
inline
std
::
size_t
strftime
(
char
*
str
,
std
::
size_t
count
,
const
char
*
format
,
const
std
::
tm
*
time
)
{
return
std
::
strftime
(
str
,
count
,
format
,
time
);
}
inline
std
::
size_t
strftime
(
wchar_t
*
str
,
std
::
size_t
count
,
const
wchar_t
*
format
,
const
std
::
tm
*
time
)
{
return
std
::
wcsftime
(
str
,
count
,
format
,
time
);
}
}
// namespace internal
template
<
typename
Char
>
struct
formatter
<
std
::
tm
,
Char
>
{
template
<
typename
ParseContext
>
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
{
auto
it
=
internal
::
null_terminating_iterator
<
Char
>
(
ctx
);
if
(
*
it
==
':'
)
++
it
;
auto
end
=
it
;
while
(
*
end
&&
*
end
!=
'}'
)
++
end
;
tm_format
.
reserve
(
end
-
it
+
1
);
using
internal
::
pointer_from
;
tm_format
.
append
(
pointer_from
(
it
),
pointer_from
(
end
));
tm_format
.
push_back
(
'\0'
);
return
pointer_from
(
end
);
}
template
<
typename
FormatContext
>
auto
format
(
const
std
::
tm
&
tm
,
FormatContext
&
ctx
)
->
decltype
(
ctx
.
out
())
{
internal
::
basic_buffer
<
Char
>
&
buf
=
internal
::
get_container
(
ctx
.
out
());
std
::
size_t
start
=
buf
.
size
();
for
(;;)
{
std
::
size_t
size
=
buf
.
capacity
()
-
start
;
std
::
size_t
count
=
internal
::
strftime
(
&
buf
[
start
],
size
,
&
tm_format
[
0
],
&
tm
);
if
(
count
!=
0
)
{
buf
.
resize
(
start
+
count
);
break
;
}
if
(
size
>=
tm_format
.
size
()
*
256
)
{
// If the buffer is 256 times larger than the format string, assume
// that `strftime` gives an empty result. There doesn't seem to be a
// better way to distinguish the two cases:
// https://github.com/fmtlib/fmt/issues/367
break
;
}
const
std
::
size_t
MIN_GROWTH
=
10
;
buf
.
reserve
(
buf
.
capacity
()
+
(
size
>
MIN_GROWTH
?
size
:
MIN_GROWTH
));
}
return
ctx
.
out
();
}
basic_memory_buffer
<
Char
>
tm_format
;
};
FMT_END_NAMESPACE
#endif // FMT_TIME_H_
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment