|
12 | 12 | #include "src/__support/CPP/bit.h" |
13 | 13 | #include "src/__support/CPP/limits.h" |
14 | 14 | #include "src/__support/CPP/optional.h" |
| 15 | +#include "src/__support/CPP/string_view.h" |
15 | 16 | #include "src/__support/FPUtil/FEnvImpl.h" |
16 | 17 | #include "src/__support/FPUtil/FPBits.h" |
17 | 18 | #include "src/__support/FPUtil/dyadic_float.h" |
@@ -1044,6 +1045,27 @@ hexadecimal_string_to_float(const char *__restrict src, |
1044 | 1045 | return output; |
1045 | 1046 | } |
1046 | 1047 |
|
| 1048 | +LIBC_INLINE uint64_t |
| 1049 | +nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) { |
| 1050 | + uint64_t nan_mantissa = 0; |
| 1051 | + |
| 1052 | + if (ncharseq.data() != nullptr && isdigit(ncharseq[0])) { |
| 1053 | + // This is to prevent errors when StorageType is larger than 64 |
| 1054 | + // bits, since strtointeger only supports up to 64 bits. This is |
| 1055 | + // actually more than is required by the specification, which says |
| 1056 | + // for the input type "NAN(n-char-sequence)" that "the meaning of |
| 1057 | + // the n-char sequence is implementation-defined." |
| 1058 | + auto strtoint_result = strtointeger<uint64_t>(ncharseq.data(), 0); |
| 1059 | + if (!strtoint_result.has_error()) |
| 1060 | + nan_mantissa = strtoint_result.value; |
| 1061 | + |
| 1062 | + if (strtoint_result.parsed_len != static_cast<ptrdiff_t>(ncharseq.size())) |
| 1063 | + nan_mantissa = 0; |
| 1064 | + } |
| 1065 | + |
| 1066 | + return nan_mantissa; |
| 1067 | +} |
| 1068 | + |
1047 | 1069 | // Takes a pointer to a string and a pointer to a string pointer. This function |
1048 | 1070 | // is used as the backend for all of the string to float functions. |
1049 | 1071 | template <class T> |
@@ -1136,31 +1158,18 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) { |
1136 | 1158 | ++index; |
1137 | 1159 | if (src[index] == ')') { |
1138 | 1160 | ++index; |
1139 | | - if (isdigit(src[left_paren + 1])) { |
1140 | | - // This is to prevent errors when StorageType is larger than 64 |
1141 | | - // bits, since strtointeger only supports up to 64 bits. This is |
1142 | | - // actually more than is required by the specification, which says |
1143 | | - // for the input type "NAN(n-char-sequence)" that "the meaning of |
1144 | | - // the n-char sequence is implementation-defined." |
1145 | | - |
1146 | | - auto strtoint_result = |
1147 | | - strtointeger<uint64_t>(src + (left_paren + 1), 0); |
1148 | | - if (strtoint_result.has_error()) { |
1149 | | - error = strtoint_result.error; |
1150 | | - } |
1151 | | - nan_mantissa = static_cast<StorageType>(strtoint_result.value); |
1152 | | - if (src[left_paren + 1 + strtoint_result.parsed_len] != ')') |
1153 | | - nan_mantissa = 0; |
1154 | | - } |
| 1161 | + auto nan_mantissa_result = nan_mantissa_from_ncharseq( |
| 1162 | + cpp::string_view(src + (left_paren + 1), index - left_paren - 2)); |
| 1163 | + nan_mantissa = static_cast<StorageType>(nan_mantissa_result); |
1155 | 1164 | } else { |
1156 | 1165 | index = left_paren; |
1157 | 1166 | } |
1158 | 1167 | } |
| 1168 | + |
1159 | 1169 | if (result.get_sign()) { |
1160 | 1170 | result = FPBits(result.build_quiet_nan(nan_mantissa)); |
1161 | 1171 | result.set_sign(true); |
1162 | 1172 | } else { |
1163 | | - result.set_sign(false); |
1164 | 1173 | result = FPBits(result.build_quiet_nan(nan_mantissa)); |
1165 | 1174 | } |
1166 | 1175 | } |
@@ -1195,6 +1204,28 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) { |
1195 | 1204 | return {T(result), index, error}; |
1196 | 1205 | } |
1197 | 1206 |
|
| 1207 | +template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) { |
| 1208 | + using FPBits = typename fputil::FPBits<T>; |
| 1209 | + using StorageType = typename FPBits::StorageType; |
| 1210 | + |
| 1211 | + FPBits result; |
| 1212 | + int error = 0; |
| 1213 | + StorageType nan_mantissa = 0; |
| 1214 | + |
| 1215 | + ptrdiff_t index = 0; |
| 1216 | + while (isalnum(arg[index]) || arg[index] == '_') |
| 1217 | + ++index; |
| 1218 | + |
| 1219 | + if (arg[index] == '\0') { |
| 1220 | + auto nan_mantissa_result = |
| 1221 | + nan_mantissa_from_ncharseq(cpp::string_view(arg, index)); |
| 1222 | + nan_mantissa = static_cast<StorageType>(nan_mantissa_result); |
| 1223 | + } |
| 1224 | + |
| 1225 | + result = FPBits(result.build_quiet_nan(nan_mantissa)); |
| 1226 | + return {T(result), 0, error}; |
| 1227 | +} |
| 1228 | + |
1198 | 1229 | } // namespace internal |
1199 | 1230 | } // namespace LIBC_NAMESPACE |
1200 | 1231 |
|
|
0 commit comments