/* * Copyright (c) 2022, David Tuin * Copyright (c) 2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include namespace AK { #define ENUMERATE_INTEGRAL_TYPES \ __ENUMERATE_TYPE(i8) \ __ENUMERATE_TYPE(i16) \ __ENUMERATE_TYPE(i32) \ __ENUMERATE_TYPE(long) \ __ENUMERATE_TYPE(long long) \ __ENUMERATE_TYPE(u8) \ __ENUMERATE_TYPE(u16) \ __ENUMERATE_TYPE(u32) \ __ENUMERATE_TYPE(unsigned long) \ __ENUMERATE_TYPE(unsigned long long) #define ENUMERATE_ARITHMETIC_TYPES \ ENUMERATE_INTEGRAL_TYPES \ __ENUMERATE_TYPE(float) \ __ENUMERATE_TYPE(double) template Optional> parse_first_number(StringView string, TrimWhitespace trim_whitespace, int base) { if (trim_whitespace == TrimWhitespace::Yes) string = StringUtils::trim_whitespace(string, TrimMode::Both); auto const* begin = string.characters_without_null_termination(); auto const* end = begin + string.length(); T value { 0 }; fast_float::parse_options_t options; options.base = base; options.format |= fast_float::chars_format::no_infnan; if constexpr (IsSigned || IsFloatingPoint) { options.format |= fast_float::chars_format::allow_leading_plus; } auto result = fast_float::from_chars_advanced(begin, end, value, options); if constexpr (IsFloatingPoint) { if (result.ec == std::errc::result_out_of_range && (__builtin_isinf(value) || value == 0)) result.ec = {}; } if (result.ec != std::errc {}) return {}; return ParseFirstNumberResult { value, static_cast(result.ptr - begin) }; } #define __ENUMERATE_TYPE(type) \ template Optional> parse_first_number(StringView, TrimWhitespace, int); ENUMERATE_ARITHMETIC_TYPES #undef __ENUMERATE_TYPE template Optional parse_number(StringView string, TrimWhitespace trim_whitespace, int base) { if (trim_whitespace == TrimWhitespace::Yes) string = StringUtils::trim_whitespace(string, TrimMode::Both); auto result = parse_first_number(string, TrimWhitespace::No, base); if (!result.has_value()) return {}; if (result->characters_parsed != string.length()) return {}; return result->value; } #define __ENUMERATE_TYPE(type) \ template Optional parse_number(StringView, TrimWhitespace, int); ENUMERATE_ARITHMETIC_TYPES #undef __ENUMERATE_TYPE template Optional parse_hexadecimal_number(StringView string, TrimWhitespace trim_whitespace) { return parse_number(string, trim_whitespace, 16); } #define __ENUMERATE_TYPE(type) \ template Optional parse_hexadecimal_number(StringView, TrimWhitespace); ENUMERATE_INTEGRAL_TYPES #undef __ENUMERATE_TYPE }