Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
spdlog
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
spdlog
Commits
87ddb9a6
Commit
87ddb9a6
authored
Oct 20, 2016
by
gabime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
astyle
parent
6128a87d
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
5252 additions
and
4746 deletions
+5252
-4746
include/spdlog/fmt/bundled/format.h
include/spdlog/fmt/bundled/format.h
+4494
-4068
include/spdlog/fmt/bundled/ostream.h
include/spdlog/fmt/bundled/ostream.h
+117
-106
include/spdlog/fmt/bundled/printf.h
include/spdlog/fmt/bundled/printf.h
+641
-572
No files found.
include/spdlog/fmt/bundled/format.h
View file @
87ddb9a6
This source diff could not be displayed because it is too large. You can
view the blob
instead.
include/spdlog/fmt/bundled/ostream.h
View file @
87ddb9a6
/*
/*
Formatting library for C++ - std::ostream support
Formatting library for C++ - std::ostream support
Copyright (c) 2012 - 2016, Victor Zverovich
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
All rights reserved.
For the license information refer to format.h.
For the license information refer to format.h.
*/
*/
#ifndef FMT_OSTREAM_H_
#ifndef FMT_OSTREAM_H_
#define FMT_OSTREAM_H_
#define FMT_OSTREAM_H_
// commented out by spdlog
// commented out by spdlog
//#include "format.h"
//#include "format.h"
#include <ostream>
#include <ostream>
namespace
fmt
{
namespace
fmt
{
namespace
internal
{
namespace
internal
template
<
class
Char
>
{
class
FormatBuf
:
public
std
::
basic_streambuf
<
Char
>
{
private:
template
<
class
Char
>
typedef
typename
std
::
basic_streambuf
<
Char
>::
int_type
int_type
;
class
FormatBuf
:
public
std
::
basic_streambuf
<
Char
>
typedef
typename
std
::
basic_streambuf
<
Char
>::
traits_type
traits_type
;
{
private:
Buffer
<
Char
>
&
buffer_
;
typedef
typename
std
::
basic_streambuf
<
Char
>::
int_type
int_type
;
Char
*
start_
;
typedef
typename
std
::
basic_streambuf
<
Char
>::
traits_type
traits_type
;
public:
Buffer
<
Char
>
&
buffer_
;
FormatBuf
(
Buffer
<
Char
>
&
buffer
)
:
buffer_
(
buffer
),
start_
(
&
buffer
[
0
])
{
Char
*
start_
;
this
->
setp
(
start_
,
start_
+
buffer_
.
capacity
());
}
public:
FormatBuf
(
Buffer
<
Char
>
&
buffer
)
:
buffer_
(
buffer
),
start_
(
&
buffer
[
0
])
int_type
overflow
(
int_type
ch
=
traits_type
::
eof
())
{
{
if
(
!
traits_type
::
eq_int_type
(
ch
,
traits_type
::
eof
()))
{
this
->
setp
(
start_
,
start_
+
buffer_
.
capacity
());
size_t
buf_size
=
size
();
}
buffer_
.
resize
(
buf_size
);
buffer_
.
reserve
(
buf_size
*
2
);
int_type
overflow
(
int_type
ch
=
traits_type
::
eof
())
{
start_
=
&
buffer_
[
0
];
if
(
!
traits_type
::
eq_int_type
(
ch
,
traits_type
::
eof
()))
start_
[
buf_size
]
=
traits_type
::
to_char_type
(
ch
);
{
this
->
setp
(
start_
+
buf_size
+
1
,
start_
+
buf_size
*
2
);
size_t
buf_size
=
size
();
}
buffer_
.
resize
(
buf_size
);
return
ch
;
buffer_
.
reserve
(
buf_size
*
2
);
}
start_
=
&
buffer_
[
0
];
size_t
size
()
const
{
start_
[
buf_size
]
=
traits_type
::
to_char_type
(
ch
);
return
to_unsigned
(
this
->
pptr
()
-
start_
);
this
->
setp
(
start_
+
buf_size
+
1
,
start_
+
buf_size
*
2
);
}
}
};
return
ch
;
}
Yes
&
convert
(
std
::
ostream
&
);
size_t
size
()
const
struct
DummyStream
:
std
::
ostream
{
{
DummyStream
();
// Suppress a bogus warning in MSVC.
return
to_unsigned
(
this
->
pptr
()
-
start_
);
// Hide all operator<< overloads from std::ostream.
}
void
operator
<<
(
Null
<>
);
};
};
Yes
&
convert
(
std
::
ostream
&
);
No
&
operator
<<
(
std
::
ostream
&
,
int
);
struct
DummyStream
:
std
::
ostream
template
<
typename
T
>
{
struct
ConvertToIntImpl
<
T
,
true
>
{
DummyStream
();
// Suppress a bogus warning in MSVC.
// Convert to int only if T doesn't have an overloaded operator<<.
// Hide all operator<< overloads from std::ostream.
enum
{
void
operator
<<
(
Null
<>
);
value
=
sizeof
(
convert
(
get
<
DummyStream
>
()
<<
get
<
T
>
()))
==
sizeof
(
No
)
};
};
};
No
&
operator
<<
(
std
::
ostream
&
,
int
);
// Write the content of w to os.
template
<
typename
T
>
void
write
(
std
::
ostream
&
os
,
Writer
&
w
);
struct
ConvertToIntImpl
<
T
,
true
>
}
// namespace internal
{
// Convert to int only if T doesn't have an overloaded operator<<.
// Formats a value.
enum
template
<
typename
Char
,
typename
ArgFormatter
,
typename
T
>
{
void
format_arg
(
BasicFormatter
<
Char
,
ArgFormatter
>
&
f
,
value
=
sizeof
(
convert
(
get
<
DummyStream
>
()
<<
get
<
T
>
()))
==
sizeof
(
No
)
const
Char
*&
format_str
,
const
T
&
value
)
{
};
internal
::
MemoryBuffer
<
Char
,
internal
::
INLINE_BUFFER_SIZE
>
buffer
;
};
internal
::
FormatBuf
<
Char
>
format_buf
(
buffer
);
// Write the content of w to os.
std
::
basic_ostream
<
Char
>
output
(
&
format_buf
);
void
write
(
std
::
ostream
&
os
,
Writer
&
w
);
output
<<
value
;
}
// namespace internal
BasicStringRef
<
Char
>
str
(
&
buffer
[
0
],
format_buf
.
size
());
// Formats a value.
typedef
internal
::
MakeArg
<
BasicFormatter
<
Char
>
>
MakeArg
;
template
<
typename
Char
,
typename
ArgFormatter
,
typename
T
>
format_str
=
f
.
format
(
format_str
,
MakeArg
(
str
));
void
format_arg
(
BasicFormatter
<
Char
,
ArgFormatter
>
&
f
,
}
const
Char
*&
format_str
,
const
T
&
value
)
{
/**
internal
::
MemoryBuffer
<
Char
,
internal
::
INLINE_BUFFER_SIZE
>
buffer
;
\rst
Prints formatted data to the stream *os*.
internal
::
FormatBuf
<
Char
>
format_buf
(
buffer
);
std
::
basic_ostream
<
Char
>
output
(
&
format_buf
);
**Example**::
output
<<
value
;
print(cerr, "Don't {}!", "panic");
BasicStringRef
<
Char
>
str
(
&
buffer
[
0
],
format_buf
.
size
());
\endrst
typedef
internal
::
MakeArg
<
BasicFormatter
<
Char
>
>
MakeArg
;
*/
format_str
=
f
.
format
(
format_str
,
MakeArg
(
str
));
FMT_API
void
print
(
std
::
ostream
&
os
,
CStringRef
format_str
,
ArgList
args
);
}
FMT_VARIADIC
(
void
,
print
,
std
::
ostream
&
,
CStringRef
)
}
// namespace fmt
/**
\rst
#ifdef FMT_HEADER_ONLY
Prints formatted data to the stream *os*.
# include "ostream.cc"
#endif
**Example**::
print(cerr, "Don't {}!", "panic");
\endrst
*/
FMT_API
void
print
(
std
::
ostream
&
os
,
CStringRef
format_str
,
ArgList
args
);
FMT_VARIADIC
(
void
,
print
,
std
::
ostream
&
,
CStringRef
)
}
// namespace fmt
#ifdef FMT_HEADER_ONLY
# include "ostream.cc"
#endif
#endif // FMT_OSTREAM_H_
#endif // FMT_OSTREAM_H_
\ No newline at end of file
include/spdlog/fmt/bundled/printf.h
View file @
87ddb9a6
/*
/*
Formatting library for C++
Formatting library for C++
Copyright (c) 2012 - 2016, Victor Zverovich
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
All rights reserved.
For the license information refer to format.h.
For the license information refer to format.h.
*/
*/
#ifndef FMT_PRINTF_H_
#ifndef FMT_PRINTF_H_
#define FMT_PRINTF_H_
#define FMT_PRINTF_H_
#include <algorithm> // std::fill_n
#include <algorithm> // std::fill_n
#include <limits> // std::numeric_limits
#include <limits> // std::numeric_limits
#include "ostream.h"
#include "ostream.h"
namespace
fmt
{
namespace
fmt
namespace
internal
{
{
namespace
internal
// Checks if a value fits in int - used to avoid warnings about comparing
{
// signed and unsigned integers.
template
<
bool
IsSigned
>
// Checks if a value fits in int - used to avoid warnings about comparing
struct
IntChecker
{
// signed and unsigned integers.
template
<
typename
T
>
template
<
bool
IsSigned
>
static
bool
fits_in_int
(
T
value
)
{
struct
IntChecker
unsigned
max
=
std
::
numeric_limits
<
int
>::
max
();
{
return
value
<=
max
;
template
<
typename
T
>
}
static
bool
fits_in_int
(
T
value
)
static
bool
fits_in_int
(
bool
)
{
{
return
true
;
unsigned
max
=
std
::
numeric_limits
<
int
>::
max
();
}
return
value
<=
max
;
};
}
static
bool
fits_in_int
(
bool
)
template
<
>
{
struct
IntChecker
<
true
>
{
return
true
;
template
<
typename
T
>
}
static
bool
fits_in_int
(
T
value
)
{
};
return
value
>=
std
::
numeric_limits
<
int
>::
min
()
&&
value
<=
std
::
numeric_limits
<
int
>::
max
();
template
<
>
}
struct
IntChecker
<
true
>
static
bool
fits_in_int
(
int
)
{
{
return
true
;
template
<
typename
T
>
}
static
bool
fits_in_int
(
T
value
)
};
{
return
value
>=
std
::
numeric_limits
<
int
>::
min
()
&&
class
PrecisionHandler
:
public
ArgVisitor
<
PrecisionHandler
,
int
>
{
value
<=
std
::
numeric_limits
<
int
>::
max
();
public:
}
void
report_unhandled_arg
()
{
static
bool
fits_in_int
(
int
)
FMT_THROW
(
FormatError
(
"precision is not integer"
));
{
}
return
true
;
}
template
<
typename
T
>
};
int
visit_any_int
(
T
value
)
{
if
(
!
IntChecker
<
std
::
numeric_limits
<
T
>::
is_signed
>::
fits_in_int
(
value
))
class
PrecisionHandler
:
public
ArgVisitor
<
PrecisionHandler
,
int
>
FMT_THROW
(
FormatError
(
"number is too big"
));
{
return
static_cast
<
int
>
(
value
);
public:
}
void
report_unhandled_arg
()
};
{
FMT_THROW
(
FormatError
(
"precision is not integer"
));
// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
}
class
IsZeroInt
:
public
ArgVisitor
<
IsZeroInt
,
bool
>
{
public:
template
<
typename
T
>
template
<
typename
T
>
int
visit_any_int
(
T
value
)
bool
visit_any_int
(
T
value
)
{
{
return
value
==
0
;
if
(
!
IntChecker
<
std
::
numeric_limits
<
T
>::
is_signed
>::
fits_in_int
(
value
))
}
FMT_THROW
(
FormatError
(
"number is too big"
));
};
return
static_cast
<
int
>
(
value
);
}
template
<
typename
T
,
typename
U
>
};
struct
is_same
{
enum
{
value
=
0
};
// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
};
class
IsZeroInt
:
public
ArgVisitor
<
IsZeroInt
,
bool
>
{
template
<
typename
T
>
public:
struct
is_same
<
T
,
T
>
{
template
<
typename
T
>
enum
{
value
=
1
};
bool
visit_any_int
(
T
value
)
};
{
return
value
==
0
;
// An argument visitor that converts an integer argument to T for printf,
}
// if T is an integral type. If T is void, the argument is converted to
};
// corresponding signed or unsigned type depending on the type specifier:
// 'd' and 'i' - signed, other - unsigned)
template
<
typename
T
,
typename
U
>
template
<
typename
T
=
void
>
struct
is_same
class
ArgConverter
:
public
ArgVisitor
<
ArgConverter
<
T
>
,
void
>
{
{
private:
enum
{
value
=
0
};
internal
::
Arg
&
arg_
;
};
wchar_t
type_
;
template
<
typename
T
>
FMT_DISALLOW_COPY_AND_ASSIGN
(
ArgConverter
);
struct
is_same
<
T
,
T
>
{
public:
enum
{
value
=
1
};
ArgConverter
(
internal
::
Arg
&
arg
,
wchar_t
type
)
};
:
arg_
(
arg
),
type_
(
type
)
{}
// An argument visitor that converts an integer argument to T for printf,
void
visit_bool
(
bool
value
)
{
// if T is an integral type. If T is void, the argument is converted to
if
(
type_
!=
's'
)
// corresponding signed or unsigned type depending on the type specifier:
visit_any_int
(
value
);
// 'd' and 'i' - signed, other - unsigned)
}
template
<
typename
T
=
void
>
class
ArgConverter
:
public
ArgVisitor
<
ArgConverter
<
T
>
,
void
>
template
<
typename
U
>
{
void
visit_any_int
(
U
value
)
{
private:
bool
is_signed
=
type_
==
'd'
||
type_
==
'i'
;
internal
::
Arg
&
arg_
;
using
internal
::
Arg
;
wchar_t
type_
;
typedef
typename
internal
::
Conditional
<
is_same
<
T
,
void
>::
value
,
U
,
T
>::
type
TargetType
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
ArgConverter
);
if
(
sizeof
(
TargetType
)
<=
sizeof
(
int
))
{
// Extra casts are used to silence warnings.
public:
if
(
is_signed
)
{
ArgConverter
(
internal
::
Arg
&
arg
,
wchar_t
type
)
arg_
.
type
=
Arg
::
INT
;
:
arg_
(
arg
),
type_
(
type
)
{}
arg_
.
int_value
=
static_cast
<
int
>
(
static_cast
<
TargetType
>
(
value
));
}
void
visit_bool
(
bool
value
)
else
{
{
arg_
.
type
=
Arg
::
UINT
;
if
(
type_
!=
's'
)
typedef
typename
internal
::
MakeUnsigned
<
TargetType
>::
Type
Unsigned
;
visit_any_int
(
value
);
arg_
.
uint_value
=
static_cast
<
unsigned
>
(
static_cast
<
Unsigned
>
(
value
));
}
}
}
template
<
typename
U
>
else
{
void
visit_any_int
(
U
value
)
if
(
is_signed
)
{
{
arg_
.
type
=
Arg
::
LONG_LONG
;
bool
is_signed
=
type_
==
'd'
||
type_
==
'i'
;
// glibc's printf doesn't sign extend arguments of smaller types:
using
internal
::
Arg
;
// std::printf("%lld", -42); // prints "4294967254"
typedef
typename
internal
::
Conditional
<
// but we don't have to do the same because it's a UB.
is_same
<
T
,
void
>::
value
,
U
,
T
>::
type
TargetType
;
arg_
.
long_long_value
=
static_cast
<
LongLong
>
(
value
);
if
(
sizeof
(
TargetType
)
<=
sizeof
(
int
))
}
{
else
{
// Extra casts are used to silence warnings.
arg_
.
type
=
Arg
::
ULONG_LONG
;
if
(
is_signed
)
arg_
.
ulong_long_value
=
{
static_cast
<
typename
internal
::
MakeUnsigned
<
U
>::
Type
>
(
value
);
arg_
.
type
=
Arg
::
INT
;
}
arg_
.
int_value
=
static_cast
<
int
>
(
static_cast
<
TargetType
>
(
value
));
}
}
}
else
};
{
arg_
.
type
=
Arg
::
UINT
;
// Converts an integer argument to char for printf.
typedef
typename
internal
::
MakeUnsigned
<
TargetType
>::
Type
Unsigned
;
class
CharConverter
:
public
ArgVisitor
<
CharConverter
,
void
>
{
arg_
.
uint_value
=
static_cast
<
unsigned
>
(
static_cast
<
Unsigned
>
(
value
));
private:
}
internal
::
Arg
&
arg_
;
}
else
FMT_DISALLOW_COPY_AND_ASSIGN
(
CharConverter
);
{
if
(
is_signed
)
public:
{
explicit
CharConverter
(
internal
::
Arg
&
arg
)
:
arg_
(
arg
)
{}
arg_
.
type
=
Arg
::
LONG_LONG
;
// glibc's printf doesn't sign extend arguments of smaller types:
template
<
typename
T
>
// std::printf("%lld", -42); // prints "4294967254"
void
visit_any_int
(
T
value
)
{
// but we don't have to do the same because it's a UB.
arg_
.
type
=
internal
::
Arg
::
CHAR
;
arg_
.
long_long_value
=
static_cast
<
LongLong
>
(
value
);
arg_
.
int_value
=
static_cast
<
char
>
(
value
);
}
}
else
};
{
arg_
.
type
=
Arg
::
ULONG_LONG
;
// Checks if an argument is a valid printf width specifier and sets
arg_
.
ulong_long_value
=
// left alignment if it is negative.
static_cast
<
typename
internal
::
MakeUnsigned
<
U
>::
Type
>
(
value
);
class
WidthHandler
:
public
ArgVisitor
<
WidthHandler
,
unsigned
>
{
}
private:
}
FormatSpec
&
spec_
;
}
};
FMT_DISALLOW_COPY_AND_ASSIGN
(
WidthHandler
);
// Converts an integer argument to char for printf.
public:
class
CharConverter
:
public
ArgVisitor
<
CharConverter
,
void
>
explicit
WidthHandler
(
FormatSpec
&
spec
)
:
spec_
(
spec
)
{}
{
private:
void
report_unhandled_arg
()
{
internal
::
Arg
&
arg_
;
FMT_THROW
(
FormatError
(
"width is not integer"
));
}
FMT_DISALLOW_COPY_AND_ASSIGN
(
CharConverter
);
template
<
typename
T
>
public:
unsigned
visit_any_int
(
T
value
)
{
explicit
CharConverter
(
internal
::
Arg
&
arg
)
:
arg_
(
arg
)
{}
typedef
typename
internal
::
IntTraits
<
T
>::
MainType
UnsignedType
;
UnsignedType
width
=
static_cast
<
UnsignedType
>
(
value
);
template
<
typename
T
>
if
(
internal
::
is_negative
(
value
))
{
void
visit_any_int
(
T
value
)
spec_
.
align_
=
ALIGN_LEFT
;
{
width
=
0
-
width
;
arg_
.
type
=
internal
::
Arg
::
CHAR
;
}
arg_
.
int_value
=
static_cast
<
char
>
(
value
);
unsigned
int_max
=
std
::
numeric_limits
<
int
>::
max
();
}
if
(
width
>
int_max
)
};
FMT_THROW
(
FormatError
(
"number is too big"
));
return
static_cast
<
unsigned
>
(
width
);
// Checks if an argument is a valid printf width specifier and sets
}
// left alignment if it is negative.
};
class
WidthHandler
:
public
ArgVisitor
<
WidthHandler
,
unsigned
>
}
// namespace internal
{
private:
/**
FormatSpec
&
spec_
;
\rst
A ``printf`` argument formatter based on the `curiously recurring template
FMT_DISALLOW_COPY_AND_ASSIGN
(
WidthHandler
);
pattern <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_.
public:
To use `~fmt::BasicPrintfArgFormatter` define a subclass that implements some
explicit
WidthHandler
(
FormatSpec
&
spec
)
:
spec_
(
spec
)
{}
or all of the visit methods with the same signatures as the methods in
`~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`.
void
report_unhandled_arg
()
Pass the subclass as the *Impl* template parameter. When a formatting
{
function processes an argument, it will dispatch to a visit method
FMT_THROW
(
FormatError
(
"width is not integer"
));
specific to the argument type. For example, if the argument type is
}
``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass
will be called. If the subclass doesn't contain a method with this signature,
template
<
typename
T
>
then a corresponding method of `~fmt::BasicPrintfArgFormatter` or its
unsigned
visit_any_int
(
T
value
)
superclass will be called.
{
\endrst
typedef
typename
internal
::
IntTraits
<
T
>::
MainType
UnsignedType
;
*/
UnsignedType
width
=
static_cast
<
UnsignedType
>
(
value
);
template
<
typename
Impl
,
typename
Char
>
if
(
internal
::
is_negative
(
value
))
class
BasicPrintfArgFormatter
:
public
internal
::
ArgFormatterBase
<
Impl
,
Char
>
{
{
private:
spec_
.
align_
=
ALIGN_LEFT
;
void
write_null_pointer
()
{
width
=
0
-
width
;
this
->
spec
().
type_
=
0
;
}
this
->
write
(
"(nil)"
);
unsigned
int_max
=
std
::
numeric_limits
<
int
>::
max
();
}
if
(
width
>
int_max
)
FMT_THROW
(
FormatError
(
"number is too big"
));
typedef
internal
::
ArgFormatterBase
<
Impl
,
Char
>
Base
;
return
static_cast
<
unsigned
>
(
width
);
}
public:
};
/**
}
// namespace internal
\rst
Constructs an argument formatter object.
/**
*writer* is a reference to the output writer and *spec* contains format
\rst
specifier information for standard argument types.
A ``printf`` argument formatter based on the `curiously recurring template
\endrst
pattern <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_.
*/
BasicPrintfArgFormatter
(
BasicWriter
<
Char
>
&
writer
,
FormatSpec
&
spec
)
To use `~fmt::BasicPrintfArgFormatter` define a subclass that implements some
:
internal
::
ArgFormatterBase
<
Impl
,
Char
>
(
writer
,
spec
)
{}
or all of the visit methods with the same signatures as the methods in
`~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`.
/** Formats an argument of type ``bool``. */
Pass the subclass as the *Impl* template parameter. When a formatting
void
visit_bool
(
bool
value
)
{
function processes an argument, it will dispatch to a visit method
FormatSpec
&
fmt_spec
=
this
->
spec
();
specific to the argument type. For example, if the argument type is
if
(
fmt_spec
.
type_
!=
's'
)
``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass
return
this
->
visit_any_int
(
value
);
will be called. If the subclass doesn't contain a method with this signature,
fmt_spec
.
type_
=
0
;
then a corresponding method of `~fmt::BasicPrintfArgFormatter` or its
this
->
write
(
value
);
superclass will be called.
}
\endrst
*/
/** Formats a character. */
template
<
typename
Impl
,
typename
Char
>
void
visit_char
(
int
value
)
{
class
BasicPrintfArgFormatter
:
public
internal
::
ArgFormatterBase
<
Impl
,
Char
>
const
FormatSpec
&
fmt_spec
=
this
->
spec
();
{
BasicWriter
<
Char
>
&
w
=
this
->
writer
();
private:
if
(
fmt_spec
.
type_
&&
fmt_spec
.
type_
!=
'c'
)
void
write_null_pointer
()
w
.
write_int
(
value
,
fmt_spec
);
{
typedef
typename
BasicWriter
<
Char
>::
CharPtr
CharPtr
;
this
->
spec
().
type_
=
0
;
CharPtr
out
=
CharPtr
();
this
->
write
(
"(nil)"
);
if
(
fmt_spec
.
width_
>
1
)
{
}
Char
fill
=
' '
;
out
=
w
.
grow_buffer
(
fmt_spec
.
width_
);
typedef
internal
::
ArgFormatterBase
<
Impl
,
Char
>
Base
;
if
(
fmt_spec
.
align_
!=
ALIGN_LEFT
)
{
std
::
fill_n
(
out
,
fmt_spec
.
width_
-
1
,
fill
);
public:
out
+=
fmt_spec
.
width_
-
1
;
/**
}
\rst
else
{
Constructs an argument formatter object.
std
::
fill_n
(
out
+
1
,
fmt_spec
.
width_
-
1
,
fill
);
*writer* is a reference to the output writer and *spec* contains format
}
specifier information for standard argument types.
}
\endrst
else
{
*/
out
=
w
.
grow_buffer
(
1
);
BasicPrintfArgFormatter
(
BasicWriter
<
Char
>
&
writer
,
FormatSpec
&
spec
)
}
:
internal
::
ArgFormatterBase
<
Impl
,
Char
>
(
writer
,
spec
)
{}
*
out
=
static_cast
<
Char
>
(
value
);
}
/** Formats an argument of type ``bool``. */
void
visit_bool
(
bool
value
)
/** Formats a null-terminated C string. */
{
void
visit_cstring
(
const
char
*
value
)
{
FormatSpec
&
fmt_spec
=
this
->
spec
();
if
(
value
)
if
(
fmt_spec
.
type_
!=
's'
)
Base
::
visit_cstring
(
value
);
return
this
->
visit_any_int
(
value
);
else
if
(
this
->
spec
().
type_
==
'p'
)
fmt_spec
.
type_
=
0
;
write_null_pointer
();
this
->
write
(
value
);
else
}
this
->
write
(
"(null)"
);
}
/** Formats a character. */
void
visit_char
(
int
value
)
/** Formats a pointer. */
{
void
visit_pointer
(
const
void
*
value
)
{
const
FormatSpec
&
fmt_spec
=
this
->
spec
();
if
(
value
)
BasicWriter
<
Char
>
&
w
=
this
->
writer
();
return
Base
::
visit_pointer
(
value
);
if
(
fmt_spec
.
type_
&&
fmt_spec
.
type_
!=
'c'
)
this
->
spec
().
type_
=
0
;
w
.
write_int
(
value
,
fmt_spec
);
write_null_pointer
();
typedef
typename
BasicWriter
<
Char
>::
CharPtr
CharPtr
;
}
CharPtr
out
=
CharPtr
();
if
(
fmt_spec
.
width_
>
1
)
/** Formats an argument of a custom (user-defined) type. */
{
void
visit_custom
(
internal
::
Arg
::
CustomValue
c
)
{
Char
fill
=
' '
;
BasicFormatter
<
Char
>
formatter
(
ArgList
(),
this
->
writer
());
out
=
w
.
grow_buffer
(
fmt_spec
.
width_
);
const
Char
format_str
[]
=
{
'}'
,
0
};
if
(
fmt_spec
.
align_
!=
ALIGN_LEFT
)
const
Char
*
format
=
format_str
;
{
c
.
format
(
&
formatter
,
c
.
value
,
&
format
);
std
::
fill_n
(
out
,
fmt_spec
.
width_
-
1
,
fill
);
}
out
+=
fmt_spec
.
width_
-
1
;
};
}
else
/** The default printf argument formatter. */
{
template
<
typename
Char
>
std
::
fill_n
(
out
+
1
,
fmt_spec
.
width_
-
1
,
fill
);
class
PrintfArgFormatter
}
:
public
BasicPrintfArgFormatter
<
PrintfArgFormatter
<
Char
>
,
Char
>
{
}
public:
else
/** Constructs an argument formatter object. */
{
PrintfArgFormatter
(
BasicWriter
<
Char
>
&
w
,
FormatSpec
&
s
)
out
=
w
.
grow_buffer
(
1
);
:
BasicPrintfArgFormatter
<
PrintfArgFormatter
<
Char
>
,
Char
>
(
w
,
s
)
{}
}
};
*
out
=
static_cast
<
Char
>
(
value
);
}
/** This template formats data and writes the output to a writer. */
template
<
typename
Char
,
typename
ArgFormatter
=
PrintfArgFormatter
<
Char
>
>
/** Formats a null-terminated C string. */
class
PrintfFormatter
:
private
internal
::
FormatterBase
{
void
visit_cstring
(
const
char
*
value
)
private:
{
BasicWriter
<
Char
>
&
writer_
;
if
(
value
)
Base
::
visit_cstring
(
value
);
void
parse_flags
(
FormatSpec
&
spec
,
const
Char
*&
s
);
else
if
(
this
->
spec
().
type_
==
'p'
)
write_null_pointer
();
// Returns the argument with specified index or, if arg_index is equal
else
// to the maximum unsigned value, the next argument.
this
->
write
(
"(null)"
);
internal
::
Arg
get_arg
(
}
const
Char
*
s
,
unsigned
arg_index
=
(
std
::
numeric_limits
<
unsigned
>::
max
)());
/** Formats a pointer. */
void
visit_pointer
(
const
void
*
value
)
// Parses argument index, flags and width and returns the argument index.
{
unsigned
parse_header
(
const
Char
*&
s
,
FormatSpec
&
spec
);
if
(
value
)
return
Base
::
visit_pointer
(
value
);
public:
this
->
spec
().
type_
=
0
;
/**
write_null_pointer
();
\rst
}
Constructs a ``PrintfFormatter`` object. References to the arguments and
the writer are stored in the formatter object so make sure they have
/** Formats an argument of a custom (user-defined) type. */
appropriate lifetimes.
void
visit_custom
(
internal
::
Arg
::
CustomValue
c
)
\endrst
{
*/
BasicFormatter
<
Char
>
formatter
(
ArgList
(),
this
->
writer
());
explicit
PrintfFormatter
(
const
ArgList
&
args
,
BasicWriter
<
Char
>
&
w
)
const
Char
format_str
[]
=
{
'}'
,
0
};
:
FormatterBase
(
args
),
writer_
(
w
)
{}
const
Char
*
format
=
format_str
;
c
.
format
(
&
formatter
,
c
.
value
,
&
format
);
/** Formats stored arguments and writes the output to the writer. */
}
FMT_API
void
format
(
BasicCStringRef
<
Char
>
format_str
);
};
};
/** The default printf argument formatter. */
template
<
typename
Char
,
typename
AF
>
template
<
typename
Char
>
void
PrintfFormatter
<
Char
,
AF
>::
parse_flags
(
FormatSpec
&
spec
,
const
Char
*&
s
)
{
class
PrintfArgFormatter
for
(;;)
{
:
public
BasicPrintfArgFormatter
<
PrintfArgFormatter
<
Char
>
,
Char
>
switch
(
*
s
++
)
{
{
case
'-'
:
public:
spec
.
align_
=
ALIGN_LEFT
;
/** Constructs an argument formatter object. */
break
;
PrintfArgFormatter
(
BasicWriter
<
Char
>
&
w
,
FormatSpec
&
s
)
case
'+'
:
:
BasicPrintfArgFormatter
<
PrintfArgFormatter
<
Char
>
,
Char
>
(
w
,
s
)
{}
spec
.
flags_
|=
SIGN_FLAG
|
PLUS_FLAG
;
};
break
;
case
'0'
:
/** This template formats data and writes the output to a writer. */
spec
.
fill_
=
'0'
;
template
<
typename
Char
,
typename
ArgFormatter
=
PrintfArgFormatter
<
Char
>
>
break
;
class
PrintfFormatter
:
private
internal
::
FormatterBase
case
' '
:
{
spec
.
flags_
|=
SIGN_FLAG
;
private:
break
;
BasicWriter
<
Char
>
&
writer_
;
case
'#'
:
spec
.
flags_
|=
HASH_FLAG
;
void
parse_flags
(
FormatSpec
&
spec
,
const
Char
*&
s
);
break
;
default:
// Returns the argument with specified index or, if arg_index is equal
--
s
;
// to the maximum unsigned value, the next argument.
return
;
internal
::
Arg
get_arg
(
}
const
Char
*
s
,
}
unsigned
arg_index
=
(
std
::
numeric_limits
<
unsigned
>::
max
)());
}
// Parses argument index, flags and width and returns the argument index.
template
<
typename
Char
,
typename
AF
>
unsigned
parse_header
(
const
Char
*&
s
,
FormatSpec
&
spec
);
internal
::
Arg
PrintfFormatter
<
Char
,
AF
>::
get_arg
(
const
Char
*
s
,
unsigned
arg_index
)
{
public:
(
void
)
s
;
/**
const
char
*
error
=
0
;
\rst
internal
::
Arg
arg
=
arg_index
==
std
::
numeric_limits
<
unsigned
>::
max
()
?
Constructs a ``PrintfFormatter`` object. References to the arguments and
next_arg
(
error
)
:
FormatterBase
::
get_arg
(
arg_index
-
1
,
error
);
the writer are stored in the formatter object so make sure they have
if
(
error
)
appropriate lifetimes.
FMT_THROW
(
FormatError
(
!*
s
?
"invalid format string"
:
error
));
\endrst
return
arg
;
*/
}
explicit
PrintfFormatter
(
const
ArgList
&
args
,
BasicWriter
<
Char
>
&
w
)
:
FormatterBase
(
args
),
writer_
(
w
)
{}
template
<
typename
Char
,
typename
AF
>
unsigned
PrintfFormatter
<
Char
,
AF
>::
parse_header
(
/** Formats stored arguments and writes the output to the writer. */
const
Char
*&
s
,
FormatSpec
&
spec
)
{
FMT_API
void
format
(
BasicCStringRef
<
Char
>
format_str
);
unsigned
arg_index
=
std
::
numeric_limits
<
unsigned
>::
max
();
};
Char
c
=
*
s
;
if
(
c
>=
'0'
&&
c
<=
'9'
)
{
template
<
typename
Char
,
typename
AF
>
// Parse an argument index (if followed by '$') or a width possibly
void
PrintfFormatter
<
Char
,
AF
>::
parse_flags
(
FormatSpec
&
spec
,
const
Char
*&
s
)
// preceded with '0' flag(s).
{
unsigned
value
=
internal
::
parse_nonnegative_int
(
s
);
for
(;;)
if
(
*
s
==
'$'
)
{
// value is an argument index
{
++
s
;
switch
(
*
s
++
)
arg_index
=
value
;
{
}
case
'-'
:
else
{
spec
.
align_
=
ALIGN_LEFT
;
if
(
c
==
'0'
)
break
;
spec
.
fill_
=
'0'
;
case
'+'
:
if
(
value
!=
0
)
{
spec
.
flags_
|=
SIGN_FLAG
|
PLUS_FLAG
;
// Nonzero value means that we parsed width and don't need to
break
;
// parse it or flags again, so return now.
case
'0'
:
spec
.
width_
=
value
;
spec
.
fill_
=
'0'
;
return
arg_index
;
break
;
}
case
' '
:
}
spec
.
flags_
|=
SIGN_FLAG
;
}
break
;
parse_flags
(
spec
,
s
);
case
'#'
:
// Parse width.
spec
.
flags_
|=
HASH_FLAG
;
if
(
*
s
>=
'0'
&&
*
s
<=
'9'
)
{
break
;
spec
.
width_
=
internal
::
parse_nonnegative_int
(
s
);
default:
}
--
s
;
else
if
(
*
s
==
'*'
)
{
return
;
++
s
;
}
spec
.
width_
=
internal
::
WidthHandler
(
spec
).
visit
(
get_arg
(
s
));
}
}
}
return
arg_index
;
}
template
<
typename
Char
,
typename
AF
>
internal
::
Arg
PrintfFormatter
<
Char
,
AF
>::
get_arg
(
const
Char
*
s
,
template
<
typename
Char
,
typename
AF
>
unsigned
arg_index
)
void
PrintfFormatter
<
Char
,
AF
>::
format
(
BasicCStringRef
<
Char
>
format_str
)
{
{
const
Char
*
start
=
format_str
.
c_str
();
(
void
)
s
;
const
Char
*
s
=
start
;
const
char
*
error
=
0
;
while
(
*
s
)
{
internal
::
Arg
arg
=
arg_index
==
std
::
numeric_limits
<
unsigned
>::
max
()
?
Char
c
=
*
s
++
;
next_arg
(
error
)
:
FormatterBase
::
get_arg
(
arg_index
-
1
,
error
);
if
(
c
!=
'%'
)
continue
;
if
(
error
)
if
(
*
s
==
c
)
{
FMT_THROW
(
FormatError
(
!*
s
?
"invalid format string"
:
error
));
write
(
writer_
,
start
,
s
);
return
arg
;
start
=
++
s
;
}
continue
;
}
template
<
typename
Char
,
typename
AF
>
write
(
writer_
,
start
,
s
-
1
);
unsigned
PrintfFormatter
<
Char
,
AF
>::
parse_header
(
const
Char
*&
s
,
FormatSpec
&
spec
)
FormatSpec
spec
;
{
spec
.
align_
=
ALIGN_RIGHT
;
unsigned
arg_index
=
std
::
numeric_limits
<
unsigned
>::
max
();
Char
c
=
*
s
;
// Parse argument index, flags and width.
if
(
c
>=
'0'
&&
c
<=
'9'
)
unsigned
arg_index
=
parse_header
(
s
,
spec
);
{
// Parse an argument index (if followed by '$') or a width possibly
// Parse precision.
// preceded with '0' flag(s).
if
(
*
s
==
'.'
)
{
unsigned
value
=
internal
::
parse_nonnegative_int
(
s
);
++
s
;
if
(
*
s
==
'$'
)
// value is an argument index
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
{
{
spec
.
precision_
=
static_cast
<
int
>
(
internal
::
parse_nonnegative_int
(
s
));
++
s
;
}
arg_index
=
value
;
else
if
(
*
s
==
'*'
)
{
}
++
s
;
else
spec
.
precision_
=
internal
::
PrecisionHandler
().
visit
(
get_arg
(
s
));
{
}
if
(
c
==
'0'
)
}
spec
.
fill_
=
'0'
;
if
(
value
!=
0
)
using
internal
::
Arg
;
{
Arg
arg
=
get_arg
(
s
,
arg_index
);
// Nonzero value means that we parsed width and don't need to
if
(
spec
.
flag
(
HASH_FLAG
)
&&
internal
::
IsZeroInt
().
visit
(
arg
))
// parse it or flags again, so return now.
spec
.
flags_
&=
~
internal
::
to_unsigned
<
int
>
(
HASH_FLAG
);
spec
.
width_
=
value
;
if
(
spec
.
fill_
==
'0'
)
{
return
arg_index
;
if
(
arg
.
type
<=
Arg
::
LAST_NUMERIC_TYPE
)
}
spec
.
align_
=
ALIGN_NUMERIC
;
}
else
}
spec
.
fill_
=
' '
;
// Ignore '0' flag for non-numeric types.
parse_flags
(
spec
,
s
);
}
// Parse width.
if
(
*
s
>=
'0'
&&
*
s
<=
'9'
)
// Parse length and convert the argument to the required type.
{
using
internal
::
ArgConverter
;
spec
.
width_
=
internal
::
parse_nonnegative_int
(
s
);
switch
(
*
s
++
)
{
}
case
'h'
:
else
if
(
*
s
==
'*'
)
if
(
*
s
==
'h'
)
{
ArgConverter
<
signed
char
>
(
arg
,
*++
s
).
visit
(
arg
);
++
s
;
else
spec
.
width_
=
internal
::
WidthHandler
(
spec
).
visit
(
get_arg
(
s
));
ArgConverter
<
short
>
(
arg
,
*
s
).
visit
(
arg
);
}
break
;
return
arg_index
;
case
'l'
:
}
if
(
*
s
==
'l'
)
ArgConverter
<
fmt
::
LongLong
>
(
arg
,
*++
s
).
visit
(
arg
);
template
<
typename
Char
,
typename
AF
>
else
void
PrintfFormatter
<
Char
,
AF
>::
format
(
BasicCStringRef
<
Char
>
format_str
)
ArgConverter
<
long
>
(
arg
,
*
s
).
visit
(
arg
);
{
break
;
const
Char
*
start
=
format_str
.
c_str
();
case
'j'
:
const
Char
*
s
=
start
;
ArgConverter
<
intmax_t
>
(
arg
,
*
s
).
visit
(
arg
);
while
(
*
s
)
break
;
{
case
'z'
:
Char
c
=
*
s
++
;
ArgConverter
<
std
::
size_t
>
(
arg
,
*
s
).
visit
(
arg
);
if
(
c
!=
'%'
)
continue
;
break
;
if
(
*
s
==
c
)
case
't'
:
{
ArgConverter
<
std
::
ptrdiff_t
>
(
arg
,
*
s
).
visit
(
arg
);
write
(
writer_
,
start
,
s
);
break
;
start
=
++
s
;
case
'L'
:
continue
;
// printf produces garbage when 'L' is omitted for long double, no
}
// need to do the same.
write
(
writer_
,
start
,
s
-
1
);
break
;
default:
FormatSpec
spec
;
--
s
;
spec
.
align_
=
ALIGN_RIGHT
;
ArgConverter
<
void
>
(
arg
,
*
s
).
visit
(
arg
);
}
// Parse argument index, flags and width.
unsigned
arg_index
=
parse_header
(
s
,
spec
);
// Parse type.
if
(
!*
s
)
// Parse precision.
FMT_THROW
(
FormatError
(
"invalid format string"
));
if
(
*
s
==
'.'
)
spec
.
type_
=
static_cast
<
char
>
(
*
s
++
);
{
if
(
arg
.
type
<=
Arg
::
LAST_INTEGER_TYPE
)
{
++
s
;
// Normalize type.
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
switch
(
spec
.
type_
)
{
{
case
'i'
:
spec
.
precision_
=
static_cast
<
int
>
(
internal
::
parse_nonnegative_int
(
s
));
case
'u'
:
}
spec
.
type_
=
'd'
;
else
if
(
*
s
==
'*'
)
break
;
{
case
'c'
:
++
s
;
// TODO: handle wchar_t
spec
.
precision_
=
internal
::
PrecisionHandler
().
visit
(
get_arg
(
s
));
internal
::
CharConverter
(
arg
).
visit
(
arg
);
}
break
;
}
}
}
using
internal
::
Arg
;
Arg
arg
=
get_arg
(
s
,
arg_index
);
start
=
s
;
if
(
spec
.
flag
(
HASH_FLAG
)
&&
internal
::
IsZeroInt
().
visit
(
arg
))
spec
.
flags_
&=
~
internal
::
to_unsigned
<
int
>
(
HASH_FLAG
);
// Format argument.
if
(
spec
.
fill_
==
'0'
)
AF
(
writer_
,
spec
).
visit
(
arg
);
{
}
if
(
arg
.
type
<=
Arg
::
LAST_NUMERIC_TYPE
)
write
(
writer_
,
start
,
s
);
spec
.
align_
=
ALIGN_NUMERIC
;
}
else
spec
.
fill_
=
' '
;
// Ignore '0' flag for non-numeric types.
template
<
typename
Char
>
}
void
printf
(
BasicWriter
<
Char
>
&
w
,
BasicCStringRef
<
Char
>
format
,
ArgList
args
)
{
PrintfFormatter
<
Char
>
(
args
,
w
).
format
(
format
);
// Parse length and convert the argument to the required type.
}
using
internal
::
ArgConverter
;
switch
(
*
s
++
)
/**
{
\rst
case
'h'
:
Formats arguments and returns the result as a string.
if
(
*
s
==
'h'
)
ArgConverter
<
signed
char
>
(
arg
,
*++
s
).
visit
(
arg
);
**Example**::
else
ArgConverter
<
short
>
(
arg
,
*
s
).
visit
(
arg
);
std::string message = fmt::sprintf("The answer is %d", 42);
break
;
\endrst
case
'l'
:
*/
if
(
*
s
==
'l'
)
inline
std
::
string
sprintf
(
CStringRef
format
,
ArgList
args
)
{
ArgConverter
<
fmt
::
LongLong
>
(
arg
,
*++
s
).
visit
(
arg
);
MemoryWriter
w
;
else
printf
(
w
,
format
,
args
);
ArgConverter
<
long
>
(
arg
,
*
s
).
visit
(
arg
);
return
w
.
str
();
break
;
}
case
'j'
:
FMT_VARIADIC
(
std
::
string
,
sprintf
,
CStringRef
)
ArgConverter
<
intmax_t
>
(
arg
,
*
s
).
visit
(
arg
);
break
;
inline
std
::
wstring
sprintf
(
WCStringRef
format
,
ArgList
args
)
{
case
'z'
:
WMemoryWriter
w
;
ArgConverter
<
std
::
size_t
>
(
arg
,
*
s
).
visit
(
arg
);
printf
(
w
,
format
,
args
);
break
;
return
w
.
str
();
case
't'
:
}
ArgConverter
<
std
::
ptrdiff_t
>
(
arg
,
*
s
).
visit
(
arg
);
FMT_VARIADIC_W
(
std
::
wstring
,
sprintf
,
WCStringRef
)
break
;
case
'L'
:
/**
// printf produces garbage when 'L' is omitted for long double, no
\rst
// need to do the same.
Prints formatted data to the file *f*.
break
;
default:
**Example**::
--
s
;
ArgConverter
<
void
>
(
arg
,
*
s
).
visit
(
arg
);
fmt::fprintf(stderr, "Don't %s!", "panic");
}
\endrst
*/
// Parse type.
FMT_API
int
fprintf
(
std
::
FILE
*
f
,
CStringRef
format
,
ArgList
args
);
if
(
!*
s
)
FMT_VARIADIC
(
int
,
fprintf
,
std
::
FILE
*
,
CStringRef
)
FMT_THROW
(
FormatError
(
"invalid format string"
));
spec
.
type_
=
static_cast
<
char
>
(
*
s
++
);
/**
if
(
arg
.
type
<=
Arg
::
LAST_INTEGER_TYPE
)
\rst
{
Prints formatted data to ``stdout``.
// Normalize type.
switch
(
spec
.
type_
)
**Example**::
{
case
'i'
:
fmt::printf("Elapsed time: %.2f seconds", 1.23);
case
'u'
:
\endrst
spec
.
type_
=
'd'
;
*/
break
;
inline
int
printf
(
CStringRef
format
,
ArgList
args
)
{
case
'c'
:
return
fprintf
(
stdout
,
format
,
args
);
// TODO: handle wchar_t
}
internal
::
CharConverter
(
arg
).
visit
(
arg
);
FMT_VARIADIC
(
int
,
printf
,
CStringRef
)
break
;
}
/**
}
\rst
Prints formatted data to the stream *os*.
start
=
s
;
**Example**::
// Format argument.
AF
(
writer_
,
spec
).
visit
(
arg
);
fprintf(cerr, "Don't %s!", "panic");
}
\endrst
write
(
writer_
,
start
,
s
);
*/
}
inline
int
fprintf
(
std
::
ostream
&
os
,
CStringRef
format_str
,
ArgList
args
)
{
MemoryWriter
w
;
template
<
typename
Char
>
printf
(
w
,
format_str
,
args
);
void
printf
(
BasicWriter
<
Char
>
&
w
,
BasicCStringRef
<
Char
>
format
,
ArgList
args
)
internal
::
write
(
os
,
w
);
{
return
static_cast
<
int
>
(
w
.
size
());
PrintfFormatter
<
Char
>
(
args
,
w
).
format
(
format
);
}
}
FMT_VARIADIC
(
int
,
fprintf
,
std
::
ostream
&
,
CStringRef
)
}
// namespace fmt
/**
\rst
Formats arguments and returns the result as a string.
**Example**::
std::string message = fmt::sprintf("The answer is %d", 42);
\endrst
*/
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
)
{
WMemoryWriter
w
;
printf
(
w
,
format
,
args
);
return
w
.
str
();
}
FMT_VARIADIC_W
(
std
::
wstring
,
sprintf
,
WCStringRef
)
/**
\rst
Prints formatted data to the file *f*.
**Example**::
fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst
*/
FMT_API
int
fprintf
(
std
::
FILE
*
f
,
CStringRef
format
,
ArgList
args
);
FMT_VARIADIC
(
int
,
fprintf
,
std
::
FILE
*
,
CStringRef
)
/**
\rst
Prints formatted data to ``stdout``.
**Example**::
fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst
*/
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_
#endif // FMT_PRINTF_H_
\ No newline at end of file
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