Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
spdlog
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
spdlog
Commits
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
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
5773 additions
and
6827 deletions
+5773
-6827
include/spdlog/fmt/bundled/core.h
include/spdlog/fmt/bundled/core.h
+899
-1142
include/spdlog/fmt/bundled/format-inl.h
include/spdlog/fmt/bundled/format-inl.h
+419
-389
include/spdlog/fmt/bundled/format.cc
include/spdlog/fmt/bundled/format.cc
+0
-46
include/spdlog/fmt/bundled/format.h
include/spdlog/fmt/bundled/format.h
+3171
-3748
include/spdlog/fmt/bundled/ostream.h
include/spdlog/fmt/bundled/ostream.h
+110
-119
include/spdlog/fmt/bundled/posix.h
include/spdlog/fmt/bundled/posix.h
+270
-337
include/spdlog/fmt/bundled/printf.h
include/spdlog/fmt/bundled/printf.h
+581
-639
include/spdlog/fmt/bundled/ranges.h
include/spdlog/fmt/bundled/ranges.h
+204
-241
include/spdlog/fmt/bundled/time.h
include/spdlog/fmt/bundled/time.h
+119
-166
No files found.
include/spdlog/fmt/bundled/core.h
View file @
f4771be7
...
@@ -19,187 +19,199 @@
...
@@ -19,187 +19,199 @@
#define FMT_VERSION 50100
#define FMT_VERSION 50100
#ifdef __has_feature
#ifdef __has_feature
#define FMT_HAS_FEATURE(x) __has_feature(x)
#
define FMT_HAS_FEATURE(x) __has_feature(x)
#else
#else
#define FMT_HAS_FEATURE(x) 0
#
define FMT_HAS_FEATURE(x) 0
#endif
#endif
#ifdef __has_include
#ifdef __has_include
#define FMT_HAS_INCLUDE(x) __has_include(x)
#
define FMT_HAS_INCLUDE(x) __has_include(x)
#else
#else
#define FMT_HAS_INCLUDE(x) 0
#
define FMT_HAS_INCLUDE(x) 0
#endif
#endif
#ifdef __has_cpp_attribute
#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
#else
#define FMT_HAS_CPP_ATTRIBUTE(x) 0
#
define FMT_HAS_CPP_ATTRIBUTE(x) 0
#endif
#endif
#if defined(__GNUC__) && !defined(__clang__)
#if defined(__GNUC__) && !defined(__clang__)
#define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#
define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#else
#else
#define FMT_GCC_VERSION 0
#
define FMT_GCC_VERSION 0
#endif
#endif
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
#define FMT_HAS_GXX_CXX11 FMT_GCC_VERSION
#
define FMT_HAS_GXX_CXX11 FMT_GCC_VERSION
#else
#else
#define FMT_HAS_GXX_CXX11 0
#
define FMT_HAS_GXX_CXX11 0
#endif
#endif
#ifdef _MSC_VER
#ifdef _MSC_VER
#define FMT_MSC_VER _MSC_VER
#
define FMT_MSC_VER _MSC_VER
#else
#else
#define FMT_MSC_VER 0
#
define FMT_MSC_VER 0
#endif
#endif
// Check if relaxed c++14 constexpr is supported.
// Check if relaxed c++14 constexpr is supported.
// GCC doesn't allow throw in constexpr until version 6 (bug 67371).
// GCC doesn't allow throw in constexpr until version 6 (bug 67371).
#ifndef FMT_USE_CONSTEXPR
#ifndef FMT_USE_CONSTEXPR
#define FMT_USE_CONSTEXPR \
# define FMT_USE_CONSTEXPR \
(FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1910 || (FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L))
(FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1910 || \
(FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L))
#endif
#endif
#if FMT_USE_CONSTEXPR
#if FMT_USE_CONSTEXPR
#define FMT_CONSTEXPR constexpr
#
define FMT_CONSTEXPR constexpr
#define FMT_CONSTEXPR_DECL constexpr
#
define FMT_CONSTEXPR_DECL constexpr
#else
#else
#define FMT_CONSTEXPR inline
#
define FMT_CONSTEXPR inline
#define FMT_CONSTEXPR_DECL
#
define FMT_CONSTEXPR_DECL
#endif
#endif
#ifndef FMT_OVERRIDE
#ifndef FMT_OVERRIDE
#if FMT_HAS_FEATURE(cxx_override) || (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900
# if FMT_HAS_FEATURE(cxx_override) || \
#define FMT_OVERRIDE override
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
#else
FMT_MSC_VER >= 1900
#define FMT_OVERRIDE
# define FMT_OVERRIDE override
#endif
# else
# define FMT_OVERRIDE
# endif
#endif
#endif
#if FMT_HAS_FEATURE(cxx_explicit_conversions) || FMT_MSC_VER >= 1800
#if FMT_HAS_FEATURE(cxx_explicit_conversions) || \
#define FMT_EXPLICIT explicit
FMT_MSC_VER >= 1800
# define FMT_EXPLICIT explicit
#else
#else
#define FMT_EXPLICIT
#
define FMT_EXPLICIT
#endif
#endif
#ifndef FMT_NULL
#ifndef FMT_NULL
#if FMT_HAS_FEATURE(cxx_nullptr) || (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1600
# if FMT_HAS_FEATURE(cxx_nullptr) || \
#define FMT_NULL nullptr
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
#define FMT_USE_NULLPTR 1
FMT_MSC_VER >= 1600
#else
# define FMT_NULL nullptr
#define FMT_NULL NULL
# define FMT_USE_NULLPTR 1
#endif
# else
# define FMT_NULL NULL
# endif
#endif
#endif
#ifndef FMT_USE_NULLPTR
#ifndef FMT_USE_NULLPTR
#define FMT_USE_NULLPTR 0
#
define FMT_USE_NULLPTR 0
#endif
#endif
#if FMT_HAS_CPP_ATTRIBUTE(noreturn)
#if FMT_HAS_CPP_ATTRIBUTE(noreturn)
#define FMT_NORETURN [[noreturn]]
#
define FMT_NORETURN [[noreturn]]
#else
#else
#define FMT_NORETURN
#
define FMT_NORETURN
#endif
#endif
// Check if exceptions are disabled.
// Check if exceptions are disabled.
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
#define FMT_EXCEPTIONS 0
#
define FMT_EXCEPTIONS 0
#elif FMT_MSC_VER && !_HAS_EXCEPTIONS
#elif FMT_MSC_VER && !_HAS_EXCEPTIONS
#define FMT_EXCEPTIONS 0
#
define FMT_EXCEPTIONS 0
#endif
#endif
#ifndef FMT_EXCEPTIONS
#ifndef FMT_EXCEPTIONS
#define FMT_EXCEPTIONS 1
#
define FMT_EXCEPTIONS 1
#endif
#endif
// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature).
// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature).
#ifndef FMT_USE_NOEXCEPT
#ifndef FMT_USE_NOEXCEPT
#define FMT_USE_NOEXCEPT 0
#
define FMT_USE_NOEXCEPT 0
#endif
#endif
#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900
#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
#define FMT_DETECTED_NOEXCEPT noexcept
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
FMT_MSC_VER >= 1900
# define FMT_DETECTED_NOEXCEPT noexcept
#else
#else
#define FMT_DETECTED_NOEXCEPT throw()
#
define FMT_DETECTED_NOEXCEPT throw()
#endif
#endif
#ifndef FMT_NOEXCEPT
#ifndef FMT_NOEXCEPT
#if FMT_EXCEPTIONS
#
if FMT_EXCEPTIONS
#define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT
#
define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT
#else
#
else
#define FMT_NOEXCEPT
#
define FMT_NOEXCEPT
#endif
#
endif
#endif
#endif
// This is needed because GCC still uses throw() in its headers when exceptions
// This is needed because GCC still uses throw() in its headers when exceptions
// are disabled.
// are disabled.
#if FMT_GCC_VERSION
#if FMT_GCC_VERSION
#define FMT_DTOR_NOEXCEPT FMT_DETECTED_NOEXCEPT
#
define FMT_DTOR_NOEXCEPT FMT_DETECTED_NOEXCEPT
#else
#else
#define FMT_DTOR_NOEXCEPT FMT_NOEXCEPT
#
define FMT_DTOR_NOEXCEPT FMT_NOEXCEPT
#endif
#endif
#ifndef FMT_BEGIN_NAMESPACE
#ifndef FMT_BEGIN_NAMESPACE
#if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || FMT_MSC_VER >= 1900
# if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || \
#define FMT_INLINE_NAMESPACE inline namespace
FMT_MSC_VER >= 1900
#define FMT_END_NAMESPACE \
# define FMT_INLINE_NAMESPACE inline namespace
} \
# define FMT_END_NAMESPACE }}
}
# else
#else
# define FMT_INLINE_NAMESPACE namespace
#define FMT_INLINE_NAMESPACE namespace
# define FMT_END_NAMESPACE } using namespace v5; }
#define FMT_END_NAMESPACE \
# endif
} \
# define FMT_BEGIN_NAMESPACE namespace fmt { FMT_INLINE_NAMESPACE v5 {
using namespace v5; \
}
#endif
#define FMT_BEGIN_NAMESPACE \
namespace fmt { \
FMT_INLINE_NAMESPACE v5 \
{
#endif
#endif
#if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
#if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
#ifdef FMT_EXPORT
#
ifdef FMT_EXPORT
#define FMT_API __declspec(dllexport)
#
define FMT_API __declspec(dllexport)
#elif defined(FMT_SHARED)
#
elif defined(FMT_SHARED)
#define FMT_API __declspec(dllimport)
#
define FMT_API __declspec(dllimport)
#endif
#
endif
#endif
#endif
#ifndef FMT_API
#ifndef FMT_API
#define FMT_API
#
define FMT_API
#endif
#endif
#ifndef FMT_ASSERT
#ifndef FMT_ASSERT
#define FMT_ASSERT(condition, message) assert((condition) && message)
#
define FMT_ASSERT(condition, message) assert((condition) && message)
#endif
#endif
#define FMT_DELETED = delete
#define FMT_DELETED = delete
// A macro to disallow the copy construction and assignment.
// A macro to disallow the copy construction and assignment.
#define FMT_DISALLOW_COPY_AND_ASSIGN(Type)
\
#define FMT_DISALLOW_COPY_AND_ASSIGN(Type) \
Type(const Type &) FMT_DELETED;
\
Type(const Type &) FMT_DELETED; \
void operator=(const Type &) FMT_DELETED
void operator=(const Type &) FMT_DELETED
// libc++ supports string_view in pre-c++17.
// 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)
(defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
#include <string_view>
# include <string_view>
#define FMT_USE_STD_STRING_VIEW
# define FMT_USE_STD_STRING_VIEW
#elif (FMT_HAS_INCLUDE(<experimental / string_view>) && __cplusplus >= 201402L)
#elif (FMT_HAS_INCLUDE(<experimental/string_view>) && \
#include <experimental/string_view>
__cplusplus >= 201402L)
#define FMT_USE_EXPERIMENTAL_STRING_VIEW
# include <experimental/string_view>
# define FMT_USE_EXPERIMENTAL_STRING_VIEW
#endif
#endif
// std::result_of is defined in <functional> in gcc 4.4.
// std::result_of is defined in <functional> in gcc 4.4.
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 404
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 404
#include <functional>
#
include <functional>
#endif
#endif
FMT_BEGIN_NAMESPACE
FMT_BEGIN_NAMESPACE
// An implementation of declval for pre-C++11 compilers such as gcc 4.
namespace
internal
{
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
;
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,484 +221,361 @@ typename std::add_rvalue_reference<T>::type declval() FMT_NOEXCEPT;
...
@@ -209,484 +221,361 @@ typename std::add_rvalue_reference<T>::type declval() FMT_NOEXCEPT;
compiled with a different ``-std`` option than the client code (which is not
compiled with a different ``-std`` option than the client code (which is not
recommended).
recommended).
*/
*/
template
<
typename
Char
>
template
<
typename
Char
>
class
basic_string_view
class
basic_string_view
{
{
private:
private:
const
Char
*
data_
;
const
Char
*
data_
;
size_t
size_
;
size_t
size_
;
public:
public:
typedef
Char
char_type
;
typedef
Char
char_type
;
typedef
const
Char
*
iterator
;
typedef
const
Char
*
iterator
;
// Standard basic_string_view type.
// Standard basic_string_view type.
#if defined(FMT_USE_STD_STRING_VIEW)
#if defined(FMT_USE_STD_STRING_VIEW)
typedef
std
::
basic_string_view
<
Char
>
type
;
typedef
std
::
basic_string_view
<
Char
>
type
;
#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)
#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)
typedef
std
::
experimental
::
basic_string_view
<
Char
>
type
;
typedef
std
::
experimental
::
basic_string_view
<
Char
>
type
;
#else
#else
struct
type
struct
type
{
{
const
char
*
data
()
const
{
return
FMT_NULL
;
}
const
char
*
data
()
const
size_t
size
()
const
{
return
0
;
}
{
};
return
FMT_NULL
;
}
size_t
size
()
const
{
return
0
;
}
};
#endif
#endif
FMT_CONSTEXPR
basic_string_view
()
FMT_NOEXCEPT
:
data_
(
FMT_NULL
),
size_
(
0
)
{}
FMT_CONSTEXPR
basic_string_view
()
FMT_NOEXCEPT
:
data_
(
FMT_NULL
),
size_
(
0
)
{}
/** Constructs a string reference object from a C string and a size. */
/** 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
/**
Constructs a string reference object from a C string computing
\rst
the size with ``std::char_traits<Char>::length``.
Constructs a string reference object from a C string computing
\endrst
the size with ``std::char_traits<Char>::length``.
*/
\endrst
basic_string_view
(
const
Char
*
s
)
*/
:
data_
(
s
)
basic_string_view
(
const
Char
*
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
>
/** Constructs a string reference from a ``std::basic_string`` object. */
FMT_CONSTEXPR
basic_string_view
(
template
<
typename
Alloc
>
const
std
::
basic_string
<
Char
,
Alloc
>
&
s
)
FMT_NOEXCEPT
FMT_CONSTEXPR
basic_string_view
(
const
std
::
basic_string
<
Char
,
Alloc
>
&
s
)
FMT_NOEXCEPT
:
data_
(
s
.
c_str
()),
size_
(
s
.
size
())
:
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. */
/** Returns a pointer to the string data. */
const
Char
*
data
()
const
{
return
data_
;
}
const
Char
*
data
()
const
{
/** Returns the string size. */
return
data_
;
FMT_CONSTEXPR
size_t
size
()
const
{
return
size_
;
}
}
FMT_CONSTEXPR
iterator
begin
()
const
{
return
data_
;
}
/** Returns the string size. */
FMT_CONSTEXPR
iterator
end
()
const
{
return
data_
+
size_
;
}
FMT_CONSTEXPR
size_t
size
()
const
{
FMT_CONSTEXPR
void
remove_prefix
(
size_t
n
)
{
return
size_
;
data_
+=
n
;
}
size_
-=
n
;
}
FMT_CONSTEXPR
iterator
begin
()
const
{
// Lexicographically compare this string reference to other.
return
data_
;
int
compare
(
basic_string_view
other
)
const
{
}
size_t
str_size
=
size_
<
other
.
size_
?
size_
:
other
.
size_
;
FMT_CONSTEXPR
iterator
end
()
const
int
result
=
std
::
char_traits
<
Char
>::
compare
(
data_
,
other
.
data_
,
str_size
);
{
if
(
result
==
0
)
return
data_
+
size_
;
result
=
size_
==
other
.
size_
?
0
:
(
size_
<
other
.
size_
?
-
1
:
1
);
}
return
result
;
}
FMT_CONSTEXPR
void
remove_prefix
(
size_t
n
)
{
friend
bool
operator
==
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
data_
+=
n
;
return
lhs
.
compare
(
rhs
)
==
0
;
size_
-=
n
;
}
}
friend
bool
operator
!=
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
return
lhs
.
compare
(
rhs
)
!=
0
;
// Lexicographically compare this string reference to other.
}
int
compare
(
basic_string_view
other
)
const
friend
bool
operator
<
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
{
return
lhs
.
compare
(
rhs
)
<
0
;
size_t
str_size
=
size_
<
other
.
size_
?
size_
:
other
.
size_
;
}
int
result
=
std
::
char_traits
<
Char
>::
compare
(
data_
,
other
.
data_
,
str_size
);
friend
bool
operator
<=
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
if
(
result
==
0
)
return
lhs
.
compare
(
rhs
)
<=
0
;
result
=
size_
==
other
.
size_
?
0
:
(
size_
<
other
.
size_
?
-
1
:
1
);
}
return
result
;
friend
bool
operator
>
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
}
return
lhs
.
compare
(
rhs
)
>
0
;
}
friend
bool
operator
==
(
basic_string_view
lhs
,
basic_string_view
rhs
)
friend
bool
operator
>=
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
{
return
lhs
.
compare
(
rhs
)
>=
0
;
return
lhs
.
compare
(
rhs
)
==
0
;
}
}
friend
bool
operator
!=
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
return
lhs
.
compare
(
rhs
)
!=
0
;
}
friend
bool
operator
<
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
return
lhs
.
compare
(
rhs
)
<
0
;
}
friend
bool
operator
<=
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
return
lhs
.
compare
(
rhs
)
<=
0
;
}
friend
bool
operator
>
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
return
lhs
.
compare
(
rhs
)
>
0
;
}
friend
bool
operator
>=
(
basic_string_view
lhs
,
basic_string_view
rhs
)
{
return
lhs
.
compare
(
rhs
)
>=
0
;
}
};
};
typedef
basic_string_view
<
char
>
string_view
;
typedef
basic_string_view
<
char
>
string_view
;
typedef
basic_string_view
<
wchar_t
>
wstring_view
;
typedef
basic_string_view
<
wchar_t
>
wstring_view
;
template
<
typename
Context
>
template
<
typename
Context
>
class
basic_format_arg
;
class
basic_format_arg
;
template
<
typename
Context
>
template
<
typename
Context
>
class
basic_format_args
;
class
basic_format_args
;
// A formatter for objects of type T.
// 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
;
struct
formatter
;
namespace
internal
{
namespace
internal
{
/** A contiguous memory buffer with an optional growing ability. */
/** A contiguous memory buffer with an optional growing ability. */
template
<
typename
T
>
template
<
typename
T
>
class
basic_buffer
class
basic_buffer
{
{
private:
private:
FMT_DISALLOW_COPY_AND_ASSIGN
(
basic_buffer
);
FMT_DISALLOW_COPY_AND_ASSIGN
(
basic_buffer
);
T
*
ptr_
;
T
*
ptr_
;
std
::
size_t
size_
;
std
::
size_t
size_
;
std
::
size_t
capacity_
;
std
::
size_t
capacity_
;
protected:
protected:
basic_buffer
(
T
*
p
=
FMT_NULL
,
std
::
size_t
sz
=
0
,
std
::
size_t
cap
=
0
)
basic_buffer
(
T
*
p
=
FMT_NULL
,
std
::
size_t
buf_size
=
0
,
std
::
size_t
buf_capacity
=
0
)
FMT_NOEXCEPT
:
ptr_
(
p
),
FMT_NOEXCEPT:
ptr_
(
p
),
size_
(
sz
),
capacity_
(
cap
)
{}
size_
(
buf_size
),
capacity_
(
buf_capacity
)
/** Sets the buffer data and capacity. */
{
void
set
(
T
*
buf_data
,
std
::
size_t
buf_capacity
)
FMT_NOEXCEPT
{
}
ptr_
=
buf_data
;
capacity_
=
buf_capacity
;
/** Sets the buffer data and capacity. */
}
void
set
(
T
*
buf_data
,
std
::
size_t
buf_capacity
)
FMT_NOEXCEPT
{
/** Increases the buffer capacity to hold at least *capacity* elements. */
ptr_
=
buf_data
;
virtual
void
grow
(
std
::
size_t
capacity
)
=
0
;
capacity_
=
buf_capacity
;
}
public:
typedef
T
value_type
;
/** Increases the buffer capacity to hold at least *capacity* elements. */
typedef
const
T
&
const_reference
;
virtual
void
grow
(
std
::
size_t
capacity
)
=
0
;
virtual
~
basic_buffer
()
{}
public:
typedef
T
value_type
;
T
*
begin
()
FMT_NOEXCEPT
{
return
ptr_
;
}
typedef
const
T
&
const_reference
;
T
*
end
()
FMT_NOEXCEPT
{
return
ptr_
+
size_
;
}
virtual
~
basic_buffer
()
{}
/** Returns the size of this buffer. */
std
::
size_t
size
()
const
FMT_NOEXCEPT
{
return
size_
;
}
T
*
begin
()
FMT_NOEXCEPT
{
/** Returns the capacity of this buffer. */
return
ptr_
;
std
::
size_t
capacity
()
const
FMT_NOEXCEPT
{
return
capacity_
;
}
}
T
*
end
()
FMT_NOEXCEPT
/** Returns a pointer to the buffer data. */
{
T
*
data
()
FMT_NOEXCEPT
{
return
ptr_
;
}
return
ptr_
+
size_
;
}
/** Returns a pointer to the buffer data. */
const
T
*
data
()
const
FMT_NOEXCEPT
{
return
ptr_
;
}
/** Returns the size of this buffer. */
std
::
size_t
size
()
const
FMT_NOEXCEPT
/**
{
Resizes the buffer. If T is a POD type new elements may not be initialized.
return
size_
;
*/
}
void
resize
(
std
::
size_t
new_size
)
{
reserve
(
new_size
);
/** Returns the capacity of this buffer. */
size_
=
new_size
;
std
::
size_t
capacity
()
const
FMT_NOEXCEPT
}
{
return
capacity_
;
/** Reserves space to store at least *capacity* elements. */
}
void
reserve
(
std
::
size_t
new_capacity
)
{
if
(
new_capacity
>
capacity_
)
/** Returns a pointer to the buffer data. */
grow
(
new_capacity
);
T
*
data
()
FMT_NOEXCEPT
}
{
return
ptr_
;
void
push_back
(
const
T
&
value
)
{
}
reserve
(
size_
+
1
);
ptr_
[
size_
++
]
=
value
;
/** Returns a pointer to the buffer data. */
}
const
T
*
data
()
const
FMT_NOEXCEPT
{
/** Appends data to the end of the buffer. */
return
ptr_
;
template
<
typename
U
>
}
void
append
(
const
U
*
begin
,
const
U
*
end
);
/**
T
&
operator
[](
std
::
size_t
index
)
{
return
ptr_
[
index
];
}
Resizes the buffer. If T is a POD type new elements may not be initialized.
const
T
&
operator
[](
std
::
size_t
index
)
const
{
return
ptr_
[
index
];
}
*/
void
resize
(
std
::
size_t
new_size
)
{
reserve
(
new_size
);
size_
=
new_size
;
}
/** Reserves space to store at least *buf_capacity* elements. */
void
reserve
(
std
::
size_t
buf_capacity
)
{
if
(
buf_capacity
>
capacity_
)
grow
(
buf_capacity
);
}
void
push_back
(
const
T
&
value
)
{
reserve
(
size_
+
1
);
ptr_
[
size_
++
]
=
value
;
}
/** Appends data to the end of the buffer. */
template
<
typename
U
>
void
append
(
const
U
*
begin
,
const
U
*
end
);
T
&
operator
[](
std
::
size_t
index
)
{
return
ptr_
[
index
];
}
const
T
&
operator
[](
std
::
size_t
index
)
const
{
return
ptr_
[
index
];
}
};
};
typedef
basic_buffer
<
char
>
buffer
;
typedef
basic_buffer
<
char
>
buffer
;
typedef
basic_buffer
<
wchar_t
>
wbuffer
;
typedef
basic_buffer
<
wchar_t
>
wbuffer
;
// A container-backed buffer.
// A container-backed buffer.
template
<
typename
Container
>
template
<
typename
Container
>
class
container_buffer
:
public
basic_buffer
<
typename
Container
::
value_type
>
class
container_buffer
:
public
basic_buffer
<
typename
Container
::
value_type
>
{
{
private:
private:
Container
&
container_
;
Container
&
container_
;
protected:
protected:
void
grow
(
std
::
size_t
capacity
)
FMT_OVERRIDE
{
void
grow
(
std
::
size_t
capacity
)
FMT_OVERRIDE
container_
.
resize
(
capacity
);
{
this
->
set
(
&
container_
[
0
],
capacity
);
container_
.
resize
(
capacity
);
}
this
->
set
(
&
container_
[
0
],
capacity
);
}
public:
explicit
container_buffer
(
Container
&
c
)
public:
:
basic_buffer
<
typename
Container
::
value_type
>
(
&
c
[
0
],
c
.
size
(),
c
.
size
()),
explicit
container_buffer
(
Container
&
c
)
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
()
{}
FMT_CONSTEXPR
error_handler
(
const
error_handler
&
)
{}
FMT_CONSTEXPR
error_handler
(
const
error_handler
&
)
{}
// This function is intentionally not constexpr to give a compile-time error.
// This function is intentionally not constexpr to give a compile-time error.
FMT_API
void
on_error
(
const
char
*
message
);
FMT_API
void
on_error
(
const
char
*
message
);
};
};
// Formatting of wide characters and strings into a narrow output is disallowed:
// Formatting of wide characters and strings into a narrow output is disallowed:
// fmt::format("{}", L"test"); // error
// fmt::format("{}", L"test"); // error
// To fix this, use a wide format string:
// To fix this, use a wide format string:
// fmt::format(L"{}", L"test");
// fmt::format(L"{}", L"test");
template
<
typename
Char
>
template
<
typename
Char
>
inline
void
require_wchar
()
inline
void
require_wchar
()
{
{
static_assert
(
static_assert
(
std
::
is_same
<
wchar_t
,
Char
>::
value
,
"formatting of wide characters into a narrow output is disallowed"
);
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
;
struct
named_arg_base
;
template
<
typename
T
,
typename
Char
>
template
<
typename
T
,
typename
Char
>
struct
named_arg
;
struct
named_arg
;
template
<
typename
T
>
template
<
typename
T
>
struct
is_named_arg
:
std
::
false_type
struct
is_named_arg
:
std
::
false_type
{};
{
};
template
<
typename
T
,
typename
Char
>
template
<
typename
T
,
typename
Char
>
struct
is_named_arg
<
named_arg
<
T
,
Char
>>
:
std
::
true_type
struct
is_named_arg
<
named_arg
<
T
,
Char
>>
:
std
::
true_type
{};
{
};
enum
type
enum
type
{
{
none_type
,
named_arg_type
,
none_type
,
// Integer types should go first,
named_arg_type
,
int_type
,
uint_type
,
long_long_type
,
ulong_long_type
,
bool_type
,
char_type
,
// Integer types should go first,
last_integer_type
=
char_type
,
int_type
,
// followed by floating-point types.
uint_type
,
double_type
,
long_double_type
,
last_numeric_type
=
long_double_type
,
long_long_type
,
cstring_type
,
string_type
,
pointer_type
,
custom_type
ulong_long_type
,
bool_type
,
char_type
,
last_integer_type
=
char_type
,
// followed by floating-point types.
double_type
,
long_double_type
,
last_numeric_type
=
long_double_type
,
cstring_type
,
string_type
,
pointer_type
,
custom_type
};
};
FMT_CONSTEXPR
bool
is_integral
(
type
t
)
FMT_CONSTEXPR
bool
is_integral
(
type
t
)
{
{
FMT_ASSERT
(
t
!=
internal
::
named_arg_type
,
"invalid argument type"
);
FMT_ASSERT
(
t
!=
internal
::
named_arg_type
,
"invalid argument type"
);
return
t
>
internal
::
none_type
&&
t
<=
internal
::
last_integer_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"
);
FMT_ASSERT
(
t
!=
internal
::
named_arg_type
,
"invalid argument type"
);
return
t
>
internal
::
none_type
&&
t
<=
internal
::
last_numeric_type
;
return
t
>
internal
::
none_type
&&
t
<=
internal
::
last_numeric_type
;
}
}
template
<
typename
T
,
typename
Char
,
bool
ENABLE
=
true
>
template
<
typename
T
,
typename
Char
,
bool
ENABLE
=
true
>
struct
convert_to_int
struct
convert_to_int
{
{
enum
{
enum
value
=
!
std
::
is_arithmetic
<
T
>::
value
&&
std
::
is_convertible
<
T
,
int
>::
value
{
};
value
=
!
std
::
is_arithmetic
<
T
>::
value
&&
std
::
is_convertible
<
T
,
int
>::
value
};
};
};
template
<
typename
Char
>
template
<
typename
Char
>
struct
string_value
struct
string_value
{
{
const
Char
*
value
;
const
Char
*
value
;
std
::
size_t
size
;
std
::
size_t
size
;
};
};
template
<
typename
Context
>
template
<
typename
Context
>
struct
custom_value
struct
custom_value
{
{
const
void
*
value
;
const
void
*
value
;
void
(
*
format
)(
const
void
*
arg
,
Context
&
ctx
);
void
(
*
format
)(
const
void
*
arg
,
Context
&
ctx
);
};
};
// A formatting argument value.
// A formatting argument value.
template
<
typename
Context
>
template
<
typename
Context
>
class
value
class
value
{
{
public:
public:
typedef
typename
Context
::
char_type
char_type
;
typedef
typename
Context
::
char_type
char_type
;
union
{
union
int
int_value
;
{
unsigned
uint_value
;
int
int_value
;
long
long
long_long_value
;
unsigned
uint_value
;
unsigned
long
long
ulong_long_value
;
long
long
long_long_value
;
double
double_value
;
unsigned
long
long
ulong_long_value
;
long
double
long_double_value
;
double
double_value
;
const
void
*
pointer
;
long
double
long_double_value
;
string_value
<
char_type
>
string
;
const
void
*
pointer
;
string_value
<
signed
char
>
sstring
;
string_value
<
char_type
>
string
;
string_value
<
unsigned
char
>
ustring
;
string_value
<
signed
char
>
sstring
;
custom_value
<
Context
>
custom
;
string_value
<
unsigned
char
>
ustring
;
};
custom_value
<
Context
>
custom
;
};
FMT_CONSTEXPR
value
(
int
val
=
0
)
:
int_value
(
val
)
{}
value
(
unsigned
val
)
{
uint_value
=
val
;
}
FMT_CONSTEXPR
value
(
int
val
=
0
)
value
(
long
long
val
)
{
long_long_value
=
val
;
}
:
int_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
(
unsigned
val
)
value
(
const
char_type
*
val
)
{
string
.
value
=
val
;
}
{
value
(
const
signed
char
*
val
)
{
uint_value
=
val
;
static_assert
(
std
::
is_same
<
char
,
char_type
>::
value
,
}
"incompatible string types"
);
value
(
long
long
val
)
sstring
.
value
=
val
;
{
}
long_long_value
=
val
;
value
(
const
unsigned
char
*
val
)
{
}
static_assert
(
std
::
is_same
<
char
,
char_type
>::
value
,
value
(
unsigned
long
long
val
)
"incompatible string types"
);
{
ustring
.
value
=
val
;
ulong_long_value
=
val
;
}
}
value
(
basic_string_view
<
char_type
>
val
)
{
value
(
double
val
)
string
.
value
=
val
.
data
();
{
string
.
size
=
val
.
size
();
double_value
=
val
;
}
}
value
(
const
void
*
val
)
{
pointer
=
val
;
}
value
(
long
double
val
)
{
template
<
typename
T
>
long_double_value
=
val
;
explicit
value
(
const
T
&
val
)
{
}
custom
.
value
=
&
val
;
value
(
const
char_type
*
val
)
custom
.
format
=
&
format_custom_arg
<
T
>
;
{
}
string
.
value
=
val
;
}
const
named_arg_base
<
char_type
>
&
as_named_arg
()
{
value
(
const
signed
char
*
val
)
return
*
static_cast
<
const
named_arg_base
<
char_type
>*>
(
pointer
);
{
}
static_assert
(
std
::
is_same
<
char
,
char_type
>::
value
,
"incompatible string types"
);
sstring
.
value
=
val
;
private:
}
// Formats an argument of a custom type, such as a user-defined class.
value
(
const
unsigned
char
*
val
)
template
<
typename
T
>
{
static
void
format_custom_arg
(
const
void
*
arg
,
Context
&
ctx
)
{
static_assert
(
std
::
is_same
<
char
,
char_type
>::
value
,
"incompatible string types"
);
// Get the formatter type through the context to allow different contexts
ustring
.
value
=
val
;
// have different extension points, e.g. `formatter<T>` for `format` and
}
// `printf_formatter<T>` for `printf`.
value
(
basic_string_view
<
char_type
>
val
)
typename
Context
::
template
formatter_type
<
T
>
::
type
f
;
{
auto
&&
parse_ctx
=
ctx
.
parse_context
();
string
.
value
=
val
.
data
();
parse_ctx
.
advance_to
(
f
.
parse
(
parse_ctx
));
string
.
size
=
val
.
size
();
ctx
.
advance_to
(
f
.
format
(
*
static_cast
<
const
T
*>
(
arg
),
ctx
));
}
}
value
(
const
void
*
val
)
{
pointer
=
val
;
}
template
<
typename
T
>
explicit
value
(
const
T
&
val
)
{
custom
.
value
=
&
val
;
custom
.
format
=
&
format_custom_arg
<
T
>
;
}
const
named_arg_base
<
char_type
>
&
as_named_arg
()
{
return
*
static_cast
<
const
named_arg_base
<
char_type
>
*>
(
pointer
);
}
private:
// Formats an argument of a custom type, such as a user-defined class.
template
<
typename
T
>
static
void
format_custom_arg
(
const
void
*
arg
,
Context
&
ctx
)
{
// Get the formatter type through the context to allow different contexts
// have different extension points, e.g. `formatter<T>` for `format` and
// `printf_formatter<T>` for `printf`.
typename
Context
::
template
formatter_type
<
T
>
::
type
f
;
auto
&&
parse_ctx
=
ctx
.
parse_context
();
parse_ctx
.
advance_to
(
f
.
parse
(
parse_ctx
));
ctx
.
advance_to
(
f
.
format
(
*
static_cast
<
const
T
*>
(
arg
),
ctx
));
}
};
};
template
<
typename
Context
,
type
TYPE
>
template
<
typename
Context
,
type
TYPE
>
struct
typed_value
:
value
<
Context
>
struct
typed_value
:
value
<
Context
>
{
{
static
const
type
type_tag
=
TYPE
;
static
const
type
type_tag
=
TYPE
;
template
<
typename
T
>
template
<
typename
T
>
FMT_CONSTEXPR
typed_value
(
const
T
&
val
)
FMT_CONSTEXPR
typed_value
(
const
T
&
val
)
:
value
<
Context
>
(
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
);
FMT_CONSTEXPR
basic_format_arg
<
Context
>
make_arg
(
const
T
&
value
);
#define FMT_MAKE_VALUE(TAG, ArgType, ValueType) \
#define FMT_MAKE_VALUE(TAG, ArgType, ValueType) \
template<typename C> \
template <typename C> \
FMT_CONSTEXPR typed_value<C, TAG> make_value(ArgType val) \
FMT_CONSTEXPR typed_value<C, TAG> make_value(ArgType val) { \
{ \
return static_cast<ValueType>(val); \
return static_cast<ValueType>(val); \
}
}
#define FMT_MAKE_VALUE_SAME(TAG, Type) \
#define FMT_MAKE_VALUE_SAME(TAG, Type) \
template<typename C> \
template <typename C> \
FMT_CONSTEXPR typed_value<C, TAG> make_value(Type val) \
FMT_CONSTEXPR typed_value<C, TAG> make_value(Type val) { \
{ \
return val; \
return val; \
}
}
FMT_MAKE_VALUE
(
bool_type
,
bool
,
int
)
FMT_MAKE_VALUE
(
bool_type
,
bool
,
int
)
FMT_MAKE_VALUE
(
int_type
,
short
,
int
)
FMT_MAKE_VALUE
(
int_type
,
short
,
int
)
...
@@ -696,10 +585,15 @@ FMT_MAKE_VALUE_SAME(uint_type, unsigned)
...
@@ -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
// 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.
// either to int or to long long depending on its size.
typedef
std
::
conditional
<
sizeof
(
long
)
==
sizeof
(
int
),
int
,
long
long
>::
type
long_type
;
typedef
std
::
conditional
<
sizeof
(
long
)
==
sizeof
(
int
),
int
,
long
long
>::
type
FMT_MAKE_VALUE
((
sizeof
(
long
)
==
sizeof
(
int
)
?
int_type
:
long_long_type
),
long
,
long_type
)
long_type
;
typedef
std
::
conditional
<
sizeof
(
unsigned
long
)
==
sizeof
(
unsigned
),
unsigned
,
unsigned
long
long
>::
type
ulong_type
;
FMT_MAKE_VALUE
(
FMT_MAKE_VALUE
((
sizeof
(
unsigned
long
)
==
sizeof
(
unsigned
)
?
uint_type
:
ulong_long_type
),
unsigned
long
,
ulong_type
)
(
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
(
long_long_type
,
long
long
)
FMT_MAKE_VALUE_SAME
(
ulong_long_type
,
unsigned
long
long
)
FMT_MAKE_VALUE_SAME
(
ulong_long_type
,
unsigned
long
long
)
...
@@ -708,11 +602,10 @@ FMT_MAKE_VALUE(uint_type, unsigned char, unsigned)
...
@@ -708,11 +602,10 @@ FMT_MAKE_VALUE(uint_type, unsigned char, unsigned)
FMT_MAKE_VALUE
(
char_type
,
char
,
int
)
FMT_MAKE_VALUE
(
char_type
,
char
,
int
)
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
template
<
typename
C
>
template
<
typename
C
>
inline
typed_value
<
C
,
char_type
>
make_value
(
wchar_t
val
)
inline
typed_value
<
C
,
char_type
>
make_value
(
wchar_t
val
)
{
{
require_wchar
<
typename
C
::
char_type
>
();
require_wchar
<
typename
C
::
char_type
>
();
return
static_cast
<
int
>
(
val
);
return
static_cast
<
int
>
(
val
);
}
}
#endif
#endif
...
@@ -722,204 +615,170 @@ FMT_MAKE_VALUE_SAME(long_double_type, long double)
...
@@ -722,204 +615,170 @@ FMT_MAKE_VALUE_SAME(long_double_type, long double)
// Formatting of wide strings into a narrow buffer and multibyte strings
// Formatting of wide strings into a narrow buffer and multibyte strings
// into a wide buffer is disallowed (https://github.com/fmtlib/fmt/pull/606).
// 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
,
typename
C
::
char_type
*
,
FMT_MAKE_VALUE
(
cstring_type
,
const
typename
C
::
char_type
*
,
const
typename
C
::
char_type
*
)
const
typename
C
::
char_type
*
)
FMT_MAKE_VALUE
(
cstring_type
,
const
typename
C
::
char_type
*
,
FMT_MAKE_VALUE
(
cstring_type
,
signed
char
*
,
const
signed
char
*
)
const
typename
C
::
char_type
*
)
FMT_MAKE_VALUE_SAME
(
cstring_type
,
const
signed
char
*
)
FMT_MAKE_VALUE
(
cstring_type
,
unsigned
char
*
,
const
unsigned
char
*
)
FMT_MAKE_VALUE
(
cstring_type
,
signed
char
*
,
const
signed
char
*
)
FMT_MAKE_VALUE_SAME
(
cstring_type
,
const
unsigned
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_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
,
FMT_MAKE_VALUE
(
string_type
,
const
std
::
basic_string
<
typename
C
::
char_type
>
&
,
basic_string_view
<
typename
C
::
char_type
>
)
typename
basic_string_view
<
typename
C
::
char_type
>::
type
,
FMT_MAKE_VALUE
(
pointer_type
,
void
*
,
const
void
*
)
basic_string_view
<
typename
C
::
char_type
>
)
FMT_MAKE_VALUE_SAME
(
pointer_type
,
const
void
*
)
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
#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
#endif
// Formatting of arbitrary pointers is disallowed. If you want to output a
// Formatting of arbitrary pointers is disallowed. If you want to output a
// pointer cast it to "void *" or "const void *". In particular, this forbids
// pointer cast it to "void *" or "const void *". In particular, this forbids
// formatting of "[const] volatile char *" which is printed as bool by
// formatting of "[const] volatile char *" which is printed as bool by
// iostreams.
// iostreams.
template
<
typename
C
,
typename
T
>
template
<
typename
C
,
typename
T
>
typename
std
::
enable_if
<!
std
::
is_same
<
T
,
typename
C
::
char_type
>::
value
>::
type
make_value
(
const
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"
);
static_assert
(
!
sizeof
(
T
),
"formatting of non-void pointers is disallowed"
);
}
}
template
<
typename
C
,
typename
T
>
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
inline
typename
std
::
enable_if
<
make_value
(
const
T
&
val
)
std
::
is_enum
<
T
>::
value
&&
convert_to_int
<
T
,
typename
C
::
char_type
>::
value
,
{
typed_value
<
C
,
int_type
>>::
type
return
static_cast
<
int
>
(
val
);
make_value
(
const
T
&
val
)
{
return
static_cast
<
int
>
(
val
);
}
}
template
<
typename
C
,
typename
T
,
typename
Char
=
typename
C
::
char_type
>
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
,
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
// Implicit conversion to std::string is not handled here because it's
// unsafe: https://github.com/fmtlib/fmt/issues/729
// unsafe: https://github.com/fmtlib/fmt/issues/729
typed_value
<
C
,
custom_type
>>::
type
typed_value
<
C
,
custom_type
>>::
type
make_value
(
const
T
&
val
)
make_value
(
const
T
&
val
)
{
return
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
>
basic_format_arg
<
C
>
arg
=
make_arg
<
C
>
(
val
.
value
);
typed_value
<
C
,
named_arg_type
>
make_value
(
const
named_arg
<
T
,
typename
C
::
char_type
>
&
val
)
std
::
memcpy
(
val
.
data
,
&
arg
,
sizeof
(
arg
));
{
return
static_cast
<
const
void
*>
(
&
val
);
basic_format_arg
<
C
>
arg
=
make_arg
<
C
>
(
val
.
value
);
std
::
memcpy
(
val
.
data
,
&
arg
,
sizeof
(
arg
));
return
static_cast
<
const
void
*>
(
&
val
);
}
}
// Maximum number of arguments with packed types.
// Maximum number of arguments with packed types.
enum
enum
{
max_packed_args
=
15
};
{
max_packed_args
=
15
};
template
<
typename
Context
>
template
<
typename
Context
>
class
arg_map
;
class
arg_map
;
template
<
typename
>
template
<
typename
>
struct
result_of
;
struct
result_of
;
template
<
typename
F
,
typename
...
Args
>
template
<
typename
F
,
typename
...
Args
>
struct
result_of
<
F
(
Args
...)
>
struct
result_of
<
F
(
Args
...)
>
{
{
// A workaround for gcc 4.4 that doesn't allow F to be a reference.
// A workaround for gcc 4.4 that doesn't allow F to be a reference.
typedef
typename
std
::
result_of
<
type
def
typename
std
::
result_of
<
type
name
std
::
remove_reference
<
F
>::
type
(
Args
...)
>::
type
type
;
typename
std
::
remove_reference
<
F
>::
type
(
Args
...)
>::
type
type
;
};
};
}
// namespace internal
}
// A formatting argument. It is a trivially copyable/constructible type to
// A formatting argument. It is a trivially copyable/constructible type to
// allow storage in basic_memory_buffer.
// allow storage in basic_memory_buffer.
template
<
typename
Context
>
template
<
typename
Context
>
class
basic_format_arg
class
basic_format_arg
{
{
private:
private:
internal
::
value
<
Context
>
value_
;
internal
::
value
<
Context
>
value_
;
internal
::
type
type_
;
internal
::
type
type_
;
template
<
typename
ContextType
,
typename
T
>
friend
FMT_CONSTEXPR
basic_format_arg
<
ContextType
>
internal
::
make_arg
(
const
T
&
value
);
template
<
typename
Visitor
,
typename
Ctx
>
friend
FMT_CONSTEXPR
typename
internal
::
result_of
<
Visitor
(
int
)
>::
type
visit
(
Visitor
&&
vis
,
basic_format_arg
<
Ctx
>
arg
);
friend
class
basic_format_args
<
Context
>
;
friend
class
internal
::
arg_map
<
Context
>
;
typedef
typename
Context
::
char_type
char_type
;
public:
class
handle
{
public:
explicit
handle
(
internal
::
custom_value
<
Context
>
custom
)
:
custom_
(
custom
)
{
}
void
format
(
Context
&
ctx
)
const
{
custom_
.
format
(
custom_
.
value
,
ctx
);
}
private:
internal
::
custom_value
<
Context
>
custom_
;
};
FMT_CONSTEXPR
basic_format_arg
()
:
type_
(
internal
::
none_type
)
{
}
FMT_EXPLICIT
operator
bool
()
const
FMT_NOEXCEPT
template
<
typename
ContextType
,
typename
T
>
{
friend
FMT_CONSTEXPR
basic_format_arg
<
ContextType
>
return
type_
!=
internal
::
none_type
;
internal
::
make_arg
(
const
T
&
value
);
}
internal
::
type
type
()
const
template
<
typename
Visitor
,
typename
Ctx
>
{
friend
FMT_CONSTEXPR
typename
internal
::
result_of
<
Visitor
(
int
)
>::
type
return
type_
;
visit
(
Visitor
&&
vis
,
basic_format_arg
<
Ctx
>
arg
);
}
bool
is_integral
()
const
friend
class
basic_format_args
<
Context
>
;
{
friend
class
internal
::
arg_map
<
Context
>
;
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
typedef
typename
Context
::
char_type
char_type
;
// argument counter for automatic indexing.
template
<
typename
Char
,
typename
ErrorHandler
=
internal
::
error_handler
>
class
basic_parse_context
:
private
ErrorHandler
{
private:
basic_string_view
<
Char
>
format_str_
;
int
next_arg_id_
;
public:
typedef
Char
char_type
;
typedef
typename
basic_string_view
<
Char
>::
iterator
iterator
;
explicit
FMT_CONSTEXPR
basic_parse_context
(
basic_string_view
<
Char
>
format_str
,
ErrorHandler
eh
=
ErrorHandler
())
:
ErrorHandler
(
eh
)
,
format_str_
(
format_str
)
,
next_arg_id_
(
0
)
{
}
// Returns an iterator to the beginning of the format string range being
public:
// parsed.
class
handle
{
FMT_CONSTEXPR
iterator
begin
()
const
FMT_NOEXCEPT
public:
{
explicit
handle
(
internal
::
custom_value
<
Context
>
custom
)
:
custom_
(
custom
)
{}
return
format_str_
.
begin
();
}
// Returns an iterator past the end of the format string range being parsed.
void
format
(
Context
&
ctx
)
const
{
custom_
.
format
(
custom_
.
value
,
ctx
);
}
FMT_CONSTEXPR
iterator
end
()
const
FMT_NOEXCEPT
{
return
format_str_
.
end
();
}
// Advances the begin iterator to ``it``.
private:
FMT_CONSTEXPR
void
advance_to
(
iterator
it
)
internal
::
custom_value
<
Context
>
custom_
;
{
};
format_str_
.
remove_prefix
(
it
-
begin
());
}
// Returns the next argument index.
FMT_CONSTEXPR
basic_format_arg
()
:
type_
(
internal
::
none_type
)
{}
FMT_CONSTEXPR
unsigned
next_arg_id
();
FMT_CONSTEXPR
bool
check_arg_id
(
unsigned
)
{
if
(
next_arg_id_
>
0
)
{
on_error
(
"cannot switch from automatic to manual argument indexing"
);
return
false
;
}
next_arg_id_
=
-
1
;
return
true
;
}
void
check_arg_id
(
basic_string_view
<
Char
>
)
{}
FMT_CONSTEXPR
void
on_error
(
const
char
*
message
)
FMT_EXPLICIT
operator
bool
()
const
FMT_NOEXCEPT
{
{
return
type_
!=
internal
::
none_type
;
ErrorHandler
::
on_error
(
message
);
}
}
FMT_CONSTEXPR
ErrorHandler
error_handler
()
const
internal
::
type
type
()
const
{
return
type_
;
}
{
return
*
this
;
bool
is_integral
()
const
{
return
internal
::
is_integral
(
type_
);
}
}
bool
is_arithmetic
()
const
{
return
internal
::
is_arithmetic
(
type_
);
}
};
// Parsing context consisting of a format string range being parsed and an
// argument counter for automatic indexing.
template
<
typename
Char
,
typename
ErrorHandler
=
internal
::
error_handler
>
class
basic_parse_context
:
private
ErrorHandler
{
private:
basic_string_view
<
Char
>
format_str_
;
int
next_arg_id_
;
public:
typedef
Char
char_type
;
typedef
typename
basic_string_view
<
Char
>::
iterator
iterator
;
explicit
FMT_CONSTEXPR
basic_parse_context
(
basic_string_view
<
Char
>
format_str
,
ErrorHandler
eh
=
ErrorHandler
())
:
ErrorHandler
(
eh
),
format_str_
(
format_str
),
next_arg_id_
(
0
)
{}
// Returns an iterator to the beginning of the format string range being
// parsed.
FMT_CONSTEXPR
iterator
begin
()
const
FMT_NOEXCEPT
{
return
format_str_
.
begin
();
}
// Returns an iterator past the end of the format string range being parsed.
FMT_CONSTEXPR
iterator
end
()
const
FMT_NOEXCEPT
{
return
format_str_
.
end
();
}
// Advances the begin iterator to ``it``.
FMT_CONSTEXPR
void
advance_to
(
iterator
it
)
{
format_str_
.
remove_prefix
(
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
)
{
on_error
(
"cannot switch from automatic to manual argument indexing"
);
return
false
;
}
next_arg_id_
=
-
1
;
return
true
;
}
void
check_arg_id
(
basic_string_view
<
Char
>
)
{}
FMT_CONSTEXPR
void
on_error
(
const
char
*
message
)
{
ErrorHandler
::
on_error
(
message
);
}
FMT_CONSTEXPR
ErrorHandler
error_handler
()
const
{
return
*
this
;
}
};
};
typedef
basic_parse_context
<
char
>
parse_context
;
typedef
basic_parse_context
<
char
>
parse_context
;
...
@@ -927,246 +786,195 @@ typedef basic_parse_context<wchar_t> wparse_context;
...
@@ -927,246 +786,195 @@ typedef basic_parse_context<wchar_t> wparse_context;
namespace
internal
{
namespace
internal
{
// A map from argument names to their values for named arguments.
// A map from argument names to their values for named arguments.
template
<
typename
Context
>
template
<
typename
Context
>
class
arg_map
class
arg_map
{
{
private:
private:
FMT_DISALLOW_COPY_AND_ASSIGN
(
arg_map
);
FMT_DISALLOW_COPY_AND_ASSIGN
(
arg_map
);
typedef
typename
Context
::
char_type
char_type
;
struct
entry
{
basic_string_view
<
char_type
>
name
;
basic_format_arg
<
Context
>
arg
;
};
entry
*
map_
;
unsigned
size_
;
void
push_back
(
value
<
Context
>
val
)
{
const
internal
::
named_arg_base
<
char_type
>
&
named
=
val
.
as_named_arg
();
map_
[
size_
]
=
entry
{
named
.
name
,
named
.
template
deserialize
<
Context
>()};
++
size_
;
}
public:
typedef
typename
Context
::
char_type
char_type
;
arg_map
()
:
map_
(
FMT_NULL
)
,
size_
(
0
)
{
}
void
init
(
const
basic_format_args
<
Context
>
&
args
);
~
arg_map
()
{
delete
[]
map_
;
}
basic_format_arg
<
Context
>
find
(
basic_string_view
<
char_type
>
name
)
const
struct
entry
{
{
basic_string_view
<
char_type
>
name
;
// The list is unsorted, so just return the first matching name.
basic_format_arg
<
Context
>
arg
;
for
(
entry
*
it
=
map_
,
*
end
=
map_
+
size_
;
it
!=
end
;
++
it
)
};
{
if
(
it
->
name
==
name
)
entry
*
map_
;
return
it
->
arg
;
unsigned
size_
;
}
return
basic_format_arg
<
Context
>
();
void
push_back
(
value
<
Context
>
val
)
{
}
const
internal
::
named_arg_base
<
char_type
>
&
named
=
val
.
as_named_arg
();
map_
[
size_
]
=
entry
{
named
.
name
,
named
.
template
deserialize
<
Context
>()};
++
size_
;
}
public:
arg_map
()
:
map_
(
FMT_NULL
),
size_
(
0
)
{}
void
init
(
const
basic_format_args
<
Context
>
&
args
);
~
arg_map
()
{
delete
[]
map_
;
}
basic_format_arg
<
Context
>
find
(
basic_string_view
<
char_type
>
name
)
const
{
// The list is unsorted, so just return the first matching name.
for
(
entry
*
it
=
map_
,
*
end
=
map_
+
size_
;
it
!=
end
;
++
it
)
{
if
(
it
->
name
==
name
)
return
it
->
arg
;
}
return
basic_format_arg
<
Context
>
();
}
};
};
template
<
typename
OutputIt
,
typename
Context
,
typename
Char
>
template
<
typename
OutputIt
,
typename
Context
,
typename
Char
>
class
context_base
class
context_base
{
{
public:
public:
typedef
OutputIt
iterator
;
typedef
OutputIt
iterator
;
private:
private:
basic_parse_context
<
Char
>
parse_context_
;
basic_parse_context
<
Char
>
parse_context_
;
iterator
out_
;
iterator
out_
;
basic_format_args
<
Context
>
args_
;
basic_format_args
<
Context
>
args_
;
protected:
protected:
typedef
Char
char_type
;
typedef
Char
char_type
;
typedef
basic_format_arg
<
Context
>
format_arg
;
typedef
basic_format_arg
<
Context
>
format_arg
;
context_base
(
OutputIt
out
,
basic_string_view
<
char_type
>
format_str
,
context_base
(
OutputIt
out
,
basic_string_view
<
char_type
>
format_str
,
basic_format_args
<
Context
>
ctx_args
)
basic_format_args
<
Context
>
ctx_args
)
:
parse_context_
(
format_str
)
:
parse_context_
(
format_str
),
out_
(
out
),
args_
(
ctx_args
)
{}
,
out_
(
out
)
,
args_
(
ctx_args
)
// Returns the argument with specified index.
{
format_arg
do_get_arg
(
unsigned
arg_id
)
{
}
format_arg
arg
=
args_
.
get
(
arg_id
);
if
(
!
arg
)
parse_context_
.
on_error
(
"argument index out of range"
);
return
arg
;
}
// Returns the argument with specified index.
// Checks if manual indexing is used and returns the argument with
format_arg
do_get_arg
(
unsigned
arg_id
)
// specified index.
{
format_arg
get_arg
(
unsigned
arg_id
)
{
format_arg
arg
=
args_
.
get
(
arg_id
);
return
this
->
parse_context
().
check_arg_id
(
arg_id
)
?
if
(
!
arg
)
this
->
do_get_arg
(
arg_id
)
:
format_arg
();
parse_context_
.
on_error
(
"argument index out of range"
);
}
return
arg
;
}
// Checks if manual indexing is used and returns the argument with
public:
// specified index.
basic_parse_context
<
char_type
>
&
parse_context
()
{
format_arg
get_arg
(
unsigned
arg_id
)
return
parse_context_
;
{
}
return
this
->
parse_context
().
check_arg_id
(
arg_id
)
?
this
->
do_get_arg
(
arg_id
)
:
format_arg
();
}
public:
internal
::
error_handler
error_handler
()
{
basic_parse_context
<
char_type
>
&
parse_context
()
return
parse_context_
.
error_handler
();
{
}
return
parse_context_
;
}
internal
::
error_handler
error_handler
()
void
on_error
(
const
char
*
message
)
{
parse_context_
.
on_error
(
message
);
}
{
return
parse_context_
.
error_handler
();
}
void
on_error
(
const
char
*
message
)
// Returns an iterator to the beginning of the output range.
{
iterator
out
()
{
return
out_
;
}
parse_context_
.
on_error
(
message
);
iterator
begin
()
{
return
out_
;
}
// deprecated
}
// Returns an iterator to the beginning of the output range.
// Advances the begin iterator to ``it``.
iterator
out
()
void
advance_to
(
iterator
it
)
{
out_
=
it
;
}
{
return
out_
;
}
iterator
begin
()
{
return
out_
;
}
// deprecated
// Advances the begin iterator to ``it``.
void
advance_to
(
iterator
it
)
{
out_
=
it
;
}
basic_format_args
<
Context
>
args
()
const
basic_format_args
<
Context
>
args
()
const
{
return
args_
;
}
{
return
args_
;
}
};
};
// Extracts a reference to the container from back_insert_iterator.
// Extracts a reference to the container from back_insert_iterator.
template
<
typename
Container
>
template
<
typename
Container
>
inline
Container
&
get_container
(
std
::
back_insert_iterator
<
Container
>
it
)
inline
Container
&
get_container
(
std
::
back_insert_iterator
<
Container
>
it
)
{
{
typedef
std
::
back_insert_iterator
<
Container
>
bi_iterator
;
typedef
std
::
back_insert_iterator
<
Container
>
bi_iterator
;
struct
accessor
:
bi_iterator
{
struct
accessor
:
bi_iterator
accessor
(
bi_iterator
iter
)
:
bi_iterator
(
iter
)
{}
{
using
bi_iterator
::
container
;
accessor
(
bi_iterator
iter
)
};
:
bi_iterator
(
iter
)
return
*
accessor
(
it
).
container
;
{
}
using
bi_iterator
::
container
;
};
return
*
accessor
(
it
).
container
;
}
}
}
// namespace internal
}
// namespace internal
// Formatting context.
// Formatting context.
template
<
typename
OutputIt
,
typename
Char
>
template
<
typename
OutputIt
,
typename
Char
>
class
basic_format_context
:
public
internal
::
context_base
<
OutputIt
,
basic_format_context
<
OutputIt
,
Char
>
,
Char
>
class
basic_format_context
:
{
public
internal
::
context_base
<
public:
OutputIt
,
basic_format_context
<
OutputIt
,
Char
>
,
Char
>
{
/** The character type for the output. */
public:
typedef
Char
char_type
;
/** The character type for the output. */
typedef
Char
char_type
;
// using formatter_type = formatter<T, char_type>;
template
<
typename
T
>
// using formatter_type = formatter<T, char_type>;
struct
formatter_type
template
<
typename
T
>
{
struct
formatter_type
{
typedef
formatter
<
T
,
char_type
>
type
;
};
typedef
formatter
<
T
,
char_type
>
type
;
};
private:
internal
::
arg_map
<
basic_format_context
>
map_
;
private:
internal
::
arg_map
<
basic_format_context
>
map_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
basic_format_context
);
FMT_DISALLOW_COPY_AND_ASSIGN
(
basic_format_context
);
typedef
internal
::
context_base
<
OutputIt
,
basic_format_context
,
Char
>
base
;
typedef
typename
base
::
format_arg
format_arg
;
typedef
internal
::
context_base
<
OutputIt
,
basic_format_context
,
Char
>
base
;
using
base
::
get_arg
;
typedef
typename
base
::
format_arg
format_arg
;
using
base
::
get_arg
;
public:
using
typename
base
::
iterator
;
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.
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
)
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
)
{}
:
base
(
out
,
format_str
,
ctx_args
)
{
format_arg
next_arg
()
{
}
return
this
->
do_get_arg
(
this
->
parse_context
().
next_arg_id
());
}
format_arg
next_arg
()
format_arg
get_arg
(
unsigned
arg_id
)
{
return
this
->
do_get_arg
(
arg_id
);
}
{
return
this
->
do_get_arg
(
this
->
parse_context
().
next_arg_id
());
// Checks if manual indexing is used and returns the argument with the
}
// specified name.
format_arg
get_arg
(
unsigned
arg_id
)
format_arg
get_arg
(
basic_string_view
<
char_type
>
name
);
{
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
>
template
<
typename
Char
>
struct
buffer_context
struct
buffer_context
{
{
typedef
basic_format_context
<
typedef
basic_format_context
<
std
::
back_insert_iterator
<
internal
::
basic_buffer
<
Char
>>
,
Char
>
type
;
std
::
back_insert_iterator
<
internal
::
basic_buffer
<
Char
>>
,
Char
>
type
;
};
};
typedef
buffer_context
<
char
>::
type
format_context
;
typedef
buffer_context
<
char
>::
type
format_context
;
typedef
buffer_context
<
wchar_t
>::
type
wformat_context
;
typedef
buffer_context
<
wchar_t
>::
type
wformat_context
;
namespace
internal
{
namespace
internal
{
template
<
typename
Context
,
typename
T
>
template
<
typename
Context
,
typename
T
>
struct
get_type
struct
get_type
{
{
typedef
decltype
(
make_value
<
Context
>
(
typedef
decltype
(
make_value
<
Context
>
(
declval
<
typename
std
::
decay
<
T
>::
type
&>
()))
value_type
;
declval
<
typename
std
::
decay
<
T
>::
type
&>
()))
value_type
;
static
const
type
value
=
value_type
::
type_tag
;
static
const
type
value
=
value_type
::
type_tag
;
};
};
template
<
typename
Context
>
template
<
typename
Context
>
FMT_CONSTEXPR
uint64_t
get_types
()
FMT_CONSTEXPR
unsigned
long
long
get_types
()
{
return
0
;
}
{
return
0
;
}
template
<
typename
Context
,
typename
Arg
,
typename
...
Args
>
template
<
typename
Context
,
typename
Arg
,
typename
...
Args
>
FMT_CONSTEXPR
uint64_t
get_types
()
FMT_CONSTEXPR
unsigned
long
long
get_types
()
{
{
return
get_type
<
Context
,
Arg
>::
value
|
(
get_types
<
Context
,
Args
...
>
()
<<
4
);
return
get_type
<
Context
,
Arg
>::
value
|
(
get_types
<
Context
,
Args
...
>
()
<<
4
);
}
}
template
<
typename
Context
,
typename
T
>
template
<
typename
Context
,
typename
T
>
FMT_CONSTEXPR
basic_format_arg
<
Context
>
make_arg
(
const
T
&
value
)
FMT_CONSTEXPR
basic_format_arg
<
Context
>
make_arg
(
const
T
&
value
)
{
{
basic_format_arg
<
Context
>
arg
;
basic_format_arg
<
Context
>
arg
;
arg
.
type_
=
get_type
<
Context
,
T
>::
value
;
arg
.
type_
=
get_type
<
Context
,
T
>::
value
;
arg
.
value_
=
make_value
<
Context
>
(
value
);
arg
.
value_
=
make_value
<
Context
>
(
value
);
return
arg
;
return
arg
;
}
}
template
<
bool
IS_PACKED
,
typename
Context
,
typename
T
>
template
<
bool
IS_PACKED
,
typename
Context
,
typename
T
>
inline
typename
std
::
enable_if
<
IS_PACKED
,
value
<
Context
>>::
type
make_arg
(
const
T
&
value
)
inline
typename
std
::
enable_if
<
IS_PACKED
,
value
<
Context
>>::
type
{
make_arg
(
const
T
&
value
)
{
return
make_value
<
Context
>
(
value
);
return
make_value
<
Context
>
(
value
);
}
}
template
<
bool
IS_PACKED
,
typename
Context
,
typename
T
>
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
)
inline
typename
std
::
enable_if
<!
IS_PACKED
,
basic_format_arg
<
Context
>>::
type
{
make_arg
(
const
T
&
value
)
{
return
make_arg
<
Context
>
(
value
);
return
make_arg
<
Context
>
(
value
);
}
}
}
}
// namespace internal
/**
/**
\rst
\rst
...
@@ -1175,51 +983,54 @@ inline typename std::enable_if<!IS_PACKED, basic_format_arg<Context>>::type make
...
@@ -1175,51 +983,54 @@ inline typename std::enable_if<!IS_PACKED, basic_format_arg<Context>>::type make
such as `~fmt::vformat`.
such as `~fmt::vformat`.
\endrst
\endrst
*/
*/
template
<
typename
Context
,
typename
...
Args
>
template
<
typename
Context
,
typename
...
Args
>
class
format_arg_store
class
format_arg_store
{
{
private:
private:
static
const
size_t
NUM_ARGS
=
sizeof
...(
Args
);
static
const
size_t
NUM_ARGS
=
sizeof
...(
Args
);
// Packed is a macro on MinGW so use IS_PACKED instead.
// Packed is a macro on MinGW so use IS_PACKED instead.
static
const
bool
IS_PACKED
=
NUM_ARGS
<
internal
::
max_packed_args
;
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.
// 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
>
;
friend
class
basic_format_args
<
Context
>
;
static
FMT_CONSTEXPR
int64_t
get_types
()
static
FMT_CONSTEXPR
long
long
get_types
()
{
{
return
IS_PACKED
?
return
IS_PACKED
?
static_cast
<
int64_t
>
(
internal
::
get_types
<
Context
,
Args
...
>
())
:
-
static_cast
<
int64_t
>
(
NUM_ARGS
);
static_cast
<
long
long
>
(
internal
::
get_types
<
Context
,
Args
...
>
())
:
}
-
static_cast
<
long
long
>
(
NUM_ARGS
);
}
public:
public:
#if FMT_USE_CONSTEXPR
#if FMT_USE_CONSTEXPR
static
constexpr
int64_t
TYPES
=
get_types
();
static
constexpr
long
long
TYPES
=
get_types
();
#else
#else
static
const
int64_t
TYPES
;
static
const
long
long
TYPES
;
#endif
#endif
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 405
#if (FMT_GCC_VERSION && FMT_GCC_VERSION <= 405) || \
// Workaround an array initialization bug in gcc 4.5 and earlier.
(FMT_MSC_VER && FMT_MSC_VER <= 1800)
format_arg_store
(
const
Args
&
...
args
)
// Workaround array initialization issues in gcc <= 4.5 and MSVC <= 2013.
{
format_arg_store
(
const
Args
&
...
args
)
{
data_
=
{
internal
::
make_arg
<
IS_PACKED
,
Context
>
(
args
)...};
value_type
init
[
DATA_SIZE
]
=
}
{
internal
::
make_arg
<
IS_PACKED
,
Context
>
(
args
)...};
std
::
memcpy
(
data_
,
init
,
sizeof
(
init
));
}
#else
#else
format_arg_store
(
const
Args
&
...
args
)
format_arg_store
(
const
Args
&
...
args
)
:
data_
{
internal
::
make_arg
<
IS_PACKED
,
Context
>
(
args
)...}
:
data_
{
internal
::
make_arg
<
IS_PACKED
,
Context
>
(
args
)...}
{}
{
}
#endif
#endif
};
};
#if !FMT_USE_CONSTEXPR
#if !FMT_USE_CONSTEXPR
template
<
typename
Context
,
typename
...
Args
>
template
<
typename
Context
,
typename
...
Args
>
const
int64_t
format_arg_store
<
Context
,
Args
...
>::
TYPES
=
get_types
();
const
long
long
format_arg_store
<
Context
,
Args
...
>::
TYPES
=
get_types
();
#endif
#endif
/**
/**
...
@@ -1229,164 +1040,136 @@ const int64_t format_arg_store<Context, Args...>::TYPES = get_types();
...
@@ -1229,164 +1040,136 @@ const int64_t format_arg_store<Context, Args...>::TYPES = get_types();
be omitted in which case it defaults to `~fmt::context`.
be omitted in which case it defaults to `~fmt::context`.
\endrst
\endrst
*/
*/
template
<
typename
Context
,
typename
...
Args
>
template
<
typename
Context
,
typename
...
Args
>
inline
format_arg_store
<
Context
,
Args
...
>
make_format_args
(
const
Args
&
...
args
)
inline
format_arg_store
<
Context
,
Args
...
>
{
make_format_args
(
const
Args
&
...
args
)
{
return
format_arg_store
<
Context
,
Args
...
>
(
args
...);
return
format_arg_store
<
Context
,
Args
...
>
(
args
...);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
format_arg_store
<
format_context
,
Args
...
>
make_format_args
(
const
Args
&
...
args
)
inline
format_arg_store
<
format_context
,
Args
...
>
{
make_format_args
(
const
Args
&
...
args
)
{
return
format_arg_store
<
format_context
,
Args
...
>
(
args
...);
return
format_arg_store
<
format_context
,
Args
...
>
(
args
...);
}
}
/** Formatting arguments. */
/** Formatting arguments. */
template
<
typename
Context
>
template
<
typename
Context
>
class
basic_format_args
class
basic_format_args
{
{
public:
public:
typedef
unsigned
size_type
;
typedef
unsigned
size_type
;
typedef
basic_format_arg
<
Context
>
format_arg
;
typedef
basic_format_arg
<
Context
>
format_arg
;
private:
private:
// To reduce compiled code size per formatting function call, types of first
// To reduce compiled code size per formatting function call, types of first
// max_packed_args arguments are passed in the types_ field.
// max_packed_args arguments are passed in the types_ field.
unsigned
long
long
types_
;
uint64_t
types_
;
union
{
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_.
// If the number of arguments is less than max_packed_args, the argument
// This is done to reduce compiled code size as storing larger objects
// values are stored in values_, otherwise they are stored in args_.
// may require more code (at least on x86-64) even if the same amount of
// This is done to reduce compiled code size as storing larger objects
// data is actually copied to stack. It saves ~10% on the bloat test.
// may require more code (at least on x86-64) even if the same amount of
const
internal
::
value
<
Context
>
*
values_
;
// data is actually copied to stack. It saves ~10% on the bloat test.
const
format_arg
*
args_
;
const
internal
::
value
<
Context
>
*
values_
;
};
const
format_arg
*
args_
;
};
typename
internal
::
type
type
(
unsigned
index
)
const
{
unsigned
shift
=
index
*
4
;
typename
internal
::
type
type
(
unsigned
index
)
const
unsigned
long
long
mask
=
0xf
;
{
return
static_cast
<
typename
internal
::
type
>
(
unsigned
shift
=
index
*
4
;
(
types_
&
(
mask
<<
shift
))
>>
shift
);
uint64_t
mask
=
0xf
;
}
return
static_cast
<
typename
internal
::
type
>
((
types_
&
(
mask
<<
shift
))
>>
shift
);
}
friend
class
internal
::
arg_map
<
Context
>
;
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
)
{
format_arg
do_get
(
size_type
index
)
const
{
values_
=
values
;
long
long
signed_types
=
static_cast
<
long
long
>
(
types_
);
}
if
(
signed_types
<
0
)
{
void
set_data
(
const
format_arg
*
args
)
unsigned
long
long
num_args
=
static_cast
<
unsigned
long
long
>
(
-
signed_types
);
{
return
index
<
num_args
?
args_
[
index
]
:
format_arg
();
args_
=
args
;
}
}
format_arg
arg
;
if
(
index
>
internal
::
max_packed_args
)
format_arg
do_get
(
size_type
index
)
const
return
arg
;
{
arg
.
type_
=
type
(
index
);
int64_t
signed_types
=
static_cast
<
int64_t
>
(
types_
);
if
(
arg
.
type_
==
internal
::
none_type
)
if
(
signed_types
<
0
)
return
arg
;
{
internal
::
value
<
Context
>
&
val
=
arg
.
value_
;
uint64_t
num_args
=
-
signed_types
;
val
=
values_
[
index
];
return
index
<
num_args
?
args_
[
index
]
:
format_arg
();
return
arg
;
}
}
format_arg
arg
;
if
(
index
>
internal
::
max_packed_args
)
public:
return
arg
;
basic_format_args
()
:
types_
(
0
)
{}
arg
.
type_
=
type
(
index
);
if
(
arg
.
type_
==
internal
::
none_type
)
/**
return
arg
;
\rst
internal
::
value
<
Context
>
&
val
=
arg
.
value_
;
Constructs a `basic_format_args` object from `~fmt::format_arg_store`.
val
=
values_
[
index
];
\endrst
return
arg
;
*/
}
template
<
typename
...
Args
>
basic_format_args
(
const
format_arg_store
<
Context
,
Args
...
>
&
store
)
public:
:
types_
(
static_cast
<
unsigned
long
long
>
(
store
.
TYPES
))
{
basic_format_args
()
set_data
(
store
.
data_
);
:
types_
(
0
)
}
{
}
/** Returns the argument at specified index. */
format_arg
get
(
size_type
index
)
const
{
/**
format_arg
arg
=
do_get
(
index
);
\rst
return
arg
.
type_
==
internal
::
named_arg_type
?
Constructs a `basic_format_args` object from `~fmt::format_arg_store`.
arg
.
value_
.
as_named_arg
().
template
deserialize
<
Context
>()
:
arg
;
\endrst
}
*/
template
<
typename
...
Args
>
unsigned
max_size
()
const
{
basic_format_args
(
const
format_arg_store
<
Context
,
Args
...
>
&
store
)
long
long
signed_types
=
static_cast
<
long
long
>
(
types_
);
:
types_
(
store
.
TYPES
)
return
static_cast
<
unsigned
>
(
{
signed_types
<
0
?
set_data
(
store
.
data_
);
-
signed_types
:
static_cast
<
long
long
>
(
internal
::
max_packed_args
));
}
}
/** Returns the argument at specified index. */
format_arg
get
(
size_type
index
)
const
{
format_arg
arg
=
do_get
(
index
);
return
arg
.
type_
==
internal
::
named_arg_type
?
arg
.
value_
.
as_named_arg
().
template
deserialize
<
Context
>()
:
arg
;
}
unsigned
max_size
()
const
{
int64_t
signed_types
=
static_cast
<
int64_t
>
(
types_
);
return
static_cast
<
unsigned
>
(
signed_types
<
0
?
-
signed_types
:
static_cast
<
int64_t
>
(
internal
::
max_packed_args
));
}
};
};
/** An alias to ``basic_format_args<context>``. */
/** An alias to ``basic_format_args<context>``. */
// It is a separate type rather than a typedef to make symbols readable.
// It is a separate type rather than a typedef to make symbols readable.
struct
format_args
:
basic_format_args
<
format_context
>
struct
format_args
:
basic_format_args
<
format_context
>
{
{
template
<
typename
...
Args
>
template
<
typename
...
Args
>
format_args
(
Args
&&
...
arg
)
format_args
(
Args
&&
...
arg
)
:
basic_format_args
<
format_context
>
(
std
::
forward
<
Args
>
(
arg
)...)
{}
:
basic_format_args
<
format_context
>
(
std
::
forward
<
Args
>
(
arg
)...)
{
}
};
};
struct
wformat_args
:
basic_format_args
<
wformat_context
>
struct
wformat_args
:
basic_format_args
<
wformat_context
>
{
{
template
<
typename
...
Args
>
template
<
typename
...
Args
>
wformat_args
(
Args
&&
...
arg
)
wformat_args
(
Args
&&
...
arg
)
:
basic_format_args
<
wformat_context
>
(
std
::
forward
<
Args
>
(
arg
)...)
{}
:
basic_format_args
<
wformat_context
>
(
std
::
forward
<
Args
>
(
arg
)...)
{
}
};
};
namespace
internal
{
namespace
internal
{
template
<
typename
Char
>
template
<
typename
Char
>
struct
named_arg_base
struct
named_arg_base
{
{
basic_string_view
<
Char
>
name
;
basic_string_view
<
Char
>
name
;
// Serialized value<context>.
// Serialized value<context>.
mutable
char
data
[
sizeof
(
basic_format_arg
<
format_context
>
)];
mutable
char
data
[
sizeof
(
basic_format_arg
<
format_context
>
)];
named_arg_base
(
basic_string_view
<
Char
>
nm
)
named_arg_base
(
basic_string_view
<
Char
>
nm
)
:
name
(
nm
)
{}
:
name
(
nm
)
{
}
template
<
typename
Context
>
template
<
typename
Context
>
basic_format_arg
<
Context
>
deserialize
()
const
basic_format_arg
<
Context
>
deserialize
()
const
{
{
basic_format_arg
<
Context
>
arg
;
basic_format_arg
<
Context
>
arg
;
std
::
memcpy
(
&
arg
,
data
,
sizeof
(
basic_format_arg
<
Context
>
));
std
::
memcpy
(
&
arg
,
data
,
sizeof
(
basic_format_arg
<
Context
>
));
return
arg
;
return
arg
;
}
}
};
};
template
<
typename
T
,
typename
Char
>
template
<
typename
T
,
typename
Char
>
struct
named_arg
:
named_arg_base
<
Char
>
struct
named_arg
:
named_arg_base
<
Char
>
{
{
const
T
&
value
;
const
T
&
value
;
named_arg
(
basic_string_view
<
Char
>
name
,
const
T
&
val
)
named_arg
(
basic_string_view
<
Char
>
name
,
const
T
&
val
)
:
named_arg_base
<
Char
>
(
name
)
:
named_arg_base
<
Char
>
(
name
),
value
(
val
)
{}
,
value
(
val
)
{
}
};
};
}
// namespace internal
}
/**
/**
\rst
\rst
...
@@ -1397,93 +1180,73 @@ struct named_arg : named_arg_base<Char>
...
@@ -1397,93 +1180,73 @@ struct named_arg : named_arg_base<Char>
fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23));
fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23));
\endrst
\endrst
*/
*/
template
<
typename
T
>
template
<
typename
T
>
inline
internal
::
named_arg
<
T
,
char
>
arg
(
string_view
name
,
const
T
&
arg
)
inline
internal
::
named_arg
<
T
,
char
>
arg
(
string_view
name
,
const
T
&
arg
)
{
{
return
internal
::
named_arg
<
T
,
char
>
(
name
,
arg
);
return
internal
::
named_arg
<
T
,
char
>
(
name
,
arg
);
}
}
template
<
typename
T
>
template
<
typename
T
>
inline
internal
::
named_arg
<
T
,
wchar_t
>
arg
(
wstring_view
name
,
const
T
&
arg
)
inline
internal
::
named_arg
<
T
,
wchar_t
>
arg
(
wstring_view
name
,
const
T
&
arg
)
{
{
return
internal
::
named_arg
<
T
,
wchar_t
>
(
name
,
arg
);
return
internal
::
named_arg
<
T
,
wchar_t
>
(
name
,
arg
);
}
}
// This function template is deleted intentionally to disable nested named
// This function template is deleted intentionally to disable nested named
// arguments as in ``format("{}", arg("a", arg("b", 42)))``.
// 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
;
void
arg
(
S
,
internal
::
named_arg
<
T
,
Char
>
)
FMT_DELETED
;
enum
color
#ifndef FMT_EXTENDED_COLORS
{
// color and (v)print_colored are deprecated.
black
,
enum
color
{
black
,
red
,
green
,
yellow
,
blue
,
magenta
,
cyan
,
white
};
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
,
string_view
format
,
format_args
args
);
FMT_API
void
vprint_colored
(
color
c
,
wstring_view
format
,
wformat_args
args
);
FMT_API
void
vprint_colored
(
color
c
,
wstring_view
format
,
wformat_args
args
);
template
<
typename
...
Args
>
/**
inline
void
print_colored
(
color
c
,
string_view
format_str
,
Formats a string and prints it to stdout using ANSI escape sequences to
const
Args
&
...
args
)
{
specify color (experimental).
vprint_colored
(
c
,
format_str
,
make_format_args
(
args
...));
Example:
fmt::print_colored(fmt::RED, "Elapsed time: {0:.2f} seconds", 1.23);
*/
template
<
typename
...
Args
>
inline
void
print_colored
(
color
c
,
string_view
format_str
,
const
Args
&
...
args
)
{
vprint_colored
(
c
,
format_str
,
make_format_args
(
args
...));
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
void
print_colored
(
color
c
,
wstring_view
format_str
,
inline
void
print_colored
(
color
c
,
wstring_view
format_str
,
const
Args
&
...
args
)
const
Args
&
...
args
)
{
{
vprint_colored
(
c
,
format_str
,
make_format_args
<
wformat_context
>
(
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
);
format_context
::
iterator
vformat_to
(
wformat_context
::
iterator
vformat_to
(
internal
::
wbuffer
&
buf
,
wstring_view
format_str
,
wformat_args
args
);
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
>
template
<
typename
Container
>
struct
is_contiguous
:
std
::
false_type
struct
is_contiguous
:
std
::
false_type
{};
{
};
template
<
typename
Char
>
template
<
typename
Char
>
struct
is_contiguous
<
std
::
basic_string
<
Char
>>
:
std
::
true_type
struct
is_contiguous
<
std
::
basic_string
<
Char
>>
:
std
::
true_type
{};
{
};
template
<
typename
Char
>
template
<
typename
Char
>
struct
is_contiguous
<
internal
::
basic_buffer
<
Char
>>
:
std
::
true_type
struct
is_contiguous
<
internal
::
basic_buffer
<
Char
>>
:
std
::
true_type
{};
{
};
/** Formats a string and writes the output to ``out``. */
/** Formats a string and writes the output to ``out``. */
template
<
typename
Container
>
template
<
typename
Container
>
typename
std
::
enable_if
<
is_contiguous
<
Container
>::
value
,
std
::
back_insert_iterator
<
Container
>>::
type
vformat_to
(
typename
std
::
enable_if
<
std
::
back_insert_iterator
<
Container
>
out
,
string_view
format_str
,
format_args
args
)
is_contiguous
<
Container
>::
value
,
std
::
back_insert_iterator
<
Container
>>::
type
{
vformat_to
(
std
::
back_insert_iterator
<
Container
>
out
,
auto
&
container
=
internal
::
get_container
(
out
);
string_view
format_str
,
format_args
args
)
{
internal
::
container_buffer
<
Container
>
buf
(
container
);
auto
&
container
=
internal
::
get_container
(
out
);
vformat_to
(
buf
,
format_str
,
args
);
internal
::
container_buffer
<
Container
>
buf
(
container
);
return
std
::
back_inserter
(
container
);
vformat_to
(
buf
,
format_str
,
args
);
return
std
::
back_inserter
(
container
);
}
}
template
<
typename
Container
>
template
<
typename
Container
>
typename
std
::
enable_if
<
is_contiguous
<
Container
>::
value
,
std
::
back_insert_iterator
<
Container
>>::
type
vformat_to
(
typename
std
::
enable_if
<
std
::
back_insert_iterator
<
Container
>
out
,
wstring_view
format_str
,
wformat_args
args
)
is_contiguous
<
Container
>::
value
,
std
::
back_insert_iterator
<
Container
>>::
type
{
vformat_to
(
std
::
back_insert_iterator
<
Container
>
out
,
auto
&
container
=
internal
::
get_container
(
out
);
wstring_view
format_str
,
wformat_args
args
)
{
internal
::
container_buffer
<
Container
>
buf
(
container
);
auto
&
container
=
internal
::
get_container
(
out
);
vformat_to
(
buf
,
format_str
,
args
);
internal
::
container_buffer
<
Container
>
buf
(
container
);
return
std
::
back_inserter
(
container
);
vformat_to
(
buf
,
format_str
,
args
);
return
std
::
back_inserter
(
container
);
}
}
std
::
string
vformat
(
string_view
format_str
,
format_args
args
);
std
::
string
vformat
(
string_view
format_str
,
format_args
args
);
...
@@ -1499,20 +1262,18 @@ std::wstring vformat(wstring_view format_str, wformat_args args);
...
@@ -1499,20 +1262,18 @@ std::wstring vformat(wstring_view format_str, wformat_args args);
std::string message = fmt::format("The answer is {}", 42);
std::string message = fmt::format("The answer is {}", 42);
\endrst
\endrst
*/
*/
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
std
::
string
format
(
string_view
format_str
,
const
Args
&
...
args
)
inline
std
::
string
format
(
string_view
format_str
,
const
Args
&
...
args
)
{
{
// This should be just
// This should be just
// return vformat(format_str, make_format_args(args...));
// return vformat(format_str, make_format_args(args...));
// but gcc has trouble optimizing the latter, so break it down.
// but gcc has trouble optimizing the latter, so break it down.
format_arg_store
<
format_context
,
Args
...
>
as
{
args
...};
format_arg_store
<
format_context
,
Args
...
>
as
{
args
...};
return
vformat
(
format_str
,
as
);
return
vformat
(
format_str
,
as
);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
std
::
wstring
format
(
wstring_view
format_str
,
const
Args
&
...
args
)
inline
std
::
wstring
format
(
wstring_view
format_str
,
const
Args
&
...
args
)
{
{
format_arg_store
<
wformat_context
,
Args
...
>
as
{
args
...};
format_arg_store
<
wformat_context
,
Args
...
>
as
{
args
...};
return
vformat
(
format_str
,
as
);
return
vformat
(
format_str
,
as
);
}
}
FMT_API
void
vprint
(
std
::
FILE
*
f
,
string_view
format_str
,
format_args
args
);
FMT_API
void
vprint
(
std
::
FILE
*
f
,
string_view
format_str
,
format_args
args
);
...
@@ -1527,21 +1288,19 @@ FMT_API void vprint(std::FILE *f, wstring_view format_str, wformat_args args);
...
@@ -1527,21 +1288,19 @@ FMT_API void vprint(std::FILE *f, wstring_view format_str, wformat_args args);
fmt::print(stderr, "Don't {}!", "panic");
fmt::print(stderr, "Don't {}!", "panic");
\endrst
\endrst
*/
*/
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
void
print
(
std
::
FILE
*
f
,
string_view
format_str
,
const
Args
&
...
args
)
inline
void
print
(
std
::
FILE
*
f
,
string_view
format_str
,
const
Args
&
...
args
)
{
{
format_arg_store
<
format_context
,
Args
...
>
as
(
args
...);
format_arg_store
<
format_context
,
Args
...
>
as
(
args
...);
vprint
(
f
,
format_str
,
as
);
vprint
(
f
,
format_str
,
as
);
}
}
/**
/**
Prints formatted data to the file *f* which should be in wide-oriented mode set
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.
via ``fwide(f, 1)`` or ``_setmode(_fileno(f), _O_U8TEXT)`` on Windows.
*/
*/
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
void
print
(
std
::
FILE
*
f
,
wstring_view
format_str
,
const
Args
&
...
args
)
inline
void
print
(
std
::
FILE
*
f
,
wstring_view
format_str
,
const
Args
&
...
args
)
{
{
format_arg_store
<
wformat_context
,
Args
...
>
as
(
args
...);
format_arg_store
<
wformat_context
,
Args
...
>
as
(
args
...);
vprint
(
f
,
format_str
,
as
);
vprint
(
f
,
format_str
,
as
);
}
}
FMT_API
void
vprint
(
string_view
format_str
,
format_args
args
);
FMT_API
void
vprint
(
string_view
format_str
,
format_args
args
);
...
@@ -1556,19 +1315,17 @@ FMT_API void vprint(wstring_view format_str, wformat_args args);
...
@@ -1556,19 +1315,17 @@ FMT_API void vprint(wstring_view format_str, wformat_args args);
fmt::print("Elapsed time: {0:.2f} seconds", 1.23);
fmt::print("Elapsed time: {0:.2f} seconds", 1.23);
\endrst
\endrst
*/
*/
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
void
print
(
string_view
format_str
,
const
Args
&
...
args
)
inline
void
print
(
string_view
format_str
,
const
Args
&
...
args
)
{
{
format_arg_store
<
format_context
,
Args
...
>
as
{
args
...};
format_arg_store
<
format_context
,
Args
...
>
as
{
args
...};
vprint
(
format_str
,
as
);
vprint
(
format_str
,
as
);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
void
print
(
wstring_view
format_str
,
const
Args
&
...
args
)
inline
void
print
(
wstring_view
format_str
,
const
Args
&
...
args
)
{
{
format_arg_store
<
wformat_context
,
Args
...
>
as
(
args
...);
format_arg_store
<
wformat_context
,
Args
...
>
as
(
args
...);
vprint
(
format_str
,
as
);
vprint
(
format_str
,
as
);
}
}
FMT_END_NAMESPACE
FMT_END_NAMESPACE
#endif // FMT_CORE_H_
#endif
// FMT_CORE_H_
include/spdlog/fmt/bundled/format-inl.h
View file @
f4771be7
...
@@ -17,52 +17,50 @@
...
@@ -17,52 +17,50 @@
#include <climits>
#include <climits>
#include <cmath>
#include <cmath>
#include <cstdarg>
#include <cstdarg>
#include <cstddef> // for std::ptrdiff_t
#include <cstddef>
// for std::ptrdiff_t
#include <locale>
#include <locale>
#if defined(_WIN32) && defined(__MINGW32__)
#if defined(_WIN32) && defined(__MINGW32__)
#include <cstring>
#
include <cstring>
#endif
#endif
#if FMT_USE_WINDOWS_H
#if FMT_USE_WINDOWS_H
#if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
#
if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#
define WIN32_LEAN_AND_MEAN
#endif
#
endif
#if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
#
if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
#include <windows.h>
#
include <windows.h>
#else
#
else
#define NOMINMAX
#
define NOMINMAX
#include <windows.h>
#
include <windows.h>
#undef NOMINMAX
#
undef NOMINMAX
#endif
#
endif
#endif
#endif
#if FMT_EXCEPTIONS
#if FMT_EXCEPTIONS
#define FMT_TRY try
#
define FMT_TRY try
#define FMT_CATCH(x) catch (x)
#
define FMT_CATCH(x) catch (x)
#else
#else
#define FMT_TRY if (true)
#
define FMT_TRY if (true)
#define FMT_CATCH(x) if (false)
#
define FMT_CATCH(x) if (false)
#endif
#endif
#ifdef _MSC_VER
#ifdef _MSC_VER
#pragma warning(push)
#
pragma warning(push)
#
pragma warning(disable : 4127)
// conditional expression is constant
#
pragma warning(disable: 4127)
// conditional expression is constant
#
pragma warning(disable : 4702)
// unreachable code
#
pragma warning(disable: 4702)
// unreachable code
// Disable deprecation warning for strerror. The latter is not called but
// Disable deprecation warning for strerror. The latter is not called but
// MSVC fails to detect it.
// MSVC fails to detect it.
#
pragma warning(disable
: 4996)
#
pragma warning(disable
: 4996)
#endif
#endif
// Dummy implementations of strerror_r and strerror_s called if corresponding
// Dummy implementations of strerror_r and strerror_s called if corresponding
// system functions are not available.
// 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
<>
();
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
<>
();
return
fmt
::
internal
::
null
<>
();
}
}
FMT_BEGIN_NAMESPACE
FMT_BEGIN_NAMESPACE
...
@@ -70,28 +68,24 @@ FMT_BEGIN_NAMESPACE
...
@@ -70,28 +68,24 @@ FMT_BEGIN_NAMESPACE
namespace
{
namespace
{
#ifndef _MSC_VER
#ifndef _MSC_VER
#define FMT_SNPRINTF snprintf
# define FMT_SNPRINTF snprintf
#else // _MSC_VER
#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_list
args
;
va_start
(
args
,
format
);
va_start
(
args
,
format
);
int
result
=
vsnprintf_s
(
buffer
,
size
,
_TRUNCATE
,
format
,
args
);
int
result
=
vsnprintf_s
(
buffer
,
size
,
_TRUNCATE
,
format
,
args
);
va_end
(
args
);
va_end
(
args
);
return
result
;
return
result
;
}
}
#define FMT_SNPRINTF fmt_snprintf
#
define FMT_SNPRINTF fmt_snprintf
#endif // _MSC_VER
#endif
// _MSC_VER
#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
#define FMT_SWPRINTF snwprintf
#
define FMT_SWPRINTF snwprintf
#else
#else
#define FMT_SWPRINTF swprintf
#
define FMT_SWPRINTF swprintf
#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
#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
);
typedef
void
(
*
FormatFunc
)(
internal
::
buffer
&
,
int
,
string_view
);
// Portable thread-safe version of strerror.
// Portable thread-safe version of strerror.
...
@@ -103,432 +97,468 @@ typedef void (*FormatFunc)(internal::buffer &, int, string_view);
...
@@ -103,432 +97,468 @@ typedef void (*FormatFunc)(internal::buffer &, int, string_view);
// ERANGE - buffer is not large enough to store the error message
// ERANGE - buffer is not large enough to store the error message
// other - failure
// other - failure
// Buffer should be at least of size 1.
// 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"
);
FMT_ASSERT
(
buffer
!=
FMT_NULL
&&
buffer_size
!=
0
,
"invalid buffer"
);
class
dispatcher
class
dispatcher
{
{
private:
private:
int
error_code_
;
int
error_code_
;
char
*&
buffer_
;
char
*&
buffer_
;
std
::
size_t
buffer_size_
;
std
::
size_t
buffer_size_
;
// A noop assignment operator to avoid bogus warnings.
// A noop assignment operator to avoid bogus warnings.
void
operator
=
(
const
dispatcher
&
)
{}
void
operator
=
(
const
dispatcher
&
)
{}
// Handle the result of XSI-compliant version of strerror_r.
// 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
;
// glibc versions before 2.13 return result in errno.
}
return
result
==
-
1
?
errno
:
result
;
}
// Handle the result of GNU-specific version of strerror_r.
// 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 the buffer is full then the message is probably truncated.
if
(
message
==
buffer_
&&
strlen
(
buffer_
)
==
buffer_size_
-
1
)
if
(
message
==
buffer_
&&
strlen
(
buffer_
)
==
buffer_size_
-
1
)
return
ERANGE
;
return
ERANGE
;
buffer_
=
message
;
buffer_
=
message
;
return
0
;
return
0
;
}
}
// Handle the case when strerror_r is not available.
// 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_
));
return
fallback
(
strerror_s
(
buffer_
,
buffer_size_
,
error_code_
));
}
}
// Fallback to strerror_s when strerror_r is not available.
// 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.
// If the buffer is full then the message is probably truncated.
return
result
==
0
&&
strlen
(
buffer_
)
==
buffer_size_
-
1
?
return
result
==
0
&&
strlen
(
buffer_
)
==
buffer_size_
-
1
?
ERANGE
:
result
;
ERANGE
:
result
;
}
}
// Fallback to strerror if strerror_r and strerror_s are not available.
// Fallback to strerror if strerror_r and strerror_s are not available.
int
fallback
(
internal
::
null
<>
)
int
fallback
(
internal
::
null
<>
)
{
{
errno
=
0
;
errno
=
0
;
buffer_
=
strerror
(
error_code_
);
buffer_
=
strerror
(
error_code_
);
return
errno
;
return
errno
;
}
}
public:
public:
dispatcher
(
int
err_code
,
char
*&
buf
,
std
::
size_t
buf_size
)
dispatcher
(
int
err_code
,
char
*&
buf
,
std
::
size_t
buf_size
)
:
error_code_
(
err_code
)
:
error_code_
(
err_code
),
buffer_
(
buf
),
buffer_size_
(
buf_size
)
{}
,
buffer_
(
buf
)
,
buffer_size_
(
buf_size
)
{
}
int
run
()
int
run
()
{
{
return
handle
(
strerror_r
(
error_code_
,
buffer_
,
buffer_size_
));
return
handle
(
strerror_r
(
error_code_
,
buffer_
,
buffer_size_
));
}
}
};
};
return
dispatcher
(
error_code
,
buffer
,
buffer_size
).
run
();
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
// Report error code making sure that the output fits into
// inline_buffer_size to avoid dynamic memory allocation and potential
// inline_buffer_size to avoid dynamic memory allocation and potential
// bad_alloc.
// bad_alloc.
out
.
resize
(
0
);
out
.
resize
(
0
);
static
const
char
SEP
[]
=
": "
;
static
const
char
SEP
[]
=
": "
;
static
const
char
ERROR_STR
[]
=
"error "
;
static
const
char
ERROR_STR
[]
=
"error "
;
// Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
// Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
std
::
size_t
error_code_size
=
sizeof
(
SEP
)
+
sizeof
(
ERROR_STR
)
-
2
;
std
::
size_t
error_code_size
=
sizeof
(
SEP
)
+
sizeof
(
ERROR_STR
)
-
2
;
typedef
internal
::
int_traits
<
int
>::
main_type
main_type
;
typedef
internal
::
int_traits
<
int
>::
main_type
main_type
;
main_type
abs_value
=
static_cast
<
main_type
>
(
error_code
);
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
;
abs_value
=
0
-
abs_value
;
++
error_code_size
;
++
error_code_size
;
}
}
error_code_size
+=
internal
::
count_digits
(
abs_value
);
error_code_size
+=
internal
::
count_digits
(
abs_value
);
writer
w
(
out
);
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
);
w
.
write
(
message
);
}
w
.
write
(
SEP
);
w
.
write
(
ERROR_STR
);
}
w
.
write
(
error_code
);
w
.
write
(
ERROR_STR
);
assert
(
out
.
size
()
<=
inline_buffer_size
);
w
.
write
(
error_code
);
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
;
memory_buffer
full_message
;
func
(
full_message
,
error_code
,
message
);
func
(
full_message
,
error_code
,
message
);
// Use Writer::data instead of Writer::c_str to avoid potential memory
// Use Writer::data instead of Writer::c_str to avoid potential memory
// allocation.
// allocation.
std
::
fwrite
(
full_message
.
data
(),
full_message
.
size
(),
1
,
stderr
);
std
::
fwrite
(
full_message
.
data
(),
full_message
.
size
(),
1
,
stderr
);
std
::
fputc
(
'\n'
,
stderr
);
std
::
fputc
(
'\n'
,
stderr
);
}
}
}
// namespace
}
// namespace
class
locale
class
locale
{
{
private:
private:
std
::
locale
locale_
;
std
::
locale
locale_
;
public:
public:
explicit
locale
(
std
::
locale
loc
=
std
::
locale
())
explicit
locale
(
std
::
locale
loc
=
std
::
locale
())
:
locale_
(
loc
)
{}
:
locale_
(
loc
)
std
::
locale
get
()
{
return
locale_
;
}
{
}
std
::
locale
get
()
{
return
locale_
;
}
};
};
template
<
typename
Char
>
template
<
typename
Char
>
FMT_FUNC
Char
internal
::
thousands_sep
(
locale_provider
*
lp
)
FMT_FUNC
Char
internal
::
thousands_sep
(
locale_provider
*
lp
)
{
{
std
::
locale
loc
=
lp
?
lp
->
locale
().
get
()
:
std
::
locale
();
std
::
locale
loc
=
lp
?
lp
->
locale
().
get
()
:
std
::
locale
();
return
std
::
use_facet
<
std
::
numpunct
<
Char
>>
(
loc
).
thousands_sep
();
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
;
error_code_
=
err_code
;
memory_buffer
buffer
;
memory_buffer
buffer
;
format_system_error
(
buffer
,
err_code
,
vformat
(
format_str
,
args
));
format_system_error
(
buffer
,
err_code
,
vformat
(
format_str
,
args
));
std
::
runtime_error
&
base
=
*
this
;
std
::
runtime_error
&
base
=
*
this
;
base
=
std
::
runtime_error
(
to_string
(
buffer
));
base
=
std
::
runtime_error
(
to_string
(
buffer
));
}
}
namespace
internal
{
namespace
internal
{
template
<
typename
T
>
template
<
typename
T
>
int
char_traits
<
char
>::
format_float
(
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
int
precision
,
T
value
)
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
);
return
precision
<
0
?
FMT_SNPRINTF
(
buffer
,
size
,
format
,
value
)
:
FMT_SNPRINTF
(
buffer
,
size
,
format
,
precision
,
value
);
}
}
template
<
typename
T
>
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
)
int
char_traits
<
wchar_t
>::
format_float
(
{
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
int
precision
,
return
precision
<
0
?
FMT_SWPRINTF
(
buffer
,
size
,
format
,
value
)
:
FMT_SWPRINTF
(
buffer
,
size
,
format
,
precision
,
value
);
T
value
)
{
return
precision
<
0
?
FMT_SWPRINTF
(
buffer
,
size
,
format
,
value
)
:
FMT_SWPRINTF
(
buffer
,
size
,
format
,
precision
,
value
);
}
}
template
<
typename
T
>
template
<
typename
T
>
const
char
basic_data
<
T
>::
DIGITS
[]
=
"0001020304050607080910111213141516171819"
const
char
basic_data
<
T
>::
DIGITS
[]
=
"2021222324252627282930313233343536373839"
"0001020304050607080910111213141516171819"
"4041424344454647484950515253545556575859"
"2021222324252627282930313233343536373839"
"6061626364656667686970717273747576777879"
"4041424344454647484950515253545556575859"
"8081828384858687888990919293949596979899"
;
"6061626364656667686970717273747576777879"
"8081828384858687888990919293949596979899"
;
#define FMT_POWERS_OF_10(factor) \
factor * 10, factor * 100, factor * 1000, factor * 10000, factor * 100000, factor * 1000000, factor * 10000000, factor * 100000000, \
#define FMT_POWERS_OF_10(factor) \
factor * 1000000000
factor * 10, \
factor * 100, \
template
<
typename
T
>
factor * 1000, \
const
uint32_t
basic_data
<
T
>::
POWERS_OF_10_32
[]
=
{
0
,
FMT_POWERS_OF_10
(
1
)};
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
>
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
};
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.
// Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.
// These are generated by support/compute-powers.py.
// These are generated by support/compute-powers.py.
template
<
typename
T
>
template
<
typename
T
>
const
uint64_t
basic_data
<
T
>::
POW10_SIGNIFICANDS
[]
=
{
0xfa8fd5a0081c0288
,
0xbaaee17fa23ebf76
,
0x8b16fb203055ac76
,
0xcf42894a5dce35ea
,
const
uint64_t
basic_data
<
T
>::
POW10_SIGNIFICANDS
[]
=
{
0x9a6bb0aa55653b2d
,
0xe61acf033d1a45df
,
0xab70fe17c79ac6ca
,
0xff77b1fcbebcdc4f
,
0xbe5691ef416bd60c
,
0x8dd01fad907ffc3c
,
0xfa8fd5a0081c0288
,
0xbaaee17fa23ebf76
,
0x8b16fb203055ac76
,
0xcf42894a5dce35ea
,
0xd3515c2831559a83
,
0x9d71ac8fada6c9b5
,
0xea9c227723ee8bcb
,
0xaecc49914078536d
,
0x823c12795db6ce57
,
0xc21094364dfb5637
,
0x9a6bb0aa55653b2d
,
0xe61acf033d1a45df
,
0xab70fe17c79ac6ca
,
0xff77b1fcbebcdc4f
,
0x9096ea6f3848984f
,
0xd77485cb25823ac7
,
0xa086cfcd97bf97f4
,
0xef340a98172aace5
,
0xb23867fb2a35b28e
,
0x84c8d4dfd2c63f3b
,
0xbe5691ef416bd60c
,
0x8dd01fad907ffc3c
,
0xd3515c2831559a83
,
0x9d71ac8fada6c9b5
,
0xc5dd44271ad3cdba
,
0x936b9fcebb25c996
,
0xdbac6c247d62a584
,
0xa3ab66580d5fdaf6
,
0xf3e2f893dec3f126
,
0xb5b5ada8aaff80b8
,
0xea9c227723ee8bcb
,
0xaecc49914078536d
,
0x823c12795db6ce57
,
0xc21094364dfb5637
,
0x87625f056c7c4a8b
,
0xc9bcff6034c13053
,
0x964e858c91ba2655
,
0xdff9772470297ebd
,
0xa6dfbd9fb8e5b88f
,
0xf8a95fcf88747d94
,
0x9096ea6f3848984f
,
0xd77485cb25823ac7
,
0xa086cfcd97bf97f4
,
0xef340a98172aace5
,
0xb94470938fa89bcf
,
0x8a08f0f8bf0f156b
,
0xcdb02555653131b6
,
0x993fe2c6d07b7fac
,
0xe45c10c42a2b3b06
,
0xaa242499697392d3
,
0xb23867fb2a35b28e
,
0x84c8d4dfd2c63f3b
,
0xc5dd44271ad3cdba
,
0x936b9fcebb25c996
,
0xfd87b5f28300ca0e
,
0xbce5086492111aeb
,
0x8cbccc096f5088cc
,
0xd1b71758e219652c
,
0x9c40000000000000
,
0xe8d4a51000000000
,
0xdbac6c247d62a584
,
0xa3ab66580d5fdaf6
,
0xf3e2f893dec3f126
,
0xb5b5ada8aaff80b8
,
0xad78ebc5ac620000
,
0x813f3978f8940984
,
0xc097ce7bc90715b3
,
0x8f7e32ce7bea5c70
,
0xd5d238a4abe98068
,
0x9f4f2726179a2245
,
0x87625f056c7c4a8b
,
0xc9bcff6034c13053
,
0x964e858c91ba2655
,
0xdff9772470297ebd
,
0xed63a231d4c4fb27
,
0xb0de65388cc8ada8
,
0x83c7088e1aab65db
,
0xc45d1df942711d9a
,
0x924d692ca61be758
,
0xda01ee641a708dea
,
0xa6dfbd9fb8e5b88f
,
0xf8a95fcf88747d94
,
0xb94470938fa89bcf
,
0x8a08f0f8bf0f156b
,
0xa26da3999aef774a
,
0xf209787bb47d6b85
,
0xb454e4a179dd1877
,
0x865b86925b9bc5c2
,
0xc83553c5c8965d3d
,
0x952ab45cfa97a0b3
,
0xcdb02555653131b6
,
0x993fe2c6d07b7fac
,
0xe45c10c42a2b3b06
,
0xaa242499697392d3
,
0xde469fbd99a05fe3
,
0xa59bc234db398c25
,
0xf6c69a72a3989f5c
,
0xb7dcbf5354e9bece
,
0x88fcf317f22241e2
,
0xcc20ce9bd35c78a5
,
0xfd87b5f28300ca0e
,
0xbce5086492111aeb
,
0x8cbccc096f5088cc
,
0xd1b71758e219652c
,
0x98165af37b2153df
,
0xe2a0b5dc971f303a
,
0xa8d9d1535ce3b396
,
0xfb9b7cd9a4a7443c
,
0xbb764c4ca7a44410
,
0x8bab8eefb6409c1a
,
0x9c40000000000000
,
0xe8d4a51000000000
,
0xad78ebc5ac620000
,
0x813f3978f8940984
,
0xd01fef10a657842c
,
0x9b10a4e5e9913129
,
0xe7109bfba19c0c9d
,
0xac2820d9623bf429
,
0x80444b5e7aa7cf85
,
0xbf21e44003acdd2d
,
0xc097ce7bc90715b3
,
0x8f7e32ce7bea5c70
,
0xd5d238a4abe98068
,
0x9f4f2726179a2245
,
0x8e679c2f5e44ff8f
,
0xd433179d9c8cb841
,
0x9e19db92b4e31ba9
,
0xeb96bf6ebadf77d9
,
0xaf87023b9bf0ee6b
};
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
// Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding
// to significands above.
// to significands above.
template
<
typename
T
>
template
<
typename
T
>
const
int16_t
basic_data
<
T
>::
POW10_EXPONENTS
[]
=
{
-
1220
,
-
1193
,
-
1166
,
-
1140
,
-
1113
,
-
1087
,
-
1060
,
-
1034
,
-
1007
,
-
980
,
-
954
,
-
927
,
-
901
,
const
int16_t
basic_data
<
T
>::
POW10_EXPONENTS
[]
=
{
-
874
,
-
847
,
-
821
,
-
794
,
-
768
,
-
741
,
-
715
,
-
688
,
-
661
,
-
635
,
-
608
,
-
582
,
-
555
,
-
529
,
-
502
,
-
475
,
-
449
,
-
422
,
-
396
,
-
369
,
-
343
,
-
316
,
-
1220
,
-
1193
,
-
1166
,
-
1140
,
-
1113
,
-
1087
,
-
1060
,
-
1034
,
-
1007
,
-
980
,
-
954
,
-
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
,
-
927
,
-
901
,
-
874
,
-
847
,
-
821
,
-
794
,
-
768
,
-
741
,
-
715
,
-
688
,
-
661
,
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
};
-
635
,
-
608
,
-
582
,
-
555
,
-
529
,
-
502
,
-
475
,
-
449
,
-
422
,
-
396
,
-
369
,
-
343
,
-
316
,
-
289
,
-
263
,
-
236
,
-
210
,
-
183
,
-
157
,
-
130
,
-
103
,
-
77
,
FMT_FUNC
fp
operator
*
(
fp
x
,
fp
y
)
-
50
,
-
24
,
3
,
30
,
56
,
83
,
109
,
136
,
162
,
189
,
216
,
{
242
,
269
,
295
,
322
,
348
,
375
,
402
,
428
,
455
,
481
,
508
,
// Multiply 32-bit parts of significands.
534
,
561
,
588
,
614
,
641
,
667
,
694
,
720
,
747
,
774
,
800
,
uint64_t
mask
=
(
1ULL
<<
32
)
-
1
;
827
,
853
,
880
,
907
,
933
,
960
,
986
,
1013
,
1039
,
1066
uint64_t
a
=
x
.
f
>>
32
,
b
=
x
.
f
&
mask
;
};
uint64_t
c
=
y
.
f
>>
32
,
d
=
y
.
f
&
mask
;
uint64_t
ac
=
a
*
c
,
bc
=
b
*
c
,
ad
=
a
*
d
,
bd
=
b
*
d
;
template
<
typename
T
>
const
char
basic_data
<
T
>::
RESET_COLOR
[]
=
"
\x1b
[0m"
;
// Compute mid 64-bit of result and round.
template
<
typename
T
>
const
wchar_t
basic_data
<
T
>::
WRESET_COLOR
[]
=
L"
\x1b
[0m"
;
uint64_t
mid
=
(
bd
>>
32
)
+
(
ad
&
mask
)
+
(
bc
&
mask
)
+
(
1U
<<
31
);
return
fp
(
ac
+
(
ad
>>
32
)
+
(
bc
>>
32
)
+
(
mid
>>
32
),
x
.
e
+
y
.
e
+
64
);
FMT_FUNC
fp
operator
*
(
fp
x
,
fp
y
)
{
// Multiply 32-bit parts of significands.
uint64_t
mask
=
(
1ULL
<<
32
)
-
1
;
uint64_t
a
=
x
.
f
>>
32
,
b
=
x
.
f
&
mask
;
uint64_t
c
=
y
.
f
>>
32
,
d
=
y
.
f
&
mask
;
uint64_t
ac
=
a
*
c
,
bc
=
b
*
c
,
ad
=
a
*
d
,
bd
=
b
*
d
;
// Compute mid 64-bit of result and round.
uint64_t
mid
=
(
bd
>>
32
)
+
(
ad
&
mask
)
+
(
bc
&
mask
)
+
(
1U
<<
31
);
return
fp
(
ac
+
(
ad
>>
32
)
+
(
bc
>>
32
)
+
(
mid
>>
32
),
x
.
e
+
y
.
e
+
64
);
}
}
FMT_FUNC
fp
get_cached_power
(
int
min_exponent
,
int
&
pow10_exponent
)
FMT_FUNC
fp
get_cached_power
(
int
min_exponent
,
int
&
pow10_exponent
)
{
{
const
double
one_over_log2_10
=
0.30102999566398114
;
// 1 / log2(10)
const
double
one_over_log2_10
=
0.30102999566398114
;
// 1 / log2(10)
int
index
=
static_cast
<
int
>
(
std
::
ceil
(
int
index
=
static_cast
<
int
>
(
std
::
ceil
(
(
min_exponent
+
fp
::
significand_size
-
1
)
*
one_over_log2_10
));
(
min_exponent
+
fp
::
significand_size
-
1
)
*
one_over_log2_10
));
// Decimal exponent of the first (smallest) cached power of 10.
// Decimal exponent of the first (smallest) cached power of 10.
const
int
first_dec_exp
=
-
348
;
const
int
first_dec_exp
=
-
348
;
// Difference between two consecutive decimal exponents in cached powers of 10.
// Difference between two consecutive decimal exponents in cached powers of 10.
const
int
dec_exp_step
=
8
;
const
int
dec_exp_step
=
8
;
index
=
(
index
-
first_dec_exp
-
1
)
/
dec_exp_step
+
1
;
index
=
(
index
-
first_dec_exp
-
1
)
/
dec_exp_step
+
1
;
pow10_exponent
=
first_dec_exp
+
index
*
dec_exp_step
;
pow10_exponent
=
first_dec_exp
+
index
*
dec_exp_step
;
return
fp
(
data
::
POW10_SIGNIFICANDS
[
index
],
data
::
POW10_EXPONENTS
[
index
]);
return
fp
(
data
::
POW10_SIGNIFICANDS
[
index
],
data
::
POW10_EXPONENTS
[
index
]);
}
}
}
// namespace internal
}
// namespace internal
#if FMT_USE_WINDOWS_H
#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"
;
static
const
char
ERROR_MSG
[]
=
"cannot convert string from UTF-8 to UTF-16"
;
if
(
s
.
size
()
>
INT_MAX
)
if
(
s
.
size
()
>
INT_MAX
)
FMT_THROW
(
windows_error
(
ERROR_INVALID_PARAMETER
,
ERROR_MSG
));
FMT_THROW
(
windows_error
(
ERROR_INVALID_PARAMETER
,
ERROR_MSG
));
int
s_size
=
static_cast
<
int
>
(
s
.
size
(
));
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
);
// MultiByteToWideChar does not support zero length, handle separately.
buffer_
[
0
]
=
0
;
buffer_
.
resize
(
1
)
;
return
;
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
)
if
(
length
==
0
)
FMT_THROW
(
windows_error
(
GetLastError
(),
ERROR_MSG
));
FMT_THROW
(
windows_error
(
GetLastError
(),
ERROR_MSG
)
);
buffer_
.
resize
(
length
+
1
);
buffer_
.
resize
(
length
+
1
);
length
=
MultiByteToWideChar
(
length
=
MultiByteToWideChar
(
CP_UTF8
,
MB_ERR_INVALID_CHARS
,
s
.
data
(),
s_size
,
&
buffer_
[
0
],
length
);
CP_UTF8
,
MB_ERR_INVALID_CHARS
,
s
.
data
(),
s_size
,
&
buffer_
[
0
],
length
);
if
(
length
==
0
)
if
(
length
==
0
)
FMT_THROW
(
windows_error
(
GetLastError
(),
ERROR_MSG
));
FMT_THROW
(
windows_error
(
GetLastError
(),
ERROR_MSG
));
buffer_
[
length
]
=
0
;
buffer_
[
length
]
=
0
;
}
}
FMT_FUNC
internal
::
utf16_to_utf8
::
utf16_to_utf8
(
wstring_view
s
)
FMT_FUNC
internal
::
utf16_to_utf8
::
utf16_to_utf8
(
wstring_view
s
)
{
{
if
(
int
error_code
=
convert
(
s
))
{
if
(
int
error_code
=
convert
(
s
))
FMT_THROW
(
windows_error
(
error_code
,
{
"cannot convert string from UTF-16 to UTF-8"
));
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
)
if
(
s
.
size
()
>
INT_MAX
)
return
ERROR_INVALID_PARAMETER
;
return
ERROR_INVALID_PARAMETER
;
int
s_size
=
static_cast
<
int
>
(
s
.
size
());
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
);
// WideCharToMultiByte does not support zero length, handle separately.
buffer_
[
0
]
=
0
;
buffer_
.
resize
(
1
);
buffer_
[
0
]
=
0
;
return
0
;
}
int
length
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
s
.
data
(),
s_size
,
FMT_NULL
,
0
,
FMT_NULL
,
FMT_NULL
);
if
(
length
==
0
)
return
GetLastError
();
buffer_
.
resize
(
length
+
1
);
length
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
s
.
data
(),
s_size
,
&
buffer_
[
0
],
length
,
FMT_NULL
,
FMT_NULL
);
if
(
length
==
0
)
return
GetLastError
();
buffer_
[
length
]
=
0
;
return
0
;
return
0
;
}
int
length
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
s
.
data
(),
s_size
,
FMT_NULL
,
0
,
FMT_NULL
,
FMT_NULL
);
if
(
length
==
0
)
return
GetLastError
();
buffer_
.
resize
(
length
+
1
);
length
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
s
.
data
(),
s_size
,
&
buffer_
[
0
],
length
,
FMT_NULL
,
FMT_NULL
);
if
(
length
==
0
)
return
GetLastError
();
buffer_
[
length
]
=
0
;
return
0
;
}
}
FMT_FUNC
void
windows_error
::
init
(
int
err_code
,
string_view
format_str
,
format_args
args
)
FMT_FUNC
void
windows_error
::
init
(
{
int
err_code
,
string_view
format_str
,
format_args
args
)
{
error_code_
=
err_code
;
error_code_
=
err_code
;
memory_buffer
buffer
;
memory_buffer
buffer
;
internal
::
format_windows_error
(
buffer
,
err_code
,
vformat
(
format_str
,
args
));
internal
::
format_windows_error
(
buffer
,
err_code
,
vformat
(
format_str
,
args
));
std
::
runtime_error
&
base
=
*
this
;
std
::
runtime_error
&
base
=
*
this
;
base
=
std
::
runtime_error
(
to_string
(
buffer
));
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_FUNC
void
internal
::
format_windows_error
(
{
internal
::
buffer
&
out
,
int
error_code
,
string_view
message
)
FMT_NOEXCEPT
{
FMT_TRY
FMT_TRY
{
{
wmemory_buffer
buf
;
wmemory_buffer
buf
;
buf
.
resize
(
inline_buffer_size
);
buf
.
resize
(
inline_buffer_size
);
for
(;;)
{
for
(;;)
wchar_t
*
system_message
=
&
buf
[
0
];
{
int
result
=
FormatMessageW
(
wchar_t
*
system_message
=
&
buf
[
0
];
FORMAT_MESSAGE_FROM_SYSTEM
|
FORMAT_MESSAGE_IGNORE_INSERTS
,
int
result
=
FormatMessageW
(
FORMAT_MESSAGE_FROM_SYSTEM
|
FORMAT_MESSAGE_IGNORE_INSERTS
,
FMT_NULL
,
error_code
,
FMT_NULL
,
error_code
,
MAKELANGID
(
LANG_NEUTRAL
,
SUBLANG_DEFAULT
),
MAKELANGID
(
LANG_NEUTRAL
,
SUBLANG_DEFAULT
),
system_message
,
static_cast
<
uint32_t
>
(
buf
.
size
()),
FMT_NULL
);
system_message
,
static_cast
<
uint32_t
>
(
buf
.
size
()),
FMT_NULL
);
if
(
result
!=
0
)
if
(
result
!=
0
)
{
{
utf16_to_utf8
utf8_message
;
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
);
writer
w
(
out
);
w
.
write
(
": "
);
w
.
write
(
message
);
w
.
write
(
utf8_message
);
w
.
write
(
": "
);
return
;
w
.
write
(
utf8_message
);
return
;
}
break
;
}
if
(
GetLastError
()
!=
ERROR_INSUFFICIENT_BUFFER
)
break
;
// Can't get error message, report error code instead.
buf
.
resize
(
buf
.
size
()
*
2
);
}
}
break
;
}
if
(
GetLastError
()
!=
ERROR_INSUFFICIENT_BUFFER
)
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
);
format_error_code
(
out
,
error_code
,
message
);
}
}
#endif // FMT_USE_WINDOWS_H
#endif // FMT_USE_WINDOWS_H
FMT_FUNC
void
format_system_error
(
internal
::
buffer
&
out
,
int
error_code
,
string_view
message
)
FMT_NOEXCEPT
FMT_FUNC
void
format_system_error
(
{
internal
::
buffer
&
out
,
int
error_code
,
string_view
message
)
FMT_NOEXCEPT
{
FMT_TRY
FMT_TRY
{
{
memory_buffer
buf
;
memory_buffer
buf
;
buf
.
resize
(
inline_buffer_size
);
buf
.
resize
(
inline_buffer_size
);
for
(;;)
{
for
(;;)
char
*
system_message
=
&
buf
[
0
];
{
int
result
=
safe_strerror
(
error_code
,
system_message
,
buf
.
size
());
char
*
system_message
=
&
buf
[
0
];
if
(
result
==
0
)
{
int
result
=
safe_strerror
(
error_code
,
system_message
,
buf
.
size
());
writer
w
(
out
);
if
(
result
==
0
)
w
.
write
(
message
);
{
w
.
write
(
": "
);
writer
w
(
out
);
w
.
write
(
system_message
);
w
.
write
(
message
);
return
;
w
.
write
(
": "
);
}
w
.
write
(
system_message
);
if
(
result
!=
ERANGE
)
return
;
break
;
// Can't get error message, report error code instead.
}
buf
.
resize
(
buf
.
size
()
*
2
);
if
(
result
!=
ERANGE
)
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
);
format_error_code
(
out
,
error_code
,
message
);
}
}
template
<
typename
Char
>
template
<
typename
Char
>
void
basic_fixed_buffer
<
Char
>::
grow
(
std
::
size_t
)
void
basic_fixed_buffer
<
Char
>::
grow
(
std
::
size_t
)
{
{
FMT_THROW
(
std
::
runtime_error
(
"buffer overflow"
));
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_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
);
report_error
(
format_system_error
,
error_code
,
message
);
}
}
#if FMT_USE_WINDOWS_H
#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
);
report_error
(
internal
::
format_windows_error
,
error_code
,
message
);
}
}
#endif
#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
;
memory_buffer
buffer
;
vformat_to
(
buffer
,
format_str
,
args
);
vformat_to
(
buffer
,
format_str
,
args
);
std
::
fwrite
(
buffer
.
data
(),
1
,
buffer
.
size
(),
f
);
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
;
wmemory_buffer
buffer
;
vformat_to
(
buffer
,
format_str
,
args
);
vformat_to
(
buffer
,
format_str
,
args
);
std
::
fwrite
(
buffer
.
data
(),
sizeof
(
wchar_t
),
buffer
.
size
(),
f
);
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
);
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
);
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"
;
char
escape
[]
=
"
\x1b
[30m"
;
escape
[
3
]
=
static_cast
<
char
>
(
'0'
+
c
);
escape
[
3
]
=
static_cast
<
char
>
(
'0'
+
c
);
std
::
fputs
(
escape
,
stdout
);
std
::
fputs
(
escape
,
stdout
);
vprint
(
format
,
args
);
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
)
{
wchar_t
escape
[]
=
L"
\x1b
[30m"
;
escape
[
3
]
=
static_cast
<
wchar_t
>
(
'0'
+
c
);
std
::
fputws
(
escape
,
stdout
);
vprint
(
format
,
args
);
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
void
vprint_colored
(
color
c
,
wstring_view
format
,
wformat_args
args
)
FMT_FUNC
void
vprint_rgb
(
rgb
fd
,
string_view
format
,
format_args
args
)
{
{
char
escape_fd
[]
=
"
\x1b
[38;2;000;000;000m"
;
wchar_t
escape
[]
=
L"
\x1b
[30m"
;
internal
::
to_esc
(
fd
.
r
,
escape_fd
,
7
);
escape
[
3
]
=
static_cast
<
wchar_t
>
(
'0'
+
c
);
internal
::
to_esc
(
fd
.
g
,
escape_fd
,
11
);
std
::
fputws
(
escape
,
stdout
);
internal
::
to_esc
(
fd
.
b
,
escape_fd
,
15
);
vprint
(
format
,
args
);
std
::
fputws
(
WRESET_COLOR
,
stdout
);
std
::
fputs
(
escape_fd
,
stdout
);
vprint
(
format
,
args
);
std
::
fputs
(
internal
::
data
::
RESET_COLOR
,
stdout
);
}
}
FMT_FUNC
locale
locale_provider
::
locale
()
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
return
fmt
::
locale
();
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
FMT_END_NAMESPACE
#ifdef _MSC_VER
#ifdef _MSC_VER
#pragma warning(pop)
#
pragma warning(pop)
#endif
#endif
#endif // FMT_FORMAT_INL_H_
#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,137 +14,128 @@
...
@@ -14,137 +14,128 @@
FMT_BEGIN_NAMESPACE
FMT_BEGIN_NAMESPACE
namespace
internal
{
namespace
internal
{
template
<
class
Char
>
template
<
class
Char
>
class
formatbuf
:
public
std
::
basic_streambuf
<
Char
>
class
formatbuf
:
public
std
::
basic_streambuf
<
Char
>
{
{
private:
private:
typedef
typename
std
::
basic_streambuf
<
Char
>::
int_type
int_type
;
typedef
typename
std
::
basic_streambuf
<
Char
>::
int_type
int_type
;
typedef
typename
std
::
basic_streambuf
<
Char
>::
traits_type
traits_type
;
typedef
typename
std
::
basic_streambuf
<
Char
>::
traits_type
traits_type
;
basic_buffer
<
Char
>
&
buffer_
;
basic_buffer
<
Char
>
&
buffer_
;
public:
public:
formatbuf
(
basic_buffer
<
Char
>
&
buffer
)
:
buffer_
(
buffer
)
{}
formatbuf
(
basic_buffer
<
Char
>
&
buffer
)
:
buffer_
(
buffer
)
protected:
{
// The put-area is actually always empty. This makes the implementation
}
// simpler and has the advantage that the streambuf and the buffer are always
// in sync and sputc never writes into uninitialized memory. The obvious
protected:
// disadvantage is that each call to sputc always results in a (virtual) call
// The put-area is actually always empty. This makes the implementation
// to overflow. There is no disadvantage here for sputn since this always
// simpler and has the advantage that the streambuf and the buffer are always
// results in a call to xsputn.
// in sync and sputc never writes into uninitialized memory. The obvious
// disadvantage is that each call to sputc always results in a (virtual) call
int_type
overflow
(
int_type
ch
=
traits_type
::
eof
())
FMT_OVERRIDE
{
// to overflow. There is no disadvantage here for sputn since this always
if
(
!
traits_type
::
eq_int_type
(
ch
,
traits_type
::
eof
()))
// results in a call to xsputn.
buffer_
.
push_back
(
static_cast
<
Char
>
(
ch
));
return
ch
;
int_type
overflow
(
int_type
ch
=
traits_type
::
eof
())
FMT_OVERRIDE
}
{
if
(
!
traits_type
::
eq_int_type
(
ch
,
traits_type
::
eof
()))
std
::
streamsize
xsputn
(
const
Char
*
s
,
std
::
streamsize
count
)
FMT_OVERRIDE
{
buffer_
.
push_back
(
static_cast
<
Char
>
(
ch
));
buffer_
.
append
(
s
,
s
+
count
);
return
ch
;
return
count
;
}
}
std
::
streamsize
xsputn
(
const
Char
*
s
,
std
::
streamsize
count
)
FMT_OVERRIDE
{
buffer_
.
append
(
s
,
s
+
count
);
return
count
;
}
};
};
template
<
typename
Char
>
template
<
typename
Char
>
struct
test_stream
:
std
::
basic_ostream
<
Char
>
struct
test_stream
:
std
::
basic_ostream
<
Char
>
{
{
private:
private:
struct
null
;
struct
null
;
// Hide all operator<< from std::basic_ostream<Char>.
// Hide all operator<< from std::basic_ostream<Char>.
void
operator
<<
(
null
);
void
operator
<<
(
null
);
};
};
// Checks if T has a user-defined operator<< (e.g. not a member of std::ostream).
// Checks if T has a user-defined operator<< (e.g. not a member of std::ostream).
template
<
typename
T
,
typename
Char
>
template
<
typename
T
,
typename
Char
>
class
is_streamable
class
is_streamable
{
{
private:
private:
template
<
typename
U
>
template
<
typename
U
>
static
decltype
(
static
decltype
(
internal
::
declval
<
test_stream
<
Char
>
&>
()
<<
internal
::
declval
<
U
>
(),
std
::
true_type
())
test
(
int
);
internal
::
declval
<
test_stream
<
Char
>&>
()
<<
internal
::
declval
<
U
>
(),
std
::
true_type
())
test
(
int
);
template
<
typename
>
static
std
::
false_type
test
(...);
template
<
typename
>
static
std
::
false_type
test
(...);
typedef
decltype
(
test
<
T
>
(
0
))
result
;
typedef
decltype
(
test
<
T
>
(
0
))
result
;
public:
// std::string operator<< is not considered user-defined because we handle strings
public:
// specially.
// std::string operator<< is not considered user-defined because we handle strings
static
const
bool
value
=
result
::
value
&&
!
std
::
is_same
<
T
,
std
::
string
>::
value
;
// specially.
static
const
bool
value
=
result
::
value
&&
!
std
::
is_same
<
T
,
std
::
string
>::
value
;
};
};
// Disable conversion to int if T has an overloaded operator<< which is a free
// Disable conversion to int if T has an overloaded operator<< which is a free
// function (not a member of std::ostream).
// function (not a member of std::ostream).
template
<
typename
T
,
typename
Char
>
template
<
typename
T
,
typename
Char
>
class
convert_to_int
<
T
,
Char
,
true
>
class
convert_to_int
<
T
,
Char
,
true
>
{
{
public:
public:
static
const
bool
value
=
static
const
bool
value
=
convert_to_int
<
T
,
Char
,
false
>::
value
&&
!
is_streamable
<
T
,
Char
>::
value
;
convert_to_int
<
T
,
Char
,
false
>::
value
&&
!
is_streamable
<
T
,
Char
>::
value
;
};
};
// Write the content of buf to os.
// Write the content of buf to os.
template
<
typename
Char
>
template
<
typename
Char
>
void
write
(
std
::
basic_ostream
<
Char
>
&
os
,
basic_buffer
<
Char
>
&
buf
)
void
write
(
std
::
basic_ostream
<
Char
>
&
os
,
basic_buffer
<
Char
>
&
buf
)
{
{
const
Char
*
data
=
buf
.
data
();
const
Char
*
data
=
buf
.
data
();
typedef
std
::
make_unsigned
<
std
::
streamsize
>::
type
UnsignedStreamSize
;
typedef
std
::
make_unsigned
<
std
::
streamsize
>::
type
UnsignedStreamSize
;
UnsignedStreamSize
size
=
buf
.
size
();
UnsignedStreamSize
size
=
buf
.
size
();
UnsignedStreamSize
max_size
=
UnsignedStreamSize
max_size
=
internal
::
to_unsigned
((
std
::
numeric_limits
<
std
::
streamsize
>::
max
)());
internal
::
to_unsigned
((
std
::
numeric_limits
<
std
::
streamsize
>::
max
)());
do
do
{
{
UnsignedStreamSize
n
=
size
<=
max_size
?
size
:
max_size
;
UnsignedStreamSize
n
=
size
<=
max_size
?
size
:
max_size
;
os
.
write
(
data
,
static_cast
<
std
::
streamsize
>
(
n
));
os
.
write
(
data
,
static_cast
<
std
::
streamsize
>
(
n
));
data
+=
n
;
data
+=
n
;
size
-=
n
;
size
-=
n
;
}
while
(
size
!=
0
);
}
while
(
size
!=
0
);
}
}
template
<
typename
Char
,
typename
T
>
template
<
typename
Char
,
typename
T
>
void
format_value
(
basic_buffer
<
Char
>
&
buffer
,
const
T
&
value
)
void
format_value
(
basic_buffer
<
Char
>
&
buffer
,
const
T
&
value
)
{
{
internal
::
formatbuf
<
Char
>
format_buf
(
buffer
);
internal
::
formatbuf
<
Char
>
format_buf
(
buffer
);
std
::
basic_ostream
<
Char
>
output
(
&
format_buf
);
std
::
basic_ostream
<
Char
>
output
(
&
format_buf
);
output
.
exceptions
(
std
::
ios_base
::
failbit
|
std
::
ios_base
::
badbit
);
output
.
exceptions
(
std
::
ios_base
::
failbit
|
std
::
ios_base
::
badbit
);
output
<<
value
;
output
<<
value
;
buffer
.
resize
(
buffer
.
size
());
buffer
.
resize
(
buffer
.
size
());
}
}
// Disable builtin formatting of enums and use operator<< instead.
// Disable builtin formatting of enums and use operator<< instead.
template
<
typename
T
>
template
<
typename
T
>
struct
format_enum
<
T
,
typename
std
::
enable_if
<
std
::
is_enum
<
T
>::
value
>::
type
>
:
std
::
false_type
struct
format_enum
<
T
,
{
typename
std
::
enable_if
<
std
::
is_enum
<
T
>::
value
>::
type
>
:
std
::
false_type
{};
};
}
// namespace internal
}
// namespace internal
// Formats an object of type T that has an overloaded ostream operator<<.
// Formats an object of type T that has an overloaded ostream operator<<.
template
<
typename
T
,
typename
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
>
struct
formatter
<
T
,
Char
,
{
typename
std
::
enable_if
<
internal
::
is_streamable
<
T
,
Char
>::
value
>::
type
>
:
formatter
<
basic_string_view
<
Char
>
,
Char
>
{
template
<
typename
Context
>
auto
format
(
const
T
&
value
,
Context
&
ctx
)
->
decltype
(
ctx
.
out
())
{
basic_memory_buffer
<
Char
>
buffer
;
internal
::
format_value
(
buffer
,
value
);
basic_string_view
<
Char
>
str
(
buffer
.
data
(),
buffer
.
size
());
formatter
<
basic_string_view
<
Char
>
,
Char
>::
format
(
str
,
ctx
);
return
ctx
.
out
();
}
};
template
<
typename
Char
>
template
<
typename
Context
>
inline
void
vprint
(
auto
format
(
const
T
&
value
,
Context
&
ctx
)
->
decltype
(
ctx
.
out
())
{
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
;
basic_memory_buffer
<
Char
>
buffer
;
vformat_to
(
buffer
,
format_str
,
args
);
internal
::
format_value
(
buffer
,
value
);
internal
::
write
(
os
,
buffer
);
basic_string_view
<
Char
>
str
(
buffer
.
data
(),
buffer
.
size
());
formatter
<
basic_string_view
<
Char
>
,
Char
>::
format
(
str
,
ctx
);
return
ctx
.
out
();
}
};
template
<
typename
Char
>
inline
void
vprint
(
std
::
basic_ostream
<
Char
>
&
os
,
basic_string_view
<
Char
>
format_str
,
basic_format_args
<
typename
buffer_context
<
Char
>::
type
>
args
)
{
basic_memory_buffer
<
Char
>
buffer
;
vformat_to
(
buffer
,
format_str
,
args
);
internal
::
write
(
os
,
buffer
);
}
}
/**
/**
\rst
\rst
...
@@ -155,17 +146,17 @@ inline void vprint(
...
@@ -155,17 +146,17 @@ inline void vprint(
fmt::print(cerr, "Don't {}!", "panic");
fmt::print(cerr, "Don't {}!", "panic");
\endrst
\endrst
*/
*/
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
void
print
(
std
::
ostream
&
os
,
string_view
format_str
,
const
Args
&
...
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
...));
vprint
<
char
>
(
os
,
format_str
,
make_format_args
<
format_context
>
(
args
...));
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
void
print
(
std
::
wostream
&
os
,
wstring_view
format_str
,
const
Args
&
...
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
...));
vprint
<
wchar_t
>
(
os
,
format_str
,
make_format_args
<
wformat_context
>
(
args
...));
}
}
FMT_END_NAMESPACE
FMT_END_NAMESPACE
#endif // FMT_OSTREAM_H_
#endif
// FMT_OSTREAM_H_
include/spdlog/fmt/bundled/posix.h
View file @
f4771be7
...
@@ -10,55 +10,54 @@
...
@@ -10,55 +10,54 @@
#if defined(__MINGW32__) || defined(__CYGWIN__)
#if defined(__MINGW32__) || defined(__CYGWIN__)
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
#undef __STRICT_ANSI__
#
undef __STRICT_ANSI__
#endif
#endif
#include <errno.h>
#include <errno.h>
#include <fcntl.h> // for O_RDONLY
#include <fcntl.h>
// for O_RDONLY
#include <locale.h> // for locale_t
#include <locale.h>
// for locale_t
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h> // for strtod_l
#include <stdlib.h>
// for strtod_l
#include <cstddef>
#include <cstddef>
#if defined __APPLE__ || defined(__FreeBSD__)
#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
#endif
#include "format.h"
#include "format.h"
#ifndef FMT_POSIX
#ifndef FMT_POSIX
#if defined(_WIN32) && !defined(__MINGW32__)
#
if defined(_WIN32) && !defined(__MINGW32__)
// Fix warnings about deprecated symbols.
// Fix warnings about deprecated symbols.
#define FMT_POSIX(call) _##call
#
define FMT_POSIX(call) _##call
#else
#
else
#define FMT_POSIX(call) call
#
define FMT_POSIX(call) call
#endif
#
endif
#endif
#endif
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
#ifdef FMT_SYSTEM
#ifdef FMT_SYSTEM
#define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
#
define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
#else
#else
#define FMT_SYSTEM(call) call
#
define FMT_SYSTEM(call) call
#ifdef _WIN32
#
ifdef _WIN32
// Fix warnings about deprecated symbols.
// Fix warnings about deprecated symbols.
#define FMT_POSIX_CALL(call) ::_##call
#
define FMT_POSIX_CALL(call) ::_##call
#else
#
else
#define FMT_POSIX_CALL(call) ::call
#
define FMT_POSIX_CALL(call) ::call
#endif
#
endif
#endif
#endif
// Retries the expression while it evaluates to error_result and errno
// Retries the expression while it evaluates to error_result and errno
// equals to EINTR.
// equals to EINTR.
#ifndef _WIN32
#ifndef _WIN32
#define FMT_RETRY_VAL(result, expression, error_result) \
# define FMT_RETRY_VAL(result, expression, error_result) \
do \
do { \
{ \
result = (expression); \
result = (expression); \
} while (result == error_result && errno == EINTR)
} while (result == error_result && errno == EINTR)
#else
#else
#define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#
define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#endif
#endif
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
...
@@ -90,167 +89,137 @@ FMT_BEGIN_NAMESPACE
...
@@ -90,167 +89,137 @@ FMT_BEGIN_NAMESPACE
format(std::string("{}"), 42);
format(std::string("{}"), 42);
\endrst
\endrst
*/
*/
template
<
typename
Char
>
template
<
typename
Char
>
class
basic_cstring_view
class
basic_cstring_view
{
{
private:
private:
const
Char
*
data_
;
const
Char
*
data_
;
public:
public:
/** Constructs a string reference object from a C string. */
/** 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
/**
*/
\rst
basic_cstring_view
(
const
std
::
basic_string
<
Char
>
&
s
)
:
data_
(
s
.
c_str
())
{}
Constructs a string reference from an ``std::string`` object.
\endrst
/** Returns the pointer to a C string. */
*/
const
Char
*
c_str
()
const
{
return
data_
;
}
basic_cstring_view
(
const
std
::
basic_string
<
Char
>
&
s
)
:
data_
(
s
.
c_str
())
{
}
/** Returns the pointer to a C string. */
const
Char
*
c_str
()
const
{
return
data_
;
}
};
};
typedef
basic_cstring_view
<
char
>
cstring_view
;
typedef
basic_cstring_view
<
char
>
cstring_view
;
typedef
basic_cstring_view
<
wchar_t
>
wcstring_view
;
typedef
basic_cstring_view
<
wchar_t
>
wcstring_view
;
// An error code.
// An error code.
class
error_code
class
error_code
{
{
private:
private:
int
value_
;
int
value_
;
public:
public:
explicit
error_code
(
int
value
=
0
)
FMT_NOEXCEPT
:
value_
(
value
)
{}
explicit
error_code
(
int
value
=
0
)
FMT_NOEXCEPT
:
value_
(
value
)
{}
int
get
()
const
FMT_NOEXCEPT
int
get
()
const
FMT_NOEXCEPT
{
return
value_
;
}
{
return
value_
;
}
};
};
// A buffered file.
// A buffered file.
class
buffered_file
class
buffered_file
{
{
private:
private:
FILE
*
file_
;
FILE
*
file_
;
friend
class
file
;
friend
class
file
;
explicit
buffered_file
(
FILE
*
f
)
explicit
buffered_file
(
FILE
*
f
)
:
file_
(
f
)
{}
:
file_
(
f
)
{
}
public:
public:
// Constructs a buffered_file object which doesn't represent any file.
// Constructs a buffered_file object which doesn't represent any file.
buffered_file
()
FMT_NOEXCEPT
:
file_
(
FMT_NULL
)
{}
buffered_file
()
FMT_NOEXCEPT
:
file_
(
FMT_NULL
)
{}
// Destroys the object closing the file it represents if any.
// Destroys the object closing the file it represents if any.
FMT_API
~
buffered_file
()
FMT_DTOR_NOEXCEPT
;
FMT_API
~
buffered_file
()
FMT_DTOR_NOEXCEPT
;
#if !FMT_USE_RVALUE_REFERENCES
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
// references are not supported.
private:
private:
// A proxy object to emulate a move constructor.
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
// It is private to make it impossible call operator Proxy directly.
struct
Proxy
struct
Proxy
{
{
FILE
*
file
;
FILE
*
file
;
};
};
public:
public:
// A "move constructor" for moving from a temporary.
// A "move constructor" for moving from a temporary.
buffered_file
(
Proxy
p
)
FMT_NOEXCEPT
:
file_
(
p
.
file
)
{}
buffered_file
(
Proxy
p
)
FMT_NOEXCEPT
:
file_
(
p
.
file
)
{}
// A "move constructor" for moving from an lvalue.
// 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
;
f
.
file_
=
FMT_NULL
;
}
}
// A "move assignment operator" for moving from a temporary.
// A "move assignment operator" for moving from a temporary.
buffered_file
&
operator
=
(
Proxy
p
)
{
buffered_file
&
operator
=
(
Proxy
p
)
close
();
{
file_
=
p
.
file
;
close
();
return
*
this
;
file_
=
p
.
file
;
}
return
*
this
;
}
// A "move assignment operator" for moving from an lvalue.
buffered_file
&
operator
=
(
buffered_file
&
other
)
{
// A "move assignment operator" for moving from an lvalue.
close
();
buffered_file
&
operator
=
(
buffered_file
&
other
)
file_
=
other
.
file_
;
{
other
.
file_
=
FMT_NULL
;
close
();
return
*
this
;
file_
=
other
.
file_
;
}
other
.
file_
=
FMT_NULL
;
return
*
this
;
// Returns a proxy object for moving from a temporary:
}
// buffered_file file = buffered_file(...);
operator
Proxy
()
FMT_NOEXCEPT
{
// Returns a proxy object for moving from a temporary:
Proxy
p
=
{
file_
};
// buffered_file file = buffered_file(...);
file_
=
FMT_NULL
;
operator
Proxy
()
FMT_NOEXCEPT
return
p
;
{
}
Proxy
p
=
{
file_
};
file_
=
FMT_NULL
;
return
p
;
}
#else
#else
private:
private:
FMT_DISALLOW_COPY_AND_ASSIGN
(
buffered_file
);
FMT_DISALLOW_COPY_AND_ASSIGN
(
buffered_file
);
public:
public:
buffered_file
(
buffered_file
&&
other
)
FMT_NOEXCEPT
:
file_
(
other
.
file_
)
buffered_file
(
buffered_file
&&
other
)
FMT_NOEXCEPT
:
file_
(
other
.
file_
)
{
{
other
.
file_
=
FMT_NULL
;
other
.
file_
=
FMT_NULL
;
}
}
buffered_file
&
operator
=
(
buffered_file
&&
other
)
{
buffered_file
&
operator
=
(
buffered_file
&&
other
)
close
();
{
file_
=
other
.
file_
;
close
();
other
.
file_
=
FMT_NULL
;
file_
=
other
.
file_
;
return
*
this
;
other
.
file_
=
FMT_NULL
;
}
return
*
this
;
}
#endif
#endif
// Opens a file.
// Opens a file.
FMT_API
buffered_file
(
cstring_view
filename
,
cstring_view
mode
);
FMT_API
buffered_file
(
cstring_view
filename
,
cstring_view
mode
);
// Closes the file.
// Closes the file.
FMT_API
void
close
();
FMT_API
void
close
();
// Returns the pointer to a FILE object representing this file.
// Returns the pointer to a FILE object representing this file.
FILE
*
get
()
const
FMT_NOEXCEPT
FILE
*
get
()
const
FMT_NOEXCEPT
{
return
file_
;
}
{
return
file_
;
}
// We place parentheses around fileno to workaround a bug in some versions
// We place parentheses around fileno to workaround a bug in some versions
// of MinGW that define fileno as a macro.
// 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
);
fmt
::
vprint
(
file_
,
format_str
,
args
);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
void
print
(
string_view
format_str
,
const
Args
&
...
args
)
inline
void
print
(
string_view
format_str
,
const
Args
&
...
args
)
{
{
vprint
(
format_str
,
make_format_args
(
args
...));
vprint
(
format_str
,
make_format_args
(
args
...));
}
}
};
};
// A file. Closed file is represented by a file object with descriptor -1.
// A file. Closed file is represented by a file object with descriptor -1.
...
@@ -259,226 +228,190 @@ public:
...
@@ -259,226 +228,190 @@ public:
// closing the file multiple times will cause a crash on Windows rather
// closing the file multiple times will cause a crash on Windows rather
// than an exception. You can get standard behavior by overriding the
// than an exception. You can get standard behavior by overriding the
// invalid parameter handler with _set_invalid_parameter_handler.
// invalid parameter handler with _set_invalid_parameter_handler.
class
file
class
file
{
{
private:
private:
int
fd_
;
// File descriptor.
int
fd_
;
// File descriptor.
// Constructs a file object with a given descriptor.
// Constructs a file object with a given descriptor.
explicit
file
(
int
fd
)
explicit
file
(
int
fd
)
:
fd_
(
fd
)
{}
:
fd_
(
fd
)
{
}
public:
public:
// Possible values for the oflag argument to the constructor.
// Possible values for the oflag argument to the constructor.
enum
enum
{
{
RDONLY
=
FMT_POSIX
(
O_RDONLY
),
// Open for reading only.
RDONLY
=
FMT_POSIX
(
O_RDONLY
),
// Open for reading only.
WRONLY
=
FMT_POSIX
(
O_WRONLY
),
// Open for writing only.
WRONLY
=
FMT_POSIX
(
O_WRONLY
),
// Open for writing only.
RDWR
=
FMT_POSIX
(
O_RDWR
)
// Open for reading and writing.
RDWR
=
FMT_POSIX
(
O_RDWR
)
// Open for reading and writing.
};
};
// Constructs a file object which doesn't represent any file.
// Constructs a file object which doesn't represent any file.
file
()
FMT_NOEXCEPT
:
fd_
(
-
1
)
{}
file
()
FMT_NOEXCEPT
:
fd_
(
-
1
)
{}
// Opens a file and constructs a file object representing this file.
// Opens a file and constructs a file object representing this file.
FMT_API
file
(
cstring_view
path
,
int
oflag
);
FMT_API
file
(
cstring_view
path
,
int
oflag
);
#if !FMT_USE_RVALUE_REFERENCES
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
// references are not supported.
private:
private:
// A proxy object to emulate a move constructor.
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
// It is private to make it impossible call operator Proxy directly.
struct
Proxy
struct
Proxy
{
{
int
fd
;
int
fd
;
};
};
public:
public:
// A "move constructor" for moving from a temporary.
// A "move constructor" for moving from a temporary.
file
(
Proxy
p
)
FMT_NOEXCEPT
:
fd_
(
p
.
fd
)
{}
file
(
Proxy
p
)
FMT_NOEXCEPT
:
fd_
(
p
.
fd
)
{}
// A "move constructor" for moving from an lvalue.
// 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
;
{
}
other
.
fd_
=
-
1
;
}
// A "move assignment operator" for moving from a temporary.
file
&
operator
=
(
Proxy
p
)
{
// A "move assignment operator" for moving from a temporary.
close
();
file
&
operator
=
(
Proxy
p
)
fd_
=
p
.
fd
;
{
return
*
this
;
close
();
}
fd_
=
p
.
fd
;
return
*
this
;
// A "move assignment operator" for moving from an lvalue.
}
file
&
operator
=
(
file
&
other
)
{
close
();
// A "move assignment operator" for moving from an lvalue.
fd_
=
other
.
fd_
;
file
&
operator
=
(
file
&
other
)
other
.
fd_
=
-
1
;
{
return
*
this
;
close
();
}
fd_
=
other
.
fd_
;
other
.
fd_
=
-
1
;
// Returns a proxy object for moving from a temporary:
return
*
this
;
// file f = file(...);
}
operator
Proxy
()
FMT_NOEXCEPT
{
Proxy
p
=
{
fd_
};
// Returns a proxy object for moving from a temporary:
fd_
=
-
1
;
// file f = file(...);
return
p
;
operator
Proxy
()
FMT_NOEXCEPT
}
{
Proxy
p
=
{
fd_
};
fd_
=
-
1
;
return
p
;
}
#else
#else
private:
private:
FMT_DISALLOW_COPY_AND_ASSIGN
(
file
);
FMT_DISALLOW_COPY_AND_ASSIGN
(
file
);
public:
public:
file
(
file
&&
other
)
FMT_NOEXCEPT
:
fd_
(
other
.
fd_
)
file
(
file
&&
other
)
FMT_NOEXCEPT
:
fd_
(
other
.
fd_
)
{
{
other
.
fd_
=
-
1
;
other
.
fd_
=
-
1
;
}
}
file
&
operator
=
(
file
&&
other
)
{
file
&
operator
=
(
file
&&
other
)
close
();
{
fd_
=
other
.
fd_
;
close
();
other
.
fd_
=
-
1
;
fd_
=
other
.
fd_
;
return
*
this
;
other
.
fd_
=
-
1
;
}
return
*
this
;
}
#endif
#endif
// Destroys the object closing the file it represents if any.
// Destroys the object closing the file it represents if any.
FMT_API
~
file
()
FMT_DTOR_NOEXCEPT
;
FMT_API
~
file
()
FMT_DTOR_NOEXCEPT
;
// Returns the file descriptor.
// Returns the file descriptor.
int
descriptor
()
const
FMT_NOEXCEPT
int
descriptor
()
const
FMT_NOEXCEPT
{
return
fd_
;
}
{
return
fd_
;
}
// Closes the file.
// Closes the file.
FMT_API
void
close
();
FMT_API
void
close
();
// Returns the file size. The size has signed type for consistency with
// Returns the file size. The size has signed type for consistency with
// stat::st_size.
// stat::st_size.
FMT_API
long
long
size
()
const
;
FMT_API
long
long
size
()
const
;
// Attempts to read count bytes from the file into the specified buffer.
// Attempts to read count bytes from the file into the specified buffer.
FMT_API
std
::
size_t
read
(
void
*
buffer
,
std
::
size_t
count
);
FMT_API
std
::
size_t
read
(
void
*
buffer
,
std
::
size_t
count
);
// Attempts to write count bytes from the specified buffer to the file.
// Attempts to write count bytes from the specified buffer to the file.
FMT_API
std
::
size_t
write
(
const
void
*
buffer
,
std
::
size_t
count
);
FMT_API
std
::
size_t
write
(
const
void
*
buffer
,
std
::
size_t
count
);
// Duplicates a file descriptor with the dup function and returns
// Duplicates a file descriptor with the dup function and returns
// the duplicate as a file object.
// the duplicate as a file object.
FMT_API
static
file
dup
(
int
fd
);
FMT_API
static
file
dup
(
int
fd
);
// Makes fd be the copy of this file descriptor, closing fd first if
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
// necessary.
FMT_API
void
dup2
(
int
fd
);
FMT_API
void
dup2
(
int
fd
);
// Makes fd be the copy of this file descriptor, closing fd first if
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
// necessary.
FMT_API
void
dup2
(
int
fd
,
error_code
&
ec
)
FMT_NOEXCEPT
;
FMT_API
void
dup2
(
int
fd
,
error_code
&
ec
)
FMT_NOEXCEPT
;
// Creates a pipe setting up read_end and write_end file objects for reading
// Creates a pipe setting up read_end and write_end file objects for reading
// and writing respectively.
// and writing respectively.
FMT_API
static
void
pipe
(
file
&
read_end
,
file
&
write_end
);
FMT_API
static
void
pipe
(
file
&
read_end
,
file
&
write_end
);
// Creates a buffered_file object associated with this file and detaches
// Creates a buffered_file object associated with this file and detaches
// this file object from the file.
// this file object from the file.
FMT_API
buffered_file
fdopen
(
const
char
*
mode
);
FMT_API
buffered_file
fdopen
(
const
char
*
mode
);
};
};
// Returns the memory page size.
// Returns the memory page size.
long
getpagesize
();
long
getpagesize
();
#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && !defined(__ANDROID__) && !defined(__CYGWIN__) && !defined(__OpenBSD__)
#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \
#define FMT_LOCALE
!defined(__ANDROID__) && !defined(__CYGWIN__) && !defined(__OpenBSD__)
# define FMT_LOCALE
#endif
#endif
#ifdef FMT_LOCALE
#ifdef FMT_LOCALE
// A "C" numeric locale.
// A "C" numeric locale.
class
Locale
class
Locale
{
{
private:
private:
# ifdef _MSC_VER
#ifdef _MSC_VER
typedef
_locale_t
locale_t
;
typedef
_locale_t
locale_t
;
enum
{
LC_NUMERIC_MASK
=
LC_NUMERIC
};
static
locale_t
newlocale
(
int
category_mask
,
const
char
*
locale
,
locale_t
)
{
return
_create_locale
(
category_mask
,
locale
);
}
static
void
freelocale
(
locale_t
locale
)
{
_free_locale
(
locale
);
}
static
double
strtod_l
(
const
char
*
nptr
,
char
**
endptr
,
_locale_t
locale
)
{
return
_strtod_l
(
nptr
,
endptr
,
locale
);
}
#endif
locale_t
locale_
;
enum
{
LC_NUMERIC_MASK
=
LC_NUMERIC
}
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
Locale
);
static
locale_t
newlocale
(
int
category_mask
,
const
char
*
locale
,
locale_t
)
{
return
_create_locale
(
category_mask
,
locale
);
}
public:
static
void
freelocale
(
locale_t
locale
)
{
typedef
locale_t
Type
;
_free_locale
(
locale
);
}
Locale
()
:
locale_
(
newlocale
(
LC_NUMERIC_MASK
,
"C"
,
FMT_NULL
))
static
double
strtod_l
(
const
char
*
nptr
,
char
**
endptr
,
_locale_t
locale
)
{
{
return
_strtod_l
(
nptr
,
endptr
,
locale
);
if
(
!
locale_
)
}
FMT_THROW
(
system_error
(
errno
,
"cannot create locale"
));
# endif
}
~
Locale
()
locale_t
locale_
;
{
freelocale
(
locale_
);
FMT_DISALLOW_COPY_AND_ASSIGN
(
Locale
);
}
public:
Type
get
()
const
typedef
locale_t
Type
;
{
return
locale_
;
Locale
()
:
locale_
(
newlocale
(
LC_NUMERIC_MASK
,
"C"
,
FMT_NULL
))
{
}
if
(
!
locale_
)
FMT_THROW
(
system_error
(
errno
,
"cannot create locale"
));
// Converts string to floating-point number and advances str past the end
}
// of the parsed input.
~
Locale
()
{
freelocale
(
locale_
);
}
double
strtod
(
const
char
*&
str
)
const
{
Type
get
()
const
{
return
locale_
;
}
char
*
end
=
FMT_NULL
;
double
result
=
strtod_l
(
str
,
&
end
,
locale_
);
// Converts string to floating-point number and advances str past the end
str
=
end
;
// of the parsed input.
return
result
;
double
strtod
(
const
char
*&
str
)
const
{
}
char
*
end
=
FMT_NULL
;
double
result
=
strtod_l
(
str
,
&
end
,
locale_
);
str
=
end
;
return
result
;
}
};
};
#endif // FMT_LOCALE
#endif
// FMT_LOCALE
FMT_END_NAMESPACE
FMT_END_NAMESPACE
#if !FMT_USE_RVALUE_REFERENCES
#if !FMT_USE_RVALUE_REFERENCES
namespace
std
{
namespace
std
{
// For compatibility with C++98.
// For compatibility with C++98.
inline
fmt
::
buffered_file
&
move
(
fmt
::
buffered_file
&
f
)
inline
fmt
::
buffered_file
&
move
(
fmt
::
buffered_file
&
f
)
{
return
f
;
}
{
inline
fmt
::
file
&
move
(
fmt
::
file
&
f
)
{
return
f
;
}
return
f
;
}
inline
fmt
::
file
&
move
(
fmt
::
file
&
f
)
{
return
f
;
}
}
}
// namespace std
#endif
#endif
#endif // FMT_POSIX_H_
#endif
// FMT_POSIX_H_
include/spdlog/fmt/bundled/printf.h
View file @
f4771be7
...
@@ -8,8 +8,8 @@
...
@@ -8,8 +8,8 @@
#ifndef FMT_PRINTF_H_
#ifndef FMT_PRINTF_H_
#define FMT_PRINTF_H_
#define FMT_PRINTF_H_
#include <algorithm> // std::fill_n
#include <algorithm>
// std::fill_n
#include <limits> // std::numeric_limits
#include <limits>
// std::numeric_limits
#include "ostream.h"
#include "ostream.h"
...
@@ -18,231 +18,193 @@ namespace internal {
...
@@ -18,231 +18,193 @@ namespace internal {
// Checks if a value fits in int - used to avoid warnings about comparing
// Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers.
// signed and unsigned integers.
template
<
bool
IsSigned
>
template
<
bool
IsSigned
>
struct
int_checker
struct
int_checker
{
{
template
<
typename
T
>
template
<
typename
T
>
static
bool
fits_in_int
(
T
value
)
{
static
bool
fits_in_int
(
T
value
)
unsigned
max
=
std
::
numeric_limits
<
int
>::
max
();
{
return
value
<=
max
;
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
<
>
template
<
>
struct
int_checker
<
true
>
struct
int_checker
<
true
>
{
{
template
<
typename
T
>
template
<
typename
T
>
static
bool
fits_in_int
(
T
value
)
{
static
bool
fits_in_int
(
T
value
)
return
value
>=
std
::
numeric_limits
<
int
>::
min
()
&&
{
value
<=
std
::
numeric_limits
<
int
>::
max
();
return
value
>=
std
::
numeric_limits
<
int
>::
min
()
&&
value
<=
std
::
numeric_limits
<
int
>::
max
();
}
}
static
bool
fits_in_int
(
int
)
{
return
true
;
}
static
bool
fits_in_int
(
int
)
{
return
true
;
}
};
};
class
printf_precision_handler
:
public
function
<
int
>
class
printf_precision_handler
:
public
function
<
int
>
{
{
public:
public:
template
<
typename
T
>
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
int
>::
type
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
int
>::
type
operator
()(
T
value
)
operator
()(
T
value
)
{
{
if
(
!
int_checker
<
std
::
numeric_limits
<
T
>::
is_signed
>::
fits_in_int
(
value
))
if
(
!
int_checker
<
std
::
numeric_limits
<
T
>::
is_signed
>::
fits_in_int
(
value
))
FMT_THROW
(
format_error
(
"number is too big"
));
FMT_THROW
(
format_error
(
"number is too big"
));
return
static_cast
<
int
>
(
value
);
return
static_cast
<
int
>
(
value
);
}
}
template
<
typename
T
>
template
<
typename
T
>
typename
std
::
enable_if
<!
std
::
is_integral
<
T
>::
value
,
int
>::
type
operator
()(
T
)
{
typename
std
::
enable_if
<!
std
::
is_integral
<
T
>::
value
,
int
>::
type
operator
()(
T
)
FMT_THROW
(
format_error
(
"precision is not integer"
));
{
return
0
;
FMT_THROW
(
format_error
(
"precision is not integer"
));
}
return
0
;
}
};
};
// An argument visitor that returns true iff arg is a zero integer.
// An argument visitor that returns true iff arg is a zero integer.
class
is_zero_int
:
public
function
<
bool
>
class
is_zero_int
:
public
function
<
bool
>
{
{
public:
public:
template
<
typename
T
>
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
bool
>::
type
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
bool
>::
type
operator
()(
T
value
)
operator
()(
T
value
)
{
return
value
==
0
;
}
{
return
value
==
0
;
template
<
typename
T
>
}
typename
std
::
enable_if
<!
std
::
is_integral
<
T
>::
value
,
bool
>::
type
operator
()(
T
)
{
return
false
;
}
template
<
typename
T
>
typename
std
::
enable_if
<!
std
::
is_integral
<
T
>::
value
,
bool
>::
type
operator
()(
T
)
{
return
false
;
}
};
};
template
<
typename
T
>
template
<
typename
T
>
struct
make_unsigned_or_bool
:
std
::
make_unsigned
<
T
>
struct
make_unsigned_or_bool
:
std
::
make_unsigned
<
T
>
{};
{
};
template
<
>
template
<
>
struct
make_unsigned_or_bool
<
bool
>
struct
make_unsigned_or_bool
<
bool
>
{
{
typedef
bool
type
;
typedef
bool
type
;
};
};
template
<
typename
T
,
typename
Context
>
template
<
typename
T
,
typename
Context
>
class
arg_converter
:
public
function
<
void
>
class
arg_converter
:
public
function
<
void
>
{
{
private:
private:
typedef
typename
Context
::
char_type
Char
;
typedef
typename
Context
::
char_type
Char
;
basic_format_arg
<
Context
>
&
arg_
;
basic_format_arg
<
Context
>
&
arg_
;
typename
Context
::
char_type
type_
;
typename
Context
::
char_type
type_
;
public:
public:
arg_converter
(
basic_format_arg
<
Context
>
&
arg
,
Char
type
)
arg_converter
(
basic_format_arg
<
Context
>
&
arg
,
Char
type
)
:
arg_
(
arg
),
type_
(
type
)
{}
:
arg_
(
arg
)
,
type_
(
type
)
void
operator
()(
bool
value
)
{
{
if
(
type_
!=
's'
)
}
operator
()
<
bool
>
(
value
);
}
void
operator
()(
bool
value
)
{
template
<
typename
U
>
if
(
type_
!=
's'
)
typename
std
::
enable_if
<
std
::
is_integral
<
U
>::
value
>::
type
operator
()
<
bool
>
(
value
);
operator
()(
U
value
)
{
}
bool
is_signed
=
type_
==
'd'
||
type_
==
'i'
;
typedef
typename
std
::
conditional
<
template
<
typename
U
>
std
::
is_same
<
T
,
void
>::
value
,
U
,
T
>::
type
TargetType
;
typename
std
::
enable_if
<
std
::
is_integral
<
U
>::
value
>::
type
operator
()(
U
value
)
if
(
const_check
(
sizeof
(
TargetType
)
<=
sizeof
(
int
)))
{
{
// Extra casts are used to silence warnings.
bool
is_signed
=
type_
==
'd'
||
type_
==
'i'
;
if
(
is_signed
)
{
typedef
typename
std
::
conditional
<
std
::
is_same
<
T
,
void
>::
value
,
U
,
T
>::
type
TargetType
;
arg_
=
internal
::
make_arg
<
Context
>
(
if
(
const_check
(
sizeof
(
TargetType
)
<=
sizeof
(
int
)))
static_cast
<
int
>
(
static_cast
<
TargetType
>
(
value
)));
{
}
else
{
// Extra casts are used to silence warnings.
typedef
typename
make_unsigned_or_bool
<
TargetType
>::
type
Unsigned
;
if
(
is_signed
)
arg_
=
internal
::
make_arg
<
Context
>
(
{
static_cast
<
unsigned
>
(
static_cast
<
Unsigned
>
(
value
)));
arg_
=
internal
::
make_arg
<
Context
>
(
static_cast
<
int
>
(
static_cast
<
TargetType
>
(
value
)));
}
}
}
else
{
else
if
(
is_signed
)
{
{
// glibc's printf doesn't sign extend arguments of smaller types:
typedef
typename
make_unsigned_or_bool
<
TargetType
>::
type
Unsigned
;
// std::printf("%lld", -42); // prints "4294967254"
arg_
=
internal
::
make_arg
<
Context
>
(
static_cast
<
unsigned
>
(
static_cast
<
Unsigned
>
(
value
)));
// 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
{
else
arg_
=
internal
::
make_arg
<
Context
>
(
{
static_cast
<
typename
make_unsigned_or_bool
<
U
>::
type
>
(
value
));
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.
template
<
typename
U
>
arg_
=
internal
::
make_arg
<
Context
>
(
static_cast
<
long
long
>
(
value
));
typename
std
::
enable_if
<!
std
::
is_integral
<
U
>::
value
>::
type
operator
()(
U
)
{
}
// No coversion needed for non-integral types.
else
}
{
arg_
=
internal
::
make_arg
<
Context
>
(
static_cast
<
typename
make_unsigned_or_bool
<
U
>::
type
>
(
value
));
}
}
}
template
<
typename
U
>
typename
std
::
enable_if
<!
std
::
is_integral
<
U
>::
value
>::
type
operator
()(
U
)
{
// No coversion needed for non-integral types.
}
};
};
// Converts an integer argument to T for printf, if T is an integral type.
// Converts an integer argument to T for printf, if T is an integral type.
// If T is void, the argument is converted to corresponding signed or unsigned
// If T is void, the argument is converted to corresponding signed or unsigned
// type depending on the type specifier: 'd' and 'i' - signed, other -
// type depending on the type specifier: 'd' and 'i' - signed, other -
// unsigned).
// unsigned).
template
<
typename
T
,
typename
Context
,
typename
Char
>
template
<
typename
T
,
typename
Context
,
typename
Char
>
void
convert_arg
(
basic_format_arg
<
Context
>
&
arg
,
Char
type
)
void
convert_arg
(
basic_format_arg
<
Context
>
&
arg
,
Char
type
)
{
{
visit
(
arg_converter
<
T
,
Context
>
(
arg
,
type
),
arg
);
visit
(
arg_converter
<
T
,
Context
>
(
arg
,
type
),
arg
);
}
}
// Converts an integer argument to char for printf.
// Converts an integer argument to char for printf.
template
<
typename
Context
>
template
<
typename
Context
>
class
char_converter
:
public
function
<
void
>
class
char_converter
:
public
function
<
void
>
{
{
private:
private:
basic_format_arg
<
Context
>
&
arg_
;
basic_format_arg
<
Context
>
&
arg_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
char_converter
);
public:
explicit
char_converter
(
basic_format_arg
<
Context
>
&
arg
)
:
arg_
(
arg
)
{
}
template
<
typename
T
>
FMT_DISALLOW_COPY_AND_ASSIGN
(
char_converter
);
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
>
public:
typename
std
::
enable_if
<!
std
::
is_integral
<
T
>::
value
>::
type
operator
()(
T
)
explicit
char_converter
(
basic_format_arg
<
Context
>
&
arg
)
:
arg_
(
arg
)
{}
{
// No coversion needed for non-integral types.
template
<
typename
T
>
}
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
>::
type
operator
()(
T
value
)
{
typedef
typename
Context
::
char_type
Char
;
arg_
=
internal
::
make_arg
<
Context
>
(
static_cast
<
Char
>
(
value
));
}
template
<
typename
T
>
typename
std
::
enable_if
<!
std
::
is_integral
<
T
>::
value
>::
type
operator
()(
T
)
{
// No coversion needed for non-integral types.
}
};
};
// Checks if an argument is a valid printf width specifier and sets
// Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative.
// left alignment if it is negative.
template
<
typename
Char
>
template
<
typename
Char
>
class
printf_width_handler
:
public
function
<
unsigned
>
class
printf_width_handler
:
public
function
<
unsigned
>
{
{
private:
private:
typedef
basic_format_specs
<
Char
>
format_specs
;
typedef
basic_format_specs
<
Char
>
format_specs
;
format_specs
&
spec_
;
format_specs
&
spec_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
printf_width_handler
);
FMT_DISALLOW_COPY_AND_ASSIGN
(
printf_width_handler
);
public:
public:
explicit
printf_width_handler
(
format_specs
&
spec
)
:
spec_
(
spec
)
{}
explicit
printf_width_handler
(
format_specs
&
spec
)
:
spec_
(
spec
)
template
<
typename
T
>
{
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
unsigned
>::
type
}
operator
()(
T
value
)
{
typedef
typename
internal
::
int_traits
<
T
>::
main_type
UnsignedType
;
template
<
typename
T
>
UnsignedType
width
=
static_cast
<
UnsignedType
>
(
value
);
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
unsigned
>::
type
operator
()(
T
value
)
if
(
internal
::
is_negative
(
value
))
{
{
spec_
.
align_
=
ALIGN_LEFT
;
typedef
typename
internal
::
int_traits
<
T
>::
main_type
UnsignedType
;
width
=
0
-
width
;
UnsignedType
width
=
static_cast
<
UnsignedType
>
(
value
);
}
if
(
internal
::
is_negative
(
value
))
unsigned
int_max
=
std
::
numeric_limits
<
int
>::
max
();
{
if
(
width
>
int_max
)
spec_
.
align_
=
ALIGN_LEFT
;
FMT_THROW
(
format_error
(
"number is too big"
));
width
=
0
-
width
;
return
static_cast
<
unsigned
>
(
width
);
}
}
unsigned
int_max
=
std
::
numeric_limits
<
int
>::
max
();
if
(
width
>
int_max
)
template
<
typename
T
>
FMT_THROW
(
format_error
(
"number is too big"
));
typename
std
::
enable_if
<!
std
::
is_integral
<
T
>::
value
,
unsigned
>::
type
return
static_cast
<
unsigned
>
(
width
);
operator
()(
T
)
{
}
FMT_THROW
(
format_error
(
"width is not integer"
));
return
0
;
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
}
// namespace internal
template
<
typename
Range
>
template
<
typename
Range
>
class
printf_arg_formatter
;
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
;
class
basic_printf_context
;
/**
/**
...
@@ -250,406 +212,385 @@ class basic_printf_context;
...
@@ -250,406 +212,385 @@ class basic_printf_context;
The ``printf`` argument formatter.
The ``printf`` argument formatter.
\endrst
\endrst
*/
*/
template
<
typename
Range
>
template
<
typename
Range
>
class
printf_arg_formatter
:
public
internal
::
function
<
typename
internal
::
arg_formatter_base
<
Range
>::
iterator
>
,
class
printf_arg_formatter
:
public
internal
::
arg_formatter_base
<
Range
>
public
internal
::
function
<
{
typename
internal
::
arg_formatter_base
<
Range
>::
iterator
>
,
private:
public
internal
::
arg_formatter_base
<
Range
>
{
typedef
typename
Range
::
value_type
char_type
;
private:
typedef
decltype
(
internal
::
declval
<
Range
>
().
begin
())
iterator
;
typedef
typename
Range
::
value_type
char_type
;
typedef
internal
::
arg_formatter_base
<
Range
>
base
;
typedef
decltype
(
internal
::
declval
<
Range
>
().
begin
())
iterator
;
typedef
basic_printf_context
<
iterator
,
char_type
>
context_type
;
typedef
internal
::
arg_formatter_base
<
Range
>
base
;
typedef
basic_printf_context
<
iterator
,
char_type
>
context_type
;
context_type
&
context_
;
context_type
&
context_
;
void
write_null_pointer
(
char
)
{
void
write_null_pointer
(
char
)
{
this
->
spec
().
type_
=
0
;
this
->
spec
().
type_
=
0
;
this
->
write
(
"(nil)"
);
this
->
write
(
"(nil)"
);
}
}
void
write_null_pointer
(
wchar_t
)
void
write_null_pointer
(
wchar_t
)
{
{
this
->
spec
().
type_
=
0
;
this
->
spec
().
type_
=
0
;
this
->
write
(
L"(nil)"
);
this
->
write
(
L"(nil)"
);
}
}
public:
public:
typedef
typename
base
::
format_specs
format_specs
;
typedef
typename
base
::
format_specs
format_specs
;
/**
/**
\rst
\rst
Constructs an argument formatter object.
Constructs an argument formatter object.
*buffer* is a reference to the output buffer and *spec* contains format
*buffer* is a reference to the output buffer and *spec* contains format
specifier information for standard argument types.
specifier information for standard argument types.
\endrst
\endrst
*/
*/
printf_arg_formatter
(
internal
::
basic_buffer
<
char_type
>
&
buffer
,
printf_arg_formatter
(
internal
::
basic_buffer
<
char_type
>
&
buffer
,
format_specs
&
spec
,
context_type
&
ctx
)
format_specs
&
spec
,
context_type
&
ctx
)
:
base
(
back_insert_range
<
internal
::
basic_buffer
<
char_type
>>
(
buffer
),
spec
)
:
base
(
back_insert_range
<
internal
::
basic_buffer
<
char_type
>>
(
buffer
),
spec
),
,
context_
(
ctx
)
context_
(
ctx
)
{}
{
}
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
iterator
>::
type
using
base
::
operator
();
operator
()(
T
value
)
{
// MSVC2013 fails to compile separate overloads for bool and char_type so
/** Formats an argument of type ``bool``. */
// use std::is_same instead.
iterator
operator
()(
bool
value
)
if
(
std
::
is_same
<
T
,
bool
>::
value
)
{
{
format_specs
&
fmt_spec
=
this
->
spec
();
format_specs
&
fmt_spec
=
this
->
spec
();
if
(
fmt_spec
.
type_
!=
's'
)
if
(
fmt_spec
.
type_
!=
's'
)
return
base
::
operator
()(
value
?
1
:
0
);
return
(
*
this
)(
value
?
1
:
0
);
fmt_spec
.
type_
=
0
;
fmt_spec
.
type_
=
0
;
this
->
write
(
value
!=
0
);
this
->
write
(
value
);
}
else
if
(
std
::
is_same
<
T
,
char_type
>::
value
)
{
return
this
->
out
();
format_specs
&
fmt_spec
=
this
->
spec
();
}
if
(
fmt_spec
.
type_
&&
fmt_spec
.
type_
!=
'c'
)
return
(
*
this
)(
static_cast
<
int
>
(
value
));
/** Formats a character. */
fmt_spec
.
flags_
=
0
;
iterator
operator
()(
char_type
value
)
fmt_spec
.
align_
=
ALIGN_RIGHT
;
{
return
base
::
operator
()(
value
);
format_specs
&
fmt_spec
=
this
->
spec
();
}
else
{
if
(
fmt_spec
.
type_
&&
fmt_spec
.
type_
!=
'c'
)
return
base
::
operator
()(
value
);
return
(
*
this
)(
static_cast
<
int
>
(
value
));
}
fmt_spec
.
flags_
=
0
;
return
this
->
out
();
fmt_spec
.
align_
=
ALIGN_RIGHT
;
}
return
base
::
operator
()(
value
);
}
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_floating_point
<
T
>::
value
,
iterator
>::
type
/** Formats a null-terminated C string. */
operator
()(
T
value
)
{
iterator
operator
()(
const
char
*
value
)
return
base
::
operator
()(
value
);
{
}
if
(
value
)
base
::
operator
()(
value
);
/** Formats a null-terminated C string. */
else
if
(
this
->
spec
().
type_
==
'p'
)
iterator
operator
()(
const
char
*
value
)
{
write_null_pointer
(
char_type
());
if
(
value
)
else
base
::
operator
()(
value
);
this
->
write
(
"(null)"
);
else
if
(
this
->
spec
().
type_
==
'p'
)
return
this
->
out
();
write_null_pointer
(
char_type
());
}
else
this
->
write
(
"(null)"
);
/** Formats a null-terminated wide C string. */
return
this
->
out
();
iterator
operator
()(
const
wchar_t
*
value
)
}
{
if
(
value
)
/** Formats a null-terminated wide C string. */
base
::
operator
()(
value
);
iterator
operator
()(
const
wchar_t
*
value
)
{
else
if
(
this
->
spec
().
type_
==
'p'
)
if
(
value
)
write_null_pointer
(
char_type
());
base
::
operator
()(
value
);
else
else
if
(
this
->
spec
().
type_
==
'p'
)
this
->
write
(
L"(null)"
);
write_null_pointer
(
char_type
());
return
this
->
out
();
else
}
this
->
write
(
L"(null)"
);
return
this
->
out
();
/** Formats a pointer. */
}
iterator
operator
()(
const
void
*
value
)
{
iterator
operator
()(
basic_string_view
<
char_type
>
value
)
{
if
(
value
)
return
base
::
operator
()(
value
);
return
base
::
operator
()(
value
);
}
this
->
spec
().
type_
=
0
;
write_null_pointer
(
char_type
());
iterator
operator
()(
monostate
value
)
{
return
this
->
out
();
return
base
::
operator
()(
value
);
}
}
/** Formats an argument of a custom (user-defined) type. */
/** Formats a pointer. */
iterator
operator
()(
typename
basic_format_arg
<
context_type
>::
handle
handle
)
iterator
operator
()(
const
void
*
value
)
{
{
if
(
value
)
handle
.
format
(
context_
);
return
base
::
operator
()(
value
);
return
this
->
out
();
this
->
spec
().
type_
=
0
;
}
write_null_pointer
(
char_type
());
return
this
->
out
();
}
/** Formats an argument of a custom (user-defined) type. */
iterator
operator
()(
typename
basic_format_arg
<
context_type
>::
handle
handle
)
{
handle
.
format
(
context_
);
return
this
->
out
();
}
};
};
template
<
typename
T
>
template
<
typename
T
>
struct
printf_formatter
struct
printf_formatter
{
{
template
<
typename
ParseContext
>
template
<
typename
ParseContext
>
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
{
return
ctx
.
begin
();
}
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
{
return
ctx
.
begin
();
}
template
<
typename
FormatContext
>
template
<
typename
FormatContext
>
auto
format
(
const
T
&
value
,
FormatContext
&
ctx
)
->
decltype
(
ctx
.
out
())
auto
format
(
const
T
&
value
,
FormatContext
&
ctx
)
->
decltype
(
ctx
.
out
())
{
{
internal
::
format_value
(
internal
::
get_container
(
ctx
.
out
()),
value
);
internal
::
format_value
(
internal
::
get_container
(
ctx
.
out
()),
value
);
return
ctx
.
out
();
return
ctx
.
out
();
}
}
};
};
/** This template formats data and writes the output to a writer. */
/** This template formats data and writes the output to a writer. */
template
<
typename
OutputIt
,
typename
Char
,
typename
ArgFormatter
>
template
<
typename
OutputIt
,
typename
Char
,
typename
ArgFormatter
>
class
basic_printf_context
:
private
internal
::
context_base
<
OutputIt
,
basic_printf_context
<
OutputIt
,
Char
,
ArgFormatter
>
,
Char
>
class
basic_printf_context
:
{
private
internal
::
context_base
<
public:
OutputIt
,
basic_printf_context
<
OutputIt
,
Char
,
ArgFormatter
>
,
Char
>
{
/** The character type for the output. */
public:
typedef
Char
char_type
;
/** The character type for the output. */
typedef
Char
char_type
;
template
<
typename
T
>
struct
formatter_type
template
<
typename
T
>
{
struct
formatter_type
{
typedef
printf_formatter
<
T
>
type
;
};
typedef
printf_formatter
<
T
>
type
;
};
private:
typedef
internal
::
context_base
<
OutputIt
,
basic_printf_context
,
Char
>
base
;
private:
typedef
typename
base
::
format_arg
format_arg
;
typedef
internal
::
context_base
<
OutputIt
,
basic_printf_context
,
Char
>
base
;
typedef
basic_format_specs
<
char_type
>
format_specs
;
typedef
typename
base
::
format_arg
format_arg
;
typedef
internal
::
null_terminating_iterator
<
char_type
>
iterator
;
typedef
basic_format_specs
<
char_type
>
format_specs
;
typedef
internal
::
null_terminating_iterator
<
char_type
>
iterator
;
void
parse_flags
(
format_specs
&
spec
,
iterator
&
it
);
void
parse_flags
(
format_specs
&
spec
,
iterator
&
it
);
// Returns the argument with specified index or, if arg_index is equal
// to the maximum unsigned value, the next argument.
// Returns the argument with specified index or, if arg_index is equal
format_arg
get_arg
(
// to the maximum unsigned value, the next argument.
iterator
it
,
format_arg
get_arg
(
iterator
it
,
unsigned
arg_index
=
(
std
::
numeric_limits
<
unsigned
>::
max
)());
unsigned
arg_index
=
(
std
::
numeric_limits
<
unsigned
>::
max
)());
// Parses argument index, flags and width and returns the argument index.
// Parses argument index, flags and width and returns the argument index.
unsigned
parse_header
(
iterator
&
it
,
format_specs
&
spec
);
unsigned
parse_header
(
iterator
&
it
,
format_specs
&
spec
);
public:
public:
/**
/**
\rst
\rst
Constructs a ``printf_context`` object. References to the arguments and
Constructs a ``printf_context`` object. References to the arguments and
the writer are stored in the context object so make sure they have
the writer are stored in the context object so make sure they have
appropriate lifetimes.
appropriate lifetimes.
\endrst
\endrst
*/
*/
basic_printf_context
(
OutputIt
out
,
basic_string_view
<
char_type
>
format_str
,
basic_format_args
<
basic_printf_context
>
args
)
basic_printf_context
(
OutputIt
out
,
basic_string_view
<
char_type
>
format_str
,
:
base
(
out
,
format_str
,
args
)
basic_format_args
<
basic_printf_context
>
args
)
{
:
base
(
out
,
format_str
,
args
)
{}
}
using
base
::
parse_context
;
using
base
::
advance_to
;
using
base
::
out
;
using
base
::
out
;
using
base
::
advance_to
;
using
base
::
parse_context
;
/** Formats stored arguments and writes the output to the range. */
/** Formats stored arguments and writes the output to the range. */
void
format
();
void
format
();
};
};
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
void
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
parse_flags
(
format_specs
&
spec
,
iterator
&
it
)
void
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
parse_flags
(
{
format_specs
&
spec
,
iterator
&
it
)
{
for
(;;)
for
(;;)
{
{
switch
(
*
it
++
)
{
switch
(
*
it
++
)
case
'-'
:
{
spec
.
align_
=
ALIGN_LEFT
;
case
'-'
:
break
;
spec
.
align_
=
ALIGN_LEFT
;
case
'+'
:
break
;
spec
.
flags_
|=
SIGN_FLAG
|
PLUS_FLAG
;
case
'+'
:
break
;
spec
.
flags_
|=
SIGN_FLAG
|
PLUS_FLAG
;
case
'0'
:
break
;
spec
.
fill_
=
'0'
;
case
'0'
:
break
;
spec
.
fill_
=
'0'
;
case
' '
:
break
;
spec
.
flags_
|=
SIGN_FLAG
;
case
' '
:
break
;
spec
.
flags_
|=
SIGN_FLAG
;
case
'#'
:
break
;
spec
.
flags_
|=
HASH_FLAG
;
case
'#'
:
break
;
spec
.
flags_
|=
HASH_FLAG
;
default:
break
;
--
it
;
default:
return
;
--
it
;
}
return
;
}
}
}
}
}
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
typename
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
format_arg
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
get_arg
(
typename
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
format_arg
iterator
it
,
unsigned
arg_index
)
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
get_arg
(
{
iterator
it
,
unsigned
arg_index
)
{
(
void
)
it
;
(
void
)
it
;
if
(
arg_index
==
std
::
numeric_limits
<
unsigned
>::
max
())
if
(
arg_index
==
std
::
numeric_limits
<
unsigned
>::
max
())
return
this
->
do_get_arg
(
this
->
parse_context
().
next_arg_id
());
return
this
->
do_get_arg
(
this
->
parse_context
().
next_arg_id
());
return
base
::
get_arg
(
arg_index
-
1
);
return
base
::
get_arg
(
arg_index
-
1
);
}
}
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
unsigned
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
parse_header
(
iterator
&
it
,
format_specs
&
spec
)
unsigned
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
parse_header
(
{
iterator
&
it
,
format_specs
&
spec
)
{
unsigned
arg_index
=
std
::
numeric_limits
<
unsigned
>::
max
();
unsigned
arg_index
=
std
::
numeric_limits
<
unsigned
>::
max
();
char_type
c
=
*
it
;
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
// Parse an argument index (if followed by '$') or a width possibly
// preceded with '0' flag(s).
// preceded with '0' flag(s).
internal
::
error_handler
eh
;
internal
::
error_handler
eh
;
unsigned
value
=
parse_nonnegative_int
(
it
,
eh
);
unsigned
value
=
parse_nonnegative_int
(
it
,
eh
);
if
(
*
it
==
'$'
)
{
// value is an argument index
if
(
*
it
==
'$'
)
++
it
;
{
// value is an argument index
arg_index
=
value
;
++
it
;
}
else
{
arg_index
=
value
;
if
(
c
==
'0'
)
}
spec
.
fill_
=
'0'
;
else
if
(
value
!=
0
)
{
{
// Nonzero value means that we parsed width and don't need to
if
(
c
==
'0'
)
// parse it or flags again, so return now.
spec
.
fill_
=
'0'
;
spec
.
width_
=
value
;
if
(
value
!=
0
)
return
arg_index
;
{
}
// Nonzero value means that we parsed width and don't need to
}
// parse it or flags again, so return now.
}
spec
.
width_
=
value
;
parse_flags
(
spec
,
it
);
return
arg_index
;
// Parse width.
}
if
(
*
it
>=
'0'
&&
*
it
<=
'9'
)
{
}
internal
::
error_handler
eh
;
}
spec
.
width_
=
parse_nonnegative_int
(
it
,
eh
);
parse_flags
(
spec
,
it
);
}
else
if
(
*
it
==
'*'
)
{
// Parse width.
++
it
;
if
(
*
it
>=
'0'
&&
*
it
<=
'9'
)
spec
.
width_
=
{
visit
(
internal
::
printf_width_handler
<
char_type
>
(
spec
),
get_arg
(
it
));
internal
::
error_handler
eh
;
}
spec
.
width_
=
parse_nonnegative_int
(
it
,
eh
);
return
arg_index
;
}
else
if
(
*
it
==
'*'
)
{
++
it
;
spec
.
width_
=
visit
(
internal
::
printf_width_handler
<
char_type
>
(
spec
),
get_arg
(
it
));
}
return
arg_index
;
}
}
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
void
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
format
()
void
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
format
()
{
{
auto
&
buffer
=
internal
::
get_container
(
this
->
out
());
auto
&
buffer
=
internal
::
get_container
(
this
->
out
());
auto
start
=
iterator
(
this
->
parse_context
());
auto
start
=
iterator
(
this
->
parse_context
());
auto
it
=
start
;
auto
it
=
start
;
using
internal
::
pointer_from
;
using
internal
::
pointer_from
;
while
(
*
it
)
{
while
(
*
it
)
char_type
c
=
*
it
++
;
{
if
(
c
!=
'%'
)
continue
;
char_type
c
=
*
it
++
;
if
(
*
it
==
c
)
{
if
(
c
!=
'%'
)
buffer
.
append
(
pointer_from
(
start
),
pointer_from
(
it
));
continue
;
start
=
++
it
;
if
(
*
it
==
c
)
continue
;
{
}
buffer
.
append
(
pointer_from
(
start
),
pointer_from
(
it
));
buffer
.
append
(
pointer_from
(
start
),
pointer_from
(
it
)
-
1
);
start
=
++
it
;
continue
;
format_specs
spec
;
}
spec
.
align_
=
ALIGN_RIGHT
;
buffer
.
append
(
pointer_from
(
start
),
pointer_from
(
it
)
-
1
);
// Parse argument index, flags and width.
format_specs
spec
;
unsigned
arg_index
=
parse_header
(
it
,
spec
);
spec
.
align_
=
ALIGN_RIGHT
;
// Parse precision.
// Parse argument index, flags and width.
if
(
*
it
==
'.'
)
{
unsigned
arg_index
=
parse_header
(
it
,
spec
);
++
it
;
if
(
'0'
<=
*
it
&&
*
it
<=
'9'
)
{
// Parse precision.
internal
::
error_handler
eh
;
if
(
*
it
==
'.'
)
spec
.
precision_
=
static_cast
<
int
>
(
parse_nonnegative_int
(
it
,
eh
));
{
}
else
if
(
*
it
==
'*'
)
{
++
it
;
++
it
;
if
(
'0'
<=
*
it
&&
*
it
<=
'9'
)
spec
.
precision_
=
{
visit
(
internal
::
printf_precision_handler
(),
get_arg
(
it
));
internal
::
error_handler
eh
;
}
else
{
spec
.
precision_
=
static_cast
<
int
>
(
parse_nonnegative_int
(
it
,
eh
));
spec
.
precision_
=
0
;
}
}
else
if
(
*
it
==
'*'
)
}
{
++
it
;
format_arg
arg
=
get_arg
(
it
,
arg_index
);
spec
.
precision_
=
visit
(
internal
::
printf_precision_handler
(),
get_arg
(
it
));
if
(
spec
.
flag
(
HASH_FLAG
)
&&
visit
(
internal
::
is_zero_int
(),
arg
))
}
spec
.
flags_
&=
~
internal
::
to_unsigned
<
int
>
(
HASH_FLAG
);
else
if
(
spec
.
fill_
==
'0'
)
{
{
if
(
arg
.
is_arithmetic
())
spec
.
precision_
=
0
;
spec
.
align_
=
ALIGN_NUMERIC
;
}
else
}
spec
.
fill_
=
' '
;
// Ignore '0' flag for non-numeric types.
}
format_arg
arg
=
get_arg
(
it
,
arg_index
);
if
(
spec
.
flag
(
HASH_FLAG
)
&&
visit
(
internal
::
is_zero_int
(),
arg
))
// Parse length and convert the argument to the required type.
spec
.
flags_
&=
~
internal
::
to_unsigned
<
int
>
(
HASH_FLAG
);
using
internal
::
convert_arg
;
if
(
spec
.
fill_
==
'0'
)
switch
(
*
it
++
)
{
{
case
'h'
:
if
(
arg
.
is_arithmetic
())
if
(
*
it
==
'h'
)
spec
.
align_
=
ALIGN_NUMERIC
;
convert_arg
<
signed
char
>
(
arg
,
*++
it
);
else
else
spec
.
fill_
=
' '
;
// Ignore '0' flag for non-numeric types.
convert_arg
<
short
>
(
arg
,
*
it
);
}
break
;
case
'l'
:
// Parse length and convert the argument to the required type.
if
(
*
it
==
'l'
)
using
internal
::
convert_arg
;
convert_arg
<
long
long
>
(
arg
,
*++
it
);
switch
(
*
it
++
)
else
{
convert_arg
<
long
>
(
arg
,
*
it
);
case
'h'
:
break
;
if
(
*
it
==
'h'
)
case
'j'
:
convert_arg
<
signed
char
>
(
arg
,
*++
it
);
convert_arg
<
intmax_t
>
(
arg
,
*
it
);
else
break
;
convert_arg
<
short
>
(
arg
,
*
it
);
case
'z'
:
break
;
convert_arg
<
std
::
size_t
>
(
arg
,
*
it
);
case
'l'
:
break
;
if
(
*
it
==
'l'
)
case
't'
:
convert_arg
<
long
long
>
(
arg
,
*++
it
);
convert_arg
<
std
::
ptrdiff_t
>
(
arg
,
*
it
);
else
break
;
convert_arg
<
long
>
(
arg
,
*
it
);
case
'L'
:
break
;
// printf produces garbage when 'L' is omitted for long double, no
case
'j'
:
// need to do the same.
convert_arg
<
intmax_t
>
(
arg
,
*
it
);
break
;
break
;
default:
case
'z'
:
--
it
;
convert_arg
<
std
::
size_t
>
(
arg
,
*
it
);
convert_arg
<
void
>
(
arg
,
*
it
);
break
;
}
case
't'
:
convert_arg
<
std
::
ptrdiff_t
>
(
arg
,
*
it
);
// Parse type.
break
;
if
(
!*
it
)
case
'L'
:
FMT_THROW
(
format_error
(
"invalid format string"
));
// printf produces garbage when 'L' is omitted for long double, no
spec
.
type_
=
static_cast
<
char
>
(
*
it
++
);
// need to do the same.
if
(
arg
.
is_integral
())
{
break
;
// Normalize type.
default:
switch
(
spec
.
type_
)
{
--
it
;
case
'i'
:
case
'u'
:
convert_arg
<
void
>
(
arg
,
*
it
);
spec
.
type_
=
'd'
;
}
break
;
case
'c'
:
// Parse type.
// TODO: handle wchar_t better?
if
(
!*
it
)
visit
(
internal
::
char_converter
<
basic_printf_context
>
(
arg
),
arg
);
FMT_THROW
(
format_error
(
"invalid format string"
));
break
;
spec
.
type_
=
static_cast
<
char
>
(
*
it
++
);
}
if
(
arg
.
is_integral
())
}
{
// Normalize type.
start
=
it
;
switch
(
spec
.
type_
)
{
// Format argument.
case
'i'
:
visit
(
AF
(
buffer
,
spec
,
*
this
),
arg
);
case
'u'
:
}
spec
.
type_
=
'd'
;
buffer
.
append
(
pointer_from
(
start
),
pointer_from
(
it
));
break
;
case
'c'
:
// TODO: handle wchar_t better?
visit
(
internal
::
char_converter
<
basic_printf_context
>
(
arg
),
arg
);
break
;
}
}
start
=
it
;
// Format argument.
visit
(
AF
(
buffer
,
spec
,
*
this
),
arg
);
}
buffer
.
append
(
pointer_from
(
start
),
pointer_from
(
it
));
}
}
template
<
typename
Char
,
typename
Context
>
template
<
typename
Char
,
typename
Context
>
void
printf
(
internal
::
basic_buffer
<
Char
>
&
buf
,
basic_string_view
<
Char
>
format
,
basic_format_args
<
Context
>
args
)
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
();
Context
(
std
::
back_inserter
(
buf
),
format
,
args
).
format
();
}
}
template
<
typename
Buffer
>
template
<
typename
Buffer
>
struct
printf_context
struct
printf_context
{
{
typedef
basic_printf_context
<
typedef
basic_printf_context
<
std
::
back_insert_iterator
<
Buffer
>
,
typename
Buffer
::
value_type
>
type
;
std
::
back_insert_iterator
<
Buffer
>
,
typename
Buffer
::
value_type
>
type
;
};
};
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
format_arg_store
<
printf_context
<
internal
::
buffer
>::
type
,
Args
...
>
make_printf_args
(
const
Args
&
...
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
...);
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
::
buffer
>::
type
>
printf_args
;
typedef
basic_format_args
<
printf_context
<
internal
::
wbuffer
>::
type
>
wprintf_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
;
memory_buffer
buffer
;
printf
(
buffer
,
format
,
args
);
printf
(
buffer
,
format
,
args
);
return
to_string
(
buffer
);
return
to_string
(
buffer
);
}
}
/**
/**
...
@@ -661,33 +602,33 @@ inline std::string vsprintf(string_view format, printf_args args)
...
@@ -661,33 +602,33 @@ inline std::string vsprintf(string_view format, printf_args args)
std::string message = fmt::sprintf("The answer is %d", 42);
std::string message = fmt::sprintf("The answer is %d", 42);
\endrst
\endrst
*/
*/
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
std
::
string
sprintf
(
string_view
format_str
,
const
Args
&
...
args
)
inline
std
::
string
sprintf
(
string_view
format_str
,
const
Args
&
...
args
)
{
{
return
vsprintf
(
format_str
,
return
vsprintf
(
format_str
,
make_format_args
<
typename
printf_context
<
internal
::
buffer
>::
type
>
(
args
...));
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
;
wmemory_buffer
buffer
;
printf
(
buffer
,
format
,
args
);
printf
(
buffer
,
format
,
args
);
return
to_string
(
buffer
);
return
to_string
(
buffer
);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
std
::
wstring
sprintf
(
wstring_view
format_str
,
const
Args
&
...
args
)
inline
std
::
wstring
sprintf
(
wstring_view
format_str
,
const
Args
&
...
args
)
{
{
return
vsprintf
(
format_str
,
return
vsprintf
(
format_str
,
make_format_args
<
typename
printf_context
<
internal
::
wbuffer
>::
type
>
(
args
...));
make_format_args
<
typename
printf_context
<
internal
::
wbuffer
>::
type
>
(
args
...));
}
}
template
<
typename
Char
>
template
<
typename
Char
>
inline
int
vfprintf
(
inline
int
vfprintf
(
std
::
FILE
*
f
,
basic_string_view
<
Char
>
format
,
std
::
FILE
*
f
,
basic_string_view
<
Char
>
format
,
basic_format_args
<
typename
printf_context
<
internal
::
basic_buffer
<
Char
>>::
type
>
args
)
basic_format_args
<
typename
printf_context
<
{
internal
::
basic_buffer
<
Char
>>::
type
>
args
)
{
basic_memory_buffer
<
Char
>
buffer
;
basic_memory_buffer
<
Char
>
buffer
;
printf
(
buffer
,
format
,
args
);
printf
(
buffer
,
format
,
args
);
std
::
size_t
size
=
buffer
.
size
();
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,27 +640,26 @@ inline int vfprintf(
...
@@ -699,27 +640,26 @@ inline int vfprintf(
fmt::fprintf(stderr, "Don't %s!", "panic");
fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst
\endrst
*/
*/
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
int
fprintf
(
std
::
FILE
*
f
,
string_view
format_str
,
const
Args
&
...
args
)
inline
int
fprintf
(
std
::
FILE
*
f
,
string_view
format_str
,
const
Args
&
...
args
)
{
{
auto
vargs
=
make_format_args
<
auto
vargs
=
make_format_args
<
typename
printf_context
<
internal
::
buffer
>::
type
>
(
args
...);
typename
printf_context
<
internal
::
buffer
>::
type
>
(
args
...);
return
vfprintf
<
char
>
(
f
,
format_str
,
vargs
);
return
vfprintf
<
char
>
(
f
,
format_str
,
vargs
);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
int
fprintf
(
std
::
FILE
*
f
,
wstring_view
format_str
,
const
Args
&
...
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
...));
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
);
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
);
return
vfprintf
(
stdout
,
format
,
args
);
}
}
/**
/**
...
@@ -731,32 +671,32 @@ inline int vprintf(wstring_view format, wprintf_args args)
...
@@ -731,32 +671,32 @@ inline int vprintf(wstring_view format, wprintf_args args)
fmt::printf("Elapsed time: %.2f seconds", 1.23);
fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst
\endrst
*/
*/
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
int
printf
(
string_view
format_str
,
const
Args
&
...
args
)
inline
int
printf
(
string_view
format_str
,
const
Args
&
...
args
)
{
{
return
vprintf
(
format_str
,
return
vprintf
(
format_str
,
make_format_args
<
typename
printf_context
<
internal
::
buffer
>::
type
>
(
args
...));
make_format_args
<
typename
printf_context
<
internal
::
buffer
>::
type
>
(
args
...));
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
int
printf
(
wstring_view
format_str
,
const
Args
&
...
args
)
inline
int
printf
(
wstring_view
format_str
,
const
Args
&
...
args
)
{
{
return
vprintf
(
format_str
,
return
vprintf
(
format_str
,
make_format_args
<
typename
printf_context
<
internal
::
wbuffer
>::
type
>
(
args
...));
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
;
memory_buffer
buffer
;
printf
(
buffer
,
format_str
,
args
);
printf
(
buffer
,
format_str
,
args
);
internal
::
write
(
os
,
buffer
);
internal
::
write
(
os
,
buffer
);
return
static_cast
<
int
>
(
buffer
.
size
());
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
;
wmemory_buffer
buffer
;
printf
(
buffer
,
format_str
,
args
);
printf
(
buffer
,
format_str
,
args
);
internal
::
write
(
os
,
buffer
);
internal
::
write
(
os
,
buffer
);
return
static_cast
<
int
>
(
buffer
.
size
());
return
static_cast
<
int
>
(
buffer
.
size
());
}
}
/**
/**
...
@@ -768,19 +708,21 @@ inline int vfprintf(std::wostream &os, wstring_view format_str, wprintf_args arg
...
@@ -768,19 +708,21 @@ inline int vfprintf(std::wostream &os, wstring_view format_str, wprintf_args arg
fmt::fprintf(cerr, "Don't %s!", "panic");
fmt::fprintf(cerr, "Don't %s!", "panic");
\endrst
\endrst
*/
*/
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
int
fprintf
(
std
::
ostream
&
os
,
string_view
format_str
,
const
Args
&
...
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
...);
auto
vargs
=
make_format_args
<
return
vfprintf
(
os
,
format_str
,
vargs
);
typename
printf_context
<
internal
::
buffer
>::
type
>
(
args
...);
return
vfprintf
(
os
,
format_str
,
vargs
);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
inline
int
fprintf
(
std
::
wostream
&
os
,
wstring_view
format_str
,
const
Args
&
...
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
...);
auto
vargs
=
make_format_args
<
return
vfprintf
(
os
,
format_str
,
vargs
);
typename
printf_context
<
internal
::
buffer
>::
type
>
(
args
...);
return
vfprintf
(
os
,
format_str
,
vargs
);
}
}
FMT_END_NAMESPACE
FMT_END_NAMESPACE
#endif // FMT_PRINTF_H_
#endif
// FMT_PRINTF_H_
include/spdlog/fmt/bundled/ranges.h
View file @
f4771be7
...
@@ -17,326 +17,289 @@
...
@@ -17,326 +17,289 @@
// output only up to N items from the range.
// output only up to N items from the range.
#ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT
#ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT
#define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256
#
define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256
#endif
#endif
FMT_BEGIN_NAMESPACE
FMT_BEGIN_NAMESPACE
template
<
typename
Char
>
template
<
typename
Char
>
struct
formatting_base
struct
formatting_base
{
{
template
<
typename
ParseContext
>
template
<
typename
ParseContext
>
FMT_CONSTEXPR
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
{
FMT_CONSTEXPR
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
return
ctx
.
begin
();
{
}
return
ctx
.
begin
();
}
};
};
template
<
typename
Char
,
typename
Enable
=
void
>
template
<
typename
Char
,
typename
Enable
=
void
>
struct
formatting_range
:
formatting_base
<
Char
>
struct
formatting_range
:
formatting_base
<
Char
>
{
{
static
FMT_CONSTEXPR_DECL
const
std
::
size_t
range_length_limit
=
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.
FMT_RANGE_OUTPUT_LENGTH_LIMIT
;
// output only up to N items from the range.
Char
prefix
;
Char
prefix
;
Char
delimiter
;
Char
delimiter
;
Char
postfix
;
Char
postfix
;
formatting_range
()
:
prefix
(
'{'
),
delimiter
(
','
),
postfix
(
'}'
)
{}
formatting_range
()
static
FMT_CONSTEXPR_DECL
const
bool
add_delimiter_spaces
=
true
;
:
prefix
(
'{'
)
static
FMT_CONSTEXPR_DECL
const
bool
add_prepostfix_space
=
false
;
,
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
>
template
<
typename
Char
,
typename
Enable
=
void
>
struct
formatting_tuple
:
formatting_base
<
Char
>
struct
formatting_tuple
:
formatting_base
<
Char
>
{
{
Char
prefix
;
Char
prefix
;
Char
delimiter
;
Char
delimiter
;
Char
postfix
;
Char
postfix
;
formatting_tuple
()
:
prefix
(
'('
),
delimiter
(
','
),
postfix
(
')'
)
{}
formatting_tuple
()
static
FMT_CONSTEXPR_DECL
const
bool
add_delimiter_spaces
=
true
;
:
prefix
(
'('
)
static
FMT_CONSTEXPR_DECL
const
bool
add_prepostfix_space
=
false
;
,
delimiter
(
','
)
,
postfix
(
')'
)
{
}
static
FMT_CONSTEXPR_DECL
const
bool
add_delimiter_spaces
=
true
;
static
FMT_CONSTEXPR_DECL
const
bool
add_prepostfix_space
=
false
;
};
};
namespace
internal
{
namespace
internal
{
template
<
typename
RangeT
,
typename
OutputIterator
>
template
<
typename
RangeT
,
typename
OutputIterator
>
void
copy
(
const
RangeT
&
range
,
OutputIterator
out
)
void
copy
(
const
RangeT
&
range
,
OutputIterator
out
)
{
{
for
(
auto
it
=
range
.
begin
(),
end
=
range
.
end
();
it
!=
end
;
++
it
)
for
(
auto
it
=
range
.
begin
(),
end
=
range
.
end
();
it
!=
end
;
++
it
)
*
out
++
=
*
it
;
*
out
++
=
*
it
;
}
}
template
<
typename
OutputIterator
>
template
<
typename
OutputIterator
>
void
copy
(
const
char
*
str
,
OutputIterator
out
)
void
copy
(
const
char
*
str
,
OutputIterator
out
)
{
{
const
char
*
p_curr
=
str
;
const
char
*
p_curr
=
str
;
while
(
*
p_curr
)
{
while
(
*
p_curr
)
*
out
++
=
*
p_curr
++
;
{
}
*
out
++
=
*
p_curr
++
;
}
}
}
template
<
typename
OutputIterator
>
template
<
typename
OutputIterator
>
void
copy
(
char
ch
,
OutputIterator
out
)
void
copy
(
char
ch
,
OutputIterator
out
)
{
{
*
out
++
=
ch
;
*
out
++
=
ch
;
}
}
/// Return true value if T has std::string interface, like std::string_view.
/// Return true value if T has std::string interface, like std::string_view.
template
<
typename
T
>
template
<
typename
T
>
class
is_like_std_string
class
is_like_std_string
{
{
template
<
typename
U
>
template
<
typename
U
>
static
auto
check
(
U
*
p
)
->
static
auto
check
(
U
*
p
)
->
decltype
(
p
->
find
(
'a'
),
p
->
length
(),
p
->
data
(),
int
());
decltype
(
p
->
find
(
'a'
),
p
->
length
(),
p
->
data
(),
int
());
template
<
typename
>
template
<
typename
>
static
void
check
(...);
static
void
check
(...);
public:
public:
static
FMT_CONSTEXPR_DECL
const
bool
value
=
!
std
::
is_void
<
decltype
(
check
<
T
>
(
FMT_NULL
))
>::
value
;
static
FMT_CONSTEXPR_DECL
const
bool
value
=
!
std
::
is_void
<
decltype
(
check
<
T
>
(
FMT_NULL
))
>::
value
;
};
};
template
<
typename
...
Ts
>
template
<
typename
...
Ts
>
struct
conditional_helper
struct
conditional_helper
{};
{
};
template
<
typename
T
,
typename
_
=
void
>
template
<
typename
T
,
typename
_
=
void
>
struct
is_range_
:
std
::
false_type
struct
is_range_
:
std
::
false_type
{};
{
};
template
<
typename
T
>
#if !FMT_MSC_VER || FMT_MSC_VER > 1800
struct
is_range_
<
T
,
typename
std
::
conditional
<
false
,
template
<
typename
T
>
conditional_helper
<
decltype
(
internal
::
declval
<
T
>
().
begin
()),
decltype
(
internal
::
declval
<
T
>
().
end
())
>
,
void
>::
type
>
struct
is_range_
<
T
,
typename
std
::
conditional
<
:
std
::
true_type
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.
/// tuple_size and tuple_element check.
template
<
typename
T
>
template
<
typename
T
>
class
is_tuple_like_
class
is_tuple_like_
{
{
template
<
typename
U
>
template
<
typename
U
>
static
auto
check
(
U
*
p
)
->
static
auto
check
(
U
*
p
)
->
decltype
(
std
::
tuple_size
<
U
>::
value
,
internal
::
declval
<
typename
std
::
tuple_element
<
0
,
U
>::
type
>
(),
int
());
decltype
(
std
::
tuple_size
<
U
>::
value
,
template
<
typename
>
internal
::
declval
<
typename
std
::
tuple_element
<
0
,
U
>::
type
>
(),
int
());
static
void
check
(...);
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
// Check for integer_sequence
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
#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
...
>
;
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
...
>
;
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
>
;
using
make_index_sequence
=
std
::
make_index_sequence
<
N
>
;
#else
#else
template
<
typename
T
,
T
...
N
>
template
<
typename
T
,
T
...
N
>
struct
integer_sequence
struct
integer_sequence
{
{
typedef
T
value_type
;
typedef
T
value_type
;
static
FMT_CONSTEXPR
std
::
size_t
size
()
{
static
FMT_CONSTEXPR
std
::
size_t
size
()
return
sizeof
...(
N
);
{
}
return
sizeof
...(
N
);
}
};
};
template
<
std
::
size_t
...
N
>
template
<
std
::
size_t
...
N
>
using
index_sequence
=
integer_sequence
<
std
::
size_t
,
N
...
>
;
using
index_sequence
=
integer_sequence
<
std
::
size_t
,
N
...
>
;
template
<
typename
T
,
std
::
size_t
N
,
T
...
Ns
>
template
<
typename
T
,
std
::
size_t
N
,
T
...
Ns
>
struct
make_integer_sequence
:
make_integer_sequence
<
T
,
N
-
1
,
N
-
1
,
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
,
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
>
;
using
make_index_sequence
=
make_integer_sequence
<
std
::
size_t
,
N
>
;
#endif
#endif
template
<
class
Tuple
,
class
F
,
size_t
...
Is
>
template
<
class
Tuple
,
class
F
,
size_t
...
Is
>
void
for_each
(
index_sequence
<
Is
...
>
,
Tuple
&&
tup
,
F
&&
f
)
noexcept
void
for_each
(
index_sequence
<
Is
...
>
,
Tuple
&&
tup
,
F
&&
f
)
FMT_NOEXCEPT
{
{
using
std
::
get
;
using
std
::
get
;
// using free function get<I>(T) now.
// using free function get<I>(T) now.
const
int
_
[]
=
{
0
,
((
void
)
f
(
get
<
Is
>
(
tup
)),
0
)...};
const
int
_
[]
=
{
0
,
((
void
)
f
(
get
<
Is
>
(
tup
)),
0
)...};
(
void
)
_
;
// blocks warnings
(
void
)
_
;
// blocks warnings
}
}
template
<
class
T
>
template
<
class
T
>
FMT_CONSTEXPR
make_index_sequence
<
std
::
tuple_size
<
T
>::
value
>
get_indexes
(
T
const
&
)
FMT_CONSTEXPR
make_index_sequence
<
std
::
tuple_size
<
T
>::
value
>
{
get_indexes
(
T
const
&
)
{
return
{};
}
return
{};
}
template
<
class
Tuple
,
class
F
>
template
<
class
Tuple
,
class
F
>
void
for_each
(
Tuple
&&
tup
,
F
&&
f
)
void
for_each
(
Tuple
&&
tup
,
F
&&
f
)
{
{
const
auto
indexes
=
get_indexes
(
tup
);
const
auto
indexes
=
get_indexes
(
tup
);
for_each
(
indexes
,
std
::
forward
<
Tuple
>
(
tup
),
std
::
forward
<
F
>
(
f
));
for_each
(
indexes
,
std
::
forward
<
Tuple
>
(
tup
),
std
::
forward
<
F
>
(
f
));
}
}
template
<
typename
Arg
>
template
<
typename
Arg
>
FMT_CONSTEXPR
const
char
*
format_str_quoted
(
FMT_CONSTEXPR
const
char
*
format_str_quoted
(
bool
add_space
,
const
Arg
&
,
bool
add_space
,
const
Arg
&
,
typename
std
::
enable_if
<!
is_like_std_string
<
typename
std
::
decay
<
Arg
>::
type
>::
value
>::
type
*
=
nullptr
)
typename
std
::
enable_if
<
{
!
is_like_std_string
<
typename
std
::
decay
<
Arg
>::
type
>::
value
>::
type
*
=
nullptr
)
{
return
add_space
?
" {}"
:
"{}"
;
return
add_space
?
" {}"
:
"{}"
;
}
}
template
<
typename
Arg
>
template
<
typename
Arg
>
FMT_CONSTEXPR
const
char
*
format_str_quoted
(
FMT_CONSTEXPR
const
char
*
format_str_quoted
(
bool
add_space
,
const
Arg
&
,
bool
add_space
,
const
Arg
&
,
typename
std
::
enable_if
<
is_like_std_string
<
typename
std
::
decay
<
Arg
>::
type
>::
value
>::
type
*
=
nullptr
)
typename
std
::
enable_if
<
{
is_like_std_string
<
typename
std
::
decay
<
Arg
>::
type
>::
value
>::
type
*
=
nullptr
)
{
return
add_space
?
"
\"
{}
\"
"
:
"
\"
{}
\"
"
;
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
?
"
\"
{}
\"
"
:
"
\"
{}
\"
"
;
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"
\"
{}
\"
"
;
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
?
" '{}'"
:
"'{}'"
;
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"'{}'"
;
return
add_space
?
L" '{}'"
:
L"'{}'"
;
}
}
}
// namespace internal
}
// namespace internal
template
<
typename
T
>
template
<
typename
T
>
struct
is_tuple_like
struct
is_tuple_like
{
{
static
FMT_CONSTEXPR_DECL
const
bool
value
=
static
FMT_CONSTEXPR_DECL
const
bool
value
=
internal
::
is_tuple_like_
<
T
>::
value
&&
!
internal
::
is_range_
<
T
>::
value
;
internal
::
is_tuple_like_
<
T
>::
value
&&
!
internal
::
is_range_
<
T
>::
value
;
};
};
template
<
typename
TupleT
,
typename
Char
>
template
<
typename
TupleT
,
typename
Char
>
struct
formatter
<
TupleT
,
Char
,
typename
std
::
enable_if
<
fmt
::
is_tuple_like
<
TupleT
>::
value
>::
type
>
struct
formatter
<
TupleT
,
Char
,
{
typename
std
::
enable_if
<
fmt
::
is_tuple_like
<
TupleT
>::
value
>::
type
>
{
private:
private:
// C++11 generic lambda for format()
// C++11 generic lambda for format()
template
<
typename
FormatContext
>
template
<
typename
FormatContext
>
struct
format_each
struct
format_each
{
{
template
<
typename
T
>
template
<
typename
T
>
void
operator
()(
const
T
&
v
)
{
void
operator
()(
const
T
&
v
)
if
(
i
>
0
)
{
{
if
(
formatting
.
add_prepostfix_space
)
{
if
(
i
>
0
)
*
out
++
=
' '
;
{
if
(
formatting
.
add_prepostfix_space
)
{
*
out
++
=
' '
;
}
internal
::
copy
(
formatting
.
delimiter
,
out
);
}
format_to
(
out
,
internal
::
format_str_quoted
((
formatting
.
add_delimiter_spaces
&&
i
>
0
),
v
),
v
);
++
i
;
}
}
internal
::
copy
(
formatting
.
delimiter
,
out
);
}
format_to
(
out
,
internal
::
format_str_quoted
(
(
formatting
.
add_delimiter_spaces
&&
i
>
0
),
v
),
v
);
++
i
;
}
formatting_tuple
<
Char
>
&
formatting
;
formatting_tuple
<
Char
>&
formatting
;
std
::
size_t
&
i
;
std
::
size_t
&
i
;
typename
std
::
add_lvalue_reference
<
decltype
(
std
::
declval
<
FormatContext
>
().
out
())
>::
type
out
;
typename
std
::
add_lvalue_reference
<
decltype
(
std
::
declval
<
FormatContext
>
().
out
())
>::
type
out
;
};
};
public:
public:
formatting_tuple
<
Char
>
formatting
;
formatting_tuple
<
Char
>
formatting
;
template
<
typename
ParseContext
>
template
<
typename
ParseContext
>
FMT_CONSTEXPR
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
FMT_CONSTEXPR
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
{
{
return
formatting
.
parse
(
ctx
);
return
formatting
.
parse
(
ctx
);
}
template
<
typename
FormatContext
=
format_context
>
auto
format
(
const
TupleT
&
values
,
FormatContext
&
ctx
)
->
decltype
(
ctx
.
out
())
{
auto
out
=
ctx
.
out
();
std
::
size_t
i
=
0
;
internal
::
copy
(
formatting
.
prefix
,
out
);
internal
::
for_each
(
values
,
format_each
<
FormatContext
>
{
formatting
,
i
,
out
});
if
(
formatting
.
add_prepostfix_space
)
{
*
out
++
=
' '
;
}
}
internal
::
copy
(
formatting
.
postfix
,
out
);
template
<
typename
FormatContext
=
format_context
>
return
ctx
.
out
();
auto
format
(
const
TupleT
&
values
,
FormatContext
&
ctx
)
->
decltype
(
ctx
.
out
())
}
{
auto
out
=
ctx
.
out
();
std
::
size_t
i
=
0
;
internal
::
copy
(
formatting
.
prefix
,
out
);
internal
::
for_each
(
values
,
format_each
<
FormatContext
>
{
formatting
,
i
,
out
});
if
(
formatting
.
add_prepostfix_space
)
{
*
out
++
=
' '
;
}
internal
::
copy
(
formatting
.
postfix
,
out
);
return
ctx
.
out
();
}
};
};
template
<
typename
T
>
template
<
typename
T
>
struct
is_range
struct
is_range
{
{
static
FMT_CONSTEXPR_DECL
const
bool
value
=
static
FMT_CONSTEXPR_DECL
const
bool
value
=
internal
::
is_range_
<
T
>::
value
&&
!
internal
::
is_like_std_string
<
T
>::
value
;
internal
::
is_range_
<
T
>::
value
&&
!
internal
::
is_like_std_string
<
T
>::
value
;
};
};
template
<
typename
RangeT
,
typename
Char
>
template
<
typename
RangeT
,
typename
Char
>
struct
formatter
<
RangeT
,
Char
,
typename
std
::
enable_if
<
fmt
::
is_range
<
RangeT
>::
value
>::
type
>
struct
formatter
<
RangeT
,
Char
,
{
typename
std
::
enable_if
<
fmt
::
is_range
<
RangeT
>::
value
>::
type
>
{
formatting_range
<
Char
>
formatting
;
formatting_range
<
Char
>
formatting
;
template
<
typename
ParseContext
>
template
<
typename
ParseContext
>
FMT_CONSTEXPR
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
FMT_CONSTEXPR
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
{
{
return
formatting
.
parse
(
ctx
);
return
formatting
.
parse
(
ctx
);
}
}
template
<
typename
FormatContext
>
template
<
typename
FormatContext
>
typename
FormatContext
::
iterator
format
(
typename
FormatContext
::
iterator
format
(
const
RangeT
&
values
,
FormatContext
&
ctx
)
const
RangeT
&
values
,
FormatContext
&
ctx
)
{
{
auto
out
=
ctx
.
out
();
auto
out
=
ctx
.
out
();
internal
::
copy
(
formatting
.
prefix
,
out
);
internal
::
copy
(
formatting
.
prefix
,
out
);
std
::
size_t
i
=
0
;
std
::
size_t
i
=
0
;
for
(
auto
it
=
values
.
begin
(),
end
=
values
.
end
();
it
!=
end
;
++
it
)
{
for
(
auto
it
=
values
.
begin
(),
end
=
values
.
end
();
it
!=
end
;
++
it
)
if
(
i
>
0
)
{
{
if
(
formatting
.
add_prepostfix_space
)
{
if
(
i
>
0
)
*
out
++
=
' '
;
{
if
(
formatting
.
add_prepostfix_space
)
{
*
out
++
=
' '
;
}
internal
::
copy
(
formatting
.
delimiter
,
out
);
}
format_to
(
out
,
internal
::
format_str_quoted
((
formatting
.
add_delimiter_spaces
&&
i
>
0
),
*
it
),
*
it
);
if
(
++
i
>
formatting
.
range_length_limit
)
{
format_to
(
out
,
" ... <other elements>"
);
break
;
}
}
}
if
(
formatting
.
add_prepostfix_space
)
internal
::
copy
(
formatting
.
delimiter
,
out
);
{
}
*
out
++
=
' '
;
format_to
(
out
,
}
internal
::
format_str_quoted
(
internal
::
copy
(
formatting
.
postfix
,
out
);
(
formatting
.
add_delimiter_spaces
&&
i
>
0
),
*
it
),
return
ctx
.
out
();
*
it
);
if
(
++
i
>
formatting
.
range_length_limit
)
{
format_to
(
out
,
" ... <other elements>"
);
break
;
}
}
if
(
formatting
.
add_prepostfix_space
)
{
*
out
++
=
' '
;
}
}
internal
::
copy
(
formatting
.
postfix
,
out
);
return
ctx
.
out
();
}
};
};
FMT_END_NAMESPACE
FMT_END_NAMESPACE
#endif // FMT_RANGES_H_
#endif // FMT_RANGES_H_
include/spdlog/fmt/bundled/time.h
View file @
f4771be7
...
@@ -13,187 +13,140 @@
...
@@ -13,187 +13,140 @@
FMT_BEGIN_NAMESPACE
FMT_BEGIN_NAMESPACE
namespace
internal
{
namespace
internal
{
inline
null
<>
localtime_r
(...)
inline
null
<>
localtime_r
(...)
{
return
null
<>
();
}
{
inline
null
<>
localtime_s
(...)
{
return
null
<>
();
}
return
null
<>
();
inline
null
<>
gmtime_r
(...)
{
return
null
<>
();
}
}
inline
null
<>
gmtime_s
(...)
{
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
// Thread-safe replacement for std::localtime
inline
std
::
tm
localtime
(
std
::
time_t
time
)
inline
std
::
tm
localtime
(
std
::
time_t
time
)
{
{
struct
dispatcher
{
struct
dispatcher
std
::
time_t
time_
;
{
std
::
tm
tm_
;
std
::
time_t
time_
;
std
::
tm
tm_
;
dispatcher
(
std
::
time_t
t
)
:
time_
(
t
)
{}
dispatcher
(
std
::
time_t
t
)
bool
run
()
{
:
time_
(
t
)
using
namespace
fmt
::
internal
;
{
return
handle
(
localtime_r
(
&
time_
,
&
tm_
));
}
}
bool
run
()
bool
handle
(
std
::
tm
*
tm
)
{
return
tm
!=
FMT_NULL
;
}
{
using
namespace
fmt
::
internal
;
bool
handle
(
internal
::
null
<>
)
{
return
handle
(
localtime_r
(
&
time_
,
&
tm_
));
using
namespace
fmt
::
internal
;
}
return
fallback
(
localtime_s
(
&
tm_
,
&
time_
));
}
bool
handle
(
std
::
tm
*
tm
)
{
bool
fallback
(
int
res
)
{
return
res
==
0
;
}
return
tm
!=
FMT_NULL
;
}
bool
fallback
(
internal
::
null
<>
)
{
using
namespace
fmt
::
internal
;
bool
handle
(
internal
::
null
<>
)
std
::
tm
*
tm
=
std
::
localtime
(
&
time_
);
{
if
(
tm
)
tm_
=
*
tm
;
using
namespace
fmt
::
internal
;
return
tm
!=
FMT_NULL
;
return
fallback
(
localtime_s
(
&
tm_
,
&
time_
));
}
}
};
dispatcher
lt
(
time
);
bool
fallback
(
int
res
)
if
(
lt
.
run
())
{
return
lt
.
tm_
;
return
res
==
0
;
// Too big time values may be unsupported.
}
FMT_THROW
(
format_error
(
"time_t value out of range"
));
bool
fallback
(
internal
::
null
<>
)
{
using
namespace
fmt
::
internal
;
std
::
tm
*
tm
=
std
::
localtime
(
&
time_
);
if
(
tm
)
tm_
=
*
tm
;
return
tm
!=
FMT_NULL
;
}
};
dispatcher
lt
(
time
);
if
(
lt
.
run
())
return
lt
.
tm_
;
// Too big time values may be unsupported.
FMT_THROW
(
format_error
(
"time_t value out of range"
));
}
}
// Thread-safe replacement for std::gmtime
// Thread-safe replacement for std::gmtime
inline
std
::
tm
gmtime
(
std
::
time_t
time
)
inline
std
::
tm
gmtime
(
std
::
time_t
time
)
{
{
struct
dispatcher
{
struct
dispatcher
std
::
time_t
time_
;
{
std
::
tm
tm_
;
std
::
time_t
time_
;
std
::
tm
tm_
;
dispatcher
(
std
::
time_t
t
)
:
time_
(
t
)
{}
dispatcher
(
std
::
time_t
t
)
bool
run
()
{
:
time_
(
t
)
using
namespace
fmt
::
internal
;
{
return
handle
(
gmtime_r
(
&
time_
,
&
tm_
));
}
}
bool
run
()
bool
handle
(
std
::
tm
*
tm
)
{
return
tm
!=
FMT_NULL
;
}
{
using
namespace
fmt
::
internal
;
bool
handle
(
internal
::
null
<>
)
{
return
handle
(
gmtime_r
(
&
time_
,
&
tm_
));
using
namespace
fmt
::
internal
;
}
return
fallback
(
gmtime_s
(
&
tm_
,
&
time_
));
}
bool
handle
(
std
::
tm
*
tm
)
{
bool
fallback
(
int
res
)
{
return
res
==
0
;
}
return
tm
!=
FMT_NULL
;
}
bool
fallback
(
internal
::
null
<>
)
{
std
::
tm
*
tm
=
std
::
gmtime
(
&
time_
);
bool
handle
(
internal
::
null
<>
)
if
(
tm
)
tm_
=
*
tm
;
{
return
tm
!=
FMT_NULL
;
using
namespace
fmt
::
internal
;
}
return
fallback
(
gmtime_s
(
&
tm_
,
&
time_
));
};
}
dispatcher
gt
(
time
);
if
(
gt
.
run
())
bool
fallback
(
int
res
)
return
gt
.
tm_
;
{
// Too big time values may be unsupported.
return
res
==
0
;
FMT_THROW
(
format_error
(
"time_t value out of range"
));
}
bool
fallback
(
internal
::
null
<>
)
{
std
::
tm
*
tm
=
std
::
gmtime
(
&
time_
);
if
(
tm
)
tm_
=
*
tm
;
return
tm
!=
FMT_NULL
;
}
};
dispatcher
gt
(
time
);
if
(
gt
.
run
())
return
gt
.
tm_
;
// Too big time values may be unsupported.
FMT_THROW
(
format_error
(
"time_t value out of range"
));
}
}
namespace
internal
{
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
);
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
);
return
std
::
wcsftime
(
str
,
count
,
format
,
time
);
}
}
}
}
// namespace internal
template
<
typename
Char
>
struct
formatter
<
std
::
tm
,
Char
>
{
template
<
typename
ParseContext
>
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
{
auto
it
=
internal
::
null_terminating_iterator
<
Char
>
(
ctx
);
if
(
*
it
==
':'
)
++
it
;
auto
end
=
it
;
while
(
*
end
&&
*
end
!=
'}'
)
++
end
;
tm_format
.
reserve
(
end
-
it
+
1
);
using
internal
::
pointer_from
;
tm_format
.
append
(
pointer_from
(
it
),
pointer_from
(
end
));
tm_format
.
push_back
(
'\0'
);
return
pointer_from
(
end
);
}
template
<
typename
FormatContext
>
template
<
typename
Char
>
auto
format
(
const
std
::
tm
&
tm
,
FormatContext
&
ctx
)
->
decltype
(
ctx
.
out
())
struct
formatter
<
std
::
tm
,
Char
>
{
{
template
<
typename
ParseContext
>
internal
::
basic_buffer
<
Char
>
&
buf
=
internal
::
get_container
(
ctx
.
out
());
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
{
std
::
size_t
start
=
buf
.
size
();
auto
it
=
internal
::
null_terminating_iterator
<
Char
>
(
ctx
);
for
(;;)
if
(
*
it
==
':'
)
{
++
it
;
std
::
size_t
size
=
buf
.
capacity
()
-
start
;
auto
end
=
it
;
std
::
size_t
count
=
internal
::
strftime
(
&
buf
[
start
],
size
,
&
tm_format
[
0
],
&
tm
);
while
(
*
end
&&
*
end
!=
'}'
)
if
(
count
!=
0
)
++
end
;
{
tm_format
.
reserve
(
end
-
it
+
1
);
buf
.
resize
(
start
+
count
);
using
internal
::
pointer_from
;
break
;
tm_format
.
append
(
pointer_from
(
it
),
pointer_from
(
end
));
}
tm_format
.
push_back
(
'\0'
);
if
(
size
>=
tm_format
.
size
()
*
256
)
return
pointer_from
(
end
);
{
}
// 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
template
<
typename
FormatContext
>
// better way to distinguish the two cases:
auto
format
(
const
std
::
tm
&
tm
,
FormatContext
&
ctx
)
->
decltype
(
ctx
.
out
())
{
// https://github.com/fmtlib/fmt/issues/367
internal
::
basic_buffer
<
Char
>
&
buf
=
internal
::
get_container
(
ctx
.
out
());
break
;
std
::
size_t
start
=
buf
.
size
();
}
for
(;;)
{
const
std
::
size_t
MIN_GROWTH
=
10
;
std
::
size_t
size
=
buf
.
capacity
()
-
start
;
buf
.
reserve
(
buf
.
capacity
()
+
(
size
>
MIN_GROWTH
?
size
:
MIN_GROWTH
));
std
::
size_t
count
=
}
internal
::
strftime
(
&
buf
[
start
],
size
,
&
tm_format
[
0
],
&
tm
);
return
ctx
.
out
();
if
(
count
!=
0
)
{
buf
.
resize
(
start
+
count
);
break
;
}
if
(
size
>=
tm_format
.
size
()
*
256
)
{
// If the buffer is 256 times larger than the format string, assume
// that `strftime` gives an empty result. There doesn't seem to be a
// better way to distinguish the two cases:
// https://github.com/fmtlib/fmt/issues/367
break
;
}
const
std
::
size_t
MIN_GROWTH
=
10
;
buf
.
reserve
(
buf
.
capacity
()
+
(
size
>
MIN_GROWTH
?
size
:
MIN_GROWTH
));
}
}
return
ctx
.
out
();
}
basic_memory_buffer
<
Char
>
tm_format
;
basic_memory_buffer
<
Char
>
tm_format
;
};
};
FMT_END_NAMESPACE
FMT_END_NAMESPACE
#endif // FMT_TIME_H_
#endif
// FMT_TIME_H_
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment