-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathapi.h
More file actions
191 lines (168 loc) · 7.63 KB
/
Copy pathapi.h
File metadata and controls
191 lines (168 loc) · 7.63 KB
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#ifndef FFC_API
#define FFC_API
#define FFC_VERSION_YEAR 26
#define FFC_VERSION_MONTH 04
#define FFC_VERSION_BUILD 01
#define FFC_VERSION ((FFC_VERSION_YEAR << 16) | (FFC_VERSION_MONTH << 8) | (FFC_VERSION_BUILD))
#define FFC_VERSION_STRINGIFY_(x) #x
#define FFC_VERSION_STRINGIFY(x) FFC_VERSION_STRINGIFY_(x)
#define FFC_VERSION_STRING \
FFC_VERSION_STRINGIFY(FFC_VERSION_YEAR) "." \
FFC_VERSION_STRINGIFY(FFC_VERSION_MONTH) "." \
FFC_VERSION_STRINGIFY(FFC_VERSION_BUILD)
#include <stddef.h>
#include <stdint.h>
/* always_inline marker, defined here so FFC_IMPL_INLINE (below) can reuse it.
* common.h re-uses this same definition under an #ifndef guard. */
#if defined(_MSC_VER)
#define ffc_inline __forceinline
#elif defined(__GNUC__) || defined(__clang__)
#define ffc_inline __attribute__((always_inline)) inline
#else
#define ffc_inline inline
#endif
typedef uint32_t ffc_outcome;
enum ffc_outcome_bits {
FFC_OUTCOME_OK = 0,
FFC_OUTCOME_INVALID_INPUT = 1,
FFC_OUTCOME_OUT_OF_RANGE = 2,
};
typedef struct ffc_result {
// Where parsing stopped
char const *ptr;
// The outcome of the call
ffc_outcome outcome;
} ffc_result;
typedef uint64_t ffc_format;
enum ffc_format_bits {
FFC_FORMAT_FLAG_SCIENTIFIC = 1ULL << 0,
FFC_FORMAT_FLAG_FIXED = 1ULL << 2, // Gap is present in fast_float original
FFC_FORMAT_FLAG_HEX = 1ULL << 3,
FFC_FORMAT_FLAG_NO_INFNAN = 1ULL << 4,
FFC_FORMAT_FLAG_BASIC_JSON = 1ULL << 5,
FFC_FORMAT_FLAG_BASIC_FORTRAN = 1ULL << 6,
FFC_FORMAT_FLAG_ALLOW_LEADING_PLUS = 1ULL << 7,
FFC_FORMAT_FLAG_SKIP_WHITE_SPACE = 1ULL << 8,
/* Presets */
FFC_PRESET_GENERAL = FFC_FORMAT_FLAG_FIXED | FFC_FORMAT_FLAG_SCIENTIFIC,
FFC_PRESET_JSON = FFC_FORMAT_FLAG_BASIC_JSON |
FFC_PRESET_GENERAL |
FFC_FORMAT_FLAG_NO_INFNAN,
FFC_PRESET_JSON_OR_INFNAN = FFC_FORMAT_FLAG_BASIC_JSON |
FFC_PRESET_GENERAL,
FFC_PRESET_FORTRAN = FFC_FORMAT_FLAG_BASIC_FORTRAN |
FFC_PRESET_GENERAL
};
typedef struct ffc_parse_options {
/** Which number formats are accepted */
ffc_format format;
/** The character used as decimal point; period will be used if decimal_point == '\0' */
char decimal_point;
} ffc_parse_options;
ffc_parse_options ffc_parse_options_default(void);
typedef enum ffc_parse_outcome {
FFC_PARSE_OUTCOME_NO_ERROR = 0,
// [JSON-only] The minus sign must be followed by an integer.
FFC_PARSE_OUTCOME_JSON_MISSING_INTEGER_AFTER_SIGN = 1,
// A sign must be followed by an integer or dot.
FFC_PARSE_OUTCOME_MISSING_INTEGER_OR_DOT_AFTER_SIGN = 2,
// [JSON-only] The integer part must not have leading zeros.
FFC_PARSE_OUTCOME_JSON_LEADING_ZEROS_IN_INTEGER_PART = 3,
// [JSON-only] The integer part must have at least one digit.
FFC_PARSE_OUTCOME_JSON_NO_DIGITS_IN_INTEGER_PART = 4,
// [JSON-only] If there is a decimal point, there must be digits in the
// fractional part.
FFC_PARSE_OUTCOME_JSON_NO_DIGITS_IN_FRACTIONAL_PART = 5,
// The mantissa must have at least one digit.
FFC_PARSE_OUTCOME_NO_DIGITS_IN_MANTISSA = 6,
// Scientific notation requires an exponential part.
FFC_PARSE_OUTCOME_MISSING_EXPONENTIAL_PART = 7,
} ffc_parse_outcome;
/*
* A simplified API; the result will be 0.0 on error, not uninitialized.
* If outcome is null, it will not be written to
*/
double ffc_parse_double_simple(size_t len, const char *input, ffc_outcome *outcome);
ffc_result ffc_parse_double(size_t len, const char *input, double *out);
/**
* Implements the fast_float algorithm from https://github.com/fastfloat/fast_float
* See original for more details
*
* This function parses the character sequence [first,last) for a number. It
* parses floating-point numbers expecting a locale-independent format equivalent
* to what is used by std::strtod in the default ("C") locale. The resulting
* floating-point value is the closest floating-point value (using either float
* or double), using the "round to even" convention for values that would
* otherwise fall right in-between two values. That is, we provide exact parsing
* according to the IEEE standard.
*
* Given a successful parse, the pointer (`ptr`) in the returned value is set to
* point right after the parsed number, and the `value` referenced is set to the
* parsed value. In case of error, the returned `ec` contains a representative
* error, otherwise the default (`FFC_OUTCOME_OK`) value is stored.
*
* The implementation does not allocate heap memory.
*
* Like the C++17 standard, the `fast_float::from_chars` functions take an
* optional last argument of the type `fast_float::chars_format`. It is a bitset
* value: we check whether `fmt & fast_float::chars_format::fixed` and `fmt &
* fast_float::chars_format::scientific` are set to determine whether we allow
* the fixed point and scientific notation respectively. The default is
* `fast_float::chars_format::general` which allows both `fixed` and
* `scientific`.
*/
/* When included from a FFC_IMPL translation unit, the critical-path API
* functions are declared always_inline so GCC inlines them at call sites
* in the same TU. In non-FFC_IMPL TUs the declarations are plain extern.
* Under FFC_IMPL this is just ffc_inline (always_inline); the non-FFC_IMPL
* branch must stay empty so the symbols keep external linkage. */
#ifdef FFC_IMPL
# define FFC_IMPL_INLINE ffc_inline
#else
# define FFC_IMPL_INLINE
#endif
FFC_IMPL_INLINE ffc_result ffc_from_chars_double(const char *start, const char *end, double* out);
FFC_IMPL_INLINE ffc_result ffc_from_chars_double_options(const char *start, const char *end, double* out, ffc_parse_options options);
/*
* A simplified API; the result will be 0.0 on error, not uninitialized.
* If outcome is null, it will not be written to
*/
float ffc_parse_float_simple(size_t len, const char *s, ffc_outcome *outcome);
ffc_result ffc_parse_float(size_t len, const char *s, float *out);
ffc_result ffc_from_chars_float(const char *start, const char *end, float* out);
ffc_result ffc_from_chars_float_options(const char *start, const char *end, float* out, ffc_parse_options options);
ffc_result ffc_parse_i64(size_t len, const char *input, int base, int64_t *out);
ffc_result ffc_parse_u64(size_t len, const char *input, int base, uint64_t *out);
ffc_result ffc_parse_i32(size_t len, const char *input, int base, int32_t *out);
ffc_result ffc_parse_u32(size_t len, const char *input, int base, uint32_t *out);
/*
* A simplified API; the result will be 0 on error, not uninitialized.
* If outcome is null, it will not be written to
*/
int64_t ffc_parse_i64_simple(size_t len, const char *input, int base, ffc_outcome *outcome);
uint64_t ffc_parse_u64_simple(size_t len, const char *input, int base, ffc_outcome *outcome);
int32_t ffc_parse_i32_simple(size_t len, const char *input, int base, ffc_outcome *outcome);
uint32_t ffc_parse_u32_simple(size_t len, const char *input, int base, ffc_outcome *outcome);
/**
* Parse a JSON number from the range [start, end) and return an int64_t or a double
*
* If the outcome is FCC_OUTCOME_OK
* If kind == FFC_JSON_NUM_KIND_INT64, value will be an int64
* If kind == FCC_JSON_NUM_DOUBLE, value will be a double
*
* The returned ffc_result's ptr points at the byte where parsing stopped
*/
typedef uint32_t ffc_json_number_kind;
enum ffc_json_number_kind_bits {
FFC_JSON_NUM_KIND_INT64 = 0,
FFC_JSON_NUM_KIND_DOUBLE = 1,
};
typedef struct ffc_json_number {
ffc_json_number_kind kind;
union {
int64_t i64;
double f64;
} value;
} ffc_json_number;
ffc_result ffc_parse_json_number(const char *start, const char *end, ffc_json_number *out);
#endif // FFC_API