You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
48 lines
1.3 KiB
48 lines
1.3 KiB
#pragma once |
|
|
|
#include <charconv> |
|
#include <string_view> |
|
#include <system_error> |
|
|
|
namespace devilution { |
|
|
|
enum class ParseIntStatus { |
|
Ok, |
|
ParseError, |
|
OutOfRange |
|
}; |
|
|
|
template <typename IntT> |
|
struct ParseIntResult { |
|
ParseIntStatus status; |
|
IntT value = 0; |
|
|
|
[[nodiscard]] bool ok() const |
|
{ |
|
return status == ParseIntStatus::Ok; |
|
} |
|
|
|
template <typename T> |
|
[[nodiscard]] IntT value_or(T defaultValue) const // NOLINT(readability-identifier-naming) |
|
{ |
|
return ok() ? value : static_cast<IntT>(defaultValue); |
|
} |
|
}; |
|
|
|
template <typename IntT> |
|
ParseIntResult<IntT> ParseInt( |
|
std::string_view str, IntT min = std::numeric_limits<IntT>::min(), |
|
IntT max = std::numeric_limits<IntT>::max()) |
|
{ |
|
IntT value; |
|
const std::from_chars_result result = std::from_chars(str.data(), str.data() + str.size(), value); |
|
if (result.ec == std::errc::invalid_argument) |
|
return ParseIntResult<IntT> { ParseIntStatus::ParseError }; |
|
if (result.ec == std::errc::result_out_of_range || value < min || value > max) |
|
return ParseIntResult<IntT> { ParseIntStatus::OutOfRange }; |
|
if (result.ec != std::errc()) |
|
return ParseIntResult<IntT> { ParseIntStatus::ParseError }; |
|
return ParseIntResult<IntT> { ParseIntStatus::Ok, value }; |
|
} |
|
|
|
} // namespace devilution
|
|
|