2020#include " src/__support/ctype_utils.h"
2121#include " src/__support/macros/config.h"
2222#include " src/__support/str_to_integer.h"
23+ #include " src/__support/wctype_utils.h"
2324
2425namespace LIBC_NAMESPACE_DECL {
2526namespace internal {
@@ -38,6 +39,24 @@ struct LShiftTableEntry {
3839// TODO: Figure out where to put this.
3940enum class RoundDirection { Up, Down, Nearest };
4041
42+ // These constants are used in both this file and in the main str_to_float.h.
43+ // TODO: Figure out where to put this.
44+ template <typename CharType> struct constants ;
45+ template <> struct constants <char > {
46+ static constexpr char DECIMAL_POINT = ' .' ;
47+ static constexpr char DECIMAL_EXPONENT_MARKER = ' e' ;
48+ static constexpr char HEX_EXPONENT_MARKER = ' p' ;
49+ static constexpr char INF_STRING[] = " infinity" ;
50+ static constexpr char NAN_STRING[] = " nan" ;
51+ };
52+ template <> struct constants <wchar_t > {
53+ static constexpr wchar_t DECIMAL_POINT = L' .' ;
54+ static constexpr wchar_t DECIMAL_EXPONENT_MARKER = L' e' ;
55+ static constexpr wchar_t HEX_EXPONENT_MARKER = L' p' ;
56+ static constexpr wchar_t INF_STRING[] = L" infinity" ;
57+ static constexpr wchar_t NAN_STRING[] = L" nan" ;
58+ };
59+
4160// This is based on the HPD data structure described as part of the Simple
4261// Decimal Conversion algorithm by Nigel Tao, described at this link:
4362// https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html
@@ -314,35 +333,36 @@ class HighPrecisionDecimal {
314333public:
315334 // num_string is assumed to be a string of numeric characters. It doesn't
316335 // handle leading spaces.
317- LIBC_INLINE
318- HighPrecisionDecimal (
319- const char *__restrict num_string,
336+ template < typename CharType>
337+ LIBC_INLINE HighPrecisionDecimal (
338+ const CharType *__restrict num_string,
320339 const size_t num_len = cpp::numeric_limits<size_t >::max()) {
321340 bool saw_dot = false ;
322341 size_t num_cur = 0 ;
323342 // This counts the digits in the number, even if there isn't space to store
324343 // them all.
325344 uint32_t total_digits = 0 ;
326345 while (num_cur < num_len &&
327- (isdigit (num_string[num_cur]) || num_string[num_cur] == ' .' )) {
328- if (num_string[num_cur] == ' .' ) {
346+ (isdigit (num_string[num_cur]) ||
347+ num_string[num_cur] == constants<CharType>::DECIMAL_POINT)) {
348+ if (num_string[num_cur] == constants<CharType>::DECIMAL_POINT) {
329349 if (saw_dot) {
330350 break ;
331351 }
332352 this ->decimal_point = static_cast <int32_t >(total_digits);
333353 saw_dot = true ;
334354 } else {
335- if (num_string[num_cur] == ' 0' && this ->num_digits == 0 ) {
355+ int digit = b36_char_to_int (num_string[num_cur]);
356+ if (digit == 0 && this ->num_digits == 0 ) {
336357 --this ->decimal_point ;
337358 ++num_cur;
338359 continue ;
339360 }
340361 ++total_digits;
341362 if (this ->num_digits < MAX_NUM_DIGITS) {
342- this ->digits [this ->num_digits ] = static_cast <uint8_t >(
343- internal::b36_char_to_int (num_string[num_cur]));
363+ this ->digits [this ->num_digits ] = static_cast <uint8_t >(digit);
344364 ++this ->num_digits ;
345- } else if (num_string[num_cur] != ' 0 ' ) {
365+ } else if (digit != 0 ) {
346366 this ->truncated = true ;
347367 }
348368 }
@@ -352,11 +372,10 @@ class HighPrecisionDecimal {
352372 if (!saw_dot)
353373 this ->decimal_point = static_cast <int32_t >(total_digits);
354374
355- if (num_cur < num_len &&
356- (num_string[num_cur] == ' e ' || num_string[num_cur] == ' E ' ) ) {
375+ if (num_cur < num_len && tolower (num_string[num_cur]) ==
376+ constants<CharType>::DECIMAL_EXPONENT_MARKER ) {
357377 ++num_cur;
358- if (isdigit (num_string[num_cur]) || num_string[num_cur] == ' +' ||
359- num_string[num_cur] == ' -' ) {
378+ if (isdigit (num_string[num_cur]) || get_sign (num_string + num_cur) != 0 ) {
360379 auto result =
361380 strtointeger<int32_t >(num_string + num_cur, 10 , num_len - num_cur);
362381 if (result.has_error ()) {
0 commit comments