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