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
7b3fc4ba
Commit
7b3fc4ba
authored
Nov 26, 2015
by
gabime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
updated to latest cppformat
parent
cbc8ba72
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
978 additions
and
611 deletions
+978
-611
format.cc
include/spdlog/details/format.cc
+188
-96
format.h
include/spdlog/details/format.h
+790
-515
No files found.
include/spdlog/details/format.cc
View file @
7b3fc4ba
/*
Formatting library for C++
Copyright (c) 2012 - 2015, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
Formatting library for C++
Copyright (c) 2012 - 2015, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "format.h"
...
...
@@ -34,6 +34,7 @@
#include <climits>
#include <cmath>
#include <cstdarg>
#include <cstddef> // for std::ptrdiff_t
#if defined(_WIN32) && defined(__MINGW32__)
# include <cstring>
...
...
@@ -133,7 +134,9 @@ struct IntChecker {
unsigned
max
=
INT_MAX
;
return
value
<=
max
;
}
static
bool
fits_in_int
(
bool
)
{
return
true
;
}
static
bool
fits_in_int
(
bool
)
{
return
true
;
}
};
template
<>
...
...
@@ -142,12 +145,14 @@ struct IntChecker<true> {
static
bool
fits_in_int
(
T
value
)
{
return
value
>=
INT_MIN
&&
value
<=
INT_MAX
;
}
static
bool
fits_in_int
(
int
)
{
return
true
;
}
static
bool
fits_in_int
(
int
)
{
return
true
;
}
};
const
char
RESET_COLOR
[]
=
"
\x1b
[0m"
;
typedef
void
(
*
FormatFunc
)(
fmt
::
Writer
&
,
int
,
fmt
::
StringRef
);
typedef
void
(
*
FormatFunc
)(
fmt
::
Writer
&
,
int
,
fmt
::
StringRef
);
// Portable thread-safe version of strerror.
// Sets buffer to point to a string describing the error code.
...
...
@@ -159,7 +164,7 @@ typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
// other - failure
// Buffer should be at least of size 1.
int
safe_strerror
(
int
error_code
,
char
*&
buffer
,
std
::
size_t
buffer_size
)
FMT_NOEXCEPT
{
int
error_code
,
char
*&
buffer
,
std
::
size_t
buffer_size
)
FMT_NOEXCEPT
{
FMT_ASSERT
(
buffer
!=
0
&&
buffer_size
!=
0
,
"invalid buffer"
);
class
StrError
{
...
...
@@ -218,7 +223,7 @@ int safe_strerror(
}
void
format_error_code
(
fmt
::
Writer
&
out
,
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
// Report error code making sure that the output fits into
// INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
// bad_alloc.
...
...
@@ -236,7 +241,7 @@ void format_error_code(fmt::Writer &out, int error_code,
}
void
report_error
(
FormatFunc
func
,
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
fmt
::
MemoryWriter
full_message
;
func
(
full_message
,
error_code
,
message
);
// Use Writer::data instead of Writer::c_str to avoid potential memory
...
...
@@ -247,9 +252,11 @@ void report_error(FormatFunc func,
// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
class
IsZeroInt
:
public
fmt
::
internal
::
ArgVisitor
<
IsZeroInt
,
bool
>
{
public
:
public
:
template
<
typename
T
>
bool
visit_any_int
(
T
value
)
{
return
value
==
0
;
}
bool
visit_any_int
(
T
value
)
{
return
value
==
0
;
}
};
// Parses an unsigned integer advancing s to the end of the parsed input.
...
...
@@ -299,12 +306,12 @@ void check_sign(const Char *&s, const Arg &arg) {
// Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative.
class
WidthHandler
:
public
fmt
::
internal
::
ArgVisitor
<
WidthHandler
,
unsigned
>
{
private
:
private
:
fmt
::
FormatSpec
&
spec_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
WidthHandler
);
public
:
public
:
explicit
WidthHandler
(
fmt
::
FormatSpec
&
spec
)
:
spec_
(
spec
)
{}
void
report_unhandled_arg
()
{
...
...
@@ -327,7 +334,7 @@ class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
class
PrecisionHandler
:
public
fmt
::
internal
::
ArgVisitor
<
PrecisionHandler
,
int
>
{
public
:
public
:
void
report_unhandled_arg
()
{
FMT_THROW
(
fmt
::
FormatError
(
"precision is not integer"
));
}
...
...
@@ -343,16 +350,21 @@ class PrecisionHandler :
// Converts an integer argument to an integral type T for printf.
template
<
typename
T
>
class
ArgConverter
:
public
fmt
::
internal
::
ArgVisitor
<
ArgConverter
<
T
>
,
void
>
{
private
:
private
:
fmt
::
internal
::
Arg
&
arg_
;
wchar_t
type_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
ArgConverter
);
public
:
public
:
ArgConverter
(
fmt
::
internal
::
Arg
&
arg
,
wchar_t
type
)
:
arg_
(
arg
),
type_
(
type
)
{}
void
visit_bool
(
bool
value
)
{
if
(
type_
!=
's'
)
visit_any_int
(
value
);
}
template
<
typename
U
>
void
visit_any_int
(
U
value
)
{
bool
is_signed
=
type_
==
'd'
||
type_
==
'i'
;
...
...
@@ -362,17 +374,20 @@ class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
if
(
is_signed
)
{
arg_
.
type
=
Arg
::
INT
;
arg_
.
int_value
=
static_cast
<
int
>
(
static_cast
<
T
>
(
value
));
}
else
{
}
else
{
arg_
.
type
=
Arg
::
UINT
;
arg_
.
uint_value
=
static_cast
<
unsigned
>
(
static_cast
<
typename
fmt
::
internal
::
MakeUnsigned
<
T
>::
Type
>
(
value
));
}
}
else
{
}
else
{
if
(
is_signed
)
{
arg_
.
type
=
Arg
::
LONG_LONG
;
arg_
.
long_long_value
=
static_cast
<
typename
fmt
::
internal
::
MakeUnsigned
<
U
>::
Type
>
(
value
);
}
else
{
}
else
{
arg_
.
type
=
Arg
::
ULONG_LONG
;
arg_
.
ulong_long_value
=
static_cast
<
typename
fmt
::
internal
::
MakeUnsigned
<
U
>::
Type
>
(
value
);
...
...
@@ -383,12 +398,12 @@ class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
// Converts an integer argument to char for printf.
class
CharConverter
:
public
fmt
::
internal
::
ArgVisitor
<
CharConverter
,
void
>
{
private
:
private
:
fmt
::
internal
::
Arg
&
arg_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
CharConverter
);
public
:
public
:
explicit
CharConverter
(
fmt
::
internal
::
Arg
&
arg
)
:
arg_
(
arg
)
{}
template
<
typename
T
>
...
...
@@ -403,34 +418,55 @@ namespace internal {
template
<
typename
Impl
,
typename
Char
>
class
BasicArgFormatter
:
public
ArgVisitor
<
Impl
,
void
>
{
private
:
private
:
BasicWriter
<
Char
>
&
writer_
;
FormatSpec
&
spec_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
BasicArgFormatter
);
protected
:
BasicWriter
<
Char
>
&
writer
()
{
return
writer_
;
}
const
FormatSpec
&
spec
()
const
{
return
spec_
;
}
void
write_pointer
(
const
void
*
p
)
{
spec_
.
flags_
=
HASH_FLAG
;
spec_
.
type_
=
'x'
;
writer_
.
write_int
(
reinterpret_cast
<
uintptr_t
>
(
p
),
spec_
);
}
public
:
protected
:
BasicWriter
<
Char
>
&
writer
()
{
return
writer_
;
}
FormatSpec
&
spec
()
{
return
spec_
;
}
void
write
(
bool
value
)
{
const
char
*
str_value
=
value
?
"true"
:
"false"
;
Arg
::
StringValue
<
char
>
str
=
{
str_value
,
strlen
(
str_value
)
};
writer_
.
write_str
(
str
,
spec_
);
}
void
write
(
const
char
*
value
)
{
Arg
::
StringValue
<
char
>
str
=
{
value
,
value
!=
0
?
strlen
(
value
)
:
0
};
writer_
.
write_str
(
str
,
spec_
);
}
public
:
BasicArgFormatter
(
BasicWriter
<
Char
>
&
w
,
FormatSpec
&
s
)
:
writer_
(
w
),
spec_
(
s
)
{}
template
<
typename
T
>
void
visit_any_int
(
T
value
)
{
writer_
.
write_int
(
value
,
spec_
);
}
void
visit_any_int
(
T
value
)
{
writer_
.
write_int
(
value
,
spec_
);
}
template
<
typename
T
>
void
visit_any_double
(
T
value
)
{
writer_
.
write_double
(
value
,
spec_
);
}
void
visit_any_double
(
T
value
)
{
writer_
.
write_double
(
value
,
spec_
);
}
void
visit_bool
(
bool
value
)
{
if
(
spec_
.
type_
)
{
writer_
.
write_int
(
value
,
spec_
);
return
;
}
const
char
*
str_value
=
value
?
"true"
:
"false"
;
Arg
::
StringValue
<
char
>
str
=
{
str_value
,
strlen
(
str_value
)
};
writer_
.
write_str
(
str
,
spec_
);
if
(
spec_
.
type_
)
return
visit_any_int
(
value
);
write
(
value
);
}
void
visit_char
(
int
value
)
{
...
...
@@ -450,18 +486,27 @@ class BasicArgFormatter : public ArgVisitor<Impl, void> {
if
(
spec_
.
align_
==
ALIGN_RIGHT
)
{
std
::
fill_n
(
out
,
spec_
.
width_
-
CHAR_WIDTH
,
fill
);
out
+=
spec_
.
width_
-
CHAR_WIDTH
;
}
else
if
(
spec_
.
align_
==
ALIGN_CENTER
)
{
}
else
if
(
spec_
.
align_
==
ALIGN_CENTER
)
{
out
=
writer_
.
fill_padding
(
out
,
spec_
.
width_
,
internal
::
check
(
CHAR_WIDTH
),
fill
);
}
else
{
}
else
{
std
::
fill_n
(
out
+
CHAR_WIDTH
,
spec_
.
width_
-
CHAR_WIDTH
,
fill
);
}
}
else
{
}
else
{
out
=
writer_
.
grow_buffer
(
CHAR_WIDTH
);
}
*
out
=
internal
::
CharTraits
<
Char
>::
cast
(
value
);
}
void
visit_cstring
(
const
char
*
value
)
{
if
(
spec_
.
type_
==
'p'
)
return
write_pointer
(
value
);
write
(
value
);
}
void
visit_string
(
Arg
::
StringValue
<
char
>
value
)
{
writer_
.
write_str
(
value
,
spec_
);
}
...
...
@@ -475,20 +520,18 @@ class BasicArgFormatter : public ArgVisitor<Impl, void> {
void
visit_pointer
(
const
void
*
value
)
{
if
(
spec_
.
type_
&&
spec_
.
type_
!=
'p'
)
report_unknown_type
(
spec_
.
type_
,
"pointer"
);
spec_
.
flags_
=
HASH_FLAG
;
spec_
.
type_
=
'x'
;
writer_
.
write_int
(
reinterpret_cast
<
uintptr_t
>
(
value
),
spec_
);
write_pointer
(
value
);
}
};
// An argument formatter.
template
<
typename
Char
>
class
ArgFormatter
:
public
BasicArgFormatter
<
ArgFormatter
<
Char
>
,
Char
>
{
private
:
private
:
BasicFormatter
<
Char
>
&
formatter_
;
const
Char
*
format_
;
public
:
public
:
ArgFormatter
(
BasicFormatter
<
Char
>
&
f
,
FormatSpec
&
s
,
const
Char
*
fmt
)
:
BasicArgFormatter
<
ArgFormatter
<
Char
>
,
Char
>
(
f
.
writer
(),
s
),
formatter_
(
f
),
format_
(
fmt
)
{}
...
...
@@ -501,10 +544,26 @@ class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> {
template
<
typename
Char
>
class
PrintfArgFormatter
:
public
BasicArgFormatter
<
PrintfArgFormatter
<
Char
>
,
Char
>
{
public
:
void
write_null_pointer
()
{
this
->
spec
().
type_
=
0
;
this
->
write
(
"(nil)"
);
}
typedef
BasicArgFormatter
<
PrintfArgFormatter
<
Char
>
,
Char
>
Base
;
public
:
PrintfArgFormatter
(
BasicWriter
<
Char
>
&
w
,
FormatSpec
&
s
)
:
BasicArgFormatter
<
PrintfArgFormatter
<
Char
>
,
Char
>
(
w
,
s
)
{}
void
visit_bool
(
bool
value
)
{
FormatSpec
&
fmt_spec
=
this
->
spec
();
if
(
fmt_spec
.
type_
!=
's'
)
return
this
->
visit_any_int
(
value
);
fmt_spec
.
type_
=
0
;
this
->
write
(
value
);
}
void
visit_char
(
int
value
)
{
const
FormatSpec
&
fmt_spec
=
this
->
spec
();
BasicWriter
<
Char
>
&
w
=
this
->
writer
();
...
...
@@ -518,18 +577,36 @@ class PrintfArgFormatter :
if
(
fmt_spec
.
align_
!=
ALIGN_LEFT
)
{
std
::
fill_n
(
out
,
fmt_spec
.
width_
-
1
,
fill
);
out
+=
fmt_spec
.
width_
-
1
;
}
else
{
}
else
{
std
::
fill_n
(
out
+
1
,
fmt_spec
.
width_
-
1
,
fill
);
}
}
else
{
}
else
{
out
=
w
.
grow_buffer
(
1
);
}
*
out
=
static_cast
<
Char
>
(
value
);
}
void
visit_cstring
(
const
char
*
value
)
{
if
(
value
)
Base
::
visit_cstring
(
value
);
else
if
(
this
->
spec
().
type_
==
'p'
)
write_null_pointer
();
else
this
->
write
(
"(null)"
);
}
void
visit_pointer
(
const
void
*
value
)
{
if
(
value
)
return
Base
::
visit_pointer
(
value
);
this
->
spec
().
type_
=
0
;
write_null_pointer
();
}
void
visit_custom
(
Arg
::
CustomValue
c
)
{
BasicFormatter
<
Char
>
formatter
(
ArgList
(),
this
->
writer
());
const
Char
format_str
[]
=
{
'}'
,
0
};
const
Char
format_str
[]
=
{
'}'
,
0
};
const
Char
*
format
=
format_str
;
c
.
format
(
&
formatter
,
c
.
value
,
&
format
);
}
...
...
@@ -672,18 +749,22 @@ FMT_FUNC void fmt::WindowsError::init(
FMT_FUNC
void
fmt
::
internal
::
format_windows_error
(
fmt
::
Writer
&
out
,
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
class
String
{
private
:
LPWSTR
str_
;
public
:
String
()
:
str_
()
{}
~
String
()
{
LocalFree
(
str_
);
}
LPWSTR
*
ptr
()
{
return
&
str_
;
}
~
String
()
{
LocalFree
(
str_
);
}
LPWSTR
*
ptr
()
{
return
&
str_
;
}
LPCWSTR
c_str
()
const
{
return
str_
;
}
};
FMT_TRY
{
FMT_TRY
{
String
system_message
;
if
(
FormatMessageW
(
FORMAT_MESSAGE_ALLOCATE_BUFFER
|
FORMAT_MESSAGE_FROM_SYSTEM
|
FORMAT_MESSAGE_IGNORE_INSERTS
,
0
,
...
...
@@ -696,15 +777,15 @@ FMT_FUNC void fmt::internal::format_windows_error(
}
}
}
FMT_CATCH
(...)
{}
format_error_code
(
out
,
error_code
,
message
);
fmt
::
format_error_code
(
out
,
error_code
,
message
);
// 'fmt::' is for bcc32.
}
#endif // FMT_USE_WINDOWS_H
FMT_FUNC
void
fmt
::
internal
::
format_system_error
(
fmt
::
Writer
&
out
,
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
FMT_TRY
{
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
FMT_TRY
{
MemoryBuffer
<
char
,
INLINE_BUFFER_SIZE
>
buffer
;
buffer
.
resize
(
INLINE_BUFFER_SIZE
);
for
(;;)
{
...
...
@@ -719,7 +800,7 @@ FMT_FUNC void fmt::internal::format_system_error(
buffer
.
resize
(
buffer
.
size
()
*
2
);
}
}
FMT_CATCH
(...)
{}
format_error_code
(
out
,
error_code
,
message
);
fmt
::
format_error_code
(
out
,
error_code
,
message
);
// 'fmt::' is for bcc32.
}
template
<
typename
Char
>
...
...
@@ -741,7 +822,8 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
map_
.
insert
(
Pair
(
named_arg
->
name
,
*
named_arg
));
break
;
default
:
/*nothing*/
;
/*nothing*/
;
}
}
return
;
...
...
@@ -762,7 +844,8 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
map_
.
insert
(
Pair
(
named_arg
->
name
,
*
named_arg
));
break
;
default
:
/*nothing*/
;
/*nothing*/
;
}
}
}
...
...
@@ -787,8 +870,6 @@ void fmt::BasicWriter<Char>::write_str(
FMT_THROW
(
FormatError
(
"string pointer is null"
));
return
;
}
if
(
*
str_value
)
str_size
=
std
::
char_traits
<
StrChar
>::
length
(
str_value
);
}
std
::
size_t
precision
=
spec
.
precision_
;
if
(
spec
.
precision_
>=
0
&&
precision
<
str_size
)
...
...
@@ -846,7 +927,8 @@ FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
case
Arg
:
:
NAMED_ARG
:
arg
=
*
static_cast
<
const
internal
::
Arg
*>
(
arg
.
pointer
);
default
:
/*nothing*/
;
/*nothing*/
;
}
return
arg
;
}
...
...
@@ -924,7 +1006,8 @@ unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
if
(
*
s
==
'$'
)
{
// value is an argument index
++
s
;
arg_index
=
value
;
}
else
{
}
else
{
if
(
c
==
'0'
)
spec
.
fill_
=
'0'
;
if
(
value
!=
0
)
{
...
...
@@ -939,7 +1022,8 @@ unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
// Parse width.
if
(
*
s
>=
'0'
&&
*
s
<=
'9'
)
{
spec
.
width_
=
parse_nonnegative_int
(
s
);
}
else
if
(
*
s
==
'*'
)
{
}
else
if
(
*
s
==
'*'
)
{
++
s
;
spec
.
width_
=
WidthHandler
(
spec
).
visit
(
get_arg
(
s
));
}
...
...
@@ -972,7 +1056,8 @@ void fmt::internal::PrintfFormatter<Char>::format(
++
s
;
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
{
spec
.
precision_
=
parse_nonnegative_int
(
s
);
}
else
if
(
*
s
==
'*'
)
{
}
else
if
(
*
s
==
'*'
)
{
++
s
;
spec
.
precision_
=
PrecisionHandler
().
visit
(
get_arg
(
s
));
}
...
...
@@ -1006,10 +1091,10 @@ void fmt::internal::PrintfFormatter<Char>::format(
ArgConverter
<
intmax_t
>
(
arg
,
*
s
).
visit
(
arg
);
break
;
case
'z'
:
ArgConverter
<
size_t
>
(
arg
,
*
s
).
visit
(
arg
);
ArgConverter
<
std
::
size_t
>
(
arg
,
*
s
).
visit
(
arg
);
break
;
case
't'
:
ArgConverter
<
ptrdiff_t
>
(
arg
,
*
s
).
visit
(
arg
);
ArgConverter
<
std
::
ptrdiff_t
>
(
arg
,
*
s
).
visit
(
arg
);
break
;
case
'L'
:
// printf produces garbage when 'L' is omitted for long double, no
...
...
@@ -1027,7 +1112,8 @@ void fmt::internal::PrintfFormatter<Char>::format(
if
(
arg
.
type
<=
Arg
::
LAST_INTEGER_TYPE
)
{
// Normalize type.
switch
(
spec
.
type_
)
{
case
'i'
:
case
'u'
:
case
'i'
:
case
'u'
:
spec
.
type_
=
'd'
;
break
;
case
'c'
:
...
...
@@ -1082,7 +1168,8 @@ const Char *fmt::BasicFormatter<Char>::format(
FMT_THROW
(
FormatError
(
"invalid fill character '{'"
));
s
+=
2
;
spec
.
fill_
=
c
;
}
else
++
s
;
}
else
++
s
;
if
(
spec
.
align_
==
ALIGN_NUMERIC
)
require_numeric_argument
(
arg
,
'='
);
break
;
...
...
@@ -1123,7 +1210,8 @@ const Char *fmt::BasicFormatter<Char>::format(
// Parse width.
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
{
spec
.
width_
=
parse_nonnegative_int
(
s
);
}
else
if
(
*
s
==
'{'
)
{
}
else
if
(
*
s
==
'{'
)
{
++
s
;
Arg
width_arg
=
is_name_start
(
*
s
)
?
parse_arg_name
(
s
)
:
parse_arg_index
(
s
);
...
...
@@ -1161,7 +1249,8 @@ const Char *fmt::BasicFormatter<Char>::format(
spec
.
precision_
=
0
;
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
{
spec
.
precision_
=
parse_nonnegative_int
(
s
);
}
else
if
(
*
s
==
'{'
)
{
}
else
if
(
*
s
==
'{'
)
{
++
s
;
Arg
precision_arg
=
is_name_start
(
*
s
)
?
parse_arg_name
(
s
)
:
parse_arg_index
(
s
);
...
...
@@ -1191,7 +1280,8 @@ const Char *fmt::BasicFormatter<Char>::format(
if
(
value
>
INT_MAX
)
FMT_THROW
(
FormatError
(
"number is too big"
));
spec
.
precision_
=
static_cast
<
int
>
(
value
);
}
else
{
}
else
{
FMT_THROW
(
FormatError
(
"missing precision specifier"
));
}
if
(
arg
.
type
<=
Arg
::
LAST_INTEGER_TYPE
||
arg
.
type
==
Arg
::
POINTER
)
{
...
...
@@ -1236,14 +1326,16 @@ void fmt::BasicFormatter<Char>::format(BasicCStringRef<Char> format_str) {
}
FMT_FUNC
void
fmt
::
report_system_error
(
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
report_error
(
internal
::
format_system_error
,
error_code
,
message
);
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
// 'fmt::' is for bcc32.
fmt
::
report_error
(
internal
::
format_system_error
,
error_code
,
message
);
}
#if FMT_USE_WINDOWS_H
FMT_FUNC
void
fmt
::
report_windows_error
(
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
report_error
(
internal
::
format_windows_error
,
error_code
,
message
);
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
// 'fmt::' is for bcc32.
fmt
::
report_error
(
internal
::
format_windows_error
,
error_code
,
message
);
}
#endif
...
...
include/spdlog/details/format.h
View file @
7b3fc4ba
/*
Formatting library for C++
Copyright (c) 2012 - 2015, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
Formatting library for C++
Copyright (c) 2012 - 2015, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FMT_FORMAT_H_
#define FMT_FORMAT_H_
#define FMT_HEADER_ONLY
#include <stdint.h>
#include <cassert>
#include <cmath>
#include <cstddef> // for std::ptrdiff_t
#include <cstdio>
#include <algorithm>
#include <limits>
...
...
@@ -46,7 +46,7 @@
#endif
#if FMT_USE_IOSTREAMS
# include <
s
stream>
# include <
o
stream>
#endif
#ifdef _SECURE_SCL
...
...
@@ -117,7 +117,7 @@ inline uint32_t clzll(uint64_t x) {
# define FMT_GCC_EXTENSION
#endif
#if
def __clang__
#if
defined(__clang__) && !defined(__INTEL_COMPILER)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdocumentation"
#endif
...
...
@@ -208,7 +208,7 @@ inline uint32_t clzll(uint64_t x) {
// makes the fmt::literals implementation easier. However, an explicit check
// for variadic templates is added here just in case.
# define FMT_USE_USER_DEFINED_LITERALS \
FMT_USE_VARIADIC_TEMPLATES && \
FMT_USE_VARIADIC_TEMPLATES &&
FMT_USE_RVALUE_REFERENCES &&
\
(FMT_HAS_FEATURE(cxx_user_literals) || \
(FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1900)
#endif
...
...
@@ -217,6 +217,94 @@ inline uint32_t clzll(uint64_t x) {
# define FMT_ASSERT(condition, message) assert((condition) && message)
#endif
namespace
fmt
{
namespace
internal
{
struct
DummyInt
{
int
data
[
2
];
operator
int
()
const
{
return
0
;
}
};
typedef
std
::
numeric_limits
<
fmt
::
internal
::
DummyInt
>
FPUtil
;
// Dummy implementations of system functions such as signbit and ecvt called
// if the latter are not available.
inline
DummyInt
signbit
(...)
{
return
DummyInt
();
}
inline
DummyInt
_ecvt_s
(...)
{
return
DummyInt
();
}
inline
DummyInt
isinf
(...)
{
return
DummyInt
();
}
inline
DummyInt
_finite
(...)
{
return
DummyInt
();
}
inline
DummyInt
isnan
(...)
{
return
DummyInt
();
}
inline
DummyInt
_isnan
(...)
{
return
DummyInt
();
}
// A helper function to suppress bogus "conditional expression is constant"
// warnings.
template
<
typename
T
>
inline
T
check
(
T
value
)
{
return
value
;
}
}
}
// namespace fmt
namespace
std
{
// Standard permits specialization of std::numeric_limits. This specialization
// is used to resolve ambiguity between isinf and std::isinf in glibc:
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48891
// and the same for isnan and signbit.
template
<>
class
numeric_limits
<
fmt
::
internal
::
DummyInt
>
:
public
std
::
numeric_limits
<
int
>
{
public
:
// Portable version of isinf.
template
<
typename
T
>
static
bool
isinfinity
(
T
x
)
{
using
namespace
fmt
::
internal
;
// The resolution "priority" is:
// isinf macro > std::isinf > ::isinf > fmt::internal::isinf
if
(
check
(
sizeof
(
isinf
(
x
))
==
sizeof
(
bool
)
||
sizeof
(
isinf
(
x
))
==
sizeof
(
int
)))
{
return
isinf
(
x
);
}
return
!
_finite
(
static_cast
<
double
>
(
x
));
}
// Portable version of isnan.
template
<
typename
T
>
static
bool
isnotanumber
(
T
x
)
{
using
namespace
fmt
::
internal
;
if
(
check
(
sizeof
(
isnan
(
x
))
==
sizeof
(
bool
)
||
sizeof
(
isnan
(
x
))
==
sizeof
(
int
)))
{
return
isnan
(
x
);
}
return
_isnan
(
static_cast
<
double
>
(
x
))
!=
0
;
}
// Portable version of signbit.
static
bool
isnegative
(
double
x
)
{
using
namespace
fmt
::
internal
;
if
(
check
(
sizeof
(
signbit
(
x
))
==
sizeof
(
int
)))
return
signbit
(
x
);
if
(
x
<
0
)
return
true
;
if
(
!
isnotanumber
(
x
))
return
false
;
int
dec
=
0
,
sign
=
0
;
char
buffer
[
2
];
// The buffer size must be >= 2 or _ecvt_s will fail.
_ecvt_s
(
buffer
,
sizeof
(
buffer
),
x
,
0
,
&
dec
,
&
sign
);
return
sign
!=
0
;
}
};
}
// namespace std
namespace
fmt
{
// Fix the warning about long long on older versions of GCC
...
...
@@ -241,36 +329,36 @@ template <typename Char, typename T>
void
format
(
BasicFormatter
<
Char
>
&
f
,
const
Char
*&
format_str
,
const
T
&
value
);
/**
\rst
A string reference. It can be constructed from a C string or ``std::string``.
\rst
A string reference. It can be constructed from a C string or ``std::string``.
You can use one of the following typedefs for common character types:
You can use one of the following typedefs for common character types:
+------------+-------------------------+
| Type | Definition |
+============+=========================+
| StringRef | BasicStringRef<char> |
+------------+-------------------------+
| WStringRef | BasicStringRef<wchar_t> |
+------------+-------------------------+
+------------+-------------------------+
| Type | Definition |
+============+=========================+
| StringRef | BasicStringRef<char> |
+------------+-------------------------+
| WStringRef | BasicStringRef<wchar_t> |
+------------+-------------------------+
This class is most useful as a parameter type to allow passing
different types of strings to a function, for example::
This class is most useful as a parameter type to allow passing
different types of strings to a function, for example::
template <typename... Args>
std::string format(StringRef format_str, const Args & ... args);
template <typename... Args>
std::string format(StringRef format_str, const Args & ... args);
format("{}", 42);
format(std::string("{}"), 42);
\endrst
*/
format("{}", 42);
format(std::string("{}"), 42);
\endrst
*/
template
<
typename
Char
>
class
BasicStringRef
{
private
:
private
:
const
Char
*
data_
;
std
::
size_t
size_
;
public
:
public
:
/** Constructs a string reference object from a C string and a size. */
BasicStringRef
(
const
Char
*
s
,
std
::
size_t
size
)
:
data_
(
s
),
size_
(
size
)
{}
...
...
@@ -301,10 +389,14 @@ class BasicStringRef {
}
/** Returns the pointer to a C string. */
const
Char
*
data
()
const
{
return
data_
;
}
const
Char
*
data
()
const
{
return
data_
;
}
/** Returns the string size. */
std
::
size_t
size
()
const
{
return
size_
;
}
std
::
size_t
size
()
const
{
return
size_
;
}
// Lexicographically compare this string reference to other.
int
compare
(
BasicStringRef
other
)
const
{
...
...
@@ -339,36 +431,36 @@ typedef BasicStringRef<char> StringRef;
typedef
BasicStringRef
<
wchar_t
>
WStringRef
;
/**
\rst
A reference to a null terminated string. It can be constructed from a C
string or ``std::string``.
\rst
A reference to a null terminated string. It can be constructed from a C
string or ``std::string``.
You can use one of the following typedefs for common character types:
You can use one of the following typedefs for common character types:
+-------------+--------------------------+
| Type | Definition |
+=============+==========================+
| CStringRef | BasicCStringRef<char> |
+-------------+--------------------------+
| WCStringRef | BasicCStringRef<wchar_t> |
+-------------+--------------------------+
+-------------+--------------------------+
| Type | Definition |
+=============+==========================+
| CStringRef | BasicCStringRef<char> |
+-------------+--------------------------+
| WCStringRef | BasicCStringRef<wchar_t> |
+-------------+--------------------------+
This class is most useful as a parameter type to allow passing
different types of strings to a function, for example::
This class is most useful as a parameter type to allow passing
different types of strings to a function, for example::
template <typename... Args>
std::string format(CStringRef format_str, const Args & ... args);
template <typename... Args>
std::string format(CStringRef format_str, const Args & ... args);
format("{}", 42);
format(std::string("{}"), 42);
\endrst
*/
format("{}", 42);
format(std::string("{}"), 42);
\endrst
*/
template
<
typename
Char
>
class
BasicCStringRef
{
private
:
private
:
const
Char
*
data_
;
public
:
public
:
/** Constructs a string reference object from a C string. */
BasicCStringRef
(
const
Char
*
s
)
:
data_
(
s
)
{}
...
...
@@ -380,17 +472,19 @@ class BasicCStringRef {
BasicCStringRef
(
const
std
::
basic_string
<
Char
>
&
s
)
:
data_
(
s
.
c_str
())
{}
/** Returns the pointer to a C string. */
const
Char
*
c_str
()
const
{
return
data_
;
}
const
Char
*
c_str
()
const
{
return
data_
;
}
};
typedef
BasicCStringRef
<
char
>
CStringRef
;
typedef
BasicCStringRef
<
wchar_t
>
WCStringRef
;
/**
A formatting error such as invalid format string.
A formatting error such as invalid format string.
*/
class
FormatError
:
public
std
::
runtime_error
{
public
:
public
:
explicit
FormatError
(
CStringRef
message
)
:
std
::
runtime_error
(
message
.
c_str
())
{}
};
...
...
@@ -408,21 +502,23 @@ inline stdext::checked_array_iterator<T*> make_ptr(T *ptr, std::size_t size) {
}
#else
template
<
typename
T
>
inline
T
*
make_ptr
(
T
*
ptr
,
std
::
size_t
)
{
return
ptr
;
}
inline
T
*
make_ptr
(
T
*
ptr
,
std
::
size_t
)
{
return
ptr
;
}
#endif
}
// namespace internal
/**
\rst
A buffer supporting a subset of ``std::vector``'s operations.
\endrst
*/
\rst
A buffer supporting a subset of ``std::vector``'s operations.
\endrst
*/
template
<
typename
T
>
class
Buffer
{
private
:
private
:
FMT_DISALLOW_COPY_AND_ASSIGN
(
Buffer
);
protected
:
protected
:
T
*
ptr_
;
std
::
size_t
size_
;
std
::
size_t
capacity_
;
...
...
@@ -438,14 +534,18 @@ class Buffer {
*/
virtual
void
grow
(
std
::
size_t
size
)
=
0
;
public
:
public
:
virtual
~
Buffer
()
{}
/** Returns the size of this buffer. */
std
::
size_t
size
()
const
{
return
size_
;
}
std
::
size_t
size
()
const
{
return
size_
;
}
/** Returns the capacity of this buffer. */
std
::
size_t
capacity
()
const
{
return
capacity_
;
}
std
::
size_t
capacity
()
const
{
return
capacity_
;
}
/**
Resizes the buffer. If T is a POD type new elements may not be initialized.
...
...
@@ -466,7 +566,7 @@ class Buffer {
grow
(
capacity
);
}
void
clear
()
FMT_NOEXCEPT
{
size_
=
0
;
}
void
clear
()
FMT_NOEXCEPT
{
size_
=
0
;
}
void
push_back
(
const
T
&
value
)
{
if
(
size_
==
capacity_
)
...
...
@@ -478,18 +578,23 @@ class 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
];
}
T
&
operator
[](
std
::
size_t
index
)
{
return
ptr_
[
index
];
}
const
T
&
operator
[](
std
::
size_t
index
)
const
{
return
ptr_
[
index
];
}
};
template
<
typename
T
>
template
<
typename
U
>
void
Buffer
<
T
>::
append
(
const
U
*
begin
,
const
U
*
end
)
{
std
::
ptrdiff_t
num_elements
=
end
-
begin
;
if
(
size_
+
num_elements
>
capacity_
)
grow
(
size_
+
num_elements
);
assert
(
begin
<=
end
);
std
::
size_t
new_size
=
size_
+
(
end
-
begin
);
if
(
new_size
>
capacity_
)
grow
(
new_size
);
std
::
copy
(
begin
,
end
,
internal
::
make_ptr
(
ptr_
,
capacity_
)
+
size_
);
size_
+=
num_elements
;
size_
=
new_size
;
}
namespace
internal
{
...
...
@@ -498,7 +603,7 @@ namespace internal {
// the object itself.
template
<
typename
T
,
std
::
size_t
SIZE
,
typename
Allocator
=
std
::
allocator
<
T
>
>
class
MemoryBuffer
:
private
Allocator
,
public
Buffer
<
T
>
{
private
:
private
:
T
data_
[
SIZE
];
// Deallocate memory allocated by the buffer.
...
...
@@ -506,16 +611,18 @@ class MemoryBuffer : private Allocator, public Buffer<T> {
if
(
this
->
ptr_
!=
data_
)
Allocator
::
deallocate
(
this
->
ptr_
,
this
->
capacity_
);
}
protected
:
protected
:
void
grow
(
std
::
size_t
size
);
public
:
public
:
explicit
MemoryBuffer
(
const
Allocator
&
alloc
=
Allocator
())
:
Allocator
(
alloc
),
Buffer
<
T
>
(
data_
,
SIZE
)
{}
~
MemoryBuffer
()
{
deallocate
();
}
~
MemoryBuffer
()
{
deallocate
();
}
#if FMT_USE_RVALUE_REFERENCES
private
:
private
:
// Move data from other to this buffer.
void
move
(
MemoryBuffer
&
other
)
{
Allocator
&
this_alloc
=
*
this
,
&
other_alloc
=
other
;
...
...
@@ -526,7 +633,8 @@ class MemoryBuffer : private Allocator, public Buffer<T> {
this
->
ptr_
=
data_
;
std
::
copy
(
other
.
data_
,
other
.
data_
+
this
->
size_
,
make_ptr
(
data_
,
this
->
capacity_
));
}
else
{
}
else
{
this
->
ptr_
=
other
.
ptr_
;
// Set pointer to the inline array so that delete is not called
// when deallocating.
...
...
@@ -534,7 +642,7 @@ class MemoryBuffer : private Allocator, public Buffer<T> {
}
}
public
:
public
:
MemoryBuffer
(
MemoryBuffer
&&
other
)
{
move
(
other
);
}
...
...
@@ -548,7 +656,9 @@ class MemoryBuffer : private Allocator, public Buffer<T> {
#endif
// Returns a copy of the allocator associated with this buffer.
Allocator
get_allocator
()
const
{
return
*
this
;
}
Allocator
get_allocator
()
const
{
return
*
this
;
}
};
template
<
typename
T
,
std
::
size_t
SIZE
,
typename
Allocator
>
...
...
@@ -573,70 +683,24 @@ void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size) {
// A fixed-size buffer.
template
<
typename
Char
>
class
FixedBuffer
:
public
fmt
::
Buffer
<
Char
>
{
public
:
public
:
FixedBuffer
(
Char
*
array
,
std
::
size_t
size
)
:
fmt
::
Buffer
<
Char
>
(
array
,
size
)
{}
protected
:
protected
:
void
grow
(
std
::
size_t
size
);
};
#ifndef _MSC_VER
// Portable version of signbit.
inline
int
getsign
(
double
x
)
{
// When compiled in C++11 mode signbit is no longer a macro but a function
// defined in namespace std and the macro is undefined.
# ifdef signbit
return
signbit
(
x
);
# else
return
std
::
signbit
(
x
);
# endif
}
// Portable version of isinf.
# ifdef isinf
inline
int
isinfinity
(
double
x
)
{
return
isinf
(
x
);
}
inline
int
isinfinity
(
long
double
x
)
{
return
isinf
(
x
);
}
# else
inline
int
isinfinity
(
double
x
)
{
return
std
::
isinf
(
x
);
}
inline
int
isinfinity
(
long
double
x
)
{
return
std
::
isinf
(
x
);
}
# endif
// Portable version of isnan.
# ifdef isnan
inline
int
isnotanumber
(
double
x
)
{
return
isnan
(
x
);
}
inline
int
isnotanumber
(
long
double
x
)
{
return
isnan
(
x
);
}
# else
inline
int
isnotanumber
(
double
x
)
{
return
std
::
isnan
(
x
);
}
inline
int
isnotanumber
(
long
double
x
)
{
return
std
::
isnan
(
x
);
}
# endif
#else
inline
int
getsign
(
double
value
)
{
if
(
value
<
0
)
return
1
;
if
(
value
==
value
)
return
0
;
int
dec
=
0
,
sign
=
0
;
char
buffer
[
2
];
// The buffer size must be >= 2 or _ecvt_s will fail.
_ecvt_s
(
buffer
,
sizeof
(
buffer
),
value
,
0
,
&
dec
,
&
sign
);
return
sign
;
}
inline
int
isinfinity
(
double
x
)
{
return
!
_finite
(
x
);
}
inline
int
isinfinity
(
long
double
x
)
{
return
!
_finite
(
static_cast
<
double
>
(
x
));
}
inline
int
isnotanumber
(
double
x
)
{
return
_isnan
(
x
);
}
inline
int
isnotanumber
(
long
double
x
)
{
return
_isnan
(
static_cast
<
double
>
(
x
));
}
#endif
template
<
typename
Char
>
class
BasicCharTraits
{
public
:
public
:
#if FMT_SECURE_SCL
typedef
stdext
::
checked_array_iterator
<
Char
*>
CharPtr
;
#else
typedef
Char
*
CharPtr
;
#endif
static
Char
cast
(
wchar_t
value
)
{
return
static_cast
<
Char
>
(
value
);
}
static
Char
cast
(
wchar_t
value
)
{
return
static_cast
<
Char
>
(
value
);
}
};
template
<
typename
Char
>
...
...
@@ -644,12 +708,14 @@ class CharTraits;
template
<>
class
CharTraits
<
char
>
:
public
BasicCharTraits
<
char
>
{
private
:
private
:
// Conversion from wchar_t to char is not allowed.
static
char
convert
(
wchar_t
);
public
:
static
char
convert
(
char
value
)
{
return
value
;
}
public
:
static
char
convert
(
char
value
)
{
return
value
;
}
// Formats a floating-point number.
template
<
typename
T
>
...
...
@@ -659,9 +725,13 @@ class CharTraits<char> : public BasicCharTraits<char> {
template
<>
class
CharTraits
<
wchar_t
>
:
public
BasicCharTraits
<
wchar_t
>
{
public
:
static
wchar_t
convert
(
char
value
)
{
return
value
;
}
static
wchar_t
convert
(
wchar_t
value
)
{
return
value
;
}
public
:
static
wchar_t
convert
(
char
value
)
{
return
value
;
}
static
wchar_t
convert
(
wchar_t
value
)
{
return
value
;
}
template
<
typename
T
>
static
int
format_float
(
wchar_t
*
buffer
,
std
::
size_t
size
,
...
...
@@ -672,13 +742,17 @@ class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> {
template
<
bool
IsSigned
>
struct
SignChecker
{
template
<
typename
T
>
static
bool
is_negative
(
T
value
)
{
return
value
<
0
;
}
static
bool
is_negative
(
T
value
)
{
return
value
<
0
;
}
};
template
<>
struct
SignChecker
<
false
>
{
template
<
typename
T
>
static
bool
is_negative
(
T
)
{
return
false
;
}
static
bool
is_negative
(
T
)
{
return
false
;
}
};
// Returns true if value is negative, false otherwise.
...
...
@@ -690,10 +764,14 @@ inline bool is_negative(T value) {
// Selects uint32_t if FitsIn32Bits is true, uint64_t otherwise.
template
<
bool
FitsIn32Bits
>
struct
TypeSelector
{
typedef
uint32_t
Type
;
};
struct
TypeSelector
{
typedef
uint32_t
Type
;
};
template
<>
struct
TypeSelector
<
false
>
{
typedef
uint64_t
Type
;
};
struct
TypeSelector
<
false
>
{
typedef
uint64_t
Type
;
};
template
<
typename
T
>
struct
IntTraits
{
...
...
@@ -705,7 +783,9 @@ struct IntTraits {
// MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T.
template
<
typename
T
>
struct
MakeUnsigned
{
typedef
T
Type
;
};
struct
MakeUnsigned
{
typedef
T
Type
;
};
#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \
template <> \
...
...
@@ -808,30 +888,46 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
// A converter from UTF-8 to UTF-16.
// It is only provided for Windows since other systems support UTF-8 natively.
class
UTF8ToUTF16
{
private
:
private
:
MemoryBuffer
<
wchar_t
,
INLINE_BUFFER_SIZE
>
buffer_
;
public
:
public
:
explicit
UTF8ToUTF16
(
StringRef
s
);
operator
WStringRef
()
const
{
return
WStringRef
(
&
buffer_
[
0
],
size
());
}
size_t
size
()
const
{
return
buffer_
.
size
()
-
1
;
}
const
wchar_t
*
c_str
()
const
{
return
&
buffer_
[
0
];
}
std
::
wstring
str
()
const
{
return
std
::
wstring
(
&
buffer_
[
0
],
size
());
}
operator
WStringRef
()
const
{
return
WStringRef
(
&
buffer_
[
0
],
size
());
}
size_t
size
()
const
{
return
buffer_
.
size
()
-
1
;
}
const
wchar_t
*
c_str
()
const
{
return
&
buffer_
[
0
];
}
std
::
wstring
str
()
const
{
return
std
::
wstring
(
&
buffer_
[
0
],
size
());
}
};
// A converter from UTF-16 to UTF-8.
// It is only provided for Windows since other systems support UTF-8 natively.
class
UTF16ToUTF8
{
private
:
private
:
MemoryBuffer
<
char
,
INLINE_BUFFER_SIZE
>
buffer_
;
public
:
public
:
UTF16ToUTF8
()
{}
explicit
UTF16ToUTF8
(
WStringRef
s
);
operator
StringRef
()
const
{
return
StringRef
(
&
buffer_
[
0
],
size
());
}
size_t
size
()
const
{
return
buffer_
.
size
()
-
1
;
}
const
char
*
c_str
()
const
{
return
&
buffer_
[
0
];
}
std
::
string
str
()
const
{
return
std
::
string
(
&
buffer_
[
0
],
size
());
}
operator
StringRef
()
const
{
return
StringRef
(
&
buffer_
[
0
],
size
());
}
size_t
size
()
const
{
return
buffer_
.
size
()
-
1
;
}
const
char
*
c_str
()
const
{
return
&
buffer_
[
0
];
}
std
::
string
str
()
const
{
return
std
::
string
(
&
buffer_
[
0
],
size
());
}
// Performs conversion returning a system error code instead of
// throwing exception on conversion error. This method may still throw
...
...
@@ -854,7 +950,7 @@ struct Value {
std
::
size_t
size
;
};
typedef
void
(
*
FormatFunc
)(
typedef
void
(
*
FormatFunc
)(
void
*
formatter
,
const
void
*
arg
,
void
*
format_str_ptr
);
struct
CustomValue
{
...
...
@@ -913,54 +1009,98 @@ struct WCharHelper<T, wchar_t> {
typedef
Null
<
T
>
Unsupported
;
};
typedef
char
Yes
[
1
];
typedef
char
No
[
2
];
// These are non-members to workaround an overload resolution bug in bcc32.
Yes
&
convert
(
fmt
::
ULongLong
);
Yes
&
convert
(
std
::
ostream
&
);
No
&
convert
(...);
template
<
typename
T
>
class
IsConvertibleToInt
{
protected
:
typedef
char
yes
[
1
];
typedef
char
no
[
2
];
T
&
get
();
struct
DummyStream
:
std
::
ostream
{
// Hide all operator<< overloads from std::ostream.
void
operator
<<
(
Null
<>
);
};
No
&
operator
<<
(
std
::
ostream
&
,
int
);
template
<
typename
T
,
bool
ENABLE_CONVERSION
>
struct
ConvertToIntImpl
{
enum
{
value
=
false
};
};
template
<
typename
T
>
struct
ConvertToIntImpl
<
T
,
true
>
{
// Convert to int only if T doesn't have an overloaded operator<<.
enum
{
value
=
sizeof
(
convert
(
get
<
DummyStream
>
()
<<
get
<
T
>
()))
==
sizeof
(
No
)
};
};
static
const
T
&
get
();
template
<
typename
T
,
bool
ENABLE_CONVERSION
>
struct
ConvertToIntImpl2
{
enum
{
value
=
false
};
};
static
yes
&
convert
(
fmt
::
ULongLong
);
static
no
&
convert
(...);
template
<
typename
T
>
struct
ConvertToIntImpl2
<
T
,
true
>
{
enum
{
// Don't convert numeric types.
value
=
ConvertToIntImpl
<
T
,
!
std
::
numeric_limits
<
T
>::
is_specialized
>::
value
};
};
public
:
enum
{
value
=
(
sizeof
(
convert
(
get
()))
==
sizeof
(
yes
))
};
template
<
typename
T
>
struct
ConvertToInt
{
enum
{
enable_conversion
=
sizeof
(
convert
(
get
<
T
>
()))
==
sizeof
(
Yes
)
};
enum
{
value
=
ConvertToIntImpl2
<
T
,
enable_conversion
>::
value
};
};
#define FMT_
CONVERTIBLE
_TO_INT(Type) \
#define FMT_
DISABLE_CONVERSION
_TO_INT(Type) \
template <> \
class IsConvertibleToInt<Type> { \
public: \
enum { value = 1 }; \
}
struct ConvertToInt<Type> { enum { value = 0 }; }
// Silence warnings about convering float to int.
FMT_
CONVERTIBLE
_TO_INT
(
float
);
FMT_
CONVERTIBLE
_TO_INT
(
double
);
FMT_
CONVERTIBLE
_TO_INT
(
long
double
);
FMT_
DISABLE_CONVERSION
_TO_INT
(
float
);
FMT_
DISABLE_CONVERSION
_TO_INT
(
double
);
FMT_
DISABLE_CONVERSION
_TO_INT
(
long
double
);
template
<
bool
B
,
class
T
=
void
>
struct
EnableIf
{};
template
<
class
T
>
struct
EnableIf
<
true
,
T
>
{
typedef
T
type
;
};
struct
EnableIf
<
true
,
T
>
{
typedef
T
type
;
};
template
<
bool
B
,
class
T
,
class
F
>
struct
Conditional
{
typedef
T
type
;
};
struct
Conditional
{
typedef
T
type
;
};
template
<
class
T
,
class
F
>
struct
Conditional
<
false
,
T
,
F
>
{
typedef
F
type
;
};
struct
Conditional
<
false
,
T
,
F
>
{
typedef
F
type
;
};
// A helper function to suppress bogus "conditional expression is constant"
// warnings.
template
<
typename
T
>
inline
T
check
(
T
value
)
{
return
value
;
}
// For bcc32 which doesn't understand ! in template arguments.
template
<
bool
>
struct
Not
{
enum
{
value
=
0
};
};
template
<>
struct
Not
<
false
>
{
enum
{
value
=
1
};
};
// Makes an Arg object from any type.
template
<
typename
Char
>
class
MakeValue
:
public
Arg
{
private
:
private
:
// The following two methods are private to disallow formatting of
// arbitrary pointers. If you want to output a pointer cast it to
// "void *" or "const void *". In particular, this forbids formatting
...
...
@@ -1002,7 +1142,7 @@ class MakeValue : public Arg {
*
static_cast
<
const
T
*>
(
arg
));
}
public
:
public
:
MakeValue
()
{}
#define FMT_MAKE_VALUE_(Type, field, TYPE, rhs) \
...
...
@@ -1046,15 +1186,17 @@ class MakeValue : public Arg {
FMT_MAKE_VALUE
(
float
,
double_value
,
DOUBLE
)
FMT_MAKE_VALUE
(
double
,
double_value
,
DOUBLE
)
FMT_MAKE_VALUE
(
long
double
,
long_double_value
,
LONG_DOUBLE
)
FMT_MAKE_VALUE
(
signed
char
,
int_value
,
CHAR
)
FMT_MAKE_VALUE
(
unsigned
char
,
int_value
,
CHAR
)
FMT_MAKE_VALUE
(
signed
char
,
int_value
,
INT
)
FMT_MAKE_VALUE
(
unsigned
char
,
uint_value
,
UINT
)
FMT_MAKE_VALUE
(
char
,
int_value
,
CHAR
)
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
MakeValue
(
typename
WCharHelper
<
wchar_t
,
Char
>::
Supported
value
)
{
int_value
=
value
;
}
static
uint64_t
type
(
wchar_t
)
{
return
Arg
::
CHAR
;
}
static
uint64_t
type
(
wchar_t
)
{
return
Arg
::
CHAR
;
}
#endif
#define FMT_MAKE_STR_VALUE(Type, TYPE) \
...
...
@@ -1085,29 +1227,34 @@ class MakeValue : public Arg {
template
<
typename
T
>
MakeValue
(
const
T
&
value
,
typename
EnableIf
<!
IsConvertibleToInt
<
T
>::
value
,
int
>::
type
=
0
)
{
typename
EnableIf
<
Not
<
ConvertToInt
<
T
>::
value
>::
value
,
int
>::
type
=
0
)
{
custom
.
value
=
&
value
;
custom
.
format
=
&
format_custom_arg
<
T
>
;
}
template
<
typename
T
>
MakeValue
(
const
T
&
value
,
typename
EnableIf
<
IsConvertible
ToInt
<
T
>::
value
,
int
>::
type
=
0
)
{
typename
EnableIf
<
Convert
ToInt
<
T
>::
value
,
int
>::
type
=
0
)
{
int_value
=
value
;
}
template
<
typename
T
>
static
uint64_t
type
(
const
T
&
)
{
return
IsConvertible
ToInt
<
T
>::
value
?
Arg
::
INT
:
Arg
::
CUSTOM
;
return
Convert
ToInt
<
T
>::
value
?
Arg
::
INT
:
Arg
::
CUSTOM
;
}
// Additional template param `Char_` is needed here because make_type always
// uses MakeValue<char>.
template
<
typename
Char_
>
MakeValue
(
const
NamedArg
<
Char_
>
&
value
)
{
pointer
=
&
value
;
}
MakeValue
(
const
NamedArg
<
Char_
>
&
value
)
{
pointer
=
&
value
;
}
template
<
typename
Char_
>
static
uint64_t
type
(
const
NamedArg
<
Char_
>
&
)
{
return
Arg
::
NAMED_ARG
;
}
static
uint64_t
type
(
const
NamedArg
<
Char_
>
&
)
{
return
Arg
::
NAMED_ARG
;
}
};
template
<
typename
Char
>
...
...
@@ -1145,7 +1292,7 @@ struct NamedArg : Arg {
// http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
template
<
typename
Impl
,
typename
Result
>
class
ArgVisitor
{
public
:
public
:
void
report_unhandled_arg
()
{}
Result
visit_unhandled_arg
()
{
...
...
@@ -1187,6 +1334,9 @@ class ArgVisitor {
return
FMT_DISPATCH
(
visit_unhandled_arg
());
}
Result
visit_cstring
(
const
char
*
)
{
return
FMT_DISPATCH
(
visit_unhandled_arg
());
}
Result
visit_string
(
Arg
::
StringValue
<
char
>
)
{
return
FMT_DISPATCH
(
visit_unhandled_arg
());
}
...
...
@@ -1221,11 +1371,8 @@ class ArgVisitor {
return
FMT_DISPATCH
(
visit_double
(
arg
.
double_value
));
case
Arg
:
:
LONG_DOUBLE
:
return
FMT_DISPATCH
(
visit_long_double
(
arg
.
long_double_value
));
case
Arg
:
:
CSTRING
:
{
Arg
::
StringValue
<
char
>
str
=
arg
.
string
;
str
.
size
=
0
;
return
FMT_DISPATCH
(
visit_string
(
str
));
}
case
Arg
:
:
CSTRING
:
return
FMT_DISPATCH
(
visit_cstring
(
arg
.
string
.
value
));
case
Arg
:
:
STRING
:
return
FMT_DISPATCH
(
visit_string
(
arg
.
string
));
case
Arg
:
:
WSTRING
:
...
...
@@ -1239,7 +1386,7 @@ class ArgVisitor {
};
class
RuntimeError
:
public
std
::
runtime_error
{
protected
:
protected
:
RuntimeError
()
:
std
::
runtime_error
(
""
)
{}
};
...
...
@@ -1255,7 +1402,7 @@ class ArgMap;
/** An argument list. */
class
ArgList
{
private
:
private
:
// To reduce compiled code size per formatting function call, types of first
// MAX_PACKED_ARGS arguments are passed in the types_ field.
uint64_t
types_
;
...
...
@@ -1279,7 +1426,7 @@ class ArgList {
template
<
typename
Char
>
friend
class
internal
::
ArgMap
;
public
:
public
:
// Maximum number of arguments with packed types.
enum
{
MAX_PACKED_ARGS
=
16
};
...
...
@@ -1323,13 +1470,13 @@ namespace internal {
template
<
typename
Char
>
class
ArgMap
{
private
:
private
:
typedef
std
::
map
<
fmt
::
BasicStringRef
<
Char
>
,
internal
::
Arg
>
MapType
;
typedef
typename
MapType
::
value_type
Pair
;
MapType
map_
;
public
:
public
:
void
init
(
const
ArgList
&
args
);
const
internal
::
Arg
*
find
(
const
fmt
::
BasicStringRef
<
Char
>
&
name
)
const
{
...
...
@@ -1339,15 +1486,17 @@ class ArgMap {
};
class
FormatterBase
{
private
:
private
:
ArgList
args_
;
int
next_arg_index_
;
// Returns the argument with specified index.
Arg
do_get_arg
(
unsigned
arg_index
,
const
char
*&
error
);
protected
:
const
ArgList
&
args
()
const
{
return
args_
;
}
protected
:
const
ArgList
&
args
()
const
{
return
args_
;
}
explicit
FormatterBase
(
const
ArgList
&
args
)
{
args_
=
args
;
...
...
@@ -1373,7 +1522,7 @@ class FormatterBase {
// A printf formatter.
template
<
typename
Char
>
class
PrintfFormatter
:
private
FormatterBase
{
private
:
private
:
void
parse_flags
(
FormatSpec
&
spec
,
const
Char
*&
s
);
// Returns the argument with specified index or, if arg_index is equal
...
...
@@ -1384,7 +1533,7 @@ class PrintfFormatter : private FormatterBase {
// Parses argument index, flags and width and returns the argument index.
unsigned
parse_header
(
const
Char
*&
s
,
FormatSpec
&
spec
);
public
:
public
:
explicit
PrintfFormatter
(
const
ArgList
&
args
)
:
FormatterBase
(
args
)
{}
void
format
(
BasicWriter
<
Char
>
&
writer
,
BasicCStringRef
<
Char
>
format_str
);
};
...
...
@@ -1393,13 +1542,13 @@ class PrintfFormatter : private FormatterBase {
// A formatter.
template
<
typename
Char
>
class
BasicFormatter
:
private
internal
::
FormatterBase
{
private
:
private
:
BasicWriter
<
Char
>
&
writer_
;
internal
::
ArgMap
<
Char
>
map_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
BasicFormatter
);
using
FormatterBase
::
get_arg
;
using
internal
::
FormatterBase
::
get_arg
;
// Checks if manual indexing is used and returns the argument with
// specified name.
...
...
@@ -1411,11 +1560,13 @@ class BasicFormatter : private internal::FormatterBase {
// Parses argument name and returns corresponding argument.
internal
::
Arg
parse_arg_name
(
const
Char
*&
s
);
public
:
public
:
BasicFormatter
(
const
ArgList
&
args
,
BasicWriter
<
Char
>
&
w
)
:
FormatterBase
(
args
),
writer_
(
w
)
{}
:
internal
::
FormatterBase
(
args
),
writer_
(
w
)
{}
BasicWriter
<
Char
>
&
writer
()
{
return
writer_
;
}
BasicWriter
<
Char
>
&
writer
()
{
return
writer_
;
}
void
format
(
BasicCStringRef
<
Char
>
format_str
);
...
...
@@ -1438,12 +1589,24 @@ struct EmptySpec {};
// A type specifier.
template
<
char
TYPE
>
struct
TypeSpec
:
EmptySpec
{
Alignment
align
()
const
{
return
ALIGN_DEFAULT
;
}
unsigned
width
()
const
{
return
0
;
}
int
precision
()
const
{
return
-
1
;
}
bool
flag
(
unsigned
)
const
{
return
false
;
}
char
type
()
const
{
return
TYPE
;
}
char
fill
()
const
{
return
' '
;
}
Alignment
align
()
const
{
return
ALIGN_DEFAULT
;
}
unsigned
width
()
const
{
return
0
;
}
int
precision
()
const
{
return
-
1
;
}
bool
flag
(
unsigned
)
const
{
return
false
;
}
char
type
()
const
{
return
TYPE
;
}
char
fill
()
const
{
return
' '
;
}
};
// A width specifier.
...
...
@@ -1455,8 +1618,12 @@ struct WidthSpec {
WidthSpec
(
unsigned
width
,
wchar_t
fill
)
:
width_
(
width
),
fill_
(
fill
)
{}
unsigned
width
()
const
{
return
width_
;
}
wchar_t
fill
()
const
{
return
fill_
;
}
unsigned
width
()
const
{
return
width_
;
}
wchar_t
fill
()
const
{
return
fill_
;
}
};
// An alignment specifier.
...
...
@@ -1466,9 +1633,13 @@ struct AlignSpec : WidthSpec {
AlignSpec
(
unsigned
width
,
wchar_t
fill
,
Alignment
align
=
ALIGN_DEFAULT
)
:
WidthSpec
(
width
,
fill
),
align_
(
align
)
{}
Alignment
align
()
const
{
return
align_
;
}
Alignment
align
()
const
{
return
align_
;
}
int
precision
()
const
{
return
-
1
;
}
int
precision
()
const
{
return
-
1
;
}
};
// An alignment and type specifier.
...
...
@@ -1476,8 +1647,12 @@ template <char TYPE>
struct
AlignTypeSpec
:
AlignSpec
{
AlignTypeSpec
(
unsigned
width
,
wchar_t
fill
)
:
AlignSpec
(
width
,
fill
)
{}
bool
flag
(
unsigned
)
const
{
return
false
;
}
char
type
()
const
{
return
TYPE
;
}
bool
flag
(
unsigned
)
const
{
return
false
;
}
char
type
()
const
{
return
TYPE
;
}
};
// A full format specifier.
...
...
@@ -1490,76 +1665,86 @@ struct FormatSpec : AlignSpec {
unsigned
width
=
0
,
char
type
=
0
,
wchar_t
fill
=
' '
)
:
AlignSpec
(
width
,
fill
),
flags_
(
0
),
precision_
(
-
1
),
type_
(
type
)
{}
bool
flag
(
unsigned
f
)
const
{
return
(
flags_
&
f
)
!=
0
;
}
int
precision
()
const
{
return
precision_
;
}
char
type
()
const
{
return
type_
;
}
bool
flag
(
unsigned
f
)
const
{
return
(
flags_
&
f
)
!=
0
;
}
int
precision
()
const
{
return
precision_
;
}
char
type
()
const
{
return
type_
;
}
};
// An integer format specifier.
template
<
typename
T
,
typename
SpecT
=
TypeSpec
<
0
>
,
typename
Char
=
char
>
class
IntFormatSpec
:
public
SpecT
{
private
:
private
:
T
value_
;
public
:
public
:
IntFormatSpec
(
T
val
,
const
SpecT
&
spec
=
SpecT
())
:
SpecT
(
spec
),
value_
(
val
)
{}
T
value
()
const
{
return
value_
;
}
T
value
()
const
{
return
value_
;
}
};
// A string format specifier.
template
<
typename
Char
>
class
StrFormatSpec
:
public
AlignSpec
{
private
:
private
:
const
Char
*
str_
;
public
:
public
:
template
<
typename
FillChar
>
StrFormatSpec
(
const
Char
*
str
,
unsigned
width
,
FillChar
fill
)
:
AlignSpec
(
width
,
fill
),
str_
(
str
)
{
internal
::
CharTraits
<
Char
>::
convert
(
FillChar
());
}
const
Char
*
str
()
const
{
return
str_
;
}
const
Char
*
str
()
const
{
return
str_
;
}
};
/**
Returns an integer format specifier to format the value in base 2.
*/
Returns an integer format specifier to format the value in base 2.
*/
IntFormatSpec
<
int
,
TypeSpec
<
'b'
>
>
bin
(
int
value
);
/**
Returns an integer format specifier to format the value in base 8.
*/
Returns an integer format specifier to format the value in base 8.
*/
IntFormatSpec
<
int
,
TypeSpec
<
'o'
>
>
oct
(
int
value
);
/**
Returns an integer format specifier to format the value in base 16 using
lower-case letters for the digits above 9.
*/
Returns an integer format specifier to format the value in base 16 using
lower-case letters for the digits above 9.
*/
IntFormatSpec
<
int
,
TypeSpec
<
'x'
>
>
hex
(
int
value
);
/**
Returns an integer formatter format specifier to format in base 16 using
upper-case letters for the digits above 9.
*/
Returns an integer formatter format specifier to format in base 16 using
upper-case letters for the digits above 9.
*/
IntFormatSpec
<
int
,
TypeSpec
<
'X'
>
>
hexu
(
int
value
);
/**
\rst
Returns an integer format specifier to pad the formatted argument with the
fill character to the specified width using the default (right) numeric
alignment.
\rst
Returns an integer format specifier to pad the formatted argument with the
fill character to the specified width using the default (right) numeric
alignment.
**Example**::
**Example**::
MemoryWriter out;
out << pad(hex(0xcafe), 8, '0');
// out.str() == "0000cafe"
MemoryWriter out;
out << pad(hex(0xcafe), 8, '0');
// out.str() == "0000cafe"
\endrst
*/
\endrst
*/
template
<
char
TYPE_CODE
,
typename
Char
>
IntFormatSpec
<
int
,
AlignTypeSpec
<
TYPE_CODE
>
,
Char
>
pad
(
int
value
,
unsigned
width
,
Char
fill
=
' '
);
...
...
@@ -1567,26 +1752,26 @@ IntFormatSpec<int, AlignTypeSpec<TYPE_CODE>, Char> pad(
#define FMT_DEFINE_INT_FORMATTERS(TYPE) \
inline IntFormatSpec<TYPE, TypeSpec<'b'> > bin(TYPE value) { \
return IntFormatSpec<TYPE, TypeSpec<'b'> >(value, TypeSpec<'b'>()); \
} \
} \
\
inline IntFormatSpec<TYPE, TypeSpec<'o'> > oct(TYPE value) { \
return IntFormatSpec<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \
} \
} \
\
inline IntFormatSpec<TYPE, TypeSpec<'x'> > hex(TYPE value) { \
return IntFormatSpec<TYPE, TypeSpec<'x'> >(value, TypeSpec<'x'>()); \
} \
} \
\
inline IntFormatSpec<TYPE, TypeSpec<'X'> > hexu(TYPE value) { \
return IntFormatSpec<TYPE, TypeSpec<'X'> >(value, TypeSpec<'X'>()); \
} \
} \
\
template <char TYPE_CODE> \
inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> > pad( \
IntFormatSpec<TYPE, TypeSpec<TYPE_CODE> > f, unsigned width) { \
return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> >( \
f.value(), AlignTypeSpec<TYPE_CODE>(width, ' ')); \
} \
} \
\
/* For compatibility with older compilers we provide two overloads for pad, */
\
/* one that takes a fill character and one that doesn't. In the future this */
\
...
...
@@ -1598,20 +1783,20 @@ inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char> pad( \
unsigned width, Char fill) { \
return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char>( \
f.value(), AlignTypeSpec<TYPE_CODE>(width, fill)); \
} \
} \
\
inline IntFormatSpec<TYPE, AlignTypeSpec<0> > pad( \
TYPE value, unsigned width) { \
return IntFormatSpec<TYPE, AlignTypeSpec<0> >( \
value, AlignTypeSpec<0>(width, ' ')); \
} \
} \
\
template <typename Char> \
inline IntFormatSpec<TYPE, AlignTypeSpec<0>, Char> pad( \
TYPE value, unsigned width, Char fill) { \
return IntFormatSpec<TYPE, AlignTypeSpec<0>, Char>( \
value, AlignTypeSpec<0>(width, fill)); \
}
}
FMT_DEFINE_INT_FORMATTERS
(
int
)
FMT_DEFINE_INT_FORMATTERS
(
long
)
...
...
@@ -1621,17 +1806,17 @@ FMT_DEFINE_INT_FORMATTERS(LongLong)
FMT_DEFINE_INT_FORMATTERS
(
ULongLong
)
/**
\rst
Returns a string formatter that pads the formatted argument with the fill
character to the specified width using the default (left) string alignment.
\rst
Returns a string formatter that pads the formatted argument with the fill
character to the specified width using the default (left) string alignment.
**Example**::
**Example**::
std::string s = str(MemoryWriter() << pad("abc", 8));
// s == "abc "
std::string s = str(MemoryWriter() << pad("abc", 8));
// s == "abc "
\endrst
*/
\endrst
*/
template
<
typename
Char
>
inline
StrFormatSpec
<
Char
>
pad
(
const
Char
*
str
,
unsigned
width
,
Char
fill
=
' '
)
{
...
...
@@ -1663,10 +1848,14 @@ inline StrFormatSpec<wchar_t> pad(
# define FMT_GEN15(f) FMT_GEN14(f), f(14)
namespace
internal
{
inline
uint64_t
make_type
()
{
return
0
;
}
inline
uint64_t
make_type
()
{
return
0
;
}
template
<
typename
T
>
inline
uint64_t
make_type
(
const
T
&
arg
)
{
return
MakeValue
<
char
>::
type
(
arg
);
}
inline
uint64_t
make_type
(
const
T
&
arg
)
{
return
MakeValue
<
char
>::
type
(
arg
);
}
template
<
unsigned
N
>
struct
ArgArray
{
...
...
@@ -1746,13 +1935,45 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
(
t12
.
type
<<
48
)
|
(
t13
.
type
<<
52
)
|
(
t14
.
type
<<
56
);
}
#endif
template
<
class
Char
>
class
FormatBuf
:
public
std
::
basic_streambuf
<
Char
>
{
private
:
typedef
typename
std
::
basic_streambuf
<
Char
>::
int_type
int_type
;
typedef
typename
std
::
basic_streambuf
<
Char
>::
traits_type
traits_type
;
Buffer
<
Char
>
&
buffer_
;
Char
*
start_
;
public
:
FormatBuf
(
Buffer
<
Char
>
&
buffer
)
:
buffer_
(
buffer
),
start_
(
&
buffer
[
0
])
{
this
->
setp
(
start_
,
start_
+
buffer_
.
capacity
());
}
int_type
overflow
(
int_type
ch
=
traits_type
::
eof
())
{
if
(
!
traits_type
::
eq_int_type
(
ch
,
traits_type
::
eof
()))
{
size_t
size
=
this
->
pptr
()
-
start_
;
buffer_
.
resize
(
size
);
buffer_
.
reserve
(
size
*
2
);
start_
=
&
buffer_
[
0
];
start_
[
size
]
=
traits_type
::
to_char_type
(
ch
);
this
->
setp
(
start_
+
size
+
1
,
start_
+
size
*
2
);
}
return
ch
;
}
size_t
size
()
const
{
return
this
->
pptr
()
-
start_
;
}
};
}
// namespace internal
# define FMT_MAKE_TEMPLATE_ARG(n) typename T##n
# define FMT_MAKE_ARG_TYPE(n) T##n
# define FMT_MAKE_ARG(n) const T##n &v##n
# define FMT_
MAKE_REF_char(n)
fmt::internal::MakeValue<char>(v##n)
# define FMT_
MAKE_REF_wchar_t(n)
fmt::internal::MakeValue<wchar_t>(v##n)
# define FMT_
ASSIGN_char(n) arr[n] =
fmt::internal::MakeValue<char>(v##n)
# define FMT_
ASSIGN_wchar_t(n) arr[n] =
fmt::internal::MakeValue<wchar_t>(v##n)
#if FMT_USE_VARIADIC_TEMPLATES
// Defines a variadic function returning void.
...
...
@@ -1840,21 +2061,21 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8), f(x9, 9)
/**
An error returned by an operating system or a language runtime,
for example a file opening error.
An error returned by an operating system or a language runtime,
for example a file opening error.
*/
class
SystemError
:
public
internal
::
RuntimeError
{
private
:
private
:
void
init
(
int
err_code
,
CStringRef
format_str
,
ArgList
args
);
protected
:
protected
:
int
error_code_
;
typedef
char
Char
;
// For FMT_VARIADIC_CTOR.
SystemError
()
{}
public
:
public
:
/**
\rst
Constructs a :class:`fmt::SystemError` object with the description
...
...
@@ -1885,30 +2106,32 @@ class SystemError : public internal::RuntimeError {
}
FMT_VARIADIC_CTOR
(
SystemError
,
init
,
int
,
CStringRef
)
int
error_code
()
const
{
return
error_code_
;
}
int
error_code
()
const
{
return
error_code_
;
}
};
/**
\rst
This template provides operations for formatting and writing data into
a character stream. The output is stored in a buffer provided by a subclass
such as :class:`fmt::BasicMemoryWriter`.
You can use one of the following typedefs for common character types:
+---------+----------------------+
| Type | Definition |
+=========+======================+
| Writer | BasicWriter<char> |
+---------+----------------------+
| WWriter | BasicWriter<wchar_t> |
+---------+----------------------+
\endrst
*/
\rst
This template provides operations for formatting and writing data into
a character stream. The output is stored in a buffer provided by a subclass
such as :class:`fmt::BasicMemoryWriter`.
You can use one of the following typedefs for common character types:
+---------+----------------------+
| Type | Definition |
+=========+======================+
| Writer | BasicWriter<char> |
+---------+----------------------+
| WWriter | BasicWriter<wchar_t> |
+---------+----------------------+
\endrst
*/
template
<
typename
Char
>
class
BasicWriter
{
private
:
private
:
// Output buffer.
Buffer
<
Char
>
&
buffer_
;
...
...
@@ -1918,9 +2141,13 @@ class BasicWriter {
#if FMT_SECURE_SCL
// Returns pointer value.
static
Char
*
get
(
CharPtr
p
)
{
return
p
.
base
();
}
static
Char
*
get
(
CharPtr
p
)
{
return
p
.
base
();
}
#else
static
Char
*
get
(
Char
*
p
)
{
return
p
;
}
static
Char
*
get
(
Char
*
p
)
{
return
p
;
}
#endif
// Fills the padding around the content and returns the pointer to the
...
...
@@ -1952,7 +2179,8 @@ class BasicWriter {
if
(
internal
::
is_negative
(
value
))
{
abs_value
=
0
-
abs_value
;
*
write_unsigned_decimal
(
abs_value
,
1
)
=
'-'
;
}
else
{
}
else
{
write_unsigned_decimal
(
abs_value
,
0
);
}
}
...
...
@@ -2009,13 +2237,13 @@ class BasicWriter {
friend
class
internal
::
PrintfArgFormatter
<
Char
>
;
protected
:
protected
:
/**
Constructs a ``BasicWriter`` object.
*/
explicit
BasicWriter
(
Buffer
<
Char
>
&
b
)
:
buffer_
(
b
)
{}
public
:
public
:
/**
\rst
Destroys a ``BasicWriter`` object.
...
...
@@ -2026,13 +2254,17 @@ class BasicWriter {
/**
Returns the total number of characters written.
*/
std
::
size_t
size
()
const
{
return
buffer_
.
size
();
}
std
::
size_t
size
()
const
{
return
buffer_
.
size
();
}
/**
Returns a pointer to the output buffer content. No terminating null
character is appended.
*/
const
Char
*
data
()
const
FMT_NOEXCEPT
{
return
&
buffer_
[
0
];
}
const
Char
*
data
()
const
FMT_NOEXCEPT
{
return
&
buffer_
[
0
];
}
/**
Returns a pointer to the output buffer content with terminating null
...
...
@@ -2174,7 +2406,7 @@ class BasicWriter {
return
*
this
;
}
void
clear
()
FMT_NOEXCEPT
{
buffer_
.
clear
();
}
void
clear
()
FMT_NOEXCEPT
{
buffer_
.
clear
();
}
};
template
<
typename
Char
>
...
...
@@ -2188,12 +2420,15 @@ typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
if
(
spec
.
align
()
==
ALIGN_RIGHT
)
{
std
::
fill_n
(
out
,
spec
.
width
()
-
size
,
fill
);
out
+=
spec
.
width
()
-
size
;
}
else
if
(
spec
.
align
()
==
ALIGN_CENTER
)
{
}
else
if
(
spec
.
align
()
==
ALIGN_CENTER
)
{
out
=
fill_padding
(
out
,
spec
.
width
(),
size
,
fill
);
}
else
{
}
else
{
std
::
fill_n
(
out
+
size
,
spec
.
width
()
-
size
,
fill
);
}
}
else
{
}
else
{
out
=
grow_buffer
(
size
);
}
std
::
copy
(
s
,
s
+
size
,
out
);
...
...
@@ -2202,7 +2437,7 @@ typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
template
<
typename
Char
>
typename
BasicWriter
<
Char
>::
CharPtr
BasicWriter
<
Char
>::
fill_padding
(
BasicWriter
<
Char
>::
fill_padding
(
CharPtr
buffer
,
unsigned
total_size
,
std
::
size_t
content_size
,
wchar_t
fill
)
{
std
::
size_t
padding
=
total_size
-
content_size
;
...
...
@@ -2218,7 +2453,7 @@ typename BasicWriter<Char>::CharPtr
template
<
typename
Char
>
template
<
typename
Spec
>
typename
BasicWriter
<
Char
>::
CharPtr
BasicWriter
<
Char
>::
prepare_int_buffer
(
BasicWriter
<
Char
>::
prepare_int_buffer
(
unsigned
num_digits
,
const
Spec
&
spec
,
const
char
*
prefix
,
unsigned
prefix_size
)
{
unsigned
width
=
spec
.
width
();
...
...
@@ -2259,17 +2494,20 @@ typename BasicWriter<Char>::CharPtr
std
::
copy
(
prefix
,
prefix
+
prefix_size
,
p
);
p
+=
size
;
std
::
fill
(
p
,
end
,
fill
);
}
else
if
(
align
==
ALIGN_CENTER
)
{
}
else
if
(
align
==
ALIGN_CENTER
)
{
p
=
fill_padding
(
p
,
width
,
size
,
fill
);
std
::
copy
(
prefix
,
prefix
+
prefix_size
,
p
);
p
+=
size
;
}
else
{
}
else
{
if
(
align
==
ALIGN_NUMERIC
)
{
if
(
prefix_size
!=
0
)
{
p
=
std
::
copy
(
prefix
,
prefix
+
prefix_size
,
p
);
size
-=
prefix_size
;
}
}
else
{
}
else
{
std
::
copy
(
prefix
,
prefix
+
prefix_size
,
end
-
size
);
}
std
::
fill
(
p
,
end
-
size
,
fill
);
...
...
@@ -2289,19 +2527,22 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
prefix
[
0
]
=
'-'
;
++
prefix_size
;
abs_value
=
0
-
abs_value
;
}
else
if
(
spec
.
flag
(
SIGN_FLAG
))
{
}
else
if
(
spec
.
flag
(
SIGN_FLAG
))
{
prefix
[
0
]
=
spec
.
flag
(
PLUS_FLAG
)
?
'+'
:
' '
;
++
prefix_size
;
}
switch
(
spec
.
type
())
{
case
0
:
case
'd'
:
{
case
0
:
case
'd'
:
{
unsigned
num_digits
=
internal
::
count_digits
(
abs_value
);
CharPtr
p
=
prepare_int_buffer
(
num_digits
,
spec
,
prefix
,
prefix_size
)
+
1
-
num_digits
;
internal
::
format_decimal
(
get
(
p
),
abs_value
,
num_digits
);
break
;
}
case
'x'
:
case
'X'
:
{
case
'x'
:
case
'X'
:
{
UnsignedType
n
=
abs_value
;
if
(
spec
.
flag
(
HASH_FLAG
))
{
prefix
[
prefix_size
++
]
=
'0'
;
...
...
@@ -2321,7 +2562,8 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
}
while
((
n
>>=
4
)
!=
0
);
break
;
}
case
'b'
:
case
'B'
:
{
case
'b'
:
case
'B'
:
{
UnsignedType
n
=
abs_value
;
if
(
spec
.
flag
(
HASH_FLAG
))
{
prefix
[
prefix_size
++
]
=
'0'
;
...
...
@@ -2371,7 +2613,10 @@ void BasicWriter<Char>::write_double(
case
0
:
type
=
'g'
;
break
;
case
'e'
:
case
'f'
:
case
'g'
:
case
'a'
:
case
'e'
:
case
'f'
:
case
'g'
:
case
'a'
:
break
;
case
'F'
:
#ifdef _MSC_VER
...
...
@@ -2379,7 +2624,9 @@ void BasicWriter<Char>::write_double(
type
=
'f'
;
#endif
// Fall through.
case
'E'
:
case
'G'
:
case
'A'
:
case
'E'
:
case
'G'
:
case
'A'
:
upper
=
true
;
break
;
default
:
...
...
@@ -2388,16 +2635,17 @@ void BasicWriter<Char>::write_double(
}
char
sign
=
0
;
// Use getsign
instead of value < 0 because the latter is always
// Use isnegative
instead of value < 0 because the latter is always
// false for NaN.
if
(
internal
::
getsign
(
static_cast
<
double
>
(
value
)))
{
if
(
internal
::
FPUtil
::
isnegative
(
static_cast
<
double
>
(
value
)))
{
sign
=
'-'
;
value
=
-
value
;
}
else
if
(
spec
.
flag
(
SIGN_FLAG
))
{
}
else
if
(
spec
.
flag
(
SIGN_FLAG
))
{
sign
=
spec
.
flag
(
PLUS_FLAG
)
?
'+'
:
' '
;
}
if
(
interna
l
::
isnotanumber
(
value
))
{
if
(
internal
::
FPUti
l
::
isnotanumber
(
value
))
{
// Format NaN ourselves because sprintf's output is not consistent
// across platforms.
std
::
size_t
nan_size
=
4
;
...
...
@@ -2412,7 +2660,7 @@ void BasicWriter<Char>::write_double(
return
;
}
if
(
interna
l
::
isinfinity
(
value
))
{
if
(
internal
::
FPUti
l
::
isinfinity
(
value
))
{
// Format infinity ourselves because sprintf's output is not consistent
// across platforms.
std
::
size_t
inf_size
=
4
;
...
...
@@ -2437,7 +2685,7 @@ void BasicWriter<Char>::write_double(
}
// Build format string.
enum
{
MAX_FORMAT_SIZE
=
10
};
// longest format: %#-*.*Lg
enum
{
MAX_FORMAT_SIZE
=
10
};
// longest format: %#-*.*Lg
Char
format
[
MAX_FORMAT_SIZE
];
Char
*
format_ptr
=
format
;
*
format_ptr
++
=
'%'
;
...
...
@@ -2446,7 +2694,8 @@ void BasicWriter<Char>::write_double(
*
format_ptr
++
=
'#'
;
if
(
spec
.
align
()
==
ALIGN_CENTER
)
{
width_for_sprintf
=
0
;
}
else
{
}
else
{
if
(
spec
.
align
()
==
ALIGN_LEFT
)
*
format_ptr
++
=
'-'
;
if
(
width
!=
0
)
...
...
@@ -2483,7 +2732,8 @@ void BasicWriter<Char>::write_double(
*
start
!=
' '
)
{
*
(
start
-
1
)
=
sign
;
sign
=
0
;
}
else
{
}
else
{
*
(
start
-
1
)
=
fill
;
}
++
n
;
...
...
@@ -2512,45 +2762,45 @@ void BasicWriter<Char>::write_double(
}
/**
\rst
This class template provides operations for formatting and writing data
into a character stream. The output is stored in a memory buffer that grows
dynamically.
\rst
This class template provides operations for formatting and writing data
into a character stream. The output is stored in a memory buffer that grows
dynamically.
You can use one of the following typedefs for common character types
and the standard allocator:
You can use one of the following typedefs for common character types
and the standard allocator:
+---------------+-----------------------------------------------------+
| Type | Definition |
+===============+=====================================================+
| MemoryWriter | BasicMemoryWriter<char, std::allocator<char>> |
+---------------+-----------------------------------------------------+
| WMemoryWriter | BasicMemoryWriter<wchar_t, std::allocator<wchar_t>> |
+---------------+-----------------------------------------------------+
+---------------+-----------------------------------------------------+
| Type | Definition |
+===============+=====================================================+
| MemoryWriter | BasicMemoryWriter<char, std::allocator<char>> |
+---------------+-----------------------------------------------------+
| WMemoryWriter | BasicMemoryWriter<wchar_t, std::allocator<wchar_t>> |
+---------------+-----------------------------------------------------+
**Example**::
**Example**::
MemoryWriter out;
out << "The answer is " << 42 << "\n";
out.write("({:+f}, {:+f})", -3.14, 3.14);
MemoryWriter out;
out << "The answer is " << 42 << "\n";
out.write("({:+f}, {:+f})", -3.14, 3.14);
This will write the following output to the ``out`` object:
This will write the following output to the ``out`` object:
.. code-block:: none
.. code-block:: none
The answer is 42
(-3.140000, +3.140000)
The answer is 42
(-3.140000, +3.140000)
The output can be converted to an ``std::string`` with ``out.str()`` or
accessed as a C string with ``out.c_str()``.
\endrst
*/
The output can be converted to an ``std::string`` with ``out.str()`` or
accessed as a C string with ``out.c_str()``.
\endrst
*/
template
<
typename
Char
,
typename
Allocator
=
std
::
allocator
<
Char
>
>
class
BasicMemoryWriter
:
public
BasicWriter
<
Char
>
{
private
:
private
:
internal
::
MemoryBuffer
<
Char
,
internal
::
INLINE_BUFFER_SIZE
,
Allocator
>
buffer_
;
public
:
public
:
explicit
BasicMemoryWriter
(
const
Allocator
&
alloc
=
Allocator
())
:
BasicWriter
<
Char
>
(
buffer_
),
buffer_
(
alloc
)
{}
...
...
@@ -2581,31 +2831,31 @@ typedef BasicMemoryWriter<char> MemoryWriter;
typedef
BasicMemoryWriter
<
wchar_t
>
WMemoryWriter
;
/**
\rst
This class template provides operations for formatting and writing data
into a fixed-size array. For writing into a dynamically growing buffer
use :class:`fmt::BasicMemoryWriter`.
Any write method will throw ``std::runtime_error`` if the output doesn't fit
into the array.
You can use one of the following typedefs for common character types:
+--------------+---------------------------+
| Type | Definition |
+==============+===========================+
| ArrayWriter | BasicArrayWriter<char> |
+--------------+---------------------------+
| WArrayWriter | BasicArrayWriter<wchar_t> |
+--------------+---------------------------+
\endrst
*/
\rst
This class template provides operations for formatting and writing data
into a fixed-size array. For writing into a dynamically growing buffer
use :class:`fmt::BasicMemoryWriter`.
Any write method will throw ``std::runtime_error`` if the output doesn't fit
into the array.
You can use one of the following typedefs for common character types:
+--------------+---------------------------+
| Type | Definition |
+==============+===========================+
| ArrayWriter | BasicArrayWriter<char> |
+--------------+---------------------------+
| WArrayWriter | BasicArrayWriter<wchar_t> |
+--------------+---------------------------+
\endrst
*/
template
<
typename
Char
>
class
BasicArrayWriter
:
public
BasicWriter
<
Char
>
{
private
:
private
:
internal
::
FixedBuffer
<
Char
>
buffer_
;
public
:
public
:
/**
\rst
Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the
...
...
@@ -2622,7 +2872,7 @@ class BasicArrayWriter : public BasicWriter<Char> {
\endrst
*/
template
<
std
::
size_t
SIZE
>
explicit
BasicArrayWriter
(
Char
(
&
array
)[
SIZE
])
explicit
BasicArrayWriter
(
Char
(
&
array
)[
SIZE
])
:
BasicWriter
<
Char
>
(
buffer_
),
buffer_
(
array
,
SIZE
)
{}
};
...
...
@@ -2632,9 +2882,13 @@ typedef BasicArrayWriter<wchar_t> WArrayWriter;
// Formats a value.
template
<
typename
Char
,
typename
T
>
void
format
(
BasicFormatter
<
Char
>
&
f
,
const
Char
*&
format_str
,
const
T
&
value
)
{
std
::
basic_ostringstream
<
Char
>
os
;
os
<<
value
;
std
::
basic_string
<
Char
>
str
=
os
.
str
();
internal
::
MemoryBuffer
<
Char
,
internal
::
INLINE_BUFFER_SIZE
>
buffer
;
internal
::
FormatBuf
<
Char
>
format_buf
(
buffer
);
std
::
basic_ostream
<
Char
>
output
(
&
format_buf
);
output
<<
value
;
BasicStringRef
<
Char
>
str
(
&
buffer
[
0
],
format_buf
.
size
());
internal
::
Arg
arg
=
internal
::
MakeValue
<
Char
>
(
str
);
arg
.
type
=
static_cast
<
internal
::
Arg
::
Type
>
(
internal
::
MakeValue
<
Char
>::
type
(
str
));
...
...
@@ -2649,10 +2903,10 @@ void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT;
/** A Windows error. */
class
WindowsError
:
public
SystemError
{
private
:
private
:
void
init
(
int
error_code
,
CStringRef
format_str
,
ArgList
args
);
public
:
public
:
/**
\rst
Constructs a :class:`fmt::WindowsError` object with the description
...
...
@@ -2696,21 +2950,21 @@ void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT;
enum
Color
{
BLACK
,
RED
,
GREEN
,
YELLOW
,
BLUE
,
MAGENTA
,
CYAN
,
WHITE
};
/**
Formats a string and prints it to stdout using ANSI escape sequences
to specify color (experimental).
Example:
PrintColored(fmt::RED, "Elapsed time: {0:.2f} seconds") << 1.23
;
*/
Formats a string and prints it to stdout using ANSI escape sequences
to specify color (experimental).
Example:
print_colored(fmt::RED, "Elapsed time: {0:.2f} seconds", 1.23)
;
*/
void
print_colored
(
Color
c
,
CStringRef
format
,
ArgList
args
);
/**
\rst
Formats arguments and returns the result as a string.
\rst
Formats arguments and returns the result as a string.
**Example**::
**Example**::
std::string message = format("The answer is {}", 42);
\endrst
std::string message = format("The answer is {}", 42);
\endrst
*/
inline
std
::
string
format
(
CStringRef
format_str
,
ArgList
args
)
{
MemoryWriter
w
;
...
...
@@ -2725,25 +2979,25 @@ inline std::wstring format(WCStringRef format_str, ArgList args) {
}
/**
\rst
Prints formatted data to the file *f*.
\rst
Prints formatted data to the file *f*.
**Example**::
**Example**::
print(stderr, "Don't {}!", "panic");
\endrst
*/
print(stderr, "Don't {}!", "panic");
\endrst
*/
void
print
(
std
::
FILE
*
f
,
CStringRef
format_str
,
ArgList
args
);
/**
\rst
Prints formatted data to ``stdout``.
\rst
Prints formatted data to ``stdout``.
**Example**::
**Example**::
print("Elapsed time: {0:.2f} seconds", 1.23);
\endrst
*/
print("Elapsed time: {0:.2f} seconds", 1.23);
\endrst
*/
void
print
(
CStringRef
format_str
,
ArgList
args
);
template
<
typename
Char
>
...
...
@@ -2752,13 +3006,13 @@ void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) {
}
/**
\rst
Formats arguments and returns the result as a string.
\rst
Formats arguments and returns the result as a string.
**Example**::
**Example**::
std::string message = fmt::sprintf("The answer is %d", 42);
\endrst
std::string message = fmt::sprintf("The answer is %d", 42);
\endrst
*/
inline
std
::
string
sprintf
(
CStringRef
format
,
ArgList
args
)
{
MemoryWriter
w
;
...
...
@@ -2773,37 +3027,37 @@ inline std::wstring sprintf(WCStringRef format, ArgList args) {
}
/**
\rst
Prints formatted data to the file *f*.
\rst
Prints formatted data to the file *f*.
**Example**::
**Example**::
fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst
*/
fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst
*/
int
fprintf
(
std
::
FILE
*
f
,
CStringRef
format
,
ArgList
args
);
/**
\rst
Prints formatted data to ``stdout``.
\rst
Prints formatted data to ``stdout``.
**Example**::
**Example**::
fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst
*/
fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst
*/
inline
int
printf
(
CStringRef
format
,
ArgList
args
)
{
return
fprintf
(
stdout
,
format
,
args
);
}
/**
Fast integer formatter.
*/
Fast integer formatter.
*/
class
FormatInt
{
private
:
private
:
// Buffer should be large enough to hold all digits (digits10 + 1),
// a sign and a null character.
enum
{
BUFFER_SIZE
=
std
::
numeric_limits
<
ULongLong
>::
digits10
+
3
};
enum
{
BUFFER_SIZE
=
std
::
numeric_limits
<
ULongLong
>::
digits10
+
3
};
mutable
char
buffer_
[
BUFFER_SIZE
];
char
*
str_
;
...
...
@@ -2839,10 +3093,16 @@ class FormatInt {
*--
str_
=
'-'
;
}
public
:
explicit
FormatInt
(
int
value
)
{
FormatSigned
(
value
);
}
explicit
FormatInt
(
long
value
)
{
FormatSigned
(
value
);
}
explicit
FormatInt
(
LongLong
value
)
{
FormatSigned
(
value
);
}
public
:
explicit
FormatInt
(
int
value
)
{
FormatSigned
(
value
);
}
explicit
FormatInt
(
long
value
)
{
FormatSigned
(
value
);
}
explicit
FormatInt
(
LongLong
value
)
{
FormatSigned
(
value
);
}
explicit
FormatInt
(
unsigned
value
)
:
str_
(
format_decimal
(
value
))
{}
explicit
FormatInt
(
unsigned
long
value
)
:
str_
(
format_decimal
(
value
))
{}
explicit
FormatInt
(
ULongLong
value
)
:
str_
(
format_decimal
(
value
))
{}
...
...
@@ -2850,13 +3110,17 @@ class FormatInt {
/**
Returns the number of characters written to the output buffer.
*/
std
::
size_t
size
()
const
{
return
buffer_
-
str_
+
BUFFER_SIZE
-
1
;
}
std
::
size_t
size
()
const
{
return
buffer_
-
str_
+
BUFFER_SIZE
-
1
;
}
/**
Returns a pointer to the output buffer content. No terminating null
character is appended.
*/
const
char
*
data
()
const
{
return
str_
;
}
const
char
*
data
()
const
{
return
str_
;
}
/**
Returns a pointer to the output buffer content with terminating null
...
...
@@ -2872,7 +3136,9 @@ class FormatInt {
Returns the content of the output buffer as an ``std::string``.
\endrst
*/
std
::
string
str
()
const
{
return
std
::
string
(
str_
,
size
());
}
std
::
string
str
()
const
{
return
std
::
string
(
str_
,
size
());
}
};
// Formats a decimal integer value writing into buffer and returns
...
...
@@ -2901,15 +3167,15 @@ inline void format_decimal(char *&buffer, T value) {
}
/**
\rst
Returns a named argument for formatting functions.
\rst
Returns a named argument for formatting functions.
**Example**::
**Example**::
print("Elapsed time: {s:.2f} seconds", arg("s", 1.23));
print("Elapsed time: {s:.2f} seconds", arg("s", 1.23));
\endrst
*/
\endrst
*/
template
<
typename
T
>
inline
internal
::
NamedArg
<
char
>
arg
(
StringRef
name
,
const
T
&
arg
)
{
return
internal
::
NamedArg
<
char
>
(
name
,
arg
);
...
...
@@ -2971,7 +3237,8 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
FMT_GEN(n, FMT_MAKE_ARG)) { \
fmt::internal::ArgArray<n>::Type arr = {FMT_GEN(n, FMT_MAKE_REF_##Char)}; \
fmt::internal::ArgArray<n>::Type arr; \
FMT_GEN(n, FMT_ASSIGN_##Char); \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr)); \
}
...
...
@@ -2998,32 +3265,32 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
#endif // FMT_USE_VARIADIC_TEMPLATES
/**
\rst
Defines a variadic function with the specified return type, function name
and argument types passed as variable arguments to this macro.
\rst
Defines a variadic function with the specified return type, function name
and argument types passed as variable arguments to this macro.
**Example**::
**Example**::
void print_error(const char *file, int line, const char *format,
fmt::ArgList args) {
fmt::print("{}: {}: ", file, line);
fmt::print(format, args);
}
FMT_VARIADIC(void, print_error, const char *, int, const char *)
void print_error(const char *file, int line, const char *format,
fmt::ArgList args) {
fmt::print("{}: {}: ", file, line);
fmt::print(format, args);
}
FMT_VARIADIC(void, print_error, const char *, int, const char *)
``FMT_VARIADIC`` is used for compatibility with legacy C++ compilers that
don't implement variadic templates. You don't have to use this macro if
you don't need legacy compiler support and can use variadic templates
directly::
``FMT_VARIADIC`` is used for compatibility with legacy C++ compilers that
don't implement variadic templates. You don't have to use this macro if
you don't need legacy compiler support and can use variadic templates
directly::
template <typename... Args>
void print_error(const char *file, int line, const char *format,
const Args & ... args) {
fmt::print("{}: {}: ", file, line);
fmt::print(format, args...);
}
\endrst
*/
template <typename... Args>
void print_error(const char *file, int line, const char *format,
const Args & ... args) {
fmt::print("{}: {}: ", file, line);
fmt::print(format, args...);
}
\endrst
*/
#define FMT_VARIADIC(ReturnType, func, ...) \
FMT_VARIADIC_(char, ReturnType, func, return func, __VA_ARGS__)
...
...
@@ -3035,19 +3302,19 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
#define FMT_CAPTURE_ARG_W_(id, index) ::fmt::arg(L###id, id)
/**
\rst
Convenient macro to capture the arguments' names and values into several
``fmt::arg(name, value)``.
\rst
Convenient macro to capture the arguments' names and values into several
``fmt::arg(name, value)``.
**Example**::
**Example**::
int x = 1, y = 2;
print("point: ({x}, {y})", FMT_CAPTURE(x, y));
// same as:
// print("point: ({x}, {y})", arg("x", x), arg("y", y));
int x = 1, y = 2;
print("point: ({x}, {y})", FMT_CAPTURE(x, y));
// same as:
// print("point: ({x}, {y})", arg("x", x), arg("y", y));
\endrst
*/
\endrst
*/
#define FMT_CAPTURE(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_, __VA_ARGS__)
#define FMT_CAPTURE_W(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_W_, __VA_ARGS__)
...
...
@@ -3066,14 +3333,14 @@ FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
#if FMT_USE_IOSTREAMS
/**
\rst
Prints formatted data to the stream *os*.
\rst
Prints formatted data to the stream *os*.
**Example**::
**Example**::
print(cerr, "Don't {}!", "panic");
\endrst
*/
print(cerr, "Don't {}!", "panic");
\endrst
*/
void
print
(
std
::
ostream
&
os
,
CStringRef
format_str
,
ArgList
args
);
FMT_VARIADIC
(
void
,
print
,
std
::
ostream
&
,
CStringRef
)
#endif
...
...
@@ -3100,7 +3367,7 @@ struct UdlArg {
template
<
typename
T
>
NamedArg
<
Char
>
operator
=
(
T
&&
value
)
const
{
return
{
str
,
std
::
forward
<
T
>
(
value
)
};
return
{
str
,
std
::
forward
<
T
>
(
value
)
};
}
};
...
...
@@ -3109,34 +3376,42 @@ struct UdlArg {
inline
namespace
literals
{
/**
\rst
C++11 literal equivalent of :func:`fmt::format`.
\rst
C++11 literal equivalent of :func:`fmt::format`.
**Example**::
**Example**::
using namespace fmt::literals;
std::string message = "The answer is {}"_format(42);
\endrst
*/
using namespace fmt::literals;
std::string message = "The answer is {}"_format(42);
\endrst
*/
inline
internal
::
UdlFormat
<
char
>
operator
""
_format
(
const
char
*
s
,
std
::
size_t
)
{
return
{
s
};
}
operator
""
_format
(
const
char
*
s
,
std
::
size_t
)
{
return
{
s
};
}
inline
internal
::
UdlFormat
<
wchar_t
>
operator
""
_format
(
const
wchar_t
*
s
,
std
::
size_t
)
{
return
{
s
};
}
operator
""
_format
(
const
wchar_t
*
s
,
std
::
size_t
)
{
return
{
s
};
}
/**
\rst
C++11 literal equivalent of :func:`fmt::arg`.
\rst
C++11 literal equivalent of :func:`fmt::arg`.
**Example**::
**Example**::
using namespace fmt::literals;
print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
\endrst
*/
using namespace fmt::literals;
print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
\endrst
*/
inline
internal
::
UdlArg
<
char
>
operator
""
_a
(
const
char
*
s
,
std
::
size_t
)
{
return
{
s
};
}
operator
""
_a
(
const
char
*
s
,
std
::
size_t
)
{
return
{
s
};
}
inline
internal
::
UdlArg
<
wchar_t
>
operator
""
_a
(
const
wchar_t
*
s
,
std
::
size_t
)
{
return
{
s
};
}
operator
""
_a
(
const
wchar_t
*
s
,
std
::
size_t
)
{
return
{
s
};
}
}
// inline namespace literals
}
// namespace fmt
...
...
@@ -3147,7 +3422,7 @@ operator"" _a(const wchar_t *s, std::size_t) { return {s}; }
# pragma GCC diagnostic pop
#endif
#if
def __clang__
#if
defined(__clang__) && !defined(__INTEL_COMPILER)
# pragma clang diagnostic pop
#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