5 #include "src/conversions.h" 11 #include "src/allocation.h" 12 #include "src/assert-scope.h" 13 #include "src/char-predicates-inl.h" 15 #include "src/handles.h" 16 #include "src/heap/factory.h" 17 #include "src/objects-inl.h" 18 #include "src/objects/bigint.h" 19 #include "src/strtod.h" 20 #include "src/utils.h" 22 #if defined(_STLP_VENDOR_CSTD) 24 #define FPCLASSIFY_NAMESPACE 26 #define FPCLASSIFY_NAMESPACE std 32 inline double JunkStringValue() {
33 return bit_cast<double, uint64_t>(kQuietNaNMask);
36 inline double SignedZero(
bool negative) {
37 return negative ? uint64_to_double(Double::kSignMask) : 0.0;
40 inline bool isDigit(
int x,
int radix) {
41 return (x >=
'0' && x <=
'9' && x <
'0' + radix) ||
42 (radix > 10 && x >=
'a' && x <
'a' + radix - 10) ||
43 (radix > 10 && x >=
'A' && x <
'A' + radix - 10);
46 inline bool isBinaryDigit(
int x) {
return x ==
'0' || x ==
'1'; }
48 template <
class Iterator,
class EndMark>
49 bool SubStringEquals(Iterator* current, EndMark end,
const char* substring) {
50 DCHECK(**current == *substring);
51 for (substring++; *substring !=
'\0'; substring++) {
53 if (*current == end || **current != *substring)
return false;
61 template <
class Iterator,
class EndMark>
62 inline bool AdvanceToNonspace(Iterator* current, EndMark end) {
63 while (*current != end) {
64 if (!IsWhiteSpaceOrLineTerminator(**current))
return true;
71 template <
int radix_log_2,
class Iterator,
class EndMark>
72 double InternalStringToIntDouble(Iterator current, EndMark end,
bool negative,
73 bool allow_trailing_junk) {
74 DCHECK(current != end);
77 while (*current ==
'0') {
79 if (current == end)
return SignedZero(negative);
84 const int radix = (1 << radix_log_2);
86 int lim_0 =
'0' + (radix < 10 ? radix : 10);
87 int lim_a =
'a' + (radix - 10);
88 int lim_A =
'A' + (radix - 10);
92 if (*current >=
'0' && *current < lim_0) {
93 digit =
static_cast<char>(*current) -
'0';
94 }
else if (*current >=
'a' && *current < lim_a) {
95 digit =
static_cast<char>(*current) -
'a' + 10;
96 }
else if (*current >=
'A' && *current < lim_A) {
97 digit =
static_cast<char>(*current) -
'A' + 10;
99 if (allow_trailing_junk || !AdvanceToNonspace(¤t, end)) {
102 return JunkStringValue();
106 number = number * radix + digit;
107 int overflow =
static_cast<int>(number >> 53);
111 int overflow_bits_count = 1;
112 while (overflow > 1) {
113 overflow_bits_count++;
117 int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
118 int dropped_bits =
static_cast<int>(number) & dropped_bits_mask;
119 number >>= overflow_bits_count;
120 exponent = overflow_bits_count;
122 bool zero_tail =
true;
125 if (current == end || !isDigit(*current, radix))
break;
126 zero_tail = zero_tail && *current ==
'0';
127 exponent += radix_log_2;
130 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
131 return JunkStringValue();
134 int middle_value = (1 << (overflow_bits_count - 1));
135 if (dropped_bits > middle_value) {
137 }
else if (dropped_bits == middle_value) {
140 if ((number & 1) != 0 || !zero_tail) {
146 if ((number & (static_cast<int64_t>(1) << 53)) != 0) {
153 }
while (current != end);
155 DCHECK(number < ((
int64_t)1 << 53));
156 DCHECK(static_cast<int64_t>(static_cast<double>(number)) == number);
160 if (number == 0)
return -0.0;
163 return static_cast<double>(number);
166 DCHECK_NE(number, 0);
167 return std::ldexp(static_cast<double>(negative ? -number : number), exponent);
176 : isolate_(isolate), subject_(subject), radix_(radix) {
177 DCHECK(subject->IsFlat());
182 : isolate_(isolate), subject_(subject) {
183 DCHECK(subject->IsFlat());
189 : isolate_(isolate), raw_one_byte_subject_(subject), length_(length) {}
194 virtual void AllocateResult() = 0;
201 virtual void HandleSpecialCases() {}
205 void set_allow_binary_and_octal_prefixes() {
206 allow_binary_and_octal_prefixes_ =
true;
208 void set_disallow_trailing_junk() { allow_trailing_junk_ =
false; }
210 bool IsOneByte()
const {
211 return raw_one_byte_subject_ !=
nullptr ||
212 subject_->IsOneByteRepresentationUnderneath();
216 if (raw_one_byte_subject_ !=
nullptr) {
219 return subject_->GetFlatContent().ToOneByteVector();
223 return subject_->GetFlatContent().ToUC16Vector();
227 enum State { kRunning, kError, kJunk, kEmpty, kZero, kDone };
229 enum class Sign { kNegative, kPositive,
kNone };
231 Isolate* isolate() {
return isolate_; }
232 int radix() {
return radix_; }
233 int cursor() {
return cursor_; }
234 int length() {
return length_; }
235 bool negative() {
return sign_ == Sign::kNegative; }
236 Sign sign() {
return sign_; }
237 State state() {
return state_; }
238 void set_state(State state) { state_ = state; }
241 template <
class Char>
242 void DetectRadixInternal(Char current,
int length);
243 template <
class Char>
244 void ParseInternal(Char start);
248 const uint8_t* raw_one_byte_subject_ =
nullptr;
252 Sign sign_ = Sign::kNone;
253 bool leading_zero_ =
false;
254 bool allow_binary_and_octal_prefixes_ =
false;
255 bool allow_trailing_junk_ =
true;
256 State state_ = kRunning;
259 void StringToIntHelper::ParseInt() {
264 DetectRadixInternal(vector.start(), vector.length());
266 Vector<const uc16> vector = GetTwoByteVector();
267 DetectRadixInternal(vector.start(), vector.length());
270 if (state_ != kRunning)
return;
272 HandleSpecialCases();
273 if (state_ != kRunning)
return;
275 DisallowHeapAllocation no_gc;
277 Vector<const uint8_t> vector = GetOneByteVector();
278 DCHECK_EQ(length_, vector.length());
279 ParseInternal(vector.start());
281 Vector<const uc16> vector = GetTwoByteVector();
282 DCHECK_EQ(length_, vector.length());
283 ParseInternal(vector.start());
286 DCHECK_NE(state_, kRunning);
289 template <
class Char>
290 void StringToIntHelper::DetectRadixInternal(Char current,
int length) {
291 Char start = current;
293 Char end = start + length;
295 if (!AdvanceToNonspace(¤t, end)) {
296 return set_state(kEmpty);
299 if (*current ==
'+') {
302 if (current == end) {
303 return set_state(kJunk);
305 sign_ = Sign::kPositive;
306 }
else if (*current ==
'-') {
308 if (current == end) {
309 return set_state(kJunk);
311 sign_ = Sign::kNegative;
317 if (*current ==
'0') {
319 if (current == end)
return set_state(kZero);
320 if (*current ==
'x' || *current ==
'X') {
323 if (current == end)
return set_state(kJunk);
324 }
else if (allow_binary_and_octal_prefixes_ &&
325 (*current ==
'o' || *current ==
'O')) {
328 if (current == end)
return set_state(kJunk);
329 }
else if (allow_binary_and_octal_prefixes_ &&
330 (*current ==
'b' || *current ==
'B')) {
333 if (current == end)
return set_state(kJunk);
335 leading_zero_ =
true;
338 }
else if (radix_ == 16) {
339 if (*current ==
'0') {
342 if (current == end)
return set_state(kZero);
343 if (*current ==
'x' || *current ==
'X') {
345 if (current == end)
return set_state(kJunk);
347 leading_zero_ =
true;
352 while (*current ==
'0') {
353 leading_zero_ =
true;
355 if (current == end)
return set_state(kZero);
358 if (!leading_zero_ && !isDigit(*current, radix_)) {
359 return set_state(kJunk);
362 DCHECK(radix_ >= 2 && radix_ <= 36);
363 STATIC_ASSERT(String::kMaxLength <= INT_MAX);
364 cursor_ =
static_cast<int>(current - start);
367 template <
class Char>
368 void StringToIntHelper::ParseInternal(Char start) {
369 Char current = start + cursor_;
370 Char end = start + length_;
377 int lim_0 =
'0' + (radix_ < 10 ? radix_ : 10);
378 int lim_a =
'a' + (radix_ - 10);
379 int lim_A =
'A' + (radix_ - 10);
393 if (*current >=
'0' && *current < lim_0) {
395 }
else if (*current >=
'a' && *current < lim_a) {
396 d = *current -
'a' + 10;
397 }
else if (*current >=
'A' && *current < lim_A) {
398 d = *current -
'A' + 10;
408 const uint32_t kMaximumMultiplier = 0xFFFFFFFFU / 36;
410 if (m > kMaximumMultiplier)
break;
411 part = part * radix_ + d;
413 DCHECK(multiplier > part);
416 if (current == end) {
423 ResultMultiplyAdd(multiplier, part);
426 if (!allow_trailing_junk_ && AdvanceToNonspace(¤t, end)) {
427 return set_state(kJunk);
430 return set_state(kDone);
443 return JunkStringValue();
445 return SignedZero(negative());
447 return negative() ? -result_ : result_;
456 void AllocateResult()
override {}
458 result_ = result_ * multiplier + part;
462 void HandleSpecialCases()
override {
463 bool is_power_of_two = base::bits::IsPowerOfTwo(radix());
464 if (!is_power_of_two && radix() != 10)
return;
468 DCHECK_EQ(length(), vector.length());
469 result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.start())
470 : HandleBaseTenCase(vector.start());
473 DCHECK_EQ(length(), vector.length());
474 result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.start())
475 : HandleBaseTenCase(vector.start());
480 template <
class Char>
481 double HandlePowerOfTwoCase(Char start) {
482 Char current = start + cursor();
483 Char end = start + length();
484 const bool allow_trailing_junk =
true;
486 const bool negative =
false;
489 return InternalStringToIntDouble<1>(current, end, negative,
490 allow_trailing_junk);
492 return InternalStringToIntDouble<2>(current, end, negative,
493 allow_trailing_junk);
495 return InternalStringToIntDouble<3>(current, end, negative,
496 allow_trailing_junk);
499 return InternalStringToIntDouble<4>(current, end, negative,
500 allow_trailing_junk);
503 return InternalStringToIntDouble<5>(current, end, negative,
504 allow_trailing_junk);
510 template <
class Char>
511 double HandleBaseTenCase(Char start) {
513 Char current = start + cursor();
514 Char end = start + length();
515 const int kMaxSignificantDigits = 309;
518 const int kBufferSize = kMaxSignificantDigits + 2;
519 char buffer[kBufferSize];
521 while (*current >=
'0' && *current <=
'9') {
522 if (buffer_pos <= kMaxSignificantDigits) {
525 DCHECK_LT(buffer_pos, kBufferSize);
526 buffer[buffer_pos++] =
static_cast<char>(*current);
529 if (current == end)
break;
532 SLOW_DCHECK(buffer_pos < kBufferSize);
533 buffer[buffer_pos] =
'\0';
535 return Strtod(buffer_vector, 0);
546 template <
class Iterator,
class EndMark>
547 double InternalStringToDouble(Iterator current, EndMark end,
int flags,
548 double empty_string_val) {
557 if (!AdvanceToNonspace(¤t, end)) {
558 return empty_string_val;
561 const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
570 const int kMaxSignificantDigits = 772;
573 const int kBufferSize = kMaxSignificantDigits + 10;
574 char buffer[kBufferSize];
580 int significant_digits = 0;
581 int insignificant_digits = 0;
582 bool nonzero_digit_dropped =
false;
584 enum Sign { NONE, NEGATIVE, POSITIVE };
588 if (*current ==
'+') {
591 if (current == end)
return JunkStringValue();
593 }
else if (*current ==
'-') {
595 if (current == end)
return JunkStringValue();
599 static const char kInfinityString[] =
"Infinity";
600 if (*current == kInfinityString[0]) {
601 if (!SubStringEquals(¤t, end, kInfinityString)) {
602 return JunkStringValue();
605 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
606 return JunkStringValue();
609 DCHECK_EQ(buffer_pos, 0);
610 return (sign == NEGATIVE) ? -V8_INFINITY : V8_INFINITY;
613 bool leading_zero =
false;
614 if (*current ==
'0') {
616 if (current == end)
return SignedZero(sign == NEGATIVE);
621 if ((flags & ALLOW_HEX) && (*current ==
'x' || *current ==
'X')) {
623 if (current == end || !isDigit(*current, 16) || sign != NONE) {
624 return JunkStringValue();
627 return InternalStringToIntDouble<4>(current, end,
false,
628 allow_trailing_junk);
631 }
else if ((flags & ALLOW_OCTAL) && (*current ==
'o' || *current ==
'O')) {
633 if (current == end || !isDigit(*current, 8) || sign != NONE) {
634 return JunkStringValue();
637 return InternalStringToIntDouble<3>(current, end,
false,
638 allow_trailing_junk);
641 }
else if ((flags & ALLOW_BINARY) && (*current ==
'b' || *current ==
'B')) {
643 if (current == end || !isBinaryDigit(*current) || sign != NONE) {
644 return JunkStringValue();
647 return InternalStringToIntDouble<1>(current, end,
false,
648 allow_trailing_junk);
652 while (*current ==
'0') {
654 if (current == end)
return SignedZero(sign == NEGATIVE);
658 bool octal = leading_zero && (flags & ALLOW_IMPLICIT_OCTAL) != 0;
661 while (*current >=
'0' && *current <=
'9') {
662 if (significant_digits < kMaxSignificantDigits) {
663 DCHECK_LT(buffer_pos, kBufferSize);
664 buffer[buffer_pos++] =
static_cast<char>(*current);
665 significant_digits++;
668 insignificant_digits++;
669 nonzero_digit_dropped = nonzero_digit_dropped || *current !=
'0';
671 octal = octal && *current <
'8';
673 if (current == end)
goto parsing_done;
676 if (significant_digits == 0) {
680 if (*current ==
'.') {
681 if (octal && !allow_trailing_junk)
return JunkStringValue();
682 if (octal)
goto parsing_done;
685 if (current == end) {
686 if (significant_digits == 0 && !leading_zero) {
687 return JunkStringValue();
693 if (significant_digits == 0) {
697 while (*current ==
'0') {
699 if (current == end)
return SignedZero(sign == NEGATIVE);
706 while (*current >=
'0' && *current <=
'9') {
707 if (significant_digits < kMaxSignificantDigits) {
708 DCHECK_LT(buffer_pos, kBufferSize);
709 buffer[buffer_pos++] =
static_cast<char>(*current);
710 significant_digits++;
714 nonzero_digit_dropped = nonzero_digit_dropped || *current !=
'0';
717 if (current == end)
goto parsing_done;
721 if (!leading_zero && exponent == 0 && significant_digits == 0) {
726 return JunkStringValue();
730 if (*current ==
'e' || *current ==
'E') {
731 if (octal)
return JunkStringValue();
733 if (current == end) {
734 if (allow_trailing_junk) {
737 return JunkStringValue();
741 if (*current ==
'+' || *current ==
'-') {
742 sign =
static_cast<char>(*current);
744 if (current == end) {
745 if (allow_trailing_junk) {
748 return JunkStringValue();
753 if (current == end || *current < '0' || *current >
'9') {
754 if (allow_trailing_junk) {
757 return JunkStringValue();
761 const int max_exponent = INT_MAX / 2;
762 DCHECK(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
766 int digit = *current -
'0';
767 if (num >= max_exponent / 10 &&
768 !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
771 num = num * 10 + digit;
774 }
while (current != end && *current >=
'0' && *current <=
'9');
776 exponent += (sign ==
'-' ? -num : num);
779 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
780 return JunkStringValue();
784 exponent += insignificant_digits;
787 return InternalStringToIntDouble<3>(buffer, buffer + buffer_pos,
788 sign == NEGATIVE, allow_trailing_junk);
791 if (nonzero_digit_dropped) {
792 buffer[buffer_pos++] =
'1';
796 SLOW_DCHECK(buffer_pos < kBufferSize);
797 buffer[buffer_pos] =
'\0';
799 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
800 return (sign == NEGATIVE) ? -converted : converted;
803 double StringToDouble(
const char* str,
int flags,
double empty_string_val) {
806 const uint8_t* start =
reinterpret_cast<const uint8_t*
>(str);
807 const uint8_t* end = start + StrLength(str);
808 return InternalStringToDouble(start, end, flags, empty_string_val);
811 double StringToDouble(Vector<const uint8_t> str,
int flags,
812 double empty_string_val) {
815 const uint8_t* start =
reinterpret_cast<const uint8_t*
>(str.start());
816 const uint8_t* end = start + str.length();
817 return InternalStringToDouble(start, end, flags, empty_string_val);
820 double StringToDouble(Vector<const uc16> str,
int flags,
821 double empty_string_val) {
822 const uc16* end = str.start() + str.length();
823 return InternalStringToDouble(str.start(), end, flags, empty_string_val);
826 double StringToInt(Isolate* isolate, Handle<String>
string,
int radix) {
827 NumberParseIntHelper helper(isolate,
string, radix);
828 return helper.GetResult();
833 enum class Behavior { kStringToBigInt, kLiteral };
838 behavior_(Behavior::kStringToBigInt) {
839 set_allow_binary_and_octal_prefixes();
840 set_disallow_trailing_junk();
847 behavior_(Behavior::kLiteral) {
848 set_allow_binary_and_octal_prefixes();
853 if (behavior_ == Behavior::kStringToBigInt && sign() != Sign::kNone &&
857 if (state() == kEmpty) {
858 if (behavior_ == Behavior::kStringToBigInt) {
866 if (should_throw() == kThrowOnError) {
867 THROW_NEW_ERROR(isolate(),
868 NewSyntaxError(MessageTemplate::kBigIntInvalidString),
871 DCHECK_EQ(should_throw(), kDontThrow);
875 return BigInt::Zero(isolate());
877 DCHECK_EQ(should_throw() == kThrowOnError,
878 isolate()->has_pending_exception());
881 return BigInt::Finalize(result_, negative());
890 void AllocateResult()
override {
895 int charcount = length() - cursor();
898 PretenureFlag pretenure =
899 behavior_ == Behavior::kLiteral ? TENURED : NOT_TENURED;
901 isolate(), radix(), charcount, should_throw(), pretenure);
902 if (!maybe.ToHandle(&result_)) {
908 BigInt::InplaceMultiplyAdd(result_, static_cast<uintptr_t>(multiplier),
909 static_cast<uintptr_t>(part));
913 ShouldThrow should_throw()
const {
return kDontThrow; }
920 string = String::Flatten(isolate,
string);
922 return helper.GetResult();
925 MaybeHandle<BigInt> BigIntLiteral(Isolate* isolate,
const char*
string) {
926 StringToBigIntHelper helper(isolate, reinterpret_cast<const uint8_t*>(
string),
927 static_cast<int>(strlen(
string)));
928 return helper.GetResult();
931 const char* DoubleToCString(
double v, Vector<char> buffer) {
932 switch (FPCLASSIFY_NAMESPACE::fpclassify(v)) {
933 case FP_NAN:
return "NaN";
934 case FP_INFINITE:
return (v < 0.0 ?
"-Infinity" :
"Infinity");
935 case FP_ZERO:
return "0";
937 SimpleStringBuilder builder(buffer.start(), buffer.length());
940 const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
941 char decimal_rep[kV8DtoaBufferCapacity];
944 DoubleToAscii(v, DTOA_SHORTEST, 0,
945 Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
946 &sign, &length, &decimal_point);
948 if (sign) builder.AddCharacter(
'-');
950 if (length <= decimal_point && decimal_point <= 21) {
952 builder.AddString(decimal_rep);
953 builder.AddPadding(
'0', decimal_point - length);
955 }
else if (0 < decimal_point && decimal_point <= 21) {
957 builder.AddSubstring(decimal_rep, decimal_point);
958 builder.AddCharacter(
'.');
959 builder.AddString(decimal_rep + decimal_point);
961 }
else if (decimal_point <= 0 && decimal_point > -6) {
963 builder.AddString(
"0.");
964 builder.AddPadding(
'0', -decimal_point);
965 builder.AddString(decimal_rep);
969 builder.AddCharacter(decimal_rep[0]);
971 builder.AddCharacter(
'.');
972 builder.AddString(decimal_rep + 1);
974 builder.AddCharacter(
'e');
975 builder.AddCharacter((decimal_point >= 0) ?
'+' :
'-');
976 int exponent = decimal_point - 1;
977 if (exponent < 0) exponent = -exponent;
978 builder.AddDecimalInteger(exponent);
980 return builder.Finalize();
986 const char* IntToCString(
int n, Vector<char> buffer) {
987 bool negative =
false;
990 if (n == kMinInt)
return DoubleToCString(n, buffer);
995 int i = buffer.length();
998 buffer[--
i] =
'0' + (n % 10);
1001 if (negative) buffer[--
i] =
'-';
1002 return buffer.start() +
i;
1006 char* DoubleToFixedCString(
double value,
int f) {
1007 const int kMaxDigitsBeforePoint = 21;
1008 const double kFirstNonFixed = 1e21;
1010 DCHECK_LE(f, kMaxFractionDigits);
1012 bool negative =
false;
1013 double abs_value = value;
1021 if (abs_value >= kFirstNonFixed) {
1022 char arr[kMaxFractionDigits];
1023 Vector<char> buffer(arr, arraysize(arr));
1024 return StrDup(DoubleToCString(value, buffer));
1031 const int kDecimalRepCapacity =
1032 kMaxDigitsBeforePoint + kMaxFractionDigits + 1;
1033 char decimal_rep[kDecimalRepCapacity];
1034 int decimal_rep_length;
1035 DoubleToAscii(value, DTOA_FIXED, f,
1036 Vector<char>(decimal_rep, kDecimalRepCapacity),
1037 &sign, &decimal_rep_length, &decimal_point);
1040 int zero_prefix_length = 0;
1041 int zero_postfix_length = 0;
1043 if (decimal_point <= 0) {
1044 zero_prefix_length = -decimal_point + 1;
1048 if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
1049 zero_postfix_length = decimal_point + f - decimal_rep_length -
1053 unsigned rep_length =
1054 zero_prefix_length + decimal_rep_length + zero_postfix_length;
1055 SimpleStringBuilder rep_builder(rep_length + 1);
1056 rep_builder.AddPadding(
'0', zero_prefix_length);
1057 rep_builder.AddString(decimal_rep);
1058 rep_builder.AddPadding(
'0', zero_postfix_length);
1059 char* rep = rep_builder.Finalize();
1063 unsigned result_size = decimal_point + f + 2;
1064 SimpleStringBuilder builder(result_size + 1);
1065 if (negative) builder.AddCharacter(
'-');
1066 builder.AddSubstring(rep, decimal_point);
1068 builder.AddCharacter(
'.');
1069 builder.AddSubstring(rep + decimal_point, f);
1072 return builder.Finalize();
1076 static char* CreateExponentialRepresentation(
char* decimal_rep,
1079 int significant_digits) {
1080 bool negative_exponent =
false;
1082 negative_exponent =
true;
1083 exponent = -exponent;
1089 unsigned result_size = significant_digits + 7;
1090 SimpleStringBuilder builder(result_size + 1);
1092 if (negative) builder.AddCharacter(
'-');
1093 builder.AddCharacter(decimal_rep[0]);
1094 if (significant_digits != 1) {
1095 builder.AddCharacter(
'.');
1096 builder.AddString(decimal_rep + 1);
1097 int rep_length = StrLength(decimal_rep);
1098 builder.AddPadding(
'0', significant_digits - rep_length);
1101 builder.AddCharacter(
'e');
1102 builder.AddCharacter(negative_exponent ?
'-' :
'+');
1103 builder.AddDecimalInteger(exponent);
1104 return builder.Finalize();
1108 char* DoubleToExponentialCString(
double value,
int f) {
1110 DCHECK(f >= -1 && f <= kMaxFractionDigits);
1112 bool negative =
false;
1124 const int kV8DtoaBufferCapacity = kMaxFractionDigits + 1 + 1;
1127 DCHECK_LE(kBase10MaximalLength, kMaxFractionDigits + 1);
1128 char decimal_rep[kV8DtoaBufferCapacity];
1129 int decimal_rep_length;
1132 DoubleToAscii(value, DTOA_SHORTEST, 0,
1133 Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
1134 &sign, &decimal_rep_length, &decimal_point);
1135 f = decimal_rep_length - 1;
1137 DoubleToAscii(value, DTOA_PRECISION, f + 1,
1138 Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
1139 &sign, &decimal_rep_length, &decimal_point);
1141 DCHECK_GT(decimal_rep_length, 0);
1142 DCHECK(decimal_rep_length <= f + 1);
1144 int exponent = decimal_point - 1;
1146 CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
1152 char* DoubleToPrecisionCString(
double value,
int p) {
1153 const int kMinimalDigits = 1;
1154 DCHECK(p >= kMinimalDigits && p <= kMaxFractionDigits);
1155 USE(kMinimalDigits);
1157 bool negative =
false;
1167 const int kV8DtoaBufferCapacity = kMaxFractionDigits + 1;
1168 char decimal_rep[kV8DtoaBufferCapacity];
1169 int decimal_rep_length;
1171 DoubleToAscii(value, DTOA_PRECISION, p,
1172 Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
1173 &sign, &decimal_rep_length, &decimal_point);
1174 DCHECK(decimal_rep_length <= p);
1176 int exponent = decimal_point - 1;
1178 char* result =
nullptr;
1180 if (exponent < -6 || exponent >= p) {
1182 CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
1189 unsigned result_size = (decimal_point <= 0)
1190 ? -decimal_point + p + 3
1192 SimpleStringBuilder builder(result_size + 1);
1193 if (negative) builder.AddCharacter(
'-');
1194 if (decimal_point <= 0) {
1195 builder.AddString(
"0.");
1196 builder.AddPadding(
'0', -decimal_point);
1197 builder.AddString(decimal_rep);
1198 builder.AddPadding(
'0', p - decimal_rep_length);
1200 const int m = Min(decimal_rep_length, decimal_point);
1201 builder.AddSubstring(decimal_rep, m);
1202 builder.AddPadding(
'0', decimal_point - decimal_rep_length);
1203 if (decimal_point < p) {
1204 builder.AddCharacter(
'.');
1205 const int extra = negative ? 2 : 1;
1206 if (decimal_rep_length > decimal_point) {
1207 const int len = StrLength(decimal_rep + decimal_point);
1208 const int n = Min(len, p - (builder.position() - extra));
1209 builder.AddSubstring(decimal_rep + decimal_point, n);
1211 builder.AddPadding(
'0', extra + (p - builder.position()));
1214 result = builder.Finalize();
1220 char* DoubleToRadixCString(
double value,
int radix) {
1221 DCHECK(radix >= 2 && radix <= 36);
1222 DCHECK(std::isfinite(value));
1223 DCHECK_NE(0.0, value);
1225 static const char chars[] =
"0123456789abcdefghijklmnopqrstuvwxyz";
1232 static const int kBufferSize = 2200;
1233 char buffer[kBufferSize];
1234 int integer_cursor = kBufferSize / 2;
1235 int fraction_cursor = integer_cursor;
1237 bool negative = value < 0;
1238 if (negative) value = -value;
1241 double integer = std::floor(value);
1242 double fraction = value - integer;
1244 double delta = 0.5 * (Double(value).NextDouble() - value);
1245 delta = std::max(Double(0.0).NextDouble(), delta);
1246 DCHECK_GT(delta, 0.0);
1247 if (fraction > delta) {
1249 buffer[fraction_cursor++] =
'.';
1255 int digit =
static_cast<int>(fraction);
1256 buffer[fraction_cursor++] = chars[digit];
1260 if (fraction > 0.5 || (fraction == 0.5 && (digit & 1))) {
1261 if (fraction + delta > 1) {
1265 if (fraction_cursor == kBufferSize / 2) {
1266 CHECK_EQ(
'.', buffer[fraction_cursor]);
1271 char c = buffer[fraction_cursor];
1273 int digit = c >
'9' ? (c -
'a' + 10) : (c -
'0');
1274 if (digit + 1 < radix) {
1275 buffer[fraction_cursor++] = chars[digit + 1];
1282 }
while (fraction > delta);
1286 while (Double(integer / radix).Exponent() > 0) {
1288 buffer[--integer_cursor] =
'0';
1291 double remainder = Modulo(integer, radix);
1292 buffer[--integer_cursor] = chars[
static_cast<int>(remainder)];
1293 integer = (integer - remainder) / radix;
1294 }
while (integer > 0);
1297 if (negative) buffer[--integer_cursor] =
'-';
1298 buffer[fraction_cursor++] =
'\0';
1299 DCHECK_LT(fraction_cursor, kBufferSize);
1300 DCHECK_LE(0, integer_cursor);
1302 char* result = NewArray<char>(fraction_cursor - integer_cursor);
1303 memcpy(result, buffer + integer_cursor, fraction_cursor - integer_cursor);
1309 double StringToDouble(Isolate* isolate, Handle<String>
string,
int flags,
1310 double empty_string_val) {
1311 Handle<String> flattened = String::Flatten(isolate,
string);
1313 DisallowHeapAllocation no_gc;
1314 String::FlatContent flat = flattened->GetFlatContent();
1315 DCHECK(flat.IsFlat());
1316 if (flat.IsOneByte()) {
1317 return StringToDouble(flat.ToOneByteVector(), flags, empty_string_val);
1319 return StringToDouble(flat.ToUC16Vector(), flags, empty_string_val);
1324 bool IsSpecialIndex(String
string) {
1326 const int kBufferSize = 24;
1327 const int length =
string->length();
1328 if (length == 0 || length > kBufferSize)
return false;
1329 uint16_t buffer[kBufferSize];
1330 String::WriteToFlat(
string, buffer, 0, length);
1334 if (!IsDecimalDigit(buffer[0])) {
1335 if (buffer[0] ==
'-') {
1336 if (length == 1)
return false;
1337 if (!IsDecimalDigit(buffer[1])) {
1338 if (buffer[1] ==
'I' && length == 9) {
1345 }
else if (buffer[0] ==
'I' && length == 8) {
1347 }
else if (buffer[0] ==
'N' && length == 3) {
1349 return buffer[1] ==
'a' && buffer[2] ==
'N';
1355 static const int kRepresentableIntegerLength = 15;
1356 if (length - offset <= kRepresentableIntegerLength) {
1357 const int initial_offset = offset;
1358 bool matches =
true;
1359 for (; offset < length; offset++) {
1360 matches &= IsDecimalDigit(buffer[offset]);
1364 if (buffer[initial_offset] ==
'0')
return initial_offset == length - 1;
1369 Vector<const uint16_t> vector(buffer, length);
1370 double d = StringToDouble(vector, NO_FLAGS);
1371 if (std::isnan(d))
return false;
1373 char reverse_buffer[kBufferSize + 1];
1374 Vector<char> reverse_vector(reverse_buffer, arraysize(reverse_buffer));
1375 const char* reverse_string = DoubleToCString(d, reverse_vector);
1376 for (
int i = 0;
i < length; ++
i) {
1377 if (static_cast<uint16_t>(reverse_string[
i]) != buffer[
i])
return false;