diff options
| -rw-r--r-- | include/cxxformat/core.hpp | 23 | ||||
| -rw-r--r-- | main.cpp | 2 |
2 files changed, 11 insertions, 14 deletions
diff --git a/include/cxxformat/core.hpp b/include/cxxformat/core.hpp index 55d1629..4e9858b 100644 --- a/include/cxxformat/core.hpp +++ b/include/cxxformat/core.hpp @@ -188,29 +188,24 @@ namespace format { return std::nullopt; } - template<std::integral T = int> - constexpr std::pair<std::optional<T>, std::size_t> parseNumber(std::string_view s, std::size_t pos) noexcept + template<std::unsigned_integral T = unsigned int> + constexpr std::pair<std::optional<T>, std::size_t> parseNumber(std::string_view s, std::size_t pos) { if (pos >= s.size()) { return {std::nullopt, pos}; } - bool isNegative = (std::signed_integral<T> && s[pos] == '-'); - auto startPos = isNegative ? pos + 1 : pos; - if (startPos >= s.size()) - { - return {std::nullopt, pos}; - } - - auto d = digit<T>(s[startPos]); + const auto d = digit<T>(s[pos]); if (!d) { return {std::nullopt, pos}; } + constexpr auto max = std::numeric_limits<T>::max(); + T val{*d}; - auto p = startPos + 1; + auto p = pos + 1; for (; p < s.size(); ++p) { auto nextD = digit<T>(s[p]); @@ -219,10 +214,14 @@ namespace format { break; } + if (val > max / 10 || val * 10 > max - *nextD) + { + throw std::out_of_range{"Number is too big for the target type and would overflow"}; + } val *= 10; val += *nextD; } - return {isNegative ? -val : val, p}; + return {val, p}; } constexpr auto parseSpec(std::string_view fmt, std::size_t pos, ArgIndex nextArg) @@ -11,8 +11,6 @@ void numberTests() static_assert(parseNumber("1", 0).first == 1); static_assert(parseNumber("10", 0).first == 10); static_assert(parseNumber("10907", 0).first == 10907); - static_assert(parseNumber("-1", 0).first == -1); - static_assert(parseNumber("-11097", 0).first == -11097); } int main(int argc, char* argv[]) |
