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
744e66bb
Commit
744e66bb
authored
Feb 09, 2019
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Deprecate format_context::parse_context()
parent
d231d68a
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
134 additions
and
115 deletions
+134
-115
include/fmt/core.h
include/fmt/core.h
+77
-66
include/fmt/format.h
include/fmt/format.h
+16
-12
include/fmt/ostream.h
include/fmt/ostream.h
+1
-1
include/fmt/prepare.h
include/fmt/prepare.h
+8
-9
include/fmt/printf.h
include/fmt/printf.h
+3
-4
include/fmt/ranges.h
include/fmt/ranges.h
+4
-5
include/format
include/format
+3
-2
test/core-test.cc
test/core-test.cc
+5
-6
test/format-test.cc
test/format-test.cc
+17
-10
No files found.
include/fmt/core.h
View file @
744e66bb
...
@@ -226,7 +226,7 @@ struct result_of<F(Args...)> : std::invoke_result<F, Args...> {};
...
@@ -226,7 +226,7 @@ struct result_of<F(Args...)> : std::invoke_result<F, Args...> {};
// A workaround for gcc 4.4 that doesn't allow F to be a reference.
// A workaround for gcc 4.4 that doesn't allow F to be a reference.
template
<
typename
F
,
typename
...
Args
>
template
<
typename
F
,
typename
...
Args
>
struct
result_of
<
F
(
Args
...)
>
struct
result_of
<
F
(
Args
...)
>
:
std
::
result_of
<
typename
std
::
remove_reference
<
F
>::
type
(
Args
...)
>
{};
:
std
::
result_of
<
typename
std
::
remove_reference
<
F
>::
type
(
Args
...)
>
{};
#endif
#endif
// Casts nonnegative integer to unsigned.
// Casts nonnegative integer to unsigned.
...
@@ -518,6 +518,63 @@ FMT_CONSTEXPR basic_string_view<typename S::char_type> to_string_view(
...
@@ -518,6 +518,63 @@ FMT_CONSTEXPR basic_string_view<typename S::char_type> to_string_view(
return
s
;
return
s
;
}
}
// Parsing context consisting of a format string range being parsed and an
// argument counter for automatic indexing.
template
<
typename
Char
,
typename
ErrorHandler
=
internal
::
error_handler
>
class
basic_parse_context
:
private
ErrorHandler
{
private:
basic_string_view
<
Char
>
format_str_
;
int
next_arg_id_
;
public:
typedef
Char
char_type
;
typedef
typename
basic_string_view
<
Char
>::
iterator
iterator
;
explicit
FMT_CONSTEXPR
basic_parse_context
(
basic_string_view
<
Char
>
format_str
,
ErrorHandler
eh
=
ErrorHandler
())
:
ErrorHandler
(
eh
),
format_str_
(
format_str
),
next_arg_id_
(
0
)
{}
// Returns an iterator to the beginning of the format string range being
// parsed.
FMT_CONSTEXPR
iterator
begin
()
const
FMT_NOEXCEPT
{
return
format_str_
.
begin
();
}
// Returns an iterator past the end of the format string range being parsed.
FMT_CONSTEXPR
iterator
end
()
const
FMT_NOEXCEPT
{
return
format_str_
.
end
();
}
// Advances the begin iterator to ``it``.
FMT_CONSTEXPR
void
advance_to
(
iterator
it
)
{
format_str_
.
remove_prefix
(
internal
::
to_unsigned
(
it
-
begin
()));
}
// Returns the next argument index.
FMT_CONSTEXPR
unsigned
next_arg_id
();
FMT_CONSTEXPR
bool
check_arg_id
(
unsigned
)
{
if
(
next_arg_id_
>
0
)
{
on_error
(
"cannot switch from automatic to manual argument indexing"
);
return
false
;
}
next_arg_id_
=
-
1
;
return
true
;
}
FMT_CONSTEXPR
void
check_arg_id
(
basic_string_view
<
Char
>
)
{}
FMT_CONSTEXPR
void
on_error
(
const
char
*
message
)
{
ErrorHandler
::
on_error
(
message
);
}
FMT_CONSTEXPR
ErrorHandler
error_handler
()
const
{
return
*
this
;
}
};
typedef
basic_parse_context
<
char
>
format_parse_context
;
typedef
basic_parse_context
<
wchar_t
>
wformat_parse_context
;
FMT_DEPRECATED
typedef
basic_parse_context
<
char
>
parse_context
;
FMT_DEPRECATED
typedef
basic_parse_context
<
wchar_t
>
wparse_context
;
template
<
typename
Context
>
class
basic_format_arg
;
template
<
typename
Context
>
class
basic_format_arg
;
template
<
typename
Context
>
class
basic_format_args
;
template
<
typename
Context
>
class
basic_format_args
;
...
@@ -605,7 +662,9 @@ template <typename Char> struct string_value {
...
@@ -605,7 +662,9 @@ template <typename Char> struct string_value {
template
<
typename
Context
>
struct
custom_value
{
template
<
typename
Context
>
struct
custom_value
{
const
void
*
value
;
const
void
*
value
;
void
(
*
format
)(
const
void
*
arg
,
Context
&
ctx
);
void
(
*
format
)(
const
void
*
arg
,
basic_parse_context
<
typename
Context
::
char_type
>&
parse_ctx
,
Context
&
ctx
);
};
};
// A formatting argument value.
// A formatting argument value.
...
@@ -673,9 +732,10 @@ template <typename Context> class value {
...
@@ -673,9 +732,10 @@ template <typename Context> class value {
private:
private:
// Formats an argument of a custom type, such as a user-defined class.
// Formats an argument of a custom type, such as a user-defined class.
template
<
typename
T
,
typename
Formatter
>
template
<
typename
T
,
typename
Formatter
>
static
void
format_custom_arg
(
const
void
*
arg
,
Context
&
ctx
)
{
static
void
format_custom_arg
(
const
void
*
arg
,
basic_parse_context
<
char_type
>&
parse_ctx
,
Context
&
ctx
)
{
Formatter
f
;
Formatter
f
;
auto
&&
parse_ctx
=
ctx
.
parse_context
();
parse_ctx
.
advance_to
(
f
.
parse
(
parse_ctx
));
parse_ctx
.
advance_to
(
f
.
parse
(
parse_ctx
));
ctx
.
advance_to
(
f
.
format
(
*
static_cast
<
const
T
*>
(
arg
),
ctx
));
ctx
.
advance_to
(
f
.
format
(
*
static_cast
<
const
T
*>
(
arg
),
ctx
));
}
}
...
@@ -866,7 +926,9 @@ template <typename Context> class basic_format_arg {
...
@@ -866,7 +926,9 @@ template <typename Context> class basic_format_arg {
public:
public:
explicit
handle
(
internal
::
custom_value
<
Context
>
custom
)
:
custom_
(
custom
)
{}
explicit
handle
(
internal
::
custom_value
<
Context
>
custom
)
:
custom_
(
custom
)
{}
void
format
(
Context
&
ctx
)
const
{
custom_
.
format
(
custom_
.
value
,
ctx
);
}
void
format
(
basic_parse_context
<
char_type
>&
parse_ctx
,
Context
&
ctx
)
const
{
custom_
.
format
(
custom_
.
value
,
parse_ctx
,
ctx
);
}
private:
private:
internal
::
custom_value
<
Context
>
custom_
;
internal
::
custom_value
<
Context
>
custom_
;
...
@@ -938,63 +1000,6 @@ visit(Visitor&& vis, const basic_format_arg<Context>& arg) {
...
@@ -938,63 +1000,6 @@ visit(Visitor&& vis, const basic_format_arg<Context>& arg) {
return
visit_format_arg
(
std
::
forward
<
Visitor
>
(
vis
),
arg
);
return
visit_format_arg
(
std
::
forward
<
Visitor
>
(
vis
),
arg
);
}
}
// Parsing context consisting of a format string range being parsed and an
// argument counter for automatic indexing.
template
<
typename
Char
,
typename
ErrorHandler
=
internal
::
error_handler
>
class
basic_parse_context
:
private
ErrorHandler
{
private:
basic_string_view
<
Char
>
format_str_
;
int
next_arg_id_
;
public:
typedef
Char
char_type
;
typedef
typename
basic_string_view
<
Char
>::
iterator
iterator
;
explicit
FMT_CONSTEXPR
basic_parse_context
(
basic_string_view
<
Char
>
format_str
,
ErrorHandler
eh
=
ErrorHandler
())
:
ErrorHandler
(
eh
),
format_str_
(
format_str
),
next_arg_id_
(
0
)
{}
// Returns an iterator to the beginning of the format string range being
// parsed.
FMT_CONSTEXPR
iterator
begin
()
const
FMT_NOEXCEPT
{
return
format_str_
.
begin
();
}
// Returns an iterator past the end of the format string range being parsed.
FMT_CONSTEXPR
iterator
end
()
const
FMT_NOEXCEPT
{
return
format_str_
.
end
();
}
// Advances the begin iterator to ``it``.
FMT_CONSTEXPR
void
advance_to
(
iterator
it
)
{
format_str_
.
remove_prefix
(
internal
::
to_unsigned
(
it
-
begin
()));
}
// Returns the next argument index.
FMT_CONSTEXPR
unsigned
next_arg_id
();
FMT_CONSTEXPR
bool
check_arg_id
(
unsigned
)
{
if
(
next_arg_id_
>
0
)
{
on_error
(
"cannot switch from automatic to manual argument indexing"
);
return
false
;
}
next_arg_id_
=
-
1
;
return
true
;
}
FMT_CONSTEXPR
void
check_arg_id
(
basic_string_view
<
Char
>
)
{}
FMT_CONSTEXPR
void
on_error
(
const
char
*
message
)
{
ErrorHandler
::
on_error
(
message
);
}
FMT_CONSTEXPR
ErrorHandler
error_handler
()
const
{
return
*
this
;
}
};
typedef
basic_parse_context
<
char
>
format_parse_context
;
typedef
basic_parse_context
<
wchar_t
>
wformat_parse_context
;
FMT_DEPRECATED
typedef
basic_parse_context
<
char
>
parse_context
;
FMT_DEPRECATED
typedef
basic_parse_context
<
wchar_t
>
wparse_context
;
namespace
internal
{
namespace
internal
{
// A map from argument names to their values for named arguments.
// A map from argument names to their values for named arguments.
template
<
typename
Context
>
class
arg_map
{
template
<
typename
Context
>
class
arg_map
{
...
@@ -1073,15 +1078,21 @@ class context_base {
...
@@ -1073,15 +1078,21 @@ class context_base {
return
arg
;
return
arg
;
}
}
friend
basic_parse_context
<
Char
>&
get_parse_context
(
context_base
&
ctx
)
{
return
ctx
.
parse_context_
;
}
// 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.
format_arg
arg
(
unsigned
arg_id
)
{
format_arg
arg
(
unsigned
arg_id
)
{
return
this
->
parse_context
()
.
check_arg_id
(
arg_id
)
?
this
->
do_get_arg
(
arg_id
)
return
parse_context_
.
check_arg_id
(
arg_id
)
?
this
->
do_get_arg
(
arg_id
)
:
format_arg
();
:
format_arg
();
}
}
public:
public:
basic_parse_context
<
char_type
>&
parse_context
()
{
return
parse_context_
;
}
FMT_DEPRECATED
basic_parse_context
<
Char
>&
parse_context
()
{
return
parse_context_
;
}
// basic_format_context::arg() depends on this
// basic_format_context::arg() depends on this
// Cannot be marked as deprecated without causing warnings
// Cannot be marked as deprecated without causing warnings
...
@@ -1178,7 +1189,7 @@ class basic_format_context
...
@@ -1178,7 +1189,7 @@ class basic_format_context
:
base
(
out
,
format_str
,
ctx_args
,
loc
)
{}
:
base
(
out
,
format_str
,
ctx_args
,
loc
)
{}
format_arg
next_arg
()
{
format_arg
next_arg
()
{
return
this
->
do_get_arg
(
this
->
parse_context
(
).
next_arg_id
());
return
this
->
do_get_arg
(
get_parse_context
(
*
this
).
next_arg_id
());
}
}
format_arg
arg
(
unsigned
arg_id
)
{
return
this
->
do_get_arg
(
arg_id
);
}
format_arg
arg
(
unsigned
arg_id
)
{
return
this
->
do_get_arg
(
arg_id
);
}
...
...
include/fmt/format.h
View file @
744e66bb
...
@@ -1576,7 +1576,7 @@ class custom_formatter : public function<bool> {
...
@@ -1576,7 +1576,7 @@ class custom_formatter : public function<bool> {
explicit
custom_formatter
(
Context
&
ctx
)
:
ctx_
(
ctx
)
{}
explicit
custom_formatter
(
Context
&
ctx
)
:
ctx_
(
ctx
)
{}
bool
operator
()(
typename
basic_format_arg
<
Context
>::
handle
h
)
const
{
bool
operator
()(
typename
basic_format_arg
<
Context
>::
handle
h
)
const
{
h
.
format
(
ctx_
);
h
.
format
(
get_parse_context
(
ctx_
),
ctx_
);
return
true
;
return
true
;
}
}
...
@@ -1762,14 +1762,14 @@ FMT_CONSTEXPR void set_dynamic_spec(T& value, FormatArg arg, ErrorHandler eh) {
...
@@ -1762,14 +1762,14 @@ FMT_CONSTEXPR void set_dynamic_spec(T& value, FormatArg arg, ErrorHandler eh) {
struct
auto_id
{};
struct
auto_id
{};
// The standard format specifier handler with checking.
// The standard format specifier handler with checking.
template
<
typename
Context
>
template
<
typename
ParseContext
,
typename
Context
>
class
specs_handler
:
public
specs_setter
<
typename
Context
::
char_type
>
{
class
specs_handler
:
public
specs_setter
<
typename
Context
::
char_type
>
{
public:
public:
typedef
typename
Context
::
char_type
char_type
;
typedef
typename
Context
::
char_type
char_type
;
FMT_CONSTEXPR
specs_handler
(
basic_format_specs
<
char_type
>&
specs
,
FMT_CONSTEXPR
specs_handler
(
basic_format_specs
<
char_type
>&
specs
,
Context
&
ctx
)
ParseContext
&
parse_ctx
,
Context
&
ctx
)
:
specs_setter
<
char_type
>
(
specs
),
context_
(
ctx
)
{}
:
specs_setter
<
char_type
>
(
specs
),
parse_ctx_
(
parse_ctx
),
context_
(
ctx
)
{}
template
<
typename
Id
>
FMT_CONSTEXPR
void
on_dynamic_width
(
Id
arg_id
)
{
template
<
typename
Id
>
FMT_CONSTEXPR
void
on_dynamic_width
(
Id
arg_id
)
{
set_dynamic_spec
<
width_checker
>
(
this
->
specs_
.
width_
,
get_arg
(
arg_id
),
set_dynamic_spec
<
width_checker
>
(
this
->
specs_
.
width_
,
get_arg
(
arg_id
),
...
@@ -1790,10 +1790,11 @@ class specs_handler : public specs_setter<typename Context::char_type> {
...
@@ -1790,10 +1790,11 @@ class specs_handler : public specs_setter<typename Context::char_type> {
FMT_CONSTEXPR
format_arg
get_arg
(
auto_id
)
{
return
context_
.
next_arg
();
}
FMT_CONSTEXPR
format_arg
get_arg
(
auto_id
)
{
return
context_
.
next_arg
();
}
template
<
typename
Id
>
FMT_CONSTEXPR
format_arg
get_arg
(
Id
arg_id
)
{
template
<
typename
Id
>
FMT_CONSTEXPR
format_arg
get_arg
(
Id
arg_id
)
{
context_
.
parse_context
()
.
check_arg_id
(
arg_id
);
parse_ctx_
.
check_arg_id
(
arg_id
);
return
context_
.
arg
(
arg_id
);
return
context_
.
arg
(
arg_id
);
}
}
ParseContext
&
parse_ctx_
;
Context
&
context_
;
Context
&
context_
;
};
};
...
@@ -2273,7 +2274,7 @@ void handle_dynamic_spec(Spec& value, arg_ref<typename Context::char_type> ref,
...
@@ -2273,7 +2274,7 @@ void handle_dynamic_spec(Spec& value, arg_ref<typename Context::char_type> ref,
ctx
.
error_handler
());
ctx
.
error_handler
());
break
;
break
;
case
arg_ref
<
char_type
>
:
:
NAME
:
{
case
arg_ref
<
char_type
>
:
:
NAME
:
{
const
auto
arg_id
=
ref
.
val
.
name
.
to_view
(
ctx
.
parse_context
(
).
begin
());
const
auto
arg_id
=
ref
.
val
.
name
.
to_view
(
get_parse_context
(
ctx
).
begin
());
internal
::
set_dynamic_spec
<
Handler
>
(
value
,
ctx
.
arg
(
arg_id
),
internal
::
set_dynamic_spec
<
Handler
>
(
value
,
ctx
.
arg
(
arg_id
),
ctx
.
error_handler
());
ctx
.
error_handler
());
}
break
;
}
break
;
...
@@ -2316,7 +2317,7 @@ class arg_formatter
...
@@ -2316,7 +2317,7 @@ class arg_formatter
/** Formats an argument of a user-defined type. */
/** Formats an argument of a user-defined type. */
iterator
operator
()(
typename
basic_format_arg
<
context_type
>::
handle
handle
)
{
iterator
operator
()(
typename
basic_format_arg
<
context_type
>::
handle
handle
)
{
handle
.
format
(
ctx_
);
handle
.
format
(
get_parse_context
(
ctx_
),
ctx_
);
return
this
->
out
();
return
this
->
out
();
}
}
};
};
...
@@ -3181,27 +3182,30 @@ struct format_handler : internal::error_handler {
...
@@ -3181,27 +3182,30 @@ struct format_handler : internal::error_handler {
void
on_arg_id
()
{
arg
=
context
.
next_arg
();
}
void
on_arg_id
()
{
arg
=
context
.
next_arg
();
}
void
on_arg_id
(
unsigned
id
)
{
void
on_arg_id
(
unsigned
id
)
{
context
.
parse_context
(
).
check_arg_id
(
id
);
get_parse_context
(
context
).
check_arg_id
(
id
);
arg
=
context
.
arg
(
id
);
arg
=
context
.
arg
(
id
);
}
}
void
on_arg_id
(
basic_string_view
<
Char
>
id
)
{
arg
=
context
.
arg
(
id
);
}
void
on_arg_id
(
basic_string_view
<
Char
>
id
)
{
arg
=
context
.
arg
(
id
);
}
void
on_replacement_field
(
const
Char
*
p
)
{
void
on_replacement_field
(
const
Char
*
p
)
{
context
.
parse_context
(
).
advance_to
(
p
);
get_parse_context
(
context
).
advance_to
(
p
);
internal
::
custom_formatter
<
Char
,
Context
>
f
(
context
);
internal
::
custom_formatter
<
Char
,
Context
>
f
(
context
);
if
(
!
visit_format_arg
(
f
,
arg
))
if
(
!
visit_format_arg
(
f
,
arg
))
context
.
advance_to
(
visit_format_arg
(
ArgFormatter
(
context
),
arg
));
context
.
advance_to
(
visit_format_arg
(
ArgFormatter
(
context
),
arg
));
}
}
const
Char
*
on_format_specs
(
const
Char
*
begin
,
const
Char
*
end
)
{
const
Char
*
on_format_specs
(
const
Char
*
begin
,
const
Char
*
end
)
{
auto
&
parse_ctx
=
context
.
parse_context
(
);
auto
&
parse_ctx
=
get_parse_context
(
context
);
parse_ctx
.
advance_to
(
begin
);
parse_ctx
.
advance_to
(
begin
);
internal
::
custom_formatter
<
Char
,
Context
>
f
(
context
);
internal
::
custom_formatter
<
Char
,
Context
>
f
(
context
);
if
(
visit_format_arg
(
f
,
arg
))
return
parse_ctx
.
begin
();
if
(
visit_format_arg
(
f
,
arg
))
return
parse_ctx
.
begin
();
basic_format_specs
<
Char
>
specs
;
basic_format_specs
<
Char
>
specs
;
using
internal
::
specs_handler
;
using
internal
::
specs_handler
;
internal
::
specs_checker
<
specs_handler
<
Context
>>
handler
(
typedef
basic_parse_context
<
Char
>
parse_context
;
specs_handler
<
Context
>
(
specs
,
context
),
arg
.
type
());
internal
::
specs_checker
<
specs_handler
<
parse_context
,
Context
>>
handler
(
specs_handler
<
parse_context
,
Context
>
(
specs
,
get_parse_context
(
context
),
context
),
arg
.
type
());
begin
=
parse_format_specs
(
begin
,
end
,
handler
);
begin
=
parse_format_specs
(
begin
,
end
,
handler
);
if
(
begin
==
end
||
*
begin
!=
'}'
)
on_error
(
"missing '}' in format string"
);
if
(
begin
==
end
||
*
begin
!=
'}'
)
on_error
(
"missing '}' in format string"
);
parse_ctx
.
advance_to
(
begin
);
parse_ctx
.
advance_to
(
begin
);
...
...
include/fmt/ostream.h
View file @
744e66bb
...
@@ -57,7 +57,7 @@ template <typename T, typename Char> class is_streamable {
...
@@ -57,7 +57,7 @@ template <typename T, typename Char> class is_streamable {
private:
private:
template
<
typename
U
>
template
<
typename
U
>
static
decltype
((
void
)(
internal
::
declval
<
test_stream
<
Char
>&>
()
static
decltype
((
void
)(
internal
::
declval
<
test_stream
<
Char
>&>
()
<<
internal
::
declval
<
U
>
()),
<<
internal
::
declval
<
U
>
()),
std
::
true_type
())
std
::
true_type
())
test
(
int
);
test
(
int
);
...
...
include/fmt/prepare.h
View file @
744e66bb
...
@@ -310,12 +310,12 @@ class prepared_format {
...
@@ -310,12 +310,12 @@ class prepared_format {
const
format_part_t
&
part
)
const
{
const
format_part_t
&
part
)
const
{
const
auto
view
=
to_string_view
(
format_
);
const
auto
view
=
to_string_view
(
format_
);
const
auto
specification_begin
=
view
.
data
()
+
part
.
end_of_argument_id
;
const
auto
specification_begin
=
view
.
data
()
+
part
.
end_of_argument_id
;
ctx
.
parse_context
(
).
advance_to
(
specification_begin
);
get_parse_context
(
ctx
).
advance_to
(
specification_begin
);
}
}
template
<
typename
Range
,
typename
Context
,
typename
Id
>
template
<
typename
Range
,
typename
Context
,
typename
Id
>
void
format_arg
(
Context
&
ctx
,
Id
arg_id
)
const
{
void
format_arg
(
Context
&
ctx
,
Id
arg_id
)
const
{
ctx
.
parse_context
(
).
check_arg_id
(
arg_id
);
get_parse_context
(
ctx
).
check_arg_id
(
arg_id
);
const
auto
stopped_at
=
const
auto
stopped_at
=
visit_format_arg
(
arg_formatter
<
Range
>
(
ctx
),
ctx
.
arg
(
arg_id
));
visit_format_arg
(
arg_formatter
<
Range
>
(
ctx
),
ctx
.
arg
(
arg_id
));
ctx
.
advance_to
(
stopped_at
);
ctx
.
advance_to
(
stopped_at
);
...
@@ -537,9 +537,9 @@ struct parts_container_concept_check : std::true_type {
...
@@ -537,9 +537,9 @@ struct parts_container_concept_check : std::true_type {
template
<
typename
T
>
static
std
::
false_type
has_add_check
(
check_second
);
template
<
typename
T
>
static
std
::
false_type
has_add_check
(
check_second
);
template
<
typename
T
>
template
<
typename
T
>
static
decltype
(
(
void
)
declval
<
T
>
().
add
(
static
decltype
(
declval
<
typename
T
::
format_part_type
>
()),
(
void
)
declval
<
T
>
().
add
(
declval
<
typename
T
::
format_part_type
>
()),
std
::
true_type
())
has_add_check
(
check_first
);
std
::
true_type
())
has_add_check
(
check_first
);
typedef
decltype
(
has_add_check
<
PartsContainer
>
(
check_first
()))
has_add
;
typedef
decltype
(
has_add_check
<
PartsContainer
>
(
check_first
()))
has_add
;
static_assert
(
has_add
::
value
,
"PartsContainer doesn't provide add() method"
);
static_assert
(
has_add
::
value
,
"PartsContainer doesn't provide add() method"
);
...
@@ -554,10 +554,9 @@ struct parts_container_concept_check : std::true_type {
...
@@ -554,10 +554,9 @@ struct parts_container_concept_check : std::true_type {
template
<
typename
T
>
template
<
typename
T
>
static
std
::
false_type
has_substitute_last_check
(
check_second
);
static
std
::
false_type
has_substitute_last_check
(
check_second
);
template
<
typename
T
>
template
<
typename
T
>
static
decltype
(
static
decltype
((
void
)
declval
<
T
>
().
substitute_last
(
(
void
)
declval
<
T
>
().
substitute_last
(
declval
<
typename
T
::
format_part_type
>
()),
declval
<
typename
T
::
format_part_type
>
()),
std
::
true_type
())
has_substitute_last_check
(
check_first
);
std
::
true_type
())
has_substitute_last_check
(
check_first
);
typedef
decltype
(
has_substitute_last_check
<
PartsContainer
>
(
typedef
decltype
(
has_substitute_last_check
<
PartsContainer
>
(
check_first
()))
has_substitute_last
;
check_first
()))
has_substitute_last
;
static_assert
(
has_substitute_last
::
value
,
static_assert
(
has_substitute_last
::
value
,
...
...
include/fmt/printf.h
View file @
744e66bb
...
@@ -319,7 +319,7 @@ class printf_arg_formatter
...
@@ -319,7 +319,7 @@ class printf_arg_formatter
/** Formats an argument of a custom (user-defined) type. */
/** Formats an argument of a custom (user-defined) type. */
iterator
operator
()(
typename
basic_format_arg
<
context_type
>::
handle
handle
)
{
iterator
operator
()(
typename
basic_format_arg
<
context_type
>::
handle
handle
)
{
handle
.
format
(
context_
);
handle
.
format
(
get_parse_context
(
context_
),
context_
);
return
this
->
out
();
return
this
->
out
();
}
}
};
};
...
@@ -380,7 +380,6 @@ class basic_printf_context :
...
@@ -380,7 +380,6 @@ class basic_printf_context :
using
base
::
advance_to
;
using
base
::
advance_to
;
using
base
::
out
;
using
base
::
out
;
using
base
::
parse_context
;
/** Formats stored arguments and writes the output to the range. */
/** Formats stored arguments and writes the output to the range. */
OutputIt
format
();
OutputIt
format
();
...
@@ -417,7 +416,7 @@ template <typename OutputIt, typename Char, typename AF>
...
@@ -417,7 +416,7 @@ template <typename OutputIt, typename Char, typename AF>
typename
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
format_arg
typename
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
format_arg
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
get_arg
(
unsigned
arg_index
)
{
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
get_arg
(
unsigned
arg_index
)
{
if
(
arg_index
==
std
::
numeric_limits
<
unsigned
>::
max
())
if
(
arg_index
==
std
::
numeric_limits
<
unsigned
>::
max
())
return
this
->
do_get_arg
(
this
->
parse_context
(
).
next_arg_id
());
return
this
->
do_get_arg
(
get_parse_context
(
*
this
).
next_arg_id
());
return
base
::
arg
(
arg_index
-
1
);
return
base
::
arg
(
arg_index
-
1
);
}
}
...
@@ -462,7 +461,7 @@ unsigned basic_printf_context<OutputIt, Char, AF>::parse_header(
...
@@ -462,7 +461,7 @@ unsigned basic_printf_context<OutputIt, Char, AF>::parse_header(
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
template
<
typename
OutputIt
,
typename
Char
,
typename
AF
>
OutputIt
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
format
()
{
OutputIt
basic_printf_context
<
OutputIt
,
Char
,
AF
>::
format
()
{
auto
out
=
this
->
out
();
auto
out
=
this
->
out
();
const
auto
range
=
this
->
parse_context
(
);
const
auto
range
=
get_parse_context
(
*
this
);
const
Char
*
const
end
=
range
.
end
();
const
Char
*
const
end
=
range
.
end
();
const
Char
*
start
=
range
.
begin
();
const
Char
*
start
=
range
.
begin
();
auto
it
=
start
;
auto
it
=
start
;
...
...
include/fmt/ranges.h
View file @
744e66bb
...
@@ -104,11 +104,10 @@ struct is_range_<
...
@@ -104,11 +104,10 @@ struct is_range_<
/// tuple_size and tuple_element check.
/// tuple_size and tuple_element check.
template
<
typename
T
>
class
is_tuple_like_
{
template
<
typename
T
>
class
is_tuple_like_
{
template
<
typename
U
>
template
<
typename
U
>
static
auto
check
(
U
*
p
)
static
auto
check
(
U
*
p
)
->
decltype
(
->
decltype
(
std
::
tuple_size
<
U
>::
value
,
std
::
tuple_size
<
U
>::
value
,
(
void
)
internal
::
declval
<
(
void
)
internal
::
declval
<
typename
std
::
tuple_element
<
0
,
U
>::
type
>
(),
typename
std
::
tuple_element
<
0
,
U
>::
type
>
(),
int
());
int
());
template
<
typename
>
static
void
check
(...);
template
<
typename
>
static
void
check
(...);
public:
public:
...
...
include/format
View file @
744e66bb
...
@@ -582,8 +582,9 @@ struct format_handler : fmt::internal::error_handler {
...
@@ -582,8 +582,9 @@ struct format_handler : fmt::internal::error_handler {
if (visit_format_arg(f, arg)) return parse_ctx.begin();
if (visit_format_arg(f, arg)) return parse_ctx.begin();
fmt::basic_format_specs<Char> specs;
fmt::basic_format_specs<Char> specs;
using fmt::internal::specs_handler;
using fmt::internal::specs_handler;
fmt::internal::specs_checker<specs_handler<Context>> handler(
using parse_context = basic_format_parse_context<Char>;
specs_handler<Context>(specs, context), get_type(arg));
fmt::internal::specs_checker<specs_handler<parse_context, Context>> handler(
specs_handler<parse_context, Context>(specs, parse_ctx, context), get_type(arg));
begin = parse_format_specs(begin, end, handler);
begin = parse_format_specs(begin, end, handler);
if (begin == end || *begin != '}') on_error("missing '}' in format string");
if (begin == end || *begin != '}') on_error("missing '}' in format string");
parse_ctx.advance_to(begin);
parse_ctx.advance_to(begin);
...
...
test/core-test.cc
View file @
744e66bb
...
@@ -223,10 +223,9 @@ struct custom_context {
...
@@ -223,10 +223,9 @@ struct custom_context {
};
};
bool
called
;
bool
called
;
fmt
::
format_parse_context
ctx
;
fmt
::
format_parse_context
parse_context
()
{
fmt
::
format_parse_context
&
parse_context
()
{
return
ctx
;
}
return
fmt
::
format_parse_context
(
""
);
}
void
advance_to
(
const
char
*
)
{}
void
advance_to
(
const
char
*
)
{}
};
};
...
@@ -234,8 +233,8 @@ TEST(ArgTest, MakeValueWithCustomContext) {
...
@@ -234,8 +233,8 @@ TEST(ArgTest, MakeValueWithCustomContext) {
test_struct
t
;
test_struct
t
;
fmt
::
internal
::
value
<
custom_context
>
arg
=
fmt
::
internal
::
value
<
custom_context
>
arg
=
fmt
::
internal
::
make_value
<
custom_context
>
(
t
);
fmt
::
internal
::
make_value
<
custom_context
>
(
t
);
custom_context
ctx
=
{
false
};
custom_context
ctx
=
{
false
,
fmt
::
format_parse_context
(
""
)
};
arg
.
custom
.
format
(
&
t
,
ctx
);
arg
.
custom
.
format
(
&
t
,
ctx
.
parse_context
(),
ctx
);
EXPECT_TRUE
(
ctx
.
called
);
EXPECT_TRUE
(
ctx
.
called
);
}
}
...
@@ -379,7 +378,7 @@ struct check_custom {
...
@@ -379,7 +378,7 @@ struct check_custom {
}
buffer
;
}
buffer
;
fmt
::
internal
::
basic_buffer
<
char
>&
base
=
buffer
;
fmt
::
internal
::
basic_buffer
<
char
>&
base
=
buffer
;
fmt
::
format_context
ctx
(
std
::
back_inserter
(
base
),
""
,
fmt
::
format_args
());
fmt
::
format_context
ctx
(
std
::
back_inserter
(
base
),
""
,
fmt
::
format_args
());
h
.
format
(
ctx
);
h
.
format
(
get_parse_context
(
ctx
),
ctx
);
EXPECT_EQ
(
"test"
,
std
::
string
(
buffer
.
data
,
buffer
.
size
()));
EXPECT_EQ
(
"test"
,
std
::
string
(
buffer
.
data
,
buffer
.
size
()));
return
test_result
();
return
test_result
();
}
}
...
...
test/format-test.cc
View file @
744e66bb
...
@@ -2164,6 +2164,18 @@ TEST(FormatTest, ConstexprParseFormatSpecs) {
...
@@ -2164,6 +2164,18 @@ TEST(FormatTest, ConstexprParseFormatSpecs) {
static_assert
(
parse_test_specs
(
"{<"
).
res
==
handler
::
ERROR
,
""
);
static_assert
(
parse_test_specs
(
"{<"
).
res
==
handler
::
ERROR
,
""
);
}
}
struct
test_parse_context
{
typedef
char
char_type
;
FMT_CONSTEXPR
unsigned
next_arg_id
()
{
return
33
;
}
template
<
typename
Id
>
FMT_CONSTEXPR
void
check_arg_id
(
Id
)
{}
FMT_CONSTEXPR
const
char
*
begin
()
{
return
FMT_NULL
;
}
FMT_CONSTEXPR
const
char
*
end
()
{
return
FMT_NULL
;
}
void
on_error
(
const
char
*
)
{}
};
struct
test_context
{
struct
test_context
{
typedef
char
char_type
;
typedef
char
char_type
;
typedef
fmt
::
basic_format_arg
<
test_context
>
format_arg
;
typedef
fmt
::
basic_format_arg
<
test_context
>
format_arg
;
...
@@ -2181,23 +2193,18 @@ struct test_context {
...
@@ -2181,23 +2193,18 @@ struct test_context {
return
fmt
::
internal
::
make_arg
<
test_context
>
(
22
);
return
fmt
::
internal
::
make_arg
<
test_context
>
(
22
);
}
}
template
<
typename
Id
>
FMT_CONSTEXPR
void
check_arg_id
(
Id
)
{}
FMT_CONSTEXPR
unsigned
next_arg_id
()
{
return
33
;
}
void
on_error
(
const
char
*
)
{}
void
on_error
(
const
char
*
)
{}
FMT_CONSTEXPR
test_context
&
parse_context
()
{
return
*
this
;
}
FMT_CONSTEXPR
test_context
error_handler
()
{
return
*
this
;
}
FMT_CONSTEXPR
test_context
error_handler
()
{
return
*
this
;
}
FMT_CONSTEXPR
const
char
*
begin
()
{
return
FMT_NULL
;
}
FMT_CONSTEXPR
const
char
*
end
()
{
return
FMT_NULL
;
}
};
};
template
<
size_t
N
>
template
<
size_t
N
>
FMT_CONSTEXPR
fmt
::
format_specs
parse_specs
(
const
char
(
&
s
)[
N
])
{
FMT_CONSTEXPR
fmt
::
format_specs
parse_specs
(
const
char
(
&
s
)[
N
])
{
fmt
::
format_specs
specs
;
fmt
::
format_specs
specs
;
test_parse_context
parse_ctx
;
test_context
ctx
{};
test_context
ctx
{};
fmt
::
internal
::
specs_handler
<
test_context
>
h
(
specs
,
ctx
);
fmt
::
internal
::
specs_handler
<
test_parse_context
,
test_context
>
h
(
specs
,
parse_ctx
,
ctx
);
parse_format_specs
(
s
,
s
+
N
,
h
);
parse_format_specs
(
s
,
s
+
N
,
h
);
return
specs
;
return
specs
;
}
}
...
@@ -2223,8 +2230,8 @@ template <size_t N>
...
@@ -2223,8 +2230,8 @@ template <size_t N>
FMT_CONSTEXPR
fmt
::
internal
::
dynamic_format_specs
<
char
>
parse_dynamic_specs
(
FMT_CONSTEXPR
fmt
::
internal
::
dynamic_format_specs
<
char
>
parse_dynamic_specs
(
const
char
(
&
s
)[
N
])
{
const
char
(
&
s
)[
N
])
{
fmt
::
internal
::
dynamic_format_specs
<
char
>
specs
;
fmt
::
internal
::
dynamic_format_specs
<
char
>
specs
;
test_context
ctx
{};
test_
parse_
context
ctx
{};
fmt
::
internal
::
dynamic_specs_handler
<
test_context
>
h
(
specs
,
ctx
);
fmt
::
internal
::
dynamic_specs_handler
<
test_
parse_
context
>
h
(
specs
,
ctx
);
parse_format_specs
(
s
,
s
+
N
,
h
);
parse_format_specs
(
s
,
s
+
N
,
h
);
return
specs
;
return
specs
;
}
}
...
...
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