diff options
| author | Markus Mittendrein <maxmitti@maxmitti.tk> | 2022-01-09 20:35:34 +0100 |
|---|---|---|
| committer | Markus Mittendrein <maxmitti@maxmitti.tk> | 2022-01-09 20:35:34 +0100 |
| commit | bf4c0d7089d262a1ea61550ff4cd951f52dad4da (patch) | |
| tree | 829adabc1aa9fc8fde0989066318d4ed8b77d345 | |
| parent | f1ff922eafc6972dd6437d6e9908146fa92577fa (diff) | |
| download | cxxformat-bf4c0d7089d262a1ea61550ff4cd951f52dad4da.tar.gz cxxformat-bf4c0d7089d262a1ea61550ff4cd951f52dad4da.zip | |
Fix maximum value check for parsing numbers from format strings
| -rw-r--r-- | include/cxxformat/core.hpp | 8 | ||||
| -rw-r--r-- | include/cxxformat/helpers.hpp | 5 |
2 files changed, 8 insertions, 5 deletions
diff --git a/include/cxxformat/core.hpp b/include/cxxformat/core.hpp index 2a78b26..acf8613 100644 --- a/include/cxxformat/core.hpp +++ b/include/cxxformat/core.hpp @@ -189,7 +189,7 @@ namespace format { } 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) + constexpr std::pair<optional_int<T>, std::size_t> parseNumber(std::string_view s, std::size_t pos) { if (pos >= s.size()) { @@ -202,7 +202,7 @@ namespace format { return {std::nullopt, pos}; } - constexpr auto max = std::numeric_limits<T>::max(); + constexpr auto max = optional_int<T>::max; T val{*d}; auto p = pos + 1; @@ -225,12 +225,12 @@ namespace format { } template<std::unsigned_integral T = unsigned int> - constexpr std::pair<std::optional<T>, std::size_t> parseNumberWithMessage(std::string_view s, std::size_t pos, std::string_view numberName) + constexpr std::pair<optional_int<T>, std::size_t> parseNumberWithMessage(std::string_view s, std::size_t pos, std::string_view numberName) { try { return parseNumber<T>(s, pos); } catch(const std::out_of_range&) { - throw std::out_of_range{std::string{numberName} + " is too big; maximum is " + std::to_string(std::numeric_limits<T>::max())}; + throw std::out_of_range{std::string{numberName} + " is too big; maximum is " + std::to_string(optional_int<T>::max)}; } } diff --git a/include/cxxformat/helpers.hpp b/include/cxxformat/helpers.hpp index 73cb0be..c713835 100644 --- a/include/cxxformat/helpers.hpp +++ b/include/cxxformat/helpers.hpp @@ -226,7 +226,7 @@ struct optional_int { constexpr optional_int() noexcept : val{emptyVal} {} constexpr optional_int(std::nullopt_t) noexcept : val{emptyVal} {} - constexpr optional_int(T val) noexcept : val{val} {} + constexpr optional_int(T val) noexcept : val{val} { assert(val != emptyVal); } constexpr optional_int(const optional_int&) noexcept = default; template<std::convertible_to<T> U> constexpr optional_int(const optional_int<U>& other) noexcept : val{other ? other.val : emptyVal} {} @@ -257,4 +257,7 @@ struct optional_int { constexpr T& operator*() noexcept { return val; } constexpr T operator*() const noexcept { return val; } constexpr T value_or(T fallback) const noexcept { return empty() ? fallback : val; } + + static inline constexpr T max{std::signed_integral<T> ? std::numeric_limits<T>::max() : emptyVal - 1}; + static inline constexpr T min{std::numeric_limits<T>::min() + (std::signed_integral<T> ? 1 : 0)}; }; |
