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
ca171307
Commit
ca171307
authored
Sep 04, 2013
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
TempFormatter -> Formatter. Complete refactoring.
parent
50cf5e17
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
175 additions
and
153 deletions
+175
-153
format.h
format.h
+131
-103
format_test.cc
format_test.cc
+44
-50
No files found.
format.h
View file @
ca171307
...
...
@@ -237,7 +237,7 @@ class FormatterProxy;
or as a result of a formatting operation. It is most useful as a parameter
type to allow passing different types of strings in a function, for example::
Temp
Formatter<> Format(StringRef format);
Formatter<> Format(StringRef format);
Format("{}") << 42;
Format(std::string("{}")) << 42;
...
...
@@ -432,25 +432,17 @@ DEFINE_INT_FORMATTERS(long)
DEFINE_INT_FORMATTERS
(
unsigned
)
DEFINE_INT_FORMATTERS
(
unsigned
long
)
template
<
typename
Action
>
template
<
typename
Char
>
class
BasicFormatter
;
template
<
typename
Action
,
typename
Char
>
class
TempFormatter
;
/**
A formatting action that does nothing.
*/
class
NoAction
{
public:
/** Does nothing. */
template
<
typename
Char
>
void
operator
()(
const
BasicFormatter
<
Char
>
&
)
const
{}
};
template
<
typename
Char
>
class
BasicWriter
{
protected:
private:
enum
{
INLINE_BUFFER_SIZE
=
500
};
mutable
internal
::
Array
<
Char
,
INLINE_BUFFER_SIZE
>
buffer_
;
// Output buffer.
friend
class
BasicFormatter
<
Char
>
;
#if _SECURE_SCL
typedef
stdext
::
checked_array_iterator
<
Char
*>
CharPtr
;
static
Char
*
GetBase
(
CharPtr
p
)
{
return
p
.
base
();
}
...
...
@@ -459,17 +451,12 @@ class BasicWriter {
static
Char
*
GetBase
(
Char
*
p
)
{
return
p
;
}
#endif
private:
static
void
FormatDecimal
(
CharPtr
buffer
,
uint64_t
value
,
unsigned
num_digits
);
protected:
static
CharPtr
FillPadding
(
CharPtr
buffer
,
unsigned
total_size
,
std
::
size_t
content_size
,
char
fill
);
enum
{
INLINE_BUFFER_SIZE
=
500
};
mutable
internal
::
Array
<
Char
,
INLINE_BUFFER_SIZE
>
buffer_
;
// Output buffer.
// Grows the buffer by n characters and returns a pointer to the newly
// allocated area.
CharPtr
GrowBuffer
(
std
::
size_t
n
)
{
...
...
@@ -560,12 +547,10 @@ private:
/**
Formats a string appending the output to the internal buffer.
Arguments are accepted through the returned `
Temp
Formatter` object
Arguments are accepted through the returned `
Basic
Formatter` object
using inserter operator `<<`.
*/
TempFormatter
<
NoAction
,
Char
>
Format
(
StringRef
format
)
{
return
TempFormatter
<
NoAction
,
Char
>
(
format
);
}
BasicFormatter
<
Char
>
Format
(
StringRef
format
);
void
Clear
()
{
buffer_
.
clear
();
...
...
@@ -881,6 +866,11 @@ BasicWriter<Char> &BasicWriter<Char>::operator<<(
return
*
this
;
}
template
<
typename
Char
>
BasicFormatter
<
Char
>
BasicWriter
<
Char
>::
Format
(
StringRef
format
)
{
return
BasicFormatter
<
Char
>
(
*
this
,
format
.
c_str
());
}
typedef
BasicWriter
<
char
>
Writer
;
typedef
BasicWriter
<
wchar_t
>
WWriter
;
...
...
@@ -907,6 +897,7 @@ void FormatCustomArg(
functionality similar to Python's `str.format
<http://docs.python.org/3/library/stdtypes.html#str.format>`__.
The output is stored in a memory buffer that grows dynamically.
The class provides operator<< for feeding formatting arguments.
**Example**::
...
...
@@ -923,11 +914,16 @@ void FormatCustomArg(
(-3.140000, +3.140000)
The buffer can be accessed using :meth:`data` or :meth:`c_str`.
Objects of this class normally exists only as temporaries returned
by one of the formatting functions.
\endrst
*/
template
<
typename
Char
>
class
BasicFormatter
:
public
BasicWriter
<
Char
>
{
class
BasicFormatter
{
private:
BasicWriter
<
Char
>
*
writer_
;
enum
Type
{
// Numeric types should go first.
INT
,
UINT
,
LONG
,
ULONG
,
DOUBLE
,
LONG_DOUBLE
,
...
...
@@ -1026,7 +1022,7 @@ class BasicFormatter : public BasicWriter<Char> {
// constructed before the Arg object, it will be destroyed after,
// so it will be alive in the Arg's destructor where Format is called.
// Note that the string object will not necessarily be alive when
// the destructor of
Temp
Formatter is called.
// the destructor of
Basic
Formatter is called.
if
(
formatter
)
formatter
->
CompleteFormatting
();
}
...
...
@@ -1039,11 +1035,12 @@ class BasicFormatter : public BasicWriter<Char> {
int
num_open_braces_
;
int
next_arg_index_
;
template
<
typename
Action
,
typename
CharT
>
friend
class
TempFormatter
;
// TODO
friend
class
internal
::
FormatterProxy
<
Char
>
;
// Forbid copying other than from a temporary. Do not implement.
BasicFormatter
(
BasicFormatter
&
);
BasicFormatter
&
operator
=
(
const
BasicFormatter
&
);
void
Add
(
const
Arg
&
arg
)
{
args_
.
push_back
(
&
arg
);
}
...
...
@@ -1059,6 +1056,20 @@ class BasicFormatter : public BasicWriter<Char> {
void
DoFormat
();
struct
Proxy
{
BasicWriter
<
Char
>
*
writer
;
const
Char
*
format
;
Proxy
(
BasicWriter
<
Char
>
*
w
,
const
Char
*
fmt
)
:
writer
(
w
),
format
(
fmt
)
{}
};
protected
:
const
Char
*
TakeFormatString
()
{
const
Char
*
format
=
this
->
format_
;
this
->
format_
=
0
;
return
format
;
}
void
CompleteFormatting
()
{
if
(
!
format_
)
return
;
DoFormat
();
...
...
@@ -1068,11 +1079,40 @@ class BasicFormatter : public BasicWriter<Char> {
/**
Constructs a formatter with an empty output buffer.
*/
BasicFormatter
(
const
Char
*
format
=
0
)
:
format_
(
format
)
{}
}
;
BasicFormatter
(
BasicWriter
<
Char
>
&
w
,
const
Char
*
format
=
0
)
:
writer_
(
&
w
),
format_
(
format
)
{}
typedef
BasicFormatter
<
char
>
Formatter
;
typedef
BasicFormatter
<
wchar_t
>
WFormatter
;
~
BasicFormatter
()
{
CompleteFormatting
();
}
/**
Constructs a formatter from a proxy object.
*/
BasicFormatter
(
const
Proxy
&
p
)
:
BasicFormatter
<
Char
>
(
*
p
.
writer
,
p
.
format
)
{}
operator
Proxy
()
{
const
Char
*
format
=
format_
;
format_
=
0
;
return
Proxy
(
writer_
,
format
);
}
// Feeds an argument to a formatter.
BasicFormatter
&
operator
<<
(
const
Arg
&
arg
)
{
arg
.
formatter
=
this
;
Add
(
arg
);
return
*
this
;
}
operator
internal
::
FormatterProxy
<
Char
>
()
{
return
internal
::
FormatterProxy
<
Char
>
(
this
);
}
operator
StringRef
()
{
CompleteFormatting
();
return
StringRef
(
writer_
->
c_str
(),
writer_
->
size
());
}
}
;
template
<
typename
Char
>
inline
std
::
basic_string
<
Char
>
str
(
const
BasicWriter
<
Char
>
&
f
)
{
...
...
@@ -1098,19 +1138,11 @@ class FormatterProxy {
public:
explicit
FormatterProxy
(
BasicFormatter
<
Char
>
*
f
)
:
formatter_
(
f
)
{}
Basic
Format
ter
<
Char
>
*
Format
()
{
Basic
Wri
ter
<
Char
>
*
Format
()
{
formatter_
->
CompleteFormatting
();
return
formatter_
;
return
formatter_
->
writer_
;
}
};
// This is a transient object that normally exists only as a temporary
// returned by one of the formatting functions. It stores a reference
// to a formatter and provides operator<< that feeds arguments to the
// formatter.
template
<
typename
Char
>
class
ArgInserter
{
};
}
/**
...
...
@@ -1128,27 +1160,34 @@ inline const char *c_str(internal::FormatterProxy<char> p) {
return
p
.
Format
()
->
c_str
();
}
/**
A formatting action that does nothing.
*/
class
NoAction
{
public:
/** Does nothing. */
template
<
typename
Char
>
void
operator
()(
const
BasicWriter
<
Char
>
&
)
const
{}
};
/**
A formatter with an action performed when formatting is complete.
Objects of this class normally exist only as temporaries returned
by one of the formatting functions
which explains the name
.
by one of the formatting functions.
*/
template
<
typename
Action
=
NoAction
,
typename
Char
=
char
>
class
TempFormatter
{
private:
friend
class
fmt
::
BasicFormatter
<
Char
>
;
friend
class
fmt
::
StringRef
;
class
Formatter
:
private
Action
,
public
BasicFormatter
<
Char
>
{
private:
friend
class
fmt
::
BasicFormatter
<
Char
>
;
friend
class
fmt
::
StringRef
;
private:
BasicFormatter
<
Char
>
formatter_
;
Action
action_
;
BasicWriter
<
Char
>
writer_
;
bool
inactive_
;
// Forbid copying other than from a temporary. Do not implement.
TempFormatter
(
TempFormatter
&
);
// Do not implement.
TempFormatter
&
operator
=
(
const
TempFormatter
&
);
Formatter
(
Formatter
&
);
Formatter
&
operator
=
(
const
Formatter
&
);
struct
Proxy
{
const
char
*
format
;
...
...
@@ -1160,55 +1199,42 @@ private:
public:
/**
\rst
Constructs a
temporary
formatter with a format string and an action.
Constructs a formatter with a format string and an action.
The action should be an unary function object that takes a const
reference to :cpp:class:`fmt::BasicFormatter` as an argument.
See :cpp:class:`fmt::NoAction` and :cpp:class:`fmt::Write` for
examples of action classes.
\endrst
*/
explicit
TempFormatter
(
StringRef
format
,
Action
a
=
Action
())
:
formatter_
(
format
.
c_str
()),
action_
(
a
),
inactive_
(
false
)
{
explicit
Formatter
(
StringRef
format
,
Action
a
=
Action
())
:
Action
(
a
),
BasicFormatter
<
Char
>
(
writer_
,
format
.
c_str
()),
inactive_
(
false
)
{
}
/**
Constructs a
temporary
formatter from a proxy object.
Constructs a formatter from a proxy object.
*/
TempFormatter
(
const
Proxy
&
p
)
:
formatter_
(
p
.
format
),
action_
(
p
.
action
),
inactive_
(
false
)
{}
Formatter
(
const
Proxy
&
p
)
:
Action
(
p
.
action
),
BasicFormatter
<
Char
>
(
writer_
,
p
.
format
),
inactive_
(
false
)
{
}
/**
Performs the actual formatting, invokes the action and destroys the object.
*/
~
Temp
Formatter
()
FMT_NOEXCEPT
(
false
)
{
~
Formatter
()
FMT_NOEXCEPT
(
false
)
{
if
(
!
inactive_
)
{
formatter_
.
CompleteFormatting
();
action_
(
format
ter_
);
this
->
CompleteFormatting
();
(
*
this
)(
wri
ter_
);
}
}
/**
Converts
a temporary
formatter into a proxy object.
Converts
the
formatter into a proxy object.
*/
operator
Proxy
()
{
inactive_
=
true
;
return
Proxy
(
formatter_
.
format_
,
action_
);
}
// Feeds an argument to a formatter.
TempFormatter
&
operator
<<
(
const
typename
BasicFormatter
<
Char
>::
Arg
&
arg
)
{
arg
.
formatter
=
&
formatter_
;
formatter_
.
Add
(
arg
);
return
*
this
;
}
operator
internal
::
FormatterProxy
<
Char
>
()
{
return
internal
::
FormatterProxy
<
Char
>
(
&
formatter_
);
}
operator
StringRef
()
{
formatter_
.
CompleteFormatting
();
return
StringRef
(
formatter_
.
c_str
(),
formatter_
.
size
());
return
Proxy
(
this
->
TakeFormatString
(),
*
this
);
}
};
...
...
@@ -1229,22 +1255,22 @@ private:
See also `Format String Syntax`_.
\endrst
*/
inline
Temp
Formatter
<>
Format
(
StringRef
format
)
{
return
Temp
Formatter
<>
(
format
);
inline
Formatter
<>
Format
(
StringRef
format
)
{
return
Formatter
<>
(
format
);
}
// A formatting action that writes formatted output to stdout.
struct
Write
{
void
operator
()(
const
Basic
Formatter
<
char
>
&
f
)
const
{
std
::
fwrite
(
f
.
data
(),
1
,
f
.
size
(),
stdout
);
void
operator
()(
const
Basic
Writer
<
char
>
&
w
)
const
{
std
::
fwrite
(
w
.
data
(),
1
,
w
.
size
(),
stdout
);
}
};
// Formats a string and prints it to stdout.
// Example:
// Print("Elapsed time: {0:.2f} seconds") << 1.23;
inline
Temp
Formatter
<
Write
>
Print
(
StringRef
format
)
{
return
Temp
Formatter
<
Write
>
(
format
);
inline
Formatter
<
Write
>
Print
(
StringRef
format
)
{
return
Formatter
<
Write
>
(
format
);
}
// Throws Exception(message) if format contains '}', otherwise throws
...
...
@@ -1322,18 +1348,20 @@ void BasicFormatter<Char>::DoFormat() {
format_
=
0
;
next_arg_index_
=
0
;
const
Char
*
s
=
start
;
typedef
internal
::
Array
<
Char
,
BasicWriter
<
Char
>::
INLINE_BUFFER_SIZE
>
Buffer
;
Writer
&
writer
=
*
writer_
;
while
(
*
s
)
{
char
c
=
*
s
++
;
if
(
c
!=
'{'
&&
c
!=
'}'
)
continue
;
if
(
*
s
==
c
)
{
this
->
buffer_
.
append
(
start
,
s
);
writer
.
buffer_
.
append
(
start
,
s
);
start
=
++
s
;
continue
;
}
if
(
c
==
'}'
)
throw
FormatError
(
"unmatched '}' in format"
);
num_open_braces_
=
1
;
this
->
buffer_
.
append
(
start
,
s
-
1
);
writer
.
buffer_
.
append
(
start
,
s
-
1
);
const
Arg
&
arg
=
ParseArgIndex
(
s
);
...
...
@@ -1475,22 +1503,22 @@ void BasicFormatter<Char>::DoFormat() {
// Format argument.
switch
(
arg
.
type
)
{
case
INT
:
this
->
FormatInt
(
arg
.
int_value
,
spec
);
writer
.
FormatInt
(
arg
.
int_value
,
spec
);
break
;
case
UINT
:
this
->
FormatInt
(
arg
.
uint_value
,
spec
);
writer
.
FormatInt
(
arg
.
uint_value
,
spec
);
break
;
case
LONG
:
this
->
FormatInt
(
arg
.
long_value
,
spec
);
writer
.
FormatInt
(
arg
.
long_value
,
spec
);
break
;
case
ULONG
:
this
->
FormatInt
(
arg
.
ulong_value
,
spec
);
writer
.
FormatInt
(
arg
.
ulong_value
,
spec
);
break
;
case
DOUBLE
:
this
->
FormatDouble
(
arg
.
double_value
,
spec
,
precision
);
writer
.
FormatDouble
(
arg
.
double_value
,
spec
,
precision
);
break
;
case
LONG_DOUBLE
:
this
->
FormatDouble
(
arg
.
long_double_value
,
spec
,
precision
);
writer
.
FormatDouble
(
arg
.
long_double_value
,
spec
,
precision
);
break
;
case
CHAR
:
{
if
(
spec
.
type_
&&
spec
.
type_
!=
'c'
)
...
...
@@ -1498,17 +1526,17 @@ void BasicFormatter<Char>::DoFormat() {
typedef
typename
BasicWriter
<
Char
>::
CharPtr
CharPtr
;
CharPtr
out
=
CharPtr
();
if
(
spec
.
width_
>
1
)
{
out
=
this
->
GrowBuffer
(
spec
.
width_
);
out
=
writer
.
GrowBuffer
(
spec
.
width_
);
if
(
spec
.
align_
==
ALIGN_RIGHT
)
{
std
::
fill_n
(
out
,
spec
.
width_
-
1
,
spec
.
fill_
);
out
+=
spec
.
width_
-
1
;
}
else
if
(
spec
.
align_
==
ALIGN_CENTER
)
{
out
=
this
->
FillPadding
(
out
,
spec
.
width_
,
1
,
spec
.
fill_
);
out
=
writer
.
FillPadding
(
out
,
spec
.
width_
,
1
,
spec
.
fill_
);
}
else
{
std
::
fill_n
(
out
+
1
,
spec
.
width_
-
1
,
spec
.
fill_
);
}
}
else
{
out
=
this
->
GrowBuffer
(
1
);
out
=
writer
.
GrowBuffer
(
1
);
}
*
out
=
arg
.
int_value
;
break
;
...
...
@@ -1524,7 +1552,7 @@ void BasicFormatter<Char>::DoFormat() {
if
(
*
str
)
size
=
std
::
strlen
(
str
);
}
this
->
FormatString
(
str
,
size
,
spec
);
writer
.
FormatString
(
str
,
size
,
spec
);
break
;
}
case
POINTER
:
...
...
@@ -1532,19 +1560,19 @@ void BasicFormatter<Char>::DoFormat() {
internal
::
ReportUnknownType
(
spec
.
type_
,
"pointer"
);
spec
.
flags_
=
HASH_FLAG
;
spec
.
type_
=
'x'
;
this
->
FormatInt
(
reinterpret_cast
<
uintptr_t
>
(
arg
.
pointer_value
),
spec
);
writer
.
FormatInt
(
reinterpret_cast
<
uintptr_t
>
(
arg
.
pointer_value
),
spec
);
break
;
case
CUSTOM
:
if
(
spec
.
type_
)
internal
::
ReportUnknownType
(
spec
.
type_
,
"object"
);
arg
.
custom
.
format
(
*
this
,
arg
.
custom
.
value
,
spec
);
arg
.
custom
.
format
(
writer
,
arg
.
custom
.
value
,
spec
);
break
;
default:
assert
(
false
);
break
;
}
}
this
->
buffer_
.
append
(
start
,
s
);
writer
.
buffer_
.
append
(
start
,
s
);
}
}
...
...
format_test.cc
View file @
ca171307
...
...
@@ -47,7 +47,6 @@ using std::size_t;
using
fmt
::
internal
::
Array
;
using
fmt
::
BasicWriter
;
using
fmt
::
Formatter
;
using
fmt
::
Format
;
using
fmt
::
FormatError
;
using
fmt
::
StringRef
;
...
...
@@ -214,6 +213,13 @@ TEST(ArrayTest, Append) {
EXPECT_EQ
(
15u
,
array
.
capacity
());
}
TEST
(
WriterTest
,
WriterCtor
)
{
Writer
w
;
EXPECT_EQ
(
0u
,
w
.
size
());
EXPECT_STREQ
(
""
,
w
.
c_str
());
EXPECT_EQ
(
""
,
w
.
str
());
}
TEST
(
WriterTest
,
WriteInt
)
{
EXPECT_EQ
(
"42"
,
str
(
Writer
()
<<
42
));
EXPECT_EQ
(
"-42"
,
str
(
Writer
()
<<
-
42
));
...
...
@@ -325,6 +331,20 @@ TEST(WriterTest, NoConflictWithIOManip) {
EXPECT_EQ
(
"12"
,
str
(
Writer
()
<<
oct
(
012
)));
}
TEST
(
WriterTest
,
Format
)
{
Writer
w
;
w
.
Format
(
"part{0}"
)
<<
1
;
EXPECT_EQ
(
strlen
(
"part1"
),
w
.
size
());
EXPECT_STREQ
(
"part1"
,
w
.
c_str
());
EXPECT_STREQ
(
"part1"
,
w
.
data
());
EXPECT_EQ
(
"part1"
,
w
.
str
());
w
.
Format
(
"part{0}"
)
<<
2
;
EXPECT_EQ
(
strlen
(
"part1part2"
),
w
.
size
());
EXPECT_STREQ
(
"part1part2"
,
w
.
c_str
());
EXPECT_STREQ
(
"part1part2"
,
w
.
data
());
EXPECT_EQ
(
"part1part2"
,
w
.
str
());
}
TEST
(
WriterTest
,
WWriter
)
{
EXPECT_EQ
(
L"cafe"
,
str
(
fmt
::
WWriter
()
<<
fmt
::
hex
(
0xcafe
)));
}
...
...
@@ -1015,31 +1035,13 @@ TEST(FormatterTest, FormatStringFromSpeedTest) {
<<
reinterpret_cast
<
void
*>
(
1000
)
<<
'X'
));
}
TEST
(
WriterTest
,
WriterCtor
)
{
TEST
(
FormatterTest
,
StringAccess
)
{
Writer
w
;
EXPECT_EQ
(
0u
,
w
.
size
());
EXPECT_STREQ
(
""
,
w
.
c_str
());
EXPECT_EQ
(
""
,
w
.
str
());
w
.
Format
(
"part{0}"
)
<<
1
;
w
.
Format
(
"part{0}"
)
<<
2
;
EXPECT_EQ
(
"part1part2"
,
w
.
str
());
EXPECT_EQ
(
"1"
,
str
(
w
.
Format
(
"{0}"
)
<<
1
));
EXPECT_STREQ
(
"12"
,
c_str
(
w
.
Format
(
"{0}"
)
<<
2
));
}
/*TEST(FormatterTest, FormatterAppend) {
Formatter format;
format("part{0}") << 1;
EXPECT_EQ(strlen("part1"), format.size());
EXPECT_STREQ("part1", format.c_str());
EXPECT_STREQ("part1", format.data());
EXPECT_EQ("part1", format.str());
format("part{0}") << 2;
EXPECT_EQ(strlen("part1part2"), format.size());
EXPECT_STREQ("part1part2", format.c_str());
EXPECT_STREQ("part1part2", format.data());
EXPECT_EQ("part1part2", format.str());
}*/
TEST
(
FormatTest
,
FormatExamples
)
{
TEST
(
FormatterTest
,
FormatExamples
)
{
using
fmt
::
hex
;
EXPECT_EQ
(
"0000cafe"
,
str
(
BasicWriter
<
char
>
()
<<
pad
(
hex
(
0xcafe
),
8
,
'0'
)));
...
...
@@ -1050,31 +1052,23 @@ TEST(FormatTest, FormatExamples) {
EXPECT_EQ
(
"42"
,
str
(
Format
(
std
::
string
(
"{}"
))
<<
42
));
EXPECT_EQ
(
"42"
,
str
(
Format
(
Format
(
"{{}}"
))
<<
42
));
// TODO
/*Formatter format;
format("Current point:\n");
format("({0:+f}, {1:+f})\n") << -3.14 << 3.14;
EXPECT_EQ("Current point:\n(-3.140000, +3.140000)\n", format.str());
Writer
writer
;
writer
.
Format
(
"Current point:
\n
"
);
writer
.
Format
(
"({0:+f}, {1:+f})
\n
"
)
<<
-
3.14
<<
3.14
;
EXPECT_EQ
(
"Current point:
\n
(-3.140000, +3.140000)
\n
"
,
writer
.
str
());
{
fmt::
Formatter format
;
fmt
::
Writer
writer
;
for
(
int
i
=
0
;
i
<
10
;
i
++
)
format("{0
}") << i;
std::string s =
format
.str(); // s == 0123456789
writer
.
Format
(
"{
}"
)
<<
i
;
std
::
string
s
=
writer
.
str
();
// s == 0123456789
EXPECT_EQ
(
"0123456789"
,
s
);
}
*/
}
}
// TODO
/*TEST(FormatterTest, ArgInserter) {
Formatter format;
EXPECT_EQ("1", str(format("{0}") << 1));
EXPECT_STREQ("12", c_str(format("{0}") << 2));
}*/
TEST
(
FormatterTest
,
StrNamespace
)
{
fmt
::
str
(
Format
(
""
));
fmt
::
c_str
(
Format
(
""
));
str
(
Format
(
""
));
c_str
(
Format
(
""
));
}
TEST
(
FormatterTest
,
ExceptionInNestedFormat
)
{
...
...
@@ -1101,7 +1095,7 @@ struct CountCalls {
CountCalls
(
int
&
num_calls
)
:
num_calls
(
num_calls
)
{}
void
operator
()(
const
Format
ter
&
)
const
{
void
operator
()(
const
Wri
ter
&
)
const
{
++
num_calls
;
}
};
...
...
@@ -1109,7 +1103,7 @@ struct CountCalls {
TEST
(
TempFormatterTest
,
Action
)
{
int
num_calls
=
0
;
{
fmt
::
Temp
Formatter
<
CountCalls
>
af
(
"test"
,
CountCalls
(
num_calls
));
fmt
::
Formatter
<
CountCalls
>
af
(
"test"
,
CountCalls
(
num_calls
));
EXPECT_EQ
(
0
,
num_calls
);
}
EXPECT_EQ
(
1
,
num_calls
);
...
...
@@ -1118,7 +1112,7 @@ TEST(TempFormatterTest, Action) {
TEST
(
TempFormatterTest
,
ActionNotCalledOnError
)
{
int
num_calls
=
0
;
{
typedef
fmt
::
Temp
Formatter
<
CountCalls
>
TestFormatter
;
typedef
fmt
::
Formatter
<
CountCalls
>
TestFormatter
;
EXPECT_THROW
(
TestFormatter
af
(
"{0"
,
CountCalls
(
num_calls
)),
FormatError
);
}
EXPECT_EQ
(
0
,
num_calls
);
...
...
@@ -1131,8 +1125,8 @@ TEST(TempFormatterTest, ActionNotCalledOnError) {
TEST
(
TempFormatterTest
,
ArgLifetime
)
{
// The following code is for testing purposes only. It is a definite abuse
// of the API and shouldn't be used in real applications.
const
fmt
::
Temp
Formatter
<>
&
af
=
fmt
::
Format
(
"{0}"
);
const_cast
<
fmt
::
Temp
Formatter
<>&>
(
af
)
<<
std
::
string
(
"test"
);
const
fmt
::
Formatter
<>
&
af
=
fmt
::
Format
(
"{0}"
);
const_cast
<
fmt
::
Formatter
<>&>
(
af
)
<<
std
::
string
(
"test"
);
// String object passed as an argument to TempFormatter has
// been destroyed, but ArgInserter dtor hasn't been called yet.
// But that's OK since the Arg's dtor takes care of this and
...
...
@@ -1146,13 +1140,13 @@ TEST(TempFormatterTest, ConvertToStringRef) {
}
struct
PrintError
{
void
operator
()(
const
fmt
::
Formatter
&
f
)
const
{
std
::
cerr
<<
"Error: "
<<
f
.
str
()
<<
std
::
endl
;
void
operator
()(
const
fmt
::
Writer
&
w
)
const
{
std
::
cerr
<<
"Error: "
<<
w
.
str
()
<<
std
::
endl
;
}
};
fmt
::
Temp
Formatter
<
PrintError
>
ReportError
(
const
char
*
format
)
{
return
fmt
::
Temp
Formatter
<
PrintError
>
(
format
);
fmt
::
Formatter
<
PrintError
>
ReportError
(
const
char
*
format
)
{
return
fmt
::
Formatter
<
PrintError
>
(
format
);
}
TEST
(
TempFormatterTest
,
Examples
)
{
...
...
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