diff options
| author | Markus Mittendrein <maxmitti@maxmitti.tk> | 2022-01-08 20:58:48 +0100 |
|---|---|---|
| committer | Markus Mittendrein <maxmitti@maxmitti.tk> | 2022-01-08 20:58:48 +0100 |
| commit | 5f4b06f1f99ad7bf7af743df99a2f8fbf188548f (patch) | |
| tree | 1a0fe1413a65baf72fc105a4babd3cd961d076a1 | |
| parent | 3d69e19c8f7046b4171597c778bdc82fe8d53bda (diff) | |
| download | cxxformat-5f4b06f1f99ad7bf7af743df99a2f8fbf188548f.tar.gz cxxformat-5f4b06f1f99ad7bf7af743df99a2f8fbf188548f.zip | |
Improve format parsing exception messages
| -rw-r--r-- | include/cxxformat/core.hpp | 10 | ||||
| -rw-r--r-- | include/cxxformat/runtime.hpp | 53 |
2 files changed, 39 insertions, 24 deletions
diff --git a/include/cxxformat/core.hpp b/include/cxxformat/core.hpp index 4e9858b..6eec0ef 100644 --- a/include/cxxformat/core.hpp +++ b/include/cxxformat/core.hpp @@ -224,6 +224,14 @@ namespace format { return {val, p}; } + namespace exceptions { + struct incomplete_specifier : std::invalid_argument { + using std::invalid_argument::invalid_argument; + + incomplete_specifier() : std::invalid_argument{"Incomplete format specifier at end of format string"} {} + }; + }; + constexpr auto parseSpec(std::string_view fmt, std::size_t pos, ArgIndex nextArg) { struct Result { @@ -236,7 +244,7 @@ namespace format { const auto checkEos = [&pos, fmt](std::optional<std::size_t> p = std::nullopt) { if (p.value_or(pos) >= fmt.size()) { - throw std::invalid_argument{"Incomplete format specifier at end of format string"}; + throw exceptions::incomplete_specifier{}; } }; diff --git a/include/cxxformat/runtime.hpp b/include/cxxformat/runtime.hpp index 1c881cc..7e25ee2 100644 --- a/include/cxxformat/runtime.hpp +++ b/include/cxxformat/runtime.hpp @@ -122,11 +122,11 @@ namespace format { { if (args > argCount) { - throw std::invalid_argument{"Too many arguments passed!"}; + throw std::invalid_argument{"Too many arguments passed! Expected %u."_format(argCount)}; } else if (args < argCount) { - throw std::invalid_argument{"Not enough arguments passed!"}; + throw std::invalid_argument{"Not enough arguments passed! Expected %u."_format(argCount)}; } } }; @@ -159,33 +159,40 @@ namespace format { break; } - if (nextSpec + 1 >= fmt.size()) - { - throw std::invalid_argument{"Incomplete format specifier at end of format string"}; - } + try { + if (nextSpec + 1 >= fmt.size()) + { + throw exceptions::incomplete_specifier{}; + } - const auto specStart = fmt[nextSpec + 1]; - if (specStart == '%') - { - // + 1 to include the first % - addString(fmt.substr(pos, nextSpec - pos + 1)); - pos = nextSpec + 2; - } - else - { - const auto [newPos, spec, newNextArg, specMaxArg] = parseSpec(fmt, nextSpec + 1, nextArg); - if (!checkValidConversion(spec.conversion)) + const auto specStart = fmt[nextSpec + 1]; + if (specStart == '%') { - throw std::invalid_argument{"Invalid conversion specifier ‘%c’ in format specifier “%s”"_format(spec.conversion, fmt.substr(nextSpec, newPos - nextSpec))}; + // + 1 to include the first % + addString(fmt.substr(pos, nextSpec - pos + 1)); + pos = nextSpec + 2; } + else + { + const auto [newPos, spec, newNextArg, specMaxArg] = parseSpec(fmt, nextSpec + 1, nextArg); + if (!checkValidConversion(spec.conversion)) + { + throw std::invalid_argument{"Invalid conversion specifier ‘%c’"_format(spec.conversion)}; + } - addString(fmt.substr(pos, nextSpec - pos)); + addString(fmt.substr(pos, nextSpec - pos)); - nextArg = newNextArg; - maxArg = std::max(maxArg, specMaxArg); - pos = newPos; + nextArg = newNextArg; + maxArg = std::max(maxArg, specMaxArg); + pos = newPos; - parts.emplace_back(spec); + parts.emplace_back(spec); + } + } catch(const exceptions::incomplete_specifier&) { + throw exceptions::incomplete_specifier{"Incomplete format specifier “%s” at end of format string"_format(fmt.substr(nextSpec))}; + } catch(const std::exception& e) { + constexpr std::size_t showPartSize = 10; + throw std::invalid_argument{"%s when parsing format specifier “%s%s” at column %u"_format(e.what(), fmt.substr(nextSpec, showPartSize), nextSpec + showPartSize > fmt.size() ? "" : "…", nextSpec)}; } } |
