mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-07 08:31:16 +00:00
Check dynamic widht/precision id at compile time (#1614)
This commit is contained in:
parent
2b75bd7ce6
commit
7d748a6f82
@ -8,6 +8,7 @@
|
||||
#ifndef FMT_CORE_H_
|
||||
#define FMT_CORE_H_
|
||||
|
||||
#include <climits>
|
||||
#include <cstdio> // std::FILE
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
@ -562,14 +563,24 @@ class basic_format_parse_context : private ErrorHandler {
|
||||
private:
|
||||
basic_string_view<Char> format_str_;
|
||||
int next_arg_id_;
|
||||
int num_args_;
|
||||
|
||||
FMT_CONSTEXPR int do_check_arg_id(int id) {
|
||||
if (id >= num_args_) on_error("argument not found");
|
||||
return id;
|
||||
}
|
||||
|
||||
public:
|
||||
using char_type = Char;
|
||||
using iterator = typename basic_string_view<Char>::iterator;
|
||||
|
||||
explicit FMT_CONSTEXPR basic_format_parse_context(
|
||||
basic_string_view<Char> format_str, ErrorHandler eh = ErrorHandler())
|
||||
: ErrorHandler(eh), format_str_(format_str), next_arg_id_(0) {}
|
||||
basic_string_view<Char> format_str, int num_args = INT_MAX,
|
||||
ErrorHandler eh = {})
|
||||
: ErrorHandler(eh),
|
||||
format_str_(format_str),
|
||||
next_arg_id_(0),
|
||||
num_args_(num_args) {}
|
||||
|
||||
/**
|
||||
Returns an iterator to the beginning of the format string range being
|
||||
@ -594,7 +605,7 @@ class basic_format_parse_context : private ErrorHandler {
|
||||
the next argument index and switches to the automatic indexing.
|
||||
*/
|
||||
FMT_CONSTEXPR int next_arg_id() {
|
||||
if (next_arg_id_ >= 0) return next_arg_id_++;
|
||||
if (next_arg_id_ >= 0) return do_check_arg_id(next_arg_id_++);
|
||||
on_error("cannot switch from manual to automatic argument indexing");
|
||||
return 0;
|
||||
}
|
||||
@ -603,11 +614,13 @@ class basic_format_parse_context : private ErrorHandler {
|
||||
Reports an error if using the automatic argument indexing; otherwise
|
||||
switches to the manual indexing.
|
||||
*/
|
||||
FMT_CONSTEXPR void check_arg_id(int) {
|
||||
if (next_arg_id_ > 0)
|
||||
FMT_CONSTEXPR void check_arg_id(int id) {
|
||||
if (next_arg_id_ > 0) {
|
||||
on_error("cannot switch from automatic to manual argument indexing");
|
||||
else
|
||||
next_arg_id_ = -1;
|
||||
return;
|
||||
}
|
||||
do_check_arg_id(id);
|
||||
next_arg_id_ = -1;
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR void check_arg_id(basic_string_view<Char>) {}
|
||||
|
@ -2632,19 +2632,17 @@ class format_string_checker {
|
||||
explicit FMT_CONSTEXPR format_string_checker(
|
||||
basic_string_view<Char> format_str, ErrorHandler eh)
|
||||
: arg_id_(-1),
|
||||
context_(format_str, eh),
|
||||
context_(format_str, num_args, eh),
|
||||
parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {}
|
||||
|
||||
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
|
||||
|
||||
FMT_CONSTEXPR void on_arg_id() {
|
||||
arg_id_ = context_.next_arg_id();
|
||||
check_arg_id();
|
||||
}
|
||||
FMT_CONSTEXPR void on_arg_id(int id) {
|
||||
arg_id_ = id;
|
||||
context_.check_arg_id(id);
|
||||
check_arg_id();
|
||||
}
|
||||
FMT_CONSTEXPR void on_arg_id(basic_string_view<Char>) {
|
||||
on_error("compile-time checks don't support named arguments");
|
||||
@ -2665,10 +2663,6 @@ class format_string_checker {
|
||||
using parse_context_type = basic_format_parse_context<Char, ErrorHandler>;
|
||||
enum { num_args = sizeof...(Args) };
|
||||
|
||||
FMT_CONSTEXPR void check_arg_id() {
|
||||
if (arg_id_ >= num_args) context_.on_error("argument not found");
|
||||
}
|
||||
|
||||
// Format specifier parsing function.
|
||||
using parse_func = const Char* (*)(parse_context_type&);
|
||||
|
||||
|
@ -2493,6 +2493,8 @@ TEST(FormatTest, FormatStringErrors) {
|
||||
EXPECT_ERROR("{:+}", "format specifier requires signed argument", unsigned);
|
||||
EXPECT_ERROR("{:-}", "format specifier requires signed argument", unsigned);
|
||||
EXPECT_ERROR("{: }", "format specifier requires signed argument", unsigned);
|
||||
EXPECT_ERROR("{:{}}", "argument not found", int);
|
||||
EXPECT_ERROR("{:.{}}", "argument not found", double);
|
||||
EXPECT_ERROR("{:.2}", "precision not allowed for this argument type", int);
|
||||
EXPECT_ERROR("{:s}", "invalid type specifier", int);
|
||||
EXPECT_ERROR("{:s}", "invalid type specifier", bool);
|
||||
|
Loading…
Reference in New Issue
Block a user