Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
S
spdlog
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
spdlog
Commits
f4771be7
Commit
f4771be7
authored
Jul 08, 2018
by
gabime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Upgraded to fmt 5.1.0
parent
887326e7
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
1267 additions
and
1744 deletions
+1267
-1744
core.h
include/spdlog/fmt/bundled/core.h
+497
-740
format-inl.h
include/spdlog/fmt/bundled/format-inl.h
+221
-191
format.cc
include/spdlog/fmt/bundled/format.cc
+0
-46
format.h
include/spdlog/fmt/bundled/format.h
+0
-0
ostream.h
include/spdlog/fmt/bundled/ostream.h
+52
-61
posix.h
include/spdlog/fmt/bundled/posix.h
+82
-149
printf.h
include/spdlog/fmt/bundled/printf.h
+251
-309
ranges.h
include/spdlog/fmt/bundled/ranges.h
+124
-161
time.h
include/spdlog/fmt/bundled/time.h
+40
-87
No files found.
include/spdlog/fmt/bundled/core.h
View file @
f4771be7
...
...
@@ -19,157 +19,158 @@
#define FMT_VERSION 50100
#ifdef __has_feature
#define FMT_HAS_FEATURE(x) __has_feature(x)
#
define FMT_HAS_FEATURE(x) __has_feature(x)
#else
#define FMT_HAS_FEATURE(x) 0
#
define FMT_HAS_FEATURE(x) 0
#endif
#ifdef __has_include
#define FMT_HAS_INCLUDE(x) __has_include(x)
#
define FMT_HAS_INCLUDE(x) __has_include(x)
#else
#define FMT_HAS_INCLUDE(x) 0
#
define FMT_HAS_INCLUDE(x) 0
#endif
#ifdef __has_cpp_attribute
#define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#
define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
#define FMT_HAS_CPP_ATTRIBUTE(x) 0
#
define FMT_HAS_CPP_ATTRIBUTE(x) 0
#endif
#if defined(__GNUC__) && !defined(__clang__)
#define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#
define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#else
#define FMT_GCC_VERSION 0
#
define FMT_GCC_VERSION 0
#endif
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
#define FMT_HAS_GXX_CXX11 FMT_GCC_VERSION
#
define FMT_HAS_GXX_CXX11 FMT_GCC_VERSION
#else
#define FMT_HAS_GXX_CXX11 0
#
define FMT_HAS_GXX_CXX11 0
#endif
#ifdef _MSC_VER
#define FMT_MSC_VER _MSC_VER
#
define FMT_MSC_VER _MSC_VER
#else
#define FMT_MSC_VER 0
#
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))
# 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
#
define FMT_CONSTEXPR constexpr
#
define FMT_CONSTEXPR_DECL constexpr
#else
#define FMT_CONSTEXPR inline
#define FMT_CONSTEXPR_DECL
#
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
# 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
#if FMT_HAS_FEATURE(cxx_explicit_conversions) || \
FMT_MSC_VER >= 1800
# define FMT_EXPLICIT explicit
#else
#define FMT_EXPLICIT
#
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
# 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
#
define FMT_USE_NULLPTR 0
#endif
#if FMT_HAS_CPP_ATTRIBUTE(noreturn)
#define FMT_NORETURN [[noreturn]]
#
define FMT_NORETURN [[noreturn]]
#else
#define FMT_NORETURN
#
define FMT_NORETURN
#endif
// Check if exceptions are disabled.
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
#define FMT_EXCEPTIONS 0
#
define FMT_EXCEPTIONS 0
#elif FMT_MSC_VER && !_HAS_EXCEPTIONS
#define FMT_EXCEPTIONS 0
#
define FMT_EXCEPTIONS 0
#endif
#ifndef FMT_EXCEPTIONS
#define FMT_EXCEPTIONS 1
#
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
#
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
#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()
#
define FMT_DETECTED_NOEXCEPT throw()
#endif
#ifndef FMT_NOEXCEPT
#if FMT_EXCEPTIONS
#define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT
#else
#define FMT_NOEXCEPT
#endif
#
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
#
define FMT_DTOR_NOEXCEPT FMT_DETECTED_NOEXCEPT
#else
#define FMT_DTOR_NOEXCEPT FMT_NOEXCEPT
#
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 \
{
# 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
#
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
#
define FMT_API
#endif
#ifndef FMT_ASSERT
#define FMT_ASSERT(condition, message) assert((condition) && message)
#
define FMT_ASSERT(condition, message) assert((condition) && message)
#endif
#define FMT_DELETED = delete
...
...
@@ -180,26 +181,37 @@
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))) || \
#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
# 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>
#
include <functional>
#endif
FMT_BEGIN_NAMESPACE
// An implementation of declval for pre-C++11 compilers such as gcc 4.
namespace
internal
{
template
<
typename
T
>
// An implementation of declval for pre-C++11 compilers such as gcc 4.
template
<
typename
T
>
typename
std
::
add_rvalue_reference
<
T
>::
type
declval
()
FMT_NOEXCEPT
;
// Casts nonnegative integer to unsigned.
template
<
typename
Int
>
FMT_CONSTEXPR
typename
std
::
make_unsigned
<
Int
>::
type
to_unsigned
(
Int
value
)
{
FMT_ASSERT
(
value
>=
0
,
"negative value"
);
return
static_cast
<
typename
std
::
make_unsigned
<
Int
>::
type
>
(
value
);
}
}
/**
...
...
@@ -209,14 +221,13 @@ typename std::add_rvalue_reference<T>::type declval() FMT_NOEXCEPT;
compiled with a different ``-std`` option than the client code (which is not
recommended).
*/
template
<
typename
Char
>
class
basic_string_view
{
private
:
template
<
typename
Char
>
class
basic_string_view
{
private
:
const
Char
*
data_
;
size_t
size_
;
public
:
public
:
typedef
Char
char_type
;
typedef
const
Char
*
iterator
;
...
...
@@ -226,23 +237,17 @@ public:
#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
;
}
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
)
{}
FMT_CONSTEXPR
basic_string_view
(
const
Char
*
s
,
size_t
count
)
FMT_NOEXCEPT
:
data_
(
s
),
size_
(
count
)
{}
/**
\rst
...
...
@@ -251,49 +256,33 @@ public:
\endrst
*/
basic_string_view
(
const
Char
*
s
)
:
data_
(
s
)
,
size_
(
std
::
char_traits
<
Char
>::
length
(
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
())
{
}
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
())
{}
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_
;
}
const
Char
*
data
()
const
{
return
data_
;
}
/** Returns the string size. */
FMT_CONSTEXPR
size_t
size
()
const
{
return
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
iterator
begin
()
const
{
return
data_
;
}
FMT_CONSTEXPR
iterator
end
()
const
{
return
data_
+
size_
;
}
FMT_CONSTEXPR
void
remove_prefix
(
size_t
n
)
{
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
{
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
)
...
...
@@ -301,28 +290,22 @@ public:
return
result
;
}
friend
bool
operator
==
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
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
)
{
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
)
{
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
)
{
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
)
{
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
)
{
friend
bool
operator
>=
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
return
lhs
.
compare
(
rhs
)
>=
0
;
}
};
...
...
@@ -330,39 +313,34 @@ public:
typedef
basic_string_view
<
char
>
string_view
;
typedef
basic_string_view
<
wchar_t
>
wstring_view
;
template
<
typename
Context
>
template
<
typename
Context
>
class
basic_format_arg
;
template
<
typename
Context
>
template
<
typename
Context
>
class
basic_format_args
;
// A formatter for objects of type T.
template
<
typename
T
,
typename
Char
=
char
,
typename
Enable
=
void
>
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
:
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
)
{
}
protected
:
basic_buffer
(
T
*
p
=
FMT_NULL
,
std
::
size_t
sz
=
0
,
std
::
size_t
cap
=
0
)
FMT_NOEXCEPT
:
ptr_
(
p
),
size_
(
sz
),
capacity_
(
cap
)
{}
/** Sets the buffer data and capacity. */
void
set
(
T
*
buf_data
,
std
::
size_t
buf_capacity
)
FMT_NOEXCEPT
{
void
set
(
T
*
buf_data
,
std
::
size_t
buf_capacity
)
FMT_NOEXCEPT
{
ptr_
=
buf_data
;
capacity_
=
buf_capacity
;
}
...
...
@@ -370,108 +348,76 @@ protected:
/** Increases the buffer capacity to hold at least *capacity* elements. */
virtual
void
grow
(
std
::
size_t
capacity
)
=
0
;
public
:
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_
;
}
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_
;
}
std
::
size_t
size
()
const
FMT_NOEXCEPT
{
return
size_
;
}
/** Returns the capacity of this buffer. */
std
::
size_t
capacity
()
const
FMT_NOEXCEPT
{
return
capacity_
;
}
std
::
size_t
capacity
()
const
FMT_NOEXCEPT
{
return
capacity_
;
}
/** Returns a pointer to the buffer data. */
T
*
data
()
FMT_NOEXCEPT
{
return
ptr_
;
}
T
*
data
()
FMT_NOEXCEPT
{
return
ptr_
;
}
/** Returns a pointer to the buffer data. */
const
T
*
data
()
const
FMT_NOEXCEPT
{
return
ptr_
;
}
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
)
{
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
);
/** Reserves space to store at least *capacity* elements. */
void
reserve
(
std
::
size_t
new_capacity
)
{
if
(
new_capacity
>
capacity_
)
grow
(
new_capacity
);
}
void
push_back
(
const
T
&
value
)
{
void
push_back
(
const
T
&
value
)
{
reserve
(
size_
+
1
);
ptr_
[
size_
++
]
=
value
;
}
/** Appends data to the end of the buffer. */
template
<
typename
U
>
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
];
}
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
:
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
{
protected
:
void
grow
(
std
::
size_t
capacity
)
FMT_OVERRIDE
{
container_
.
resize
(
capacity
);
this
->
set
(
&
container_
[
0
],
capacity
);
}
public
:
public
:
explicit
container_buffer
(
Container
&
c
)
:
basic_buffer
<
typename
Container
::
value_type
>
(
&
c
[
0
],
c
.
size
(),
c
.
size
())
,
container_
(
c
)
{
}
:
basic_buffer
<
typename
Container
::
value_type
>
(
&
c
[
0
],
c
.
size
(),
c
.
size
()),
container_
(
c
)
{}
};
struct
error_handler
{
struct
error_handler
{
FMT_CONSTEXPR
error_handler
()
{}
FMT_CONSTEXPR
error_handler
(
const
error_handler
&
)
{}
...
...
@@ -483,94 +429,71 @@ struct error_handler
// 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
>
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
>
template
<
typename
Char
>
struct
named_arg_base
;
template
<
typename
T
,
typename
Char
>
template
<
typename
T
,
typename
Char
>
struct
named_arg
;
template
<
typename
T
>
struct
is_named_arg
:
std
::
false_type
{
};
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
{
};
template
<
typename
T
,
typename
Char
>
struct
is_named_arg
<
named_arg
<
T
,
Char
>>
:
std
::
true_type
{};
enum
type
{
none_type
,
named_arg_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
,
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
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_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_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
{
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
{
template
<
typename
Char
>
struct
string_value
{
const
Char
*
value
;
std
::
size_t
size
;
};
template
<
typename
Context
>
struct
custom_value
{
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
:
template
<
typename
Context
>
class
value
{
public
:
typedef
typename
Context
::
char_type
char_type
;
union
{
union
{
int
int_value
;
unsigned
uint_value
;
long
long
long_long_value
;
...
...
@@ -584,107 +507,73 @@ public:
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"
);
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"
);
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
)
{
value
(
basic_string_view
<
char_type
>
val
)
{
string
.
value
=
val
.
data
();
string
.
size
=
val
.
size
();
}
value
(
const
void
*
val
)
{
pointer
=
val
;
}
value
(
const
void
*
val
)
{
pointer
=
val
;
}
template
<
typename
T
>
explicit
value
(
const
T
&
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
);
const
named_arg_base
<
char_type
>
&
as_named_arg
()
{
return
*
static_cast
<
const
named_arg_base
<
char_type
>*>
(
pointer
);
}
private
:
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
)
{
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
));
ctx
.
advance_to
(
f
.
format
(
*
static_cast
<
const
T
*>
(
arg
),
ctx
));
}
};
template
<
typename
Context
,
type
TYPE
>
struct
typed_value
:
value
<
Context
>
{
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
T
>
FMT_CONSTEXPR
typed_value
(
const
T
&
val
)
:
value
<
Context
>
(
val
)
{}
};
template
<
typename
Context
,
typename
T
>
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) \
{ \
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) \
{ \
template <typename C> \
FMT_CONSTEXPR typed_value<C, TAG> make_value(Type val) { \
return val; \
}
...
...
@@ -696,10 +585,15 @@ 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
)
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
)
...
...
@@ -708,9 +602,8 @@ 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
)
{
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
);
}
...
...
@@ -722,187 +615,157 @@ 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
(
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
*
)
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
*
)
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
*
)
{
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
>
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
,
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
;
}
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
)
{
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
);
return
static_cast
<
const
void
*>
(
&
val
);
}
// Maximum number of arguments with packed types.
enum
{
max_packed_args
=
15
};
enum
{
max_packed_args
=
15
};
template
<
typename
Context
>
template
<
typename
Context
>
class
arg_map
;
template
<
typename
>
template
<
typename
>
struct
result_of
;
template
<
typename
F
,
typename
...
Args
>
struct
result_of
<
F
(
Args
...)
>
{
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
;
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
:
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
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
);
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
)
{
}
class
handle
{
public
:
explicit
handle
(
internal
::
custom_value
<
Context
>
custom
)
:
custom_
(
custom
)
{}
void
format
(
Context
&
ctx
)
const
{
custom_
.
format
(
custom_
.
value
,
ctx
);
}
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_CONSTEXPR
basic_format_arg
()
:
type_
(
internal
::
none_type
)
{}
FMT_EXPLICIT
operator
bool
()
const
FMT_NOEXCEPT
{
FMT_EXPLICIT
operator
bool
()
const
FMT_NOEXCEPT
{
return
type_
!=
internal
::
none_type
;
}
internal
::
type
type
()
const
{
return
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_
);
}
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
:
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
:
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
)
{
}
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
{
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
();
}
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
());
FMT_CONSTEXPR
void
advance_to
(
iterator
it
)
{
format_str_
.
remove_prefix
(
internal
::
to_unsigned
(
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
)
{
FMT_CONSTEXPR
bool
check_arg_id
(
unsigned
)
{
if
(
next_arg_id_
>
0
)
{
on_error
(
"cannot switch from automatic to manual argument indexing"
);
return
false
;
}
...
...
@@ -911,15 +774,11 @@ public:
}
void
check_arg_id
(
basic_string_view
<
Char
>
)
{}
FMT_CONSTEXPR
void
on_error
(
const
char
*
message
)
{
FMT_CONSTEXPR
void
on_error
(
const
char
*
message
)
{
ErrorHandler
::
on_error
(
message
);
}
FMT_CONSTEXPR
ErrorHandler
error_handler
()
const
{
return
*
this
;
}
FMT_CONSTEXPR
ErrorHandler
error_handler
()
const
{
return
*
this
;
}
};
typedef
basic_parse_context
<
char
>
parse_context
;
...
...
@@ -927,16 +786,14 @@ 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
:
template
<
typename
Context
>
class
arg_map
{
private
:
FMT_DISALLOW_COPY_AND_ASSIGN
(
arg_map
);
typedef
typename
Context
::
char_type
char_type
;
struct
entry
{
struct
entry
{
basic_string_view
<
char_type
>
name
;
basic_format_arg
<
Context
>
arg
;
};
...
...
@@ -944,30 +801,20 @@ private:
entry
*
map_
;
unsigned
size_
;
void
push_back
(
value
<
Context
>
val
)
{
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
)
{
}
public
:
arg_map
()
:
map_
(
FMT_NULL
),
size_
(
0
)
{}
void
init
(
const
basic_format_args
<
Context
>
&
args
);
~
arg_map
()
{
delete
[]
map_
;
}
~
arg_map
()
{
delete
[]
map_
;
}
basic_format_arg
<
Context
>
find
(
basic_string_view
<
char_type
>
name
)
const
{
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
)
{
for
(
entry
*
it
=
map_
,
*
end
=
map_
+
size_
;
it
!=
end
;
++
it
)
{
if
(
it
->
name
==
name
)
return
it
->
arg
;
}
...
...
@@ -975,31 +822,26 @@ public:
}
};
template
<
typename
OutputIt
,
typename
Context
,
typename
Char
>
class
context_base
{
public
:
template
<
typename
OutputIt
,
typename
Context
,
typename
Char
>
class
context_base
{
public
:
typedef
OutputIt
iterator
;
private
:
private
:
basic_parse_context
<
Char
>
parse_context_
;
iterator
out_
;
basic_format_args
<
Context
>
args_
;
protected
:
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
)
{
}
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
do_get_arg
(
unsigned
arg_id
)
{
format_arg
arg
=
args_
.
get
(
arg_id
);
if
(
!
arg
)
parse_context_
.
on_error
(
"argument index out of range"
);
...
...
@@ -1008,60 +850,38 @@ protected:
// 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
();
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
()
{
public
:
basic_parse_context
<
char_type
>
&
parse_context
()
{
return
parse_context_
;
}
internal
::
error_handler
error_handler
()
{
internal
::
error_handler
error_handler
()
{
return
parse_context_
.
error_handler
();
}
void
on_error
(
const
char
*
message
)
{
parse_context_
.
on_error
(
message
);
}
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
iterator
out
()
{
return
out_
;
}
iterator
begin
()
{
return
out_
;
}
// deprecated
// Advances the begin iterator to ``it``.
void
advance_to
(
iterator
it
)
{
out_
=
it
;
}
void
advance_to
(
iterator
it
)
{
out_
=
it
;
}
basic_format_args
<
Context
>
args
()
const
{
return
args_
;
}
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
)
{
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
)
{
}
struct
accessor
:
bi_iterator
{
accessor
(
bi_iterator
iter
)
:
bi_iterator
(
iter
)
{}
using
bi_iterator
::
container
;
};
return
*
accessor
(
it
).
container
;
...
...
@@ -1069,21 +889,19 @@ inline Container &get_container(std::back_insert_iterator<Container> it)
}
// 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
:
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
;
};
template
<
typename
T
>
struct
formatter_type
{
typedef
formatter
<
T
,
char_type
>
type
;
};
private
:
private
:
internal
::
arg_map
<
basic_format_context
>
map_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
basic_format_context
);
...
...
@@ -1092,81 +910,71 @@ private:
typedef
typename
base
::
format_arg
format_arg
;
using
base
::
get_arg
;
public
:
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
)
{
}
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
()
{
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
);
}
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
;
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
;
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
>
FMT_CONSTEXPR
unsigned
long
long
get_types
()
{
return
0
;
}
template
<
typename
Context
,
typename
Arg
,
typename
...
Args
>
FMT_CONSTEXPR
uint64_t
get_types
()
{
template
<
typename
Context
,
typename
Arg
,
typename
...
Args
>
FMT_CONSTEXPR
unsigned
long
long
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
)
{
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
)
{
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
)
{
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
...
...
@@ -1175,51 +983,54 @@ inline typename std::enable_if<!IS_PACKED, basic_format_arg<Context>>::type make
such as `~fmt::vformat`.
\endrst
*/
template
<
typename
Context
,
typename
...
Args
>
class
format_arg_store
{
private
:
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
;
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
)];
static
const
size_t
DATA_SIZE
=
NUM_ARGS
+
(
IS_PACKED
&&
NUM_ARGS
!=
0
?
0
:
1
);
value_type
data_
[
DATA_SIZE
];
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
);
static
FMT_CONSTEXPR
long
long
get_types
()
{
return
IS_PACKED
?
static_cast
<
long
long
>
(
internal
::
get_types
<
Context
,
Args
...
>
())
:
-
static_cast
<
long
long
>
(
NUM_ARGS
);
}
public
:
public
:
#if FMT_USE_CONSTEXPR
static
constexpr
int64_t
TYPES
=
get_types
();
static
constexpr
long
long
TYPES
=
get_types
();
#else
static
const
int64_t
TYPES
;
static
const
long
long
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
)...};
#if (FMT_GCC_VERSION && FMT_GCC_VERSION <= 405) || \
(FMT_MSC_VER && FMT_MSC_VER <= 1800)
// Workaround array initialization issues in gcc <= 4.5 and MSVC <= 2013.
format_arg_store
(
const
Args
&
...
args
)
{
value_type
init
[
DATA_SIZE
]
=
{
internal
::
make_arg
<
IS_PACKED
,
Context
>
(
args
)...};
std
::
memcpy
(
data_
,
init
,
sizeof
(
init
));
}
#else
format_arg_store
(
const
Args
&
...
args
)
:
data_
{
internal
::
make_arg
<
IS_PACKED
,
Context
>
(
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
();
template
<
typename
Context
,
typename
...
Args
>
const
long
long
format_arg_store
<
Context
,
Args
...
>::
TYPES
=
get_types
();
#endif
/**
...
...
@@ -1229,32 +1040,30 @@ const int64_t format_arg_store<Context, Args...>::TYPES = get_types();
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
)
{
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
)
{
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
:
template
<
typename
Context
>
class
basic_format_args
{
public
:
typedef
unsigned
size_type
;
typedef
basic_format_arg
<
Context
>
format_arg
;
private
:
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
{
unsigned
long
long
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
...
...
@@ -1264,30 +1073,22 @@ private:
const
format_arg
*
args_
;
};
typename
internal
::
type
type
(
unsigned
index
)
const
{
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
);
unsigned
long
long
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
;
}
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
;
format_arg
do_get
(
size_type
index
)
const
{
long
long
signed_types
=
static_cast
<
long
long
>
(
types_
);
if
(
signed_types
<
0
)
{
unsigned
long
long
num_args
=
static_cast
<
unsigned
long
long
>
(
-
signed_types
);
return
index
<
num_args
?
args_
[
index
]
:
format_arg
();
}
format_arg
arg
;
...
...
@@ -1301,92 +1102,74 @@ private:
return
arg
;
}
public
:
basic_format_args
()
:
types_
(
0
)
{
}
public
:
basic_format_args
()
:
types_
(
0
)
{}
/**
\rst
Constructs a `basic_format_args` object from `~fmt::format_arg_store`.
\endrst
*/
template
<
typename
...
Args
>
template
<
typename
...
Args
>
basic_format_args
(
const
format_arg_store
<
Context
,
Args
...
>
&
store
)
:
types_
(
store
.
TYPES
)
{
:
types_
(
static_cast
<
unsigned
long
long
>
(
store
.
TYPES
))
{
set_data
(
store
.
data_
);
}
/** Returns the argument at specified index. */
format_arg
get
(
size_type
index
)
const
{
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
;
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
));
unsigned
max_size
()
const
{
long
long
signed_types
=
static_cast
<
long
long
>
(
types_
);
return
static_cast
<
unsigned
>
(
signed_types
<
0
?
-
signed_types
:
static_cast
<
long
long
>
(
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
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
)...)
{
}
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
{
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
)
{
}
named_arg_base
(
basic_string_view
<
Char
>
nm
)
:
name
(
nm
)
{}
template
<
typename
Context
>
basic_format_arg
<
Context
>
deserialize
()
const
{
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
>
{
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
)
{
}
:
named_arg_base
<
Char
>
(
name
),
value
(
val
)
{}
};
}
// namespace internal
}
/**
\rst
...
...
@@ -1397,90 +1180,70 @@ struct named_arg : named_arg_base<Char>
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
)
{
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
)
{
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
>
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
};
#ifndef FMT_EXTENDED_COLORS
// color and (v)print_colored are deprecated.
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
)
{
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
)
{
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
...));
}
#endif
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
);
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
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
<
std
::
basic_string
<
Char
>>
:
std
::
true_type
{};
template
<
typename
Char
>
struct
is_contiguous
<
internal
::
basic_buffer
<
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
);
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
);
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
);
...
...
@@ -1499,18 +1262,16 @@ std::wstring vformat(wstring_view format_str, wformat_args args);
std::string message = fmt::format("The answer is {}", 42);
\endrst
*/
template
<
typename
...
Args
>
inline
std
::
string
format
(
string_view
format_str
,
const
Args
&
...
args
)
{
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
)
{
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
);
}
...
...
@@ -1527,9 +1288,8 @@ FMT_API void vprint(std::FILE *f, wstring_view format_str, wformat_args args);
fmt::print(stderr, "Don't {}!", "panic");
\endrst
*/
template
<
typename
...
Args
>
inline
void
print
(
std
::
FILE
*
f
,
string_view
format_str
,
const
Args
&
...
args
)
{
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
);
}
...
...
@@ -1537,9 +1297,8 @@ inline void print(std::FILE *f, string_view format_str, const Args &... args)
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
)
{
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
);
}
...
...
@@ -1556,16 +1315,14 @@ FMT_API void vprint(wstring_view format_str, wformat_args args);
fmt::print("Elapsed time: {0:.2f} seconds", 1.23);
\endrst
*/
template
<
typename
...
Args
>
inline
void
print
(
string_view
format_str
,
const
Args
&
...
args
)
{
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
)
{
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
);
}
...
...
include/spdlog/fmt/bundled/format-inl.h
View file @
f4771be7
...
...
@@ -21,47 +21,45 @@
#include <locale>
#if defined(_WIN32) && defined(__MINGW32__)
#include <cstring>
#
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
#
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)
#
define FMT_TRY try
#
define FMT_CATCH(x) catch (x)
#else
#define FMT_TRY if (true)
#define FMT_CATCH(x) if (false)
#
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
#
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)
#
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
*
,
...)
{
inline
fmt
::
internal
::
null
<>
strerror_r
(
int
,
char
*
,
...)
{
return
fmt
::
internal
::
null
<>
();
}
inline
fmt
::
internal
::
null
<>
strerror_s
(
char
*
,
std
::
size_t
,
...)
{
inline
fmt
::
internal
::
null
<>
strerror_s
(
char
*
,
std
::
size_t
,
...)
{
return
fmt
::
internal
::
null
<>
();
}
...
...
@@ -70,28 +68,24 @@ FMT_BEGIN_NAMESPACE
namespace
{
#ifndef _MSC_VER
#define FMT_SNPRINTF snprintf
#
define FMT_SNPRINTF snprintf
#else // _MSC_VER
inline
int
fmt_snprintf
(
char
*
buffer
,
size_t
size
,
const
char
*
format
,
...)
{
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
#
define FMT_SNPRINTF fmt_snprintf
#endif // _MSC_VER
#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
#define FMT_SWPRINTF snwprintf
#
define FMT_SWPRINTF snwprintf
#else
#define FMT_SWPRINTF swprintf
#
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.
...
...
@@ -103,12 +97,11 @@ typedef void (*FormatFunc)(internal::buffer &, int, string_view);
// 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
{
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
{
class
dispatcher
{
private
:
int
error_code_
;
char
*&
buffer_
;
...
...
@@ -118,15 +111,13 @@ int safe_strerror(int error_code, char *&buffer, std::size_t buffer_size) FMT_NO
void
operator
=
(
const
dispatcher
&
)
{}
// Handle the result of XSI-compliant version of strerror_r.
int
handle
(
int
result
)
{
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
)
{
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
;
...
...
@@ -135,21 +126,19 @@ int safe_strerror(int error_code, char *&buffer, std::size_t buffer_size) FMT_NO
}
// Handle the case when strerror_r is not available.
int
handle
(
internal
::
null
<>
)
{
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
)
{
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
;
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
<>
)
{
int
fallback
(
internal
::
null
<>
)
{
errno
=
0
;
buffer_
=
strerror
(
error_code_
);
return
errno
;
...
...
@@ -157,22 +146,17 @@ int safe_strerror(int error_code, char *&buffer, std::size_t buffer_size) FMT_NO
public
:
dispatcher
(
int
err_code
,
char
*&
buf
,
std
::
size_t
buf_size
)
:
error_code_
(
err_code
)
,
buffer_
(
buf
)
,
buffer_size_
(
buf_size
)
{
}
:
error_code_
(
err_code
),
buffer_
(
buf
),
buffer_size_
(
buf_size
)
{}
int
run
()
{
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
{
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.
...
...
@@ -183,15 +167,13 @@ void format_error_code(internal::buffer &out, int error_code, string_view messag
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
))
{
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
)
{
if
(
message
.
size
()
<=
inline_buffer_size
-
error_code_size
)
{
w
.
write
(
message
);
w
.
write
(
SEP
);
}
...
...
@@ -200,8 +182,8 @@ void format_error_code(internal::buffer &out, int error_code, string_view messag
assert
(
out
.
size
()
<=
inline_buffer_size
);
}
void
report_error
(
FormatFunc
func
,
int
error_code
,
string_view
message
)
FMT_NOEXCEPT
{
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
...
...
@@ -211,31 +193,23 @@ void report_error(FormatFunc func, int error_code, string_view message) FMT_NOEX
}
}
// namespace
class
locale
{
private
:
class
locale
{
private
:
std
::
locale
locale_
;
public
:
explicit
locale
(
std
::
locale
loc
=
std
::
locale
())
:
locale_
(
loc
)
{
}
std
::
locale
get
()
{
return
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
)
{
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
)
{
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
));
...
...
@@ -244,64 +218,101 @@ FMT_FUNC void system_error::init(int err_code, string_view format_str, format_ar
}
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
<
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
>
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"
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 * 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
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
};
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
};
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
)
{
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
};
template
<
typename
T
>
const
char
basic_data
<
T
>::
RESET_COLOR
[]
=
"
\x1b
[0m"
;
template
<
typename
T
>
const
wchar_t
basic_data
<
T
>::
WRESET_COLOR
[]
=
L"
\x1b
[0m"
;
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
;
...
...
@@ -312,10 +323,10 @@ FMT_FUNC fp operator*(fp x, fp y)
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
)
{
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
));
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.
...
...
@@ -328,64 +339,63 @@ FMT_FUNC fp get_cached_power(int min_exponent, int &pow10_exponent)
#if FMT_USE_WINDOWS_H
FMT_FUNC
internal
::
utf8_to_utf16
::
utf8_to_utf16
(
string_view
s
)
{
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
)
{
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
);
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
);
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
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
)
{
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
)
{
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
);
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
);
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
)
{
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
));
...
...
@@ -393,22 +403,20 @@ FMT_FUNC void windows_error::init(int err_code, string_view format_str, format_a
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
{
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
(;;)
{
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
)
{
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
)
{
if
(
utf8_message
.
convert
(
system_message
)
==
ERROR_SUCCESS
)
{
writer
w
(
out
);
w
.
write
(
message
);
w
.
write
(
": "
);
...
...
@@ -421,25 +429,21 @@ FMT_FUNC void internal::format_windows_error(internal::buffer &out, int error_co
break
;
// Can't get error message, report error code instead.
buf
.
resize
(
buf
.
size
()
*
2
);
}
}
FMT_CATCH
(...)
{}
}
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
{
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
(;;)
{
for
(;;)
{
char
*
system_message
=
&
buf
[
0
];
int
result
=
safe_strerror
(
error_code
,
system_message
,
buf
.
size
());
if
(
result
==
0
)
{
if
(
result
==
0
)
{
writer
w
(
out
);
w
.
write
(
message
);
w
.
write
(
": "
);
...
...
@@ -450,85 +454,111 @@ FMT_FUNC void format_system_error(internal::buffer &out, int error_code, string_
break
;
// Can't get error message, report error code instead.
buf
.
resize
(
buf
.
size
()
*
2
);
}
}
FMT_CATCH
(...)
{}
}
FMT_CATCH
(...)
{}
format_error_code
(
out
,
error_code
,
message
);
}
template
<
typename
Char
>
void
basic_fixed_buffer
<
Char
>::
grow
(
std
::
size_t
)
{
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_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
{
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
{
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
)
{
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
)
{
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
)
{
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
)
{
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
)
{
#ifndef FMT_EXTENDED_COLORS
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
);
std
::
fputs
(
internal
::
data
::
RESET_COLOR
,
stdout
);
}
FMT_FUNC
void
vprint_colored
(
color
c
,
wstring_view
format
,
wformat_args
args
)
{
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
);
std
::
fputws
(
internal
::
data
::
WRESET_COLOR
,
stdout
);
}
#else
namespace
internal
{
FMT_CONSTEXPR
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
locale
locale_provider
::
locale
()
{
return
fmt
::
locale
();
FMT_FUNC
void
vprint_rgb
(
rgb
fd
,
string_view
format
,
format_args
args
)
{
char
escape_fd
[]
=
"
\x1b
[38;2;000;000;000m"
;
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
(
internal
::
data
::
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
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
(
internal
::
data
::
RESET_COLOR
,
stdout
);
}
#endif
FMT_FUNC
locale
locale_provider
::
locale
()
{
return
fmt
::
locale
();
}
FMT_END_NAMESPACE
#ifdef _MSC_VER
#pragma warning(pop)
#
pragma warning(pop)
#endif
#endif // FMT_FORMAT_INL_H_
include/spdlog/fmt/bundled/format.cc
deleted
100644 → 0
View file @
887326e7
// 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
View file @
f4771be7
This source diff could not be displayed because it is too large. You can
view the blob
instead.
include/spdlog/fmt/bundled/ostream.h
View file @
f4771be7
...
...
@@ -14,22 +14,18 @@
FMT_BEGIN_NAMESPACE
namespace
internal
{
template
<
class
Char
>
class
formatbuf
:
public
std
::
basic_streambuf
<
Char
>
{
private
:
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
)
{
}
public
:
formatbuf
(
basic_buffer
<
Char
>
&
buffer
)
:
buffer_
(
buffer
)
{}
protected
:
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
...
...
@@ -37,43 +33,41 @@ protected:
// 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
{
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
{
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
:
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
>
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
:
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
;
...
...
@@ -81,23 +75,22 @@ public:
// 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
;
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
)
{
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
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
;
...
...
@@ -105,9 +98,8 @@ void write(std::basic_ostream<Char> &os, basic_buffer<Char> &buf)
}
while
(
size
!=
0
);
}
template
<
typename
Char
,
typename
T
>
void
format_value
(
basic_buffer
<
Char
>
&
buffer
,
const
T
&
value
)
{
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
);
...
...
@@ -116,20 +108,19 @@ void format_value(basic_buffer<Char> &buffer, const T &value)
}
// 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
{
};
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
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
())
{
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
());
...
...
@@ -138,10 +129,10 @@ struct formatter<T, Char, typename std::enable_if<internal::is_streamable<T, Cha
}
};
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
)
{
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
);
...
...
@@ -155,15 +146,15 @@ inline void vprint(
fmt::print(cerr, "Don't {}!", "panic");
\endrst
*/
template
<
typename
...
Args
>
inline
void
print
(
std
::
ostream
&
os
,
string_view
format_str
,
const
Args
&
...
args
)
{
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
)
{
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
...
...
include/spdlog/fmt/bundled/posix.h
View file @
f4771be7
...
...
@@ -10,7 +10,7 @@
#if defined(__MINGW32__) || defined(__CYGWIN__)
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
#undef __STRICT_ANSI__
#
undef __STRICT_ANSI__
#endif
#include <errno.h>
...
...
@@ -22,43 +22,42 @@
#include <cstddef>
#if defined __APPLE__ || defined(__FreeBSD__)
#
include <xlocale.h>
// for LC_NUMERIC_MASK on OS X
#
include <xlocale.h>
// for LC_NUMERIC_MASK on OS X
#endif
#include "format.h"
#ifndef FMT_POSIX
#if defined(_WIN32) && !defined(__MINGW32__)
#
if defined(_WIN32) && !defined(__MINGW32__)
// Fix warnings about deprecated symbols.
#define FMT_POSIX(call) _##call
#else
#define FMT_POSIX(call) call
#endif
#
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)
#
define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
#else
#define FMT_SYSTEM(call) call
#ifdef _WIN32
#
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
#
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 \
{ \
# 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)
#
define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#endif
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
...
...
@@ -90,68 +89,50 @@ FMT_BEGIN_NAMESPACE
format(std::string("{}"), 42);
\endrst
*/
template
<
typename
Char
>
class
basic_cstring_view
{
private
:
template
<
typename
Char
>
class
basic_cstring_view
{
private
:
const
Char
*
data_
;
public
:
public
:
/** Constructs a string reference object from a C string. */
basic_cstring_view
(
const
Char
*
s
)
:
data_
(
s
)
{
}
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
())
{
}
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_
;
}
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
:
class
error_code
{
private
:
int
value_
;
public
:
public
:
explicit
error_code
(
int
value
=
0
)
FMT_NOEXCEPT
:
value_
(
value
)
{}
int
get
()
const
FMT_NOEXCEPT
{
return
value_
;
}
int
get
()
const
FMT_NOEXCEPT
{
return
value_
;
}
};
// A buffered file.
class
buffered_file
{
private
:
class
buffered_file
{
private
:
FILE
*
file_
;
friend
class
file
;
explicit
buffered_file
(
FILE
*
f
)
:
file_
(
f
)
{
}
explicit
buffered_file
(
FILE
*
f
)
:
file_
(
f
)
{}
public
:
public
:
// Constructs a buffered_file object which doesn't represent any file.
buffered_file
()
FMT_NOEXCEPT
:
file_
(
FMT_NULL
)
{}
...
...
@@ -162,11 +143,10 @@ public:
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
private
:
private
:
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
struct
Proxy
{
struct
Proxy
{
FILE
*
file
;
};
...
...
@@ -175,22 +155,19 @@ public:
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_
)
{
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
)
{
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
)
{
buffered_file
&
operator
=
(
buffered_file
&
other
)
{
close
();
file_
=
other
.
file_
;
other
.
file_
=
FMT_NULL
;
...
...
@@ -199,25 +176,22 @@ public:
// Returns a proxy object for moving from a temporary:
// buffered_file file = buffered_file(...);
operator
Proxy
()
FMT_NOEXCEPT
{
operator
Proxy
()
FMT_NOEXCEPT
{
Proxy
p
=
{
file_
};
file_
=
FMT_NULL
;
return
p
;
}
#else
private
:
private
:
FMT_DISALLOW_COPY_AND_ASSIGN
(
buffered_file
);
public
:
buffered_file
(
buffered_file
&&
other
)
FMT_NOEXCEPT
:
file_
(
other
.
file_
)
{
public
:
buffered_file
(
buffered_file
&&
other
)
FMT_NOEXCEPT
:
file_
(
other
.
file_
)
{
other
.
file_
=
FMT_NULL
;
}
buffered_file
&
operator
=
(
buffered_file
&&
other
)
{
buffered_file
&
operator
=
(
buffered_file
&&
other
)
{
close
();
file_
=
other
.
file_
;
other
.
file_
=
FMT_NULL
;
...
...
@@ -232,23 +206,18 @@ public:
FMT_API
void
close
();
// Returns the pointer to a FILE object representing this file.
FILE
*
get
()
const
FMT_NOEXCEPT
{
return
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
;
FMT_API
int
(
fileno
)()
const
;
void
vprint
(
string_view
format_str
,
format_args
args
)
{
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
)
{
template
<
typename
...
Args
>
inline
void
print
(
string_view
format_str
,
const
Args
&
...
args
)
{
vprint
(
format_str
,
make_format_args
(
args
...));
}
};
...
...
@@ -259,21 +228,16 @@ public:
// 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
:
class
file
{
private
:
int
fd_
;
// File descriptor.
// Constructs a file object with a given descriptor.
explicit
file
(
int
fd
)
:
fd_
(
fd
)
{
}
explicit
file
(
int
fd
)
:
fd_
(
fd
)
{}
public
:
public
:
// Possible values for the oflag argument to the constructor.
enum
{
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.
...
...
@@ -289,35 +253,31 @@ public:
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
private
:
private
:
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
struct
Proxy
{
struct
Proxy
{
int
fd
;
};
public
:
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_
)
{
file
(
file
&
other
)
FMT_NOEXCEPT
:
fd_
(
other
.
fd_
)
{
other
.
fd_
=
-
1
;
}
// A "move assignment operator" for moving from a temporary.
file
&
operator
=
(
Proxy
p
)
{
file
&
operator
=
(
Proxy
p
)
{
close
();
fd_
=
p
.
fd
;
return
*
this
;
}
// A "move assignment operator" for moving from an lvalue.
file
&
operator
=
(
file
&
other
)
{
file
&
operator
=
(
file
&
other
)
{
close
();
fd_
=
other
.
fd_
;
other
.
fd_
=
-
1
;
...
...
@@ -326,25 +286,22 @@ public:
// Returns a proxy object for moving from a temporary:
// file f = file(...);
operator
Proxy
()
FMT_NOEXCEPT
{
operator
Proxy
()
FMT_NOEXCEPT
{
Proxy
p
=
{
fd_
};
fd_
=
-
1
;
return
p
;
}
#else
private
:
private
:
FMT_DISALLOW_COPY_AND_ASSIGN
(
file
);
public
:
file
(
file
&&
other
)
FMT_NOEXCEPT
:
fd_
(
other
.
fd_
)
{
public
:
file
(
file
&&
other
)
FMT_NOEXCEPT
:
fd_
(
other
.
fd_
)
{
other
.
fd_
=
-
1
;
}
file
&
operator
=
(
file
&&
other
)
{
file
&
operator
=
(
file
&&
other
)
{
close
();
fd_
=
other
.
fd_
;
other
.
fd_
=
-
1
;
...
...
@@ -356,10 +313,7 @@ public:
FMT_API
~
file
()
FMT_DTOR_NOEXCEPT
;
// Returns the file descriptor.
int
descriptor
()
const
FMT_NOEXCEPT
{
return
fd_
;
}
int
descriptor
()
const
FMT_NOEXCEPT
{
return
fd_
;
}
// Closes the file.
FMT_API
void
close
();
...
...
@@ -398,66 +352,51 @@ public:
// Returns the memory page size.
long
getpagesize
();
#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && !defined(__ANDROID__) && !defined(__CYGWIN__) && !defined(__OpenBSD__)
#define FMT_LOCALE
#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
class
Locale
{
private
:
# ifdef _MSC_VER
typedef
_locale_t
locale_t
;
enum
{
LC_NUMERIC_MASK
=
LC_NUMERIC
};
enum
{
LC_NUMERIC_MASK
=
LC_NUMERIC
};
static
locale_t
newlocale
(
int
category_mask
,
const
char
*
locale
,
locale_t
)
{
static
locale_t
newlocale
(
int
category_mask
,
const
char
*
locale
,
locale_t
)
{
return
_create_locale
(
category_mask
,
locale
);
}
static
void
freelocale
(
locale_t
locale
)
{
static
void
freelocale
(
locale_t
locale
)
{
_free_locale
(
locale
);
}
static
double
strtod_l
(
const
char
*
nptr
,
char
**
endptr
,
_locale_t
locale
)
{
static
double
strtod_l
(
const
char
*
nptr
,
char
**
endptr
,
_locale_t
locale
)
{
return
_strtod_l
(
nptr
,
endptr
,
locale
);
}
#endif
#
endif
locale_t
locale_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
Locale
);
public
:
public
:
typedef
locale_t
Type
;
Locale
()
:
locale_
(
newlocale
(
LC_NUMERIC_MASK
,
"C"
,
FMT_NULL
))
{
Locale
()
:
locale_
(
newlocale
(
LC_NUMERIC_MASK
,
"C"
,
FMT_NULL
))
{
if
(
!
locale_
)
FMT_THROW
(
system_error
(
errno
,
"cannot create locale"
));
}
~
Locale
()
{
freelocale
(
locale_
);
}
~
Locale
()
{
freelocale
(
locale_
);
}
Type
get
()
const
{
return
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
{
double
strtod
(
const
char
*&
str
)
const
{
char
*
end
=
FMT_NULL
;
double
result
=
strtod_l
(
str
,
&
end
,
locale_
);
str
=
end
;
...
...
@@ -470,15 +409,9 @@ 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
;
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
View file @
f4771be7
...
...
@@ -18,141 +18,111 @@ 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
)
{
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
;
}
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
;
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
)
{
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
)
{
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
;
}
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
<
typename
T
>
struct
make_unsigned_or_bool
:
std
::
make_unsigned
<
T
>
{};
template
<>
struct
make_unsigned_or_bool
<
bool
>
{
template
<>
struct
make_unsigned_or_bool
<
bool
>
{
typedef
bool
type
;
};
template
<
typename
T
,
typename
Context
>
class
arg_converter
:
public
function
<
void
>
{
private
:
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
:
public
:
arg_converter
(
basic_format_arg
<
Context
>
&
arg
,
Char
type
)
:
arg_
(
arg
)
,
type_
(
type
)
{
}
:
arg_
(
arg
),
type_
(
type
)
{}
void
operator
()(
bool
value
)
{
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
)
{
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
)))
{
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
{
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
)));
arg_
=
internal
::
make_arg
<
Context
>
(
static_cast
<
unsigned
>
(
static_cast
<
Unsigned
>
(
value
)));
}
}
else
{
if
(
is_signed
)
{
}
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
));
}
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
)
{
template
<
typename
U
>
typename
std
::
enable_if
<!
std
::
is_integral
<
U
>::
value
>::
type
operator
()(
U
)
{
// No coversion needed for non-integral types.
}
};
...
...
@@ -161,66 +131,55 @@ public:
// 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
)
{
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
:
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
)
{
}
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
)
{
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
)
{
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
:
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
)
{
}
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
)
{
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
))
{
if
(
internal
::
is_negative
(
value
))
{
spec_
.
align_
=
ALIGN_LEFT
;
width
=
0
-
width
;
}
...
...
@@ -230,19 +189,22 @@ public:
return
static_cast
<
unsigned
>
(
width
);
}
template
<
typename
T
>
typename
std
::
enable_if
<!
std
::
is_integral
<
T
>::
value
,
unsigned
>::
type
operator
()(
T
)
{
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
>
template
<
typename
Range
>
class
printf_arg_formatter
;
template
<
typename
OutputIt
,
typename
Char
,
typename
ArgFormatter
=
printf_arg_formatter
<
back_insert_range
<
internal
::
basic_buffer
<
Char
>>>>
template
<
typename
OutputIt
,
typename
Char
,
typename
ArgFormatter
=
printf_arg_formatter
<
back_insert_range
<
internal
::
basic_buffer
<
Char
>>>>
class
basic_printf_context
;
/**
...
...
@@ -250,11 +212,12 @@ class basic_printf_context;
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
:
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
;
...
...
@@ -262,19 +225,17 @@ private:
context_type
&
context_
;
void
write_null_pointer
(
char
)
{
void
write_null_pointer
(
char
)
{
this
->
spec
().
type_
=
0
;
this
->
write
(
"(nil)"
);
}
void
write_null_pointer
(
wchar_t
)
{
void
write_null_pointer
(
wchar_t
)
{
this
->
spec
().
type_
=
0
;
this
->
write
(
L"(nil)"
);
}
public
:
public
:
typedef
typename
base
::
format_specs
format_specs
;
/**
...
...
@@ -284,39 +245,43 @@ public:
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
)
{
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
)
{}
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
iterator
>::
type
operator
()(
T
value
)
{
/
/ MSVC2013 fails to compile separate overloads for bool and char_type so
// use std::is_same instead.
if
(
std
::
is_same
<
T
,
bool
>::
value
)
{
format_specs
&
fmt_spec
=
this
->
spec
();
if
(
fmt_spec
.
type_
!=
's'
)
return
(
*
this
)(
value
?
1
:
0
);
return
base
::
operator
(
)(
value
?
1
:
0
);
fmt_spec
.
type_
=
0
;
this
->
write
(
value
);
return
this
->
out
();
}
/** Formats a character. */
iterator
operator
()(
char_type
value
)
{
this
->
write
(
value
!=
0
);
}
else
if
(
std
::
is_same
<
T
,
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
);
}
else
{
return
base
::
operator
()(
value
);
}
return
this
->
out
();
}
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_floating_point
<
T
>::
value
,
iterator
>::
type
operator
()(
T
value
)
{
return
base
::
operator
()(
value
);
}
/** Formats a null-terminated C string. */
iterator
operator
()(
const
char
*
value
)
{
iterator
operator
()(
const
char
*
value
)
{
if
(
value
)
base
::
operator
()(
value
);
else
if
(
this
->
spec
().
type_
==
'p'
)
...
...
@@ -327,8 +292,7 @@ public:
}
/** Formats a null-terminated wide C string. */
iterator
operator
()(
const
wchar_t
*
value
)
{
iterator
operator
()(
const
wchar_t
*
value
)
{
if
(
value
)
base
::
operator
()(
value
);
else
if
(
this
->
spec
().
type_
==
'p'
)
...
...
@@ -338,9 +302,16 @@ public:
return
this
->
out
();
}
iterator
operator
()(
basic_string_view
<
char_type
>
value
)
{
return
base
::
operator
()(
value
);
}
iterator
operator
()(
monostate
value
)
{
return
base
::
operator
()(
value
);
}
/** Formats a pointer. */
iterator
operator
()(
const
void
*
value
)
{
iterator
operator
()(
const
void
*
value
)
{
if
(
value
)
return
base
::
operator
()(
value
);
this
->
spec
().
type_
=
0
;
...
...
@@ -349,45 +320,37 @@ public:
}
/** Formats an argument of a custom (user-defined) type. */
iterator
operator
()(
typename
basic_format_arg
<
context_type
>::
handle
handle
)
{
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
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
())
{
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
:
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
;
};
template
<
typename
T
>
struct
formatter_type
{
typedef
printf_formatter
<
T
>
type
;
};
private
:
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
;
...
...
@@ -397,12 +360,14 @@ private:
// 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
)());
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
:
public
:
/**
\rst
Constructs a ``printf_context`` object. References to the arguments and
...
...
@@ -410,26 +375,23 @@ public:
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
)
{
}
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
;
using
base
::
out
;
using
base
::
advance_to
;
/** 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
++
)
{
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
;
...
...
@@ -452,38 +414,33 @@ void basic_printf_context<OutputIt, Char, AF>::parse_flags(format_specs &spec, i
}
}
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
)
{
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
)
{
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'
)
{
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
if
(
*
it
==
'$'
)
{
// value is an argument index
++
it
;
arg_index
=
value
;
}
else
{
}
else
{
if
(
c
==
'0'
)
spec
.
fill_
=
'0'
;
if
(
value
!=
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
;
...
...
@@ -493,33 +450,27 @@ unsigned basic_printf_context<OutputIt, Char, AF>::parse_header(iterator &it, fo
}
parse_flags
(
spec
,
it
);
// Parse width.
if
(
*
it
>=
'0'
&&
*
it
<=
'9'
)
{
if
(
*
it
>=
'0'
&&
*
it
<=
'9'
)
{
internal
::
error_handler
eh
;
spec
.
width_
=
parse_nonnegative_int
(
it
,
eh
);
}
else
if
(
*
it
==
'*'
)
{
}
else
if
(
*
it
==
'*'
)
{
++
it
;
spec
.
width_
=
visit
(
internal
::
printf_width_handler
<
char_type
>
(
spec
),
get_arg
(
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
()
{
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
)
{
while
(
*
it
)
{
char_type
c
=
*
it
++
;
if
(
c
!=
'%'
)
continue
;
if
(
*
it
==
c
)
{
if
(
c
!=
'%'
)
continue
;
if
(
*
it
==
c
)
{
buffer
.
append
(
pointer_from
(
start
),
pointer_from
(
it
));
start
=
++
it
;
continue
;
...
...
@@ -533,21 +484,16 @@ void basic_printf_context<OutputIt, Char, AF>::format()
unsigned
arg_index
=
parse_header
(
it
,
spec
);
// Parse precision.
if
(
*
it
==
'.'
)
{
if
(
*
it
==
'.'
)
{
++
it
;
if
(
'0'
<=
*
it
&&
*
it
<=
'9'
)
{
if
(
'0'
<=
*
it
&&
*
it
<=
'9'
)
{
internal
::
error_handler
eh
;
spec
.
precision_
=
static_cast
<
int
>
(
parse_nonnegative_int
(
it
,
eh
));
}
else
if
(
*
it
==
'*'
)
{
}
else
if
(
*
it
==
'*'
)
{
++
it
;
spec
.
precision_
=
visit
(
internal
::
printf_precision_handler
(),
get_arg
(
it
));
}
else
{
spec
.
precision_
=
visit
(
internal
::
printf_precision_handler
(),
get_arg
(
it
));
}
else
{
spec
.
precision_
=
0
;
}
}
...
...
@@ -555,8 +501,7 @@ void basic_printf_context<OutputIt, Char, AF>::format()
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
(
spec
.
fill_
==
'0'
)
{
if
(
arg
.
is_arithmetic
())
spec
.
align_
=
ALIGN_NUMERIC
;
else
...
...
@@ -565,8 +510,7 @@ void basic_printf_context<OutputIt, Char, AF>::format()
// Parse length and convert the argument to the required type.
using
internal
::
convert_arg
;
switch
(
*
it
++
)
{
switch
(
*
it
++
)
{
case
'h'
:
if
(
*
it
==
'h'
)
convert_arg
<
signed
char
>
(
arg
,
*++
it
);
...
...
@@ -601,13 +545,10 @@ void basic_printf_context<OutputIt, Char, AF>::format()
if
(
!*
it
)
FMT_THROW
(
format_error
(
"invalid format string"
));
spec
.
type_
=
static_cast
<
char
>
(
*
it
++
);
if
(
arg
.
is_integral
())
{
if
(
arg
.
is_integral
())
{
// Normalize type.
switch
(
spec
.
type_
)
{
case
'i'
:
case
'u'
:
switch
(
spec
.
type_
)
{
case
'i'
:
case
'u'
:
spec
.
type_
=
'd'
;
break
;
case
'c'
:
...
...
@@ -625,28 +566,28 @@ void basic_printf_context<OutputIt, Char, AF>::format()
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
)
{
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
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
...);
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
)
{
inline
std
::
string
vsprintf
(
string_view
format
,
printf_args
args
)
{
memory_buffer
buffer
;
printf
(
buffer
,
format
,
args
);
return
to_string
(
buffer
);
...
...
@@ -661,33 +602,33 @@ inline std::string vsprintf(string_view format, printf_args args)
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
...));
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
)
{
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
...
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
)
{
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
);
return
std
::
fwrite
(
buffer
.
data
(),
sizeof
(
Char
),
size
,
f
)
<
size
?
-
1
:
static_cast
<
int
>
(
size
);
}
/**
...
...
@@ -699,26 +640,25 @@ inline int vfprintf(
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
...);
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
...));
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
)
{
inline
int
vprintf
(
string_view
format
,
printf_args
args
)
{
return
vfprintf
(
stdout
,
format
,
args
);
}
inline
int
vprintf
(
wstring_view
format
,
wprintf_args
args
)
{
inline
int
vprintf
(
wstring_view
format
,
wprintf_args
args
)
{
return
vfprintf
(
stdout
,
format
,
args
);
}
...
...
@@ -731,28 +671,28 @@ inline int vprintf(wstring_view format, wprintf_args args)
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
(
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
...));
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
)
{
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
)
{
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
);
...
...
@@ -768,17 +708,19 @@ inline int vfprintf(std::wostream &os, wstring_view format_str, wprintf_args arg
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
...);
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
...);
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
...
...
include/spdlog/fmt/bundled/ranges.h
View file @
f4771be7
...
...
@@ -17,268 +17,233 @@
// output only up to N items from the range.
#ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT
#define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256
#
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
())
{
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
>
{
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
(
'}'
)
{
}
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
>
{
template
<
typename
Char
,
typename
Enable
=
void
>
struct
formatting_tuple
:
formatting_base
<
Char
>
{
Char
prefix
;
Char
delimiter
;
Char
postfix
;
formatting_tuple
()
:
prefix
(
'('
)
,
delimiter
(
','
)
,
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
)
{
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
)
{
template
<
typename
OutputIterator
>
void
copy
(
const
char
*
str
,
OutputIterator
out
)
{
const
char
*
p_curr
=
str
;
while
(
*
p_curr
)
{
while
(
*
p_curr
)
{
*
out
++
=
*
p_curr
++
;
}
}
template
<
typename
OutputIterator
>
void
copy
(
char
ch
,
OutputIterator
out
)
{
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
>
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
;
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
...
Ts
>
struct
conditional_helper
{};
template
<
typename
T
,
typename
_
=
void
>
struct
is_range_
:
std
::
false_type
{
};
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
{
};
#if !FMT_MSC_VER || FMT_MSC_VER > 1800
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
{};
#endif
/// 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
>
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
;
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
>
template
<
typename
T
,
T
...
N
>
using
integer_sequence
=
std
::
integer_sequence
<
T
,
N
...
>
;
template
<
std
::
size_t
...
N
>
template
<
std
::
size_t
...
N
>
using
index_sequence
=
std
::
index_sequence
<
N
...
>
;
template
<
std
::
size_t
N
>
template
<
std
::
size_t
N
>
using
make_index_sequence
=
std
::
make_index_sequence
<
N
>
;
#else
template
<
typename
T
,
T
...
N
>
struct
integer_sequence
{
template
<
typename
T
,
T
...
N
>
struct
integer_sequence
{
typedef
T
value_type
;
static
FMT_CONSTEXPR
std
::
size_t
size
()
{
static
FMT_CONSTEXPR
std
::
size_t
size
()
{
return
sizeof
...(
N
);
}
};
template
<
std
::
size_t
...
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
<
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
>
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
{
template
<
class
Tuple
,
class
F
,
size_t
...
Is
>
void
for_each
(
index_sequence
<
Is
...
>
,
Tuple
&&
tup
,
F
&&
f
)
FMT_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
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
)
{
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
)
{
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
)
{
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
*
)
{
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
*
)
{
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
)
{
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
)
{
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
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
>
{
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
)
{
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
);
format_to
(
out
,
internal
::
format_str_quoted
(
(
formatting
.
add_delimiter_spaces
&&
i
>
0
),
v
),
v
);
++
i
;
}
formatting_tuple
<
Char
>
&
formatting
;
std
::
size_t
&
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
())
{
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
())
{
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
)
{
if
(
formatting
.
add_prepostfix_space
)
{
*
out
++
=
' '
;
}
internal
::
copy
(
formatting
.
postfix
,
out
);
...
...
@@ -287,49 +252,46 @@ public:
}
};
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
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
>
{
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
())
{
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
)
{
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
)
{
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
,
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
)
{
if
(
formatting
.
add_prepostfix_space
)
{
*
out
++
=
' '
;
}
internal
::
copy
(
formatting
.
postfix
,
out
);
...
...
@@ -340,3 +302,4 @@ struct formatter<RangeT, Char, typename std::enable_if<fmt::is_range<RangeT>::va
FMT_END_NAMESPACE
#endif // FMT_RANGES_H_
include/spdlog/fmt/bundled/time.h
View file @
f4771be7
...
...
@@ -13,66 +13,39 @@
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
{
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
{
inline
std
::
tm
localtime
(
std
::
time_t
time
)
{
struct
dispatcher
{
std
::
time_t
time_
;
std
::
tm
tm_
;
dispatcher
(
std
::
time_t
t
)
:
time_
(
t
)
{
}
dispatcher
(
std
::
time_t
t
)
:
time_
(
t
)
{}
bool
run
()
{
bool
run
()
{
using
namespace
fmt
::
internal
;
return
handle
(
localtime_r
(
&
time_
,
&
tm_
));
}
bool
handle
(
std
::
tm
*
tm
)
{
return
tm
!=
FMT_NULL
;
}
bool
handle
(
std
::
tm
*
tm
)
{
return
tm
!=
FMT_NULL
;
}
bool
handle
(
internal
::
null
<>
)
{
bool
handle
(
internal
::
null
<>
)
{
using
namespace
fmt
::
internal
;
return
fallback
(
localtime_s
(
&
tm_
,
&
time_
));
}
bool
fallback
(
int
res
)
{
return
res
==
0
;
}
bool
fallback
(
int
res
)
{
return
res
==
0
;
}
bool
fallback
(
internal
::
null
<>
)
{
bool
fallback
(
internal
::
null
<>
)
{
using
namespace
fmt
::
internal
;
std
::
tm
*
tm
=
std
::
localtime
(
&
time_
);
if
(
tm
)
tm_
=
*
tm
;
if
(
tm
)
tm_
=
*
tm
;
return
tm
!=
FMT_NULL
;
}
};
...
...
@@ -84,45 +57,30 @@ inline std::tm localtime(std::time_t time)
}
// Thread-safe replacement for std::gmtime
inline
std
::
tm
gmtime
(
std
::
time_t
time
)
{
struct
dispatcher
{
inline
std
::
tm
gmtime
(
std
::
time_t
time
)
{
struct
dispatcher
{
std
::
time_t
time_
;
std
::
tm
tm_
;
dispatcher
(
std
::
time_t
t
)
:
time_
(
t
)
{
}
dispatcher
(
std
::
time_t
t
)
:
time_
(
t
)
{}
bool
run
()
{
bool
run
()
{
using
namespace
fmt
::
internal
;
return
handle
(
gmtime_r
(
&
time_
,
&
tm_
));
}
bool
handle
(
std
::
tm
*
tm
)
{
return
tm
!=
FMT_NULL
;
}
bool
handle
(
std
::
tm
*
tm
)
{
return
tm
!=
FMT_NULL
;
}
bool
handle
(
internal
::
null
<>
)
{
bool
handle
(
internal
::
null
<>
)
{
using
namespace
fmt
::
internal
;
return
fallback
(
gmtime_s
(
&
tm_
,
&
time_
));
}
bool
fallback
(
int
res
)
{
return
res
==
0
;
}
bool
fallback
(
int
res
)
{
return
res
==
0
;
}
bool
fallback
(
internal
::
null
<>
)
{
bool
fallback
(
internal
::
null
<>
)
{
std
::
tm
*
tm
=
std
::
gmtime
(
&
time_
);
if
(
tm
)
tm_
=
*
tm
;
if
(
tm
)
tm_
=
*
tm
;
return
tm
!=
FMT_NULL
;
}
};
...
...
@@ -134,23 +92,21 @@ inline std::tm gmtime(std::time_t time)
}
namespace
internal
{
inline
std
::
size_t
strftime
(
char
*
str
,
std
::
size_t
count
,
const
char
*
format
,
const
std
::
tm
*
time
)
{
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
)
{
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
())
{
}
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
;
...
...
@@ -164,22 +120,19 @@ struct formatter<std::tm, Char>
return
pointer_from
(
end
);
}
template
<
typename
FormatContext
>
auto
format
(
const
std
::
tm
&
tm
,
FormatContext
&
ctx
)
->
decltype
(
ctx
.
out
())
{
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
(;;)
{
for
(;;)
{
std
::
size_t
size
=
buf
.
capacity
()
-
start
;
std
::
size_t
count
=
internal
::
strftime
(
&
buf
[
start
],
size
,
&
tm_format
[
0
],
&
tm
);
if
(
count
!=
0
)
{
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
(
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:
...
...
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