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
6312748c
Commit
6312748c
authored
Sep 14, 2016
by
gabime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
updated bundled fmt to version 1fb0586b065c4202e976528a6bdc6384dc56dc04
parent
87d79eb9
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
658 additions
and
1330 deletions
+658
-1330
format.cc
include/spdlog/fmt/bundled/format.cc
+3
-3
format.h
include/spdlog/fmt/bundled/format.h
+533
-1110
ostream.cc
include/spdlog/fmt/bundled/ostream.cc
+5
-14
ostream.h
include/spdlog/fmt/bundled/ostream.h
+17
-37
printf.h
include/spdlog/fmt/bundled/printf.h
+100
-166
No files found.
include/spdlog/fmt/bundled/format.cc
View file @
6312748c
...
...
@@ -25,9 +25,9 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Commented out by spdlog to use header only
// #include "fmt/format.h"
// #include "fmt/printf.h"
// Commented out by spdlog to use header only
// #include "fmt/format.h"
// #include "fmt/printf.h"
#include <string.h>
...
...
include/spdlog/fmt/bundled/format.h
View file @
6312748c
...
...
@@ -244,13 +244,10 @@ typedef __int64 intmax_t;
#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL)
# include <intrin.h> // _BitScanReverse, _BitScanReverse64
namespace
fmt
{
namespace
internal
{
namespace
fmt
{
namespace
internal
{
# pragma intrinsic(_BitScanReverse)
inline
uint32_t
clz
(
uint32_t
x
)
{
inline
uint32_t
clz
(
uint32_t
x
)
{
unsigned
long
r
=
0
;
_BitScanReverse
(
&
r
,
x
);
...
...
@@ -267,8 +264,7 @@ inline uint32_t clz(uint32_t x)
# pragma intrinsic(_BitScanReverse64)
# endif
inline
uint32_t
clzll
(
uint64_t
x
)
{
inline
uint32_t
clzll
(
uint64_t
x
)
{
unsigned
long
r
=
0
;
# ifdef _WIN64
_BitScanReverse64
(
&
r
,
x
);
...
...
@@ -293,78 +289,47 @@ inline uint32_t clzll(uint64_t x)
}
#endif
namespace
fmt
{
namespace
internal
{
struct
DummyInt
{
namespace
fmt
{
namespace
internal
{
struct
DummyInt
{
int
data
[
2
];
operator
int
()
const
{
return
0
;
}
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
();
}
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
const_check
(
T
value
)
{
return
value
;
}
inline
T
const_check
(
T
value
)
{
return
value
;
}
}
}
// namespace fmt
namespace
std
{
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
:
public
std
::
numeric_limits
<
int
>
{
public
:
// Portable version of isinf.
template
<
typename
T
>
static
bool
isinfinity
(
T
x
)
{
static
bool
isinfinity
(
T
x
)
{
using
namespace
fmt
::
internal
;
// The resolution "priority" is:
// isinf macro > std::isinf > ::isinf > fmt::internal::isinf
if
(
const_check
(
sizeof
(
isinf
(
x
))
==
sizeof
(
bool
)
||
sizeof
(
isinf
(
x
))
==
sizeof
(
int
)))
{
sizeof
(
isinf
(
x
))
==
sizeof
(
int
)))
{
return
isinf
(
x
)
!=
0
;
}
return
!
_finite
(
static_cast
<
double
>
(
x
));
...
...
@@ -372,20 +337,17 @@ public:
// Portable version of isnan.
template
<
typename
T
>
static
bool
isnotanumber
(
T
x
)
{
static
bool
isnotanumber
(
T
x
)
{
using
namespace
fmt
::
internal
;
if
(
const_check
(
sizeof
(
isnan
(
x
))
==
sizeof
(
bool
)
||
sizeof
(
isnan
(
x
))
==
sizeof
(
int
)))
{
sizeof
(
isnan
(
x
))
==
sizeof
(
int
)))
{
return
isnan
(
x
)
!=
0
;
}
return
_isnan
(
static_cast
<
double
>
(
x
))
!=
0
;
}
// Portable version of signbit.
static
bool
isnegative
(
double
x
)
{
static
bool
isnegative
(
double
x
)
{
using
namespace
fmt
::
internal
;
if
(
const_check
(
sizeof
(
signbit
(
x
))
==
sizeof
(
int
)))
return
signbit
(
x
)
!=
0
;
...
...
@@ -399,8 +361,7 @@ public:
};
}
// namespace std
namespace
fmt
{
namespace
fmt
{
// Fix the warning about long long on older versions of GCC
// that don't support the diagnostic pragma.
...
...
@@ -452,13 +413,12 @@ class BasicFormatter;
\endrst
*/
template
<
typename
Char
>
class
BasicStringRef
{
private
:
class
BasicStringRef
{
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
)
{}
...
...
@@ -484,26 +444,18 @@ public:
Converts a string reference to an ``std::string`` object.
\endrst
*/
std
::
basic_string
<
Char
>
to_string
()
const
{
std
::
basic_string
<
Char
>
to_string
()
const
{
return
std
::
basic_string
<
Char
>
(
data_
,
size_
);
}
/** Returns a pointer to the string data. */
const
Char
*
data
()
const
{
return
data_
;
}
const
Char
*
data
()
const
{
return
data_
;
}
/** Returns the string size. */
std
::
size_t
size
()
const
{
return
size_
;
}
std
::
size_t
size
()
const
{
return
size_
;
}
// Lexicographically compare this string reference to other.
int
compare
(
BasicStringRef
other
)
const
{
int
compare
(
BasicStringRef
other
)
const
{
std
::
size_t
size
=
size_
<
other
.
size_
?
size_
:
other
.
size_
;
int
result
=
std
::
char_traits
<
Char
>::
compare
(
data_
,
other
.
data_
,
size
);
if
(
result
==
0
)
...
...
@@ -511,28 +463,22 @@ public:
return
result
;
}
friend
bool
operator
==
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
friend
bool
operator
==
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
return
lhs
.
compare
(
rhs
)
==
0
;
}
friend
bool
operator
!=
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
friend
bool
operator
!=
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
return
lhs
.
compare
(
rhs
)
!=
0
;
}
friend
bool
operator
<
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
friend
bool
operator
<
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
return
lhs
.
compare
(
rhs
)
<
0
;
}
friend
bool
operator
<=
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
friend
bool
operator
<=
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
return
lhs
.
compare
(
rhs
)
<=
0
;
}
friend
bool
operator
>
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
friend
bool
operator
>
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
return
lhs
.
compare
(
rhs
)
>
0
;
}
friend
bool
operator
>=
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
friend
bool
operator
>=
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
return
lhs
.
compare
(
rhs
)
>=
0
;
}
};
...
...
@@ -566,12 +512,11 @@ typedef BasicStringRef<wchar_t> WStringRef;
\endrst
*/
template
<
typename
Char
>
class
BasicCStringRef
{
private
:
class
BasicCStringRef
{
private
:
const
Char
*
data_
;
public
:
public
:
/** Constructs a string reference object from a C string. */
BasicCStringRef
(
const
Char
*
s
)
:
data_
(
s
)
{}
...
...
@@ -583,33 +528,25 @@ 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. */
class
FormatError
:
public
std
::
runtime_error
{
public
:
class
FormatError
:
public
std
::
runtime_error
{
public
:
explicit
FormatError
(
CStringRef
message
)
:
std
::
runtime_error
(
message
.
c_str
())
{}
~
FormatError
()
throw
();
};
namespace
internal
{
namespace
internal
{
// 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 <> \
...
...
@@ -624,8 +561,7 @@ FMT_SPECIALIZE_MAKE_UNSIGNED(LongLong, ULongLong);
// Casts nonnegative integer to unsigned.
template
<
typename
Int
>
inline
typename
MakeUnsigned
<
Int
>::
Type
to_unsigned
(
Int
value
)
{
inline
typename
MakeUnsigned
<
Int
>::
Type
to_unsigned
(
Int
value
)
{
FMT_ASSERT
(
value
>=
0
,
"negative value"
);
return
static_cast
<
typename
MakeUnsigned
<
Int
>::
Type
>
(
value
);
}
...
...
@@ -637,16 +573,12 @@ enum { INLINE_BUFFER_SIZE = 500 };
#if FMT_SECURE_SCL
// Use checked iterator to avoid warnings on MSVC.
template
<
typename
T
>
inline
stdext
::
checked_array_iterator
<
T
*>
make_ptr
(
T
*
ptr
,
std
::
size_t
size
)
{
inline
stdext
::
checked_array_iterator
<
T
*>
make_ptr
(
T
*
ptr
,
std
::
size_t
size
)
{
return
stdext
::
checked_array_iterator
<
T
*>
(
ptr
,
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
...
...
@@ -656,12 +588,11 @@ inline T *make_ptr(T *ptr, std::size_t)
\endrst
*/
template
<
typename
T
>
class
Buffer
{
private
:
class
Buffer
{
private
:
FMT_DISALLOW_COPY_AND_ASSIGN
(
Buffer
);
protected
:
protected
:
T
*
ptr_
;
std
::
size_t
size_
;
std
::
size_t
capacity_
;
...
...
@@ -677,26 +608,19 @@ 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.
*/
void
resize
(
std
::
size_t
new_size
)
{
void
resize
(
std
::
size_t
new_size
)
{
if
(
new_size
>
capacity_
)
grow
(
new_size
);
size_
=
new_size
;
...
...
@@ -707,16 +631,14 @@ public:
Reserves space to store at least *capacity* elements.
\endrst
*/
void
reserve
(
std
::
size_t
capacity
)
{
void
reserve
(
std
::
size_t
capacity
)
{
if
(
capacity
>
capacity_
)
grow
(
capacity
);
}
void
clear
()
FMT_NOEXCEPT
{
size_
=
0
;
}
void
push_back
(
const
T
&
value
)
{
void
push_back
(
const
T
&
value
)
{
if
(
size_
==
capacity_
)
grow
(
size_
+
1
);
ptr_
[
size_
++
]
=
value
;
...
...
@@ -726,20 +648,13 @@ 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
>
template
<
typename
U
>
void
Buffer
<
T
>::
append
(
const
U
*
begin
,
const
U
*
end
)
{
void
Buffer
<
T
>::
append
(
const
U
*
begin
,
const
U
*
end
)
{
std
::
size_t
new_size
=
size_
+
internal
::
to_unsigned
(
end
-
begin
);
if
(
new_size
>
capacity_
)
grow
(
new_size
);
...
...
@@ -748,51 +663,41 @@ void Buffer<T>::append(const U *begin, const U *end)
size_
=
new_size
;
}
namespace
internal
{
namespace
internal
{
// A memory buffer for trivially copyable/constructible types with the first
// SIZE elements stored in the object itself.
template
<
typename
T
,
std
::
size_t
SIZE
,
typename
Allocator
=
std
::
allocator
<
T
>
>
class
MemoryBuffer
:
private
Allocator
,
public
Buffer
<
T
>
{
private
:
class
MemoryBuffer
:
private
Allocator
,
public
Buffer
<
T
>
{
private
:
T
data_
[
SIZE
];
// Deallocate memory allocated by the buffer.
void
deallocate
()
{
void
deallocate
()
{
if
(
this
->
ptr_
!=
data_
)
Allocator
::
deallocate
(
this
->
ptr_
,
this
->
capacity_
);
}
protected
:
protected
:
void
grow
(
std
::
size_t
size
);
public
:
public
:
explicit
MemoryBuffer
(
const
Allocator
&
alloc
=
Allocator
())
:
Allocator
(
alloc
),
Buffer
<
T
>
(
data_
,
SIZE
)
{}
~
MemoryBuffer
()
{
deallocate
();
}
~
MemoryBuffer
()
{
deallocate
();
}
#if FMT_USE_RVALUE_REFERENCES
private
:
private
:
// Move data from other to this buffer.
void
move
(
MemoryBuffer
&
other
)
{
void
move
(
MemoryBuffer
&
other
)
{
Allocator
&
this_alloc
=
*
this
,
&
other_alloc
=
other
;
this_alloc
=
std
::
move
(
other_alloc
);
this
->
size_
=
other
.
size_
;
this
->
capacity_
=
other
.
capacity_
;
if
(
other
.
ptr_
==
other
.
data_
)
{
if
(
other
.
ptr_
==
other
.
data_
)
{
this
->
ptr_
=
data_
;
std
::
uninitialized_copy
(
other
.
data_
,
other
.
data_
+
this
->
size_
,
make_ptr
(
data_
,
this
->
capacity_
));
}
else
{
}
else
{
this
->
ptr_
=
other
.
ptr_
;
// Set pointer to the inline array so that delete is not called
// when deallocating.
...
...
@@ -800,14 +705,12 @@ private:
}
}
public
:
MemoryBuffer
(
MemoryBuffer
&&
other
)
{
public
:
MemoryBuffer
(
MemoryBuffer
&&
other
)
{
move
(
other
);
}
MemoryBuffer
&
operator
=
(
MemoryBuffer
&&
other
)
{
MemoryBuffer
&
operator
=
(
MemoryBuffer
&&
other
)
{
assert
(
this
!=
&
other
);
deallocate
();
move
(
other
);
...
...
@@ -816,15 +719,11 @@ 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
>
void
MemoryBuffer
<
T
,
SIZE
,
Allocator
>::
grow
(
std
::
size_t
size
)
{
void
MemoryBuffer
<
T
,
SIZE
,
Allocator
>::
grow
(
std
::
size_t
size
)
{
std
::
size_t
new_capacity
=
this
->
capacity_
+
this
->
capacity_
/
2
;
if
(
size
>
new_capacity
)
new_capacity
=
size
;
...
...
@@ -845,45 +744,36 @@ void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size)
// A fixed-size buffer.
template
<
typename
Char
>
class
FixedBuffer
:
public
fmt
::
Buffer
<
Char
>
{
public
:
class
FixedBuffer
:
public
fmt
::
Buffer
<
Char
>
{
public
:
FixedBuffer
(
Char
*
array
,
std
::
size_t
size
)
:
fmt
::
Buffer
<
Char
>
(
array
,
size
)
{}
protected
:
protected
:
FMT_API
void
grow
(
std
::
size_t
size
);
};
template
<
typename
Char
>
class
BasicCharTraits
{
public
:
class
BasicCharTraits
{
public
:
#if FMT_SECURE_SCL
typedef
stdext
::
checked_array_iterator
<
Char
*>
CharPtr
;
#else
typedef
Char
*
CharPtr
;
#endif
static
Char
cast
(
int
value
)
{
return
static_cast
<
Char
>
(
value
);
}
static
Char
cast
(
int
value
)
{
return
static_cast
<
Char
>
(
value
);
}
};
template
<
typename
Char
>
class
CharTraits
;
template
<>
class
CharTraits
<
char
>
:
public
BasicCharTraits
<
char
>
{
private
:
class
CharTraits
<
char
>
:
public
BasicCharTraits
<
char
>
{
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
>
...
...
@@ -892,17 +782,10 @@ 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
;
}
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
;
}
template
<
typename
T
>
FMT_API
static
int
format_float
(
wchar_t
*
buffer
,
std
::
size_t
size
,
...
...
@@ -911,49 +794,33 @@ public:
// Checks if a number is negative - used to avoid warnings.
template
<
bool
IsSigned
>
struct
SignChecker
{
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
>
{
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.
// Same as (value < 0) but doesn't produce warnings if T is an unsigned type.
template
<
typename
T
>
inline
bool
is_negative
(
T
value
)
{
inline
bool
is_negative
(
T
value
)
{
return
SignChecker
<
std
::
numeric_limits
<
T
>::
is_signed
>::
is_negative
(
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
{
struct
IntTraits
{
// Smallest of uint32_t and uint64_t that is large enough to represent
// all values of T.
typedef
typename
...
...
@@ -965,8 +832,7 @@ FMT_API void report_unknown_type(char code, const char *type);
// Static data is placed in this class template to allow header-only
// configuration.
template
<
typename
T
=
void
>
struct
FMT_API
BasicData
{
struct
FMT_API
BasicData
{
static
const
uint32_t
POWERS_OF_10_32
[];
static
const
uint64_t
POWERS_OF_10_64
[];
static
const
char
DIGITS
[];
...
...
@@ -987,8 +853,7 @@ typedef BasicData<> Data;
#ifdef FMT_BUILTIN_CLZLL
// Returns the number of decimal digits in n. Leading zeros are not counted
// except for n == 0 in which case count_digits returns 1.
inline
unsigned
count_digits
(
uint64_t
n
)
{
inline
unsigned
count_digits
(
uint64_t
n
)
{
// Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
// and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits.
int
t
=
(
64
-
FMT_BUILTIN_CLZLL
(
n
|
1
))
*
1233
>>
12
;
...
...
@@ -996,11 +861,9 @@ inline unsigned count_digits(uint64_t n)
}
#else
// Fallback version of count_digits used when __builtin_clz is not available.
inline
unsigned
count_digits
(
uint64_t
n
)
{
inline
unsigned
count_digits
(
uint64_t
n
)
{
unsigned
count
=
1
;
for
(;;)
{
for
(;;)
{
// Integer division is slow so do it for a group of four digits instead
// of for every digit. The idea comes from the talk by Alexandrescu
// "Three Optimization Tips for C++". See speed-test for a comparison.
...
...
@@ -1016,35 +879,31 @@ inline unsigned count_digits(uint64_t n)
#ifdef FMT_BUILTIN_CLZ
// Optional version of count_digits for better performance on 32-bit platforms.
inline
unsigned
count_digits
(
uint32_t
n
)
{
inline
unsigned
count_digits
(
uint32_t
n
)
{
int
t
=
(
32
-
FMT_BUILTIN_CLZ
(
n
|
1
))
*
1233
>>
12
;
return
to_unsigned
(
t
)
-
(
n
<
Data
::
POWERS_OF_10_32
[
t
])
+
1
;
}
#endif
// A functor that doesn't add a thousands separator.
struct
NoThousandsSep
{
struct
NoThousandsSep
{
template
<
typename
Char
>
void
operator
()(
Char
*
)
{}
};
// A functor that adds a thousands separator.
class
ThousandsSep
{
private
:
class
ThousandsSep
{
private
:
fmt
::
StringRef
sep_
;
// Index of a decimal digit with the least significant digit having index 0.
unsigned
digit_index_
;
public
:
public
:
explicit
ThousandsSep
(
fmt
::
StringRef
sep
)
:
sep_
(
sep
),
digit_index_
(
0
)
{}
template
<
typename
Char
>
void
operator
()(
Char
*&
buffer
)
{
void
operator
()(
Char
*&
buffer
)
{
if
(
++
digit_index_
%
3
!=
0
)
return
;
buffer
-=
sep_
.
size
();
...
...
@@ -1058,11 +917,9 @@ public:
// add a thousands separator if necessary.
template
<
typename
UInt
,
typename
Char
,
typename
ThousandsSep
>
inline
void
format_decimal
(
Char
*
buffer
,
UInt
value
,
unsigned
num_digits
,
ThousandsSep
thousands_sep
)
{
ThousandsSep
thousands_sep
)
{
buffer
+=
num_digits
;
while
(
value
>=
100
)
{
while
(
value
>=
100
)
{
// Integer division is slow so do it for a group of two digits instead
// of for every digit. The idea comes from the talk by Alexandrescu
// "Three Optimization Tips for C++". See speed-test for a comparison.
...
...
@@ -1073,8 +930,7 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits,
*--
buffer
=
Data
::
DIGITS
[
index
];
thousands_sep
(
buffer
);
}
if
(
value
<
10
)
{
if
(
value
<
10
)
{
*--
buffer
=
static_cast
<
char
>
(
'0'
+
value
);
return
;
}
...
...
@@ -1085,8 +941,7 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits,
}
template
<
typename
UInt
,
typename
Char
>
inline
void
format_decimal
(
Char
*
buffer
,
UInt
value
,
unsigned
num_digits
)
{
inline
void
format_decimal
(
Char
*
buffer
,
UInt
value
,
unsigned
num_digits
)
{
return
format_decimal
(
buffer
,
value
,
num_digits
,
NoThousandsSep
());
}
...
...
@@ -1101,57 +956,31 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits)
#if FMT_USE_WINDOWS_H
// A converter from UTF-8 to UTF-16.
// It is only provided for Windows since other systems support UTF-8 natively.
class
UTF8ToUTF16
{
private
:
class
UTF8ToUTF16
{
private
:
MemoryBuffer
<
wchar_t
,
INLINE_BUFFER_SIZE
>
buffer_
;
public
:
public
:
FMT_API
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
:
class
UTF16ToUTF8
{
private
:
MemoryBuffer
<
char
,
INLINE_BUFFER_SIZE
>
buffer_
;
public
:
public
:
UTF16ToUTF8
()
{}
FMT_API
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
...
...
@@ -1164,11 +993,9 @@ FMT_API void format_windows_error(fmt::Writer &out, int error_code,
#endif
// A formatting argument value.
struct
Value
{
struct
Value
{
template
<
typename
Char
>
struct
StringValue
{
struct
StringValue
{
const
Char
*
value
;
std
::
size_t
size
;
};
...
...
@@ -1176,14 +1003,12 @@ struct Value
typedef
void
(
*
FormatFunc
)(
void
*
formatter
,
const
void
*
arg
,
void
*
format_str_ptr
);
struct
CustomValue
{
struct
CustomValue
{
const
void
*
value
;
FormatFunc
format
;
};
union
{
union
{
int
int_value
;
unsigned
uint_value
;
LongLong
long_long_value
;
...
...
@@ -1198,8 +1023,7 @@ struct Value
CustomValue
custom
;
};
enum
Type
{
enum
Type
{
NONE
,
NAMED_ARG
,
// Integer types should go first,
INT
,
UINT
,
LONG_LONG
,
ULONG_LONG
,
BOOL
,
CHAR
,
LAST_INTEGER_TYPE
=
CHAR
,
...
...
@@ -1211,8 +1035,7 @@ struct Value
// A formatting argument. It is a trivially copyable/constructible type to
// allow storage in internal::MemoryBuffer.
struct
Arg
:
Value
{
struct
Arg
:
Value
{
Type
type
;
};
...
...
@@ -1225,15 +1048,13 @@ struct Null {};
// A helper class template to enable or disable overloads taking wide
// characters and strings in MakeValue.
template
<
typename
T
,
typename
Char
>
struct
WCharHelper
{
struct
WCharHelper
{
typedef
Null
<
T
>
Supported
;
typedef
T
Unsupported
;
};
template
<
typename
T
>
struct
WCharHelper
<
T
,
wchar_t
>
{
struct
WCharHelper
<
T
,
wchar_t
>
{
typedef
T
Supported
;
typedef
Null
<
T
>
Unsupported
;
};
...
...
@@ -1249,30 +1070,25 @@ Yes &convert(fmt::ULongLong);
No
&
convert
(...);
template
<
typename
T
,
bool
ENABLE_CONVERSION
>
struct
ConvertToIntImpl
{
struct
ConvertToIntImpl
{
enum
{
value
=
ENABLE_CONVERSION
};
};
template
<
typename
T
,
bool
ENABLE_CONVERSION
>
struct
ConvertToIntImpl2
{
struct
ConvertToIntImpl2
{
enum
{
value
=
false
};
};
template
<
typename
T
>
struct
ConvertToIntImpl2
<
T
,
true
>
{
enum
{
struct
ConvertToIntImpl2
<
T
,
true
>
{
enum
{
// Don't convert numeric types.
value
=
ConvertToIntImpl
<
T
,
!
std
::
numeric_limits
<
T
>::
is_specialized
>::
value
};
};
template
<
typename
T
>
struct
ConvertToInt
{
struct
ConvertToInt
{
enum
{
enable_conversion
=
sizeof
(
convert
(
get
<
T
>
()))
==
sizeof
(
Yes
)
};
enum
{
value
=
ConvertToIntImpl2
<
T
,
enable_conversion
>::
value
};
};
...
...
@@ -1290,38 +1106,25 @@ 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
;
};
// For bcc32 which doesn't understand ! in template arguments.
template
<
bool
>
struct
Not
{
enum
{
value
=
0
};
};
template
<
bool
>
struct
Not
{
enum
{
value
=
0
};
};
template
<>
struct
Not
<
false
>
{
enum
{
value
=
1
};
};
template
<>
struct
Not
<
false
>
{
enum
{
value
=
1
};
};
template
<
typename
T
>
struct
False
{
enum
{
value
=
0
};
};
template
<
typename
T
,
T
>
struct
LConvCheck
{
template
<
typename
T
,
T
>
struct
LConvCheck
{
LConvCheck
(
int
)
{}
};
...
...
@@ -1330,24 +1133,48 @@ template<typename T, T> struct LConvCheck
// ``lconv`` is stubbed as an empty struct.
template
<
typename
LConv
>
inline
StringRef
thousands_sep
(
LConv
*
lc
,
LConvCheck
<
char
*
LConv
::*
,
&
LConv
::
thousands_sep
>
=
0
)
{
LConv
*
lc
,
LConvCheck
<
char
*
LConv
::*
,
&
LConv
::
thousands_sep
>
=
0
)
{
return
lc
->
thousands_sep
;
}
inline
fmt
::
StringRef
thousands_sep
(...)
{
return
""
;
inline
fmt
::
StringRef
thousands_sep
(...)
{
return
""
;
}
#define FMT_CONCAT(a, b) a##b
#if FMT_GCC_VERSION >= 407
# define FMT_UNUSED __attribute__((unused))
#else
# define FMT_UNUSED
#endif
#ifndef FMT_USE_STATIC_ASSERT
# define FMT_USE_STATIC_ASSERT 0
#endif
#if FMT_USE_STATIC_ASSERT || FMT_HAS_FEATURE(cxx_static_assert) || \
(FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600
# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message)
#else
# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b)
# define FMT_STATIC_ASSERT(cond, message) \
typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
#endif
template
<
typename
Formatter
,
typename
Char
,
typename
T
>
void
format_arg
(
Formatter
&
,
const
Char
*
,
const
T
&
)
{
FMT_STATIC_ASSERT
(
False
<
T
>::
value
,
"Cannot format argument. To enable the use of ostream "
"operator<< include fmt/ostream.h. Otherwise provide "
"an overload of format_arg."
);
}
// Makes an Arg object from any type.
template
<
typename
Formatter
>
class
MakeValue
:
public
Arg
{
public
:
class
MakeValue
:
public
Arg
{
public
:
typedef
typename
Formatter
::
Char
Char
;
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
...
...
@@ -1370,14 +1197,12 @@ private:
MakeValue
(
typename
WCharHelper
<
const
std
::
wstring
&
,
Char
>::
Unsupported
);
MakeValue
(
typename
WCharHelper
<
WStringRef
,
Char
>::
Unsupported
);
void
set_string
(
StringRef
str
)
{
void
set_string
(
StringRef
str
)
{
string
.
value
=
str
.
data
();
string
.
size
=
str
.
size
();
}
void
set_string
(
WStringRef
str
)
{
void
set_string
(
WStringRef
str
)
{
wstring
.
value
=
str
.
data
();
wstring
.
size
=
str
.
size
();
}
...
...
@@ -1385,14 +1210,13 @@ private:
// Formats an argument of a custom type, such as a user-defined class.
template
<
typename
T
>
static
void
format_custom_arg
(
void
*
formatter
,
const
void
*
arg
,
void
*
format_str_ptr
)
{
format
(
*
static_cast
<
Formatter
*>
(
formatter
),
void
*
formatter
,
const
void
*
arg
,
void
*
format_str_ptr
)
{
format_arg
(
*
static_cast
<
Formatter
*>
(
formatter
),
*
static_cast
<
const
Char
**>
(
format_str_ptr
),
*
static_cast
<
const
T
*>
(
arg
));
}
public
:
public
:
MakeValue
()
{}
#define FMT_MAKE_VALUE_(Type, field, TYPE, rhs) \
...
...
@@ -1408,8 +1232,7 @@ public:
FMT_MAKE_VALUE
(
int
,
int_value
,
INT
)
FMT_MAKE_VALUE
(
unsigned
,
uint_value
,
UINT
)
MakeValue
(
long
value
)
{
MakeValue
(
long
value
)
{
// To minimize the number of types we need to deal with, long is
// translated either to int or to long long depending on its size.
if
(
const_check
(
sizeof
(
long
)
==
sizeof
(
int
)))
...
...
@@ -1417,20 +1240,17 @@ public:
else
long_long_value
=
value
;
}
static
uint64_t
type
(
long
)
{
static
uint64_t
type
(
long
)
{
return
sizeof
(
long
)
==
sizeof
(
int
)
?
Arg
::
INT
:
Arg
::
LONG_LONG
;
}
MakeValue
(
unsigned
long
value
)
{
MakeValue
(
unsigned
long
value
)
{
if
(
const_check
(
sizeof
(
unsigned
long
)
==
sizeof
(
unsigned
)))
uint_value
=
static_cast
<
unsigned
>
(
value
);
else
ulong_long_value
=
value
;
}
static
uint64_t
type
(
unsigned
long
)
{
static
uint64_t
type
(
unsigned
long
)
{
return
sizeof
(
unsigned
long
)
==
sizeof
(
unsigned
)
?
Arg
::
UINT
:
Arg
::
ULONG_LONG
;
}
...
...
@@ -1445,14 +1265,10 @@ public:
FMT_MAKE_VALUE
(
char
,
int_value
,
CHAR
)
#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
;
}
static
uint64_t
type
(
wchar_t
)
{
return
Arg
::
CHAR
;
}
static
uint64_t
type
(
wchar_t
)
{
return
Arg
::
CHAR
;
}
#endif
#define FMT_MAKE_STR_VALUE(Type, TYPE) \
...
...
@@ -1461,7 +1277,9 @@ public:
FMT_MAKE_VALUE
(
char
*
,
string
.
value
,
CSTRING
)
FMT_MAKE_VALUE
(
const
char
*
,
string
.
value
,
CSTRING
)
FMT_MAKE_VALUE
(
signed
char
*
,
sstring
.
value
,
CSTRING
)
FMT_MAKE_VALUE
(
const
signed
char
*
,
sstring
.
value
,
CSTRING
)
FMT_MAKE_VALUE
(
unsigned
char
*
,
ustring
.
value
,
CSTRING
)
FMT_MAKE_VALUE
(
const
unsigned
char
*
,
ustring
.
value
,
CSTRING
)
FMT_MAKE_STR_VALUE
(
const
std
::
string
&
,
STRING
)
FMT_MAKE_STR_VALUE
(
StringRef
,
STRING
)
...
...
@@ -1484,60 +1302,47 @@ public:
template
<
typename
T
>
MakeValue
(
const
T
&
value
,
typename
EnableIf
<
Not
<
ConvertToInt
<
T
>::
value
>::
value
,
int
>::
type
=
0
)
{
ConvertToInt
<
T
>::
value
>::
value
,
int
>::
type
=
0
)
{
custom
.
value
=
&
value
;
custom
.
format
=
&
format_custom_arg
<
T
>
;
}
template
<
typename
T
>
MakeValue
(
const
T
&
value
,
typename
EnableIf
<
ConvertToInt
<
T
>::
value
,
int
>::
type
=
0
)
{
typename
EnableIf
<
ConvertToInt
<
T
>::
value
,
int
>::
type
=
0
)
{
int_value
=
value
;
}
template
<
typename
T
>
static
uint64_t
type
(
const
T
&
)
{
static
uint64_t
type
(
const
T
&
)
{
return
ConvertToInt
<
T
>::
value
?
Arg
::
INT
:
Arg
::
CUSTOM
;
}
// Additional template param `Char_` is needed here because make_type always
// uses 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
Formatter
>
class
MakeArg
:
public
Arg
{
class
MakeArg
:
public
Arg
{
public
:
MakeArg
()
{
MakeArg
()
{
type
=
Arg
::
NONE
;
}
template
<
typename
T
>
MakeArg
(
const
T
&
value
)
:
Arg
(
MakeValue
<
Formatter
>
(
value
))
{
:
Arg
(
MakeValue
<
Formatter
>
(
value
))
{
type
=
static_cast
<
Arg
::
Type
>
(
MakeValue
<
Formatter
>::
type
(
value
));
}
};
template
<
typename
Char
>
struct
NamedArg
:
Arg
{
struct
NamedArg
:
Arg
{
BasicStringRef
<
Char
>
name
;
template
<
typename
T
>
...
...
@@ -1545,9 +1350,8 @@ struct NamedArg : Arg
:
Arg
(
MakeArg
<
BasicFormatter
<
Char
>
>
(
value
)),
name
(
argname
)
{}
};
class
RuntimeError
:
public
std
::
runtime_error
{
protected
:
class
RuntimeError
:
public
std
::
runtime_error
{
protected
:
RuntimeError
()
:
std
::
runtime_error
(
""
)
{}
~
RuntimeError
()
throw
();
};
...
...
@@ -1557,14 +1361,12 @@ class ArgMap;
}
// namespace internal
/** An argument list. */
class
ArgList
{
private
:
class
ArgList
{
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_
;
union
{
union
{
// If the number of arguments is less than MAX_PACKED_ARGS, the argument
// values are stored in values_, otherwise they are stored in args_.
// This is done to reduce compiled code size as storing larger objects
...
...
@@ -1574,8 +1376,7 @@ private:
const
internal
::
Arg
*
args_
;
};
internal
::
Arg
::
Type
type
(
unsigned
index
)
const
{
internal
::
Arg
::
Type
type
(
unsigned
index
)
const
{
unsigned
shift
=
index
*
4
;
uint64_t
mask
=
0xf
;
return
static_cast
<
internal
::
Arg
::
Type
>
(
...
...
@@ -1585,7 +1386,7 @@ private:
template
<
typename
Char
>
friend
class
internal
::
ArgMap
;
public
:
public
:
// Maximum number of arguments with packed types.
enum
{
MAX_PACKED_ARGS
=
16
};
...
...
@@ -1597,13 +1398,11 @@ public:
:
types_
(
types
),
args_
(
args
)
{}
/** Returns the argument at specified index. */
internal
::
Arg
operator
[](
unsigned
index
)
const
{
internal
::
Arg
operator
[](
unsigned
index
)
const
{
using
internal
::
Arg
;
Arg
arg
;
bool
use_values
=
type
(
MAX_PACKED_ARGS
-
1
)
==
Arg
::
NONE
;
if
(
index
<
MAX_PACKED_ARGS
)
{
if
(
index
<
MAX_PACKED_ARGS
)
{
Arg
::
Type
arg_type
=
type
(
index
);
internal
::
Value
&
val
=
arg
;
if
(
arg_type
!=
Arg
::
NONE
)
...
...
@@ -1611,15 +1410,13 @@ public:
arg
.
type
=
arg_type
;
return
arg
;
}
if
(
use_values
)
{
if
(
use_values
)
{
// The index is greater than the number of arguments that can be stored
// in values, so return a "none" argument.
arg
.
type
=
Arg
::
NONE
;
return
arg
;
}
for
(
unsigned
i
=
MAX_PACKED_ARGS
;
i
<=
index
;
++
i
)
{
for
(
unsigned
i
=
MAX_PACKED_ARGS
;
i
<=
index
;
++
i
)
{
if
(
args_
[
i
].
type
==
Arg
::
NONE
)
return
args_
[
i
];
}
...
...
@@ -1654,109 +1451,92 @@ public:
\endrst
*/
template
<
typename
Impl
,
typename
Result
>
class
ArgVisitor
{
private
:
class
ArgVisitor
{
private
:
typedef
internal
::
Arg
Arg
;
public
:
public
:
void
report_unhandled_arg
()
{}
Result
visit_unhandled_arg
()
{
Result
visit_unhandled_arg
()
{
FMT_DISPATCH
(
report_unhandled_arg
());
return
Result
();
}
/** Visits an ``int`` argument. **/
Result
visit_int
(
int
value
)
{
Result
visit_int
(
int
value
)
{
return
FMT_DISPATCH
(
visit_any_int
(
value
));
}
/** Visits a ``long long`` argument. **/
Result
visit_long_long
(
LongLong
value
)
{
Result
visit_long_long
(
LongLong
value
)
{
return
FMT_DISPATCH
(
visit_any_int
(
value
));
}
/** Visits an ``unsigned`` argument. **/
Result
visit_uint
(
unsigned
value
)
{
Result
visit_uint
(
unsigned
value
)
{
return
FMT_DISPATCH
(
visit_any_int
(
value
));
}
/** Visits an ``unsigned long long`` argument. **/
Result
visit_ulong_long
(
ULongLong
value
)
{
Result
visit_ulong_long
(
ULongLong
value
)
{
return
FMT_DISPATCH
(
visit_any_int
(
value
));
}
/** Visits a ``bool`` argument. **/
Result
visit_bool
(
bool
value
)
{
Result
visit_bool
(
bool
value
)
{
return
FMT_DISPATCH
(
visit_any_int
(
value
));
}
/** Visits a ``char`` or ``wchar_t`` argument. **/
Result
visit_char
(
int
value
)
{
Result
visit_char
(
int
value
)
{
return
FMT_DISPATCH
(
visit_any_int
(
value
));
}
/** Visits an argument of any integral type. **/
template
<
typename
T
>
Result
visit_any_int
(
T
)
{
Result
visit_any_int
(
T
)
{
return
FMT_DISPATCH
(
visit_unhandled_arg
());
}
/** Visits a ``double`` argument. **/
Result
visit_double
(
double
value
)
{
Result
visit_double
(
double
value
)
{
return
FMT_DISPATCH
(
visit_any_double
(
value
));
}
/** Visits a ``long double`` argument. **/
Result
visit_long_double
(
long
double
value
)
{
Result
visit_long_double
(
long
double
value
)
{
return
FMT_DISPATCH
(
visit_any_double
(
value
));
}
/** Visits a ``double`` or ``long double`` argument. **/
template
<
typename
T
>
Result
visit_any_double
(
T
)
{
Result
visit_any_double
(
T
)
{
return
FMT_DISPATCH
(
visit_unhandled_arg
());
}
/** Visits a null-terminated C string (``const char *``) argument. **/
Result
visit_cstring
(
const
char
*
)
{
Result
visit_cstring
(
const
char
*
)
{
return
FMT_DISPATCH
(
visit_unhandled_arg
());
}
/** Visits a string argument. **/
Result
visit_string
(
Arg
::
StringValue
<
char
>
)
{
Result
visit_string
(
Arg
::
StringValue
<
char
>
)
{
return
FMT_DISPATCH
(
visit_unhandled_arg
());
}
/** Visits a wide string argument. **/
Result
visit_wstring
(
Arg
::
StringValue
<
wchar_t
>
)
{
Result
visit_wstring
(
Arg
::
StringValue
<
wchar_t
>
)
{
return
FMT_DISPATCH
(
visit_unhandled_arg
());
}
/** Visits a pointer argument. **/
Result
visit_pointer
(
const
void
*
)
{
Result
visit_pointer
(
const
void
*
)
{
return
FMT_DISPATCH
(
visit_unhandled_arg
());
}
/** Visits an argument of a custom (user-defined) type. **/
Result
visit_custom
(
Arg
::
CustomValue
)
{
Result
visit_custom
(
Arg
::
CustomValue
)
{
return
FMT_DISPATCH
(
visit_unhandled_arg
());
}
...
...
@@ -1768,10 +1548,8 @@ public:
called.
\endrst
*/
Result
visit
(
const
Arg
&
arg
)
{
switch
(
arg
.
type
)
{
Result
visit
(
const
Arg
&
arg
)
{
switch
(
arg
.
type
)
{
case
Arg
:
:
NONE
:
case
Arg
:
:
NAMED_ARG
:
FMT_ASSERT
(
false
,
"invalid argument type"
);
...
...
@@ -1807,14 +1585,12 @@ public:
}
};
enum
Alignment
{
enum
Alignment
{
ALIGN_DEFAULT
,
ALIGN_LEFT
,
ALIGN_RIGHT
,
ALIGN_CENTER
,
ALIGN_NUMERIC
};
// Flags.
enum
{
enum
{
SIGN_FLAG
=
1
,
PLUS_FLAG
=
2
,
MINUS_FLAG
=
4
,
HASH_FLAG
=
8
,
CHAR_FLAG
=
0x10
// Argument has char type - used in error reporting.
};
...
...
@@ -1824,37 +1600,17 @@ 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
' '
;
}
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
' '
;
}
};
// A width specifier.
struct
WidthSpec
{
struct
WidthSpec
{
unsigned
width_
;
// Fill is always wchar_t and cast to char if necessary to avoid having
// two specialization of WidthSpec and its subclasses.
...
...
@@ -1862,54 +1618,33 @@ 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.
struct
AlignSpec
:
WidthSpec
{
struct
AlignSpec
:
WidthSpec
{
Alignment
align_
;
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.
template
<
char
TYPE
>
struct
AlignTypeSpec
:
AlignSpec
{
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.
struct
FormatSpec
:
AlignSpec
{
struct
FormatSpec
:
AlignSpec
{
unsigned
flags_
;
int
precision_
;
char
type_
;
...
...
@@ -1918,56 +1653,38 @@ 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
:
class
IntFormatSpec
:
public
SpecT
{
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
:
class
StrFormatSpec
:
public
AlignSpec
{
private
:
const
Char
*
str_
;
public
:
public
:
template
<
typename
FillChar
>
StrFormatSpec
(
const
Char
*
str
,
unsigned
width
,
FillChar
fill
)
:
AlignSpec
(
width
,
fill
),
str_
(
str
)
{
:
AlignSpec
(
width
,
fill
),
str_
(
str
)
{
internal
::
CharTraits
<
Char
>::
convert
(
FillChar
());
}
const
Char
*
str
()
const
{
return
str_
;
}
const
Char
*
str
()
const
{
return
str_
;
}
};
/**
...
...
@@ -2080,39 +1797,33 @@ FMT_DEFINE_INT_FORMATTERS(ULongLong)
*/
template
<
typename
Char
>
inline
StrFormatSpec
<
Char
>
pad
(
const
Char
*
str
,
unsigned
width
,
Char
fill
=
' '
)
{
const
Char
*
str
,
unsigned
width
,
Char
fill
=
' '
)
{
return
StrFormatSpec
<
Char
>
(
str
,
width
,
fill
);
}
inline
StrFormatSpec
<
wchar_t
>
pad
(
const
wchar_t
*
str
,
unsigned
width
,
char
fill
=
' '
)
{
const
wchar_t
*
str
,
unsigned
width
,
char
fill
=
' '
)
{
return
StrFormatSpec
<
wchar_t
>
(
str
,
width
,
fill
);
}
namespace
internal
{
namespace
internal
{
template
<
typename
Char
>
class
ArgMap
{
private
:
class
ArgMap
{
private
:
typedef
std
::
vector
<
std
::
pair
<
fmt
::
BasicStringRef
<
Char
>
,
internal
::
Arg
>
>
MapType
;
typedef
typename
MapType
::
value_type
Pair
;
MapType
map_
;
public
:
public
:
FMT_API
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
{
// The list is unsorted, so just return the first matching name.
for
(
typename
MapType
::
const_iterator
it
=
map_
.
begin
(),
end
=
map_
.
end
();
it
!=
end
;
++
it
)
{
it
!=
end
;
++
it
)
{
if
(
it
->
first
==
name
)
return
&
it
->
second
;
}
...
...
@@ -2121,71 +1832,52 @@ public:
};
template
<
typename
Impl
,
typename
Char
>
class
ArgFormatterBase
:
public
ArgVisitor
<
Impl
,
void
>
{
private
:
class
ArgFormatterBase
:
public
ArgVisitor
<
Impl
,
void
>
{
private
:
BasicWriter
<
Char
>
&
writer_
;
FormatSpec
&
spec_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
ArgFormatterBase
);
void
write_pointer
(
const
void
*
p
)
{
void
write_pointer
(
const
void
*
p
)
{
spec_
.
flags_
=
HASH_FLAG
;
spec_
.
type_
=
'x'
;
writer_
.
write_int
(
reinterpret_cast
<
uintptr_t
>
(
p
),
spec_
);
}
protected
:
BasicWriter
<
Char
>
&
writer
()
{
return
writer_
;
}
FormatSpec
&
spec
()
{
return
spec_
;
}
protected
:
BasicWriter
<
Char
>
&
writer
()
{
return
writer_
;
}
FormatSpec
&
spec
()
{
return
spec_
;
}
void
write
(
bool
value
)
{
void
write
(
bool
value
)
{
const
char
*
str_value
=
value
?
"true"
:
"false"
;
Arg
::
StringValue
<
char
>
str
=
{
str_value
,
std
::
strlen
(
str_value
)
};
writer_
.
write_str
(
str
,
spec_
);
}
void
write
(
const
char
*
value
)
{
void
write
(
const
char
*
value
)
{
Arg
::
StringValue
<
char
>
str
=
{
value
,
value
!=
0
?
std
::
strlen
(
value
)
:
0
};
writer_
.
write_str
(
str
,
spec_
);
}
public
:
public
:
ArgFormatterBase
(
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
)
{
void
visit_bool
(
bool
value
)
{
if
(
spec_
.
type_
)
return
visit_any_int
(
value
);
write
(
value
);
}
void
visit_char
(
int
value
)
{
if
(
spec_
.
type_
&&
spec_
.
type_
!=
'c'
)
{
void
visit_char
(
int
value
)
{
if
(
spec_
.
type_
&&
spec_
.
type_
!=
'c'
)
{
spec_
.
flags_
|=
CHAR_FLAG
;
writer_
.
write_int
(
value
,
spec_
);
return
;
...
...
@@ -2196,83 +1888,65 @@ public:
Char
fill
=
internal
::
CharTraits
<
Char
>::
cast
(
spec_
.
fill
());
CharPtr
out
=
CharPtr
();
const
unsigned
CHAR_WIDTH
=
1
;
if
(
spec_
.
width_
>
CHAR_WIDTH
)
{
if
(
spec_
.
width_
>
CHAR_WIDTH
)
{
out
=
writer_
.
grow_buffer
(
spec_
.
width_
);
if
(
spec_
.
align_
==
ALIGN_RIGHT
)
{
if
(
spec_
.
align_
==
ALIGN_RIGHT
)
{
std
::
uninitialized_fill_n
(
out
,
spec_
.
width_
-
CHAR_WIDTH
,
fill
);
out
+=
spec_
.
width_
-
CHAR_WIDTH
;
}
else
if
(
spec_
.
align_
==
ALIGN_CENTER
)
{
}
else
if
(
spec_
.
align_
==
ALIGN_CENTER
)
{
out
=
writer_
.
fill_padding
(
out
,
spec_
.
width_
,
internal
::
const_check
(
CHAR_WIDTH
),
fill
);
}
else
{
}
else
{
std
::
uninitialized_fill_n
(
out
+
CHAR_WIDTH
,
spec_
.
width_
-
CHAR_WIDTH
,
fill
);
}
}
else
{
}
else
{
out
=
writer_
.
grow_buffer
(
CHAR_WIDTH
);
}
*
out
=
internal
::
CharTraits
<
Char
>::
cast
(
value
);
}
void
visit_cstring
(
const
char
*
value
)
{
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_
);
}
using
ArgVisitor
<
Impl
,
void
>::
visit_wstring
;
void
visit_wstring
(
Arg
::
StringValue
<
Char
>
value
)
{
void
visit_wstring
(
Arg
::
StringValue
<
Char
>
value
)
{
writer_
.
write_str
(
value
,
spec_
);
}
void
visit_pointer
(
const
void
*
value
)
{
void
visit_pointer
(
const
void
*
value
)
{
if
(
spec_
.
type_
&&
spec_
.
type_
!=
'p'
)
report_unknown_type
(
spec_
.
type_
,
"pointer"
);
write_pointer
(
value
);
}
};
class
FormatterBase
{
private
:
class
FormatterBase
{
private
:
ArgList
args_
;
int
next_arg_index_
;
// Returns the argument with specified index.
FMT_API
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
)
{
explicit
FormatterBase
(
const
ArgList
&
args
)
{
args_
=
args
;
next_arg_index_
=
0
;
}
// Returns the next argument.
Arg
next_arg
(
const
char
*&
error
)
{
Arg
next_arg
(
const
char
*&
error
)
{
if
(
next_arg_index_
>=
0
)
return
do_get_arg
(
internal
::
to_unsigned
(
next_arg_index_
++
),
error
);
error
=
"cannot switch from manual to automatic argument indexing"
;
...
...
@@ -2281,15 +1955,12 @@ protected:
// Checks if manual indexing is used and returns the argument with
// specified index.
Arg
get_arg
(
unsigned
arg_index
,
const
char
*&
error
)
{
Arg
get_arg
(
unsigned
arg_index
,
const
char
*&
error
)
{
return
check_no_auto_index
(
error
)
?
do_get_arg
(
arg_index
,
error
)
:
Arg
();
}
bool
check_no_auto_index
(
const
char
*&
error
)
{
if
(
next_arg_index_
>
0
)
{
bool
check_no_auto_index
(
const
char
*&
error
)
{
if
(
next_arg_index_
>
0
)
{
error
=
"cannot switch from automatic to manual argument indexing"
;
return
false
;
}
...
...
@@ -2298,8 +1969,7 @@ protected:
}
template
<
typename
Char
>
void
write
(
BasicWriter
<
Char
>
&
w
,
const
Char
*
start
,
const
Char
*
end
)
{
void
write
(
BasicWriter
<
Char
>
&
w
,
const
Char
*
start
,
const
Char
*
end
)
{
if
(
start
!=
end
)
w
<<
BasicStringRef
<
Char
>
(
start
,
internal
::
to_unsigned
(
end
-
start
));
}
...
...
@@ -2324,13 +1994,12 @@ protected:
\endrst
*/
template
<
typename
Impl
,
typename
Char
>
class
BasicArgFormatter
:
public
internal
::
ArgFormatterBase
<
Impl
,
Char
>
{
private
:
class
BasicArgFormatter
:
public
internal
::
ArgFormatterBase
<
Impl
,
Char
>
{
private
:
BasicFormatter
<
Char
,
Impl
>
&
formatter_
;
const
Char
*
format_
;
public
:
public
:
/**
\rst
Constructs an argument formatter object.
...
...
@@ -2345,17 +2014,15 @@ public:
formatter_
(
formatter
),
format_
(
fmt
)
{}
/** Formats an argument of a custom (user-defined) type. */
void
visit_custom
(
internal
::
Arg
::
CustomValue
c
)
{
void
visit_custom
(
internal
::
Arg
::
CustomValue
c
)
{
c
.
format
(
&
formatter_
,
c
.
value
,
&
format_
);
}
};
/** The default argument formatter. */
template
<
typename
Char
>
class
ArgFormatter
:
public
BasicArgFormatter
<
ArgFormatter
<
Char
>
,
Char
>
{
public
:
class
ArgFormatter
:
public
BasicArgFormatter
<
ArgFormatter
<
Char
>
,
Char
>
{
public
:
/** Constructs an argument formatter object. */
ArgFormatter
(
BasicFormatter
<
Char
>
&
formatter
,
FormatSpec
&
spec
,
const
Char
*
fmt
)
...
...
@@ -2364,13 +2031,12 @@ public:
/** This template formats data and writes the output to a writer. */
template
<
typename
CharType
,
typename
ArgFormatter
>
class
BasicFormatter
:
private
internal
::
FormatterBase
{
public
:
class
BasicFormatter
:
private
internal
::
FormatterBase
{
public
:
/** The character type for the output. */
typedef
CharType
Char
;
private
:
private
:
BasicWriter
<
Char
>
&
writer_
;
internal
::
ArgMap
<
Char
>
map_
;
...
...
@@ -2388,7 +2054,7 @@ private:
// Parses argument name and returns corresponding argument.
internal
::
Arg
parse_arg_name
(
const
Char
*&
s
);
public
:
public
:
/**
\rst
Constructs a ``BasicFormatter`` object. References to the arguments and
...
...
@@ -2400,10 +2066,7 @@ public:
:
internal
::
FormatterBase
(
args
),
writer_
(
w
)
{}
/** Returns a reference to the writer associated with this formatter. */
BasicWriter
<
Char
>
&
writer
()
{
return
writer_
;
}
BasicWriter
<
Char
>
&
writer
()
{
return
writer_
;
}
/** Formats stored arguments and writes the output to the writer. */
void
format
(
BasicCStringRef
<
Char
>
format_str
);
...
...
@@ -2431,30 +2094,23 @@ public:
# define FMT_GEN14(f) FMT_GEN13(f), f(13)
# define FMT_GEN15(f) FMT_GEN14(f), f(14)
namespace
internal
{
inline
uint64_t
make_type
()
{
return
0
;
}
namespace
internal
{
inline
uint64_t
make_type
()
{
return
0
;
}
template
<
typename
T
>
inline
uint64_t
make_type
(
const
T
&
arg
)
{
inline
uint64_t
make_type
(
const
T
&
arg
)
{
return
MakeValue
<
BasicFormatter
<
char
>
>::
type
(
arg
);
}
template
<
unsigned
N
,
bool
/*IsPacked*/
=
(
N
<
ArgList
::
MAX_PACKED_ARGS
)
>
struct
ArgArray
;
struct
ArgArray
;
template
<
unsigned
N
>
struct
ArgArray
<
N
,
true
/*IsPacked*/
>
{
struct
ArgArray
<
N
,
true
/*IsPacked*/
>
{
typedef
Value
Type
[
N
>
0
?
N
:
1
];
template
<
typename
Formatter
,
typename
T
>
static
Value
make
(
const
T
&
value
)
{
template
<
typename
Formatter
,
typename
T
>
static
Value
make
(
const
T
&
value
)
{
#ifdef __clang__
Value
result
=
MakeValue
<
Formatter
>
(
value
);
// Workaround a bug in Apple LLVM version 4.2 (clang-425.0.28) of clang:
...
...
@@ -2464,32 +2120,26 @@ static Value make(const T &value)
#else
return
MakeValue
<
Formatter
>
(
value
);
#endif
}
};
}
};
template
<
unsigned
N
>
struct
ArgArray
<
N
,
false
/*IsPacked*/
>
{
struct
ArgArray
<
N
,
false
/*IsPacked*/
>
{
typedef
Arg
Type
[
N
+
1
];
// +1 for the list end Arg::NONE
template
<
typename
Formatter
,
typename
T
>
static
Arg
make
(
const
T
&
value
)
{
return
MakeArg
<
Formatter
>
(
value
);
}
static
Arg
make
(
const
T
&
value
)
{
return
MakeArg
<
Formatter
>
(
value
);
}
};
#if FMT_USE_VARIADIC_TEMPLATES
template
<
typename
Arg
,
typename
...
Args
>
inline
uint64_t
make_type
(
const
Arg
&
first
,
const
Args
&
...
tail
)
{
inline
uint64_t
make_type
(
const
Arg
&
first
,
const
Args
&
...
tail
)
{
return
make_type
(
first
)
|
(
make_type
(
tail
...)
<<
4
);
}
#else
struct
ArgType
{
struct
ArgType
{
uint64_t
type
;
ArgType
()
:
type
(
0
)
{}
...
...
@@ -2500,8 +2150,7 @@ struct ArgType
# define FMT_ARG_TYPE_DEFAULT(n) ArgType t##n = ArgType()
inline
uint64_t
make_type
(
FMT_GEN15
(
FMT_ARG_TYPE_DEFAULT
))
{
inline
uint64_t
make_type
(
FMT_GEN15
(
FMT_ARG_TYPE_DEFAULT
))
{
return
t0
.
type
|
(
t1
.
type
<<
4
)
|
(
t2
.
type
<<
8
)
|
(
t3
.
type
<<
12
)
|
(
t4
.
type
<<
16
)
|
(
t5
.
type
<<
20
)
|
(
t6
.
type
<<
24
)
|
(
t7
.
type
<<
28
)
|
(
t8
.
type
<<
32
)
|
(
t9
.
type
<<
36
)
|
(
t10
.
type
<<
40
)
|
(
t11
.
type
<<
44
)
|
...
...
@@ -2612,19 +2261,18 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT))
An error returned by an operating system or a language runtime,
for example a file opening error.
*/
class
SystemError
:
public
internal
::
RuntimeError
{
private
:
class
SystemError
:
public
internal
::
RuntimeError
{
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 a description
...
...
@@ -2643,18 +2291,14 @@ public:
throw fmt::SystemError(errno, "cannot open file '{}'", filename);
\endrst
*/
SystemError
(
int
error_code
,
CStringRef
message
)
{
SystemError
(
int
error_code
,
CStringRef
message
)
{
init
(
error_code
,
message
,
ArgList
());
}
FMT_VARIADIC_CTOR
(
SystemError
,
init
,
int
,
CStringRef
)
~
SystemError
()
throw
();
int
error_code
()
const
{
return
error_code_
;
}
int
error_code
()
const
{
return
error_code_
;
}
};
/**
...
...
@@ -2695,9 +2339,8 @@ FMT_API void format_system_error(fmt::Writer &out, int error_code,
\endrst
*/
template
<
typename
Char
>
class
BasicWriter
{
private
:
class
BasicWriter
{
private
:
// Output buffer.
Buffer
<
Char
>
&
buffer_
;
...
...
@@ -2707,15 +2350,9 @@ private:
#if FMT_SECURE_SCL
// Returns pointer value.
static
Char
*
get
(
CharPtr
p
)
{
return
p
.
base
();
}
static
Char
*
get
(
CharPtr
p
)
{
return
p
.
base
();
}
#else
static
Char
*
get
(
Char
*
p
)
{
return
p
;
}
static
Char
*
get
(
Char
*
p
)
{
return
p
;
}
#endif
// Fills the padding around the content and returns the pointer to the
...
...
@@ -2725,8 +2362,7 @@ private:
// Grows the buffer by n characters and returns a pointer to the newly
// allocated area.
CharPtr
grow_buffer
(
std
::
size_t
n
)
{
CharPtr
grow_buffer
(
std
::
size_t
n
)
{
std
::
size_t
size
=
buffer_
.
size
();
buffer_
.
resize
(
size
+
n
);
return
internal
::
make_ptr
(
&
buffer_
[
size
],
n
);
...
...
@@ -2734,8 +2370,7 @@ private:
// Writes an unsigned decimal integer.
template
<
typename
UInt
>
Char
*
write_unsigned_decimal
(
UInt
value
,
unsigned
prefix_size
=
0
)
{
Char
*
write_unsigned_decimal
(
UInt
value
,
unsigned
prefix_size
=
0
)
{
unsigned
num_digits
=
internal
::
count_digits
(
value
);
Char
*
ptr
=
get
(
grow_buffer
(
prefix_size
+
num_digits
));
internal
::
format_decimal
(
ptr
+
prefix_size
,
value
,
num_digits
);
...
...
@@ -2744,25 +2379,20 @@ private:
// Writes a decimal integer.
template
<
typename
Int
>
void
write_decimal
(
Int
value
)
{
void
write_decimal
(
Int
value
)
{
typedef
typename
internal
::
IntTraits
<
Int
>::
MainType
MainType
;
MainType
abs_value
=
static_cast
<
MainType
>
(
value
);
if
(
internal
::
is_negative
(
value
))
{
if
(
internal
::
is_negative
(
value
))
{
abs_value
=
0
-
abs_value
;
*
write_unsigned_decimal
(
abs_value
,
1
)
=
'-'
;
}
else
{
}
else
{
write_unsigned_decimal
(
abs_value
,
0
);
}
}
// Prepare a buffer for integer formatting.
CharPtr
prepare_int_buffer
(
unsigned
num_digits
,
const
EmptySpec
&
,
const
char
*
prefix
,
unsigned
prefix_size
)
{
const
EmptySpec
&
,
const
char
*
prefix
,
unsigned
prefix_size
)
{
unsigned
size
=
prefix_size
+
num_digits
;
CharPtr
p
=
grow_buffer
(
size
);
std
::
uninitialized_copy
(
prefix
,
prefix
+
prefix_size
,
p
);
...
...
@@ -2799,8 +2429,7 @@ private:
// Appends floating-point length specifier to the format string.
// The second argument is only used for overload resolution.
void
append_float_length
(
Char
*&
format_ptr
,
long
double
)
{
void
append_float_length
(
Char
*&
format_ptr
,
long
double
)
{
*
format_ptr
++
=
'L'
;
}
...
...
@@ -2813,13 +2442,13 @@ private:
template
<
typename
Impl
,
typename
Char_
>
friend
class
BasicPrintfArgFormatter
;
protected
:
protected
:
/**
Constructs a ``BasicWriter`` object.
*/
explicit
BasicWriter
(
Buffer
<
Char
>
&
b
)
:
buffer_
(
b
)
{}
public
:
public
:
/**
\rst
Destroys a ``BasicWriter`` object.
...
...
@@ -2830,26 +2459,19 @@ 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
character appended.
*/
const
Char
*
c_str
()
const
{
const
Char
*
c_str
()
const
{
std
::
size_t
size
=
buffer_
.
size
();
buffer_
.
reserve
(
size
+
1
);
buffer_
[
size
]
=
'\0'
;
...
...
@@ -2861,8 +2483,7 @@ public:
Returns the content of the output buffer as an `std::string`.
\endrst
*/
std
::
basic_string
<
Char
>
str
()
const
{
std
::
basic_string
<
Char
>
str
()
const
{
return
std
::
basic_string
<
Char
>
(
&
buffer_
[
0
],
buffer_
.
size
());
}
...
...
@@ -2891,32 +2512,26 @@ public:
See also :ref:`syntax`.
\endrst
*/
void
write
(
BasicCStringRef
<
Char
>
format
,
ArgList
args
)
{
void
write
(
BasicCStringRef
<
Char
>
format
,
ArgList
args
)
{
BasicFormatter
<
Char
>
(
args
,
*
this
).
format
(
format
);
}
FMT_VARIADIC_VOID
(
write
,
BasicCStringRef
<
Char
>
)
BasicWriter
&
operator
<<
(
int
value
)
{
BasicWriter
&
operator
<<
(
int
value
)
{
write_decimal
(
value
);
return
*
this
;
}
BasicWriter
&
operator
<<
(
unsigned
value
)
{
BasicWriter
&
operator
<<
(
unsigned
value
)
{
return
*
this
<<
IntFormatSpec
<
unsigned
>
(
value
);
}
BasicWriter
&
operator
<<
(
long
value
)
{
BasicWriter
&
operator
<<
(
long
value
)
{
write_decimal
(
value
);
return
*
this
;
}
BasicWriter
&
operator
<<
(
unsigned
long
value
)
{
BasicWriter
&
operator
<<
(
unsigned
long
value
)
{
return
*
this
<<
IntFormatSpec
<
unsigned
long
>
(
value
);
}
BasicWriter
&
operator
<<
(
LongLong
value
)
{
BasicWriter
&
operator
<<
(
LongLong
value
)
{
write_decimal
(
value
);
return
*
this
;
}
...
...
@@ -2926,13 +2541,11 @@ public:
Formats *value* and writes it to the stream.
\endrst
*/
BasicWriter
&
operator
<<
(
ULongLong
value
)
{
BasicWriter
&
operator
<<
(
ULongLong
value
)
{
return
*
this
<<
IntFormatSpec
<
ULongLong
>
(
value
);
}
BasicWriter
&
operator
<<
(
double
value
)
{
BasicWriter
&
operator
<<
(
double
value
)
{
write_double
(
value
,
FormatSpec
());
return
*
this
;
}
...
...
@@ -2943,8 +2556,7 @@ public:
(``'g'``) and writes it to the stream.
\endrst
*/
BasicWriter
&
operator
<<
(
long
double
value
)
{
BasicWriter
&
operator
<<
(
long
double
value
)
{
write_double
(
value
,
FormatSpec
());
return
*
this
;
}
...
...
@@ -2952,15 +2564,13 @@ public:
/**
Writes a character to the stream.
*/
BasicWriter
&
operator
<<
(
char
value
)
{
BasicWriter
&
operator
<<
(
char
value
)
{
buffer_
.
push_back
(
value
);
return
*
this
;
}
BasicWriter
&
operator
<<
(
typename
internal
::
WCharHelper
<
wchar_t
,
Char
>::
Supported
value
)
{
typename
internal
::
WCharHelper
<
wchar_t
,
Char
>::
Supported
value
)
{
buffer_
.
push_back
(
value
);
return
*
this
;
}
...
...
@@ -2970,32 +2580,28 @@ public:
Writes *value* to the stream.
\endrst
*/
BasicWriter
&
operator
<<
(
fmt
::
BasicStringRef
<
Char
>
value
)
{
BasicWriter
&
operator
<<
(
fmt
::
BasicStringRef
<
Char
>
value
)
{
const
Char
*
str
=
value
.
data
();
buffer_
.
append
(
str
,
str
+
value
.
size
());
return
*
this
;
}
BasicWriter
&
operator
<<
(
typename
internal
::
WCharHelper
<
StringRef
,
Char
>::
Supported
value
)
{
typename
internal
::
WCharHelper
<
StringRef
,
Char
>::
Supported
value
)
{
const
char
*
str
=
value
.
data
();
buffer_
.
append
(
str
,
str
+
value
.
size
());
return
*
this
;
}
template
<
typename
T
,
typename
Spec
,
typename
FillChar
>
BasicWriter
&
operator
<<
(
IntFormatSpec
<
T
,
Spec
,
FillChar
>
spec
)
{
BasicWriter
&
operator
<<
(
IntFormatSpec
<
T
,
Spec
,
FillChar
>
spec
)
{
internal
::
CharTraits
<
Char
>::
convert
(
FillChar
());
write_int
(
spec
.
value
(),
spec
);
return
*
this
;
}
template
<
typename
StrChar
>
BasicWriter
&
operator
<<
(
const
StrFormatSpec
<
StrChar
>
&
spec
)
{
BasicWriter
&
operator
<<
(
const
StrFormatSpec
<
StrChar
>
&
spec
)
{
const
StrChar
*
s
=
spec
.
str
();
write_str
(
s
,
std
::
char_traits
<
Char
>::
length
(
s
),
spec
);
return
*
this
;
...
...
@@ -3009,29 +2615,20 @@ public:
template
<
typename
Char
>
template
<
typename
StrChar
>
typename
BasicWriter
<
Char
>::
CharPtr
BasicWriter
<
Char
>::
write_str
(
const
StrChar
*
s
,
std
::
size_t
size
,
const
AlignSpec
&
spec
)
{
const
StrChar
*
s
,
std
::
size_t
size
,
const
AlignSpec
&
spec
)
{
CharPtr
out
=
CharPtr
();
if
(
spec
.
width
()
>
size
)
{
if
(
spec
.
width
()
>
size
)
{
out
=
grow_buffer
(
spec
.
width
());
Char
fill
=
internal
::
CharTraits
<
Char
>::
cast
(
spec
.
fill
());
if
(
spec
.
align
()
==
ALIGN_RIGHT
)
{
if
(
spec
.
align
()
==
ALIGN_RIGHT
)
{
std
::
uninitialized_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
::
uninitialized_fill_n
(
out
+
size
,
spec
.
width
()
-
size
,
fill
);
}
}
else
{
}
else
{
out
=
grow_buffer
(
size
);
}
std
::
uninitialized_copy
(
s
,
s
+
size
,
out
);
...
...
@@ -3041,18 +2638,15 @@ typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
template
<
typename
Char
>
template
<
typename
StrChar
>
void
BasicWriter
<
Char
>::
write_str
(
const
internal
::
Arg
::
StringValue
<
StrChar
>
&
s
,
const
FormatSpec
&
spec
)
{
const
internal
::
Arg
::
StringValue
<
StrChar
>
&
s
,
const
FormatSpec
&
spec
)
{
// Check if StrChar is convertible to Char.
internal
::
CharTraits
<
Char
>::
convert
(
StrChar
());
if
(
spec
.
type_
&&
spec
.
type_
!=
's'
)
internal
::
report_unknown_type
(
spec
.
type_
,
"string"
);
const
StrChar
*
str_value
=
s
.
value
;
std
::
size_t
str_size
=
s
.
size
;
if
(
str_size
==
0
)
{
if
(
!
str_value
)
{
if
(
str_size
==
0
)
{
if
(
!
str_value
)
{
FMT_THROW
(
FormatError
(
"string pointer is null"
));
}
}
...
...
@@ -3064,10 +2658,9 @@ void 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
content_size
,
wchar_t
fill
)
{
std
::
size_t
padding
=
total_size
-
content_size
;
std
::
size_t
left_padding
=
padding
/
2
;
Char
fill_char
=
internal
::
CharTraits
<
Char
>::
cast
(
fill
);
...
...
@@ -3082,15 +2675,13 @@ 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
)
{
const
char
*
prefix
,
unsigned
prefix_size
)
{
unsigned
width
=
spec
.
width
();
Alignment
align
=
spec
.
align
();
Char
fill
=
internal
::
CharTraits
<
Char
>::
cast
(
spec
.
fill
());
if
(
spec
.
precision
()
>
static_cast
<
int
>
(
num_digits
))
{
if
(
spec
.
precision
()
>
static_cast
<
int
>
(
num_digits
))
{
// Octal prefix '0' is counted as a digit, so ignore it if precision
// is specified.
if
(
prefix_size
>
0
&&
prefix
[
prefix_size
-
1
]
==
'0'
)
...
...
@@ -3102,53 +2693,41 @@ BasicWriter<Char>::prepare_int_buffer(
return
prepare_int_buffer
(
num_digits
,
subspec
,
prefix
,
prefix_size
);
buffer_
.
reserve
(
width
);
unsigned
fill_size
=
width
-
number_size
;
if
(
align
!=
ALIGN_LEFT
)
{
if
(
align
!=
ALIGN_LEFT
)
{
CharPtr
p
=
grow_buffer
(
fill_size
);
std
::
uninitialized_fill
(
p
,
p
+
fill_size
,
fill
);
}
CharPtr
result
=
prepare_int_buffer
(
num_digits
,
subspec
,
prefix
,
prefix_size
);
if
(
align
==
ALIGN_LEFT
)
{
if
(
align
==
ALIGN_LEFT
)
{
CharPtr
p
=
grow_buffer
(
fill_size
);
std
::
uninitialized_fill
(
p
,
p
+
fill_size
,
fill
);
}
return
result
;
}
unsigned
size
=
prefix_size
+
num_digits
;
if
(
width
<=
size
)
{
if
(
width
<=
size
)
{
CharPtr
p
=
grow_buffer
(
size
);
std
::
uninitialized_copy
(
prefix
,
prefix
+
prefix_size
,
p
);
return
p
+
size
-
1
;
}
CharPtr
p
=
grow_buffer
(
width
);
CharPtr
end
=
p
+
width
;
if
(
align
==
ALIGN_LEFT
)
{
if
(
align
==
ALIGN_LEFT
)
{
std
::
uninitialized_copy
(
prefix
,
prefix
+
prefix_size
,
p
);
p
+=
size
;
std
::
uninitialized_fill
(
p
,
end
,
fill
);
}
else
if
(
align
==
ALIGN_CENTER
)
{
}
else
if
(
align
==
ALIGN_CENTER
)
{
p
=
fill_padding
(
p
,
width
,
size
,
fill
);
std
::
uninitialized_copy
(
prefix
,
prefix
+
prefix_size
,
p
);
p
+=
size
;
}
else
{
if
(
align
==
ALIGN_NUMERIC
)
{
if
(
prefix_size
!=
0
)
{
}
else
{
if
(
align
==
ALIGN_NUMERIC
)
{
if
(
prefix_size
!=
0
)
{
p
=
std
::
uninitialized_copy
(
prefix
,
prefix
+
prefix_size
,
p
);
size
-=
prefix_size
;
}
}
else
{
}
else
{
std
::
uninitialized_copy
(
prefix
,
prefix
+
prefix_size
,
end
-
size
);
}
std
::
uninitialized_fill
(
p
,
end
-
size
,
fill
);
...
...
@@ -3159,108 +2738,84 @@ BasicWriter<Char>::prepare_int_buffer(
template
<
typename
Char
>
template
<
typename
T
,
typename
Spec
>
void
BasicWriter
<
Char
>::
write_int
(
T
value
,
Spec
spec
)
{
void
BasicWriter
<
Char
>::
write_int
(
T
value
,
Spec
spec
)
{
unsigned
prefix_size
=
0
;
typedef
typename
internal
::
IntTraits
<
T
>::
MainType
UnsignedType
;
UnsignedType
abs_value
=
static_cast
<
UnsignedType
>
(
value
);
char
prefix
[
4
]
=
""
;
if
(
internal
::
is_negative
(
value
))
{
if
(
internal
::
is_negative
(
value
))
{
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'
:
{
switch
(
spec
.
type
())
{
case
0
:
case
'd'
:
{
unsigned
num_digits
=
internal
::
count_digits
(
abs_value
);
CharPtr
p
=
prepare_int_buffer
(
num_digits
,
spec
,
prefix
,
prefix_size
)
+
1
;
internal
::
format_decimal
(
get
(
p
),
abs_value
,
0
);
break
;
}
case
'x'
:
case
'X'
:
{
case
'x'
:
case
'X'
:
{
UnsignedType
n
=
abs_value
;
if
(
spec
.
flag
(
HASH_FLAG
))
{
if
(
spec
.
flag
(
HASH_FLAG
))
{
prefix
[
prefix_size
++
]
=
'0'
;
prefix
[
prefix_size
++
]
=
spec
.
type
();
}
unsigned
num_digits
=
0
;
do
{
do
{
++
num_digits
;
}
while
((
n
>>=
4
)
!=
0
);
}
while
((
n
>>=
4
)
!=
0
);
Char
*
p
=
get
(
prepare_int_buffer
(
num_digits
,
spec
,
prefix
,
prefix_size
));
n
=
abs_value
;
const
char
*
digits
=
spec
.
type
()
==
'x'
?
"0123456789abcdef"
:
"0123456789ABCDEF"
;
do
{
do
{
*
p
--
=
digits
[
n
&
0xf
];
}
while
((
n
>>=
4
)
!=
0
);
}
while
((
n
>>=
4
)
!=
0
);
break
;
}
case
'b'
:
case
'B'
:
{
case
'b'
:
case
'B'
:
{
UnsignedType
n
=
abs_value
;
if
(
spec
.
flag
(
HASH_FLAG
))
{
if
(
spec
.
flag
(
HASH_FLAG
))
{
prefix
[
prefix_size
++
]
=
'0'
;
prefix
[
prefix_size
++
]
=
spec
.
type
();
}
unsigned
num_digits
=
0
;
do
{
do
{
++
num_digits
;
}
while
((
n
>>=
1
)
!=
0
);
}
while
((
n
>>=
1
)
!=
0
);
Char
*
p
=
get
(
prepare_int_buffer
(
num_digits
,
spec
,
prefix
,
prefix_size
));
n
=
abs_value
;
do
{
do
{
*
p
--
=
static_cast
<
Char
>
(
'0'
+
(
n
&
1
));
}
while
((
n
>>=
1
)
!=
0
);
}
while
((
n
>>=
1
)
!=
0
);
break
;
}
case
'o'
:
{
case
'o'
:
{
UnsignedType
n
=
abs_value
;
if
(
spec
.
flag
(
HASH_FLAG
))
prefix
[
prefix_size
++
]
=
'0'
;
unsigned
num_digits
=
0
;
do
{
do
{
++
num_digits
;
}
while
((
n
>>=
3
)
!=
0
);
}
while
((
n
>>=
3
)
!=
0
);
Char
*
p
=
get
(
prepare_int_buffer
(
num_digits
,
spec
,
prefix
,
prefix_size
));
n
=
abs_value
;
do
{
do
{
*
p
--
=
static_cast
<
Char
>
(
'0'
+
(
n
&
7
));
}
while
((
n
>>=
3
)
!=
0
);
}
while
((
n
>>=
3
)
!=
0
);
break
;
}
case
'n'
:
{
case
'n'
:
{
unsigned
num_digits
=
internal
::
count_digits
(
abs_value
);
fmt
::
StringRef
sep
=
internal
::
thousands_sep
(
std
::
localeconv
());
fmt
::
StringRef
sep
=
""
;
#ifndef ANDROID
sep
=
internal
::
thousands_sep
(
std
::
localeconv
());
#endif
unsigned
size
=
static_cast
<
unsigned
>
(
num_digits
+
sep
.
size
()
*
((
num_digits
-
1
)
/
3
));
CharPtr
p
=
prepare_int_buffer
(
size
,
spec
,
prefix
,
prefix_size
)
+
1
;
...
...
@@ -3276,20 +2831,15 @@ void BasicWriter<Char>::write_int(T value, Spec spec)
template
<
typename
Char
>
template
<
typename
T
>
void
BasicWriter
<
Char
>::
write_double
(
T
value
,
const
FormatSpec
&
spec
)
{
void
BasicWriter
<
Char
>::
write_double
(
T
value
,
const
FormatSpec
&
spec
)
{
// Check type.
char
type
=
spec
.
type
();
bool
upper
=
false
;
switch
(
type
)
{
switch
(
type
)
{
case
0
:
type
=
'g'
;
break
;
case
'e'
:
case
'f'
:
case
'g'
:
case
'a'
:
case
'e'
:
case
'f'
:
case
'g'
:
case
'a'
:
break
;
case
'F'
:
#if FMT_MSC_VER
...
...
@@ -3297,9 +2847,7 @@ void BasicWriter<Char>::write_double(T value, const FormatSpec &spec)
type
=
'f'
;
#endif
// Fall through.
case
'E'
:
case
'G'
:
case
'A'
:
case
'E'
:
case
'G'
:
case
'A'
:
upper
=
true
;
break
;
default
:
...
...
@@ -3310,24 +2858,19 @@ void BasicWriter<Char>::write_double(T value, const FormatSpec &spec)
char
sign
=
0
;
// Use isnegative instead of value < 0 because the latter is always
// false for NaN.
if
(
internal
::
FPUtil
::
isnegative
(
static_cast
<
double
>
(
value
)))
{
if
(
internal
::
FPUtil
::
isnegative
(
static_cast
<
double
>
(
value
)))
{
sign
=
'-'
;
value
=
-
value
;
}
else
if
(
spec
.
flag
(
SIGN_FLAG
))
{
}
else
if
(
spec
.
flag
(
SIGN_FLAG
))
{
sign
=
spec
.
flag
(
PLUS_FLAG
)
?
'+'
:
' '
;
}
if
(
internal
::
FPUtil
::
isnotanumber
(
value
))
{
if
(
internal
::
FPUtil
::
isnotanumber
(
value
))
{
// Format NaN ourselves because sprintf's output is not consistent
// across platforms.
std
::
size_t
nan_size
=
4
;
const
char
*
nan
=
upper
?
" NAN"
:
" nan"
;
if
(
!
sign
)
{
if
(
!
sign
)
{
--
nan_size
;
++
nan
;
}
...
...
@@ -3337,14 +2880,12 @@ void BasicWriter<Char>::write_double(T value, const FormatSpec &spec)
return
;
}
if
(
internal
::
FPUtil
::
isinfinity
(
value
))
{
if
(
internal
::
FPUtil
::
isinfinity
(
value
))
{
// Format infinity ourselves because sprintf's output is not consistent
// across platforms.
std
::
size_t
inf_size
=
4
;
const
char
*
inf
=
upper
?
" INF"
:
" inf"
;
if
(
!
sign
)
{
if
(
!
sign
)
{
--
inf_size
;
++
inf
;
}
...
...
@@ -3356,8 +2897,7 @@ void BasicWriter<Char>::write_double(T value, const FormatSpec &spec)
std
::
size_t
offset
=
buffer_
.
size
();
unsigned
width
=
spec
.
width
();
if
(
sign
)
{
if
(
sign
)
{
buffer_
.
reserve
(
buffer_
.
size
()
+
(
width
>
1u
?
width
:
1u
));
if
(
width
>
0
)
--
width
;
...
...
@@ -3372,19 +2912,15 @@ void BasicWriter<Char>::write_double(T value, const FormatSpec &spec)
unsigned
width_for_sprintf
=
width
;
if
(
spec
.
flag
(
HASH_FLAG
))
*
format_ptr
++
=
'#'
;
if
(
spec
.
align
()
==
ALIGN_CENTER
)
{
if
(
spec
.
align
()
==
ALIGN_CENTER
)
{
width_for_sprintf
=
0
;
}
else
{
}
else
{
if
(
spec
.
align
()
==
ALIGN_LEFT
)
*
format_ptr
++
=
'-'
;
if
(
width
!=
0
)
*
format_ptr
++
=
'*'
;
}
if
(
spec
.
precision
()
>=
0
)
{
if
(
spec
.
precision
()
>=
0
)
{
*
format_ptr
++
=
'.'
;
*
format_ptr
++
=
'*'
;
}
...
...
@@ -3397,15 +2933,13 @@ void BasicWriter<Char>::write_double(T value, const FormatSpec &spec)
Char
fill
=
internal
::
CharTraits
<
Char
>::
cast
(
spec
.
fill
());
unsigned
n
=
0
;
Char
*
start
=
0
;
for
(;;)
{
for
(;;)
{
std
::
size_t
buffer_size
=
buffer_
.
capacity
()
-
offset
;
#if FMT_MSC_VER
// MSVC's vsnprintf_s doesn't work with zero size, so reserve
// space for at least one extra character to make the size non-zero.
// Note that the buffer's capacity will increase by more than 1.
if
(
buffer_size
==
0
)
{
if
(
buffer_size
==
0
)
{
buffer_
.
reserve
(
offset
+
1
);
buffer_size
=
buffer_
.
capacity
()
-
offset
;
}
...
...
@@ -3413,44 +2947,35 @@ void BasicWriter<Char>::write_double(T value, const FormatSpec &spec)
start
=
&
buffer_
[
offset
];
int
result
=
internal
::
CharTraits
<
Char
>::
format_float
(
start
,
buffer_size
,
format
,
width_for_sprintf
,
spec
.
precision
(),
value
);
if
(
result
>=
0
)
{
if
(
result
>=
0
)
{
n
=
internal
::
to_unsigned
(
result
);
if
(
offset
+
n
<
buffer_
.
capacity
())
break
;
// The buffer is large enough - continue with formatting.
buffer_
.
reserve
(
offset
+
n
+
1
);
}
else
{
}
else
{
// If result is negative we ask to increase the capacity by at least 1,
// but as std::vector, the buffer grows exponentially.
buffer_
.
reserve
(
buffer_
.
capacity
()
+
1
);
}
}
if
(
sign
)
{
if
(
sign
)
{
if
((
spec
.
align
()
!=
ALIGN_RIGHT
&&
spec
.
align
()
!=
ALIGN_DEFAULT
)
||
*
start
!=
' '
)
{
*
start
!=
' '
)
{
*
(
start
-
1
)
=
sign
;
sign
=
0
;
}
else
{
}
else
{
*
(
start
-
1
)
=
fill
;
}
++
n
;
}
if
(
spec
.
align
()
==
ALIGN_CENTER
&&
spec
.
width
()
>
n
)
{
if
(
spec
.
align
()
==
ALIGN_CENTER
&&
spec
.
width
()
>
n
)
{
width
=
spec
.
width
();
CharPtr
p
=
grow_buffer
(
width
);
std
::
memmove
(
get
(
p
)
+
(
width
-
n
)
/
2
,
get
(
p
),
n
*
sizeof
(
Char
));
fill_padding
(
p
,
spec
.
width
(),
n
,
fill
);
return
;
}
if
(
spec
.
fill
()
!=
' '
||
sign
)
{
if
(
spec
.
fill
()
!=
' '
||
sign
)
{
while
(
*
start
==
' '
)
*
start
++
=
fill
;
if
(
sign
)
...
...
@@ -3494,12 +3019,11 @@ void BasicWriter<Char>::write_double(T value, const FormatSpec &spec)
\endrst
*/
template
<
typename
Char
,
typename
Allocator
=
std
::
allocator
<
Char
>
>
class
BasicMemoryWriter
:
public
BasicWriter
<
Char
>
{
private
:
class
BasicMemoryWriter
:
public
BasicWriter
<
Char
>
{
private
:
internal
::
MemoryBuffer
<
Char
,
internal
::
INLINE_BUFFER_SIZE
,
Allocator
>
buffer_
;
public
:
public
:
explicit
BasicMemoryWriter
(
const
Allocator
&
alloc
=
Allocator
())
:
BasicWriter
<
Char
>
(
buffer_
),
buffer_
(
alloc
)
{}
...
...
@@ -3511,8 +3035,7 @@ public:
\endrst
*/
BasicMemoryWriter
(
BasicMemoryWriter
&&
other
)
:
BasicWriter
<
Char
>
(
buffer_
),
buffer_
(
std
::
move
(
other
.
buffer_
))
{
:
BasicWriter
<
Char
>
(
buffer_
),
buffer_
(
std
::
move
(
other
.
buffer_
))
{
}
/**
...
...
@@ -3520,8 +3043,7 @@ public:
Moves the content of the other ``BasicMemoryWriter`` object to this one.
\endrst
*/
BasicMemoryWriter
&
operator
=
(
BasicMemoryWriter
&&
other
)
{
BasicMemoryWriter
&
operator
=
(
BasicMemoryWriter
&&
other
)
{
buffer_
=
std
::
move
(
other
.
buffer_
);
return
*
this
;
}
...
...
@@ -3552,12 +3074,11 @@ typedef BasicMemoryWriter<wchar_t> WMemoryWriter;
\endrst
*/
template
<
typename
Char
>
class
BasicArrayWriter
:
public
BasicWriter
<
Char
>
{
private
:
class
BasicArrayWriter
:
public
BasicWriter
<
Char
>
{
private
:
internal
::
FixedBuffer
<
Char
>
buffer_
;
public
:
public
:
/**
\rst
Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the
...
...
@@ -3589,12 +3110,11 @@ FMT_API void report_system_error(int error_code,
#if FMT_USE_WINDOWS_H
/** A Windows error. */
class
WindowsError
:
public
SystemError
{
private
:
class
WindowsError
:
public
SystemError
{
private
:
FMT_API
void
init
(
int
error_code
,
CStringRef
format_str
,
ArgList
args
);
public
:
public
:
/**
\rst
Constructs a :class:`fmt::WindowsError` object with the description
...
...
@@ -3623,8 +3143,7 @@ public:
}
\endrst
*/
WindowsError
(
int
error_code
,
CStringRef
message
)
{
WindowsError
(
int
error_code
,
CStringRef
message
)
{
init
(
error_code
,
message
,
ArgList
());
}
FMT_VARIADIC_CTOR
(
WindowsError
,
init
,
int
,
CStringRef
)
...
...
@@ -3656,15 +3175,13 @@ FMT_API void print_colored(Color c, CStringRef format, ArgList args);
std::string message = format("The answer is {}", 42);
\endrst
*/
inline
std
::
string
format
(
CStringRef
format_str
,
ArgList
args
)
{
inline
std
::
string
format
(
CStringRef
format_str
,
ArgList
args
)
{
MemoryWriter
w
;
w
.
write
(
format_str
,
args
);
return
w
.
str
();
}
inline
std
::
wstring
format
(
WCStringRef
format_str
,
ArgList
args
)
{
inline
std
::
wstring
format
(
WCStringRef
format_str
,
ArgList
args
)
{
WMemoryWriter
w
;
w
.
write
(
format_str
,
args
);
return
w
.
str
();
...
...
@@ -3695,9 +3212,8 @@ FMT_API void print(CStringRef format_str, ArgList args);
/**
Fast integer formatter.
*/
class
FormatInt
{
private
:
class
FormatInt
{
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
};
...
...
@@ -3705,11 +3221,9 @@ private:
char
*
str_
;
// Formats value in reverse and returns the number of digits.
char
*
format_decimal
(
ULongLong
value
)
{
char
*
format_decimal
(
ULongLong
value
)
{
char
*
buffer_end
=
buffer_
+
BUFFER_SIZE
-
1
;
while
(
value
>=
100
)
{
while
(
value
>=
100
)
{
// Integer division is slow so do it for a group of two digits instead
// of for every digit. The idea comes from the talk by Alexandrescu
// "Three Optimization Tips for C++". See speed-test for a comparison.
...
...
@@ -3718,8 +3232,7 @@ private:
*--
buffer_end
=
internal
::
Data
::
DIGITS
[
index
+
1
];
*--
buffer_end
=
internal
::
Data
::
DIGITS
[
index
];
}
if
(
value
<
10
)
{
if
(
value
<
10
)
{
*--
buffer_end
=
static_cast
<
char
>
(
'0'
+
value
);
return
buffer_end
;
}
...
...
@@ -3729,8 +3242,7 @@ private:
return
buffer_end
;
}
void
FormatSigned
(
LongLong
value
)
{
void
FormatSigned
(
LongLong
value
)
{
ULongLong
abs_value
=
static_cast
<
ULongLong
>
(
value
);
bool
negative
=
value
<
0
;
if
(
negative
)
...
...
@@ -3740,26 +3252,16 @@ 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
))
{}
/** Returns the number of characters written to the output buffer. */
std
::
size_t
size
()
const
{
std
::
size_t
size
()
const
{
return
internal
::
to_unsigned
(
buffer_
-
str_
+
BUFFER_SIZE
-
1
);
}
...
...
@@ -3767,17 +3269,13 @@ public:
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
character appended.
*/
const
char
*
c_str
()
const
{
const
char
*
c_str
()
const
{
buffer_
[
BUFFER_SIZE
-
1
]
=
'\0'
;
return
str_
;
}
...
...
@@ -3787,29 +3285,22 @@ 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
// a pointer to the end of the formatted string. This function doesn't
// write a terminating null character.
template
<
typename
T
>
inline
void
format_decimal
(
char
*&
buffer
,
T
value
)
{
inline
void
format_decimal
(
char
*&
buffer
,
T
value
)
{
typedef
typename
internal
::
IntTraits
<
T
>::
MainType
MainType
;
MainType
abs_value
=
static_cast
<
MainType
>
(
value
);
if
(
internal
::
is_negative
(
value
))
{
if
(
internal
::
is_negative
(
value
))
{
*
buffer
++
=
'-'
;
abs_value
=
0
-
abs_value
;
}
if
(
abs_value
<
100
)
{
if
(
abs_value
<
10
)
{
if
(
abs_value
<
100
)
{
if
(
abs_value
<
10
)
{
*
buffer
++
=
static_cast
<
char
>
(
'0'
+
abs_value
);
return
;
}
...
...
@@ -3834,14 +3325,12 @@ inline void format_decimal(char *&buffer, T value)
\endrst
*/
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
);
}
template
<
typename
T
>
inline
internal
::
NamedArg
<
wchar_t
>
arg
(
WStringRef
name
,
const
T
&
arg
)
{
inline
internal
::
NamedArg
<
wchar_t
>
arg
(
WStringRef
name
,
const
T
&
arg
)
{
return
internal
::
NamedArg
<
wchar_t
>
(
name
,
arg
);
}
...
...
@@ -3871,7 +3360,6 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
#define FMT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define FMT_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#define FMT_CONCAT(a, b) a##b
#define FMT_FOR_EACH_(N, f, ...) \
FMT_EXPAND(FMT_CONCAT(FMT_FOR_EACH, N)(f, __VA_ARGS__))
#define FMT_FOR_EACH(f, ...) \
...
...
@@ -3980,41 +3468,34 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
#define FMT_CAPTURE_W(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_W_, __VA_ARGS__)
namespace
fmt
{
namespace
fmt
{
FMT_VARIADIC
(
std
::
string
,
format
,
CStringRef
)
FMT_VARIADIC_W
(
std
::
wstring
,
format
,
WCStringRef
)
FMT_VARIADIC
(
void
,
print
,
CStringRef
)
FMT_VARIADIC
(
void
,
print
,
std
::
FILE
*
,
CStringRef
)
FMT_VARIADIC
(
void
,
print_colored
,
Color
,
CStringRef
)
namespace
internal
{
namespace
internal
{
template
<
typename
Char
>
inline
bool
is_name_start
(
Char
c
)
{
inline
bool
is_name_start
(
Char
c
)
{
return
(
'a'
<=
c
&&
c
<=
'z'
)
||
(
'A'
<=
c
&&
c
<=
'Z'
)
||
'_'
==
c
;
}
// Parses an unsigned integer advancing s to the end of the parsed input.
// This function assumes that the first character of s is a digit.
template
<
typename
Char
>
unsigned
parse_nonnegative_int
(
const
Char
*&
s
)
{
unsigned
parse_nonnegative_int
(
const
Char
*&
s
)
{
assert
(
'0'
<=
*
s
&&
*
s
<=
'9'
);
unsigned
value
=
0
;
do
{
do
{
unsigned
new_value
=
value
*
10
+
(
*
s
++
-
'0'
);
// Check if value wrapped around.
if
(
new_value
<
value
)
{
if
(
new_value
<
value
)
{
value
=
(
std
::
numeric_limits
<
unsigned
>::
max
)();
break
;
}
value
=
new_value
;
}
while
(
'0'
<=
*
s
&&
*
s
<=
'9'
);
}
while
(
'0'
<=
*
s
&&
*
s
<=
'9'
);
// Convert to unsigned to prevent a warning.
unsigned
max_int
=
(
std
::
numeric_limits
<
int
>::
max
)();
if
(
value
>
max_int
)
...
...
@@ -4022,10 +3503,8 @@ unsigned parse_nonnegative_int(const Char *&s)
return
value
;
}
inline
void
require_numeric_argument
(
const
Arg
&
arg
,
char
spec
)
{
if
(
arg
.
type
>
Arg
::
LAST_NUMERIC_TYPE
)
{
inline
void
require_numeric_argument
(
const
Arg
&
arg
,
char
spec
)
{
if
(
arg
.
type
>
Arg
::
LAST_NUMERIC_TYPE
)
{
std
::
string
message
=
fmt
::
format
(
"format specifier '{}' requires numeric argument"
,
spec
);
FMT_THROW
(
fmt
::
FormatError
(
message
));
...
...
@@ -4033,12 +3512,10 @@ inline void require_numeric_argument(const Arg &arg, char spec)
}
template
<
typename
Char
>
void
check_sign
(
const
Char
*&
s
,
const
Arg
&
arg
)
{
void
check_sign
(
const
Char
*&
s
,
const
Arg
&
arg
)
{
char
sign
=
static_cast
<
char
>
(
*
s
);
require_numeric_argument
(
arg
,
sign
);
if
(
arg
.
type
==
Arg
::
UINT
||
arg
.
type
==
Arg
::
ULONG_LONG
)
{
if
(
arg
.
type
==
Arg
::
UINT
||
arg
.
type
==
Arg
::
ULONG_LONG
)
{
FMT_THROW
(
FormatError
(
fmt
::
format
(
"format specifier '{}' requires signed argument"
,
sign
)));
}
...
...
@@ -4048,10 +3525,8 @@ void check_sign(const Char *&s, const Arg &arg)
template
<
typename
Char
,
typename
AF
>
inline
internal
::
Arg
BasicFormatter
<
Char
,
AF
>::
get_arg
(
BasicStringRef
<
Char
>
arg_name
,
const
char
*&
error
)
{
if
(
check_no_auto_index
(
error
))
{
BasicStringRef
<
Char
>
arg_name
,
const
char
*&
error
)
{
if
(
check_no_auto_index
(
error
))
{
map_
.
init
(
args
());
const
internal
::
Arg
*
arg
=
map_
.
find
(
arg_name
);
if
(
arg
)
...
...
@@ -4062,13 +3537,11 @@ inline internal::Arg BasicFormatter<Char, AF>::get_arg(
}
template
<
typename
Char
,
typename
AF
>
inline
internal
::
Arg
BasicFormatter
<
Char
,
AF
>::
parse_arg_index
(
const
Char
*&
s
)
{
inline
internal
::
Arg
BasicFormatter
<
Char
,
AF
>::
parse_arg_index
(
const
Char
*&
s
)
{
const
char
*
error
=
0
;
internal
::
Arg
arg
=
*
s
<
'0'
||
*
s
>
'9'
?
next_arg
(
error
)
:
get_arg
(
internal
::
parse_nonnegative_int
(
s
),
error
);
if
(
error
)
{
if
(
error
)
{
FMT_THROW
(
FormatError
(
*
s
!=
'}'
&&
*
s
!=
':'
?
"invalid format string"
:
error
));
}
...
...
@@ -4076,16 +3549,13 @@ inline internal::Arg BasicFormatter<Char, AF>::parse_arg_index(const Char *&s)
}
template
<
typename
Char
,
typename
AF
>
inline
internal
::
Arg
BasicFormatter
<
Char
,
AF
>::
parse_arg_name
(
const
Char
*&
s
)
{
inline
internal
::
Arg
BasicFormatter
<
Char
,
AF
>::
parse_arg_name
(
const
Char
*&
s
)
{
assert
(
internal
::
is_name_start
(
*
s
));
const
Char
*
start
=
s
;
Char
c
;
do
{
do
{
c
=
*++
s
;
}
while
(
internal
::
is_name_start
(
c
)
||
(
'0'
<=
c
&&
c
<=
'9'
));
}
while
(
internal
::
is_name_start
(
c
)
||
(
'0'
<=
c
&&
c
<=
'9'
));
const
char
*
error
=
0
;
internal
::
Arg
arg
=
get_arg
(
BasicStringRef
<
Char
>
(
start
,
s
-
start
),
error
);
if
(
error
)
...
...
@@ -4095,28 +3565,22 @@ inline internal::Arg BasicFormatter<Char, AF>::parse_arg_name(const Char *&s)
template
<
typename
Char
,
typename
ArgFormatter
>
const
Char
*
BasicFormatter
<
Char
,
ArgFormatter
>::
format
(
const
Char
*&
format_str
,
const
internal
::
Arg
&
arg
)
{
const
Char
*&
format_str
,
const
internal
::
Arg
&
arg
)
{
using
internal
::
Arg
;
const
Char
*
s
=
format_str
;
FormatSpec
spec
;
if
(
*
s
==
':'
)
{
if
(
arg
.
type
==
Arg
::
CUSTOM
)
{
if
(
*
s
==
':'
)
{
if
(
arg
.
type
==
Arg
::
CUSTOM
)
{
arg
.
custom
.
format
(
this
,
arg
.
custom
.
value
,
&
s
);
return
s
;
}
++
s
;
// Parse fill and alignment.
if
(
Char
c
=
*
s
)
{
if
(
Char
c
=
*
s
)
{
const
Char
*
p
=
s
+
1
;
spec
.
align_
=
ALIGN_DEFAULT
;
do
{
switch
(
*
p
)
{
do
{
switch
(
*
p
)
{
case
'<'
:
spec
.
align_
=
ALIGN_LEFT
;
break
;
...
...
@@ -4130,28 +3594,23 @@ const Char *BasicFormatter<Char, ArgFormatter>::format(
spec
.
align_
=
ALIGN_CENTER
;
break
;
}
if
(
spec
.
align_
!=
ALIGN_DEFAULT
)
{
if
(
p
!=
s
)
{
if
(
spec
.
align_
!=
ALIGN_DEFAULT
)
{
if
(
p
!=
s
)
{
if
(
c
==
'}'
)
break
;
if
(
c
==
'{'
)
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
;
}
}
while
(
--
p
>=
s
);
}
while
(
--
p
>=
s
);
}
// Parse sign.
switch
(
*
s
)
{
switch
(
*
s
)
{
case
'+'
:
check_sign
(
s
,
arg
);
spec
.
flags_
|=
SIGN_FLAG
|
PLUS_FLAG
;
...
...
@@ -4166,16 +3625,14 @@ const Char *BasicFormatter<Char, ArgFormatter>::format(
break
;
}
if
(
*
s
==
'#'
)
{
if
(
*
s
==
'#'
)
{
require_numeric_argument
(
arg
,
'#'
);
spec
.
flags_
|=
HASH_FLAG
;
++
s
;
}
// Parse zero flag.
if
(
*
s
==
'0'
)
{
if
(
*
s
==
'0'
)
{
require_numeric_argument
(
arg
,
'0'
);
spec
.
align_
=
ALIGN_NUMERIC
;
spec
.
fill_
=
'0'
;
...
...
@@ -4183,20 +3640,16 @@ const Char *BasicFormatter<Char, ArgFormatter>::format(
}
// Parse width.
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
{
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
{
spec
.
width_
=
internal
::
parse_nonnegative_int
(
s
);
}
else
if
(
*
s
==
'{'
)
{
}
else
if
(
*
s
==
'{'
)
{
++
s
;
Arg
width_arg
=
internal
::
is_name_start
(
*
s
)
?
parse_arg_name
(
s
)
:
parse_arg_index
(
s
);
if
(
*
s
++
!=
'}'
)
FMT_THROW
(
FormatError
(
"invalid format string"
));
ULongLong
value
=
0
;
switch
(
width_arg
.
type
)
{
switch
(
width_arg
.
type
)
{
case
Arg
:
:
INT
:
if
(
width_arg
.
int_value
<
0
)
FMT_THROW
(
FormatError
(
"negative width"
));
...
...
@@ -4222,24 +3675,19 @@ const Char *BasicFormatter<Char, ArgFormatter>::format(
}
// Parse precision.
if
(
*
s
==
'.'
)
{
if
(
*
s
==
'.'
)
{
++
s
;
spec
.
precision_
=
0
;
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
{
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
{
spec
.
precision_
=
internal
::
parse_nonnegative_int
(
s
);
}
else
if
(
*
s
==
'{'
)
{
}
else
if
(
*
s
==
'{'
)
{
++
s
;
Arg
precision_arg
=
internal
::
is_name_start
(
*
s
)
?
parse_arg_name
(
s
)
:
parse_arg_index
(
s
);
if
(
*
s
++
!=
'}'
)
FMT_THROW
(
FormatError
(
"invalid format string"
));
ULongLong
value
=
0
;
switch
(
precision_arg
.
type
)
{
switch
(
precision_arg
.
type
)
{
case
Arg
:
:
INT
:
if
(
precision_arg
.
int_value
<
0
)
FMT_THROW
(
FormatError
(
"negative precision"
));
...
...
@@ -4262,13 +3710,10 @@ const Char *BasicFormatter<Char, ArgFormatter>::format(
if
(
value
>
(
std
::
numeric_limits
<
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
)
{
if
(
arg
.
type
<=
Arg
::
LAST_INTEGER_TYPE
||
arg
.
type
==
Arg
::
POINTER
)
{
FMT_THROW
(
FormatError
(
fmt
::
format
(
"precision not allowed in {} format specifier"
,
arg
.
type
==
Arg
::
POINTER
?
"pointer"
:
"integer"
)));
...
...
@@ -4289,16 +3734,13 @@ const Char *BasicFormatter<Char, ArgFormatter>::format(
}
template
<
typename
Char
,
typename
AF
>
void
BasicFormatter
<
Char
,
AF
>::
format
(
BasicCStringRef
<
Char
>
format_str
)
{
void
BasicFormatter
<
Char
,
AF
>::
format
(
BasicCStringRef
<
Char
>
format_str
)
{
const
Char
*
s
=
format_str
.
c_str
();
const
Char
*
start
=
s
;
while
(
*
s
)
{
while
(
*
s
)
{
Char
c
=
*
s
++
;
if
(
c
!=
'{'
&&
c
!=
'}'
)
continue
;
if
(
*
s
==
c
)
{
if
(
*
s
==
c
)
{
write
(
writer_
,
start
,
s
);
start
=
++
s
;
continue
;
...
...
@@ -4315,40 +3757,33 @@ void BasicFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
}
// namespace fmt
#if FMT_USE_USER_DEFINED_LITERALS
namespace
fmt
{
namespace
internal
{
namespace
fmt
{
namespace
internal
{
template
<
typename
Char
>
struct
UdlFormat
{
struct
UdlFormat
{
const
Char
*
str
;
template
<
typename
...
Args
>
auto
operator
()(
Args
&&
...
args
)
const
->
decltype
(
format
(
str
,
std
::
forward
<
Args
>
(
args
)...))
{
->
decltype
(
format
(
str
,
std
::
forward
<
Args
>
(
args
)...))
{
return
format
(
str
,
std
::
forward
<
Args
>
(
args
)...);
}
};
template
<
typename
Char
>
struct
UdlArg
{
struct
UdlArg
{
const
Char
*
str
;
template
<
typename
T
>
NamedArg
<
Char
>
operator
=
(
T
&&
value
)
const
{
NamedArg
<
Char
>
operator
=
(
T
&&
value
)
const
{
return
{
str
,
std
::
forward
<
T
>
(
value
)};
}
};
}
// namespace internal
inline
namespace
literals
{
inline
namespace
literals
{
/**
\rst
...
...
@@ -4361,15 +3796,9 @@ inline namespace literals
\endrst
*/
inline
internal
::
UdlFormat
<
char
>
operator
""
_format
(
const
char
*
s
,
std
::
size_t
)
{
return
{
s
};
}
operator
""
_format
(
const
char
*
s
,
std
::
size_t
)
{
return
{
s
};
}
inline
internal
::
UdlFormat
<
wchar_t
>
operator
""
_format
(
const
wchar_t
*
s
,
std
::
size_t
)
{
return
{
s
};
}
operator
""
_format
(
const
wchar_t
*
s
,
std
::
size_t
)
{
return
{
s
};
}
/**
\rst
...
...
@@ -4382,15 +3811,9 @@ operator"" _format(const wchar_t *s, std::size_t)
\endrst
*/
inline
internal
::
UdlArg
<
char
>
operator
""
_a
(
const
char
*
s
,
std
::
size_t
)
{
return
{
s
};
}
operator
""
_a
(
const
char
*
s
,
std
::
size_t
)
{
return
{
s
};
}
inline
internal
::
UdlArg
<
wchar_t
>
operator
""
_a
(
const
wchar_t
*
s
,
std
::
size_t
)
{
return
{
s
};
}
operator
""
_a
(
const
wchar_t
*
s
,
std
::
size_t
)
{
return
{
s
};
}
}
// inline namespace literals
}
// namespace fmt
...
...
include/spdlog/fmt/bundled/ostream.cc
View file @
6312748c
...
...
@@ -7,15 +7,13 @@
For the license information refer to format.h.
*/
// Commented out by spdlog to use header only
// #include "fmt/ostream.h"
// #include "fmt/printf.h"
// Commented out by spdlog to use header only
// #include "fmt/ostream.h"
namespace
fmt
{
namespace
{
// Write the content of w to os.
void
write
(
std
::
ostream
&
os
,
Writer
&
w
)
{
namespace
internal
{
FMT_FUNC
void
write
(
std
::
ostream
&
os
,
Writer
&
w
)
{
const
char
*
data
=
w
.
data
();
typedef
internal
::
MakeUnsigned
<
std
::
streamsize
>::
Type
UnsignedStreamSize
;
UnsignedStreamSize
size
=
w
.
size
();
...
...
@@ -33,13 +31,6 @@ void write(std::ostream &os, Writer &w) {
FMT_FUNC
void
print
(
std
::
ostream
&
os
,
CStringRef
format_str
,
ArgList
args
)
{
MemoryWriter
w
;
w
.
write
(
format_str
,
args
);
write
(
os
,
w
);
}
FMT_FUNC
int
fprintf
(
std
::
ostream
&
os
,
CStringRef
format
,
ArgList
args
)
{
MemoryWriter
w
;
printf
(
w
,
format
,
args
);
write
(
os
,
w
);
return
static_cast
<
int
>
(
w
.
size
());
internal
::
write
(
os
,
w
);
}
}
// namespace fmt
include/spdlog/fmt/bundled/ostream.h
View file @
6312748c
...
...
@@ -14,32 +14,26 @@
// #include "fmt/format.h"
#include <ostream>
namespace
fmt
{
namespace
fmt
{
namespace
internal
{
namespace
internal
{
template
<
class
Char
>
class
FormatBuf
:
public
std
::
basic_streambuf
<
Char
>
{
private
:
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
])
{
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
()))
{
int_type
overflow
(
int_type
ch
=
traits_type
::
eof
())
{
if
(
!
traits_type
::
eq_int_type
(
ch
,
traits_type
::
eof
()))
{
size_t
buf_size
=
size
();
buffer_
.
resize
(
buf_size
);
buffer_
.
reserve
(
buf_size
*
2
);
...
...
@@ -51,16 +45,14 @@ public:
return
ch
;
}
size_t
size
()
const
{
size_t
size
()
const
{
return
to_unsigned
(
this
->
pptr
()
-
start_
);
}
};
Yes
&
convert
(
std
::
ostream
&
);
struct
DummyStream
:
std
::
ostream
{
struct
DummyStream
:
std
::
ostream
{
DummyStream
();
// Suppress a bogus warning in MSVC.
// Hide all operator<< overloads from std::ostream.
void
operator
<<
(
Null
<>
);
...
...
@@ -69,21 +61,21 @@ struct DummyStream : std::ostream
No
&
operator
<<
(
std
::
ostream
&
,
int
);
template
<
typename
T
>
struct
ConvertToIntImpl
<
T
,
true
>
{
struct
ConvertToIntImpl
<
T
,
true
>
{
// Convert to int only if T doesn't have an overloaded operator<<.
enum
{
enum
{
value
=
sizeof
(
convert
(
get
<
DummyStream
>
()
<<
get
<
T
>
()))
==
sizeof
(
No
)
};
};
// Write the content of w to os.
void
write
(
std
::
ostream
&
os
,
Writer
&
w
);
}
// namespace internal
// Formats a value.
template
<
typename
Char
,
typename
ArgFormatter
,
typename
T
>
void
format
(
BasicFormatter
<
Char
,
ArgFormatter
>
&
f
,
const
Char
*&
format_str
,
const
T
&
value
)
{
void
format_arg
(
BasicFormatter
<
Char
,
ArgFormatter
>
&
f
,
const
Char
*&
format_str
,
const
T
&
value
)
{
internal
::
MemoryBuffer
<
Char
,
internal
::
INLINE_BUFFER_SIZE
>
buffer
;
internal
::
FormatBuf
<
Char
>
format_buf
(
buffer
);
...
...
@@ -106,18 +98,6 @@ void format(BasicFormatter<Char, ArgFormatter> &f,
*/
FMT_API
void
print
(
std
::
ostream
&
os
,
CStringRef
format_str
,
ArgList
args
);
FMT_VARIADIC
(
void
,
print
,
std
::
ostream
&
,
CStringRef
)
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fprintf(cerr, "Don't %s!", "panic");
\endrst
*/
FMT_API
int
fprintf
(
std
::
ostream
&
os
,
CStringRef
format_str
,
ArgList
args
);
FMT_VARIADIC
(
int
,
fprintf
,
std
::
ostream
&
,
CStringRef
)
}
// namespace fmt
#ifdef FMT_HEADER_ONLY
...
...
include/spdlog/fmt/bundled/printf.h
View file @
6312748c
...
...
@@ -13,56 +13,41 @@
#include <algorithm> // std::fill_n
#include <limits> // std::numeric_limits
#include "fmt/
format
.h"
#include "fmt/
ostream
.h"
namespace
fmt
{
namespace
internal
{
namespace
fmt
{
namespace
internal
{
// Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers.
template
<
bool
IsSigned
>
struct
IntChecker
{
struct
IntChecker
{
template
<
typename
T
>
static
bool
fits_in_int
(
T
value
)
{
static
bool
fits_in_int
(
T
value
)
{
unsigned
max
=
std
::
numeric_limits
<
int
>::
max
();
return
value
<=
max
;
}
static
bool
fits_in_int
(
bool
)
{
return
true
;
}
static
bool
fits_in_int
(
bool
)
{
return
true
;
}
};
template
<>
struct
IntChecker
<
true
>
{
struct
IntChecker
<
true
>
{
template
<
typename
T
>
static
bool
fits_in_int
(
T
value
)
{
static
bool
fits_in_int
(
T
value
)
{
return
value
>=
std
::
numeric_limits
<
int
>::
min
()
&&
value
<=
std
::
numeric_limits
<
int
>::
max
();
}
static
bool
fits_in_int
(
int
)
{
return
true
;
}
static
bool
fits_in_int
(
int
)
{
return
true
;
}
};
class
PrecisionHandler
:
public
ArgVisitor
<
PrecisionHandler
,
int
>
{
public
:
void
report_unhandled_arg
()
{
class
PrecisionHandler
:
public
ArgVisitor
<
PrecisionHandler
,
int
>
{
public
:
void
report_unhandled_arg
()
{
FMT_THROW
(
FormatError
(
"precision is not integer"
));
}
template
<
typename
T
>
int
visit_any_int
(
T
value
)
{
int
visit_any_int
(
T
value
)
{
if
(
!
IntChecker
<
std
::
numeric_limits
<
T
>::
is_signed
>::
fits_in_int
(
value
))
FMT_THROW
(
FormatError
(
"number is too big"
));
return
static_cast
<
int
>
(
value
);
...
...
@@ -70,25 +55,19 @@ public:
};
// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
class
IsZeroInt
:
public
ArgVisitor
<
IsZeroInt
,
bool
>
{
public
:
class
IsZeroInt
:
public
ArgVisitor
<
IsZeroInt
,
bool
>
{
public
:
template
<
typename
T
>
bool
visit_any_int
(
T
value
)
{
return
value
==
0
;
}
bool
visit_any_int
(
T
value
)
{
return
value
==
0
;
}
};
template
<
typename
T
,
typename
U
>
struct
is_same
{
struct
is_same
{
enum
{
value
=
0
};
};
template
<
typename
T
>
struct
is_same
<
T
,
T
>
{
struct
is_same
<
T
,
T
>
{
enum
{
value
=
1
};
};
...
...
@@ -97,58 +76,46 @@ struct is_same<T, T>
// corresponding signed or unsigned type depending on the type specifier:
// 'd' and 'i' - signed, other - unsigned)
template
<
typename
T
=
void
>
class
ArgConverter
:
public
ArgVisitor
<
ArgConverter
<
T
>
,
void
>
{
private
:
class
ArgConverter
:
public
ArgVisitor
<
ArgConverter
<
T
>
,
void
>
{
private
:
internal
::
Arg
&
arg_
;
wchar_t
type_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
ArgConverter
);
public
:
public
:
ArgConverter
(
internal
::
Arg
&
arg
,
wchar_t
type
)
:
arg_
(
arg
),
type_
(
type
)
{}
void
visit_bool
(
bool
value
)
{
void
visit_bool
(
bool
value
)
{
if
(
type_
!=
's'
)
visit_any_int
(
value
);
}
template
<
typename
U
>
void
visit_any_int
(
U
value
)
{
void
visit_any_int
(
U
value
)
{
bool
is_signed
=
type_
==
'd'
||
type_
==
'i'
;
using
internal
::
Arg
;
typedef
typename
internal
::
Conditional
<
is_same
<
T
,
void
>::
value
,
U
,
T
>::
type
TargetType
;
if
(
sizeof
(
TargetType
)
<=
sizeof
(
int
))
{
if
(
sizeof
(
TargetType
)
<=
sizeof
(
int
))
{
// Extra casts are used to silence warnings.
if
(
is_signed
)
{
if
(
is_signed
)
{
arg_
.
type
=
Arg
::
INT
;
arg_
.
int_value
=
static_cast
<
int
>
(
static_cast
<
TargetType
>
(
value
));
}
else
{
}
else
{
arg_
.
type
=
Arg
::
UINT
;
typedef
typename
internal
::
MakeUnsigned
<
TargetType
>::
Type
Unsigned
;
arg_
.
uint_value
=
static_cast
<
unsigned
>
(
static_cast
<
Unsigned
>
(
value
));
}
}
else
{
if
(
is_signed
)
{
}
else
{
if
(
is_signed
)
{
arg_
.
type
=
Arg
::
LONG_LONG
;
// glibc's printf doesn't sign extend arguments of smaller types:
// std::printf("%lld", -42); // prints "4294967254"
// but we don't have to do the same because it's a UB.
arg_
.
long_long_value
=
static_cast
<
LongLong
>
(
value
);
}
else
{
}
else
{
arg_
.
type
=
Arg
::
ULONG_LONG
;
arg_
.
ulong_long_value
=
static_cast
<
typename
internal
::
MakeUnsigned
<
U
>::
Type
>
(
value
);
...
...
@@ -158,19 +125,17 @@ public:
};
// Converts an integer argument to char for printf.
class
CharConverter
:
public
ArgVisitor
<
CharConverter
,
void
>
{
private
:
class
CharConverter
:
public
ArgVisitor
<
CharConverter
,
void
>
{
private
:
internal
::
Arg
&
arg_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
CharConverter
);
public
:
public
:
explicit
CharConverter
(
internal
::
Arg
&
arg
)
:
arg_
(
arg
)
{}
template
<
typename
T
>
void
visit_any_int
(
T
value
)
{
void
visit_any_int
(
T
value
)
{
arg_
.
type
=
internal
::
Arg
::
CHAR
;
arg_
.
int_value
=
static_cast
<
char
>
(
value
);
}
...
...
@@ -178,28 +143,24 @@ public:
// Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative.
class
WidthHandler
:
public
ArgVisitor
<
WidthHandler
,
unsigned
>
{
private
:
class
WidthHandler
:
public
ArgVisitor
<
WidthHandler
,
unsigned
>
{
private
:
FormatSpec
&
spec_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
WidthHandler
);
public
:
public
:
explicit
WidthHandler
(
FormatSpec
&
spec
)
:
spec_
(
spec
)
{}
void
report_unhandled_arg
()
{
void
report_unhandled_arg
()
{
FMT_THROW
(
FormatError
(
"width is not integer"
));
}
template
<
typename
T
>
unsigned
visit_any_int
(
T
value
)
{
unsigned
visit_any_int
(
T
value
)
{
typedef
typename
internal
::
IntTraits
<
T
>::
MainType
UnsignedType
;
UnsignedType
width
=
static_cast
<
UnsignedType
>
(
value
);
if
(
internal
::
is_negative
(
value
))
{
if
(
internal
::
is_negative
(
value
))
{
spec_
.
align_
=
ALIGN_LEFT
;
width
=
0
-
width
;
}
...
...
@@ -229,18 +190,16 @@ public:
\endrst
*/
template
<
typename
Impl
,
typename
Char
>
class
BasicPrintfArgFormatter
:
public
internal
::
ArgFormatterBase
<
Impl
,
Char
>
{
private
:
void
write_null_pointer
()
{
class
BasicPrintfArgFormatter
:
public
internal
::
ArgFormatterBase
<
Impl
,
Char
>
{
private
:
void
write_null_pointer
()
{
this
->
spec
().
type_
=
0
;
this
->
write
(
"(nil)"
);
}
typedef
internal
::
ArgFormatterBase
<
Impl
,
Char
>
Base
;
public
:
public
:
/**
\rst
Constructs an argument formatter object.
...
...
@@ -252,8 +211,7 @@ public:
:
internal
::
ArgFormatterBase
<
Impl
,
Char
>
(
writer
,
spec
)
{}
/** Formats an argument of type ``bool``. */
void
visit_bool
(
bool
value
)
{
void
visit_bool
(
bool
value
)
{
FormatSpec
&
fmt_spec
=
this
->
spec
();
if
(
fmt_spec
.
type_
!=
's'
)
return
this
->
visit_any_int
(
value
);
...
...
@@ -262,38 +220,30 @@ public:
}
/** Formats a character. */
void
visit_char
(
int
value
)
{
void
visit_char
(
int
value
)
{
const
FormatSpec
&
fmt_spec
=
this
->
spec
();
BasicWriter
<
Char
>
&
w
=
this
->
writer
();
if
(
fmt_spec
.
type_
&&
fmt_spec
.
type_
!=
'c'
)
w
.
write_int
(
value
,
fmt_spec
);
typedef
typename
BasicWriter
<
Char
>::
CharPtr
CharPtr
;
CharPtr
out
=
CharPtr
();
if
(
fmt_spec
.
width_
>
1
)
{
if
(
fmt_spec
.
width_
>
1
)
{
Char
fill
=
' '
;
out
=
w
.
grow_buffer
(
fmt_spec
.
width_
);
if
(
fmt_spec
.
align_
!=
ALIGN_LEFT
)
{
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
);
}
/** Formats a null-terminated C string. */
void
visit_cstring
(
const
char
*
value
)
{
void
visit_cstring
(
const
char
*
value
)
{
if
(
value
)
Base
::
visit_cstring
(
value
);
else
if
(
this
->
spec
().
type_
==
'p'
)
...
...
@@ -303,8 +253,7 @@ public:
}
/** Formats a pointer. */
void
visit_pointer
(
const
void
*
value
)
{
void
visit_pointer
(
const
void
*
value
)
{
if
(
value
)
return
Base
::
visit_pointer
(
value
);
this
->
spec
().
type_
=
0
;
...
...
@@ -312,8 +261,7 @@ public:
}
/** Formats an argument of a custom (user-defined) type. */
void
visit_custom
(
internal
::
Arg
::
CustomValue
c
)
{
void
visit_custom
(
internal
::
Arg
::
CustomValue
c
)
{
BasicFormatter
<
Char
>
formatter
(
ArgList
(),
this
->
writer
());
const
Char
format_str
[]
=
{
'}'
,
0
};
const
Char
*
format
=
format_str
;
...
...
@@ -324,9 +272,8 @@ public:
/** The default printf argument formatter. */
template
<
typename
Char
>
class
PrintfArgFormatter
:
public
BasicPrintfArgFormatter
<
PrintfArgFormatter
<
Char
>
,
Char
>
{
public
:
:
public
BasicPrintfArgFormatter
<
PrintfArgFormatter
<
Char
>
,
Char
>
{
public
:
/** Constructs an argument formatter object. */
PrintfArgFormatter
(
BasicWriter
<
Char
>
&
w
,
FormatSpec
&
s
)
:
BasicPrintfArgFormatter
<
PrintfArgFormatter
<
Char
>
,
Char
>
(
w
,
s
)
{}
...
...
@@ -334,9 +281,8 @@ public:
/** This template formats data and writes the output to a writer. */
template
<
typename
Char
,
typename
ArgFormatter
=
PrintfArgFormatter
<
Char
>
>
class
PrintfFormatter
:
private
internal
::
FormatterBase
{
private
:
class
PrintfFormatter
:
private
internal
::
FormatterBase
{
private
:
BasicWriter
<
Char
>
&
writer_
;
void
parse_flags
(
FormatSpec
&
spec
,
const
Char
*&
s
);
...
...
@@ -350,7 +296,7 @@ private:
// Parses argument index, flags and width and returns the argument index.
unsigned
parse_header
(
const
Char
*&
s
,
FormatSpec
&
spec
);
public
:
public
:
/**
\rst
Constructs a ``PrintfFormatter`` object. References to the arguments and
...
...
@@ -366,12 +312,9 @@ public:
};
template
<
typename
Char
,
typename
AF
>
void
PrintfFormatter
<
Char
,
AF
>::
parse_flags
(
FormatSpec
&
spec
,
const
Char
*&
s
)
{
for
(;;)
{
switch
(
*
s
++
)
{
void
PrintfFormatter
<
Char
,
AF
>::
parse_flags
(
FormatSpec
&
spec
,
const
Char
*&
s
)
{
for
(;;)
{
switch
(
*
s
++
)
{
case
'-'
:
spec
.
align_
=
ALIGN_LEFT
;
break
;
...
...
@@ -396,8 +339,7 @@ void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s)
template
<
typename
Char
,
typename
AF
>
internal
::
Arg
PrintfFormatter
<
Char
,
AF
>::
get_arg
(
const
Char
*
s
,
unsigned
arg_index
)
{
unsigned
arg_index
)
{
(
void
)
s
;
const
char
*
error
=
0
;
internal
::
Arg
arg
=
arg_index
==
std
::
numeric_limits
<
unsigned
>::
max
()
?
...
...
@@ -409,26 +351,20 @@ internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
template
<
typename
Char
,
typename
AF
>
unsigned
PrintfFormatter
<
Char
,
AF
>::
parse_header
(
const
Char
*&
s
,
FormatSpec
&
spec
)
{
const
Char
*&
s
,
FormatSpec
&
spec
)
{
unsigned
arg_index
=
std
::
numeric_limits
<
unsigned
>::
max
();
Char
c
=
*
s
;
if
(
c
>=
'0'
&&
c
<=
'9'
)
{
if
(
c
>=
'0'
&&
c
<=
'9'
)
{
// Parse an argument index (if followed by '$') or a width possibly
// preceded with '0' flag(s).
unsigned
value
=
internal
::
parse_nonnegative_int
(
s
);
if
(
*
s
==
'$'
)
// value is an argument index
{
if
(
*
s
==
'$'
)
{
// value is an argument index
++
s
;
arg_index
=
value
;
}
else
{
}
else
{
if
(
c
==
'0'
)
spec
.
fill_
=
'0'
;
if
(
value
!=
0
)
{
if
(
value
!=
0
)
{
// Nonzero value means that we parsed width and don't need to
// parse it or flags again, so return now.
spec
.
width_
=
value
;
...
...
@@ -438,12 +374,9 @@ unsigned PrintfFormatter<Char, AF>::parse_header(
}
parse_flags
(
spec
,
s
);
// Parse width.
if
(
*
s
>=
'0'
&&
*
s
<=
'9'
)
{
if
(
*
s
>=
'0'
&&
*
s
<=
'9'
)
{
spec
.
width_
=
internal
::
parse_nonnegative_int
(
s
);
}
else
if
(
*
s
==
'*'
)
{
}
else
if
(
*
s
==
'*'
)
{
++
s
;
spec
.
width_
=
internal
::
WidthHandler
(
spec
).
visit
(
get_arg
(
s
));
}
...
...
@@ -451,16 +384,13 @@ unsigned PrintfFormatter<Char, AF>::parse_header(
}
template
<
typename
Char
,
typename
AF
>
void
PrintfFormatter
<
Char
,
AF
>::
format
(
BasicCStringRef
<
Char
>
format_str
)
{
void
PrintfFormatter
<
Char
,
AF
>::
format
(
BasicCStringRef
<
Char
>
format_str
)
{
const
Char
*
start
=
format_str
.
c_str
();
const
Char
*
s
=
start
;
while
(
*
s
)
{
while
(
*
s
)
{
Char
c
=
*
s
++
;
if
(
c
!=
'%'
)
continue
;
if
(
*
s
==
c
)
{
if
(
*
s
==
c
)
{
write
(
writer_
,
start
,
s
);
start
=
++
s
;
continue
;
...
...
@@ -474,15 +404,11 @@ void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
unsigned
arg_index
=
parse_header
(
s
,
spec
);
// Parse precision.
if
(
*
s
==
'.'
)
{
if
(
*
s
==
'.'
)
{
++
s
;
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
{
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
{
spec
.
precision_
=
static_cast
<
int
>
(
internal
::
parse_nonnegative_int
(
s
));
}
else
if
(
*
s
==
'*'
)
{
}
else
if
(
*
s
==
'*'
)
{
++
s
;
spec
.
precision_
=
internal
::
PrecisionHandler
().
visit
(
get_arg
(
s
));
}
...
...
@@ -492,8 +418,7 @@ void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
Arg
arg
=
get_arg
(
s
,
arg_index
);
if
(
spec
.
flag
(
HASH_FLAG
)
&&
internal
::
IsZeroInt
().
visit
(
arg
))
spec
.
flags_
&=
~
internal
::
to_unsigned
<
int
>
(
HASH_FLAG
);
if
(
spec
.
fill_
==
'0'
)
{
if
(
spec
.
fill_
==
'0'
)
{
if
(
arg
.
type
<=
Arg
::
LAST_NUMERIC_TYPE
)
spec
.
align_
=
ALIGN_NUMERIC
;
else
...
...
@@ -502,8 +427,7 @@ void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
// Parse length and convert the argument to the required type.
using
internal
::
ArgConverter
;
switch
(
*
s
++
)
{
switch
(
*
s
++
)
{
case
'h'
:
if
(
*
s
==
'h'
)
ArgConverter
<
signed
char
>
(
arg
,
*++
s
).
visit
(
arg
);
...
...
@@ -538,13 +462,10 @@ void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
if
(
!*
s
)
FMT_THROW
(
FormatError
(
"invalid format string"
));
spec
.
type_
=
static_cast
<
char
>
(
*
s
++
);
if
(
arg
.
type
<=
Arg
::
LAST_INTEGER_TYPE
)
{
if
(
arg
.
type
<=
Arg
::
LAST_INTEGER_TYPE
)
{
// Normalize type.
switch
(
spec
.
type_
)
{
case
'i'
:
case
'u'
:
switch
(
spec
.
type_
)
{
case
'i'
:
case
'u'
:
spec
.
type_
=
'd'
;
break
;
case
'c'
:
...
...
@@ -563,8 +484,7 @@ void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
}
template
<
typename
Char
>
void
printf
(
BasicWriter
<
Char
>
&
w
,
BasicCStringRef
<
Char
>
format
,
ArgList
args
)
{
void
printf
(
BasicWriter
<
Char
>
&
w
,
BasicCStringRef
<
Char
>
format
,
ArgList
args
)
{
PrintfFormatter
<
Char
>
(
args
,
w
).
format
(
format
);
}
...
...
@@ -577,16 +497,14 @@ void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args)
std::string message = fmt::sprintf("The answer is %d", 42);
\endrst
*/
inline
std
::
string
sprintf
(
CStringRef
format
,
ArgList
args
)
{
inline
std
::
string
sprintf
(
CStringRef
format
,
ArgList
args
)
{
MemoryWriter
w
;
printf
(
w
,
format
,
args
);
return
w
.
str
();
}
FMT_VARIADIC
(
std
::
string
,
sprintf
,
CStringRef
)
inline
std
::
wstring
sprintf
(
WCStringRef
format
,
ArgList
args
)
{
inline
std
::
wstring
sprintf
(
WCStringRef
format
,
ArgList
args
)
{
WMemoryWriter
w
;
printf
(
w
,
format
,
args
);
return
w
.
str
();
...
...
@@ -614,11 +532,27 @@ FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst
*/
inline
int
printf
(
CStringRef
format
,
ArgList
args
)
{
inline
int
printf
(
CStringRef
format
,
ArgList
args
)
{
return
fprintf
(
stdout
,
format
,
args
);
}
FMT_VARIADIC
(
int
,
printf
,
CStringRef
)
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fprintf(cerr, "Don't %s!", "panic");
\endrst
*/
inline
int
fprintf
(
std
::
ostream
&
os
,
CStringRef
format_str
,
ArgList
args
)
{
MemoryWriter
w
;
printf
(
w
,
format_str
,
args
);
internal
::
write
(
os
,
w
);
return
static_cast
<
int
>
(
w
.
size
());
}
FMT_VARIADIC
(
int
,
fprintf
,
std
::
ostream
&
,
CStringRef
)
}
// namespace fmt
#endif // FMT_PRINTF_H_
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment