/* * Copyright (c) 2025, Tomás Simões * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include using namespace AK; enum class ParserType { Regular, Hexfloat, Complete }; struct FloatingPointTestCase { StringView input; double expected_value; FloatingPointError expected_error; int expected_end_offset; ParserType parser_type; }; static void floating_point_parsing_helper(FloatingPointTestCase const& test_case) { auto const* input = test_case.input.characters_without_null_termination(); size_t const input_length = test_case.input.length(); switch (test_case.parser_type) { case ParserType::Regular: { auto result = parse_first_floating_point(input, input + input_length); EXPECT_EQ(result.error, test_case.expected_error); // If the error is NoOrInvalidInput, parse_first_floating_point might return NaN/null if (test_case.expected_error != FloatingPointError::NoOrInvalidInput) { EXPECT_EQ(result.value, test_case.expected_value); EXPECT_EQ(result.end_ptr, input + test_case.expected_end_offset); } break; } case ParserType::Hexfloat: { auto result = parse_first_hexfloat_until_zero_character(input); EXPECT_EQ(result.error, test_case.expected_error); EXPECT_EQ(result.value, test_case.expected_value); EXPECT_EQ(result.end_ptr, input + test_case.expected_end_offset); break; } case ParserType::Complete: { auto result = parse_floating_point_completely(input, input + input_length); if (test_case.expected_error == FloatingPointError::None) { EXPECT(result.has_value()); EXPECT_EQ(result.value(), test_case.expected_value); } else { EXPECT(!result.has_value()); } break; } } } TEST_CASE(basic_integer) { floating_point_parsing_helper({ "123"sv, 123.0, FloatingPointError::None, 3, ParserType::Regular }); } TEST_CASE(decimal_number) { floating_point_parsing_helper({ "123.45"sv, 123.45, FloatingPointError::None, 6, ParserType::Regular }); } TEST_CASE(exponent_notation) { floating_point_parsing_helper({ "1.5e3"sv, 1500.0, FloatingPointError::None, 5, ParserType::Regular }); } TEST_CASE(negative_number) { floating_point_parsing_helper({ "-67.89"sv, -67.89, FloatingPointError::None, 6, ParserType::Regular }); } TEST_CASE(zero) { floating_point_parsing_helper({ "0"sv, 0.0, FloatingPointError::None, 1, ParserType::Regular }); } TEST_CASE(negative_zero) { floating_point_parsing_helper({ "-0.0"sv, -0.0, FloatingPointError::None, 4, ParserType::Regular }); } TEST_CASE(invalid_input) { floating_point_parsing_helper({ "abc"sv, 0.0, FloatingPointError::NoOrInvalidInput, 0, ParserType::Regular }); } TEST_CASE(partial_parse) { floating_point_parsing_helper({ "123.45abc"sv, 123.45, FloatingPointError::None, 6, ParserType::Regular }); } TEST_CASE(hex_float) { floating_point_parsing_helper({ "0x1.8p1"sv, 3.0, FloatingPointError::None, 7, ParserType::Hexfloat }); } TEST_CASE(out_of_range) { floating_point_parsing_helper({ "1e309"sv, AK::Infinity, FloatingPointError::OutOfRange, 5, ParserType::Regular }); } TEST_CASE(rounded_down_to_zero) { floating_point_parsing_helper({ "1e-400"sv, 0.0, FloatingPointError::RoundedDownToZero, 6, ParserType::Regular }); } TEST_CASE(parse_completely_valid) { floating_point_parsing_helper({ "123.45"sv, 123.45, FloatingPointError::None, 0, ParserType::Complete }); } TEST_CASE(parse_completely_invalid) { floating_point_parsing_helper({ "123.45a"sv, 0.0, FloatingPointError::NoOrInvalidInput, 0, ParserType::Complete }); }