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
b98b2e98
Commit
b98b2e98
authored
Dec 10, 2012
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement formatting of integers.
parent
c5dce1ca
Changes
3
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
310 additions
and
185 deletions
+310
-185
format.cc
format.cc
+198
-127
format.h
format.h
+19
-19
format_test.cc
format_test.cc
+93
-39
No files found.
format.cc
View file @
b98b2e98
This diff is collapsed.
Click to expand it.
format.h
View file @
b98b2e98
...
...
@@ -53,7 +53,6 @@ class Formatter {
struct
{
union
{
const
char
*
string_value
;
const
wchar_t
*
wstring_value
;
const
void
*
pointer_value
;
};
std
::
size_t
size
;
...
...
@@ -74,7 +73,6 @@ class Formatter {
explicit
Arg
(
char
value
)
:
type
(
CHAR
),
int_value
(
value
)
{}
explicit
Arg
(
const
char
*
value
,
std
::
size_t
size
=
0
)
:
type
(
STRING
),
string_value
(
value
),
size
(
size
)
{}
explicit
Arg
(
const
wchar_t
*
value
)
:
type
(
WSTRING
),
wstring_value
(
value
)
{}
explicit
Arg
(
const
void
*
value
)
:
type
(
POINTER
),
pointer_value
(
value
)
{}
explicit
Arg
(
const
void
*
value
,
FormatFunc
f
)
:
type
(
CUSTOM
),
custom_value
(
value
),
format
(
f
)
{}
...
...
@@ -92,10 +90,14 @@ class Formatter {
args_
.
push_back
(
arg
);
}
// Formats an
argument of a built-in type, such as "int" or "double"
.
// Formats an
integer
.
template
<
typename
T
>
void
FormatBuiltinArg
(
const
char
*
format
,
const
T
&
arg
,
int
width
,
int
precision
);
void
FormatInt
(
T
value
,
unsigned
flags
,
int
width
,
char
type
);
// Formats a floating point number.
template
<
typename
T
>
void
FormatDouble
(
T
value
,
unsigned
flags
,
int
width
,
int
precision
,
char
type
);
// Formats an argument of a custom type, such as a user-defined class.
template
<
typename
T
>
...
...
@@ -199,11 +201,6 @@ class ArgFormatter {
return
*
this
;
}
ArgFormatter
&
operator
<<
(
const
wchar_t
*
value
)
{
formatter_
->
Add
(
Formatter
::
Arg
(
value
));
return
*
this
;
}
ArgFormatter
&
operator
<<
(
const
std
::
string
&
value
)
{
formatter_
->
Add
(
Formatter
::
Arg
(
value
.
c_str
(),
value
.
size
()));
return
*
this
;
...
...
@@ -214,10 +211,16 @@ class ArgFormatter {
return
*
this
;
}
// This method
is not implemented intentionally to disallow output of
// This method
contains a deliberate error to disallow formatting
// arbitrary pointers. If you want to output a pointer cast it to void*.
template
<
typename
T
>
ArgFormatter
&
operator
<<
(
const
T
*
value
);
ArgFormatter
&
operator
<<
(
const
T
*
value
)
{
"Formatting arbitrary pointers is not allowed"
=
value
;
}
// This method is not implemented intentionally to disallow formatting
// wide characters.
ArgFormatter
&
operator
<<
(
wchar_t
value
);
template
<
typename
T
>
ArgFormatter
&
operator
<<
(
T
*
value
)
{
...
...
@@ -253,13 +256,10 @@ void Formatter::FormatCustomArg(const void *arg, int width) {
std
::
ostringstream
os
;
os
<<
value
;
std
::
string
str
(
os
.
str
());
if
(
width
<
0
)
{
// Extra char is reserved for terminating '\0'.
buffer_
.
reserve
(
buffer_
.
size
()
+
str
.
size
()
+
1
);
buffer_
.
insert
(
buffer_
.
end
(),
str
.
begin
(),
str
.
end
());
return
;
}
FormatBuiltinArg
(
"%-*s"
,
str
.
c_str
(),
width
,
-
1
);
buffer_
.
reserve
(
buffer_
.
size
()
+
std
::
max
<
std
::
size_t
>
(
width
,
str
.
size
()));
buffer_
.
insert
(
buffer_
.
end
(),
str
.
begin
(),
str
.
end
());
if
(
width
>
str
.
size
())
buffer_
.
resize
(
buffer_
.
size
()
+
width
-
str
.
size
(),
' '
);
}
inline
ArgFormatter
Formatter
::
operator
()(
const
char
*
format
)
{
...
...
format_test.cc
View file @
b98b2e98
...
...
@@ -71,7 +71,7 @@ TEST(FormatterTest, NoArgs) {
EXPECT_EQ
(
"test"
,
str
(
Format
(
"test"
)));
}
TEST
(
FormatterTest
,
Args
)
{
TEST
(
FormatterTest
,
Args
InDifferentPositions
)
{
EXPECT_EQ
(
"42"
,
str
(
Format
(
"{0}"
)
<<
42
));
EXPECT_EQ
(
"before 42"
,
str
(
Format
(
"before {0}"
)
<<
42
));
EXPECT_EQ
(
"42 after"
,
str
(
Format
(
"{0} after"
)
<<
42
));
...
...
@@ -86,13 +86,13 @@ TEST(FormatterTest, ArgErrors) {
EXPECT_THROW_MSG
(
Format
(
"{}"
),
FormatError
,
"missing argument index in format string"
);
EXPECT_THROW_MSG
(
Format
(
"{0"
),
FormatError
,
"unmatched '{' in format"
);
EXPECT_THROW_MSG
(
Format
(
"{0}"
),
std
::
out_of_range
,
EXPECT_THROW_MSG
(
Format
(
"{0}"
),
FormatError
,
"argument index is out of range in format"
);
char
format
[
256
];
std
::
sprintf
(
format
,
"{%u"
,
UINT_MAX
);
EXPECT_THROW_MSG
(
Format
(
format
),
FormatError
,
"unmatched '{' in format"
);
std
::
sprintf
(
format
,
"{%u}"
,
UINT_MAX
);
EXPECT_THROW_MSG
(
Format
(
format
),
std
::
out_of_range
,
EXPECT_THROW_MSG
(
Format
(
format
),
FormatError
,
"argument index is out of range in format"
);
if
(
ULONG_MAX
>
UINT_MAX
)
{
std
::
sprintf
(
format
,
"{%lu"
,
UINT_MAX
+
1l
);
...
...
@@ -130,8 +130,6 @@ TEST(FormatterTest, PlusFlag) {
FormatError
,
"format specifier '+' requires numeric argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:+}"
)
<<
"abc"
,
FormatError
,
"format specifier '+' requires numeric argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:+}"
)
<<
L"abc"
,
FormatError
,
"format specifier '+' requires numeric argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:+}"
)
<<
reinterpret_cast
<
void
*>
(
0x42
),
FormatError
,
"format specifier '+' requires numeric argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:+}"
)
<<
TestString
(),
...
...
@@ -152,8 +150,6 @@ TEST(FormatterTest, ZeroFlag) {
FormatError
,
"format specifier '0' requires numeric argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:05}"
)
<<
"abc"
,
FormatError
,
"format specifier '0' requires numeric argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:05}"
)
<<
L"abc"
,
FormatError
,
"format specifier '0' requires numeric argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:05}"
)
<<
reinterpret_cast
<
void
*>
(
0x42
),
FormatError
,
"format specifier '0' requires numeric argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:05}"
)
<<
TestString
(),
...
...
@@ -189,9 +185,8 @@ TEST(FormatterTest, Width) {
EXPECT_EQ
(
" 0xcafe"
,
str
(
Format
(
"{0:10}"
)
<<
reinterpret_cast
<
void
*>
(
0xcafe
)));
EXPECT_EQ
(
"x "
,
str
(
Format
(
"{0:11}"
)
<<
'x'
));
EXPECT_EQ
(
"narrow "
,
str
(
Format
(
"{0:12}"
)
<<
"narrow"
));
EXPECT_EQ
(
"wide "
,
str
(
Format
(
"{0:13}"
)
<<
L"wide"
));
EXPECT_EQ
(
"test "
,
str
(
Format
(
"{0:14}"
)
<<
TestString
(
"test"
)));
EXPECT_EQ
(
"str "
,
str
(
Format
(
"{0:12}"
)
<<
"str"
));
EXPECT_EQ
(
"test "
,
str
(
Format
(
"{0:13}"
)
<<
TestString
(
"test"
)));
}
TEST
(
FormatterTest
,
Precision
)
{
...
...
@@ -224,55 +219,97 @@ TEST(FormatterTest, Precision) {
FormatError
,
"unmatched '{' in format"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2}"
)
<<
42
,
FormatError
,
"precision specifier requires floating-point type"
);
EXPECT_EQ
(
"42.00"
,
str
(
Format
(
"{0:.2f}"
)
<<
42
));
FormatError
,
"precision specifier requires floating-point argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2f}"
)
<<
42
,
FormatError
,
"precision specifier requires floating-point argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2}"
)
<<
42u
,
FormatError
,
"precision specifier requires floating-point type"
);
EXPECT_EQ
(
"42.00"
,
str
(
Format
(
"{0:.2f}"
)
<<
42u
));
FormatError
,
"precision specifier requires floating-point argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2f}"
)
<<
42u
,
FormatError
,
"precision specifier requires floating-point argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2}"
)
<<
42l
,
FormatError
,
"precision specifier requires floating-point type"
);
EXPECT_EQ
(
"42.00"
,
str
(
Format
(
"{0:.2f}"
)
<<
42l
));
FormatError
,
"precision specifier requires floating-point argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2f}"
)
<<
42l
,
FormatError
,
"precision specifier requires floating-point argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2}"
)
<<
42ul
,
FormatError
,
"precision specifier requires floating-point type"
);
EXPECT_EQ
(
"42.00"
,
str
(
Format
(
"{0:.2f}"
)
<<
42ul
));
FormatError
,
"precision specifier requires floating-point argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2f}"
)
<<
42ul
,
FormatError
,
"precision specifier requires floating-point argument"
);
EXPECT_EQ
(
"1.2"
,
str
(
Format
(
"{0:.2}"
)
<<
1.2345
));
EXPECT_EQ
(
"1.2"
,
str
(
Format
(
"{0:.2}"
)
<<
1.2345
l
));
EXPECT_THROW_MSG
(
Format
(
"{0:.2}"
)
<<
reinterpret_cast
<
void
*>
(
0xcafe
),
FormatError
,
"precision specifier requires floating-point
type
"
);
FormatError
,
"precision specifier requires floating-point
argument
"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2f}"
)
<<
reinterpret_cast
<
void
*>
(
0xcafe
),
FormatError
,
"precision specifier requires floating-point
type
"
);
FormatError
,
"precision specifier requires floating-point
argument
"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2}"
)
<<
'x'
,
FormatError
,
"precision specifier requires floating-point
type
"
);
FormatError
,
"precision specifier requires floating-point
argument
"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2f}"
)
<<
'x'
,
FormatError
,
"precision specifier requires floating-point
type
"
);
FormatError
,
"precision specifier requires floating-point
argument
"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2}"
)
<<
"str"
,
FormatError
,
"precision specifier requires floating-point
type
"
);
FormatError
,
"precision specifier requires floating-point
argument
"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2f}"
)
<<
"str"
,
FormatError
,
"precision specifier requires floating-point type"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2}"
)
<<
L"str"
,
FormatError
,
"precision specifier requires floating-point type"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2f}"
)
<<
L"str"
,
FormatError
,
"precision specifier requires floating-point type"
);
FormatError
,
"precision specifier requires floating-point argument"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2}"
)
<<
TestString
(),
FormatError
,
"precision specifier requires floating-point
type
"
);
FormatError
,
"precision specifier requires floating-point
argument
"
);
EXPECT_THROW_MSG
(
Format
(
"{0:.2f}"
)
<<
TestString
(),
FormatError
,
"precision specifier requires floating-point type"
);
FormatError
,
"precision specifier requires floating-point argument"
);
}
TEST
(
FormatterTest
,
Type
)
{
EXPECT_THROW_MSG
(
Format
(
"{0:v"
)
<<
42
,
FormatError
,
"unmatched '{' in format"
);
EXPECT_THROW_MSG
(
Format
(
"{0:v}"
)
<<
42
,
FormatError
,
"unknown format code 'v' for integer"
);
}
TEST
(
FormatterTest
,
FormatInt
)
{
TEST
(
FormatterTest
,
FormatDec
)
{
EXPECT_EQ
(
"0"
,
str
(
Format
(
"{0}"
)
<<
0
));
EXPECT_EQ
(
"42"
,
str
(
Format
(
"{0}"
)
<<
42
));
EXPECT_EQ
(
"-1234"
,
str
(
Format
(
"{0}"
)
<<
-
1234
));
std
::
ostringstream
os
;
os
<<
INT_MIN
;
EXPECT_EQ
(
os
.
str
(),
str
(
Format
(
"{0}"
)
<<
INT_MIN
));
os
.
str
(
std
::
string
());
os
<<
INT_MAX
;
EXPECT_EQ
(
os
.
str
(),
str
(
Format
(
"{0}"
)
<<
INT_MAX
));
EXPECT_EQ
(
"42"
,
str
(
Format
(
"{0:d}"
)
<<
42
));
EXPECT_EQ
(
"42"
,
str
(
Format
(
"{0}"
)
<<
42u
));
EXPECT_EQ
(
"-42"
,
str
(
Format
(
"{0}"
)
<<
-
42
));
EXPECT_EQ
(
"12345"
,
str
(
Format
(
"{0}"
)
<<
12345
));
EXPECT_EQ
(
"67890"
,
str
(
Format
(
"{0}"
)
<<
67890
));
char
buffer
[
256
];
sprintf
(
buffer
,
"%d"
,
INT_MIN
);
EXPECT_EQ
(
buffer
,
str
(
Format
(
"{0}"
)
<<
INT_MIN
));
sprintf
(
buffer
,
"%d"
,
INT_MAX
);
EXPECT_EQ
(
buffer
,
str
(
Format
(
"{0}"
)
<<
INT_MAX
));
sprintf
(
buffer
,
"%u"
,
UINT_MAX
);
EXPECT_EQ
(
buffer
,
str
(
Format
(
"{0}"
)
<<
UINT_MAX
));
sprintf
(
buffer
,
"%ld"
,
0ul
-
LONG_MIN
);
EXPECT_EQ
(
buffer
,
str
(
Format
(
"{0}"
)
<<
LONG_MIN
));
sprintf
(
buffer
,
"%ld"
,
LONG_MAX
);
EXPECT_EQ
(
buffer
,
str
(
Format
(
"{0}"
)
<<
LONG_MAX
));
sprintf
(
buffer
,
"%lu"
,
ULONG_MAX
);
EXPECT_EQ
(
buffer
,
str
(
Format
(
"{0}"
)
<<
ULONG_MAX
));
}
TEST
(
FormatterTest
,
FormatHex
)
{
EXPECT_EQ
(
"0"
,
str
(
Format
(
"{0:x}"
)
<<
0
));
EXPECT_EQ
(
"42"
,
str
(
Format
(
"{0:x}"
)
<<
0x42
));
EXPECT_EQ
(
"42"
,
str
(
Format
(
"{0:x}"
)
<<
0x42u
));
EXPECT_EQ
(
"-42"
,
str
(
Format
(
"{0:x}"
)
<<
-
0x42
));
EXPECT_EQ
(
"12345678"
,
str
(
Format
(
"{0:x}"
)
<<
0x12345678
));
EXPECT_EQ
(
"90abcdef"
,
str
(
Format
(
"{0:x}"
)
<<
0x90abcdef
));
EXPECT_EQ
(
"12345678"
,
str
(
Format
(
"{0:X}"
)
<<
0x12345678
));
EXPECT_EQ
(
"90ABCDEF"
,
str
(
Format
(
"{0:X}"
)
<<
0x90ABCDEF
));
char
buffer
[
256
];
sprintf
(
buffer
,
"-%x"
,
0u
-
INT_MIN
);
EXPECT_EQ
(
buffer
,
str
(
Format
(
"{0:x}"
)
<<
INT_MIN
));
sprintf
(
buffer
,
"%x"
,
INT_MAX
);
EXPECT_EQ
(
buffer
,
str
(
Format
(
"{0:x}"
)
<<
INT_MAX
));
sprintf
(
buffer
,
"%x"
,
UINT_MAX
);
EXPECT_EQ
(
buffer
,
str
(
Format
(
"{0:x}"
)
<<
UINT_MAX
));
sprintf
(
buffer
,
"-%lx"
,
0ul
-
LONG_MIN
);
EXPECT_EQ
(
buffer
,
str
(
Format
(
"{0:x}"
)
<<
LONG_MIN
));
sprintf
(
buffer
,
"%lx"
,
LONG_MAX
);
EXPECT_EQ
(
buffer
,
str
(
Format
(
"{0:x}"
)
<<
LONG_MAX
));
sprintf
(
buffer
,
"%lx"
,
ULONG_MAX
);
EXPECT_EQ
(
buffer
,
str
(
Format
(
"{0:x}"
)
<<
ULONG_MAX
));
}
TEST
(
FormatterTest
,
FormatChar
)
{
...
...
@@ -283,8 +320,25 @@ TEST(FormatterTest, FormatString) {
EXPECT_EQ
(
"test"
,
str
(
Format
(
"{0}"
)
<<
std
::
string
(
"test"
)));
}
TEST
(
FormatterTest
,
FormatPointer
)
{
EXPECT_EQ
(
"0x0"
,
str
(
Format
(
"{0}"
)
<<
reinterpret_cast
<
void
*>
(
0
)));
}
class
Date
{
int
year_
,
month_
,
day_
;
public:
Date
(
int
year
,
int
month
,
int
day
)
:
year_
(
year
),
month_
(
month
),
day_
(
day
)
{}
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Date
&
d
)
{
os
<<
d
.
year_
<<
'-'
<<
d
.
month_
<<
'-'
<<
d
.
day_
;
return
os
;
}
};
TEST
(
FormatterTest
,
FormatCustomArg
)
{
EXPECT_EQ
(
"a string"
,
str
(
Format
(
"{0}"
)
<<
TestString
(
"a string"
)));
std
::
string
s
=
str
(
fmt
::
Format
(
"The date is {0}"
)
<<
Date
(
2012
,
12
,
9
));
EXPECT_EQ
(
"The date is 2012-12-9"
,
s
);
}
TEST
(
FormatterTest
,
FormatStringFromSpeedTest
)
{
...
...
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