#pragma once #if __cplusplus >= 201703L #include #include #endif #include "utils/stdcompat/string_view.hpp" namespace devilution { enum class ParseIntStatus { Ok, ParseError, OutOfRange }; template struct ParseIntResult { ParseIntStatus status; IntT value = 0; [[nodiscard]] bool ok() const { return status == ParseIntStatus::Ok; } template [[nodiscard]] IntT value_or(T defaultValue) const // NOLINT(readability-identifier-naming) { return ok() ? value : static_cast(defaultValue); } }; template ParseIntResult ParseInt( string_view str, IntT min = std::numeric_limits::min(), IntT max = std::numeric_limits::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 { ParseIntStatus::ParseError }; if (result.ec == std::errc::result_out_of_range || value < min || value > max) return ParseIntResult { ParseIntStatus::OutOfRange }; if (result.ec != std::errc()) return ParseIntResult { ParseIntStatus::ParseError }; return ParseIntResult { ParseIntStatus::Ok, value }; } } // namespace devilution