mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-15 07:20:05 +00:00
More tests
This commit is contained in:
parent
dfdb1adea5
commit
f2b52bba05
@ -1708,6 +1708,9 @@ typedef basic_format_specs<char> format_specs;
|
||||
namespace internal {
|
||||
|
||||
struct error_handler {
|
||||
constexpr error_handler() {}
|
||||
constexpr error_handler(const error_handler &) {}
|
||||
|
||||
// This function is intentionally not constexpr to give a compile-time error.
|
||||
void on_error(const char *message) {
|
||||
FMT_THROW(format_error(message));
|
||||
@ -1944,8 +1947,8 @@ class arg_formatter_base {
|
||||
|
||||
// Parsing context representing a format string range being parsed and an
|
||||
// argument counter for automatic indexing.
|
||||
template <typename Char>
|
||||
class parse_context {
|
||||
template <typename Char, typename ErrorHandler = error_handler>
|
||||
class parse_context : public ErrorHandler {
|
||||
private:
|
||||
basic_string_view<Char> format_str_;
|
||||
int next_arg_index_;
|
||||
@ -1964,8 +1967,9 @@ class parse_context {
|
||||
using char_type = Char;
|
||||
using iterator = const Char*;
|
||||
|
||||
explicit constexpr parse_context(basic_string_view<Char> format_str)
|
||||
: format_str_(format_str), next_arg_index_(0) {}
|
||||
explicit constexpr parse_context(
|
||||
basic_string_view<Char> format_str, ErrorHandler eh = ErrorHandler())
|
||||
: ErrorHandler(eh), format_str_(format_str), next_arg_index_(0) {}
|
||||
|
||||
// Returns an iterator to the beginning of the format string range being
|
||||
// parsed.
|
||||
@ -2140,7 +2144,7 @@ class precision_checker {
|
||||
|
||||
// A format specifier handler that sets fields in basic_format_specs.
|
||||
template <typename Char>
|
||||
class specs_setter : public error_handler {
|
||||
class specs_setter {
|
||||
public:
|
||||
explicit constexpr specs_setter(basic_format_specs<Char> &specs):
|
||||
specs_(specs) {}
|
||||
@ -2278,6 +2282,10 @@ class specs_handler: public specs_setter<typename Context::char_type> {
|
||||
this->specs_.precision_, get_arg(arg_id));
|
||||
}
|
||||
|
||||
void on_error(const char *message) {
|
||||
context_.on_error(message);
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr basic_arg<Context> get_arg(auto_id) {
|
||||
return context_.next_arg();
|
||||
@ -2349,6 +2357,10 @@ class dynamic_specs_handler :
|
||||
specs_.precision_ref = make_arg_ref(arg_id);
|
||||
}
|
||||
|
||||
constexpr void on_error(const char *message) {
|
||||
context_.on_error(message);
|
||||
}
|
||||
|
||||
private:
|
||||
using arg_ref_type = arg_ref<char_type>;
|
||||
|
||||
@ -2593,9 +2605,10 @@ constexpr void parse_format_string(Iterator it, Handler &&handler) {
|
||||
handler.on_text(start, it);
|
||||
}
|
||||
|
||||
template <typename Char, typename T>
|
||||
constexpr const Char *parse_format_specs(parse_context<Char> &ctx) {
|
||||
formatter<T, Char> f;
|
||||
template <typename T, typename ParseContext>
|
||||
constexpr const typename ParseContext::char_type *
|
||||
parse_format_specs(ParseContext &ctx) {
|
||||
formatter<T, typename ParseContext::char_type> f;
|
||||
return f.parse(ctx);
|
||||
}
|
||||
|
||||
@ -2620,11 +2633,12 @@ class format_string_checker : public ErrorHandler {
|
||||
constexpr void on_replacement_field(const Char *) {}
|
||||
|
||||
constexpr const Char *on_format_specs(const Char *s) {
|
||||
parse_context<Char> ctx(basic_string_view<Char>(s, end_ - s));
|
||||
parse_context_type ctx(basic_string_view<Char>(s, end_ - s), *this);
|
||||
return parse_funcs_[arg_index_](ctx);
|
||||
}
|
||||
|
||||
private:
|
||||
using parse_context_type = parse_context<Char, ErrorHandler>;
|
||||
constexpr static size_t NUM_ARGS = sizeof...(Args);
|
||||
|
||||
constexpr void check_arg_index() {
|
||||
@ -2633,12 +2647,12 @@ class format_string_checker : public ErrorHandler {
|
||||
}
|
||||
|
||||
// Format specifier parsing function.
|
||||
using parse_func = const Char *(*)(parse_context<Char> &);
|
||||
using parse_func = const Char *(*)(parse_context_type &);
|
||||
|
||||
const Char *end_;
|
||||
int arg_index_ = -1;
|
||||
parse_func parse_funcs_[NUM_ARGS > 0 ? NUM_ARGS : 1] = {
|
||||
&parse_format_specs<Char, Args>...
|
||||
&parse_format_specs<Args, parse_context_type>...
|
||||
};
|
||||
};
|
||||
|
||||
@ -3184,7 +3198,7 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) {
|
||||
char prefix[4] = "";
|
||||
|
||||
spec_handler(basic_writer<Char> &w, T value, const Spec& s)
|
||||
: writer(w), abs_value(static_cast<UnsignedType>(value)), spec(s) {
|
||||
: writer(w), spec(s), abs_value(static_cast<UnsignedType>(value)) {
|
||||
if (internal::is_negative(value)) {
|
||||
prefix[0] = '-';
|
||||
++prefix_size;
|
||||
|
@ -1703,6 +1703,8 @@ struct test_context {
|
||||
constexpr void check_arg_id(Id) {}
|
||||
|
||||
constexpr unsigned next_arg_index(const char *&) { return 33; }
|
||||
|
||||
void on_error(const char *) {}
|
||||
};
|
||||
|
||||
constexpr fmt::format_specs parse_specs(const char *s) {
|
||||
@ -1867,9 +1869,11 @@ TEST(FormatTest, FormatStringErrors) {
|
||||
#ifndef _MSC_VER
|
||||
// This causes an internal compiler error in MSVC2017.
|
||||
EXPECT_ERROR("{0:=5", "unknown format specifier", char);
|
||||
EXPECT_ERROR("{:{<}", "invalid fill character '{'", int);
|
||||
#endif
|
||||
EXPECT_ERROR("{foo", "missing '}' in format string", int);
|
||||
EXPECT_ERROR("{10000000000}", "number is too big");
|
||||
EXPECT_ERROR("{0x}", "invalid format string");
|
||||
EXPECT_ERROR("{-}", "invalid format string");
|
||||
EXPECT_ERROR("{1}", "argument index out of range", int);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user