Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
S
spdlog
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
spdlog
Commits
0db4b04a
Commit
0db4b04a
authored
Dec 04, 2019
by
gabime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bump bundled fmt to version 6.1.0
parent
1aa9ea92
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
208 additions
and
395 deletions
+208
-395
chrono.h
include/spdlog/fmt/bundled/chrono.h
+0
-0
color.h
include/spdlog/fmt/bundled/color.h
+31
-46
compile.h
include/spdlog/fmt/bundled/compile.h
+0
-0
core.h
include/spdlog/fmt/bundled/core.h
+0
-0
format-inl.h
include/spdlog/fmt/bundled/format-inl.h
+0
-0
format.h
include/spdlog/fmt/bundled/format.h
+0
-0
ostream.h
include/spdlog/fmt/bundled/ostream.h
+14
-9
posix.h
include/spdlog/fmt/bundled/posix.h
+27
-17
printf.h
include/spdlog/fmt/bundled/printf.h
+14
-18
ranges.h
include/spdlog/fmt/bundled/ranges.h
+78
-1
safe-duration-cast.h
include/spdlog/fmt/bundled/safe-duration-cast.h
+0
-293
fmt.cpp
src/fmt.cpp
+44
-11
No files found.
include/spdlog/fmt/bundled/chrono.h
View file @
0db4b04a
This diff is collapsed.
Click to expand it.
include/spdlog/fmt/bundled/color.h
View file @
0db4b04a
...
...
@@ -299,15 +299,15 @@ class text_style {
return
static_cast
<
uint8_t
>
(
ems
)
!=
0
;
}
FMT_CONSTEXPR
internal
::
color_type
get_foreground
()
const
FMT_NOEXCEPT
{
assert
(
has_foreground
()
&&
"no foreground specified for this style"
);
FMT_ASSERT
(
has_foreground
(),
"no foreground specified for this style"
);
return
foreground_color
;
}
FMT_CONSTEXPR
internal
::
color_type
get_background
()
const
FMT_NOEXCEPT
{
assert
(
has_background
()
&&
"no background specified for this style"
);
FMT_ASSERT
(
has_background
(),
"no background specified for this style"
);
return
background_color
;
}
FMT_CONSTEXPR
emphasis
get_emphasis
()
const
FMT_NOEXCEPT
{
assert
(
has_emphasis
()
&&
"no emphasis specified for this style"
);
FMT_ASSERT
(
has_emphasis
(),
"no emphasis specified for this style"
);
return
ems
;
}
...
...
@@ -470,58 +470,41 @@ inline void reset_color(basic_memory_buffer<Char>& buffer) FMT_NOEXCEPT {
}
template
<
typename
Char
>
std
::
basic_string
<
Char
>
vformat
(
const
text_style
&
ts
,
basic_string_view
<
Char
>
format_str
,
basic_format_args
<
buffer_context
<
Char
>
>
args
)
{
basic_memory_buffer
<
Char
>
buffer
;
void
vformat_to
(
basic_memory_buffer
<
Char
>&
buf
,
const
text_style
&
ts
,
basic_string_view
<
Char
>
format_str
,
basic_format_args
<
buffer_context
<
Char
>>
args
)
{
bool
has_style
=
false
;
if
(
ts
.
has_emphasis
())
{
has_style
=
true
;
a
nsi_color_escape
<
Char
>
escape
=
make_emphasis
<
Char
>
(
ts
.
get_emphasis
());
buf
fer
.
append
(
escape
.
begin
(),
escape
.
end
());
a
uto
emphasis
=
internal
::
make_emphasis
<
Char
>
(
ts
.
get_emphasis
());
buf
.
append
(
emphasis
.
begin
(),
emphasis
.
end
());
}
if
(
ts
.
has_foreground
())
{
has_style
=
true
;
a
nsi_color_escape
<
Char
>
escape
=
make_foreground_color
<
Char
>
(
ts
.
get_foreground
());
buf
fer
.
append
(
escape
.
begin
(),
escape
.
end
());
a
uto
foreground
=
internal
::
make_foreground_color
<
Char
>
(
ts
.
get_foreground
());
buf
.
append
(
foreground
.
begin
(),
foreground
.
end
());
}
if
(
ts
.
has_background
())
{
has_style
=
true
;
a
nsi_color_escape
<
Char
>
escape
=
make_background_color
<
Char
>
(
ts
.
get_background
());
buf
fer
.
append
(
escape
.
begin
(),
escape
.
end
());
a
uto
background
=
internal
::
make_background_color
<
Char
>
(
ts
.
get_background
());
buf
.
append
(
background
.
begin
(),
background
.
end
());
}
internal
::
vformat_to
(
buffer
,
format_str
,
args
);
vformat_to
(
buf
,
format_str
,
args
);
if
(
has_style
)
{
reset_color
<
Char
>
(
buffer
);
internal
::
reset_color
<
Char
>
(
buf
);
}
return
fmt
::
to_string
(
buffer
);
}
}
// namespace internal
template
<
typename
S
,
typename
Char
=
char_t
<
S
>
>
template
<
typename
S
,
typename
Char
=
char_t
<
S
>>
void
vprint
(
std
::
FILE
*
f
,
const
text_style
&
ts
,
const
S
&
format
,
basic_format_args
<
buffer_context
<
Char
>
>
args
)
{
bool
has_style
=
false
;
if
(
ts
.
has_emphasis
())
{
has_style
=
true
;
internal
::
fputs
<
Char
>
(
internal
::
make_emphasis
<
Char
>
(
ts
.
get_emphasis
()),
f
);
}
if
(
ts
.
has_foreground
())
{
has_style
=
true
;
internal
::
fputs
<
Char
>
(
internal
::
make_foreground_color
<
Char
>
(
ts
.
get_foreground
()),
f
);
}
if
(
ts
.
has_background
())
{
has_style
=
true
;
internal
::
fputs
<
Char
>
(
internal
::
make_background_color
<
Char
>
(
ts
.
get_background
()),
f
);
}
vprint
(
f
,
format
,
args
);
if
(
has_style
)
{
internal
::
reset_color
<
Char
>
(
f
);
}
basic_format_args
<
buffer_context
<
Char
>>
args
)
{
basic_memory_buffer
<
Char
>
buf
;
internal
::
vformat_to
(
buf
,
ts
,
to_string_view
(
format
),
args
);
buf
.
push_back
(
Char
(
0
));
internal
::
fputs
(
buf
.
data
(),
f
);
}
/**
...
...
@@ -536,7 +519,7 @@ template <typename S, typename... Args,
void
print
(
std
::
FILE
*
f
,
const
text_style
&
ts
,
const
S
&
format_str
,
const
Args
&
...
args
)
{
internal
::
check_format_string
<
Args
...
>
(
format_str
);
using
context
=
buffer_context
<
char_t
<
S
>
>
;
using
context
=
buffer_context
<
char_t
<
S
>>
;
format_arg_store
<
context
,
Args
...
>
as
{
args
...};
vprint
(
f
,
ts
,
format_str
,
basic_format_args
<
context
>
(
as
));
}
...
...
@@ -554,11 +537,13 @@ void print(const text_style& ts, const S& format_str, const Args&... args) {
return
print
(
stdout
,
ts
,
format_str
,
args
...);
}
template
<
typename
S
,
typename
Char
=
char_t
<
S
>
>
template
<
typename
S
,
typename
Char
=
char_t
<
S
>>
inline
std
::
basic_string
<
Char
>
vformat
(
const
text_style
&
ts
,
const
S
&
format_str
,
basic_format_args
<
buffer_context
<
Char
>
>
args
)
{
return
internal
::
vformat
(
ts
,
to_string_view
(
format_str
),
args
);
basic_format_args
<
buffer_context
<
Char
>>
args
)
{
basic_memory_buffer
<
Char
>
buf
;
internal
::
vformat_to
(
buf
,
ts
,
to_string_view
(
format_str
),
args
);
return
fmt
::
to_string
(
buf
);
}
/**
...
...
@@ -573,11 +558,11 @@ inline std::basic_string<Char> vformat(
"The answer is {}", 42);
\endrst
*/
template
<
typename
S
,
typename
...
Args
,
typename
Char
=
char_t
<
S
>
>
template
<
typename
S
,
typename
...
Args
,
typename
Char
=
char_t
<
S
>>
inline
std
::
basic_string
<
Char
>
format
(
const
text_style
&
ts
,
const
S
&
format_str
,
const
Args
&
...
args
)
{
return
internal
::
vformat
(
ts
,
to_string_view
(
format_str
),
{
internal
::
make_args_checked
(
format_str
,
args
...)});
return
vformat
(
ts
,
to_string_view
(
format_str
),
{
internal
::
make_args_checked
<
Args
...
>
(
format_str
,
args
...)});
}
FMT_END_NAMESPACE
...
...
include/spdlog/fmt/bundled/compile.h
View file @
0db4b04a
This diff is collapsed.
Click to expand it.
include/spdlog/fmt/bundled/core.h
View file @
0db4b04a
This diff is collapsed.
Click to expand it.
include/spdlog/fmt/bundled/format-inl.h
View file @
0db4b04a
This diff is collapsed.
Click to expand it.
include/spdlog/fmt/bundled/format.h
View file @
0db4b04a
This diff is collapsed.
Click to expand it.
include/spdlog/fmt/bundled/ostream.h
View file @
0db4b04a
...
...
@@ -46,9 +46,13 @@ template <class Char> class formatbuf : public std::basic_streambuf<Char> {
template
<
typename
Char
>
struct
test_stream
:
std
::
basic_ostream
<
Char
>
{
private
:
struct
null
;
// Hide all operator<< from std::basic_ostream<Char>.
void
operator
<<
(
null
);
void_t
<>
operator
<<
(
null
<>
);
void_t
<>
operator
<<
(
const
Char
*
);
template
<
typename
T
,
FMT_ENABLE_IF
(
std
::
is_convertible
<
T
,
int
>::
value
&&
!
std
::
is_enum
<
T
>::
value
)
>
void_t
<>
operator
<<
(
T
);
};
// Checks if T has a user-defined operator<< (e.g. not a member of
...
...
@@ -56,9 +60,9 @@ template <typename Char> struct test_stream : std::basic_ostream<Char> {
template
<
typename
T
,
typename
Char
>
class
is_streamable
{
private
:
template
<
typename
U
>
static
decltype
((
void
)
(
std
::
declval
<
test_stream
<
Char
>&>
()
<<
std
::
declval
<
U
>
()),
std
::
true_type
())
static
bool_constant
<!
std
::
is_same
<
decltype
(
std
::
declval
<
test_stream
<
Char
>&>
()
<<
std
::
declval
<
U
>
()),
void_t
<>>::
value
>
test
(
int
);
template
<
typename
>
static
std
::
false_type
test
(...);
...
...
@@ -75,8 +79,7 @@ void write(std::basic_ostream<Char>& os, buffer<Char>& buf) {
const
Char
*
buf_data
=
buf
.
data
();
using
unsigned_streamsize
=
std
::
make_unsigned
<
std
::
streamsize
>::
type
;
unsigned_streamsize
size
=
buf
.
size
();
unsigned_streamsize
max_size
=
to_unsigned
((
std
::
numeric_limits
<
std
::
streamsize
>::
max
)());
unsigned_streamsize
max_size
=
to_unsigned
(
max_value
<
std
::
streamsize
>
());
do
{
unsigned_streamsize
n
=
size
<=
max_size
?
size
:
max_size
;
os
.
write
(
buf_data
,
static_cast
<
std
::
streamsize
>
(
n
));
...
...
@@ -86,9 +89,11 @@ void write(std::basic_ostream<Char>& os, buffer<Char>& buf) {
}
template
<
typename
Char
,
typename
T
>
void
format_value
(
buffer
<
Char
>&
buf
,
const
T
&
value
)
{
void
format_value
(
buffer
<
Char
>&
buf
,
const
T
&
value
,
locale_ref
loc
=
locale_ref
())
{
formatbuf
<
Char
>
format_buf
(
buf
);
std
::
basic_ostream
<
Char
>
output
(
&
format_buf
);
if
(
loc
)
output
.
imbue
(
loc
.
get
<
std
::
locale
>
());
output
.
exceptions
(
std
::
ios_base
::
failbit
|
std
::
ios_base
::
badbit
);
output
<<
value
;
buf
.
resize
(
buf
.
size
());
...
...
@@ -101,7 +106,7 @@ struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
template
<
typename
Context
>
auto
format
(
const
T
&
value
,
Context
&
ctx
)
->
decltype
(
ctx
.
out
())
{
basic_memory_buffer
<
Char
>
buffer
;
format_value
(
buffer
,
value
);
format_value
(
buffer
,
value
,
ctx
.
locale
()
);
basic_string_view
<
Char
>
str
(
buffer
.
data
(),
buffer
.
size
());
return
formatter
<
basic_string_view
<
Char
>
,
Char
>::
format
(
str
,
ctx
);
}
...
...
include/spdlog/fmt/bundled/posix.h
View file @
0db4b04a
...
...
@@ -13,11 +13,10 @@
# undef __STRICT_ANSI__
#endif
#include <errno.h>
#include <fcntl.h> // for O_RDONLY
#include <locale.h> // for locale_t
#include <stdio.h>
#include <stdlib.h> // for strtod_l
#include <cerrno>
#include <clocale> // for locale_t
#include <cstdio>
#include <cstdlib> // for strtod_l
#include <cstddef>
...
...
@@ -27,6 +26,18 @@
#include "format.h"
// UWP doesn't provide _pipe.
#if FMT_HAS_INCLUDE("winapifamily.h")
# include <winapifamily.h>
#endif
#if FMT_HAS_INCLUDE("fcntl.h") && \
(!defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
# include <fcntl.h> // for O_RDONLY
# define FMT_USE_FCNTL 1
#else
# define FMT_USE_FCNTL 0
#endif
#ifndef FMT_POSIX
# if defined(_WIN32) && !defined(__MINGW32__)
// Fix warnings about deprecated symbols.
...
...
@@ -54,8 +65,8 @@
#ifndef _WIN32
# define FMT_RETRY_VAL(result, expression, error_result) \
do { \
result = (expression);
\
} while (
result == error_result
&& errno == EINTR)
(result) = (expression);
\
} while (
(result) == (error_result)
&& errno == EINTR)
#else
# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#endif
...
...
@@ -132,16 +143,15 @@ class buffered_file {
explicit
buffered_file
(
FILE
*
f
)
:
file_
(
f
)
{}
public
:
buffered_file
(
const
buffered_file
&
)
=
delete
;
void
operator
=
(
const
buffered_file
&
)
=
delete
;
// Constructs a buffered_file object which doesn't represent any file.
buffered_file
()
FMT_NOEXCEPT
:
file_
(
nullptr
)
{}
// Destroys the object closing the file it represents if any.
FMT_API
~
buffered_file
()
FMT_NOEXCEPT
;
private
:
buffered_file
(
const
buffered_file
&
)
=
delete
;
void
operator
=
(
const
buffered_file
&
)
=
delete
;
public
:
buffered_file
(
buffered_file
&&
other
)
FMT_NOEXCEPT
:
file_
(
other
.
file_
)
{
other
.
file_
=
nullptr
;
...
...
@@ -177,6 +187,7 @@ class buffered_file {
}
};
#if FMT_USE_FCNTL
// A file. Closed file is represented by a file object with descriptor -1.
// Methods that are not declared with FMT_NOEXCEPT may throw
// fmt::system_error in case of failure. Note that some errors such as
...
...
@@ -204,14 +215,13 @@ class file {
// Opens a file and constructs a file object representing this file.
FMT_API
file
(
cstring_view
path
,
int
oflag
);
p
rivate
:
p
ublic
:
file
(
const
file
&
)
=
delete
;
void
operator
=
(
const
file
&
)
=
delete
;
public
:
file
(
file
&&
other
)
FMT_NOEXCEPT
:
fd_
(
other
.
fd_
)
{
other
.
fd_
=
-
1
;
}
file
&
operator
=
(
file
&&
other
)
{
file
&
operator
=
(
file
&&
other
)
FMT_NOEXCEPT
{
close
();
fd_
=
other
.
fd_
;
other
.
fd_
=
-
1
;
...
...
@@ -260,6 +270,7 @@ class file {
// Returns the memory page size.
long
getpagesize
();
#endif // FMT_USE_FCNTL
#ifdef FMT_LOCALE
// A "C" numeric locale.
...
...
@@ -283,11 +294,10 @@ class Locale {
locale_t
locale_
;
Locale
(
const
Locale
&
)
=
delete
;
void
operator
=
(
const
Locale
&
)
=
delete
;
public
:
using
type
=
locale_t
;
Locale
(
const
Locale
&
)
=
delete
;
void
operator
=
(
const
Locale
&
)
=
delete
;
Locale
()
:
locale_
(
newlocale
(
LC_NUMERIC_MASK
,
"C"
,
nullptr
))
{
if
(
!
locale_
)
FMT_THROW
(
system_error
(
errno
,
"cannot create locale"
));
...
...
include/spdlog/fmt/bundled/printf.h
View file @
0db4b04a
// Formatting library for C++
// Formatting library for C++
- legacy printf implementation
//
// Copyright (c) 2012 - 2016, Victor Zverovich
// All rights reserved.
...
...
@@ -8,7 +8,7 @@
#ifndef FMT_PRINTF_H_
#define FMT_PRINTF_H_
#include <algorithm> // std::
fill_n
#include <algorithm> // std::
max
#include <limits> // std::numeric_limits
#include "ostream.h"
...
...
@@ -16,15 +16,11 @@
FMT_BEGIN_NAMESPACE
namespace
internal
{
// A helper function to suppress bogus "conditional expression is constant"
// warnings.
template
<
typename
T
>
inline
T
const_check
(
T
value
)
{
return
value
;
}
// Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers.
template
<
bool
IsSigned
>
struct
int_checker
{
template
<
typename
T
>
static
bool
fits_in_int
(
T
value
)
{
unsigned
max
=
std
::
numeric_limits
<
int
>::
max
();
unsigned
max
=
max_value
<
int
>
();
return
value
<=
max
;
}
static
bool
fits_in_int
(
bool
)
{
return
true
;
}
...
...
@@ -33,7 +29,7 @@ template <bool IsSigned> struct int_checker {
template
<>
struct
int_checker
<
true
>
{
template
<
typename
T
>
static
bool
fits_in_int
(
T
value
)
{
return
value
>=
std
::
numeric_limits
<
int
>::
min
()
&&
value
<=
std
::
numeric_limits
<
int
>::
max
();
value
<=
max_value
<
int
>
();
}
static
bool
fits_in_int
(
int
)
{
return
true
;
}
};
...
...
@@ -158,12 +154,12 @@ template <typename Char> class printf_width_handler {
template
<
typename
T
,
FMT_ENABLE_IF
(
std
::
is_integral
<
T
>::
value
)
>
unsigned
operator
()(
T
value
)
{
auto
width
=
static_cast
<
uint32_or_64_t
<
T
>>
(
value
);
auto
width
=
static_cast
<
uint32_or_64_
or_128_
t
<
T
>>
(
value
);
if
(
internal
::
is_negative
(
value
))
{
specs_
.
align
=
align
::
left
;
width
=
0
-
width
;
}
unsigned
int_max
=
std
::
numeric_limits
<
int
>::
max
();
unsigned
int_max
=
max_value
<
int
>
();
if
(
width
>
int_max
)
FMT_THROW
(
format_error
(
"number is too big"
));
return
static_cast
<
unsigned
>
(
width
);
}
...
...
@@ -235,7 +231,7 @@ class printf_arg_formatter : public internal::arg_formatter_base<Range> {
printf_arg_formatter
(
iterator
iter
,
format_specs
&
specs
,
context_type
&
ctx
)
:
base
(
Range
(
iter
),
&
specs
,
internal
::
locale_ref
()),
context_
(
ctx
)
{}
template
<
typename
T
,
FMT_ENABLE_IF
(
std
::
is_integral
<
T
>::
value
)
>
template
<
typename
T
,
FMT_ENABLE_IF
(
fmt
::
internal
::
is_integral
<
T
>::
value
)
>
iterator
operator
()(
T
value
)
{
// MSVC2013 fails to compile separate overloads for bool and char_type so
// use std::is_same instead.
...
...
@@ -332,14 +328,14 @@ template <typename OutputIt, typename Char> class basic_printf_context {
OutputIt
out_
;
basic_format_args
<
basic_printf_context
>
args_
;
basic_parse_context
<
Char
>
parse_ctx_
;
basic_
format_
parse_context
<
Char
>
parse_ctx_
;
static
void
parse_flags
(
format_specs
&
specs
,
const
Char
*&
it
,
const
Char
*
end
);
// Returns the argument with specified index or, if arg_index is equal
// to the maximum unsigned value, the next argument.
format_arg
get_arg
(
unsigned
arg_index
=
std
::
numeric_limits
<
unsigned
>::
max
());
format_arg
get_arg
(
unsigned
arg_index
=
internal
::
max_value
<
unsigned
>
());
// Parses argument index, flags and width and returns the argument index.
unsigned
parse_header
(
const
Char
*&
it
,
const
Char
*
end
,
format_specs
&
specs
);
...
...
@@ -361,15 +357,14 @@ template <typename OutputIt, typename Char> class basic_printf_context {
format_arg
arg
(
unsigned
id
)
const
{
return
args_
.
get
(
id
);
}
basic_parse_context
<
Char
>&
parse_context
()
{
return
parse_ctx_
;
}
basic_
format_
parse_context
<
Char
>&
parse_context
()
{
return
parse_ctx_
;
}
FMT_CONSTEXPR
void
on_error
(
const
char
*
message
)
{
parse_ctx_
.
on_error
(
message
);
}
/** Formats stored arguments and writes the output to the range. */
template
<
typename
ArgFormatter
=
printf_arg_formatter
<
internal
::
buffer_range
<
Char
>>>
template
<
typename
ArgFormatter
=
printf_arg_formatter
<
buffer_range
<
Char
>>>
OutputIt
format
();
};
...
...
@@ -403,7 +398,7 @@ void basic_printf_context<OutputIt, Char>::parse_flags(format_specs& specs,
template
<
typename
OutputIt
,
typename
Char
>
typename
basic_printf_context
<
OutputIt
,
Char
>::
format_arg
basic_printf_context
<
OutputIt
,
Char
>::
get_arg
(
unsigned
arg_index
)
{
if
(
arg_index
==
std
::
numeric_limits
<
unsigned
>::
max
())
if
(
arg_index
==
internal
::
max_value
<
unsigned
>
())
arg_index
=
parse_ctx_
.
next_arg_id
();
else
parse_ctx_
.
check_arg_id
(
--
arg_index
);
...
...
@@ -413,7 +408,7 @@ basic_printf_context<OutputIt, Char>::get_arg(unsigned arg_index) {
template
<
typename
OutputIt
,
typename
Char
>
unsigned
basic_printf_context
<
OutputIt
,
Char
>::
parse_header
(
const
Char
*&
it
,
const
Char
*
end
,
format_specs
&
specs
)
{
unsigned
arg_index
=
std
::
numeric_limits
<
unsigned
>::
max
();
unsigned
arg_index
=
internal
::
max_value
<
unsigned
>
();
char_type
c
=
*
it
;
if
(
c
>=
'0'
&&
c
<=
'9'
)
{
// Parse an argument index (if followed by '$') or a width possibly
...
...
@@ -470,6 +465,7 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
// Parse argument index, flags and width.
unsigned
arg_index
=
parse_header
(
it
,
end
,
specs
);
if
(
arg_index
==
0
)
on_error
(
"argument index out of range"
);
// Parse precision.
if
(
it
!=
end
&&
*
it
==
'.'
)
{
...
...
include/spdlog/fmt/bundled/ranges.h
View file @
0db4b04a
...
...
@@ -246,7 +246,8 @@ template <typename T, typename Char> struct is_range {
static
FMT_CONSTEXPR_DECL
const
bool
value
=
internal
::
is_range_
<
T
>::
value
&&
!
internal
::
is_like_std_string
<
T
>::
value
&&
!
std
::
is_convertible
<
T
,
std
::
basic_string
<
Char
>>::
value
;
!
std
::
is_convertible
<
T
,
std
::
basic_string
<
Char
>>::
value
&&
!
std
::
is_constructible
<
internal
::
std_string_view
<
Char
>
,
T
>::
value
;
};
template
<
typename
RangeT
,
typename
Char
>
...
...
@@ -283,6 +284,82 @@ struct formatter<RangeT, Char,
}
};
template
<
typename
Char
,
typename
...
T
>
struct
tuple_arg_join
:
internal
::
view
{
const
std
::
tuple
<
T
...
>&
tuple
;
basic_string_view
<
Char
>
sep
;
tuple_arg_join
(
const
std
::
tuple
<
T
...
>&
t
,
basic_string_view
<
Char
>
s
)
:
tuple
{
t
},
sep
{
s
}
{}
};
template
<
typename
Char
,
typename
...
T
>
struct
formatter
<
tuple_arg_join
<
Char
,
T
...
>
,
Char
>
{
template
<
typename
ParseContext
>
FMT_CONSTEXPR
auto
parse
(
ParseContext
&
ctx
)
->
decltype
(
ctx
.
begin
())
{
return
ctx
.
begin
();
}
template
<
typename
FormatContext
>
typename
FormatContext
::
iterator
format
(
const
tuple_arg_join
<
Char
,
T
...
>&
value
,
FormatContext
&
ctx
)
{
return
format
(
value
,
ctx
,
internal
::
make_index_sequence
<
sizeof
...(
T
)
>
{});
}
private
:
template
<
typename
FormatContext
,
size_t
...
N
>
typename
FormatContext
::
iterator
format
(
const
tuple_arg_join
<
Char
,
T
...
>&
value
,
FormatContext
&
ctx
,
internal
::
index_sequence
<
N
...
>
)
{
return
format_args
(
value
,
ctx
,
std
::
get
<
N
>
(
value
.
tuple
)...);
}
template
<
typename
FormatContext
>
typename
FormatContext
::
iterator
format_args
(
const
tuple_arg_join
<
Char
,
T
...
>&
,
FormatContext
&
ctx
)
{
// NOTE: for compilers that support C++17, this empty function instantiation
// can be replaced with a constexpr branch in the variadic overload.
return
ctx
.
out
();
}
template
<
typename
FormatContext
,
typename
Arg
,
typename
...
Args
>
typename
FormatContext
::
iterator
format_args
(
const
tuple_arg_join
<
Char
,
T
...
>&
value
,
FormatContext
&
ctx
,
const
Arg
&
arg
,
const
Args
&
...
args
)
{
using
base
=
formatter
<
typename
std
::
decay
<
Arg
>::
type
,
Char
>
;
auto
out
=
ctx
.
out
();
out
=
base
{}.
format
(
arg
,
ctx
);
if
(
sizeof
...(
Args
)
>
0
)
{
out
=
std
::
copy
(
value
.
sep
.
begin
(),
value
.
sep
.
end
(),
out
);
ctx
.
advance_to
(
out
);
return
format_args
(
value
,
ctx
,
args
...);
}
return
out
;
}
};
/**
\rst
Returns an object that formats `tuple` with elements separated by `sep`.
**Example**::
std::tuple<int, char> t = {1, 'a'};
fmt::print("{}", fmt::join(t, ", "));
// Output: "1, a"
\endrst
*/
template
<
typename
...
T
>
FMT_CONSTEXPR
tuple_arg_join
<
char
,
T
...
>
join
(
const
std
::
tuple
<
T
...
>&
tuple
,
string_view
sep
)
{
return
{
tuple
,
sep
};
}
template
<
typename
...
T
>
FMT_CONSTEXPR
tuple_arg_join
<
wchar_t
,
T
...
>
join
(
const
std
::
tuple
<
T
...
>&
tuple
,
wstring_view
sep
)
{
return
{
tuple
,
sep
};
}
FMT_END_NAMESPACE
#endif // FMT_RANGES_H_
include/spdlog/fmt/bundled/safe-duration-cast.h
deleted
100644 → 0
View file @
1aa9ea92
/*
* For conversion between std::chrono::durations without undefined
* behaviour or erroneous results.
* This is a stripped down version of duration_cast, for inclusion in fmt.
* See https://github.com/pauldreik/safe_duration_cast
*
* Copyright Paul Dreik 2019
*
* This file is licensed under the fmt license, see format.h
*/
#include <chrono>
#include <cmath>
#include <limits>
#include <type_traits>
#include "format.h"
FMT_BEGIN_NAMESPACE
namespace
safe_duration_cast
{
template
<
typename
To
,
typename
From
,
FMT_ENABLE_IF
(
!
std
::
is_same
<
From
,
To
>::
value
&&
std
::
numeric_limits
<
From
>::
is_signed
==
std
::
numeric_limits
<
To
>::
is_signed
)
>
FMT_CONSTEXPR
To
lossless_integral_conversion
(
const
From
from
,
int
&
ec
)
{
ec
=
0
;
using
F
=
std
::
numeric_limits
<
From
>
;
using
T
=
std
::
numeric_limits
<
To
>
;
static_assert
(
F
::
is_integer
,
"From must be integral"
);
static_assert
(
T
::
is_integer
,
"To must be integral"
);
// A and B are both signed, or both unsigned.
if
(
F
::
digits
<=
T
::
digits
)
{
// From fits in To without any problem.
}
else
{
// From does not always fit in To, resort to a dynamic check.
if
(
from
<
T
::
min
()
||
from
>
T
::
max
())
{
// outside range.
ec
=
1
;
return
{};
}
}
return
static_cast
<
To
>
(
from
);
}
/**
* converts From to To, without loss. If the dynamic value of from
* can't be converted to To without loss, ec is set.
*/
template
<
typename
To
,
typename
From
,
FMT_ENABLE_IF
(
!
std
::
is_same
<
From
,
To
>::
value
&&
std
::
numeric_limits
<
From
>::
is_signed
!=
std
::
numeric_limits
<
To
>::
is_signed
)
>
FMT_CONSTEXPR
To
lossless_integral_conversion
(
const
From
from
,
int
&
ec
)
{
ec
=
0
;
using
F
=
std
::
numeric_limits
<
From
>
;
using
T
=
std
::
numeric_limits
<
To
>
;
static_assert
(
F
::
is_integer
,
"From must be integral"
);
static_assert
(
T
::
is_integer
,
"To must be integral"
);
if
(
F
::
is_signed
&&
!
T
::
is_signed
)
{
// From may be negative, not allowed!
if
(
from
<
0
)
{
ec
=
1
;
return
{};
}
// From is positive. Can it always fit in To?
if
(
F
::
digits
<=
T
::
digits
)
{
// yes, From always fits in To.
}
else
{
// from may not fit in To, we have to do a dynamic check
if
(
from
>
static_cast
<
From
>
(
T
::
max
()))
{
ec
=
1
;
return
{};
}
}
}
if
(
!
F
::
is_signed
&&
T
::
is_signed
)
{
// can from be held in To?
if
(
F
::
digits
<
T
::
digits
)
{
// yes, From always fits in To.
}
else
{
// from may not fit in To, we have to do a dynamic check
if
(
from
>
static_cast
<
From
>
(
T
::
max
()))
{
// outside range.
ec
=
1
;
return
{};
}
}
}
// reaching here means all is ok for lossless conversion.
return
static_cast
<
To
>
(
from
);
}
// function
template
<
typename
To
,
typename
From
,
FMT_ENABLE_IF
(
std
::
is_same
<
From
,
To
>::
value
)
>
FMT_CONSTEXPR
To
lossless_integral_conversion
(
const
From
from
,
int
&
ec
)
{
ec
=
0
;
return
from
;
}
// function
// clang-format off
/**
* converts From to To if possible, otherwise ec is set.
*
* input | output
* ---------------------------------|---------------
* NaN | NaN
* Inf | Inf
* normal, fits in output | converted (possibly lossy)
* normal, does not fit in output | ec is set
* subnormal | best effort
* -Inf | -Inf
*/
// clang-format on
template
<
typename
To
,
typename
From
,
FMT_ENABLE_IF
(
!
std
::
is_same
<
From
,
To
>::
value
)
>
FMT_CONSTEXPR
To
safe_float_conversion
(
const
From
from
,
int
&
ec
)
{
ec
=
0
;
using
T
=
std
::
numeric_limits
<
To
>
;
static_assert
(
std
::
is_floating_point
<
From
>::
value
,
"From must be floating"
);
static_assert
(
std
::
is_floating_point
<
To
>::
value
,
"To must be floating"
);
// catch the only happy case
if
(
std
::
isfinite
(
from
))
{
if
(
from
>=
T
::
lowest
()
&&
from
<=
T
::
max
())
{
return
static_cast
<
To
>
(
from
);
}
// not within range.
ec
=
1
;
return
{};
}
// nan and inf will be preserved
return
static_cast
<
To
>
(
from
);
}
// function
template
<
typename
To
,
typename
From
,
FMT_ENABLE_IF
(
std
::
is_same
<
From
,
To
>::
value
)
>
FMT_CONSTEXPR
To
safe_float_conversion
(
const
From
from
,
int
&
ec
)
{
ec
=
0
;
static_assert
(
std
::
is_floating_point
<
From
>::
value
,
"From must be floating"
);
return
from
;
}
/**
* safe duration cast between integral durations
*/
template
<
typename
To
,
typename
FromRep
,
typename
FromPeriod
,
FMT_ENABLE_IF
(
std
::
is_integral
<
FromRep
>::
value
),
FMT_ENABLE_IF
(
std
::
is_integral
<
typename
To
::
rep
>::
value
)
>
To
safe_duration_cast
(
std
::
chrono
::
duration
<
FromRep
,
FromPeriod
>
from
,
int
&
ec
)
{
using
From
=
std
::
chrono
::
duration
<
FromRep
,
FromPeriod
>
;
ec
=
0
;
// the basic idea is that we need to convert from count() in the from type
// to count() in the To type, by multiplying it with this:
using
Factor
=
std
::
ratio_divide
<
typename
From
::
period
,
typename
To
::
period
>
;
static_assert
(
Factor
::
num
>
0
,
"num must be positive"
);
static_assert
(
Factor
::
den
>
0
,
"den must be positive"
);
// the conversion is like this: multiply from.count() with Factor::num
// /Factor::den and convert it to To::rep, all this without
// overflow/underflow. let's start by finding a suitable type that can hold
// both To, From and Factor::num
using
IntermediateRep
=
typename
std
::
common_type
<
typename
From
::
rep
,
typename
To
::
rep
,
decltype
(
Factor
::
num
)
>::
type
;
// safe conversion to IntermediateRep
IntermediateRep
count
=
lossless_integral_conversion
<
IntermediateRep
>
(
from
.
count
(),
ec
);
if
(
ec
)
{
return
{};
}
// multiply with Factor::num without overflow or underflow
if
(
Factor
::
num
!=
1
)
{
constexpr
auto
max1
=
std
::
numeric_limits
<
IntermediateRep
>::
max
()
/
Factor
::
num
;
if
(
count
>
max1
)
{
ec
=
1
;
return
{};
}
constexpr
auto
min1
=
std
::
numeric_limits
<
IntermediateRep
>::
min
()
/
Factor
::
num
;
if
(
count
<
min1
)
{
ec
=
1
;
return
{};
}
count
*=
Factor
::
num
;
}
// this can't go wrong, right? den>0 is checked earlier.
if
(
Factor
::
den
!=
1
)
{
count
/=
Factor
::
den
;
}
// convert to the to type, safely
using
ToRep
=
typename
To
::
rep
;
const
ToRep
tocount
=
lossless_integral_conversion
<
ToRep
>
(
count
,
ec
);
if
(
ec
)
{
return
{};
}
return
To
{
tocount
};
}
/**
* safe duration_cast between floating point durations
*/
template
<
typename
To
,
typename
FromRep
,
typename
FromPeriod
,
FMT_ENABLE_IF
(
std
::
is_floating_point
<
FromRep
>::
value
),
FMT_ENABLE_IF
(
std
::
is_floating_point
<
typename
To
::
rep
>::
value
)
>
To
safe_duration_cast
(
std
::
chrono
::
duration
<
FromRep
,
FromPeriod
>
from
,
int
&
ec
)
{
using
From
=
std
::
chrono
::
duration
<
FromRep
,
FromPeriod
>
;
ec
=
0
;
if
(
std
::
isnan
(
from
.
count
()))
{
// nan in, gives nan out. easy.
return
To
{
std
::
numeric_limits
<
typename
To
::
rep
>::
quiet_NaN
()};
}
// maybe we should also check if from is denormal, and decide what to do about
// it.
// +-inf should be preserved.
if
(
std
::
isinf
(
from
.
count
()))
{
return
To
{
from
.
count
()};
}
// the basic idea is that we need to convert from count() in the from type
// to count() in the To type, by multiplying it with this:
using
Factor
=
std
::
ratio_divide
<
typename
From
::
period
,
typename
To
::
period
>
;
static_assert
(
Factor
::
num
>
0
,
"num must be positive"
);
static_assert
(
Factor
::
den
>
0
,
"den must be positive"
);
// the conversion is like this: multiply from.count() with Factor::num
// /Factor::den and convert it to To::rep, all this without
// overflow/underflow. let's start by finding a suitable type that can hold
// both To, From and Factor::num
using
IntermediateRep
=
typename
std
::
common_type
<
typename
From
::
rep
,
typename
To
::
rep
,
decltype
(
Factor
::
num
)
>::
type
;
// force conversion of From::rep -> IntermediateRep to be safe,
// even if it will never happen be narrowing in this context.
IntermediateRep
count
=
safe_float_conversion
<
IntermediateRep
>
(
from
.
count
(),
ec
);
if
(
ec
)
{
return
{};
}
// multiply with Factor::num without overflow or underflow
if
(
Factor
::
num
!=
1
)
{
constexpr
auto
max1
=
std
::
numeric_limits
<
IntermediateRep
>::
max
()
/
static_cast
<
IntermediateRep
>
(
Factor
::
num
);
if
(
count
>
max1
)
{
ec
=
1
;
return
{};
}
constexpr
auto
min1
=
std
::
numeric_limits
<
IntermediateRep
>::
lowest
()
/
static_cast
<
IntermediateRep
>
(
Factor
::
num
);
if
(
count
<
min1
)
{
ec
=
1
;
return
{};
}
count
*=
static_cast
<
IntermediateRep
>
(
Factor
::
num
);
}
// this can't go wrong, right? den>0 is checked earlier.
if
(
Factor
::
den
!=
1
)
{
using
common_t
=
typename
std
::
common_type
<
IntermediateRep
,
intmax_t
>::
type
;
count
/=
static_cast
<
common_t
>
(
Factor
::
den
);
}
// convert to the to type, safely
using
ToRep
=
typename
To
::
rep
;
const
ToRep
tocount
=
safe_float_conversion
<
ToRep
>
(
count
,
ec
);
if
(
ec
)
{
return
{};
}
return
To
{
tocount
};
}
}
// namespace safe_duration_cast
FMT_END_NAMESPACE
src/fmt.cpp
View file @
0db4b04a
...
...
@@ -9,27 +9,60 @@
#if !defined(SPDLOG_FMT_EXTERNAL)
#include "spdlog/fmt/bundled/format-inl.h"
FMT_BEGIN_NAMESPACE
template
struct
internal
::
basic_data
<
void
>
;
template
FMT_API
internal
::
locale_ref
::
locale_ref
(
const
std
::
locale
&
loc
);
template
struct
FMT_API
internal
::
basic_data
<
void
>
;
// Workaround a bug in MSVC2013 that prevents instantiation of format_float.
int
(
*
instantiate_format_float
)(
double
,
int
,
internal
::
float_specs
,
internal
::
buffer
<
char
>&
)
=
internal
::
format_float
;
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
template
FMT_API
internal
::
locale_ref
::
locale_ref
(
const
std
::
locale
&
loc
);
template
FMT_API
std
::
locale
internal
::
locale_ref
::
get
<
std
::
locale
>
()
const
;
#endif
// Explicit instantiations for char.
template
FMT_API
std
::
string
internal
::
grouping_impl
<
char
>
(
locale_ref
);
template
FMT_API
char
internal
::
thousands_sep_impl
(
locale_ref
);
template
FMT_API
char
internal
::
decimal_point_impl
(
locale_ref
);
template
FMT_API
void
internal
::
buffer
<
char
>::
append
(
const
char
*
,
const
char
*
);
template
FMT_API
void
internal
::
arg_map
<
format_context
>::
init
(
const
basic_format_args
<
format_context
>
&
args
);
template
FMT_API
std
::
string
internal
::
vformat
<
char
>
(
string_view
,
basic_format_args
<
format_context
>
);
template
FMT_API
format_context
::
iterator
internal
::
vformat_to
(
internal
::
buffer
<
char
>
&
,
string_view
,
basic_format_args
<
format_context
>
);
template
FMT_API
char
*
internal
::
sprintf_format
(
double
,
internal
::
buffer
<
char
>
&
,
sprintf_specs
);
template
FMT_API
char
*
internal
::
sprintf_format
(
long
double
,
internal
::
buffer
<
char
>
&
,
sprintf_specs
);
template
FMT_API
void
internal
::
buffer
<
char
>::
append
(
const
char
*
,
const
char
*
);
template
FMT_API
void
internal
::
arg_map
<
format_context
>::
init
(
const
basic_format_args
<
format_context
>&
args
);
template
FMT_API
std
::
string
internal
::
vformat
<
char
>
(
string_view
,
basic_format_args
<
format_context
>
);
template
FMT_API
format_context
::
iterator
internal
::
vformat_to
(
internal
::
buffer
<
char
>&
,
string_view
,
basic_format_args
<
format_context
>
);
template
FMT_API
int
internal
::
snprintf_float
(
double
,
int
,
internal
::
float_specs
,
internal
::
buffer
<
char
>&
);
template
FMT_API
int
internal
::
snprintf_float
(
long
double
,
int
,
internal
::
float_specs
,
internal
::
buffer
<
char
>&
);
template
FMT_API
int
internal
::
format_float
(
double
,
int
,
internal
::
float_specs
,
internal
::
buffer
<
char
>&
);
template
FMT_API
int
internal
::
format_float
(
long
double
,
int
,
internal
::
float_specs
,
internal
::
buffer
<
char
>&
);
// Explicit instantiations for wchar_t.
template
FMT_API
std
::
string
internal
::
grouping_impl
<
wchar_t
>
(
locale_ref
);
template
FMT_API
wchar_t
internal
::
thousands_sep_impl
(
locale_ref
);
template
FMT_API
wchar_t
internal
::
decimal_point_impl
(
locale_ref
);
template
FMT_API
void
internal
::
buffer
<
wchar_t
>::
append
(
const
wchar_t
*
,
const
wchar_t
*
);
template
FMT_API
void
internal
::
arg_map
<
wformat_context
>::
init
(
const
basic_format_args
<
wformat_context
>
&
);
template
FMT_API
std
::
wstring
internal
::
vformat
<
wchar_t
>
(
wstring_view
,
basic_format_args
<
wformat_context
>
);
template
FMT_API
void
internal
::
buffer
<
wchar_t
>::
append
(
const
wchar_t
*
,
const
wchar_t
*
);
template
FMT_API
std
::
wstring
internal
::
vformat
<
wchar_t
>
(
wstring_view
,
basic_format_args
<
wformat_context
>
);
FMT_END_NAMESPACE
#endif
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