Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
F
fmt
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
fmt
Commits
d705d516
Commit
d705d516
authored
Dec 29, 2016
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Parameterize basic_format_arg on context (#442)
parent
422236af
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
105 additions
and
100 deletions
+105
-100
fmt/format.cc
fmt/format.cc
+4
-2
fmt/format.h
fmt/format.h
+70
-67
fmt/printf.h
fmt/printf.h
+24
-25
test/format-impl-test.cc
test/format-impl-test.cc
+2
-1
test/util-test.cc
test/util-test.cc
+5
-5
No files found.
fmt/format.cc
View file @
d705d516
...
...
@@ -458,7 +458,7 @@ template struct internal::BasicData<void>;
template
void
internal
::
FixedBuffer
<
char
>
::
grow
(
std
::
size_t
);
template
void
internal
::
ArgMap
<
char
>
::
init
(
const
format_args
&
args
);
template
void
internal
::
ArgMap
<
format_context
>
::
init
(
const
format_args
&
args
);
template
void
printf_context
<
char
>
::
format
(
Writer
&
writer
);
...
...
@@ -472,9 +472,11 @@ template int internal::CharTraits<char>::format_float(
// Explicit instantiations for wchar_t.
template
class
basic_format_context
<
wchar_t
>;
template
void
internal
::
FixedBuffer
<
wchar_t
>
::
grow
(
std
::
size_t
);
template
void
internal
::
ArgMap
<
w
char_
t
>
::
init
(
const
wformat_args
&
args
);
template
void
internal
::
ArgMap
<
w
format_contex
t
>
::
init
(
const
wformat_args
&
args
);
template
void
printf_context
<
wchar_t
>
::
format
(
WWriter
&
writer
);
...
...
fmt/format.h
View file @
d705d516
...
...
@@ -230,10 +230,9 @@ typedef __int64 intmax_t;
# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
#endif
// Some compilers masquerade as both MSVC and GCC-likes or
// otherwise support __builtin_clz and __builtin_clzll, so
// only define FMT_BUILTIN_CLZ using the MSVC intrinsics
// if the clz and clzll builtins are not available.
// Some compilers masquerade as both MSVC and GCC-likes or otherwise support
// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
// MSVC intrinsics if the clz and clzll builtins are not available.
#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL)
# include <intrin.h> // _BitScanReverse, _BitScanReverse64
...
...
@@ -371,7 +370,7 @@ class BasicWriter;
typedef
BasicWriter
<
char
>
Writer
;
typedef
BasicWriter
<
wchar_t
>
WWriter
;
template
<
typename
C
har
>
template
<
typename
C
ontext
>
class
basic_format_arg
;
template
<
typename
Char
>
...
...
@@ -1331,11 +1330,11 @@ class MakeValue : public Value<typename Context::char_type> {
}
};
template
<
typename
C
har
>
template
<
typename
C
ontext
>
class
ArgMap
;
template
<
typename
Context
,
typename
T
>
basic_format_arg
<
typename
Context
::
char_type
>
make_arg
(
const
T
&
value
);
basic_format_arg
<
Context
>
make_arg
(
const
T
&
value
);
}
// namespace internal
struct
monostate
{};
...
...
@@ -1345,25 +1344,25 @@ class basic_format_args;
// A formatting argument. It is a trivially copyable/constructible type to
// allow storage in internal::MemoryBuffer.
template
<
typename
C
har
>
template
<
typename
C
ontext
>
class
basic_format_arg
{
private:
typedef
typename
Context
::
char_type
Char
;
internal
::
Value
<
Char
>
value_
;
internal
::
Type
type_
;
template
<
typename
Context
,
typename
T
>
friend
basic_format_arg
<
typename
Context
::
char_type
>
internal
::
make_arg
(
const
T
&
value
);
template
<
typename
ContextType
,
typename
T
>
friend
basic_format_arg
<
ContextType
>
internal
::
make_arg
(
const
T
&
value
);
template
<
typename
Visitor
,
typename
C
har
Type
>
template
<
typename
Visitor
,
typename
C
ontext
Type
>
friend
typename
std
::
result_of
<
Visitor
(
int
)
>::
type
visit
(
Visitor
&&
vis
,
basic_format_arg
<
C
har
Type
>
arg
);
visit
(
Visitor
&&
vis
,
basic_format_arg
<
C
ontext
Type
>
arg
);
template
<
typename
Context
,
typename
CharType
>
template
<
typename
Context
Type
,
typename
CharType
>
friend
class
basic_format_args
;
template
<
typename
CharType
>
friend
class
internal
::
ArgMap
;
friend
class
internal
::
ArgMap
<
Context
>
;
public:
basic_format_arg
()
:
type_
(
internal
::
NONE
)
{}
...
...
@@ -1385,8 +1384,8 @@ class basic_format_arg {
}
};
typedef
basic_format_arg
<
char
>
format_arg
;
typedef
basic_format_arg
<
w
char_
t
>
wformat_arg
;
typedef
basic_format_arg
<
format_context
>
format_arg
;
typedef
basic_format_arg
<
w
format_contex
t
>
wformat_arg
;
/**
\rst
...
...
@@ -1395,9 +1394,10 @@ typedef basic_format_arg<wchar_t> wformat_arg;
``vis(value)`` will be called with the value of type ``double``.
\endrst
*/
template
<
typename
Visitor
,
typename
C
har
>
template
<
typename
Visitor
,
typename
C
ontext
>
typename
std
::
result_of
<
Visitor
(
int
)
>::
type
visit
(
Visitor
&&
vis
,
basic_format_arg
<
Char
>
arg
)
{
visit
(
Visitor
&&
vis
,
basic_format_arg
<
Context
>
arg
)
{
typedef
typename
Context
::
char_type
Char
;
switch
(
arg
.
type_
)
{
case
internal
:
:
NONE
:
return
vis
(
monostate
());
...
...
@@ -1438,8 +1438,8 @@ typename std::result_of<Visitor(int)>::type
namespace
internal
{
template
<
typename
Context
,
typename
T
>
basic_format_arg
<
typename
Context
::
char_type
>
make_arg
(
const
T
&
value
)
{
basic_format_arg
<
typename
Context
::
char_type
>
arg
;
basic_format_arg
<
Context
>
make_arg
(
const
T
&
value
)
{
basic_format_arg
<
Context
>
arg
;
arg
.
type_
=
internal
::
type
<
T
>
();
arg
.
value_
=
internal
::
MakeValue
<
Context
>
(
value
);
return
arg
;
...
...
@@ -1489,14 +1489,15 @@ void format_value(BasicWriter<Char> &, const T &, Formatter &, const Char *) {
"an overload of format_arg."
);
}
template
<
typename
Char
>
struct
NamedArg
:
basic_format_arg
<
Char
>
{
template
<
typename
Context
>
struct
NamedArg
:
basic_format_arg
<
Context
>
{
typedef
typename
Context
::
char_type
Char
;
BasicStringRef
<
Char
>
name
;
template
<
typename
T
>
NamedArg
(
BasicStringRef
<
Char
>
argname
,
const
T
&
value
)
:
basic_format_arg
<
Char
>
(
make_arg
<
basic_format_context
<
Char
>
>
(
value
)),
name
(
argname
)
{}
:
basic_format_arg
<
Context
>
(
make_arg
<
Context
>
(
value
)),
name
(
argname
)
{}
};
class
RuntimeError
:
public
std
::
runtime_error
{
...
...
@@ -1524,8 +1525,7 @@ inline typename std::enable_if<
}
template
<
bool
IS_PACKED
,
typename
Context
,
typename
T
>
inline
typename
std
::
enable_if
<
!
IS_PACKED
,
basic_format_arg
<
typename
Context
::
char_type
>>::
type
inline
typename
std
::
enable_if
<!
IS_PACKED
,
basic_format_arg
<
Context
>>::
type
make_arg
(
const
T
&
value
)
{
return
make_arg
<
Context
>
(
value
);
}
...
...
@@ -1542,7 +1542,7 @@ class format_arg_store {
typedef
typename
Context
::
char_type
char_type
;
typedef
typename
std
::
conditional
<
IS_PACKED
,
internal
::
Value
<
char_type
>
,
basic_format_arg
<
char_type
>>::
type
value_type
;
internal
::
Value
<
char_type
>
,
basic_format_arg
<
Context
>>::
type
value_type
;
// If the arguments are not packed, add one more element to mark the end.
typedef
std
::
array
<
value_type
,
NUM_ARGS
+
(
IS_PACKED
?
0
:
1
)
>
Array
;
...
...
@@ -1574,7 +1574,7 @@ template <typename Context, typename Char>
class
basic_format_args
{
public:
typedef
unsigned
size_type
;
typedef
basic_format_arg
<
C
har
>
format_arg
;
typedef
basic_format_arg
<
C
ontext
>
format_arg
;
private:
// To reduce compiled code size per formatting function call, types of first
...
...
@@ -1597,7 +1597,7 @@ class basic_format_args {
(
types_
&
(
mask
<<
shift
))
>>
shift
);
}
friend
class
internal
::
ArgMap
<
C
har
>
;
friend
class
internal
::
ArgMap
<
C
ontext
>
;
void
set_data
(
const
internal
::
Value
<
Char
>
*
values
)
{
values_
=
values
;
}
void
set_data
(
const
format_arg
*
args
)
{
args_
=
args
;
}
...
...
@@ -1869,20 +1869,20 @@ inline StrFormatSpec<wchar_t> pad(
namespace
internal
{
template
<
typename
C
har
>
template
<
typename
C
ontext
>
class
ArgMap
{
private:
typedef
typename
Context
::
char_type
Char
;
typedef
std
::
vector
<
std
::
pair
<
fmt
::
BasicStringRef
<
Char
>
,
basic_format_arg
<
C
har
>
>
>
MapType
;
std
::
pair
<
fmt
::
BasicStringRef
<
Char
>
,
basic_format_arg
<
C
ontext
>
>
>
MapType
;
typedef
typename
MapType
::
value_type
Pair
;
MapType
map_
;
public:
template
<
typename
Context
>
void
init
(
const
basic_format_args
<
Context
,
Char
>
&
args
);
const
basic_format_arg
<
C
har
>
const
basic_format_arg
<
C
ontext
>
*
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
();
...
...
@@ -1894,12 +1894,11 @@ class ArgMap {
}
};
template
<
typename
Char
>
template
<
typename
Context
>
void
ArgMap
<
C
har
>::
init
(
const
basic_format_args
<
Context
,
Char
>
&
args
)
{
void
ArgMap
<
C
ontext
>::
init
(
const
basic_format_args
<
Context
,
Char
>
&
args
)
{
if
(
!
map_
.
empty
())
return
;
typedef
internal
::
NamedArg
<
C
har
>
NamedArg
;
typedef
internal
::
NamedArg
<
C
ontext
>
NamedArg
;
const
NamedArg
*
named_arg
=
0
;
bool
use_values
=
args
.
type
(
MAX_PACKED_ARGS
-
1
)
==
internal
::
NONE
;
...
...
@@ -2072,7 +2071,7 @@ class format_context_base {
int
next_arg_index_
;
protected:
typedef
basic_format_arg
<
C
har
>
format_arg
;
typedef
basic_format_arg
<
C
ontext
>
format_arg
;
format_context_base
(
const
Char
*
format_str
,
basic_format_args
<
Context
,
Char
>
args
)
...
...
@@ -2149,24 +2148,25 @@ class ArgFormatter : public internal::ArgFormatterBase<Char> {
template
<
typename
Char
>
class
basic_format_context
:
public
internal
::
format_context_base
<
Char
,
basic_format_context
<
Char
>>
{
public:
/** The character type for the output. */
typedef
Char
char_type
;
private:
internal
::
ArgMap
<
Char
>
map_
;
internal
::
ArgMap
<
basic_format_context
<
Char
>
>
map_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
basic_format_context
);
typedef
internal
::
format_context_base
<
Char
,
basic_format_context
<
Char
>>
Base
;
using
typename
Base
::
format_arg
;
typedef
typename
Base
::
format_arg
format_arg
;
using
Base
::
get_arg
;
// Checks if manual indexing is used and returns the argument with
// specified name.
basic_format_arg
<
Char
>
get_arg
(
BasicStringRef
<
Char
>
name
,
const
char
*&
error
);
format_arg
get_arg
(
BasicStringRef
<
Char
>
name
,
const
char
*&
error
);
public:
/** The character type for the output. */
typedef
Char
char_type
;
/**
\rst
Constructs a ``basic_format_context`` object. References to the arguments are
...
...
@@ -2178,7 +2178,7 @@ class basic_format_context :
:
Base
(
format_str
,
args
)
{}
// Parses argument id and returns corresponding argument.
basic_format_arg
<
Char
>
parse_arg_id
();
format_arg
parse_arg_id
();
using
Base
::
ptr
;
};
...
...
@@ -3274,21 +3274,23 @@ inline void format_decimal(char *&buffer, T value) {
\endrst
*/
template
<
typename
T
>
inline
internal
::
NamedArg
<
char
>
arg
(
StringRef
name
,
const
T
&
arg
)
{
return
internal
::
NamedArg
<
char
>
(
name
,
arg
);
inline
internal
::
NamedArg
<
format_context
>
arg
(
StringRef
name
,
const
T
&
arg
)
{
return
internal
::
NamedArg
<
format_context
>
(
name
,
arg
);
}
template
<
typename
T
>
inline
internal
::
NamedArg
<
w
char_
t
>
arg
(
WStringRef
name
,
const
T
&
arg
)
{
return
internal
::
NamedArg
<
w
char_
t
>
(
name
,
arg
);
inline
internal
::
NamedArg
<
w
format_contex
t
>
arg
(
WStringRef
name
,
const
T
&
arg
)
{
return
internal
::
NamedArg
<
w
format_contex
t
>
(
name
,
arg
);
}
// The following two functions are deleted intentionally to disable
// nested named arguments as in ``format("{}", arg("a", arg("b", 42)))``.
template
<
typename
Char
>
void
arg
(
StringRef
,
const
internal
::
NamedArg
<
Char
>&
)
FMT_DELETED_OR_UNDEFINED
;
template
<
typename
Char
>
void
arg
(
WStringRef
,
const
internal
::
NamedArg
<
Char
>&
)
FMT_DELETED_OR_UNDEFINED
;
template
<
typename
Context
>
void
arg
(
StringRef
,
const
internal
::
NamedArg
<
Context
>&
)
FMT_DELETED_OR_UNDEFINED
;
template
<
typename
Context
>
void
arg
(
WStringRef
,
const
internal
::
NamedArg
<
Context
>&
)
FMT_DELETED_OR_UNDEFINED
;
}
#if FMT_GCC_VERSION
...
...
@@ -3351,8 +3353,8 @@ struct IsUnsigned {
}
};
template
<
typename
Char
>
void
check_sign
(
const
Char
*&
s
,
const
basic_format_arg
<
C
har
>
&
arg
)
{
template
<
typename
Char
,
typename
Context
>
void
check_sign
(
const
Char
*&
s
,
const
basic_format_arg
<
C
ontext
>
&
arg
)
{
char
sign
=
static_cast
<
char
>
(
*
s
);
require_numeric_argument
(
arg
,
sign
);
if
(
visit
(
IsUnsigned
(),
arg
))
{
...
...
@@ -3425,25 +3427,27 @@ struct PrecisionHandler {
}
// namespace internal
template
<
typename
Char
>
inline
basic_format_arg
<
Char
>
basic_format_context
<
Char
>::
get_arg
(
inline
typename
basic_format_context
<
Char
>::
format_arg
basic_format_context
<
Char
>::
get_arg
(
BasicStringRef
<
Char
>
name
,
const
char
*&
error
)
{
if
(
this
->
check_no_auto_index
(
error
))
{
map_
.
init
(
this
->
args
());
const
basic_format_arg
<
Char
>
*
arg
=
map_
.
find
(
name
);
if
(
arg
)
if
(
const
format_arg
*
arg
=
map_
.
find
(
name
))
return
*
arg
;
error
=
"argument not found"
;
}
return
basic_format_arg
<
Char
>
();
return
format_arg
();
}
template
<
typename
Char
>
inline
basic_format_arg
<
Char
>
basic_format_context
<
Char
>::
parse_arg_id
()
{
inline
typename
basic_format_context
<
Char
>::
format_arg
basic_format_context
<
Char
>::
parse_arg_id
()
{
const
Char
*&
s
=
this
->
ptr
();
if
(
!
internal
::
is_name_start
(
*
s
))
{
const
char
*
error
=
0
;
basic_format_arg
<
Char
>
arg
=
*
s
<
'0'
||
*
s
>
'9'
?
this
->
next_arg
(
error
)
:
get_arg
(
internal
::
parse_nonnegative_int
(
s
),
error
);
format_arg
arg
=
*
s
<
'0'
||
*
s
>
'9'
?
this
->
next_arg
(
error
)
:
get_arg
(
internal
::
parse_nonnegative_int
(
s
),
error
);
if
(
error
)
{
FMT_THROW
(
format_error
(
*
s
!=
'}'
&&
*
s
!=
':'
?
"invalid format string"
:
error
));
...
...
@@ -3456,8 +3460,7 @@ inline basic_format_arg<Char> basic_format_context<Char>::parse_arg_id() {
c
=
*++
s
;
}
while
(
internal
::
is_name_start
(
c
)
||
(
'0'
<=
c
&&
c
<=
'9'
));
const
char
*
error
=
0
;
basic_format_arg
<
Char
>
arg
=
get_arg
(
BasicStringRef
<
Char
>
(
start
,
s
-
start
),
error
);
format_arg
arg
=
get_arg
(
BasicStringRef
<
Char
>
(
start
,
s
-
start
),
error
);
if
(
error
)
FMT_THROW
(
format_error
(
error
));
return
arg
;
...
...
@@ -3465,7 +3468,7 @@ inline basic_format_arg<Char> basic_format_context<Char>::parse_arg_id() {
// Formats a single argument.
template
<
typename
ArgFormatter
,
typename
Char
,
typename
Context
>
void
do_format_arg
(
BasicWriter
<
Char
>
&
writer
,
const
basic_format_arg
<
Char
>
&
arg
,
void
do_format_arg
(
BasicWriter
<
Char
>
&
writer
,
basic_format_arg
<
Context
>
arg
,
Context
&
ctx
)
{
const
Char
*&
s
=
ctx
.
ptr
();
FormatSpec
spec
;
...
...
@@ -3643,7 +3646,7 @@ struct UdlArg {
const
Char
*
str
;
template
<
typename
T
>
NamedArg
<
Char
>
operator
=
(
T
&&
value
)
const
{
NamedArg
<
basic_format_context
<
Char
>
>
operator
=
(
T
&&
value
)
const
{
return
{
str
,
std
::
forward
<
T
>
(
value
)};
}
};
...
...
fmt/printf.h
View file @
d705d516
...
...
@@ -80,14 +80,16 @@ struct is_same<T, T> {
enum
{
value
=
1
};
};
template
<
typename
T
,
typename
C
har
>
template
<
typename
T
,
typename
C
ontext
>
class
ArgConverter
{
private:
basic_format_arg
<
Char
>
&
arg_
;
Char
type_
;
typedef
typename
Context
::
char_type
Char
;
basic_format_arg
<
Context
>
&
arg_
;
typename
Context
::
char_type
type_
;
public:
ArgConverter
(
basic_format_arg
<
C
har
>
&
arg
,
Char
type
)
ArgConverter
(
basic_format_arg
<
C
ontext
>
&
arg
,
Char
type
)
:
arg_
(
arg
),
type_
(
type
)
{}
void
operator
()(
bool
value
)
{
...
...
@@ -105,11 +107,11 @@ class ArgConverter {
if
(
sizeof
(
TargetType
)
<=
sizeof
(
int
))
{
// Extra casts are used to silence warnings.
if
(
is_signed
)
{
arg_
=
internal
::
make_arg
<
format_c
ontext
>
(
arg_
=
internal
::
make_arg
<
C
ontext
>
(
static_cast
<
int
>
(
static_cast
<
TargetType
>
(
value
)));
}
else
{
typedef
typename
internal
::
MakeUnsigned
<
TargetType
>::
Type
Unsigned
;
arg_
=
internal
::
make_arg
<
format_c
ontext
>
(
arg_
=
internal
::
make_arg
<
C
ontext
>
(
static_cast
<
unsigned
>
(
static_cast
<
Unsigned
>
(
value
)));
}
}
else
{
...
...
@@ -117,10 +119,9 @@ class ArgConverter {
// 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_
=
internal
::
make_arg
<
format_context
>
(
static_cast
<
LongLong
>
(
value
));
arg_
=
internal
::
make_arg
<
Context
>
(
static_cast
<
LongLong
>
(
value
));
}
else
{
arg_
=
internal
::
make_arg
<
format_c
ontext
>
(
arg_
=
internal
::
make_arg
<
C
ontext
>
(
static_cast
<
typename
internal
::
MakeUnsigned
<
U
>::
Type
>
(
value
));
}
}
...
...
@@ -137,32 +138,30 @@ class ArgConverter {
// 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
Char
>
void
convert_arg
(
basic_format_arg
<
C
har
>
&
arg
,
Char
type
)
{
visit
(
ArgConverter
<
T
,
C
har
>
(
arg
,
type
),
arg
);
template
<
typename
T
,
typename
C
ontext
,
typename
C
har
>
void
convert_arg
(
basic_format_arg
<
C
ontext
>
&
arg
,
Char
type
)
{
visit
(
ArgConverter
<
T
,
C
ontext
>
(
arg
,
type
),
arg
);
}
// Converts an integer argument to char for printf.
template
<
typename
C
har
>
template
<
typename
C
ontext
>
class
CharConverter
{
private:
basic_format_arg
<
C
har
>
&
arg_
;
basic_format_arg
<
C
ontext
>
&
arg_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
CharConverter
);
public:
explicit
CharConverter
(
basic_format_arg
<
C
har
>
&
arg
)
:
arg_
(
arg
)
{}
explicit
CharConverter
(
basic_format_arg
<
C
ontext
>
&
arg
)
:
arg_
(
arg
)
{}
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
>::
type
operator
()(
T
value
)
{
arg_
=
internal
::
make_arg
<
basic_format_context
<
Char
>>
(
static_cast
<
char
>
(
value
));
arg_
=
internal
::
make_arg
<
Context
>
(
static_cast
<
char
>
(
value
));
}
template
<
typename
T
>
typename
std
::
enable_if
<!
std
::
is_integral
<
T
>::
value
>::
type
operator
()(
T
value
)
{
typename
std
::
enable_if
<!
std
::
is_integral
<
T
>::
value
>::
type
operator
()(
T
)
{
// No coversion needed for non-integral types.
}
};
...
...
@@ -301,12 +300,13 @@ class printf_context :
private:
typedef
internal
::
format_context_base
<
Char
,
printf_context
>
Base
;
typedef
typename
Base
::
format_arg
format_arg
;
void
parse_flags
(
FormatSpec
&
spec
,
const
Char
*&
s
);
// Returns the argument with specified index or, if arg_index is equal
// to the maximum unsigned value, the next argument.
basic_format_arg
<
Char
>
get_arg
(
format_arg
get_arg
(
const
Char
*
s
,
unsigned
arg_index
=
(
std
::
numeric_limits
<
unsigned
>::
max
)());
...
...
@@ -356,12 +356,11 @@ void printf_context<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s) {
}
template
<
typename
Char
,
typename
AF
>
basic_format_arg
<
Char
>
printf_context
<
Char
,
AF
>::
get_arg
(
typename
printf_context
<
Char
,
AF
>::
format_arg
printf_context
<
Char
,
AF
>::
get_arg
(
const
Char
*
s
,
unsigned
arg_index
)
{
(
void
)
s
;
const
char
*
error
=
0
;
basic_format_arg
<
Char
>
arg
=
arg_index
==
std
::
numeric_limits
<
unsigned
>::
max
()
?
format_arg
arg
=
arg_index
==
std
::
numeric_limits
<
unsigned
>::
max
()
?
this
->
next_arg
(
error
)
:
Base
::
get_arg
(
arg_index
-
1
,
error
);
if
(
error
)
FMT_THROW
(
format_error
(
!*
s
?
"invalid format string"
:
error
));
...
...
@@ -433,7 +432,7 @@ void printf_context<Char, AF>::format(BasicWriter<Char> &writer) {
}
}
basic_format_arg
<
Char
>
arg
=
get_arg
(
s
,
arg_index
);
format_arg
arg
=
get_arg
(
s
,
arg_index
);
if
(
spec
.
flag
(
HASH_FLAG
)
&&
visit
(
internal
::
IsZeroInt
(),
arg
))
spec
.
flags_
&=
~
internal
::
to_unsigned
<
int
>
(
HASH_FLAG
);
if
(
spec
.
fill_
==
'0'
)
{
...
...
@@ -488,7 +487,7 @@ void printf_context<Char, AF>::format(BasicWriter<Char> &writer) {
break
;
case
'c'
:
// TODO: handle wchar_t
visit
(
internal
::
CharConverter
<
Char
>
(
arg
),
arg
);
visit
(
internal
::
CharConverter
<
printf_context
<
Char
,
AF
>
>
(
arg
),
arg
);
break
;
}
}
...
...
test/format-impl-test.cc
View file @
d705d516
...
...
@@ -58,7 +58,8 @@ TEST(FormatTest, ArgConverter) {
using
fmt
::
format_arg
;
fmt
::
LongLong
value
=
std
::
numeric_limits
<
fmt
::
LongLong
>::
max
();
format_arg
arg
=
fmt
::
internal
::
make_arg
<
fmt
::
format_context
>
(
value
);
visit
(
fmt
::
internal
::
ArgConverter
<
fmt
::
LongLong
,
char
>
(
arg
,
'd'
),
arg
);
visit
(
fmt
::
internal
::
ArgConverter
<
fmt
::
LongLong
,
fmt
::
format_context
>
(
arg
,
'd'
),
arg
);
EXPECT_EQ
(
value
,
visit
(
ValueExtractor
<
fmt
::
LongLong
>
(),
arg
));
}
...
...
test/util-test.cc
View file @
d705d516
...
...
@@ -73,9 +73,9 @@ void format_value(fmt::BasicWriter<Char> &w, Test,
w
<<
"test"
;
}
template
<
typename
C
har
,
typename
T
>
basic_format_arg
<
C
har
>
make_arg
(
const
T
&
value
)
{
return
fmt
::
internal
::
make_arg
<
fmt
::
basic_format_context
<
Char
>
>
(
value
);
template
<
typename
C
ontext
,
typename
T
>
basic_format_arg
<
C
ontext
>
make_arg
(
const
T
&
value
)
{
return
fmt
::
internal
::
make_arg
<
Context
>
(
value
);
}
}
// namespace
...
...
@@ -487,7 +487,7 @@ VISIT_TYPE(float, double);
#define CHECK_ARG_(Char, expected, value) { \
testing::StrictMock<MockVisitor<decltype(expected)>> visitor; \
EXPECT_CALL(visitor, visit(expected)); \
fmt::visit(visitor, make_arg<
Char
>(value)); \
fmt::visit(visitor, make_arg<
fmt::basic_format_context<Char>
>(value)); \
}
#define CHECK_ARG(value) { \
...
...
@@ -575,7 +575,7 @@ TEST(UtilTest, CustomArg) {
EXPECT_EQ
(
"test"
,
w
.
str
());
return
Visitor
::
Result
();
}));
fmt
::
visit
(
visitor
,
make_arg
<
char
>
(
test
));
fmt
::
visit
(
visitor
,
make_arg
<
fmt
::
format_context
>
(
test
));
}
TEST
(
ArgVisitorTest
,
VisitInvalidArg
)
{
...
...
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