26#include "third_party/fast_float/src/include/fast_float/fast_float.h"
27#include "third_party/fast_float/src/include/fast_float/float_common.h"
29#if defined(_STLP_VENDOR_CSTD)
31#define FPCLASSIFY_NAMESPACE
33#define FPCLASSIFY_NAMESPACE std
108 uint32_t number =
static_cast<uint32_t
>(
value);
111 number =
static_cast<uint32_t
>(-
value);
114 for (uint32_t factor = 10; digits < 10; digits++, factor *= 10) {
115 if (factor > number)
break;
118 for (
int i = 1;
i <= digits;
i++) {
119 *(
cursor_ -
i) =
'0' +
static_cast<char>(number % 10);
160 return (
x >=
'0' &&
x <=
'9' &&
x <
'0' + radix) ||
161 (radix > 10 &&
x >=
'a' &&
x <
'a' + radix - 10) ||
162 (radix > 10 &&
x >=
'A' &&
x <
'A' + radix - 10);
169 const char* substring) {
170 DCHECK(**current == *substring);
171 for (substring++; *substring !=
'\0'; substring++) {
173 if (*current ==
end || **current != *substring)
return false;
183 while (*current !=
end) {
191template <
int radix_log_2,
class Char>
193 bool negative,
bool allow_trailing_junk) {
194 const Char* current =
start;
198 while (*current ==
'0') {
205 constexpr int radix = (1 << radix_log_2);
207 constexpr int lim_0 =
'0' + (radix < 10 ? radix : 10);
208 constexpr int lim_a =
'a' + (radix - 10);
209 constexpr int lim_A =
'A' + (radix - 10);
213 if (*current >=
'0' && *current < lim_0) {
214 digit =
static_cast<char>(*current) -
'0';
215 }
else if (*current >=
'a' && *current < lim_a) {
216 digit =
static_cast<char>(*current) -
'a' + 10;
217 }
else if (*current >=
'A' && *current < lim_A) {
218 digit =
static_cast<char>(*current) -
'A' + 10;
226 number = number * radix + digit;
227 int overflow =
static_cast<int>(number >> 53);
231 int overflow_bits_count = 1;
232 while (overflow > 1) {
233 overflow_bits_count++;
237 int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
238 int dropped_bits =
static_cast<int>(number) & dropped_bits_mask;
239 number >>= overflow_bits_count;
240 exponent = overflow_bits_count;
242 bool zero_tail =
true;
245 if (current ==
end || !
isDigit(*current, radix))
break;
246 zero_tail = zero_tail && *current ==
'0';
247 exponent += radix_log_2;
254 int middle_value = (1 << (overflow_bits_count - 1));
255 if (dropped_bits > middle_value) {
257 }
else if (dropped_bits == middle_value) {
260 if ((number & 1) != 0 || !zero_tail) {
266 if ((number & (
static_cast<int64_t
>(1) << 53)) != 0) {
273 }
while (current !=
end);
275 DCHECK(number < (int64_t{1} << 53));
276 DCHECK(
static_cast<int64_t
>(
static_cast<double>(number)) == number);
280 if (number == 0)
return -0.0;
283 return static_cast<double>(number);
287 return std::ldexp(
static_cast<double>(
negative ? -number : number), exponent);
293enum class State { kRunning,
kError, kJunk, kEmpty,
kZero, kDone };
295enum class Sign { kNegative, kPositive,
kNone };
306 DCHECK(subject->IsFlat());
318 DCHECK(subject->IsFlat());
354 return subject_->GetFlatContent(no_gc).ToOneByteVector();
362 return subject_->GetFlatContent(no_gc).ToUC16Vector();
374 template <
class Char>
395 if (
state_ != State::kRunning)
return;
400 if (
state_ != State::kRunning)
return;
416 if (*current ==
'+') {
419 if (current ==
end) {
422 sign_ = Sign::kPositive;
423 }
else if (*current ==
'-') {
425 if (current ==
end) {
428 sign_ = Sign::kNegative;
434 if (*current ==
'0') {
437 if (*current ==
'x' || *current ==
'X') {
442 (*current ==
'o' || *current ==
'O')) {
447 (*current ==
'b' || *current ==
'B')) {
455 }
else if (
radix_ == 16) {
456 if (*current ==
'0') {
460 if (*current ==
'x' || *current ==
'X') {
469 while (*current ==
'0') {
498 template <
class Char>
527 case State::kRunning:
534 template <
class Char>
537 template <
class Char>
565 template <
class Char>
569 constexpr size_t kMaxSignificantDigits = 309;
572 constexpr size_t kBufferSize = kMaxSignificantDigits + 2;
573 char buffer[kBufferSize];
574 size_t buffer_pos = 0;
575 while (*current >=
'0' && *current <=
'9') {
576 if (buffer_pos <= kMaxSignificantDigits) {
579 static_assert(kMaxSignificantDigits < kBufferSize);
580 buffer[buffer_pos++] =
static_cast<char>(*current);
583 if (current ==
end)
break;
587 buffer[buffer_pos] =
'\0';
589 result_ = Strtod(buffer_vector, 0);
604 int lim_0 =
'0' + (
radix() < 10 ?
radix() : 10);
605 int lim_a =
'a' + (
radix() - 10);
606 int lim_A =
'A' + (
radix() - 10);
617 uint32_t part = 0, multiplier = 1;
620 if (*current >=
'0' && *current < lim_0) {
622 }
else if (*current >=
'a' && *current < lim_a) {
623 d = *current -
'a' + 10;
624 }
else if (*current >=
'A' && *current < lim_A) {
625 d = *current -
'A' + 10;
635 const uint32_t kMaximumMultiplier = 0xFFFFFFFFU / 36;
636 uint32_t
m = multiplier *
static_cast<uint32_t
>(
radix());
637 if (
m > kMaximumMultiplier)
break;
638 part = part *
radix() + d;
640 DCHECK(multiplier > part);
643 if (current ==
end) {
670 return empty_string_val;
678 const Char* prefixed =
current;
679 if (*prefixed ==
'0') {
681 if (prefixed ==
end)
return 0;
683 if (*prefixed ==
'x' || *prefixed ==
'X') {
687 }
else if (*prefixed ==
'o' || *prefixed ==
'O') {
691 }
else if (*prefixed ==
'b' || *prefixed ==
'B') {
706 using UC = std::conditional_t<std::is_same_v<Char, uint8_t>, char,
char16_t>;
707 static_assert(
sizeof(UC) ==
sizeof(Char));
708 const UC* current_uc =
reinterpret_cast<const UC*
>(
current);
709 const UC* end_uc =
reinterpret_cast<const UC*
>(
end);
711 fast_float::from_chars(current_uc, end_uc, value,
712 static_cast<fast_float::chars_format
>(
713 fast_float::chars_format::general |
714 fast_float::chars_format::no_infnan |
715 fast_float::chars_format::allow_leading_plus));
716 if (ret.ptr == end_uc)
return value;
717 if (ret.ptr > current_uc) {
718 current =
reinterpret_cast<const Char*
>(ret.ptr);
728 static constexpr char kInfinityString[] =
"Infinity";
736 case kInfinityString[0]:
763 double empty_string_val) {
771 double empty_string_val) {
777 double empty_string_val) {
809template <
typename IsolateT>
843 if (
state() == State::kEmpty) {
850 switch (this->
state()) {
860 case State::kRunning:
871 if (
state() == State::kZero) {
873 return std::unique_ptr<char[]>(
new char[2]{
'0',
'\0'});
881 std::unique_ptr<char[]> out(
new char[num_chars + 1]);
882 processor->ToString(out.get(), &num_chars, digits, 10,
false);
883 out[num_chars] =
'\0';
889 template <
class Char>
897 if (
result == Result::kMaxSizeExceeded) {
925template <
typename IsolateT>
928 isolate,
reinterpret_cast<const uint8_t*
>(
string), strlen(
string));
945 switch (FPCLASSIFY_NAMESPACE::fpclassify(v)) {
949 return (v < 0.0 ?
"-Infinity" :
"Infinity");
962 char decimal_rep[kV8DtoaBufferCapacity];
968 &length, &decimal_point);
972 if (length <= decimal_point && decimal_point <= 21) {
975 builder.
AddPadding(
'0', decimal_point - length);
977 }
else if (0 < decimal_point && decimal_point <= 21) {
981 builder.
AddString(decimal_rep + decimal_point, length - decimal_point);
983 }
else if (decimal_point <= 0 && decimal_point > -6) {
994 builder.
AddString(decimal_rep + 1, length - 1);
998 int exponent = decimal_point - 1;
999 if (exponent < 0) exponent = -exponent;
1014 size_t i = buffer.
size();
1017 buffer[--
i] =
'0' - (n % 10);
1021 return {buffer.
begin() +
i, buffer.
end()};
1026 const double kFirstNonFixed = 1e21;
1031 double abs_value =
value;
1039 if (abs_value >= kFirstNonFixed) {
1047 constexpr int kDecimalRepCapacity =
1049 char decimal_rep[kDecimalRepCapacity];
1050 int decimal_rep_length;
1053 &
sign, &decimal_rep_length, &decimal_point);
1056 int zero_prefix_length = 0;
1057 int zero_postfix_length = 0;
1059 if (decimal_point <= 0) {
1060 zero_prefix_length = -decimal_point + 1;
1064 if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
1065 zero_postfix_length =
1066 decimal_point + f - decimal_rep_length - zero_prefix_length;
1069 unsigned rep_length =
1070 zero_prefix_length + decimal_rep_length + zero_postfix_length;
1074 rep_builder.
AddPadding(
'0', zero_prefix_length);
1075 rep_builder.
AddString(decimal_rep, decimal_rep_length);
1076 rep_builder.
AddPadding(
'0', zero_postfix_length);
1077 char* rep_end = rep_builder.
Finalize();
1095 char* decimal_rep,
int rep_length,
int exponent,
bool negative,
1097 bool negative_exponent =
false;
1099 negative_exponent =
true;
1100 exponent = -exponent;
1107 if (significant_digits != 1) {
1109 DCHECK_EQ(rep_length, strlen(decimal_rep));
1110 DCHECK_GE(significant_digits, rep_length);
1111 builder.
AddString(decimal_rep + 1, rep_length - 1);
1112 builder.
AddPadding(
'0', significant_digits - rep_length);
1142 char decimal_rep[kV8DtoaBufferCapacity];
1143 int decimal_rep_length;
1148 &
sign, &decimal_rep_length, &decimal_point);
1149 f = decimal_rep_length - 1;
1153 &
sign, &decimal_rep_length, &decimal_point);
1156 DCHECK(decimal_rep_length <= f + 1);
1158 int exponent = decimal_point - 1;
1160 exponent,
negative, f + 1, buffer);
1165 constexpr int kMinimalDigits = 1;
1167 USE(kMinimalDigits);
1180 char decimal_rep[kV8DtoaBufferCapacity];
1181 int decimal_rep_length;
1185 &
sign, &decimal_rep_length, &decimal_point);
1186 DCHECK(decimal_rep_length <= p);
1188 int exponent = decimal_point - 1;
1192 if (exponent < -6 || exponent >= p) {
1199 if (decimal_point <= 0) {
1202 builder.
AddString(decimal_rep, decimal_rep_length);
1203 builder.
AddPadding(
'0', p - decimal_rep_length);
1205 const size_t m = std::min(decimal_rep_length, decimal_point);
1207 builder.
AddPadding(
'0', decimal_point - decimal_rep_length);
1208 if (decimal_point < p) {
1210 const int extra =
negative ? 2 : 1;
1211 if (decimal_rep_length > decimal_point) {
1212 DCHECK_EQ(decimal_rep_length - decimal_point,
1213 strlen(decimal_rep + decimal_point));
1214 const int len = decimal_rep_length - decimal_point;
1217 std::min(len, p -
static_cast<int>(builder.
position() - extra));
1221 extra + (p -
static_cast<int>(builder.
position())));
1237 CHECK(radix >= 2 && radix <= 36);
1238 CHECK(std::isfinite(value));
1241 static const char chars[] =
"0123456789abcdefghijklmnopqrstuvwxyz";
1243 size_t integer_cursor = buffer.
size() / 2;
1244 size_t fraction_cursor = integer_cursor;
1250 double integer = std::floor(value);
1251 double fraction = value - integer;
1254 bool delta_is_positive =
true;
1261 delta_is_positive =
false;
1267 if (delta_is_positive && fraction >= delta) {
1269 buffer[fraction_cursor++] =
'.';
1275 int digit =
static_cast<int>(fraction);
1276 buffer[fraction_cursor++] = chars[digit];
1280 if (fraction > 0.5 || (fraction == 0.5 && (digit & 1))) {
1281 if (fraction + delta > 1) {
1285 if (fraction_cursor == buffer.
size() / 2) {
1286 CHECK_EQ(
'.', buffer[fraction_cursor]);
1291 char c = buffer[fraction_cursor];
1293 digit = c >
'9' ? (c -
'a' + 10) : (c -
'0');
1294 if (digit + 1 < radix) {
1295 buffer[fraction_cursor++] = chars[digit + 1];
1302 }
while (fraction >= delta);
1308 buffer[--integer_cursor] =
'0';
1312 buffer[--integer_cursor] = chars[
static_cast<int>(
remainder)];
1313 integer = (integer -
remainder) / radix;
1314 }
while (integer > 0);
1317 if (
negative) buffer[--integer_cursor] =
'-';
1319 DCHECK_GT(fraction_cursor, integer_cursor);
1320 return {buffer.
begin() + integer_cursor, fraction_cursor - integer_cursor};
1331 double empty_string_val) {
1333 DCHECK(string->IsFlat());
1345 uint32_t max_length_for_conversion) {
1347 uint32_t length =
object->length();
1348 if (length > max_length_for_conversion) {
1349 return std::nullopt;
1352 auto buffer = std::make_unique<base::uc16[]>(max_length_for_conversion);
1362 const uint32_t kMaxLengthForConversion = 20;
1363 uint32_t length =
object->length();
1364 if (length > kMaxLengthForConversion) {
1365 return std::nullopt;
1369 uint8_t buffer[kMaxLengthForConversion];
1393 const uint32_t kBufferSize = 24;
1394 const uint32_t length =
string->length();
1395 if (length == 0 || length > kBufferSize)
return false;
1396 uint16_t buffer[kBufferSize];
1402 if (buffer[0] ==
'-') {
1403 if (length == 1)
return false;
1405 if (buffer[1] ==
'I' && length == 9) {
1412 }
else if (buffer[0] ==
'I' && length == 8) {
1414 }
else if (buffer[0] ==
'N' && length == 3) {
1416 return buffer[1] ==
'a' && buffer[2] ==
'N';
1422 static const uint32_t kRepresentableIntegerLength = 15;
1423 if (length -
offset <= kRepresentableIntegerLength) {
1424 const uint32_t initial_offset =
offset;
1425 bool matches =
true;
1431 if (buffer[initial_offset] ==
'0')
return initial_offset == length - 1;
1438 if (std::isnan(d))
return false;
1440 char reverse_buffer[kBufferSize + 1];
1444 if (reverse_string.length() != length)
return false;
1446 if (
static_cast<uint16_t
>(reverse_string[
i]) != buffer[
i])
return false;
1458#undef FPCLASSIFY_NAMESPACE
#define SLOW_DCHECK(condition)
constexpr double NextDouble() const
static constexpr uint64_t kSignMask
static V8_BASE_EXPORT bool GetFlushDenormals()
constexpr size_t size() const
static Vector< T > New(size_t length)
constexpr T * begin() const
constexpr T * end() const
ALWAYS_INLINE CharIt Parse(CharIt start, CharIt end, digit_t radix)
static const uint32_t kMaxLength
static Handle< BigInt > Zero(IsolateT *isolate, AllocationType allocation=AllocationType::kYoung)
static MaybeHandle< BigInt > Allocate(IsolateT *isolate, bigint::FromStringAccumulator *accumulator, bool negative, AllocationType allocation)
void HandleGenericCase(const Char *current, const Char *end)
void HandleBaseTenCase(const Char *current, const Char *end)
NumberParseIntHelper(const base::uc16 *string, int radix, size_t length)
void ParseOneByte(const uint8_t *start) final
double HandlePowerOfTwoCase(const Char *current, const Char *end)
void ParseInternal(const Char *start)
void ParseTwoByte(const base::uc16 *start) final
NumberParseIntHelper(const uint8_t *string, int radix, size_t length)
NumberParseIntHelper(DirectHandle< String > string, int radix)
static bool IsNeeded(Tagged< String > str, LocalIsolate *local_isolate)
static SharedStringAccessGuardIfNeeded NotNeeded()
V8_INLINE void AddPadding(char c, int count)
void AddDecimalInteger(int value)
V8_INLINE void AddStringLiteral(const char(&s)[N])
V8_INLINE void AddSubstring(const char *s, size_t n)
DISALLOW_IMPLICIT_CONSTRUCTORS(SimpleStringBuilder)
bool is_finalized() const
SimpleStringBuilder(size_t size)
SimpleStringBuilder(char *buffer, size_t size)
V8_INLINE void AddString(const char *s, size_t len)
base::Vector< char > buffer_
V8_INLINE void AddCharacter(char c)
void ParseTwoByte(const base::uc16 *start) final
std::unique_ptr< char[]> DecimalString(bigint::Processor *processor)
StringToBigIntHelper(IsolateT *isolate, const uint8_t *string, size_t length)
void ParseOneByte(const uint8_t *start) final
StringToBigIntHelper(IsolateT *isolate, DirectHandle< String > string)
bigint::FromStringAccumulator accumulator_
AllocationType allocation_type()
MaybeHandle< BigInt > GetResult()
void ParseInternal(const Char *start)
StringToIntHelper(const uint8_t *subject, size_t length)
void set_state(State state)
base::Vector< const base::uc16 > GetTwoByteVector(const DisallowGarbageCollection &no_gc)
base::Vector< const uint8_t > GetOneByteVector(const DisallowGarbageCollection &no_gc)
virtual ~StringToIntHelper()=default
StringToIntHelper(DirectHandle< String > subject)
StringToIntHelper(const base::uc16 *subject, int radix, size_t length)
void set_allow_binary_and_octal_prefixes()
StringToIntHelper(DirectHandle< String > subject, int radix)
const base::uc16 * raw_two_byte_subject_
virtual void ParseOneByte(const uint8_t *start)=0
virtual void ParseTwoByte(const base::uc16 *start)=0
DirectHandle< String > subject_
StringToIntHelper(const uint8_t *subject, int radix, size_t length)
void DetectRadixInternal(const Char *current, size_t length)
const uint8_t * raw_one_byte_subject_
bool allow_binary_and_octal_prefixes_
void set_disallow_trailing_junk()
bool allow_trailing_junk_
bool allow_trailing_junk()
base::Vector< const uint8_t > ToOneByteVector() const
base::Vector< const base::uc16 > ToUC16Vector() const
static void WriteToFlat(Tagged< String > source, SinkCharT *sink, uint32_t start, uint32_t length)
static V8_INLINE HandleType< String > Flatten(Isolate *isolate, HandleType< T > string, AllocationType allocation=AllocationType::kYoung)
static bool IsOneByteRepresentationUnderneath(Tagged< String > string)
#define EXPORT_TEMPLATE_DEFINE(export)
ZoneVector< RpoNumber > & result
FunctionLiteral * literal
constexpr bool IsPowerOfTwo(T value)
void DoubleToAscii(double v, DtoaMode mode, int requested_digits, Vector< char > buffer, int *sign, int *length, int *point)
constexpr double uint64_to_double(uint64_t d64)
V8_INLINE Dest bit_cast(Source const &source)
const int kBase10MaximalLength
Vector< const uint8_t > OneByteVector(const char *data, size_t length)
uint32_t ToStringResultLength(Digits X, int radix, bool sign)
void DeleteArray(T *array)
int32_t DoubleToInt32_NoInline(double x)
bool isDigit(int x, int radix)
std::optional< double > TryStringToDouble(LocalIsolate *isolate, DirectHandle< String > object, uint32_t max_length_for_conversion)
double OctalStringToDouble(base::Vector< const uint8_t > str)
double FlatStringToDouble(Tagged< String > string, ConversionFlag flag, double empty_string_val)
double Modulo(double x, double y)
double HexStringToDouble(base::Vector< const uint8_t > str)
double StringToInt(Isolate *isolate, DirectHandle< String > string, int radix)
bool IsSpecialIndex(Tagged< String > string)
bool IsInt32Double(double value)
static std::string_view CreateExponentialRepresentation(char *decimal_rep, int rep_length, int exponent, bool negative, int significant_digits, base::Vector< char > buffer)
bool AdvanceToNonspace(const Char **current, const Char *end)
bool IsWhiteSpaceOrLineTerminator(base::uc32 c)
std::string_view IntToStringView(int n, base::Vector< char > buffer)
MaybeHandle< BigInt > BigIntLiteral(IsolateT *isolate, const char *string)
double ImplicitOctalStringToDouble(base::Vector< const uint8_t > str)
double BinaryStringToDouble(base::Vector< const uint8_t > str)
std::string_view DoubleToExponentialStringView(double value, int f, base::Vector< char > buffer)
double SignedZero(bool negative)
constexpr int kDoubleToFixedMaxDigitsBeforePoint
int32_t DoubleToInt32(double x)
double InternalStringToDouble(const Char *current, const Char *end, ConversionFlag flag, double empty_string_val)
constexpr bool IsDecimalDigit(base::uc32 c)
constexpr uint64_t kQuietNaNMask
float DoubleToFloat32_NoInline(double x)
float DoubleToFloat32(double x)
@ ALLOW_NON_DECIMAL_PREFIX
double InternalStringToIntDouble(const Char *start, const Char *end, bool negative, bool allow_trailing_junk)
std::string_view DoubleToStringView(double v, base::Vector< char > buffer)
std::optional< double > TryStringToInt(LocalIsolate *isolate, DirectHandle< String > object, int radix)
bool SubStringEquals(const Char **current, const Char *end, const char *substring)
std::string_view DoubleToRadixStringView(double value, int radix, base::Vector< char > buffer)
void MemCopy(void *dest, const void *src, size_t size)
std::string_view DoubleToFixedStringView(double value, int f, base::Vector< char > buffer)
std::string_view DoubleToPrecisionStringView(double value, int p, base::Vector< char > buffer)
constexpr int kMaxFractionDigits
double StringToDouble(const char *str, ConversionFlag flags, double empty_string_val)
bool isBinaryDigit(int x)
MaybeHandle< BigInt > StringToBigInt(Isolate *isolate, DirectHandle< String > string)
std::unique_ptr< char[]> BigIntLiteralToDecimal(LocalIsolate *isolate, base::Vector< const uint8_t > literal)
#define DCHECK_LE(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
#define V8_EXPORT_PRIVATE
#define V8_UNLIKELY(condition)