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