hitokage 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +89 -0
  7. data/Rakefile +19 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +8 -0
  10. data/ext/hitokage_ext/double-conversion/AUTHORS +14 -0
  11. data/ext/hitokage_ext/double-conversion/COPYING +26 -0
  12. data/ext/hitokage_ext/double-conversion/LICENSE +26 -0
  13. data/ext/hitokage_ext/double-conversion/README +54 -0
  14. data/ext/hitokage_ext/double-conversion/bignum-dtoa.cc +641 -0
  15. data/ext/hitokage_ext/double-conversion/bignum-dtoa.h +84 -0
  16. data/ext/hitokage_ext/double-conversion/bignum.cc +766 -0
  17. data/ext/hitokage_ext/double-conversion/bignum.h +144 -0
  18. data/ext/hitokage_ext/double-conversion/cached-powers.cc +175 -0
  19. data/ext/hitokage_ext/double-conversion/cached-powers.h +64 -0
  20. data/ext/hitokage_ext/double-conversion/diy-fp.cc +57 -0
  21. data/ext/hitokage_ext/double-conversion/diy-fp.h +118 -0
  22. data/ext/hitokage_ext/double-conversion/double-conversion.cc +982 -0
  23. data/ext/hitokage_ext/double-conversion/double-conversion.h +543 -0
  24. data/ext/hitokage_ext/double-conversion/fast-dtoa.cc +665 -0
  25. data/ext/hitokage_ext/double-conversion/fast-dtoa.h +88 -0
  26. data/ext/hitokage_ext/double-conversion/fixed-dtoa.cc +404 -0
  27. data/ext/hitokage_ext/double-conversion/fixed-dtoa.h +56 -0
  28. data/ext/hitokage_ext/double-conversion/ieee.h +402 -0
  29. data/ext/hitokage_ext/double-conversion/strtod.cc +555 -0
  30. data/ext/hitokage_ext/double-conversion/strtod.h +45 -0
  31. data/ext/hitokage_ext/double-conversion/utils.h +341 -0
  32. data/ext/hitokage_ext/extconf.rb +10 -0
  33. data/ext/hitokage_ext/hitokage_ext.cc +26 -0
  34. data/hitokage.gemspec +26 -0
  35. data/lib/hitokage.rb +5 -0
  36. data/lib/hitokage/replace_float_to_s.rb +6 -0
  37. data/lib/hitokage/version.rb +3 -0
  38. metadata +136 -0
@@ -0,0 +1,982 @@
1
+ // Copyright 2010 the V8 project authors. All rights reserved.
2
+ // Redistribution and use in source and binary forms, with or without
3
+ // modification, are permitted provided that the following conditions are
4
+ // met:
5
+ //
6
+ // * Redistributions of source code must retain the above copyright
7
+ // notice, this list of conditions and the following disclaimer.
8
+ // * Redistributions in binary form must reproduce the above
9
+ // copyright notice, this list of conditions and the following
10
+ // disclaimer in the documentation and/or other materials provided
11
+ // with the distribution.
12
+ // * Neither the name of Google Inc. nor the names of its
13
+ // contributors may be used to endorse or promote products derived
14
+ // from this software without specific prior written permission.
15
+ //
16
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+
28
+ #include <limits.h>
29
+ #include <math.h>
30
+
31
+ #include "double-conversion.h"
32
+
33
+ #include "bignum-dtoa.h"
34
+ #include "fast-dtoa.h"
35
+ #include "fixed-dtoa.h"
36
+ #include "ieee.h"
37
+ #include "strtod.h"
38
+ #include "utils.h"
39
+
40
+ namespace double_conversion {
41
+
42
+ const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
43
+ int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
44
+ static DoubleToStringConverter converter(flags,
45
+ "Infinity",
46
+ "NaN",
47
+ 'e',
48
+ -6, 21,
49
+ 6, 0);
50
+ return converter;
51
+ }
52
+
53
+
54
+ bool DoubleToStringConverter::HandleSpecialValues(
55
+ double value,
56
+ StringBuilder* result_builder) const {
57
+ Double double_inspect(value);
58
+ if (double_inspect.IsInfinite()) {
59
+ if (infinity_symbol_ == NULL) return false;
60
+ if (value < 0) {
61
+ result_builder->AddCharacter('-');
62
+ }
63
+ result_builder->AddString(infinity_symbol_);
64
+ return true;
65
+ }
66
+ if (double_inspect.IsNan()) {
67
+ if (nan_symbol_ == NULL) return false;
68
+ result_builder->AddString(nan_symbol_);
69
+ return true;
70
+ }
71
+ return false;
72
+ }
73
+
74
+
75
+ void DoubleToStringConverter::CreateExponentialRepresentation(
76
+ const char* decimal_digits,
77
+ int length,
78
+ int exponent,
79
+ StringBuilder* result_builder) const {
80
+ ASSERT(length != 0);
81
+ result_builder->AddCharacter(decimal_digits[0]);
82
+ if (length != 1) {
83
+ result_builder->AddCharacter('.');
84
+ result_builder->AddSubstring(&decimal_digits[1], length-1);
85
+ }
86
+ result_builder->AddCharacter(exponent_character_);
87
+ if (exponent < 0) {
88
+ result_builder->AddCharacter('-');
89
+ exponent = -exponent;
90
+ } else {
91
+ if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
92
+ result_builder->AddCharacter('+');
93
+ }
94
+ }
95
+ if (exponent == 0) {
96
+ result_builder->AddCharacter('0');
97
+ return;
98
+ }
99
+ ASSERT(exponent < 1e4);
100
+ const int kMaxExponentLength = 5;
101
+ char buffer[kMaxExponentLength + 1];
102
+ buffer[kMaxExponentLength] = '\0';
103
+ int first_char_pos = kMaxExponentLength;
104
+ while (exponent > 0) {
105
+ buffer[--first_char_pos] = '0' + (exponent % 10);
106
+ exponent /= 10;
107
+ }
108
+ result_builder->AddSubstring(&buffer[first_char_pos],
109
+ kMaxExponentLength - first_char_pos);
110
+ }
111
+
112
+
113
+ void DoubleToStringConverter::CreateDecimalRepresentation(
114
+ const char* decimal_digits,
115
+ int length,
116
+ int decimal_point,
117
+ int digits_after_point,
118
+ StringBuilder* result_builder) const {
119
+ // Create a representation that is padded with zeros if needed.
120
+ if (decimal_point <= 0) {
121
+ // "0.00000decimal_rep" or "0.000decimal_rep00".
122
+ result_builder->AddCharacter('0');
123
+ if (digits_after_point > 0) {
124
+ result_builder->AddCharacter('.');
125
+ result_builder->AddPadding('0', -decimal_point);
126
+ ASSERT(length <= digits_after_point - (-decimal_point));
127
+ result_builder->AddSubstring(decimal_digits, length);
128
+ int remaining_digits = digits_after_point - (-decimal_point) - length;
129
+ result_builder->AddPadding('0', remaining_digits);
130
+ }
131
+ } else if (decimal_point >= length) {
132
+ // "decimal_rep0000.00000" or "decimal_rep.0000".
133
+ result_builder->AddSubstring(decimal_digits, length);
134
+ result_builder->AddPadding('0', decimal_point - length);
135
+ if (digits_after_point > 0) {
136
+ result_builder->AddCharacter('.');
137
+ result_builder->AddPadding('0', digits_after_point);
138
+ }
139
+ } else {
140
+ // "decima.l_rep000".
141
+ ASSERT(digits_after_point > 0);
142
+ result_builder->AddSubstring(decimal_digits, decimal_point);
143
+ result_builder->AddCharacter('.');
144
+ ASSERT(length - decimal_point <= digits_after_point);
145
+ result_builder->AddSubstring(&decimal_digits[decimal_point],
146
+ length - decimal_point);
147
+ int remaining_digits = digits_after_point - (length - decimal_point);
148
+ result_builder->AddPadding('0', remaining_digits);
149
+ }
150
+ if (digits_after_point == 0) {
151
+ if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
152
+ result_builder->AddCharacter('.');
153
+ }
154
+ if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
155
+ result_builder->AddCharacter('0');
156
+ }
157
+ }
158
+ }
159
+
160
+
161
+ bool DoubleToStringConverter::ToShortestIeeeNumber(
162
+ double value,
163
+ StringBuilder* result_builder,
164
+ DoubleToStringConverter::DtoaMode mode) const {
165
+ ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE);
166
+ if (Double(value).IsSpecial()) {
167
+ return HandleSpecialValues(value, result_builder);
168
+ }
169
+
170
+ int decimal_point;
171
+ bool sign;
172
+ const int kDecimalRepCapacity = kBase10MaximalLength + 1;
173
+ char decimal_rep[kDecimalRepCapacity];
174
+ int decimal_rep_length;
175
+
176
+ DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity,
177
+ &sign, &decimal_rep_length, &decimal_point);
178
+
179
+ bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
180
+ if (sign && (value != 0.0 || !unique_zero)) {
181
+ result_builder->AddCharacter('-');
182
+ }
183
+
184
+ int exponent = decimal_point - 1;
185
+ if ((decimal_in_shortest_low_ <= exponent) &&
186
+ (exponent < decimal_in_shortest_high_)) {
187
+ CreateDecimalRepresentation(decimal_rep, decimal_rep_length,
188
+ decimal_point,
189
+ Max(0, decimal_rep_length - decimal_point),
190
+ result_builder);
191
+ } else {
192
+ CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
193
+ result_builder);
194
+ }
195
+ return true;
196
+ }
197
+
198
+
199
+ bool DoubleToStringConverter::ToFixed(double value,
200
+ int requested_digits,
201
+ StringBuilder* result_builder) const {
202
+ ASSERT(kMaxFixedDigitsBeforePoint == 60);
203
+ const double kFirstNonFixed = 1e60;
204
+
205
+ if (Double(value).IsSpecial()) {
206
+ return HandleSpecialValues(value, result_builder);
207
+ }
208
+
209
+ if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
210
+ if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;
211
+
212
+ // Find a sufficiently precise decimal representation of n.
213
+ int decimal_point;
214
+ bool sign;
215
+ // Add space for the '\0' byte.
216
+ const int kDecimalRepCapacity =
217
+ kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
218
+ char decimal_rep[kDecimalRepCapacity];
219
+ int decimal_rep_length;
220
+ DoubleToAscii(value, FIXED, requested_digits,
221
+ decimal_rep, kDecimalRepCapacity,
222
+ &sign, &decimal_rep_length, &decimal_point);
223
+
224
+ bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
225
+ if (sign && (value != 0.0 || !unique_zero)) {
226
+ result_builder->AddCharacter('-');
227
+ }
228
+
229
+ CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
230
+ requested_digits, result_builder);
231
+ return true;
232
+ }
233
+
234
+
235
+ bool DoubleToStringConverter::ToExponential(
236
+ double value,
237
+ int requested_digits,
238
+ StringBuilder* result_builder) const {
239
+ if (Double(value).IsSpecial()) {
240
+ return HandleSpecialValues(value, result_builder);
241
+ }
242
+
243
+ if (requested_digits < -1) return false;
244
+ if (requested_digits > kMaxExponentialDigits) return false;
245
+
246
+ int decimal_point;
247
+ bool sign;
248
+ // Add space for digit before the decimal point and the '\0' character.
249
+ const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
250
+ ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
251
+ char decimal_rep[kDecimalRepCapacity];
252
+ int decimal_rep_length;
253
+
254
+ if (requested_digits == -1) {
255
+ DoubleToAscii(value, SHORTEST, 0,
256
+ decimal_rep, kDecimalRepCapacity,
257
+ &sign, &decimal_rep_length, &decimal_point);
258
+ } else {
259
+ DoubleToAscii(value, PRECISION, requested_digits + 1,
260
+ decimal_rep, kDecimalRepCapacity,
261
+ &sign, &decimal_rep_length, &decimal_point);
262
+ ASSERT(decimal_rep_length <= requested_digits + 1);
263
+
264
+ for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
265
+ decimal_rep[i] = '0';
266
+ }
267
+ decimal_rep_length = requested_digits + 1;
268
+ }
269
+
270
+ bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
271
+ if (sign && (value != 0.0 || !unique_zero)) {
272
+ result_builder->AddCharacter('-');
273
+ }
274
+
275
+ int exponent = decimal_point - 1;
276
+ CreateExponentialRepresentation(decimal_rep,
277
+ decimal_rep_length,
278
+ exponent,
279
+ result_builder);
280
+ return true;
281
+ }
282
+
283
+
284
+ bool DoubleToStringConverter::ToPrecision(double value,
285
+ int precision,
286
+ StringBuilder* result_builder) const {
287
+ if (Double(value).IsSpecial()) {
288
+ return HandleSpecialValues(value, result_builder);
289
+ }
290
+
291
+ if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
292
+ return false;
293
+ }
294
+
295
+ // Find a sufficiently precise decimal representation of n.
296
+ int decimal_point;
297
+ bool sign;
298
+ // Add one for the terminating null character.
299
+ const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
300
+ char decimal_rep[kDecimalRepCapacity];
301
+ int decimal_rep_length;
302
+
303
+ DoubleToAscii(value, PRECISION, precision,
304
+ decimal_rep, kDecimalRepCapacity,
305
+ &sign, &decimal_rep_length, &decimal_point);
306
+ ASSERT(decimal_rep_length <= precision);
307
+
308
+ bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
309
+ if (sign && (value != 0.0 || !unique_zero)) {
310
+ result_builder->AddCharacter('-');
311
+ }
312
+
313
+ // The exponent if we print the number as x.xxeyyy. That is with the
314
+ // decimal point after the first digit.
315
+ int exponent = decimal_point - 1;
316
+
317
+ int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
318
+ if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
319
+ (decimal_point - precision + extra_zero >
320
+ max_trailing_padding_zeroes_in_precision_mode_)) {
321
+ // Fill buffer to contain 'precision' digits.
322
+ // Usually the buffer is already at the correct length, but 'DoubleToAscii'
323
+ // is allowed to return less characters.
324
+ for (int i = decimal_rep_length; i < precision; ++i) {
325
+ decimal_rep[i] = '0';
326
+ }
327
+
328
+ CreateExponentialRepresentation(decimal_rep,
329
+ precision,
330
+ exponent,
331
+ result_builder);
332
+ } else {
333
+ CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
334
+ Max(0, precision - decimal_point),
335
+ result_builder);
336
+ }
337
+ return true;
338
+ }
339
+
340
+
341
+ static BignumDtoaMode DtoaToBignumDtoaMode(
342
+ DoubleToStringConverter::DtoaMode dtoa_mode) {
343
+ switch (dtoa_mode) {
344
+ case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST;
345
+ case DoubleToStringConverter::SHORTEST_SINGLE:
346
+ return BIGNUM_DTOA_SHORTEST_SINGLE;
347
+ case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED;
348
+ case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
349
+ default:
350
+ UNREACHABLE();
351
+ }
352
+ }
353
+
354
+
355
+ void DoubleToStringConverter::DoubleToAscii(double v,
356
+ DtoaMode mode,
357
+ int requested_digits,
358
+ char* buffer,
359
+ int buffer_length,
360
+ bool* sign,
361
+ int* length,
362
+ int* point) {
363
+ Vector<char> vector(buffer, buffer_length);
364
+ ASSERT(!Double(v).IsSpecial());
365
+ ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0);
366
+
367
+ if (Double(v).Sign() < 0) {
368
+ *sign = true;
369
+ v = -v;
370
+ } else {
371
+ *sign = false;
372
+ }
373
+
374
+ if (mode == PRECISION && requested_digits == 0) {
375
+ vector[0] = '\0';
376
+ *length = 0;
377
+ return;
378
+ }
379
+
380
+ if (v == 0) {
381
+ vector[0] = '0';
382
+ vector[1] = '\0';
383
+ *length = 1;
384
+ *point = 1;
385
+ return;
386
+ }
387
+
388
+ bool fast_worked;
389
+ switch (mode) {
390
+ case SHORTEST:
391
+ fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
392
+ break;
393
+ case SHORTEST_SINGLE:
394
+ fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0,
395
+ vector, length, point);
396
+ break;
397
+ case FIXED:
398
+ fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
399
+ break;
400
+ case PRECISION:
401
+ fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
402
+ vector, length, point);
403
+ break;
404
+ default:
405
+ fast_worked = false;
406
+ UNREACHABLE();
407
+ }
408
+ if (fast_worked) return;
409
+
410
+ // If the fast dtoa didn't succeed use the slower bignum version.
411
+ BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
412
+ BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
413
+ vector[*length] = '\0';
414
+ }
415
+
416
+
417
+ // Consumes the given substring from the iterator.
418
+ // Returns false, if the substring does not match.
419
+ template <class Iterator>
420
+ static bool ConsumeSubString(Iterator* current,
421
+ Iterator end,
422
+ const char* substring) {
423
+ ASSERT(**current == *substring);
424
+ for (substring++; *substring != '\0'; substring++) {
425
+ ++*current;
426
+ if (*current == end || **current != *substring) return false;
427
+ }
428
+ ++*current;
429
+ return true;
430
+ }
431
+
432
+
433
+ // Maximum number of significant digits in decimal representation.
434
+ // The longest possible double in decimal representation is
435
+ // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
436
+ // (768 digits). If we parse a number whose first digits are equal to a
437
+ // mean of 2 adjacent doubles (that could have up to 769 digits) the result
438
+ // must be rounded to the bigger one unless the tail consists of zeros, so
439
+ // we don't need to preserve all the digits.
440
+ const int kMaxSignificantDigits = 772;
441
+
442
+
443
+ static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 };
444
+ static const int kWhitespaceTable7Length = ARRAY_SIZE(kWhitespaceTable7);
445
+
446
+
447
+ static const uc16 kWhitespaceTable16[] = {
448
+ 160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195,
449
+ 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279
450
+ };
451
+ static const int kWhitespaceTable16Length = ARRAY_SIZE(kWhitespaceTable16);
452
+
453
+
454
+ static bool isWhitespace(int x) {
455
+ if (x < 128) {
456
+ for (int i = 0; i < kWhitespaceTable7Length; i++) {
457
+ if (kWhitespaceTable7[i] == x) return true;
458
+ }
459
+ } else {
460
+ for (int i = 0; i < kWhitespaceTable16Length; i++) {
461
+ if (kWhitespaceTable16[i] == x) return true;
462
+ }
463
+ }
464
+ return false;
465
+ }
466
+
467
+
468
+ // Returns true if a nonspace found and false if the end has reached.
469
+ template <class Iterator>
470
+ static inline bool AdvanceToNonspace(Iterator* current, Iterator end) {
471
+ while (*current != end) {
472
+ if (!isWhitespace(**current)) return true;
473
+ ++*current;
474
+ }
475
+ return false;
476
+ }
477
+
478
+
479
+ static bool isDigit(int x, int radix) {
480
+ return (x >= '0' && x <= '9' && x < '0' + radix)
481
+ || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
482
+ || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
483
+ }
484
+
485
+
486
+ static double SignedZero(bool sign) {
487
+ return sign ? -0.0 : 0.0;
488
+ }
489
+
490
+
491
+ // Returns true if 'c' is a decimal digit that is valid for the given radix.
492
+ //
493
+ // The function is small and could be inlined, but VS2012 emitted a warning
494
+ // because it constant-propagated the radix and concluded that the last
495
+ // condition was always true. By moving it into a separate function the
496
+ // compiler wouldn't warn anymore.
497
+ #if _MSC_VER
498
+ #pragma optimize("",off)
499
+ static bool IsDecimalDigitForRadix(int c, int radix) {
500
+ return '0' <= c && c <= '9' && (c - '0') < radix;
501
+ }
502
+ #pragma optimize("",on)
503
+ #else
504
+ static bool inline IsDecimalDigitForRadix(int c, int radix) {
505
+ return '0' <= c && c <= '9' && (c - '0') < radix;
506
+ }
507
+ #endif
508
+ // Returns true if 'c' is a character digit that is valid for the given radix.
509
+ // The 'a_character' should be 'a' or 'A'.
510
+ //
511
+ // The function is small and could be inlined, but VS2012 emitted a warning
512
+ // because it constant-propagated the radix and concluded that the first
513
+ // condition was always false. By moving it into a separate function the
514
+ // compiler wouldn't warn anymore.
515
+ static bool IsCharacterDigitForRadix(int c, int radix, char a_character) {
516
+ return radix > 10 && c >= a_character && c < a_character + radix - 10;
517
+ }
518
+
519
+
520
+ // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
521
+ template <int radix_log_2, class Iterator>
522
+ static double RadixStringToIeee(Iterator* current,
523
+ Iterator end,
524
+ bool sign,
525
+ bool allow_trailing_junk,
526
+ double junk_string_value,
527
+ bool read_as_double,
528
+ bool* result_is_junk) {
529
+ ASSERT(*current != end);
530
+
531
+ const int kDoubleSize = Double::kSignificandSize;
532
+ const int kSingleSize = Single::kSignificandSize;
533
+ const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;
534
+
535
+ *result_is_junk = true;
536
+
537
+ // Skip leading 0s.
538
+ while (**current == '0') {
539
+ ++(*current);
540
+ if (*current == end) {
541
+ *result_is_junk = false;
542
+ return SignedZero(sign);
543
+ }
544
+ }
545
+
546
+ int64_t number = 0;
547
+ int exponent = 0;
548
+ const int radix = (1 << radix_log_2);
549
+
550
+ do {
551
+ int digit;
552
+ if (IsDecimalDigitForRadix(**current, radix)) {
553
+ digit = static_cast<char>(**current) - '0';
554
+ } else if (IsCharacterDigitForRadix(**current, radix, 'a')) {
555
+ digit = static_cast<char>(**current) - 'a' + 10;
556
+ } else if (IsCharacterDigitForRadix(**current, radix, 'A')) {
557
+ digit = static_cast<char>(**current) - 'A' + 10;
558
+ } else {
559
+ if (allow_trailing_junk || !AdvanceToNonspace(current, end)) {
560
+ break;
561
+ } else {
562
+ return junk_string_value;
563
+ }
564
+ }
565
+
566
+ number = number * radix + digit;
567
+ int overflow = static_cast<int>(number >> kSignificandSize);
568
+ if (overflow != 0) {
569
+ // Overflow occurred. Need to determine which direction to round the
570
+ // result.
571
+ int overflow_bits_count = 1;
572
+ while (overflow > 1) {
573
+ overflow_bits_count++;
574
+ overflow >>= 1;
575
+ }
576
+
577
+ int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
578
+ int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
579
+ number >>= overflow_bits_count;
580
+ exponent = overflow_bits_count;
581
+
582
+ bool zero_tail = true;
583
+ for (;;) {
584
+ ++(*current);
585
+ if (*current == end || !isDigit(**current, radix)) break;
586
+ zero_tail = zero_tail && **current == '0';
587
+ exponent += radix_log_2;
588
+ }
589
+
590
+ if (!allow_trailing_junk && AdvanceToNonspace(current, end)) {
591
+ return junk_string_value;
592
+ }
593
+
594
+ int middle_value = (1 << (overflow_bits_count - 1));
595
+ if (dropped_bits > middle_value) {
596
+ number++; // Rounding up.
597
+ } else if (dropped_bits == middle_value) {
598
+ // Rounding to even to consistency with decimals: half-way case rounds
599
+ // up if significant part is odd and down otherwise.
600
+ if ((number & 1) != 0 || !zero_tail) {
601
+ number++; // Rounding up.
602
+ }
603
+ }
604
+
605
+ // Rounding up may cause overflow.
606
+ if ((number & ((int64_t)1 << kSignificandSize)) != 0) {
607
+ exponent++;
608
+ number >>= 1;
609
+ }
610
+ break;
611
+ }
612
+ ++(*current);
613
+ } while (*current != end);
614
+
615
+ ASSERT(number < ((int64_t)1 << kSignificandSize));
616
+ ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
617
+
618
+ *result_is_junk = false;
619
+
620
+ if (exponent == 0) {
621
+ if (sign) {
622
+ if (number == 0) return -0.0;
623
+ number = -number;
624
+ }
625
+ return static_cast<double>(number);
626
+ }
627
+
628
+ ASSERT(number != 0);
629
+ return Double(DiyFp(number, exponent)).value();
630
+ }
631
+
632
+
633
+ template <class Iterator>
634
+ double StringToDoubleConverter::StringToIeee(
635
+ Iterator input,
636
+ int length,
637
+ bool read_as_double,
638
+ int* processed_characters_count) const {
639
+ Iterator current = input;
640
+ Iterator end = input + length;
641
+
642
+ *processed_characters_count = 0;
643
+
644
+ const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0;
645
+ const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;
646
+ const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;
647
+ const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
648
+
649
+ // To make sure that iterator dereferencing is valid the following
650
+ // convention is used:
651
+ // 1. Each '++current' statement is followed by check for equality to 'end'.
652
+ // 2. If AdvanceToNonspace returned false then current == end.
653
+ // 3. If 'current' becomes equal to 'end' the function returns or goes to
654
+ // 'parsing_done'.
655
+ // 4. 'current' is not dereferenced after the 'parsing_done' label.
656
+ // 5. Code before 'parsing_done' may rely on 'current != end'.
657
+ if (current == end) return empty_string_value_;
658
+
659
+ if (allow_leading_spaces || allow_trailing_spaces) {
660
+ if (!AdvanceToNonspace(&current, end)) {
661
+ *processed_characters_count = static_cast<int>(current - input);
662
+ return empty_string_value_;
663
+ }
664
+ if (!allow_leading_spaces && (input != current)) {
665
+ // No leading spaces allowed, but AdvanceToNonspace moved forward.
666
+ return junk_string_value_;
667
+ }
668
+ }
669
+
670
+ // The longest form of simplified number is: "-<significant digits>.1eXXX\0".
671
+ const int kBufferSize = kMaxSignificantDigits + 10;
672
+ char buffer[kBufferSize]; // NOLINT: size is known at compile time.
673
+ int buffer_pos = 0;
674
+
675
+ // Exponent will be adjusted if insignificant digits of the integer part
676
+ // or insignificant leading zeros of the fractional part are dropped.
677
+ int exponent = 0;
678
+ int significant_digits = 0;
679
+ int insignificant_digits = 0;
680
+ bool nonzero_digit_dropped = false;
681
+
682
+ bool sign = false;
683
+
684
+ if (*current == '+' || *current == '-') {
685
+ sign = (*current == '-');
686
+ ++current;
687
+ Iterator next_non_space = current;
688
+ // Skip following spaces (if allowed).
689
+ if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;
690
+ if (!allow_spaces_after_sign && (current != next_non_space)) {
691
+ return junk_string_value_;
692
+ }
693
+ current = next_non_space;
694
+ }
695
+
696
+ if (infinity_symbol_ != NULL) {
697
+ if (*current == infinity_symbol_[0]) {
698
+ if (!ConsumeSubString(&current, end, infinity_symbol_)) {
699
+ return junk_string_value_;
700
+ }
701
+
702
+ if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
703
+ return junk_string_value_;
704
+ }
705
+ if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
706
+ return junk_string_value_;
707
+ }
708
+
709
+ ASSERT(buffer_pos == 0);
710
+ *processed_characters_count = static_cast<int>(current - input);
711
+ return sign ? -Double::Infinity() : Double::Infinity();
712
+ }
713
+ }
714
+
715
+ if (nan_symbol_ != NULL) {
716
+ if (*current == nan_symbol_[0]) {
717
+ if (!ConsumeSubString(&current, end, nan_symbol_)) {
718
+ return junk_string_value_;
719
+ }
720
+
721
+ if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
722
+ return junk_string_value_;
723
+ }
724
+ if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
725
+ return junk_string_value_;
726
+ }
727
+
728
+ ASSERT(buffer_pos == 0);
729
+ *processed_characters_count = static_cast<int>(current - input);
730
+ return sign ? -Double::NaN() : Double::NaN();
731
+ }
732
+ }
733
+
734
+ bool leading_zero = false;
735
+ if (*current == '0') {
736
+ ++current;
737
+ if (current == end) {
738
+ *processed_characters_count = static_cast<int>(current - input);
739
+ return SignedZero(sign);
740
+ }
741
+
742
+ leading_zero = true;
743
+
744
+ // It could be hexadecimal value.
745
+ if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
746
+ ++current;
747
+ if (current == end || !isDigit(*current, 16)) {
748
+ return junk_string_value_; // "0x".
749
+ }
750
+
751
+ bool result_is_junk;
752
+ double result = RadixStringToIeee<4>(&current,
753
+ end,
754
+ sign,
755
+ allow_trailing_junk,
756
+ junk_string_value_,
757
+ read_as_double,
758
+ &result_is_junk);
759
+ if (!result_is_junk) {
760
+ if (allow_trailing_spaces) AdvanceToNonspace(&current, end);
761
+ *processed_characters_count = static_cast<int>(current - input);
762
+ }
763
+ return result;
764
+ }
765
+
766
+ // Ignore leading zeros in the integer part.
767
+ while (*current == '0') {
768
+ ++current;
769
+ if (current == end) {
770
+ *processed_characters_count = static_cast<int>(current - input);
771
+ return SignedZero(sign);
772
+ }
773
+ }
774
+ }
775
+
776
+ bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0;
777
+
778
+ // Copy significant digits of the integer part (if any) to the buffer.
779
+ while (*current >= '0' && *current <= '9') {
780
+ if (significant_digits < kMaxSignificantDigits) {
781
+ ASSERT(buffer_pos < kBufferSize);
782
+ buffer[buffer_pos++] = static_cast<char>(*current);
783
+ significant_digits++;
784
+ // Will later check if it's an octal in the buffer.
785
+ } else {
786
+ insignificant_digits++; // Move the digit into the exponential part.
787
+ nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
788
+ }
789
+ octal = octal && *current < '8';
790
+ ++current;
791
+ if (current == end) goto parsing_done;
792
+ }
793
+
794
+ if (significant_digits == 0) {
795
+ octal = false;
796
+ }
797
+
798
+ if (*current == '.') {
799
+ if (octal && !allow_trailing_junk) return junk_string_value_;
800
+ if (octal) goto parsing_done;
801
+
802
+ ++current;
803
+ if (current == end) {
804
+ if (significant_digits == 0 && !leading_zero) {
805
+ return junk_string_value_;
806
+ } else {
807
+ goto parsing_done;
808
+ }
809
+ }
810
+
811
+ if (significant_digits == 0) {
812
+ // octal = false;
813
+ // Integer part consists of 0 or is absent. Significant digits start after
814
+ // leading zeros (if any).
815
+ while (*current == '0') {
816
+ ++current;
817
+ if (current == end) {
818
+ *processed_characters_count = static_cast<int>(current - input);
819
+ return SignedZero(sign);
820
+ }
821
+ exponent--; // Move this 0 into the exponent.
822
+ }
823
+ }
824
+
825
+ // There is a fractional part.
826
+ // We don't emit a '.', but adjust the exponent instead.
827
+ while (*current >= '0' && *current <= '9') {
828
+ if (significant_digits < kMaxSignificantDigits) {
829
+ ASSERT(buffer_pos < kBufferSize);
830
+ buffer[buffer_pos++] = static_cast<char>(*current);
831
+ significant_digits++;
832
+ exponent--;
833
+ } else {
834
+ // Ignore insignificant digits in the fractional part.
835
+ nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
836
+ }
837
+ ++current;
838
+ if (current == end) goto parsing_done;
839
+ }
840
+ }
841
+
842
+ if (!leading_zero && exponent == 0 && significant_digits == 0) {
843
+ // If leading_zeros is true then the string contains zeros.
844
+ // If exponent < 0 then string was [+-]\.0*...
845
+ // If significant_digits != 0 the string is not equal to 0.
846
+ // Otherwise there are no digits in the string.
847
+ return junk_string_value_;
848
+ }
849
+
850
+ // Parse exponential part.
851
+ if (*current == 'e' || *current == 'E') {
852
+ if (octal && !allow_trailing_junk) return junk_string_value_;
853
+ if (octal) goto parsing_done;
854
+ ++current;
855
+ if (current == end) {
856
+ if (allow_trailing_junk) {
857
+ goto parsing_done;
858
+ } else {
859
+ return junk_string_value_;
860
+ }
861
+ }
862
+ char exponen_sign = '+';
863
+ if (*current == '+' || *current == '-') {
864
+ exponen_sign = static_cast<char>(*current);
865
+ ++current;
866
+ if (current == end) {
867
+ if (allow_trailing_junk) {
868
+ goto parsing_done;
869
+ } else {
870
+ return junk_string_value_;
871
+ }
872
+ }
873
+ }
874
+
875
+ if (current == end || *current < '0' || *current > '9') {
876
+ if (allow_trailing_junk) {
877
+ goto parsing_done;
878
+ } else {
879
+ return junk_string_value_;
880
+ }
881
+ }
882
+
883
+ const int max_exponent = INT_MAX / 2;
884
+ ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
885
+ int num = 0;
886
+ do {
887
+ // Check overflow.
888
+ int digit = *current - '0';
889
+ if (num >= max_exponent / 10
890
+ && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
891
+ num = max_exponent;
892
+ } else {
893
+ num = num * 10 + digit;
894
+ }
895
+ ++current;
896
+ } while (current != end && *current >= '0' && *current <= '9');
897
+
898
+ exponent += (exponen_sign == '-' ? -num : num);
899
+ }
900
+
901
+ if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
902
+ return junk_string_value_;
903
+ }
904
+ if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
905
+ return junk_string_value_;
906
+ }
907
+ if (allow_trailing_spaces) {
908
+ AdvanceToNonspace(&current, end);
909
+ }
910
+
911
+ parsing_done:
912
+ exponent += insignificant_digits;
913
+
914
+ if (octal) {
915
+ double result;
916
+ bool result_is_junk;
917
+ char* start = buffer;
918
+ result = RadixStringToIeee<3>(&start,
919
+ buffer + buffer_pos,
920
+ sign,
921
+ allow_trailing_junk,
922
+ junk_string_value_,
923
+ read_as_double,
924
+ &result_is_junk);
925
+ ASSERT(!result_is_junk);
926
+ *processed_characters_count = static_cast<int>(current - input);
927
+ return result;
928
+ }
929
+
930
+ if (nonzero_digit_dropped) {
931
+ buffer[buffer_pos++] = '1';
932
+ exponent--;
933
+ }
934
+
935
+ ASSERT(buffer_pos < kBufferSize);
936
+ buffer[buffer_pos] = '\0';
937
+
938
+ double converted;
939
+ if (read_as_double) {
940
+ converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
941
+ } else {
942
+ converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent);
943
+ }
944
+ *processed_characters_count = static_cast<int>(current - input);
945
+ return sign? -converted: converted;
946
+ }
947
+
948
+
949
+ double StringToDoubleConverter::StringToDouble(
950
+ const char* buffer,
951
+ int length,
952
+ int* processed_characters_count) const {
953
+ return StringToIeee(buffer, length, true, processed_characters_count);
954
+ }
955
+
956
+
957
+ double StringToDoubleConverter::StringToDouble(
958
+ const uc16* buffer,
959
+ int length,
960
+ int* processed_characters_count) const {
961
+ return StringToIeee(buffer, length, true, processed_characters_count);
962
+ }
963
+
964
+
965
+ float StringToDoubleConverter::StringToFloat(
966
+ const char* buffer,
967
+ int length,
968
+ int* processed_characters_count) const {
969
+ return static_cast<float>(StringToIeee(buffer, length, false,
970
+ processed_characters_count));
971
+ }
972
+
973
+
974
+ float StringToDoubleConverter::StringToFloat(
975
+ const uc16* buffer,
976
+ int length,
977
+ int* processed_characters_count) const {
978
+ return static_cast<float>(StringToIeee(buffer, length, false,
979
+ processed_characters_count));
980
+ }
981
+
982
+ } // namespace double_conversion