Serenity Operating System
at master 87 lines 3.7 kB view raw
1/* 2 * Copyright (c) 2022, David Tuin <davidot@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#ifdef KERNEL 10# error This file should not be included in the KERNEL as it deals with doubles \ 11 and there is no guraantee does not do any floating point computations. 12#endif 13 14#include <AK/StringView.h> 15 16namespace AK { 17 18static constexpr char floating_point_decimal_separator = '.'; 19 20enum class FloatingPointError { 21 None, 22 NoOrInvalidInput, 23 OutOfRange, 24 RoundedDownToZero 25}; 26 27template<FloatingPoint T> 28struct FloatingPointParseResults { 29 char const* end_ptr { nullptr }; 30 FloatingPointError error = FloatingPointError::None; 31 T value {}; 32 33 [[nodiscard]] bool parsed_value() const 34 { 35 // All other errors do indicate out of range but did produce a valid value. 36 return error != FloatingPointError::NoOrInvalidInput; 37 } 38}; 39 40/// This function finds the first floating point within [start, end). The accepted format is 41/// intentionally as lenient as possible. If your format is stricter you must validate it 42/// first. The format accepts: 43/// - An optional sign, both + and - are supported 44/// - 0 or more decimal digits, with leading zeros allowed [1] 45/// - A decimal point '.', which can have no digits after it 46/// - 0 or more decimal digits, unless the first digits [1] doesn't have any digits, 47/// then this must have at least one 48/// - An exponent 'e' or 'E' followed by an optional sign '+' or '-' and at least one digit 49/// This function additionally detects out of range values which have been rounded to 50/// [-]infinity or 0 and gives the next character to read after the floating point. 51template<FloatingPoint T = double> 52FloatingPointParseResults<T> parse_first_floating_point(char const* start, char const* end); 53 54/// This function finds the first floating point starting at start up to the first '\0'. 55/// The format is identical to parse_first_floating_point above. 56template<FloatingPoint T = double> 57FloatingPointParseResults<T> parse_first_floating_point_until_zero_character(char const* start); 58 59/// This function will return either a floating point, or an empty optional if the given StringView 60/// does not a floating point or contains more characters beyond the floating point. For the format 61/// check the comment on parse_first_floating_point. 62template<FloatingPoint T = double> 63Optional<T> parse_floating_point_completely(char const* start, char const* end); 64 65/// This function finds the first floating point as a hex float within [start, end). 66/// The accepted format is intentionally as lenient as possible. If your format is 67/// stricter you must validate it first. The format accepts: 68/// - An optional sign, both + and - are supported 69/// - Optionally either 0x or OX 70/// - 0 or more hexadecimal digits, with leading zeros allowed [1] 71/// - A decimal point '.', which can have no digits after it 72/// - 0 or more hexadecimal digits, unless the first digits [1] doesn't have any digits, 73/// then this must have at least one 74/// - An exponent 'p' or 'P' followed by an optional sign '+' or '-' and at least one decimal digit 75/// NOTE: The exponent is _not_ hexadecimal and gives powers of 2 not 16. 76/// This function additionally detects out of range values which have been rounded to 77/// [-]infinity or 0 and gives the next character to read after the floating point. 78template<FloatingPoint T = double> 79FloatingPointParseResults<T> parse_first_hexfloat_until_zero_character(char const* start); 80 81} 82 83#if USING_AK_GLOBALLY 84using AK::parse_first_floating_point; 85using AK::parse_first_hexfloat_until_zero_character; 86using AK::parse_floating_point_completely; 87#endif