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
2b415b7a
Commit
2b415b7a
authored
Apr 11, 2019
by
ToolsDevler
Committed by
Victor Zverovich
Apr 15, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Restructure printf_arg_formatter to make it customizable
parent
5d755d0a
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
78 additions
and
17 deletions
+78
-17
include/fmt/printf.h
include/fmt/printf.h
+30
-17
test/printf-test.cc
test/printf-test.cc
+48
-0
No files found.
include/fmt/printf.h
View file @
2b415b7a
...
@@ -197,9 +197,7 @@ using internal::printf; // For printing into memory_buffer.
...
@@ -197,9 +197,7 @@ using internal::printf; // For printing into memory_buffer.
template
<
typename
Range
>
class
printf_arg_formatter
;
template
<
typename
Range
>
class
printf_arg_formatter
;
template
<
typename
OutputIt
,
typename
Char
,
template
<
typename
OutputIt
,
typename
Char
>
typename
ArgFormatter
=
printf_arg_formatter
<
back_insert_range
<
internal
::
buffer
<
Char
>
>>>
class
basic_printf_context
;
class
basic_printf_context
;
/**
/**
...
@@ -212,12 +210,12 @@ class printf_arg_formatter
...
@@ -212,12 +210,12 @@ class printf_arg_formatter
:
public
internal
::
function
<
:
public
internal
::
function
<
typename
internal
::
arg_formatter_base
<
Range
>::
iterator
>
,
typename
internal
::
arg_formatter_base
<
Range
>::
iterator
>
,
public
internal
::
arg_formatter_base
<
Range
>
{
public
internal
::
arg_formatter_base
<
Range
>
{
public:
typedef
decltype
(
internal
::
declval
<
Range
>
().
begin
())
iterator
;
private:
private:
typedef
typename
Range
::
value_type
char_type
;
typedef
typename
Range
::
value_type
char_type
;
typedef
decltype
(
internal
::
declval
<
Range
>
().
begin
())
iterator
;
typedef
internal
::
arg_formatter_base
<
Range
>
base
;
typedef
internal
::
arg_formatter_base
<
Range
>
base
;
typedef
basic_printf_context
<
iterator
,
char_type
,
printf_arg_formatter
>
typedef
basic_printf_context
<
iterator
,
char_type
>
context_type
;
context_type
;
context_type
&
context_
;
context_type
&
context_
;
...
@@ -328,7 +326,7 @@ template <typename T> struct printf_formatter {
...
@@ -328,7 +326,7 @@ template <typename T> struct printf_formatter {
};
};
/** This template formats data and writes the output to a writer. */
/** This template formats data and writes the output to a writer. */
template
<
typename
OutputIt
,
typename
Char
,
typename
ArgFormatter
>
template
<
typename
OutputIt
,
typename
Char
>
class
basic_printf_context
{
class
basic_printf_context
{
public:
public:
/** The character type for the output. */
/** The character type for the output. */
...
@@ -379,11 +377,12 @@ class basic_printf_context {
...
@@ -379,11 +377,12 @@ class basic_printf_context {
}
}
/** Formats stored arguments and writes the output to the range. */
/** Formats stored arguments and writes the output to the range. */
template
<
typename
ArgFormatter
=
printf_arg_formatter
<
back_insert_range
<
internal
::
buffer
<
Char
>
>>>
OutputIt
format
();
OutputIt
format
();
};
};
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
template
<
typename
OutputIt
,
typename
Char
>
void
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
parse_flags
(
format_specs
&
spec
,
void
basic_printf_context
<
OutputIt
,
Char
>::
parse_flags
(
format_specs
&
spec
,
const
Char
*&
it
,
const
Char
*&
it
,
const
Char
*
end
)
{
const
Char
*
end
)
{
for
(;
it
!=
end
;
++
it
)
{
for
(;
it
!=
end
;
++
it
)
{
...
@@ -409,9 +408,9 @@ void basic_printf_context<OutputIt, Char, AF>::parse_flags(format_specs& spec,
...
@@ -409,9 +408,9 @@ void basic_printf_context<OutputIt, Char, AF>::parse_flags(format_specs& spec,
}
}
}
}
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
template
<
typename
OutputIt
,
typename
Char
>
typename
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
format_arg
typename
basic_printf_context
<
OutputIt
,
Char
>::
format_arg
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
get_arg
(
unsigned
arg_index
)
{
basic_printf_context
<
OutputIt
,
Char
>::
get_arg
(
unsigned
arg_index
)
{
if
(
arg_index
==
std
::
numeric_limits
<
unsigned
>::
max
())
if
(
arg_index
==
std
::
numeric_limits
<
unsigned
>::
max
())
arg_index
=
parse_ctx_
.
next_arg_id
();
arg_index
=
parse_ctx_
.
next_arg_id
();
else
else
...
@@ -419,8 +418,8 @@ basic_printf_context<OutputIt, Char, AF>::get_arg(unsigned arg_index) {
...
@@ -419,8 +418,8 @@ basic_printf_context<OutputIt, Char, AF>::get_arg(unsigned arg_index) {
return
internal
::
get_arg
(
*
this
,
arg_index
);
return
internal
::
get_arg
(
*
this
,
arg_index
);
}
}
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
template
<
typename
OutputIt
,
typename
Char
>
unsigned
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
parse_header
(
unsigned
basic_printf_context
<
OutputIt
,
Char
>::
parse_header
(
const
Char
*&
it
,
const
Char
*
end
,
format_specs
&
spec
)
{
const
Char
*&
it
,
const
Char
*
end
,
format_specs
&
spec
)
{
unsigned
arg_index
=
std
::
numeric_limits
<
unsigned
>::
max
();
unsigned
arg_index
=
std
::
numeric_limits
<
unsigned
>::
max
();
char_type
c
=
*
it
;
char_type
c
=
*
it
;
...
@@ -457,8 +456,9 @@ unsigned basic_printf_context<OutputIt, Char, AF>::parse_header(
...
@@ -457,8 +456,9 @@ unsigned basic_printf_context<OutputIt, Char, AF>::parse_header(
return
arg_index
;
return
arg_index
;
}
}
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
template
<
typename
OutputIt
,
typename
Char
>
OutputIt
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
format
()
{
template
<
typename
ArgFormatter
>
OutputIt
basic_printf_context
<
OutputIt
,
Char
>::
format
()
{
auto
out
=
this
->
out
();
auto
out
=
this
->
out
();
const
Char
*
start
=
parse_ctx_
.
begin
();
const
Char
*
start
=
parse_ctx_
.
begin
();
const
Char
*
end
=
parse_ctx_
.
end
();
const
Char
*
end
=
parse_ctx_
.
end
();
...
@@ -567,7 +567,7 @@ OutputIt basic_printf_context<OutputIt, Char, AF>::format() {
...
@@ -567,7 +567,7 @@ OutputIt basic_printf_context<OutputIt, Char, AF>::format() {
start
=
it
;
start
=
it
;
// Format argument.
// Format argument.
visit_format_arg
(
A
F
(
out
,
spec
,
*
this
),
arg
);
visit_format_arg
(
A
rgFormatter
(
out
,
spec
,
*
this
),
arg
);
}
}
return
std
::
copy
(
start
,
it
,
out
);
return
std
::
copy
(
start
,
it
,
out
);
}
}
...
@@ -712,6 +712,19 @@ inline int vfprintf(
...
@@ -712,6 +712,19 @@ inline int vfprintf(
return
static_cast
<
int
>
(
buffer
.
size
());
return
static_cast
<
int
>
(
buffer
.
size
());
}
}
/** Formats arguments and writes the output to the range. */
template
<
typename
ArgFormatter
,
typename
Char
,
typename
Context
=
basic_printf_context
<
typename
ArgFormatter
::
iterator
,
Char
>
>
typename
ArgFormatter
::
iterator
vprintf
(
internal
::
buffer
<
Char
>&
out
,
basic_string_view
<
Char
>
format_str
,
basic_format_args
<
Context
>
args
)
{
typename
ArgFormatter
::
iterator
iter
(
out
);
Context
(
iter
,
format_str
,
args
).
template
format
<
ArgFormatter
>();
return
iter
;
}
/**
/**
\rst
\rst
Prints formatted data to the stream *os*.
Prints formatted data to the stream *os*.
...
...
test/printf-test.cc
View file @
2b415b7a
...
@@ -554,3 +554,51 @@ TEST(PrintfTest, VSPrintfMakeWArgsExample) {
...
@@ -554,3 +554,51 @@ TEST(PrintfTest, VSPrintfMakeWArgsExample) {
fmt
::
make_wprintf_args
(
42
,
L"something"
)));
fmt
::
make_wprintf_args
(
42
,
L"something"
)));
#endif
#endif
}
}
typedef
fmt
::
printf_arg_formatter
<
fmt
::
back_insert_range
<
fmt
::
internal
::
buffer
<
char
>>>
formatter_t
;
typedef
fmt
::
basic_printf_context
<
formatter_t
::
iterator
,
char
>
context_t
;
// A custom printf argument formatter that doesn't print `-` for floating-point
// values rounded to 0.
class
custom_printf_arg_formatter
:
public
formatter_t
{
public:
using
formatter_t
::
iterator
;
custom_printf_arg_formatter
(
formatter_t
::
iterator
iter
,
formatter_t
::
format_specs
&
spec
,
context_t
&
ctx
)
:
formatter_t
(
iter
,
spec
,
ctx
)
{}
using
formatter_t
::
operator
();
#if FMT_MSC_VER > 0 && FMT_MSC_VER <= 1804
template
<
typename
T
,
FMT_ENABLE_IF
(
std
::
is_floating_point
<
T
>
::
value
)
>
iterator
operator
()(
T
value
)
{
#else
iterator
operator
()(
double
value
)
{
#endif
// Comparing a float to 0.0 is safe.
if
(
round
(
value
*
pow
(
10
,
spec
()
->
precision
))
==
0.0
)
value
=
0
;
return
formatter_t
::
operator
()(
value
);
}
};
typedef
fmt
::
basic_format_args
<
context_t
>
format_args_t
;
std
::
string
custom_vformat
(
fmt
::
string_view
format_str
,
format_args_t
args
)
{
fmt
::
memory_buffer
buffer
;
fmt
::
vprintf
<
custom_printf_arg_formatter
>
(
buffer
,
format_str
,
args
);
return
std
::
string
(
buffer
.
data
(),
buffer
.
size
());
}
template
<
typename
...
Args
>
std
::
string
custom_format
(
const
char
*
format_str
,
const
Args
&
...
args
)
{
auto
va
=
fmt
::
make_printf_args
(
args
...);
return
custom_vformat
(
format_str
,
va
);
}
TEST
(
CustomFormatterTest
,
Format
)
{
EXPECT_EQ
(
"0.00"
,
custom_format
(
"%.2f"
,
-
.00001
));
EXPECT_EQ
(
"0.00"
,
custom_format
(
"%.2f"
,
.00001
));
EXPECT_EQ
(
"1.00"
,
custom_format
(
"%.2f"
,
1.00001
));
EXPECT_EQ
(
"-1.00"
,
custom_format
(
"%.2f"
,
-
1.00001
));
}
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