Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
spdlog
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
spdlog
Commits
ec4233f2
Commit
ec4233f2
authored
Aug 14, 2015
by
gabime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed warnings conversion 'size_t' to 'int' on windows issue #119
parent
77acf29c
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
2562 additions
and
2753 deletions
+2562
-2753
include/spdlog/details/format.cc
include/spdlog/details/format.cc
+866
-895
include/spdlog/details/format.h
include/spdlog/details/format.h
+1696
-1858
No files found.
include/spdlog/details/format.cc
View file @
ec4233f2
/*
Formatting library for C++
Copyright (c) 2012 - 2015, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
Formatting library for C++
Copyright (c) 2012 - 2015, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "format.h"
...
...
@@ -133,9 +133,7 @@ struct IntChecker {
unsigned
max
=
INT_MAX
;
return
value
<=
max
;
}
static
bool
fits_in_int
(
bool
)
{
return
true
;
}
static
bool
fits_in_int
(
bool
)
{
return
true
;
}
};
template
<
>
...
...
@@ -148,7 +146,7 @@ struct IntChecker<true> {
const
char
RESET_COLOR
[]
=
"
\x1b
[0m"
;
typedef
void
(
*
FormatFunc
)(
fmt
::
Writer
&
,
int
,
fmt
::
StringRef
);
typedef
void
(
*
FormatFunc
)(
fmt
::
Writer
&
,
int
,
fmt
::
StringRef
);
// Portable thread-safe version of strerror.
// Sets buffer to point to a string describing the error code.
...
...
@@ -160,7 +158,7 @@ typedef void(*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
// other - failure
// Buffer should be at least of size 1.
int
safe_strerror
(
int
error_code
,
char
*&
buffer
,
std
::
size_t
buffer_size
)
FMT_NOEXCEPT
{
int
error_code
,
char
*&
buffer
,
std
::
size_t
buffer_size
)
FMT_NOEXCEPT
{
FMT_ASSERT
(
buffer
!=
0
&&
buffer_size
!=
0
,
"invalid buffer"
);
class
StrError
{
...
...
@@ -219,7 +217,7 @@ int safe_strerror(
}
void
format_error_code
(
fmt
::
Writer
&
out
,
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
// Report error code making sure that the output fits into
// INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
// bad_alloc.
...
...
@@ -237,7 +235,7 @@ void format_error_code(fmt::Writer &out, int error_code,
}
void
report_error
(
FormatFunc
func
,
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
fmt
::
MemoryWriter
full_message
;
func
(
full_message
,
error_code
,
message
);
// Use Writer::data instead of Writer::c_str to avoid potential memory
...
...
@@ -248,11 +246,9 @@ void report_error(FormatFunc func,
// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
class
IsZeroInt
:
public
fmt
::
internal
::
ArgVisitor
<
IsZeroInt
,
bool
>
{
public:
public:
template
<
typename
T
>
bool
visit_any_int
(
T
value
)
{
return
value
==
0
;
}
bool
visit_any_int
(
T
value
)
{
return
value
==
0
;
}
};
// Parses an unsigned integer advancing s to the end of the parsed input.
...
...
@@ -302,12 +298,12 @@ void check_sign(const Char *&s, const Arg &arg) {
// Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative.
class
WidthHandler
:
public
fmt
::
internal
::
ArgVisitor
<
WidthHandler
,
unsigned
>
{
private:
private:
fmt
::
FormatSpec
&
spec_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
WidthHandler
);
public:
public:
explicit
WidthHandler
(
fmt
::
FormatSpec
&
spec
)
:
spec_
(
spec
)
{}
void
report_unhandled_arg
()
{
...
...
@@ -330,7 +326,7 @@ public:
class
PrecisionHandler
:
public
fmt
::
internal
::
ArgVisitor
<
PrecisionHandler
,
int
>
{
public:
public:
void
report_unhandled_arg
()
{
FMT_THROW
(
fmt
::
FormatError
(
"precision is not integer"
));
}
...
...
@@ -346,13 +342,13 @@ public:
// Converts an integer argument to an integral type T for printf.
template
<
typename
T
>
class
ArgConverter
:
public
fmt
::
internal
::
ArgVisitor
<
ArgConverter
<
T
>
,
void
>
{
private:
private:
fmt
::
internal
::
Arg
&
arg_
;
wchar_t
type_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
ArgConverter
);
public:
public:
ArgConverter
(
fmt
::
internal
::
Arg
&
arg
,
wchar_t
type
)
:
arg_
(
arg
),
type_
(
type
)
{}
...
...
@@ -365,20 +361,17 @@ public:
if
(
is_signed
)
{
arg_
.
type
=
Arg
::
INT
;
arg_
.
int_value
=
static_cast
<
int
>
(
static_cast
<
T
>
(
value
));
}
else
{
}
else
{
arg_
.
type
=
Arg
::
UINT
;
arg_
.
uint_value
=
static_cast
<
unsigned
>
(
static_cast
<
typename
fmt
::
internal
::
MakeUnsigned
<
T
>::
Type
>
(
value
));
}
}
else
{
}
else
{
if
(
is_signed
)
{
arg_
.
type
=
Arg
::
LONG_LONG
;
arg_
.
long_long_value
=
static_cast
<
typename
fmt
::
internal
::
MakeUnsigned
<
U
>::
Type
>
(
value
);
}
else
{
}
else
{
arg_
.
type
=
Arg
::
ULONG_LONG
;
arg_
.
ulong_long_value
=
static_cast
<
typename
fmt
::
internal
::
MakeUnsigned
<
U
>::
Type
>
(
value
);
...
...
@@ -389,12 +382,12 @@ public:
// Converts an integer argument to char for printf.
class
CharConverter
:
public
fmt
::
internal
::
ArgVisitor
<
CharConverter
,
void
>
{
private:
private:
fmt
::
internal
::
Arg
&
arg_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
CharConverter
);
public:
public:
explicit
CharConverter
(
fmt
::
internal
::
Arg
&
arg
)
:
arg_
(
arg
)
{}
template
<
typename
T
>
...
...
@@ -409,33 +402,25 @@ namespace internal {
template
<
typename
Impl
,
typename
Char
>
class
BasicArgFormatter
:
public
ArgVisitor
<
Impl
,
void
>
{
private:
private:
BasicWriter
<
Char
>
&
writer_
;
FormatSpec
&
spec_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
BasicArgFormatter
);
protected:
BasicWriter
<
Char
>
&
writer
()
{
return
writer_
;
}
const
FormatSpec
&
spec
()
const
{
return
spec_
;
}
protected:
BasicWriter
<
Char
>
&
writer
()
{
return
writer_
;
}
const
FormatSpec
&
spec
()
const
{
return
spec_
;
}
public:
public:
BasicArgFormatter
(
BasicWriter
<
Char
>
&
w
,
FormatSpec
&
s
)
:
writer_
(
w
),
spec_
(
s
)
{}
template
<
typename
T
>
void
visit_any_int
(
T
value
)
{
writer_
.
write_int
(
value
,
spec_
);
}
void
visit_any_int
(
T
value
)
{
writer_
.
write_int
(
value
,
spec_
);
}
template
<
typename
T
>
void
visit_any_double
(
T
value
)
{
writer_
.
write_double
(
value
,
spec_
);
}
void
visit_any_double
(
T
value
)
{
writer_
.
write_double
(
value
,
spec_
);
}
void
visit_bool
(
bool
value
)
{
if
(
spec_
.
type_
)
{
...
...
@@ -463,15 +448,12 @@ public:
if
(
spec_
.
align_
==
ALIGN_RIGHT
)
{
std
::
fill_n
(
out
,
spec_
.
width_
-
1
,
fill
);
out
+=
spec_
.
width_
-
1
;
}
else
if
(
spec_
.
align_
==
ALIGN_CENTER
)
{
}
else
if
(
spec_
.
align_
==
ALIGN_CENTER
)
{
out
=
writer_
.
fill_padding
(
out
,
spec_
.
width_
,
1
,
fill
);
}
else
{
}
else
{
std
::
fill_n
(
out
+
1
,
spec_
.
width_
-
1
,
fill
);
}
}
else
{
}
else
{
out
=
writer_
.
grow_buffer
(
1
);
}
*
out
=
internal
::
CharTraits
<
Char
>::
cast
(
value
);
...
...
@@ -499,11 +481,11 @@ public:
// An argument formatter.
template
<
typename
Char
>
class
ArgFormatter
:
public
BasicArgFormatter
<
ArgFormatter
<
Char
>
,
Char
>
{
private:
private:
BasicFormatter
<
Char
>
&
formatter_
;
const
Char
*
format_
;
public:
public:
ArgFormatter
(
BasicFormatter
<
Char
>
&
f
,
FormatSpec
&
s
,
const
Char
*
fmt
)
:
BasicArgFormatter
<
ArgFormatter
<
Char
>
,
Char
>
(
f
.
writer
(),
s
),
formatter_
(
f
),
format_
(
fmt
)
{}
...
...
@@ -516,7 +498,7 @@ public:
template
<
typename
Char
>
class
PrintfArgFormatter
:
public
BasicArgFormatter
<
PrintfArgFormatter
<
Char
>
,
Char
>
{
public:
public:
PrintfArgFormatter
(
BasicWriter
<
Char
>
&
w
,
FormatSpec
&
s
)
:
BasicArgFormatter
<
PrintfArgFormatter
<
Char
>
,
Char
>
(
w
,
s
)
{}
...
...
@@ -533,12 +515,10 @@ public:
if
(
fmt_spec
.
align_
!=
ALIGN_LEFT
)
{
std
::
fill_n
(
out
,
fmt_spec
.
width_
-
1
,
fill
);
out
+=
fmt_spec
.
width_
-
1
;
}
else
{
}
else
{
std
::
fill_n
(
out
+
1
,
fmt_spec
.
width_
-
1
,
fill
);
}
}
else
{
}
else
{
out
=
w
.
grow_buffer
(
1
);
}
*
out
=
static_cast
<
Char
>
(
value
);
...
...
@@ -632,14 +612,17 @@ FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
#if FMT_USE_WINDOWS_H
FMT_FUNC
fmt
::
internal
::
UTF8ToUTF16
::
UTF8ToUTF16
(
fmt
::
StringRef
s
)
{
int
length
=
MultiByteToWideChar
(
CP_UTF8
,
MB_ERR_INVALID_CHARS
,
s
.
data
(),
s
.
size
(),
0
,
0
);
static
const
char
ERROR_MSG
[]
=
"cannot convert string from UTF-8 to UTF-16"
;
if
(
s
.
size
()
>
INT_MAX
)
FMT_THROW
(
WindowsError
(
ERROR_INVALID_PARAMETER
,
ERROR_MSG
));
int
s_size
=
static_cast
<
int
>
(
s
.
size
());
int
length
=
MultiByteToWideChar
(
CP_UTF8
,
MB_ERR_INVALID_CHARS
,
s
.
data
(),
s_size
,
0
,
0
);
if
(
length
==
0
)
FMT_THROW
(
WindowsError
(
GetLastError
(),
ERROR_MSG
));
buffer_
.
resize
(
length
+
1
);
length
=
MultiByteToWideChar
(
CP_UTF8
,
MB_ERR_INVALID_CHARS
,
s
.
data
(),
s
.
size
()
,
&
buffer_
[
0
],
length
);
CP_UTF8
,
MB_ERR_INVALID_CHARS
,
s
.
data
(),
s_size
,
&
buffer_
[
0
],
length
);
if
(
length
==
0
)
FMT_THROW
(
WindowsError
(
GetLastError
(),
ERROR_MSG
));
buffer_
[
length
]
=
0
;
...
...
@@ -653,12 +636,15 @@ FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
}
FMT_FUNC
int
fmt
::
internal
::
UTF16ToUTF8
::
convert
(
fmt
::
WStringRef
s
)
{
int
length
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
s
.
data
(),
s
.
size
(),
0
,
0
,
0
,
0
);
if
(
s
.
size
()
>
INT_MAX
)
return
ERROR_INVALID_PARAMETER
;
int
s_size
=
static_cast
<
int
>
(
s
.
size
());
int
length
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
s
.
data
(),
s_size
,
0
,
0
,
0
,
0
);
if
(
length
==
0
)
return
GetLastError
();
buffer_
.
resize
(
length
+
1
);
length
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
s
.
data
(),
s
.
size
()
,
&
buffer_
[
0
],
length
,
0
,
0
);
CP_UTF8
,
0
,
s
.
data
(),
s_size
,
&
buffer_
[
0
],
length
,
0
,
0
);
if
(
length
==
0
)
return
GetLastError
();
buffer_
[
length
]
=
0
;
...
...
@@ -676,22 +662,18 @@ FMT_FUNC void fmt::WindowsError::init(
FMT_FUNC
void
fmt
::
internal
::
format_windows_error
(
fmt
::
Writer
&
out
,
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
class
String
{
private:
LPWSTR
str_
;
public:
String
()
:
str_
()
{}
~
String
()
{
LocalFree
(
str_
);
}
LPWSTR
*
ptr
()
{
return
&
str_
;
}
~
String
()
{
LocalFree
(
str_
);
}
LPWSTR
*
ptr
()
{
return
&
str_
;
}
LPCWSTR
c_str
()
const
{
return
str_
;
}
};
FMT_TRY
{
FMT_TRY
{
String
system_message
;
if
(
FormatMessageW
(
FORMAT_MESSAGE_ALLOCATE_BUFFER
|
FORMAT_MESSAGE_FROM_SYSTEM
|
FORMAT_MESSAGE_IGNORE_INSERTS
,
0
,
...
...
@@ -711,8 +693,8 @@ FMT_FUNC void fmt::internal::format_windows_error(
FMT_FUNC
void
fmt
::
internal
::
format_system_error
(
fmt
::
Writer
&
out
,
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
FMT_TRY
{
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
FMT_TRY
{
MemoryBuffer
<
char
,
INLINE_BUFFER_SIZE
>
buffer
;
buffer
.
resize
(
INLINE_BUFFER_SIZE
);
for
(;;)
{
...
...
@@ -749,8 +731,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
map_
.
insert
(
Pair
(
named_arg
->
name
,
*
named_arg
));
break
;
default:
/*nothing*/
;
/*nothing*/
;
}
}
return
;
...
...
@@ -771,8 +752,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
map_
.
insert
(
Pair
(
named_arg
->
name
,
*
named_arg
));
break
;
default:
/*nothing*/
;
/*nothing*/
;
}
}
}
...
...
@@ -854,8 +834,7 @@ FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
case
Arg
:
:
NAMED_ARG
:
arg
=
*
static_cast
<
const
internal
::
Arg
*>
(
arg
.
pointer
);
default:
/*nothing*/
;
/*nothing*/
;
}
return
arg
;
}
...
...
@@ -933,8 +912,7 @@ unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
if
(
*
s
==
'$'
)
{
// value is an argument index
++
s
;
arg_index
=
value
;
}
else
{
}
else
{
if
(
c
==
'0'
)
spec
.
fill_
=
'0'
;
if
(
value
!=
0
)
{
...
...
@@ -949,8 +927,7 @@ unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
// Parse width.
if
(
*
s
>=
'0'
&&
*
s
<=
'9'
)
{
spec
.
width_
=
parse_nonnegative_int
(
s
);
}
else
if
(
*
s
==
'*'
)
{
}
else
if
(
*
s
==
'*'
)
{
++
s
;
spec
.
width_
=
WidthHandler
(
spec
).
visit
(
get_arg
(
s
));
}
...
...
@@ -983,8 +960,7 @@ void fmt::internal::PrintfFormatter<Char>::format(
++
s
;
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
{
spec
.
precision_
=
parse_nonnegative_int
(
s
);
}
else
if
(
*
s
==
'*'
)
{
}
else
if
(
*
s
==
'*'
)
{
++
s
;
spec
.
precision_
=
PrecisionHandler
().
visit
(
get_arg
(
s
));
}
...
...
@@ -1039,8 +1015,7 @@ void fmt::internal::PrintfFormatter<Char>::format(
if
(
arg
.
type
<=
Arg
::
LAST_INTEGER_TYPE
)
{
// Normalize type.
switch
(
spec
.
type_
)
{
case
'i'
:
case
'u'
:
case
'i'
:
case
'u'
:
spec
.
type_
=
'd'
;
break
;
case
'c'
:
...
...
@@ -1095,8 +1070,7 @@ const Char *fmt::BasicFormatter<Char>::format(
FMT_THROW
(
FormatError
(
"invalid fill character '{'"
));
s
+=
2
;
spec
.
fill_
=
c
;
}
else
++
s
;
}
else
++
s
;
if
(
spec
.
align_
==
ALIGN_NUMERIC
)
require_numeric_argument
(
arg
,
'='
);
break
;
...
...
@@ -1137,8 +1111,7 @@ const Char *fmt::BasicFormatter<Char>::format(
// Parse width.
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
{
spec
.
width_
=
parse_nonnegative_int
(
s
);
}
else
if
(
*
s
==
'{'
)
{
}
else
if
(
*
s
==
'{'
)
{
++
s
;
Arg
width_arg
=
is_name_start
(
*
s
)
?
parse_arg_name
(
s
)
:
parse_arg_index
(
s
);
...
...
@@ -1176,8 +1149,7 @@ const Char *fmt::BasicFormatter<Char>::format(
spec
.
precision_
=
0
;
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
{
spec
.
precision_
=
parse_nonnegative_int
(
s
);
}
else
if
(
*
s
==
'{'
)
{
}
else
if
(
*
s
==
'{'
)
{
++
s
;
Arg
precision_arg
=
is_name_start
(
*
s
)
?
parse_arg_name
(
s
)
:
parse_arg_index
(
s
);
...
...
@@ -1207,8 +1179,7 @@ const Char *fmt::BasicFormatter<Char>::format(
if
(
value
>
INT_MAX
)
FMT_THROW
(
FormatError
(
"number is too big"
));
spec
.
precision_
=
static_cast
<
int
>
(
value
);
}
else
{
}
else
{
FMT_THROW
(
FormatError
(
"missing precision specifier"
));
}
if
(
arg
.
type
<=
Arg
::
LAST_INTEGER_TYPE
||
arg
.
type
==
Arg
::
POINTER
)
{
...
...
@@ -1253,13 +1224,13 @@ void fmt::BasicFormatter<Char>::format(BasicCStringRef<Char> format_str) {
}
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
);
}
#if FMT_USE_WINDOWS_H
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
);
}
#endif
...
...
include/spdlog/details/format.h
View file @
ec4233f2
/*
Formatting library for C++
Copyright (c) 2012 - 2015, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
Formatting library for C++
Copyright (c) 2012 - 2015, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FMT_FORMAT_H_
#define FMT_FORMAT_H_
...
...
@@ -206,36 +206,36 @@ template <typename Char, typename T>
void
format
(
BasicFormatter
<
Char
>
&
f
,
const
Char
*&
format_str
,
const
T
&
value
);
/**
\rst
A string reference. It can be constructed from a C string or ``std::string``.
\rst
A string reference. It can be constructed from a C string or ``std::string``.
You can use one of the following typedefs for common character types:
You can use one of the following typedefs for common character types:
+------------+-------------------------+
| Type | Definition |
+============+=========================+
| StringRef | BasicStringRef<char> |
+------------+-------------------------+
| WStringRef | BasicStringRef<wchar_t> |
+------------+-------------------------+
+------------+-------------------------+
| Type | Definition |
+============+=========================+
| StringRef | BasicStringRef<char> |
+------------+-------------------------+
| WStringRef | BasicStringRef<wchar_t> |
+------------+-------------------------+
This class is most useful as a parameter type to allow passing
different types of strings to a function, for example::
This class is most useful as a parameter type to allow passing
different types of strings to a function, for example::
template <typename... Args>
std::string format(StringRef format_str, const Args & ... args);
template <typename... Args>
std::string format(StringRef format_str, const Args & ... args);
format("{}", 42);
format(std::string("{}"), 42);
\endrst
*/
format("{}", 42);
format(std::string("{}"), 42);
\endrst
*/
template
<
typename
Char
>
class
BasicStringRef
{
private:
private:
const
Char
*
data_
;
std
::
size_t
size_
;
public:
public:
/** Constructs a string reference object from a C string and a size. */
BasicStringRef
(
const
Char
*
s
,
std
::
size_t
size
)
:
data_
(
s
),
size_
(
size
)
{}
...
...
@@ -266,14 +266,10 @@ public:
}
/** Returns the pointer to a C string. */
const
Char
*
data
()
const
{
return
data_
;
}
const
Char
*
data
()
const
{
return
data_
;
}
/** Returns the string size. */
std
::
size_t
size
()
const
{
return
size_
;
}
std
::
size_t
size
()
const
{
return
size_
;
}
friend
bool
operator
==
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
return
lhs
.
data_
==
rhs
.
data_
;
...
...
@@ -292,36 +288,36 @@ typedef BasicStringRef<wchar_t> WStringRef;
/**
\rst
A reference to a null terminated string. It can be constructed from a C
string or ``std::string``.
\rst
A reference to a null terminated string. It can be constructed from a C
string or ``std::string``.
You can use one of the following typedefs for common character types:
You can use one of the following typedefs for common character types:
+-------------+--------------------------+
| Type | Definition |
+=============+==========================+
| CStringRef | BasicCStringRef<char> |
+-------------+--------------------------+
| WCStringRef | BasicCStringRef<wchar_t> |
+-------------+--------------------------+
+-------------+--------------------------+
| Type | Definition |
+=============+==========================+
| CStringRef | BasicCStringRef<char> |
+-------------+--------------------------+
| WCStringRef | BasicCStringRef<wchar_t> |
+-------------+--------------------------+
This class is most useful as a parameter type to allow passing
different types of strings to a function, for example::
This class is most useful as a parameter type to allow passing
different types of strings to a function, for example::
template <typename... Args>
std::string format(CStringRef format_str, const Args & ... args);
template <typename... Args>
std::string format(CStringRef format_str, const Args & ... args);
format("{}", 42);
format(std::string("{}"), 42);
\endrst
*/
format("{}", 42);
format(std::string("{}"), 42);
\endrst
*/
template
<
typename
Char
>
class
BasicCStringRef
{
private:
private:
const
Char
*
data_
;
public:
public:
/** Constructs a string reference object from a C string. */
BasicCStringRef
(
const
Char
*
s
)
:
data_
(
s
)
{}
...
...
@@ -333,19 +329,17 @@ public:
BasicCStringRef
(
const
std
::
basic_string
<
Char
>
&
s
)
:
data_
(
s
.
c_str
())
{}
/** Returns the pointer to a C string. */
const
Char
*
c_str
()
const
{
return
data_
;
}
const
Char
*
c_str
()
const
{
return
data_
;
}
};
typedef
BasicCStringRef
<
char
>
CStringRef
;
typedef
BasicCStringRef
<
wchar_t
>
WCStringRef
;
/**
A formatting error such as invalid format string.
A formatting error such as invalid format string.
*/
class
FormatError
:
public
std
::
runtime_error
{
public:
public:
explicit
FormatError
(
CStringRef
message
)
:
std
::
runtime_error
(
message
.
c_str
())
{}
};
...
...
@@ -363,23 +357,21 @@ inline stdext::checked_array_iterator<T*> make_ptr(T *ptr, std::size_t size) {
}
#else
template
<
typename
T
>
inline
T
*
make_ptr
(
T
*
ptr
,
std
::
size_t
)
{
return
ptr
;
}
inline
T
*
make_ptr
(
T
*
ptr
,
std
::
size_t
)
{
return
ptr
;
}
#endif
}
// namespace internal
/**
\rst
A buffer supporting a subset of ``std::vector``'s operations.
\endrst
*/
\rst
A buffer supporting a subset of ``std::vector``'s operations.
\endrst
*/
template
<
typename
T
>
class
Buffer
{
private:
private:
FMT_DISALLOW_COPY_AND_ASSIGN
(
Buffer
);
protected:
protected:
T
*
ptr_
;
std
::
size_t
size_
;
std
::
size_t
capacity_
;
...
...
@@ -395,18 +387,14 @@ protected:
*/
virtual
void
grow
(
std
::
size_t
size
)
=
0
;
public:
public:
virtual
~
Buffer
()
{}
/** Returns the size of this buffer. */
std
::
size_t
size
()
const
{
return
size_
;
}
std
::
size_t
size
()
const
{
return
size_
;
}
/** Returns the capacity of this buffer. */
std
::
size_t
capacity
()
const
{
return
capacity_
;
}
std
::
size_t
capacity
()
const
{
return
capacity_
;
}
/**
Resizes the buffer. If T is a POD type new elements may not be initialized.
...
...
@@ -427,7 +415,7 @@ public:
grow
(
capacity
);
}
void
clear
()
FMT_NOEXCEPT
{
size_
=
0
;
}
void
clear
()
FMT_NOEXCEPT
{
size_
=
0
;
}
void
push_back
(
const
T
&
value
)
{
if
(
size_
==
capacity_
)
...
...
@@ -439,12 +427,8 @@ public:
template
<
typename
U
>
void
append
(
const
U
*
begin
,
const
U
*
end
);
T
&
operator
[](
std
::
size_t
index
)
{
return
ptr_
[
index
];
}
const
T
&
operator
[](
std
::
size_t
index
)
const
{
return
ptr_
[
index
];
}
T
&
operator
[](
std
::
size_t
index
)
{
return
ptr_
[
index
];
}
const
T
&
operator
[](
std
::
size_t
index
)
const
{
return
ptr_
[
index
];
}
};
template
<
typename
T
>
...
...
@@ -463,7 +447,7 @@ namespace internal {
// the object itself.
template
<
typename
T
,
std
::
size_t
SIZE
,
typename
Allocator
=
std
::
allocator
<
T
>
>
class
MemoryBuffer
:
private
Allocator
,
public
Buffer
<
T
>
{
private:
private:
T
data_
[
SIZE
];
// Free memory allocated by the buffer.
...
...
@@ -471,18 +455,16 @@ private:
if
(
this
->
ptr_
!=
data_
)
this
->
deallocate
(
this
->
ptr_
,
this
->
capacity_
);
}
protected:
protected:
void
grow
(
std
::
size_t
size
);
public:
public:
explicit
MemoryBuffer
(
const
Allocator
&
alloc
=
Allocator
())
:
Allocator
(
alloc
),
Buffer
<
T
>
(
data_
,
SIZE
)
{}
~
MemoryBuffer
()
{
free
();
}
~
MemoryBuffer
()
{
free
();
}
#if FMT_USE_RVALUE_REFERENCES
private:
private:
// Move data from other to this buffer.
void
move
(
MemoryBuffer
&
other
)
{
Allocator
&
this_alloc
=
*
this
,
&
other_alloc
=
other
;
...
...
@@ -493,8 +475,7 @@ private:
this
->
ptr_
=
data_
;
std
::
copy
(
other
.
data_
,
other
.
data_
+
this
->
size_
,
make_ptr
(
data_
,
this
->
capacity_
));
}
else
{
}
else
{
this
->
ptr_
=
other
.
ptr_
;
// Set pointer to the inline array so that delete is not called
// when freeing.
...
...
@@ -502,7 +483,7 @@ private:
}
}
public:
public:
MemoryBuffer
(
MemoryBuffer
&&
other
)
{
move
(
other
);
}
...
...
@@ -516,9 +497,7 @@ public:
#endif
// Returns a copy of the allocator associated with this buffer.
Allocator
get_allocator
()
const
{
return
*
this
;
}
Allocator
get_allocator
()
const
{
return
*
this
;
}
};
template
<
typename
T
,
std
::
size_t
SIZE
,
typename
Allocator
>
...
...
@@ -543,10 +522,10 @@ void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size) {
// A fixed-size buffer.
template
<
typename
Char
>
class
FixedBuffer
:
public
fmt
::
Buffer
<
Char
>
{
public:
public:
FixedBuffer
(
Char
*
array
,
std
::
size_t
size
)
:
fmt
::
Buffer
<
Char
>
(
array
,
size
)
{}
protected:
protected:
void
grow
(
std
::
size_t
size
);
};
...
...
@@ -564,19 +543,11 @@ inline int getsign(double x) {
// Portable version of isinf.
# ifdef isinf
inline
int
isinfinity
(
double
x
)
{
return
isinf
(
x
);
}
inline
int
isinfinity
(
long
double
x
)
{
return
isinf
(
x
);
}
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
);
}
inline
int
isinfinity
(
double
x
)
{
return
std
::
isinf
(
x
);
}
inline
int
isinfinity
(
long
double
x
)
{
return
std
::
isinf
(
x
);
}
# endif
#else
inline
int
getsign
(
double
value
)
{
...
...
@@ -587,9 +558,7 @@ inline int getsign(double value) {
_ecvt_s
(
buffer
,
sizeof
(
buffer
),
value
,
0
,
&
dec
,
&
sign
);
return
sign
;
}
inline
int
isinfinity
(
double
x
)
{
return
!
_finite
(
x
);
}
inline
int
isinfinity
(
double
x
)
{
return
!
_finite
(
x
);
}
inline
int
isinfinity
(
long
double
x
)
{
return
!
_finite
(
static_cast
<
double
>
(
x
));
}
...
...
@@ -597,15 +566,13 @@ inline int isinfinity(long double x) {
template
<
typename
Char
>
class
BasicCharTraits
{
public:
public:
#if _SECURE_SCL
typedef
stdext
::
checked_array_iterator
<
Char
*>
CharPtr
;
#else
typedef
Char
*
CharPtr
;
#endif
static
Char
cast
(
wchar_t
value
)
{
return
static_cast
<
Char
>
(
value
);
}
static
Char
cast
(
wchar_t
value
)
{
return
static_cast
<
Char
>
(
value
);
}
};
template
<
typename
Char
>
...
...
@@ -613,14 +580,12 @@ class CharTraits;
template
<
>
class
CharTraits
<
char
>
:
public
BasicCharTraits
<
char
>
{
private:
private:
// Conversion from wchar_t to char is not allowed.
static
char
convert
(
wchar_t
);
public:
static
char
convert
(
char
value
)
{
return
value
;
}
public:
static
char
convert
(
char
value
)
{
return
value
;
}
// Formats a floating-point number.
template
<
typename
T
>
...
...
@@ -630,13 +595,9 @@ public:
template
<
>
class
CharTraits
<
wchar_t
>
:
public
BasicCharTraits
<
wchar_t
>
{
public:
static
wchar_t
convert
(
char
value
)
{
return
value
;
}
static
wchar_t
convert
(
wchar_t
value
)
{
return
value
;
}
public:
static
wchar_t
convert
(
char
value
)
{
return
value
;
}
static
wchar_t
convert
(
wchar_t
value
)
{
return
value
;
}
template
<
typename
T
>
static
int
format_float
(
wchar_t
*
buffer
,
std
::
size_t
size
,
...
...
@@ -647,17 +608,13 @@ public:
template
<
bool
IsSigned
>
struct
SignChecker
{
template
<
typename
T
>
static
bool
is_negative
(
T
value
)
{
return
value
<
0
;
}
static
bool
is_negative
(
T
value
)
{
return
value
<
0
;
}
};
template
<
>
struct
SignChecker
<
false
>
{
template
<
typename
T
>
static
bool
is_negative
(
T
)
{
return
false
;
}
static
bool
is_negative
(
T
)
{
return
false
;
}
};
// Returns true if value is negative, false otherwise.
...
...
@@ -669,14 +626,10 @@ inline bool is_negative(T value) {
// Selects uint32_t if FitsIn32Bits is true, uint64_t otherwise.
template
<
bool
FitsIn32Bits
>
struct
TypeSelector
{
typedef
uint32_t
Type
;
};
struct
TypeSelector
{
typedef
uint32_t
Type
;
};
template
<
>
struct
TypeSelector
<
false
>
{
typedef
uint64_t
Type
;
};
struct
TypeSelector
<
false
>
{
typedef
uint64_t
Type
;
};
template
<
typename
T
>
struct
IntTraits
{
...
...
@@ -688,9 +641,7 @@ struct IntTraits {
// MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T.
template
<
typename
T
>
struct
MakeUnsigned
{
typedef
T
Type
;
};
struct
MakeUnsigned
{
typedef
T
Type
;
};
#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \
template <> \
...
...
@@ -793,46 +744,30 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
// A converter from UTF-8 to UTF-16.
// It is only provided for Windows since other systems support UTF-8 natively.
class
UTF8ToUTF16
{
private:
private:
MemoryBuffer
<
wchar_t
,
INLINE_BUFFER_SIZE
>
buffer_
;
public:
public:
explicit
UTF8ToUTF16
(
StringRef
s
);
operator
WStringRef
()
const
{
return
WStringRef
(
&
buffer_
[
0
],
size
());
}
size_t
size
()
const
{
return
buffer_
.
size
()
-
1
;
}
const
wchar_t
*
c_str
()
const
{
return
&
buffer_
[
0
];
}
std
::
wstring
str
()
const
{
return
std
::
wstring
(
&
buffer_
[
0
],
size
());
}
operator
WStringRef
()
const
{
return
WStringRef
(
&
buffer_
[
0
],
size
());
}
size_t
size
()
const
{
return
buffer_
.
size
()
-
1
;
}
const
wchar_t
*
c_str
()
const
{
return
&
buffer_
[
0
];
}
std
::
wstring
str
()
const
{
return
std
::
wstring
(
&
buffer_
[
0
],
size
());
}
};
// A converter from UTF-16 to UTF-8.
// It is only provided for Windows since other systems support UTF-8 natively.
class
UTF16ToUTF8
{
private:
private:
MemoryBuffer
<
char
,
INLINE_BUFFER_SIZE
>
buffer_
;
public:
public:
UTF16ToUTF8
()
{}
explicit
UTF16ToUTF8
(
WStringRef
s
);
operator
StringRef
()
const
{
return
StringRef
(
&
buffer_
[
0
],
size
());
}
size_t
size
()
const
{
return
buffer_
.
size
()
-
1
;
}
const
char
*
c_str
()
const
{
return
&
buffer_
[
0
];
}
std
::
string
str
()
const
{
return
std
::
string
(
&
buffer_
[
0
],
size
());
}
operator
StringRef
()
const
{
return
StringRef
(
&
buffer_
[
0
],
size
());
}
size_t
size
()
const
{
return
buffer_
.
size
()
-
1
;
}
const
char
*
c_str
()
const
{
return
&
buffer_
[
0
];
}
std
::
string
str
()
const
{
return
std
::
string
(
&
buffer_
[
0
],
size
());
}
// Performs conversion returning a system error code instead of
// throwing exception on conversion error. This method may still throw
...
...
@@ -855,7 +790,7 @@ struct Value {
std
::
size_t
size
;
};
typedef
void
(
*
FormatFunc
)(
typedef
void
(
*
FormatFunc
)(
void
*
formatter
,
const
void
*
arg
,
void
*
format_str_ptr
);
struct
CustomValue
{
...
...
@@ -916,7 +851,7 @@ struct WCharHelper<T, wchar_t> {
template
<
typename
T
>
class
IsConvertibleToInt
{
private:
private:
typedef
char
yes
[
1
];
typedef
char
no
[
2
];
...
...
@@ -925,7 +860,7 @@ private:
static
yes
&
convert
(
fmt
::
ULongLong
);
static
no
&
convert
(...);
public:
public:
enum
{
value
=
(
sizeof
(
convert
(
get
()))
==
sizeof
(
yes
))
};
};
...
...
@@ -945,30 +880,22 @@ template<bool B, class T = void>
struct
EnableIf
{};
template
<
class
T
>
struct
EnableIf
<
true
,
T
>
{
typedef
T
type
;
};
struct
EnableIf
<
true
,
T
>
{
typedef
T
type
;
};
template
<
bool
B
,
class
T
,
class
F
>
struct
Conditional
{
typedef
T
type
;
};
struct
Conditional
{
typedef
T
type
;
};
template
<
class
T
,
class
F
>
struct
Conditional
<
false
,
T
,
F
>
{
typedef
F
type
;
};
struct
Conditional
<
false
,
T
,
F
>
{
typedef
F
type
;
};
// A helper function to suppress bogus "conditional expression is constant"
// warnings.
inline
bool
check
(
bool
value
)
{
return
value
;
}
inline
bool
check
(
bool
value
)
{
return
value
;
}
// Makes an Arg object from any type.
template
<
typename
Char
>
class
MakeValue
:
public
Arg
{
private:
private:
// The following two methods are private to disallow formatting of
// arbitrary pointers. If you want to output a pointer cast it to
// "void *" or "const void *". In particular, this forbids formatting
...
...
@@ -1008,7 +935,7 @@ private:
*
static_cast
<
const
T
*>
(
arg
));
}
public:
public:
MakeValue
()
{}
#define FMT_MAKE_VALUE_(Type, field, TYPE, rhs) \
...
...
@@ -1059,9 +986,7 @@ public:
MakeValue
(
typename
WCharHelper
<
wchar_t
,
Char
>::
Supported
value
)
{
int_value
=
value
;
}
static
uint64_t
type
(
wchar_t
)
{
return
Arg
::
CHAR
;
}
static
uint64_t
type
(
wchar_t
)
{
return
Arg
::
CHAR
;
}
#define FMT_MAKE_STR_VALUE(Type, TYPE) \
MakeValue(Type value) { set_string(value); } \
...
...
@@ -1110,14 +1035,10 @@ public:
// Additional template param `Char_` is needed here because make_type always
// uses MakeValue<char>.
template
<
typename
Char_
>
MakeValue
(
const
NamedArg
<
Char_
>
&
value
)
{
pointer
=
&
value
;
}
MakeValue
(
const
NamedArg
<
Char_
>
&
value
)
{
pointer
=
&
value
;
}
template
<
typename
Char_
>
static
uint64_t
type
(
const
NamedArg
<
Char_
>
&
)
{
return
Arg
::
NAMED_ARG
;
}
static
uint64_t
type
(
const
NamedArg
<
Char_
>
&
)
{
return
Arg
::
NAMED_ARG
;
}
};
template
<
typename
Char
>
...
...
@@ -1155,7 +1076,7 @@ struct NamedArg : Arg {
// http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
template
<
typename
Impl
,
typename
Result
>
class
ArgVisitor
{
public:
public:
void
report_unhandled_arg
()
{}
Result
visit_unhandled_arg
()
{
...
...
@@ -1249,7 +1170,7 @@ public:
};
class
RuntimeError
:
public
std
::
runtime_error
{
protected:
protected:
RuntimeError
()
:
std
::
runtime_error
(
""
)
{}
};
...
...
@@ -1265,7 +1186,7 @@ class ArgMap;
/** An argument list. */
class
ArgList
{
private:
private:
// To reduce compiled code size per formatting function call, types of first
// MAX_PACKED_ARGS arguments are passed in the types_ field.
uint64_t
types_
;
...
...
@@ -1289,7 +1210,7 @@ private:
template
<
typename
Char
>
friend
class
internal
::
ArgMap
;
public:
public:
// Maximum number of arguments with packed types.
enum
{
MAX_PACKED_ARGS
=
16
};
...
...
@@ -1333,13 +1254,13 @@ namespace internal {
template
<
typename
Char
>
class
ArgMap
{
private:
private:
typedef
std
::
map
<
fmt
::
BasicStringRef
<
Char
>
,
internal
::
Arg
>
MapType
;
typedef
typename
MapType
::
value_type
Pair
;
MapType
map_
;
public:
public:
void
init
(
const
ArgList
&
args
);
const
internal
::
Arg
*
find
(
const
fmt
::
BasicStringRef
<
Char
>
&
name
)
const
{
...
...
@@ -1349,17 +1270,15 @@ public:
};
class
FormatterBase
{
private:
private:
ArgList
args_
;
int
next_arg_index_
;
// Returns the argument with specified index.
Arg
do_get_arg
(
unsigned
arg_index
,
const
char
*&
error
);
protected:
const
ArgList
&
args
()
const
{
return
args_
;
}
protected:
const
ArgList
&
args
()
const
{
return
args_
;
}
explicit
FormatterBase
(
const
ArgList
&
args
)
{
args_
=
args
;
...
...
@@ -1385,7 +1304,7 @@ protected:
// A printf formatter.
template
<
typename
Char
>
class
PrintfFormatter
:
private
FormatterBase
{
private:
private:
void
parse_flags
(
FormatSpec
&
spec
,
const
Char
*&
s
);
// Returns the argument with specified index or, if arg_index is equal
...
...
@@ -1396,7 +1315,7 @@ private:
// Parses argument index, flags and width and returns the argument index.
unsigned
parse_header
(
const
Char
*&
s
,
FormatSpec
&
spec
);
public:
public:
explicit
PrintfFormatter
(
const
ArgList
&
args
)
:
FormatterBase
(
args
)
{}
void
format
(
BasicWriter
<
Char
>
&
writer
,
BasicCStringRef
<
Char
>
format_str
);
};
...
...
@@ -1405,7 +1324,7 @@ public:
// A formatter.
template
<
typename
Char
>
class
BasicFormatter
:
private
internal
::
FormatterBase
{
private:
private:
BasicWriter
<
Char
>
&
writer_
;
internal
::
ArgMap
<
Char
>
map_
;
...
...
@@ -1423,13 +1342,11 @@ private:
// Parses argument name and returns corresponding argument.
internal
::
Arg
parse_arg_name
(
const
Char
*&
s
);
public:
public:
BasicFormatter
(
const
ArgList
&
args
,
BasicWriter
<
Char
>
&
w
)
:
FormatterBase
(
args
),
writer_
(
w
)
{}
BasicWriter
<
Char
>
&
writer
()
{
return
writer_
;
}
BasicWriter
<
Char
>
&
writer
()
{
return
writer_
;
}
void
format
(
BasicCStringRef
<
Char
>
format_str
);
...
...
@@ -1452,24 +1369,12 @@ struct EmptySpec {};
// A type specifier.
template
<
char
TYPE
>
struct
TypeSpec
:
EmptySpec
{
Alignment
align
()
const
{
return
ALIGN_DEFAULT
;
}
unsigned
width
()
const
{
return
0
;
}
int
precision
()
const
{
return
-
1
;
}
bool
flag
(
unsigned
)
const
{
return
false
;
}
char
type
()
const
{
return
TYPE
;
}
char
fill
()
const
{
return
' '
;
}
Alignment
align
()
const
{
return
ALIGN_DEFAULT
;
}
unsigned
width
()
const
{
return
0
;
}
int
precision
()
const
{
return
-
1
;
}
bool
flag
(
unsigned
)
const
{
return
false
;
}
char
type
()
const
{
return
TYPE
;
}
char
fill
()
const
{
return
' '
;
}
};
// A width specifier.
...
...
@@ -1481,12 +1386,8 @@ struct WidthSpec {
WidthSpec
(
unsigned
width
,
wchar_t
fill
)
:
width_
(
width
),
fill_
(
fill
)
{}
unsigned
width
()
const
{
return
width_
;
}
wchar_t
fill
()
const
{
return
fill_
;
}
unsigned
width
()
const
{
return
width_
;
}
wchar_t
fill
()
const
{
return
fill_
;
}
};
// An alignment specifier.
...
...
@@ -1496,13 +1397,9 @@ struct AlignSpec : WidthSpec {
AlignSpec
(
unsigned
width
,
wchar_t
fill
,
Alignment
align
=
ALIGN_DEFAULT
)
:
WidthSpec
(
width
,
fill
),
align_
(
align
)
{}
Alignment
align
()
const
{
return
align_
;
}
Alignment
align
()
const
{
return
align_
;
}
int
precision
()
const
{
return
-
1
;
}
int
precision
()
const
{
return
-
1
;
}
};
// An alignment and type specifier.
...
...
@@ -1510,12 +1407,8 @@ template <char TYPE>
struct
AlignTypeSpec
:
AlignSpec
{
AlignTypeSpec
(
unsigned
width
,
wchar_t
fill
)
:
AlignSpec
(
width
,
fill
)
{}
bool
flag
(
unsigned
)
const
{
return
false
;
}
char
type
()
const
{
return
TYPE
;
}
bool
flag
(
unsigned
)
const
{
return
false
;
}
char
type
()
const
{
return
TYPE
;
}
};
// A full format specifier.
...
...
@@ -1528,86 +1421,76 @@ struct FormatSpec : AlignSpec {
unsigned
width
=
0
,
char
type
=
0
,
wchar_t
fill
=
' '
)
:
AlignSpec
(
width
,
fill
),
flags_
(
0
),
precision_
(
-
1
),
type_
(
type
)
{}
bool
flag
(
unsigned
f
)
const
{
return
(
flags_
&
f
)
!=
0
;
}
int
precision
()
const
{
return
precision_
;
}
char
type
()
const
{
return
type_
;
}
bool
flag
(
unsigned
f
)
const
{
return
(
flags_
&
f
)
!=
0
;
}
int
precision
()
const
{
return
precision_
;
}
char
type
()
const
{
return
type_
;
}
};
// An integer format specifier.
template
<
typename
T
,
typename
SpecT
=
TypeSpec
<
0
>,
typename
Char
=
char
>
class
IntFormatSpec
:
public
SpecT
{
private:
private:
T
value_
;
public:
public:
IntFormatSpec
(
T
val
,
const
SpecT
&
spec
=
SpecT
())
:
SpecT
(
spec
),
value_
(
val
)
{}
T
value
()
const
{
return
value_
;
}
T
value
()
const
{
return
value_
;
}
};
// A string format specifier.
template
<
typename
Char
>
class
StrFormatSpec
:
public
AlignSpec
{
private:
private:
const
Char
*
str_
;
public:
public:
template
<
typename
FillChar
>
StrFormatSpec
(
const
Char
*
str
,
unsigned
width
,
FillChar
fill
)
:
AlignSpec
(
width
,
fill
),
str_
(
str
)
{
internal
::
CharTraits
<
Char
>::
convert
(
FillChar
());
}
const
Char
*
str
()
const
{
return
str_
;
}
const
Char
*
str
()
const
{
return
str_
;
}
};
/**
Returns an integer format specifier to format the value in base 2.
*/
Returns an integer format specifier to format the value in base 2.
*/
IntFormatSpec
<
int
,
TypeSpec
<
'b'
>
>
bin
(
int
value
);
/**
Returns an integer format specifier to format the value in base 8.
*/
Returns an integer format specifier to format the value in base 8.
*/
IntFormatSpec
<
int
,
TypeSpec
<
'o'
>
>
oct
(
int
value
);
/**
Returns an integer format specifier to format the value in base 16 using
lower-case letters for the digits above 9.
*/
Returns an integer format specifier to format the value in base 16 using
lower-case letters for the digits above 9.
*/
IntFormatSpec
<
int
,
TypeSpec
<
'x'
>
>
hex
(
int
value
);
/**
Returns an integer formatter format specifier to format in base 16 using
upper-case letters for the digits above 9.
*/
Returns an integer formatter format specifier to format in base 16 using
upper-case letters for the digits above 9.
*/
IntFormatSpec
<
int
,
TypeSpec
<
'X'
>
>
hexu
(
int
value
);
/**
\rst
Returns an integer format specifier to pad the formatted argument with the
fill character to the specified width using the default (right) numeric
alignment.
\rst
Returns an integer format specifier to pad the formatted argument with the
fill character to the specified width using the default (right) numeric
alignment.
**Example**::
**Example**::
MemoryWriter out;
out << pad(hex(0xcafe), 8, '0');
// out.str() == "0000cafe"
MemoryWriter out;
out << pad(hex(0xcafe), 8, '0');
// out.str() == "0000cafe"
\endrst
*/
\endrst
*/
template
<
char
TYPE_CODE
,
typename
Char
>
IntFormatSpec
<
int
,
AlignTypeSpec
<
TYPE_CODE
>
,
Char
>
pad
(
int
value
,
unsigned
width
,
Char
fill
=
' '
);
...
...
@@ -1615,26 +1498,26 @@ IntFormatSpec<int, AlignTypeSpec<TYPE_CODE>, Char> pad(
#define FMT_DEFINE_INT_FORMATTERS(TYPE) \
inline IntFormatSpec<TYPE, TypeSpec<'b'> > bin(TYPE value) { \
return IntFormatSpec<TYPE, TypeSpec<'b'> >(value, TypeSpec<'b'>()); \
} \
} \
\
inline IntFormatSpec<TYPE, TypeSpec<'o'> > oct(TYPE value) { \
return IntFormatSpec<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \
} \
} \
\
inline IntFormatSpec<TYPE, TypeSpec<'x'> > hex(TYPE value) { \
return IntFormatSpec<TYPE, TypeSpec<'x'> >(value, TypeSpec<'x'>()); \
} \
} \
\
inline IntFormatSpec<TYPE, TypeSpec<'X'> > hexu(TYPE value) { \
return IntFormatSpec<TYPE, TypeSpec<'X'> >(value, TypeSpec<'X'>()); \
} \
} \
\
template <char TYPE_CODE> \
inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> > pad( \
IntFormatSpec<TYPE, TypeSpec<TYPE_CODE> > f, unsigned width) { \
return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> >( \
f.value(), AlignTypeSpec<TYPE_CODE>(width, ' ')); \
} \
} \
\
/* For compatibility with older compilers we provide two overloads for pad, */
\
/* one that takes a fill character and one that doesn't. In the future this */
\
...
...
@@ -1646,20 +1529,20 @@ inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char> pad( \
unsigned width, Char fill) { \
return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char>( \
f.value(), AlignTypeSpec<TYPE_CODE>(width, fill)); \
} \
} \
\
inline IntFormatSpec<TYPE, AlignTypeSpec<0> > pad( \
TYPE value, unsigned width) { \
return IntFormatSpec<TYPE, AlignTypeSpec<0> >( \
value, AlignTypeSpec<0>(width, ' ')); \
} \
} \
\
template <typename Char> \
inline IntFormatSpec<TYPE, AlignTypeSpec<0>, Char> pad( \
TYPE value, unsigned width, Char fill) { \
return IntFormatSpec<TYPE, AlignTypeSpec<0>, Char>( \
value, AlignTypeSpec<0>(width, fill)); \
}
}
FMT_DEFINE_INT_FORMATTERS
(
int
)
FMT_DEFINE_INT_FORMATTERS
(
long
)
...
...
@@ -1669,17 +1552,17 @@ FMT_DEFINE_INT_FORMATTERS(LongLong)
FMT_DEFINE_INT_FORMATTERS
(
ULongLong
)
/**
\rst
Returns a string formatter that pads the formatted argument with the fill
character to the specified width using the default (left) string alignment.
\rst
Returns a string formatter that pads the formatted argument with the fill
character to the specified width using the default (left) string alignment.
**Example**::
**Example**::
std::string s = str(MemoryWriter() << pad("abc", 8));
// s == "abc "
std::string s = str(MemoryWriter() << pad("abc", 8));
// s == "abc "
\endrst
*/
\endrst
*/
template
<
typename
Char
>
inline
StrFormatSpec
<
Char
>
pad
(
const
Char
*
str
,
unsigned
width
,
Char
fill
=
' '
)
{
...
...
@@ -1711,14 +1594,10 @@ inline StrFormatSpec<wchar_t> pad(
# define FMT_GEN15(f) FMT_GEN14(f), f(14)
namespace
internal
{
inline
uint64_t
make_type
()
{
return
0
;
}
inline
uint64_t
make_type
()
{
return
0
;
}
template
<
typename
T
>
inline
uint64_t
make_type
(
const
T
&
arg
)
{
return
MakeValue
<
char
>::
type
(
arg
);
}
inline
uint64_t
make_type
(
const
T
&
arg
)
{
return
MakeValue
<
char
>::
type
(
arg
);
}
template
<
unsigned
N
>
struct
ArgArray
{
...
...
@@ -1892,21 +1771,21 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8), f(x9, 9)
/**
An error returned by an operating system or a language runtime,
for example a file opening error.
An error returned by an operating system or a language runtime,
for example a file opening error.
*/
class
SystemError
:
public
internal
::
RuntimeError
{
private:
private:
void
init
(
int
err_code
,
CStringRef
format_str
,
ArgList
args
);
protected:
protected:
int
error_code_
;
typedef
char
Char
;
// For FMT_VARIADIC_CTOR.
SystemError
()
{}
public:
public:
/**
\rst
Constructs a :class:`fmt::SystemError` object with the description
...
...
@@ -1937,32 +1816,30 @@ public:
}
FMT_VARIADIC_CTOR
(
SystemError
,
init
,
int
,
CStringRef
)
int
error_code
()
const
{
return
error_code_
;
}
int
error_code
()
const
{
return
error_code_
;
}
};
/**
\rst
This template provides operations for formatting and writing data into
a character stream. The output is stored in a buffer provided by a subclass
such as :class:`fmt::BasicMemoryWriter`.
You can use one of the following typedefs for common character types:
+---------+----------------------+
| Type | Definition |
+=========+======================+
| Writer | BasicWriter<char> |
+---------+----------------------+
| WWriter | BasicWriter<wchar_t> |
+---------+----------------------+
\endrst
*/
\rst
This template provides operations for formatting and writing data into
a character stream. The output is stored in a buffer provided by a subclass
such as :class:`fmt::BasicMemoryWriter`.
You can use one of the following typedefs for common character types:
+---------+----------------------+
| Type | Definition |
+=========+======================+
| Writer | BasicWriter<char> |
+---------+----------------------+
| WWriter | BasicWriter<wchar_t> |
+---------+----------------------+
\endrst
*/
template
<
typename
Char
>
class
BasicWriter
{
private:
private:
// Output buffer.
Buffer
<
Char
>
&
buffer_
;
...
...
@@ -1972,13 +1849,9 @@ private:
#if _SECURE_SCL
// Returns pointer value.
static
Char
*
get
(
CharPtr
p
)
{
return
p
.
base
();
}
static
Char
*
get
(
CharPtr
p
)
{
return
p
.
base
();
}
#else
static
Char
*
get
(
Char
*
p
)
{
return
p
;
}
static
Char
*
get
(
Char
*
p
)
{
return
p
;
}
#endif
// Fills the padding around the content and returns the pointer to the
...
...
@@ -2010,8 +1883,7 @@ private:
if
(
internal
::
is_negative
(
value
))
{
abs_value
=
0
-
abs_value
;
*
write_unsigned_decimal
(
abs_value
,
1
)
=
'-'
;
}
else
{
}
else
{
write_unsigned_decimal
(
abs_value
,
0
);
}
}
...
...
@@ -2068,13 +1940,13 @@ private:
friend
class
internal
::
PrintfArgFormatter
<
Char
>
;
protected:
protected:
/**
Constructs a ``BasicWriter`` object.
*/
explicit
BasicWriter
(
Buffer
<
Char
>
&
b
)
:
buffer_
(
b
)
{}
public:
public:
/**
\rst
Destroys a ``BasicWriter`` object.
...
...
@@ -2085,17 +1957,13 @@ public:
/**
Returns the total number of characters written.
*/
std
::
size_t
size
()
const
{
return
buffer_
.
size
();
}
std
::
size_t
size
()
const
{
return
buffer_
.
size
();
}
/**
Returns a pointer to the output buffer content. No terminating null
character is appended.
*/
const
Char
*
data
()
const
FMT_NOEXCEPT
{
return
&
buffer_
[
0
];
}
const
Char
*
data
()
const
FMT_NOEXCEPT
{
return
&
buffer_
[
0
];
}
/**
Returns a pointer to the output buffer content with terminating null
...
...
@@ -2237,7 +2105,7 @@ public:
return
*
this
;
}
void
clear
()
FMT_NOEXCEPT
{
buffer_
.
clear
();
}
void
clear
()
FMT_NOEXCEPT
{
buffer_
.
clear
();
}
};
template
<
typename
Char
>
...
...
@@ -2251,15 +2119,12 @@ typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
if
(
spec
.
align
()
==
ALIGN_RIGHT
)
{
std
::
fill_n
(
out
,
spec
.
width
()
-
size
,
fill
);
out
+=
spec
.
width
()
-
size
;
}
else
if
(
spec
.
align
()
==
ALIGN_CENTER
)
{
}
else
if
(
spec
.
align
()
==
ALIGN_CENTER
)
{
out
=
fill_padding
(
out
,
spec
.
width
(),
size
,
fill
);
}
else
{
}
else
{
std
::
fill_n
(
out
+
size
,
spec
.
width
()
-
size
,
fill
);
}
}
else
{
}
else
{
out
=
grow_buffer
(
size
);
}
std
::
copy
(
s
,
s
+
size
,
out
);
...
...
@@ -2268,7 +2133,7 @@ typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
template
<
typename
Char
>
typename
BasicWriter
<
Char
>::
CharPtr
BasicWriter
<
Char
>::
fill_padding
(
BasicWriter
<
Char
>::
fill_padding
(
CharPtr
buffer
,
unsigned
total_size
,
std
::
size_t
content_size
,
wchar_t
fill
)
{
std
::
size_t
padding
=
total_size
-
content_size
;
...
...
@@ -2284,7 +2149,7 @@ BasicWriter<Char>::fill_padding(
template
<
typename
Char
>
template
<
typename
Spec
>
typename
BasicWriter
<
Char
>::
CharPtr
BasicWriter
<
Char
>::
prepare_int_buffer
(
BasicWriter
<
Char
>::
prepare_int_buffer
(
unsigned
num_digits
,
const
Spec
&
spec
,
const
char
*
prefix
,
unsigned
prefix_size
)
{
unsigned
width
=
spec
.
width
();
...
...
@@ -2325,20 +2190,17 @@ BasicWriter<Char>::prepare_int_buffer(
std
::
copy
(
prefix
,
prefix
+
prefix_size
,
p
);
p
+=
size
;
std
::
fill
(
p
,
end
,
fill
);
}
else
if
(
align
==
ALIGN_CENTER
)
{
}
else
if
(
align
==
ALIGN_CENTER
)
{
p
=
fill_padding
(
p
,
width
,
size
,
fill
);
std
::
copy
(
prefix
,
prefix
+
prefix_size
,
p
);
p
+=
size
;
}
else
{
}
else
{
if
(
align
==
ALIGN_NUMERIC
)
{
if
(
prefix_size
!=
0
)
{
p
=
std
::
copy
(
prefix
,
prefix
+
prefix_size
,
p
);
size
-=
prefix_size
;
}
}
else
{
}
else
{
std
::
copy
(
prefix
,
prefix
+
prefix_size
,
end
-
size
);
}
std
::
fill
(
p
,
end
-
size
,
fill
);
...
...
@@ -2358,22 +2220,19 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
prefix
[
0
]
=
'-'
;
++
prefix_size
;
abs_value
=
0
-
abs_value
;
}
else
if
(
spec
.
flag
(
SIGN_FLAG
))
{
}
else
if
(
spec
.
flag
(
SIGN_FLAG
))
{
prefix
[
0
]
=
spec
.
flag
(
PLUS_FLAG
)
?
'+'
:
' '
;
++
prefix_size
;
}
switch
(
spec
.
type
())
{
case
0
:
case
'd'
:
{
case
0
:
case
'd'
:
{
unsigned
num_digits
=
internal
::
count_digits
(
abs_value
);
CharPtr
p
=
prepare_int_buffer
(
num_digits
,
spec
,
prefix
,
prefix_size
)
+
1
-
num_digits
;
internal
::
format_decimal
(
get
(
p
),
abs_value
,
num_digits
);
break
;
}
case
'x'
:
case
'X'
:
{
case
'x'
:
case
'X'
:
{
UnsignedType
n
=
abs_value
;
if
(
spec
.
flag
(
HASH_FLAG
))
{
prefix
[
prefix_size
++
]
=
'0'
;
...
...
@@ -2393,8 +2252,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
}
while
((
n
>>=
4
)
!=
0
);
break
;
}
case
'b'
:
case
'B'
:
{
case
'b'
:
case
'B'
:
{
UnsignedType
n
=
abs_value
;
if
(
spec
.
flag
(
HASH_FLAG
))
{
prefix
[
prefix_size
++
]
=
'0'
;
...
...
@@ -2444,10 +2302,7 @@ void BasicWriter<Char>::write_double(
case
0
:
type
=
'g'
;
break
;
case
'e'
:
case
'f'
:
case
'g'
:
case
'a'
:
case
'e'
:
case
'f'
:
case
'g'
:
case
'a'
:
break
;
case
'F'
:
#ifdef _MSC_VER
...
...
@@ -2455,9 +2310,7 @@ void BasicWriter<Char>::write_double(
type
=
'f'
;
#endif
// Fall through.
case
'E'
:
case
'G'
:
case
'A'
:
case
'E'
:
case
'G'
:
case
'A'
:
upper
=
true
;
break
;
default:
...
...
@@ -2471,8 +2324,7 @@ void BasicWriter<Char>::write_double(
if
(
internal
::
getsign
(
static_cast
<
double
>
(
value
)))
{
sign
=
'-'
;
value
=
-
value
;
}
else
if
(
spec
.
flag
(
SIGN_FLAG
))
{
}
else
if
(
spec
.
flag
(
SIGN_FLAG
))
{
sign
=
spec
.
flag
(
PLUS_FLAG
)
?
'+'
:
' '
;
}
...
...
@@ -2516,7 +2368,7 @@ void BasicWriter<Char>::write_double(
}
// Build format string.
enum
{
MAX_FORMAT_SIZE
=
10
};
// longest format: %#-*.*Lg
enum
{
MAX_FORMAT_SIZE
=
10
};
// longest format: %#-*.*Lg
Char
format
[
MAX_FORMAT_SIZE
];
Char
*
format_ptr
=
format
;
*
format_ptr
++
=
'%'
;
...
...
@@ -2525,8 +2377,7 @@ void BasicWriter<Char>::write_double(
*
format_ptr
++
=
'#'
;
if
(
spec
.
align
()
==
ALIGN_CENTER
)
{
width_for_sprintf
=
0
;
}
else
{
}
else
{
if
(
spec
.
align
()
==
ALIGN_LEFT
)
*
format_ptr
++
=
'-'
;
if
(
width
!=
0
)
...
...
@@ -2563,8 +2414,7 @@ void BasicWriter<Char>::write_double(
*
start
!=
' '
)
{
*
(
start
-
1
)
=
sign
;
sign
=
0
;
}
else
{
}
else
{
*
(
start
-
1
)
=
fill
;
}
++
n
;
...
...
@@ -2593,45 +2443,45 @@ void BasicWriter<Char>::write_double(
}
/**
\rst
This class template provides operations for formatting and writing data
into a character stream. The output is stored in a memory buffer that grows
dynamically.
\rst
This class template provides operations for formatting and writing data
into a character stream. The output is stored in a memory buffer that grows
dynamically.
You can use one of the following typedefs for common character types
and the standard allocator:
You can use one of the following typedefs for common character types
and the standard allocator:
+---------------+-----------------------------------------------------+
| Type | Definition |
+===============+=====================================================+
| MemoryWriter | BasicMemoryWriter<char, std::allocator<char>> |
+---------------+-----------------------------------------------------+
| WMemoryWriter | BasicMemoryWriter<wchar_t, std::allocator<wchar_t>> |
+---------------+-----------------------------------------------------+
+---------------+-----------------------------------------------------+
| Type | Definition |
+===============+=====================================================+
| MemoryWriter | BasicMemoryWriter<char, std::allocator<char>> |
+---------------+-----------------------------------------------------+
| WMemoryWriter | BasicMemoryWriter<wchar_t, std::allocator<wchar_t>> |
+---------------+-----------------------------------------------------+
**Example**::
**Example**::
MemoryWriter out;
out << "The answer is " << 42 << "\n";
out.write("({:+f}, {:+f})", -3.14, 3.14);
MemoryWriter out;
out << "The answer is " << 42 << "\n";
out.write("({:+f}, {:+f})", -3.14, 3.14);
This will write the following output to the ``out`` object:
This will write the following output to the ``out`` object:
.. code-block:: none
.. code-block:: none
The answer is 42
(-3.140000, +3.140000)
The answer is 42
(-3.140000, +3.140000)
The output can be converted to an ``std::string`` with ``out.str()`` or
accessed as a C string with ``out.c_str()``.
\endrst
*/
The output can be converted to an ``std::string`` with ``out.str()`` or
accessed as a C string with ``out.c_str()``.
\endrst
*/
template
<
typename
Char
,
typename
Allocator
=
std
::
allocator
<
Char
>
>
class
BasicMemoryWriter
:
public
BasicWriter
<
Char
>
{
private:
private:
internal
::
MemoryBuffer
<
Char
,
internal
::
INLINE_BUFFER_SIZE
,
Allocator
>
buffer_
;
public:
public:
explicit
BasicMemoryWriter
(
const
Allocator
&
alloc
=
Allocator
())
:
BasicWriter
<
Char
>
(
buffer_
),
buffer_
(
alloc
)
{}
...
...
@@ -2662,31 +2512,31 @@ typedef BasicMemoryWriter<char> MemoryWriter;
typedef
BasicMemoryWriter
<
wchar_t
>
WMemoryWriter
;
/**
\rst
This class template provides operations for formatting and writing data
into a fixed-size array. For writing into a dynamically growing buffer
use :class:`fmt::BasicMemoryWriter`.
Any write method will throw ``std::runtime_error`` if the output doesn't fit
into the array.
You can use one of the following typedefs for common character types:
+--------------+---------------------------+
| Type | Definition |
+==============+===========================+
| ArrayWriter | BasicArrayWriter<char> |
+--------------+---------------------------+
| WArrayWriter | BasicArrayWriter<wchar_t> |
+--------------+---------------------------+
\endrst
*/
\rst
This class template provides operations for formatting and writing data
into a fixed-size array. For writing into a dynamically growing buffer
use :class:`fmt::BasicMemoryWriter`.
Any write method will throw ``std::runtime_error`` if the output doesn't fit
into the array.
You can use one of the following typedefs for common character types:
+--------------+---------------------------+
| Type | Definition |
+==============+===========================+
| ArrayWriter | BasicArrayWriter<char> |
+--------------+---------------------------+
| WArrayWriter | BasicArrayWriter<wchar_t> |
+--------------+---------------------------+
\endrst
*/
template
<
typename
Char
>
class
BasicArrayWriter
:
public
BasicWriter
<
Char
>
{
private:
private:
internal
::
FixedBuffer
<
Char
>
buffer_
;
public:
public:
/**
\rst
Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the
...
...
@@ -2703,7 +2553,7 @@ public:
\endrst
*/
template
<
std
::
size_t
SIZE
>
explicit
BasicArrayWriter
(
Char
(
&
array
)[
SIZE
])
explicit
BasicArrayWriter
(
Char
(
&
array
)[
SIZE
])
:
BasicWriter
<
Char
>
(
buffer_
),
buffer_
(
array
,
SIZE
)
{}
};
...
...
@@ -2730,10 +2580,10 @@ void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT;
/** A Windows error. */
class
WindowsError
:
public
SystemError
{
private:
private:
void
init
(
int
error_code
,
CStringRef
format_str
,
ArgList
args
);
public:
public:
/**
\rst
Constructs a :class:`fmt::WindowsError` object with the description
...
...
@@ -2777,21 +2627,21 @@ void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT;
enum
Color
{
BLACK
,
RED
,
GREEN
,
YELLOW
,
BLUE
,
MAGENTA
,
CYAN
,
WHITE
};
/**
Formats a string and prints it to stdout using ANSI escape sequences
to specify color (experimental).
Example:
PrintColored(fmt::RED, "Elapsed time: {0:.2f} seconds") << 1.23;
*/
Formats a string and prints it to stdout using ANSI escape sequences
to specify color (experimental).
Example:
PrintColored(fmt::RED, "Elapsed time: {0:.2f} seconds") << 1.23;
*/
void
print_colored
(
Color
c
,
CStringRef
format
,
ArgList
args
);
/**
\rst
Formats arguments and returns the result as a string.
\rst
Formats arguments and returns the result as a string.
**Example**::
**Example**::
std::string message = format("The answer is {}", 42);
\endrst
std::string message = format("The answer is {}", 42);
\endrst
*/
inline
std
::
string
format
(
CStringRef
format_str
,
ArgList
args
)
{
MemoryWriter
w
;
...
...
@@ -2806,36 +2656,36 @@ inline std::wstring format(WCStringRef format_str, ArgList args) {
}
/**
\rst
Prints formatted data to the file *f*.
\rst
Prints formatted data to the file *f*.
**Example**::
**Example**::
print(stderr, "Don't {}!", "panic");
\endrst
*/
print(stderr, "Don't {}!", "panic");
\endrst
*/
void
print
(
std
::
FILE
*
f
,
CStringRef
format_str
,
ArgList
args
);
/**
\rst
Prints formatted data to ``stdout``.
\rst
Prints formatted data to ``stdout``.
**Example**::
**Example**::
print("Elapsed time: {0:.2f} seconds", 1.23);
\endrst
*/
print("Elapsed time: {0:.2f} seconds", 1.23);
\endrst
*/
void
print
(
CStringRef
format_str
,
ArgList
args
);
/**
\rst
Prints formatted data to the stream *os*.
\rst
Prints formatted data to the stream *os*.
**Example**::
**Example**::
print(cerr, "Don't {}!", "panic");
\endrst
*/
print(cerr, "Don't {}!", "panic");
\endrst
*/
void
print
(
std
::
ostream
&
os
,
CStringRef
format_str
,
ArgList
args
);
template
<
typename
Char
>
...
...
@@ -2844,13 +2694,13 @@ void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) {
}
/**
\rst
Formats arguments and returns the result as a string.
\rst
Formats arguments and returns the result as a string.
**Example**::
**Example**::
std::string message = fmt::sprintf("The answer is %d", 42);
\endrst
std::string message = fmt::sprintf("The answer is %d", 42);
\endrst
*/
inline
std
::
string
sprintf
(
CStringRef
format
,
ArgList
args
)
{
MemoryWriter
w
;
...
...
@@ -2859,37 +2709,37 @@ inline std::string sprintf(CStringRef format, ArgList args) {
}
/**
\rst
Prints formatted data to the file *f*.
\rst
Prints formatted data to the file *f*.
**Example**::
**Example**::
fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst
*/
fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst
*/
int
fprintf
(
std
::
FILE
*
f
,
CStringRef
format
,
ArgList
args
);
/**
\rst
Prints formatted data to ``stdout``.
\rst
Prints formatted data to ``stdout``.
**Example**::
**Example**::
fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst
*/
fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst
*/
inline
int
printf
(
CStringRef
format
,
ArgList
args
)
{
return
fprintf
(
stdout
,
format
,
args
);
}
/**
Fast integer formatter.
*/
Fast integer formatter.
*/
class
FormatInt
{
private:
private:
// Buffer should be large enough to hold all digits (digits10 + 1),
// a sign and a null character.
enum
{
BUFFER_SIZE
=
std
::
numeric_limits
<
ULongLong
>::
digits10
+
3
};
enum
{
BUFFER_SIZE
=
std
::
numeric_limits
<
ULongLong
>::
digits10
+
3
};
mutable
char
buffer_
[
BUFFER_SIZE
];
char
*
str_
;
...
...
@@ -2925,16 +2775,10 @@ private:
*--
str_
=
'-'
;
}
public:
explicit
FormatInt
(
int
value
)
{
FormatSigned
(
value
);
}
explicit
FormatInt
(
long
value
)
{
FormatSigned
(
value
);
}
explicit
FormatInt
(
LongLong
value
)
{
FormatSigned
(
value
);
}
public:
explicit
FormatInt
(
int
value
)
{
FormatSigned
(
value
);
}
explicit
FormatInt
(
long
value
)
{
FormatSigned
(
value
);
}
explicit
FormatInt
(
LongLong
value
)
{
FormatSigned
(
value
);
}
explicit
FormatInt
(
unsigned
value
)
:
str_
(
format_decimal
(
value
))
{}
explicit
FormatInt
(
unsigned
long
value
)
:
str_
(
format_decimal
(
value
))
{}
explicit
FormatInt
(
ULongLong
value
)
:
str_
(
format_decimal
(
value
))
{}
...
...
@@ -2942,17 +2786,13 @@ public:
/**
Returns the number of characters written to the output buffer.
*/
std
::
size_t
size
()
const
{
return
buffer_
-
str_
+
BUFFER_SIZE
-
1
;
}
std
::
size_t
size
()
const
{
return
buffer_
-
str_
+
BUFFER_SIZE
-
1
;
}
/**
Returns a pointer to the output buffer content. No terminating null
character is appended.
*/
const
char
*
data
()
const
{
return
str_
;
}
const
char
*
data
()
const
{
return
str_
;
}
/**
Returns a pointer to the output buffer content with terminating null
...
...
@@ -2968,9 +2808,7 @@ public:
Returns the content of the output buffer as an ``std::string``.
\endrst
*/
std
::
string
str
()
const
{
return
std
::
string
(
str_
,
size
());
}
std
::
string
str
()
const
{
return
std
::
string
(
str_
,
size
());
}
};
// Formats a decimal integer value writing into buffer and returns
...
...
@@ -2999,15 +2837,15 @@ inline void format_decimal(char *&buffer, T value) {
}
/**
\rst
Returns a named argument for formatting functions.
\rst
Returns a named argument for formatting functions.
**Example**::
**Example**::
print("Elapsed time: {s:.2f} seconds", arg("s", 1.23));
print("Elapsed time: {s:.2f} seconds", arg("s", 1.23));
\endrst
*/
\endrst
*/
template
<
typename
T
>
inline
internal
::
NamedArg
<
char
>
arg
(
StringRef
name
,
const
T
&
arg
)
{
return
internal
::
NamedArg
<
char
>
(
name
,
arg
);
...
...
@@ -3096,32 +2934,32 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
#endif // FMT_USE_VARIADIC_TEMPLATES
/**
\rst
Defines a variadic function with the specified return type, function name
and argument types passed as variable arguments to this macro.
\rst
Defines a variadic function with the specified return type, function name
and argument types passed as variable arguments to this macro.
**Example**::
**Example**::
void print_error(const char *file, int line, const char *format,
fmt::ArgList args) {
fmt::print("{}: {}: ", file, line);
fmt::print(format, args);
}
FMT_VARIADIC(void, print_error, const char *, int, const char *)
void print_error(const char *file, int line, const char *format,
fmt::ArgList args) {
fmt::print("{}: {}: ", file, line);
fmt::print(format, args);
}
FMT_VARIADIC(void, print_error, const char *, int, const char *)
``FMT_VARIADIC`` is used for compatibility with legacy C++ compilers that
don't implement variadic templates. You don't have to use this macro if
you don't need legacy compiler support and can use variadic templates
directly::
``FMT_VARIADIC`` is used for compatibility with legacy C++ compilers that
don't implement variadic templates. You don't have to use this macro if
you don't need legacy compiler support and can use variadic templates
directly::
template <typename... Args>
void print_error(const char *file, int line, const char *format,
const Args & ... args) {
fmt::print("{}: {}: ", file, line);
fmt::print(format, args...);
}
\endrst
*/
template <typename... Args>
void print_error(const char *file, int line, const char *format,
const Args & ... args) {
fmt::print("{}: {}: ", file, line);
fmt::print(format, args...);
}
\endrst
*/
#define FMT_VARIADIC(ReturnType, func, ...) \
FMT_VARIADIC_(char, ReturnType, func, return func, __VA_ARGS__)
...
...
@@ -3133,19 +2971,19 @@ fmt::print(format, args...);
#define FMT_CAPTURE_ARG_W_(id, index) ::fmt::arg(L###id, id)
/**
\rst
Convenient macro to capture the arguments' names and values into several
``fmt::arg(name, value)``.
\rst
Convenient macro to capture the arguments' names and values into several
``fmt::arg(name, value)``.
**Example**::
**Example**::
int x = 1, y = 2;
print("point: ({x}, {y})", FMT_CAPTURE(x, y));
// same as:
// print("point: ({x}, {y})", arg("x", x), arg("y", y));
int x = 1, y = 2;
print("point: ({x}, {y})", FMT_CAPTURE(x, y));
// same as:
// print("point: ({x}, {y})", arg("x", x), arg("y", y));
\endrst
*/
\endrst
*/
#define FMT_CAPTURE(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_, __VA_ARGS__)
#define FMT_CAPTURE_W(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_W_, __VA_ARGS__)
...
...
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