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
de17baae
Commit
de17baae
authored
Jan 04, 2013
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move formatting methods to BasicFormat.
parent
8e158d74
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
129 additions
and
98 deletions
+129
-98
format.cc
format.cc
+49
-49
format.h
format.h
+76
-48
format_test.cc
format_test.cc
+4
-1
No files found.
format.cc
View file @
de17baae
...
...
@@ -137,48 +137,6 @@ void FormatDecimal(char *buffer, uint64_t value, unsigned num_digits) {
buffer
[
0
]
=
DIGITS
[
index
];
}
#ifdef _MSC_VER
int
signbit
(
double
value
)
{
if
(
value
<
0
)
return
1
;
if
(
value
==
value
)
return
0
;
int
dec
=
0
,
sign
=
0
;
_ecvt
(
value
,
0
,
&
dec
,
&
sign
);
return
sign
;
}
#endif
}
void
BasicFormatter
::
operator
<<
(
int
value
)
{
unsigned
abs_value
=
value
;
unsigned
num_digits
=
0
;
char
*
out
=
0
;
if
(
value
>=
0
)
{
num_digits
=
CountDigits
(
abs_value
);
out
=
GrowBuffer
(
num_digits
);
}
else
{
abs_value
=
0
-
abs_value
;
num_digits
=
CountDigits
(
abs_value
);
out
=
GrowBuffer
(
num_digits
+
1
);
*
out
++
=
'-'
;
}
FormatDecimal
(
out
,
abs_value
,
num_digits
);
}
// Throws Exception(message) if format contains '}', otherwise throws
// FormatError reporting unmatched '{'. The idea is that unmatched '{'
// should override other errors.
void
Formatter
::
ReportError
(
const
char
*
s
,
StringRef
message
)
const
{
for
(
int
num_open_braces
=
num_open_braces_
;
*
s
;
++
s
)
{
if
(
*
s
==
'{'
)
{
++
num_open_braces
;
}
else
if
(
*
s
==
'}'
)
{
if
(
--
num_open_braces
==
0
)
throw
fmt
::
FormatError
(
message
);
}
}
throw
fmt
::
FormatError
(
"unmatched '{' in format"
);
}
// Fills the padding around the content and returns the pointer to the
// content area.
char
*
FillPadding
(
char
*
buffer
,
...
...
@@ -192,7 +150,18 @@ char *FillPadding(char *buffer,
return
content
;
}
char
*
Formatter
::
PrepareFilledBuffer
(
#ifdef _MSC_VER
int
signbit
(
double
value
)
{
if
(
value
<
0
)
return
1
;
if
(
value
==
value
)
return
0
;
int
dec
=
0
,
sign
=
0
;
_ecvt
(
value
,
0
,
&
dec
,
&
sign
);
return
sign
;
}
#endif
}
char
*
BasicFormatter
::
PrepareFilledBuffer
(
unsigned
size
,
const
FormatSpec
&
spec
,
char
sign
)
{
if
(
spec
.
width
<=
size
)
{
char
*
p
=
GrowBuffer
(
size
);
...
...
@@ -225,7 +194,7 @@ char *Formatter::PrepareFilledBuffer(
}
template
<
typename
T
>
void
Formatter
::
FormatInt
(
T
value
,
const
FormatSpec
&
spec
)
{
void
Basic
Formatter
::
FormatInt
(
T
value
,
const
FormatSpec
&
spec
)
{
unsigned
size
=
0
;
char
sign
=
0
;
typedef
typename
IntTraits
<
T
>::
UnsignedType
UnsignedType
;
...
...
@@ -289,7 +258,8 @@ void Formatter::FormatInt(T value, const FormatSpec &spec) {
}
template
<
typename
T
>
void
Formatter
::
FormatDouble
(
T
value
,
const
FormatSpec
&
spec
,
int
precision
)
{
void
BasicFormatter
::
FormatDouble
(
T
value
,
const
FormatSpec
&
spec
,
int
precision
)
{
// Check type.
char
type
=
spec
.
type
;
bool
upper
=
false
;
...
...
@@ -431,7 +401,7 @@ void Formatter::FormatDouble(T value, const FormatSpec &spec, int precision) {
}
}
char
*
Formatter
::
FormatString
(
char
*
Basic
Formatter
::
FormatString
(
const
char
*
s
,
std
::
size_t
size
,
const
FormatSpec
&
spec
)
{
char
*
out
=
0
;
if
(
spec
.
width
>
size
)
{
...
...
@@ -451,6 +421,37 @@ char *Formatter::FormatString(
return
out
;
}
void
BasicFormatter
::
operator
<<
(
int
value
)
{
unsigned
abs_value
=
value
;
unsigned
num_digits
=
0
;
char
*
out
=
0
;
if
(
value
>=
0
)
{
num_digits
=
CountDigits
(
abs_value
);
out
=
GrowBuffer
(
num_digits
);
}
else
{
abs_value
=
0
-
abs_value
;
num_digits
=
CountDigits
(
abs_value
);
out
=
GrowBuffer
(
num_digits
+
1
);
*
out
++
=
'-'
;
}
FormatDecimal
(
out
,
abs_value
,
num_digits
);
}
// Throws Exception(message) if format contains '}', otherwise throws
// FormatError reporting unmatched '{'. The idea is that unmatched '{'
// should override other errors.
void
Formatter
::
ReportError
(
const
char
*
s
,
StringRef
message
)
const
{
for
(
int
num_open_braces
=
num_open_braces_
;
*
s
;
++
s
)
{
if
(
*
s
==
'{'
)
{
++
num_open_braces
;
}
else
if
(
*
s
==
'}'
)
{
if
(
--
num_open_braces
==
0
)
throw
fmt
::
FormatError
(
message
);
}
}
throw
fmt
::
FormatError
(
"unmatched '{' in format"
);
}
// Parses an unsigned integer advancing s to the end of the parsed input.
// This function assumes that the first character of s is a digit.
unsigned
Formatter
::
ParseUInt
(
const
char
*&
s
)
const
{
...
...
@@ -465,7 +466,7 @@ unsigned Formatter::ParseUInt(const char *&s) const {
return
value
;
}
const
Formatter
::
Arg
&
Formatter
::
ParseArgIndex
(
const
char
*&
s
)
{
inline
const
Formatter
::
Arg
&
Formatter
::
ParseArgIndex
(
const
char
*&
s
)
{
unsigned
arg_index
=
0
;
if
(
*
s
<
'0'
||
*
s
>
'9'
)
{
if
(
*
s
!=
'}'
&&
*
s
!=
':'
)
...
...
@@ -726,6 +727,5 @@ void Formatter::DoFormat() {
break
;
}
}
buffer_
.
append
(
start
,
s
+
1
);
buffer_
.
resize
(
buffer_
.
size
()
-
1
);
// Don't count the terminating zero.
buffer_
.
append
(
start
,
s
);
}
format.h
View file @
de17baae
...
...
@@ -124,6 +124,10 @@ class ArgInserter;
type to allow passing different types of strings in a function, for example::
TempFormatter<> Format(StringRef format);
Format("{}") << 42;
Format(std::string("{}")) << 42;
Format(Format("{{}}")) << 42;
\endrst
*/
class
StringRef
{
...
...
@@ -162,13 +166,14 @@ struct FormatSpec {
char
type
;
char
fill
;
FormatSpec
()
:
align
(
ALIGN_DEFAULT
),
flags
(
0
),
width
(
0
),
type
(
0
),
fill
(
' '
)
{}
FormatSpec
(
unsigned
width
=
0
,
char
type
=
0
,
char
fill
=
' '
)
:
align
(
ALIGN_DEFAULT
),
flags
(
0
),
width
(
width
),
type
(
type
),
fill
(
fill
)
{}
};
class
BasicFormatter
{
protected:
enum
{
INLINE_BUFFER_SIZE
=
500
};
internal
::
Array
<
char
,
INLINE_BUFFER_SIZE
>
buffer_
;
// Output buffer.
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.
...
...
@@ -178,8 +183,69 @@ class BasicFormatter {
return
&
buffer_
[
size
];
}
char
*
PrepareFilledBuffer
(
unsigned
size
,
const
FormatSpec
&
spec
,
char
sign
);
// Formats an integer.
template
<
typename
T
>
void
FormatInt
(
T
value
,
const
FormatSpec
&
spec
);
// Formats a floating point number (double or long double).
template
<
typename
T
>
void
FormatDouble
(
T
value
,
const
FormatSpec
&
spec
,
int
precision
);
char
*
FormatString
(
const
char
*
s
,
std
::
size_t
size
,
const
FormatSpec
&
spec
);
public:
/**
\rst
Returns the number of characters written to the output buffer.
\endrst
*/
std
::
size_t
size
()
const
{
return
buffer_
.
size
();
}
/**
\rst
Returns a pointer to the output buffer content. No terminating null
character is appended.
\endrst
*/
const
char
*
data
()
const
{
return
&
buffer_
[
0
];
}
/**
\rst
Returns a pointer to the output buffer content with terminating null
character appended.
\endrst
*/
const
char
*
c_str
()
const
{
std
::
size_t
size
=
buffer_
.
size
();
buffer_
.
reserve
(
size
+
1
);
buffer_
[
size
]
=
'\0'
;
return
&
buffer_
[
0
];
}
/**
\rst
Returns the content of the output buffer as an ``std::string``.
\endrst
*/
std
::
string
str
()
const
{
return
std
::
string
(
&
buffer_
[
0
],
buffer_
.
size
());
}
void
operator
<<
(
int
value
);
void
operator
<<
(
char
value
)
{
*
GrowBuffer
(
1
)
=
value
;
}
void
operator
<<
(
const
char
*
value
)
{
std
::
size_t
size
=
std
::
strlen
(
value
);
std
::
strncpy
(
GrowBuffer
(
size
),
value
,
size
);
}
BasicFormatter
&
Write
(
int
value
,
const
FormatSpec
&
spec
)
{
FormatInt
(
value
,
spec
);
return
*
this
;
}
};
/**
...
...
@@ -324,18 +390,6 @@ class Formatter : public BasicFormatter {
void
ReportError
(
const
char
*
s
,
StringRef
message
)
const
;
char
*
PrepareFilledBuffer
(
unsigned
size
,
const
FormatSpec
&
spec
,
char
sign
);
// Formats an integer.
template
<
typename
T
>
void
FormatInt
(
T
value
,
const
FormatSpec
&
spec
);
// Formats a floating point number (double or long double).
template
<
typename
T
>
void
FormatDouble
(
T
value
,
const
FormatSpec
&
spec
,
int
precision
);
char
*
FormatString
(
const
char
*
s
,
std
::
size_t
size
,
const
FormatSpec
&
spec
);
// Formats an argument of a custom type, such as a user-defined class.
template
<
typename
T
>
void
FormatCustomArg
(
const
void
*
arg
,
const
FormatSpec
&
spec
);
...
...
@@ -360,7 +414,7 @@ class Formatter : public BasicFormatter {
Constructs a formatter with an empty output buffer.
\endrst
*/
Formatter
()
:
format_
(
0
)
{
buffer_
[
0
]
=
0
;
}
Formatter
()
:
format_
(
0
)
{}
/**
\rst
...
...
@@ -370,36 +424,6 @@ class Formatter : public BasicFormatter {
\endrst
*/
internal
::
ArgInserter
operator
()(
StringRef
format
);
/**
\rst
Returns the number of characters written to the output buffer.
\endrst
*/
std
::
size_t
size
()
const
{
return
buffer_
.
size
();
}
/**
\rst
Returns a pointer to the output buffer content. No terminating null
character is appended.
\endrst
*/
const
char
*
data
()
const
{
return
&
buffer_
[
0
];
}
/**
\rst
Returns a pointer to the output buffer content with terminating null
character appended.
\endrst
*/
const
char
*
c_str
()
const
{
return
&
buffer_
[
0
];
}
/**
\rst
Returns the content of the output buffer as an ``std::string``.
\endrst
*/
std
::
string
str
()
const
{
return
std
::
string
(
&
buffer_
[
0
],
buffer_
.
size
());
}
}
;
namespace
internal
{
...
...
@@ -540,9 +564,13 @@ struct NoAction {
void
operator
()(
const
Formatter
&
)
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, thus the name.
/**
\rst
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.
\endrst
*/
template
<
typename
Action
=
NoAction
>
class
TempFormatter
:
public
internal
::
ArgInserter
{
private:
...
...
format_test.cc
View file @
de17baae
...
...
@@ -898,7 +898,6 @@ TEST(FormatterTest, FormatStringFromSpeedTest) {
TEST
(
FormatterTest
,
FormatterCtor
)
{
Formatter
format
;
EXPECT_EQ
(
0u
,
format
.
size
());
EXPECT_STREQ
(
""
,
format
.
data
());
EXPECT_STREQ
(
""
,
format
.
c_str
());
EXPECT_EQ
(
""
,
format
.
str
());
format
(
"part{0}"
)
<<
1
;
...
...
@@ -921,6 +920,10 @@ TEST(FormatterTest, FormatterAppend) {
}
TEST
(
FormatterTest
,
FormatterExamples
)
{
EXPECT_EQ
(
"42"
,
str
(
Format
(
"{}"
)
<<
42
));
EXPECT_EQ
(
"42"
,
str
(
Format
(
std
::
string
(
"{}"
))
<<
42
));
EXPECT_EQ
(
"42"
,
str
(
Format
(
Format
(
"{{}}"
))
<<
42
));
Formatter
format
;
format
(
"Current point:
\n
"
);
format
(
"({0:+f}, {1:+f})
\n
"
)
<<
-
3.14
<<
3.14
;
...
...
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