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
beb00edf
Commit
beb00edf
authored
Sep 23, 2014
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Store types in ArgList instead of Arg
parent
49222dc0
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
231 additions
and
106 deletions
+231
-106
format.cc
format.cc
+15
-15
format.h
format.h
+187
-74
test/macro-test.cc
test/macro-test.cc
+2
-2
test/util-test.cc
test/util-test.cc
+27
-15
No files found.
format.cc
View file @
beb00edf
...
@@ -579,38 +579,38 @@ void fmt::BasicWriter<Char, Allocator>::write_str(
...
@@ -579,38 +579,38 @@ void fmt::BasicWriter<Char, Allocator>::write_str(
}
}
template
<
typename
Char
>
template
<
typename
Char
>
inline
const
Arg
&
fmt
::
BasicFormatter
<
Char
>::
parse_arg_index
(
const
Char
*&
s
)
{
inline
Arg
fmt
::
BasicFormatter
<
Char
>::
parse_arg_index
(
const
Char
*&
s
)
{
const
char
*
error
=
0
;
const
char
*
error
=
0
;
const
Arg
*
arg
=
*
s
<
'0'
||
*
s
>
'9'
?
Arg
arg
=
*
s
<
'0'
||
*
s
>
'9'
?
next_arg
(
error
)
:
get_arg
(
parse_nonnegative_int
(
s
),
error
);
next_arg
(
error
)
:
get_arg
(
parse_nonnegative_int
(
s
),
error
);
if
(
error
)
if
(
error
)
throw
FormatError
(
*
s
!=
'}'
&&
*
s
!=
':'
?
"invalid format string"
:
error
);
throw
FormatError
(
*
s
!=
'}'
&&
*
s
!=
':'
?
"invalid format string"
:
error
);
return
*
arg
;
return
arg
;
}
}
const
Arg
*
fmt
::
internal
::
FormatterBase
::
do_get_arg
(
Arg
fmt
::
internal
::
FormatterBase
::
do_get_arg
(
unsigned
arg_index
,
const
char
*&
error
)
{
unsigned
arg_index
,
const
char
*&
error
)
{
if
(
arg_index
<
args_
.
size
())
Arg
arg
=
args_
[
arg_index
];
return
&
args_
[
arg_index
];
if
(
arg
.
type
==
Arg
::
NONE
)
error
=
"argument index out of range"
;
error
=
"argument index out of range"
;
return
0
;
return
arg
;
}
}
inline
const
Arg
*
fmt
::
internal
::
FormatterBase
::
next_arg
(
const
char
*&
error
)
{
inline
Arg
fmt
::
internal
::
FormatterBase
::
next_arg
(
const
char
*&
error
)
{
if
(
next_arg_index_
>=
0
)
if
(
next_arg_index_
>=
0
)
return
do_get_arg
(
next_arg_index_
++
,
error
);
return
do_get_arg
(
next_arg_index_
++
,
error
);
error
=
"cannot switch from manual to automatic argument indexing"
;
error
=
"cannot switch from manual to automatic argument indexing"
;
return
0
;
return
Arg
()
;
}
}
inline
const
Arg
*
fmt
::
internal
::
FormatterBase
::
get_arg
(
inline
Arg
fmt
::
internal
::
FormatterBase
::
get_arg
(
unsigned
arg_index
,
const
char
*&
error
)
{
unsigned
arg_index
,
const
char
*&
error
)
{
if
(
next_arg_index_
<=
0
)
{
if
(
next_arg_index_
<=
0
)
{
next_arg_index_
=
-
1
;
next_arg_index_
=
-
1
;
return
do_get_arg
(
arg_index
,
error
);
return
do_get_arg
(
arg_index
,
error
);
}
}
error
=
"cannot switch from automatic to manual argument indexing"
;
error
=
"cannot switch from automatic to manual argument indexing"
;
return
0
;
return
Arg
()
;
}
}
template
<
typename
Char
>
template
<
typename
Char
>
...
@@ -641,14 +641,14 @@ void fmt::internal::PrintfFormatter<Char>::parse_flags(
...
@@ -641,14 +641,14 @@ void fmt::internal::PrintfFormatter<Char>::parse_flags(
}
}
template
<
typename
Char
>
template
<
typename
Char
>
const
Arg
&
fmt
::
internal
::
PrintfFormatter
<
Char
>::
get_arg
(
Arg
fmt
::
internal
::
PrintfFormatter
<
Char
>::
get_arg
(
const
Char
*
s
,
unsigned
arg_index
)
{
const
Char
*
s
,
unsigned
arg_index
)
{
const
char
*
error
=
0
;
const
char
*
error
=
0
;
const
Arg
*
arg
=
arg_index
==
UINT_MAX
?
Arg
arg
=
arg_index
==
UINT_MAX
?
next_arg
(
error
)
:
FormatterBase
::
get_arg
(
arg_index
-
1
,
error
);
next_arg
(
error
)
:
FormatterBase
::
get_arg
(
arg_index
-
1
,
error
);
if
(
error
)
if
(
error
)
throw
FormatError
(
!*
s
?
"invalid format string"
:
error
);
throw
FormatError
(
!*
s
?
"invalid format string"
:
error
);
return
*
arg
;
return
arg
;
}
}
template
<
typename
Char
>
template
<
typename
Char
>
...
...
format.h
View file @
beb00edf
...
@@ -608,16 +608,7 @@ struct NonZero<0> {
...
@@ -608,16 +608,7 @@ struct NonZero<0> {
};
};
// A formatting argument. It is a POD type to allow storage in internal::Array.
// A formatting argument. It is a POD type to allow storage in internal::Array.
struct
Arg
{
struct
ArgBase
{
enum
Type
{
// Integer types should go first,
INT
,
UINT
,
LONG_LONG
,
ULONG_LONG
,
CHAR
,
LAST_INTEGER_TYPE
=
CHAR
,
// followed by floating-point types.
DOUBLE
,
LONG_DOUBLE
,
LAST_NUMERIC_TYPE
=
LONG_DOUBLE
,
STRING
,
WSTRING
,
POINTER
,
CUSTOM
};
Type
type
;
template
<
typename
Char
>
template
<
typename
Char
>
struct
StringValue
{
struct
StringValue
{
const
Char
*
value
;
const
Char
*
value
;
...
@@ -646,9 +637,98 @@ struct Arg {
...
@@ -646,9 +637,98 @@ struct Arg {
};
};
};
};
struct
Arg
:
public
ArgBase
{
enum
Type
{
NONE
,
// Integer types should go first,
INT
,
UINT
,
LONG_LONG
,
ULONG_LONG
,
CHAR
,
LAST_INTEGER_TYPE
=
CHAR
,
// followed by floating-point types.
DOUBLE
,
LONG_DOUBLE
,
LAST_NUMERIC_TYPE
=
LONG_DOUBLE
,
STRING
,
WSTRING
,
POINTER
,
CUSTOM
};
Type
type
;
};
struct
None
{};
template
<
unsigned
N
,
typename
T0
=
None
,
typename
T1
=
None
,
typename
T2
=
None
,
typename
T3
=
None
,
typename
T4
=
None
,
typename
T5
=
None
,
typename
T6
=
None
,
typename
T7
=
None
,
typename
T8
=
None
,
typename
T9
=
None
,
typename
T10
=
None
,
typename
T11
=
None
,
typename
T12
=
None
,
typename
T13
=
None
,
typename
T14
=
None
>
struct
ArgType
{
static
const
fmt
::
ULongLong
TYPE
=
ArgType
<
1
,
T0
>::
TYPE
|
(
ArgType
<
1
,
T1
>::
TYPE
<<
4
)
|
(
ArgType
<
1
,
T2
>::
TYPE
<<
8
)
|
(
ArgType
<
1
,
T3
>::
TYPE
<<
12
)
|
(
ArgType
<
1
,
T4
>::
TYPE
<<
16
)
|
(
ArgType
<
1
,
T5
>::
TYPE
<<
20
)
|
(
ArgType
<
1
,
T6
>::
TYPE
<<
24
)
|
(
ArgType
<
1
,
T7
>::
TYPE
<<
28
)
|
(
ArgType
<
1
,
T8
>::
TYPE
<<
32
)
|
(
ArgType
<
1
,
T9
>::
TYPE
<<
36
)
|
(
ArgType
<
1
,
T10
>::
TYPE
<<
40
)
|
(
ArgType
<
1
,
T11
>::
TYPE
<<
44
)
|
(
ArgType
<
1
,
T12
>::
TYPE
<<
48
)
|
(
ArgType
<
1
,
T13
>::
TYPE
<<
52
)
|
(
ArgType
<
1
,
T14
>::
TYPE
<<
56
);
};
template
<
typename
T
>
struct
ArgType
<
1
,
T
>
{
enum
{
TYPE
=
Arg
::
CUSTOM
};
};
template
<
std
::
size_t
N
>
struct
ArgType
<
1
,
char
[
N
]
>
{
enum
{
TYPE
=
Arg
::
STRING
};
};
template
<
std
::
size_t
N
>
struct
ArgType
<
1
,
const
char
[
N
]
>
{
enum
{
TYPE
=
Arg
::
STRING
};
};
template
<
>
struct
ArgType
<
1
,
const
char
*>
{
enum
{
TYPE
=
Arg
::
STRING
};
};
template
<
>
struct
ArgType
<
1
,
std
::
string
>
{
enum
{
TYPE
=
Arg
::
STRING
};
};
template
<
>
struct
ArgType
<
1
,
fmt
::
StringRef
>
{
enum
{
TYPE
=
Arg
::
STRING
};
};
template
<
std
::
size_t
N
>
struct
ArgType
<
1
,
wchar_t
[
N
]
>
{
enum
{
TYPE
=
Arg
::
WSTRING
};
};
template
<
std
::
size_t
N
>
struct
ArgType
<
1
,
const
wchar_t
[
N
]
>
{
enum
{
TYPE
=
Arg
::
WSTRING
};
};
template
<
>
struct
ArgType
<
1
,
const
wchar_t
*>
{
enum
{
TYPE
=
Arg
::
WSTRING
};
};
template
<
>
struct
ArgType
<
1
,
std
::
wstring
>
{
enum
{
TYPE
=
Arg
::
WSTRING
};
};
template
<
>
struct
ArgType
<
1
,
fmt
::
WStringRef
>
{
enum
{
TYPE
=
Arg
::
WSTRING
};
};
#define FMT_ARG_TYPE(Type, CODE) \
template <> \
struct ArgType<1, Type> { static const fmt::ULongLong TYPE = Arg::CODE; }
FMT_ARG_TYPE
(
None
,
NONE
);
FMT_ARG_TYPE
(
bool
,
INT
);
FMT_ARG_TYPE
(
signed
char
,
INT
);
FMT_ARG_TYPE
(
unsigned
char
,
UINT
);
FMT_ARG_TYPE
(
short
,
INT
);
FMT_ARG_TYPE
(
unsigned
short
,
UINT
);
FMT_ARG_TYPE
(
int
,
INT
);
FMT_ARG_TYPE
(
unsigned
,
UINT
);
FMT_ARG_TYPE
(
long
,
LONG_LONG
);
// TODO: check sizeof long
FMT_ARG_TYPE
(
unsigned
long
,
ULONG_LONG
);
// TODO: check sizeof long
FMT_ARG_TYPE
(
fmt
::
LongLong
,
LONG_LONG
);
FMT_ARG_TYPE
(
fmt
::
ULongLong
,
ULONG_LONG
);
FMT_ARG_TYPE
(
char
,
CHAR
);
FMT_ARG_TYPE
(
wchar_t
,
CHAR
);
FMT_ARG_TYPE
(
float
,
DOUBLE
);
FMT_ARG_TYPE
(
double
,
DOUBLE
);
FMT_ARG_TYPE
(
long
double
,
LONG_DOUBLE
);
FMT_ARG_TYPE
(
void
*
,
POINTER
);
// TODO: more types
// Makes an Arg object from any type.
// Makes an Arg object from any type.
template
<
typename
Char
>
template
<
typename
Char
>
class
MakeArg
:
public
Arg
{
class
MakeArg
:
public
Arg
Base
{
private:
private:
// The following two methods are private to disallow formatting of
// The following two methods are private to disallow formatting of
// arbitrary pointers. If you want to output a pointer cast it to
// arbitrary pointers. If you want to output a pointer cast it to
...
@@ -661,13 +741,11 @@ class MakeArg : public Arg {
...
@@ -661,13 +741,11 @@ class MakeArg : public Arg {
MakeArg
(
T
*
value
);
MakeArg
(
T
*
value
);
void
set_string
(
StringRef
str
)
{
void
set_string
(
StringRef
str
)
{
type
=
STRING
;
string
.
value
=
str
.
c_str
();
string
.
value
=
str
.
c_str
();
string
.
size
=
str
.
size
();
string
.
size
=
str
.
size
();
}
}
void
set_string
(
WStringRef
str
)
{
void
set_string
(
WStringRef
str
)
{
type
=
WSTRING
;
CharTraits
<
Char
>::
convert
(
wchar_t
());
CharTraits
<
Char
>::
convert
(
wchar_t
());
wstring
.
value
=
str
.
c_str
();
wstring
.
value
=
str
.
c_str
();
wstring
.
size
=
str
.
size
();
wstring
.
size
=
str
.
size
();
...
@@ -683,41 +761,34 @@ class MakeArg : public Arg {
...
@@ -683,41 +761,34 @@ class MakeArg : public Arg {
public:
public:
MakeArg
()
{}
MakeArg
()
{}
MakeArg
(
bool
value
)
{
type
=
INT
;
int_value
=
value
;
}
MakeArg
(
bool
value
)
{
int_value
=
value
;
}
MakeArg
(
short
value
)
{
type
=
INT
;
int_value
=
value
;
}
MakeArg
(
short
value
)
{
int_value
=
value
;
}
MakeArg
(
unsigned
short
value
)
{
type
=
UINT
;
uint_value
=
value
;
}
MakeArg
(
unsigned
short
value
)
{
uint_value
=
value
;
}
MakeArg
(
int
value
)
{
type
=
INT
;
int_value
=
value
;
}
MakeArg
(
int
value
)
{
int_value
=
value
;
}
MakeArg
(
unsigned
value
)
{
type
=
UINT
;
uint_value
=
value
;
}
MakeArg
(
unsigned
value
)
{
uint_value
=
value
;
}
MakeArg
(
long
value
)
{
MakeArg
(
long
value
)
{
// To minimize the number of types we need to deal with, long is
// 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.
// translated either to int or to long long depending on its size.
if
(
sizeof
(
long
)
==
sizeof
(
int
))
{
if
(
sizeof
(
long
)
==
sizeof
(
int
))
type
=
INT
;
int_value
=
static_cast
<
int
>
(
value
);
int_value
=
static_cast
<
int
>
(
value
);
}
else
{
else
type
=
LONG_LONG
;
long_long_value
=
value
;
long_long_value
=
value
;
}
}
}
MakeArg
(
unsigned
long
value
)
{
MakeArg
(
unsigned
long
value
)
{
if
(
sizeof
(
unsigned
long
)
==
sizeof
(
unsigned
))
{
if
(
sizeof
(
unsigned
long
)
==
sizeof
(
unsigned
))
type
=
UINT
;
uint_value
=
static_cast
<
unsigned
>
(
value
);
uint_value
=
static_cast
<
unsigned
>
(
value
);
}
else
{
else
type
=
ULONG_LONG
;
ulong_long_value
=
value
;
ulong_long_value
=
value
;
}
}
}
MakeArg
(
LongLong
value
)
{
long_long_value
=
value
;
}
MakeArg
(
LongLong
value
)
{
type
=
LONG_LONG
;
long_long_value
=
value
;
}
MakeArg
(
ULongLong
value
)
{
ulong_long_value
=
value
;
}
MakeArg
(
ULongLong
value
)
{
type
=
ULONG_LONG
;
ulong_long_value
=
value
;
}
MakeArg
(
float
value
)
{
double_value
=
value
;
}
MakeArg
(
float
value
)
{
type
=
DOUBLE
;
double_value
=
value
;
}
MakeArg
(
double
value
)
{
double_value
=
value
;
}
MakeArg
(
double
value
)
{
type
=
DOUBLE
;
double_value
=
value
;
}
MakeArg
(
long
double
value
)
{
long_double_value
=
value
;
}
MakeArg
(
long
double
value
)
{
type
=
LONG_DOUBLE
;
long_double_value
=
value
;
}
MakeArg
(
signed
char
value
)
{
int_value
=
value
;
}
MakeArg
(
signed
char
value
)
{
type
=
CHAR
;
int_value
=
value
;
}
MakeArg
(
unsigned
char
value
)
{
int_value
=
value
;
}
MakeArg
(
unsigned
char
value
)
{
type
=
CHAR
;
int_value
=
value
;
}
MakeArg
(
char
value
)
{
int_value
=
value
;
}
MakeArg
(
char
value
)
{
type
=
CHAR
;
int_value
=
value
;
}
MakeArg
(
wchar_t
value
)
{
MakeArg
(
wchar_t
value
)
{
type
=
CHAR
;
int_value
=
internal
::
CharTraits
<
Char
>::
convert
(
value
);
int_value
=
internal
::
CharTraits
<
Char
>::
convert
(
value
);
}
}
...
@@ -731,12 +802,11 @@ public:
...
@@ -731,12 +802,11 @@ public:
MakeArg
(
const
std
::
wstring
&
value
)
{
set_string
(
value
);
}
MakeArg
(
const
std
::
wstring
&
value
)
{
set_string
(
value
);
}
MakeArg
(
WStringRef
value
)
{
set_string
(
value
);
}
MakeArg
(
WStringRef
value
)
{
set_string
(
value
);
}
MakeArg
(
void
*
value
)
{
type
=
POINTER
;
pointer_value
=
value
;
}
MakeArg
(
void
*
value
)
{
pointer_value
=
value
;
}
MakeArg
(
const
void
*
value
)
{
type
=
POINTER
;
pointer_value
=
value
;
}
MakeArg
(
const
void
*
value
)
{
pointer_value
=
value
;
}
template
<
typename
T
>
template
<
typename
T
>
MakeArg
(
const
T
&
value
)
{
MakeArg
(
const
T
&
value
)
{
type
=
CUSTOM
;
custom
.
value
=
&
value
;
custom
.
value
=
&
value
;
custom
.
format
=
&
format_custom_arg
<
T
>
;
custom
.
format
=
&
format_custom_arg
<
T
>
;
}
}
...
@@ -858,24 +928,34 @@ class ArgFormatter;
...
@@ -858,24 +928,34 @@ class ArgFormatter;
*/
*/
class
ArgList
{
class
ArgList
{
private:
private:
const
internal
::
Arg
*
arg
s_
;
fmt
::
ULongLong
type
s_
;
std
::
size_t
size
_
;
const
internal
::
ArgBase
*
args
_
;
public:
public:
ArgList
()
:
size_
(
0
)
{}
// Maximum number of arguments that can be passed in ArgList.
ArgList
(
const
internal
::
Arg
*
args
,
std
::
size_t
size
)
enum
{
MAX_ARGS
=
16
};
:
args_
(
args
),
size_
(
size
)
{}
/**
ArgList
()
:
types_
(
0
)
{}
Returns the list size (the number of arguments).
ArgList
(
fmt
::
ULongLong
types
,
const
internal
::
ArgBase
*
args
)
*/
:
types_
(
types
),
args_
(
args
)
{}
std
::
size_t
size
()
const
{
return
size_
;
}
/**
/**
Returns the argument at specified index.
Returns the argument at specified index.
*/
*/
const
internal
::
Arg
&
operator
[](
std
::
size_t
index
)
const
{
internal
::
Arg
operator
[](
unsigned
index
)
const
{
return
args_
[
index
];
if
(
index
>=
MAX_ARGS
)
return
internal
::
Arg
();
fmt
::
ULongLong
shift
=
index
*
4
;
using
internal
::
Arg
;
Arg
::
Type
type
=
static_cast
<
Arg
::
Type
>
((
types_
&
(
0xfull
<<
shift
))
>>
shift
);
Arg
arg
;
arg
.
type
=
type
;
if
(
type
!=
Arg
::
NONE
)
{
internal
::
ArgBase
&
base
=
arg
;
base
=
args_
[
index
];
}
return
arg
;
}
}
};
};
...
@@ -889,7 +969,7 @@ class FormatterBase {
...
@@ -889,7 +969,7 @@ class FormatterBase {
int
next_arg_index_
;
int
next_arg_index_
;
// Returns the argument with specified index.
// Returns the argument with specified index.
const
Arg
*
do_get_arg
(
unsigned
arg_index
,
const
char
*&
error
);
Arg
do_get_arg
(
unsigned
arg_index
,
const
char
*&
error
);
protected:
protected:
void
set_args
(
const
ArgList
&
args
)
{
void
set_args
(
const
ArgList
&
args
)
{
...
@@ -898,11 +978,11 @@ class FormatterBase {
...
@@ -898,11 +978,11 @@ class FormatterBase {
}
}
// Returns the next argument.
// Returns the next argument.
const
Arg
*
next_arg
(
const
char
*&
error
);
Arg
next_arg
(
const
char
*&
error
);
// Checks if manual indexing is used and returns the argument with
// Checks if manual indexing is used and returns the argument with
// specified index.
// specified index.
const
Arg
*
get_arg
(
unsigned
arg_index
,
const
char
*&
error
);
Arg
get_arg
(
unsigned
arg_index
,
const
char
*&
error
);
template
<
typename
Char
>
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
)
{
...
@@ -919,7 +999,7 @@ class PrintfFormatter : private FormatterBase {
...
@@ -919,7 +999,7 @@ class PrintfFormatter : private FormatterBase {
// Returns the argument with specified index or, if arg_index is equal
// Returns the argument with specified index or, if arg_index is equal
// to the maximum unsigned value, the next argument.
// to the maximum unsigned value, the next argument.
const
Arg
&
get_arg
(
const
Char
*
s
,
Arg
get_arg
(
const
Char
*
s
,
unsigned
arg_index
=
(
std
::
numeric_limits
<
unsigned
>::
max
)());
unsigned
arg_index
=
(
std
::
numeric_limits
<
unsigned
>::
max
)());
// Parses argument index, flags and width and returns the argument index.
// Parses argument index, flags and width and returns the argument index.
...
@@ -939,7 +1019,7 @@ class BasicFormatter : private internal::FormatterBase {
...
@@ -939,7 +1019,7 @@ class BasicFormatter : private internal::FormatterBase {
const
Char
*
start_
;
const
Char
*
start_
;
// Parses argument index and returns corresponding argument.
// Parses argument index and returns corresponding argument.
const
internal
::
Arg
&
parse_arg_index
(
const
Char
*&
s
);
internal
::
Arg
parse_arg_index
(
const
Char
*&
s
);
public:
public:
explicit
BasicFormatter
(
BasicWriter
<
Char
>
&
w
)
:
writer_
(
w
)
{}
explicit
BasicFormatter
(
BasicWriter
<
Char
>
&
w
)
:
writer_
(
w
)
{}
...
@@ -1188,31 +1268,58 @@ inline StrFormatSpec<wchar_t> pad(
...
@@ -1188,31 +1268,58 @@ inline StrFormatSpec<wchar_t> pad(
# define FMT_GEN15(f) FMT_GEN14(f), f(14)
# define FMT_GEN15(f) FMT_GEN14(f), f(14)
# define FMT_MAKE_TEMPLATE_ARG(n) typename T##n
# define FMT_MAKE_TEMPLATE_ARG(n) typename T##n
# define FMT_MAKE_ARG_TYPE(n) T##n
# define FMT_MAKE_ARG(n) const T##n &v##n
# define FMT_MAKE_ARG(n) const T##n &v##n
# define FMT_MAKE_REF_char(n) fmt::internal::MakeArg<char>(v##n)
# define FMT_MAKE_REF_char(n) fmt::internal::MakeArg<char>(v##n)
# define FMT_MAKE_REF_wchar_t(n) fmt::internal::MakeArg<wchar_t>(v##n)
# define FMT_MAKE_REF_wchar_t(n) fmt::internal::MakeArg<wchar_t>(v##n)
/*namespace internal {
#undef FMT_ARG_TYPE
#define FMT_ARG_TYPE(n, m) \
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
struct ArgType##n { \
enum { TYPE = (ArgType1<T##m>::TYPE << 4 * m) | \
ArgType##m<FMT_GEN(m, FMT_MAKE_ARG_TYPE)>::TYPE }; \
}
FMT_ARG_TYPE(2, 1);
FMT_ARG_TYPE(3, 2);
FMT_ARG_TYPE(4, 3);
FMT_ARG_TYPE(5, 4);
FMT_ARG_TYPE(6, 5);
FMT_ARG_TYPE(7, 6);
FMT_ARG_TYPE(8, 7);
FMT_ARG_TYPE(9, 8);
FMT_ARG_TYPE(10, 9);
FMT_ARG_TYPE(11, 10);
FMT_ARG_TYPE(12, 11);
FMT_ARG_TYPE(13, 12);
FMT_ARG_TYPE(14, 13);
FMT_ARG_TYPE(15, 14);
}*/
#if FMT_USE_VARIADIC_TEMPLATES
#if FMT_USE_VARIADIC_TEMPLATES
// Defines a variadic function returning void.
// Defines a variadic function returning void.
# define FMT_VARIADIC_VOID(func, arg_type) \
# define FMT_VARIADIC_VOID(func, arg_type) \
template<typename... Args> \
template<typename... Args> \
void func(arg_type arg1, const Args & ... args) { \
void func(arg_type arg1, const Args & ... args) { \
using fmt::internal::Arg;
\
const fmt::internal::ArgBase arg_array[
\
const Arg arg_array[
fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \
fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \
fmt::internal::MakeArg<Char>(args)... \
fmt::internal::MakeArg<Char>(args)... \
}; \
}; \
func(arg1, ArgList(arg_array, sizeof...(Args))); \
func(arg1, ArgList( \
internal::ArgType<15, Args...>::TYPE, arg_array)); \
}
}
// Defines a variadic constructor.
// Defines a variadic constructor.
# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \
# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \
template<typename... Args> \
template<typename... Args> \
ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \
ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \
using fmt::internal::Arg;
\
const fmt::internal::ArgBase arg_array[
\
const Arg arg_array[
fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \
fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \
fmt::internal::MakeArg<Char>(args)... \
fmt::internal::MakeArg<Char>(args)... \
}; \
}; \
func(arg0, arg1, ArgList(arg_array, sizeof...(Args))); \
func(arg0, arg1, ArgList( \
internal::ArgType<15, Args...>::TYPE, arg_array)); \
}
}
#else
#else
...
@@ -1223,8 +1330,9 @@ inline StrFormatSpec<wchar_t> pad(
...
@@ -1223,8 +1330,9 @@ inline StrFormatSpec<wchar_t> pad(
# define FMT_WRAP1(func, arg_type, n) \
# define FMT_WRAP1(func, arg_type, n) \
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
inline void func(arg_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
inline void func(arg_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \
const fmt::internal::ArgBase args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \
func(arg1, fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
func(arg1, fmt::ArgList( \
fmt::internal::ArgType<n, FMT_GEN(n, FMT_MAKE_ARG_TYPE)>::TYPE, args)); \
}
}
// Emulates a variadic function returning void on a pre-C++11 compiler.
// Emulates a variadic function returning void on a pre-C++11 compiler.
...
@@ -1238,8 +1346,9 @@ inline StrFormatSpec<wchar_t> pad(
...
@@ -1238,8 +1346,9 @@ inline StrFormatSpec<wchar_t> pad(
# define FMT_CTOR(ctor, func, arg0_type, arg1_type, n) \
# define FMT_CTOR(ctor, func, arg0_type, arg1_type, n) \
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
ctor(arg0_type arg0, arg1_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
ctor(arg0_type arg0, arg1_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \
const fmt::internal::ArgBase args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \
func(arg0, arg1, fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
func(arg0, arg1, fmt::ArgList( \
internal::ArgType<n, FMT_GEN(n, FMT_MAKE_ARG_TYPE)>::TYPE, args)); \
}
}
// Emulates a variadic constructor on a pre-C++11 compiler.
// Emulates a variadic constructor on a pre-C++11 compiler.
...
@@ -1912,7 +2021,11 @@ template <typename Char, typename T>
...
@@ -1912,7 +2021,11 @@ template <typename Char, typename T>
void
format
(
BasicFormatter
<
Char
>
&
f
,
const
Char
*&
format_str
,
const
T
&
value
)
{
void
format
(
BasicFormatter
<
Char
>
&
f
,
const
Char
*&
format_str
,
const
T
&
value
)
{
std
::
basic_ostringstream
<
Char
>
os
;
std
::
basic_ostringstream
<
Char
>
os
;
os
<<
value
;
os
<<
value
;
format_str
=
f
.
format
(
format_str
,
internal
::
MakeArg
<
Char
>
(
os
.
str
()));
internal
::
Arg
arg
;
internal
::
ArgBase
&
base
=
arg
;
base
=
internal
::
MakeArg
<
Char
>
(
os
.
str
());
arg
.
type
=
internal
::
Arg
::
STRING
;
format_str
=
f
.
format
(
format_str
,
arg
);
}
}
// Reports a system error without throwing an exception.
// Reports a system error without throwing an exception.
...
@@ -2195,12 +2308,12 @@ inline void format_decimal(char *&buffer, T value) {
...
@@ -2195,12 +2308,12 @@ inline void format_decimal(char *&buffer, T value) {
template<typename... Args> \
template<typename... Args> \
ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
const Args & ... args) { \
const Args & ... args) { \
using fmt::internal::Arg; \
using fmt::internal::Arg
Base
; \
const Arg array[fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \
const Arg
Base
array[fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \
fmt::internal::MakeArg<Char>(args)... \
fmt::internal::MakeArg<Char>(args)... \
}; \
}; \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__),
fmt::ArgList(
\
fmt::
ArgList(array, sizeof...(Args)
)); \
fmt::
internal::ArgType<15, Args...>::TYPE, array
)); \
}
}
#else
#else
// Defines a wrapper for a function taking __VA_ARGS__ arguments
// Defines a wrapper for a function taking __VA_ARGS__ arguments
...
@@ -2209,9 +2322,9 @@ inline void format_decimal(char *&buffer, T value) {
...
@@ -2209,9 +2322,9 @@ inline void format_decimal(char *&buffer, T value) {
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
FMT_GEN(n, FMT_MAKE_ARG)) { \
FMT_GEN(n, FMT_MAKE_ARG)) { \
const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF_##Char)}; \
const fmt::internal::Arg
Base
args[] = {FMT_GEN(n, FMT_MAKE_REF_##Char)}; \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__),
fmt::ArgList(
\
fmt::
ArgList(args, sizeof(args) / sizeof(*args)
)); \
fmt::
internal::ArgType<n, FMT_GEN(n, FMT_MAKE_ARG_TYPE)>::TYPE, args
)); \
}
}
# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
...
...
test/macro-test.cc
View file @
beb00edf
...
@@ -67,7 +67,7 @@ int result;
...
@@ -67,7 +67,7 @@ int result;
#define MAKE_TEST(func) \
#define MAKE_TEST(func) \
void func(const char *format, const fmt::ArgList &args) { \
void func(const char *format, const fmt::ArgList &args) { \
result = 0; \
result = 0; \
for (
std::size_t i = 0, n = args.size(); i < n
; ++i) \
for (
unsigned i = 0; args[i].type
; ++i) \
result += args[i].int_value; \
result += args[i].int_value; \
}
}
...
@@ -98,7 +98,7 @@ struct S {};
...
@@ -98,7 +98,7 @@ struct S {};
int
test_variadic
(
FMT_GEN
(
10
,
GET_TYPE
),
const
fmt
::
ArgList
&
args
)
{
\
int
test_variadic
(
FMT_GEN
(
10
,
GET_TYPE
),
const
fmt
::
ArgList
&
args
)
{
\
int
result
=
0
;
\
int
result
=
0
;
\
for
(
std
::
size_t
i
=
0
,
n
=
args
.
size
();
i
<
n
;
++
i
)
\
for
(
std
::
size_t
i
=
0
;
args
[
i
].
type
;
++
i
)
\
result
+=
args
[
i
].
int_value
;
\
result
+=
args
[
i
].
int_value
;
\
return
result
;
return
result
;
}
}
...
...
test/util-test.cc
View file @
beb00edf
...
@@ -42,8 +42,8 @@
...
@@ -42,8 +42,8 @@
#undef max
#undef max
using
fmt
::
StringRef
;
using
fmt
::
StringRef
;
using
fmt
::
internal
::
ArgBase
;
using
fmt
::
internal
::
Arg
;
using
fmt
::
internal
::
Arg
;
using
fmt
::
internal
::
MakeArg
;
namespace
{
namespace
{
...
@@ -52,6 +52,16 @@ template <typename Char>
...
@@ -52,6 +52,16 @@ template <typename Char>
std
::
basic_ostream
<
Char
>
&
operator
<<
(
std
::
basic_ostream
<
Char
>
&
os
,
Test
)
{
std
::
basic_ostream
<
Char
>
&
operator
<<
(
std
::
basic_ostream
<
Char
>
&
os
,
Test
)
{
return
os
<<
"test"
;
return
os
<<
"test"
;
}
}
template
<
typename
Char
,
typename
T
>
Arg
make_arg
(
const
T
&
value
)
{
Arg
arg
=
Arg
();
ArgBase
&
base
=
arg
;
base
=
fmt
::
internal
::
MakeArg
<
Char
>
(
value
);
arg
.
type
=
static_cast
<
Arg
::
Type
>
(
fmt
::
internal
::
ArgType
<
1
,
T
>::
TYPE
);
return
arg
;
}
}
// namespace
}
// namespace
TEST
(
UtilTest
,
Increment
)
{
TEST
(
UtilTest
,
Increment
)
{
...
@@ -74,7 +84,7 @@ struct ArgInfo;
...
@@ -74,7 +84,7 @@ struct ArgInfo;
#define ARG_INFO(type_code, Type, field) \
#define ARG_INFO(type_code, Type, field) \
template <> \
template <> \
struct ArgInfo<Arg::type_code> { \
struct ArgInfo<Arg::type_code> { \
static Type get(const Arg &arg) { return arg.field; } \
static Type get(const Arg
Base
&arg) { return arg.field; } \
};
};
ARG_INFO
(
INT
,
int
,
int_value
);
ARG_INFO
(
INT
,
int
,
int_value
);
...
@@ -90,7 +100,7 @@ ARG_INFO(POINTER, const void *, pointer_value);
...
@@ -90,7 +100,7 @@ ARG_INFO(POINTER, const void *, pointer_value);
ARG_INFO
(
CUSTOM
,
Arg
::
CustomValue
,
custom
);
ARG_INFO
(
CUSTOM
,
Arg
::
CustomValue
,
custom
);
#define CHECK_ARG_INFO(Type, field, value) { \
#define CHECK_ARG_INFO(Type, field, value) { \
Arg
arg = {Arg::Type
}; \
Arg
Base arg = {
}; \
arg.field = value; \
arg.field = value; \
EXPECT_EQ(value, ArgInfo<Arg::Type>::get(arg)); \
EXPECT_EQ(value, ArgInfo<Arg::Type>::get(arg)); \
}
}
...
@@ -109,14 +119,14 @@ TEST(ArgTest, ArgInfo) {
...
@@ -109,14 +119,14 @@ TEST(ArgTest, ArgInfo) {
CHECK_ARG_INFO
(
WSTRING
,
wstring
.
value
,
WSTR
);
CHECK_ARG_INFO
(
WSTRING
,
wstring
.
value
,
WSTR
);
int
p
=
0
;
int
p
=
0
;
CHECK_ARG_INFO
(
POINTER
,
pointer_value
,
&
p
);
CHECK_ARG_INFO
(
POINTER
,
pointer_value
,
&
p
);
Arg
arg
=
{
Arg
::
CUSTOM
};
Arg
Base
arg
=
{
};
arg
.
custom
.
value
=
&
p
;
arg
.
custom
.
value
=
&
p
;
EXPECT_EQ
(
&
p
,
ArgInfo
<
Arg
::
CUSTOM
>::
get
(
arg
).
value
);
EXPECT_EQ
(
&
p
,
ArgInfo
<
Arg
::
CUSTOM
>::
get
(
arg
).
value
);
}
}
#define EXPECT_ARG_(Char, type_code, MakeArgType, ExpectedType, value) { \
#define EXPECT_ARG_(Char, type_code, MakeArgType, ExpectedType, value) { \
MakeArgType input = static_cast<MakeArgType>(value); \
MakeArgType input = static_cast<MakeArgType>(value); \
Arg arg =
MakeA
rg<Char>(input); \
Arg arg =
make_a
rg<Char>(input); \
EXPECT_EQ(Arg::type_code, arg.type); \
EXPECT_EQ(Arg::type_code, arg.type); \
ExpectedType expected_value = static_cast<ExpectedType>(value); \
ExpectedType expected_value = static_cast<ExpectedType>(value); \
EXPECT_EQ(expected_value, ArgInfo<Arg::type_code>::get(arg)); \
EXPECT_EQ(expected_value, ArgInfo<Arg::type_code>::get(arg)); \
...
@@ -221,7 +231,7 @@ TEST(ArgTest, MakeArg) {
...
@@ -221,7 +231,7 @@ TEST(ArgTest, MakeArg) {
EXPECT_ARG
(
POINTER
,
const
void
*
,
&
n
);
EXPECT_ARG
(
POINTER
,
const
void
*
,
&
n
);
::
Test
t
;
::
Test
t
;
fmt
::
internal
::
Arg
arg
=
MakeA
rg
<
char
>
(
t
);
Arg
arg
=
make_a
rg
<
char
>
(
t
);
EXPECT_EQ
(
fmt
::
internal
::
Arg
::
CUSTOM
,
arg
.
type
);
EXPECT_EQ
(
fmt
::
internal
::
Arg
::
CUSTOM
,
arg
.
type
);
EXPECT_EQ
(
&
t
,
arg
.
custom
.
value
);
EXPECT_EQ
(
&
t
,
arg
.
custom
.
value
);
fmt
::
Writer
w
;
fmt
::
Writer
w
;
...
@@ -232,13 +242,13 @@ TEST(ArgTest, MakeArg) {
...
@@ -232,13 +242,13 @@ TEST(ArgTest, MakeArg) {
}
}
struct
Result
{
struct
Result
{
fmt
::
internal
::
Arg
arg
;
Arg
arg
;
Result
()
:
arg
(
MakeA
rg
<
char
>
(
0xdeadbeef
))
{}
Result
()
:
arg
(
make_a
rg
<
char
>
(
0xdeadbeef
))
{}
template
<
typename
T
>
template
<
typename
T
>
Result
(
const
T
&
value
)
:
arg
(
MakeA
rg
<
char
>
(
value
))
{}
Result
(
const
T
&
value
)
:
arg
(
make_a
rg
<
char
>
(
value
))
{}
Result
(
const
wchar_t
*
s
)
:
arg
(
MakeA
rg
<
wchar_t
>
(
s
))
{}
Result
(
const
wchar_t
*
s
)
:
arg
(
make_a
rg
<
wchar_t
>
(
s
))
{}
};
};
struct
TestVisitor
:
fmt
::
internal
::
ArgVisitor
<
TestVisitor
,
Result
>
{
struct
TestVisitor
:
fmt
::
internal
::
ArgVisitor
<
TestVisitor
,
Result
>
{
...
@@ -258,7 +268,8 @@ struct TestVisitor : fmt::internal::ArgVisitor<TestVisitor, Result> {
...
@@ -258,7 +268,8 @@ struct TestVisitor : fmt::internal::ArgVisitor<TestVisitor, Result> {
};
};
#define EXPECT_RESULT_(Char, type_code, value) { \
#define EXPECT_RESULT_(Char, type_code, value) { \
Result result = TestVisitor().visit(MakeArg<Char>(value)); \
Arg arg = make_arg<Char>(value); \
Result result = TestVisitor().visit(arg); \
EXPECT_EQ(Arg::type_code, result.arg.type); \
EXPECT_EQ(Arg::type_code, result.arg.type); \
EXPECT_EQ(value, ArgInfo<Arg::type_code>::get(result.arg)); \
EXPECT_EQ(value, ArgInfo<Arg::type_code>::get(result.arg)); \
}
}
...
@@ -283,7 +294,7 @@ TEST(ArgVisitorTest, VisitAll) {
...
@@ -283,7 +294,7 @@ TEST(ArgVisitorTest, VisitAll) {
const
void
*
p
=
STR
;
const
void
*
p
=
STR
;
EXPECT_RESULT
(
POINTER
,
p
);
EXPECT_RESULT
(
POINTER
,
p
);
::
Test
t
;
::
Test
t
;
Result
result
=
TestVisitor
().
visit
(
MakeA
rg
<
char
>
(
t
));
Result
result
=
TestVisitor
().
visit
(
make_a
rg
<
char
>
(
t
));
EXPECT_EQ
(
Arg
::
CUSTOM
,
result
.
arg
.
type
);
EXPECT_EQ
(
Arg
::
CUSTOM
,
result
.
arg
.
type
);
EXPECT_EQ
(
&
t
,
result
.
arg
.
custom
.
value
);
EXPECT_EQ
(
&
t
,
result
.
arg
.
custom
.
value
);
}
}
...
@@ -298,7 +309,7 @@ struct TestAnyVisitor : fmt::internal::ArgVisitor<TestAnyVisitor, Result> {
...
@@ -298,7 +309,7 @@ struct TestAnyVisitor : fmt::internal::ArgVisitor<TestAnyVisitor, Result> {
#undef EXPECT_RESULT
#undef EXPECT_RESULT
#define EXPECT_RESULT(type_code, value) { \
#define EXPECT_RESULT(type_code, value) { \
Result result = TestAnyVisitor().visit(
MakeA
rg<char>(value)); \
Result result = TestAnyVisitor().visit(
make_a
rg<char>(value)); \
EXPECT_EQ(Arg::type_code, result.arg.type); \
EXPECT_EQ(Arg::type_code, result.arg.type); \
EXPECT_EQ(value, ArgInfo<Arg::type_code>::get(result.arg)); \
EXPECT_EQ(value, ArgInfo<Arg::type_code>::get(result.arg)); \
}
}
...
@@ -318,7 +329,7 @@ struct TestUnhandledVisitor :
...
@@ -318,7 +329,7 @@ struct TestUnhandledVisitor :
};
};
#define EXPECT_UNHANDLED(value) \
#define EXPECT_UNHANDLED(value) \
EXPECT_STREQ("test", TestUnhandledVisitor().visit(
MakeA
rg<wchar_t>(value)));
EXPECT_STREQ("test", TestUnhandledVisitor().visit(
make_a
rg<wchar_t>(value)));
TEST
(
ArgVisitorTest
,
VisitUnhandledArg
)
{
TEST
(
ArgVisitorTest
,
VisitUnhandledArg
)
{
EXPECT_UNHANDLED
(
42
);
EXPECT_UNHANDLED
(
42
);
...
@@ -338,7 +349,8 @@ TEST(ArgVisitorTest, VisitUnhandledArg) {
...
@@ -338,7 +349,8 @@ TEST(ArgVisitorTest, VisitUnhandledArg) {
}
}
TEST
(
ArgVisitorTest
,
VisitInvalidArg
)
{
TEST
(
ArgVisitorTest
,
VisitInvalidArg
)
{
Arg
arg
=
{
static_cast
<
Arg
::
Type
>
(
Arg
::
CUSTOM
+
1
)};
Arg
arg
=
Arg
();
arg
.
type
=
static_cast
<
Arg
::
Type
>
(
Arg
::
CUSTOM
+
1
);
EXPECT_DEBUG_DEATH
(
TestVisitor
().
visit
(
arg
),
"Assertion"
);
EXPECT_DEBUG_DEATH
(
TestVisitor
().
visit
(
arg
),
"Assertion"
);
}
}
...
...
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