| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "wtf/text/StringToNumber.h" | 5 #include "wtf/text/StringToNumber.h" |
| 6 | 6 |
| 7 #include "wtf/ASCIICType.h" | 7 #include "wtf/ASCIICType.h" |
| 8 #include "wtf/dtoa.h" | 8 #include "wtf/dtoa.h" |
| 9 #include "wtf/text/StringImpl.h" | 9 #include "wtf/text/StringImpl.h" |
| 10 #include <type_traits> |
| 10 | 11 |
| 11 namespace WTF { | 12 namespace WTF { |
| 12 | 13 |
| 13 static bool isCharacterAllowedInBase(UChar c, int base) { | 14 static bool isCharacterAllowedInBase(UChar c, int base) { |
| 14 if (c > 0x7F) | 15 if (c > 0x7F) |
| 15 return false; | 16 return false; |
| 16 if (isASCIIDigit(c)) | 17 if (isASCIIDigit(c)) |
| 17 return c - '0' < base; | 18 return c - '0' < base; |
| 18 if (isASCIIAlpha(c)) { | 19 if (isASCIIAlpha(c)) { |
| 19 if (base > 36) | 20 if (base > 36) |
| 20 base = 36; | 21 base = 36; |
| 21 return (c >= 'a' && c < 'a' + base - 10) || | 22 return (c >= 'a' && c < 'a' + base - 10) || |
| 22 (c >= 'A' && c < 'A' + base - 10); | 23 (c >= 'A' && c < 'A' + base - 10); |
| 23 } | 24 } |
| 24 return false; | 25 return false; |
| 25 } | 26 } |
| 26 | 27 |
| 27 template <typename IntegralType, typename CharType> | 28 template <typename IntegralType, typename CharType> |
| 28 static inline IntegralType toIntegralType(const CharType* data, | 29 static inline IntegralType toIntegralType(const CharType* data, |
| 29 size_t length, | 30 size_t length, |
| 30 bool* ok, | 31 bool* ok, |
| 31 int base) { | 32 int base) { |
| 32 static const IntegralType integralMax = | 33 static_assert(std::is_integral<IntegralType>::value, |
| 34 "IntegralType must be an integral type."); |
| 35 static constexpr IntegralType integralMax = |
| 33 std::numeric_limits<IntegralType>::max(); | 36 std::numeric_limits<IntegralType>::max(); |
| 34 static const bool isSigned = std::numeric_limits<IntegralType>::is_signed; | 37 static constexpr IntegralType integralMin = |
| 35 const IntegralType maxMultiplier = integralMax / base; | 38 std::numeric_limits<IntegralType>::min(); |
| 39 static constexpr bool isSigned = std::numeric_limits<IntegralType>::is_signed; |
| 36 | 40 |
| 37 IntegralType value = 0; | 41 IntegralType value = 0; |
| 38 bool isOk = false; | 42 bool isOk = false; |
| 39 bool isNegative = false; | 43 bool isNegative = false; |
| 40 | 44 |
| 41 if (!data) | 45 if (!data) |
| 42 goto bye; | 46 goto bye; |
| 43 | 47 |
| 44 // skip leading whitespace | 48 // skip leading whitespace |
| 45 while (length && isSpaceOrNewline(*data)) { | 49 while (length && isSpaceOrNewline(*data)) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 63 --length; | 67 --length; |
| 64 IntegralType digitValue; | 68 IntegralType digitValue; |
| 65 CharType c = *data; | 69 CharType c = *data; |
| 66 if (isASCIIDigit(c)) | 70 if (isASCIIDigit(c)) |
| 67 digitValue = c - '0'; | 71 digitValue = c - '0'; |
| 68 else if (c >= 'a') | 72 else if (c >= 'a') |
| 69 digitValue = c - 'a' + 10; | 73 digitValue = c - 'a' + 10; |
| 70 else | 74 else |
| 71 digitValue = c - 'A' + 10; | 75 digitValue = c - 'A' + 10; |
| 72 | 76 |
| 73 if (value > maxMultiplier || | 77 bool overflow; |
| 74 (value == maxMultiplier && | 78 if (isNegative) { |
| 75 digitValue > (integralMax % base) + isNegative)) | 79 // Overflow condition: |
| 80 // value * base - digitValue < integralMin |
| 81 // <=> value < (integralMin + digitValue) / base |
| 82 // We must be careful of rounding errors here, but the default rounding |
| 83 // mode (round to zero) works well, so we can use this formula as-is. |
| 84 overflow = value < (integralMin + digitValue) / base; |
| 85 } else { |
| 86 // Overflow condition: |
| 87 // value * base + digitValue > integralMax |
| 88 // <=> value > (integralMax + digitValue) / base |
| 89 // Ditto regarding rounding errors. |
| 90 overflow = value > (integralMax - digitValue) / base; |
| 91 } |
| 92 if (overflow) |
| 76 goto bye; | 93 goto bye; |
| 77 | 94 |
| 78 value = base * value + digitValue; | 95 if (isNegative) |
| 96 value = base * value - digitValue; |
| 97 else |
| 98 value = base * value + digitValue; |
| 79 ++data; | 99 ++data; |
| 80 } | 100 } |
| 81 | 101 |
| 82 #if COMPILER(MSVC) | |
| 83 #pragma warning(push, 0) | |
| 84 #pragma warning(disable : 4146) | |
| 85 #endif | |
| 86 | |
| 87 if (isNegative) | |
| 88 value = -value; | |
| 89 | |
| 90 #if COMPILER(MSVC) | |
| 91 #pragma warning(pop) | |
| 92 #endif | |
| 93 | |
| 94 // skip trailing space | 102 // skip trailing space |
| 95 while (length && isSpaceOrNewline(*data)) { | 103 while (length && isSpaceOrNewline(*data)) { |
| 96 --length; | 104 --length; |
| 97 ++data; | 105 ++data; |
| 98 } | 106 } |
| 99 | 107 |
| 100 if (!length) | 108 if (!length) |
| 101 isOk = true; | 109 isOk = true; |
| 102 bye: | 110 bye: |
| 103 if (ok) | 111 if (ok) |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 float charactersToFloat(const UChar* data, | 313 float charactersToFloat(const UChar* data, |
| 306 size_t length, | 314 size_t length, |
| 307 size_t& parsedLength) { | 315 size_t& parsedLength) { |
| 308 // FIXME: This will return ok even when the string fits into a double but | 316 // FIXME: This will return ok even when the string fits into a double but |
| 309 // not a float. | 317 // not a float. |
| 310 return static_cast<float>( | 318 return static_cast<float>( |
| 311 toDoubleType<UChar, AllowTrailingJunk>(data, length, 0, parsedLength)); | 319 toDoubleType<UChar, AllowTrailingJunk>(data, length, 0, parsedLength)); |
| 312 } | 320 } |
| 313 | 321 |
| 314 } // namespace WTF | 322 } // namespace WTF |
| OLD | NEW |