From 0f48852730af8d61e5c5434fa630a481cbac074f Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Thu, 18 Apr 2019 14:26:27 +0900 Subject: [PATCH] perf: check value type before parsing to avoid needless error message generation --- toml/parser.hpp | 84 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 24 deletions(-) diff --git a/toml/parser.hpp b/toml/parser.hpp index 73cd739..f8d6df0 100644 --- a/toml/parser.hpp +++ b/toml/parser.hpp @@ -1412,6 +1412,46 @@ parse_inline_table(location& loc) {{std::addressof(loc), "should be closed"}})); } +template +value_t guess_number_type(const location& l) +{ + location loc = l; + + if(lex_offset_date_time::invoke(loc)) {return value_t::OffsetDatetime;} + loc.reset(l.iter()); + + if(lex_local_date_time::invoke(loc)) {return value_t::LocalDatetime;} + loc.reset(l.iter()); + + if(lex_local_date::invoke(loc)) {return value_t::LocalDate;} + loc.reset(l.iter()); + + if(lex_local_time::invoke(loc)) {return value_t::LocalTime;} + loc.reset(l.iter()); + + if(lex_float::invoke(loc)) {return value_t::Float;} + loc.reset(l.iter()); + + return value_t::Integer; +} + +template +value_t guess_value_type(const location& loc) +{ + switch(*loc.iter()) + { + case '"' : {return value_t::String; } + case '\'': {return value_t::String; } + case 't' : {return value_t::Boolean;} + case 'f' : {return value_t::Boolean;} + case '[' : {return value_t::Array; } + case '{' : {return value_t::Table; } + case 'i' : {return value_t::Float; } // inf. + case 'n' : {return value_t::Float; } // nan. + default : {return guess_number_type(loc);} + } +} + template result parse_value(location& loc) { @@ -1421,31 +1461,27 @@ result parse_value(location& loc) return err(format_underline("[error] toml::parse_value: input is empty", {{std::addressof(loc), ""}})); } - if(auto r = parse_string (loc)) - {return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));} - if(auto r = parse_array (loc)) - {return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));} - if(auto r = parse_inline_table (loc)) - {return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));} - if(auto r = parse_boolean (loc)) - {return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));} - if(auto r = parse_offset_datetime(loc)) - {return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));} - if(auto r = parse_local_datetime (loc)) - {return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));} - if(auto r = parse_local_date (loc)) - {return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));} - if(auto r = parse_local_time (loc)) - {return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));} - if(auto r = parse_floating (loc)) - {return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));} - if(auto r = parse_integer (loc)) - {return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));} - const auto msg = format_underline("[error] toml::parse_value: " - "unknown token appeared", {{std::addressof(loc), "unknown"}}); - loc.reset(first); - return err(msg); + switch(guess_value_type(loc)) + { + case value_t::Boolean : {return parse_boolean(loc); } + case value_t::Integer : {return parse_integer(loc); } + case value_t::Float : {return parse_floating(loc); } + case value_t::String : {return parse_string(loc); } + case value_t::OffsetDatetime : {return parse_offset_datetime(loc);} + case value_t::LocalDatetime : {return parse_local_datetime(loc); } + case value_t::LocalDate : {return parse_local_date(loc); } + case value_t::LocalTime : {return parse_local_time(loc); } + case value_t::Array : {return parse_array(loc); } + case value_t::Table : {return parse_inline_table(loc); } + default: + { + const auto msg = format_underline("[error] toml::parse_value: " + "unknown token appeared", {{std::addressof(loc), "unknown"}}); + loc.reset(first); + return err(msg); + } + } } template