| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "wtf/text/StringToNumber.h" |
| 6 |
| 7 #include "wtf/ASCIICType.h" |
| 8 #include "wtf/dtoa.h" |
| 9 #include "wtf/text/StringImpl.h" |
| 10 |
| 11 namespace WTF { |
| 12 |
| 13 static bool isCharacterAllowedInBase(UChar c, int base) |
| 14 { |
| 15 if (c > 0x7F) |
| 16 return false; |
| 17 if (isASCIIDigit(c)) |
| 18 return c - '0' < base; |
| 19 if (isASCIIAlpha(c)) { |
| 20 if (base > 36) |
| 21 base = 36; |
| 22 return (c >= 'a' && c < 'a' + base - 10) |
| 23 || (c >= 'A' && c < 'A' + base - 10); |
| 24 } |
| 25 return false; |
| 26 } |
| 27 |
| 28 template <typename IntegralType, typename CharType> |
| 29 static inline IntegralType toIntegralType(const CharType* data, size_t length, b
ool* ok, int base) |
| 30 { |
| 31 static const IntegralType integralMax = std::numeric_limits<IntegralType>::m
ax(); |
| 32 static const bool isSigned = std::numeric_limits<IntegralType>::is_signed; |
| 33 const IntegralType maxMultiplier = integralMax / base; |
| 34 |
| 35 IntegralType value = 0; |
| 36 bool isOk = false; |
| 37 bool isNegative = false; |
| 38 |
| 39 if (!data) |
| 40 goto bye; |
| 41 |
| 42 // skip leading whitespace |
| 43 while (length && isSpaceOrNewline(*data)) { |
| 44 --length; |
| 45 ++data; |
| 46 } |
| 47 |
| 48 if (isSigned && length && *data == '-') { |
| 49 --length; |
| 50 ++data; |
| 51 isNegative = true; |
| 52 } else if (length && *data == '+') { |
| 53 --length; |
| 54 ++data; |
| 55 } |
| 56 |
| 57 if (!length || !isCharacterAllowedInBase(*data, base)) |
| 58 goto bye; |
| 59 |
| 60 while (length && isCharacterAllowedInBase(*data, base)) { |
| 61 --length; |
| 62 IntegralType digitValue; |
| 63 CharType c = *data; |
| 64 if (isASCIIDigit(c)) |
| 65 digitValue = c - '0'; |
| 66 else if (c >= 'a') |
| 67 digitValue = c - 'a' + 10; |
| 68 else |
| 69 digitValue = c - 'A' + 10; |
| 70 |
| 71 if (value > maxMultiplier || (value == maxMultiplier && digitValue > (in
tegralMax % base) + isNegative)) |
| 72 goto bye; |
| 73 |
| 74 value = base * value + digitValue; |
| 75 ++data; |
| 76 } |
| 77 |
| 78 #if COMPILER(MSVC) |
| 79 #pragma warning(push, 0) |
| 80 #pragma warning(disable:4146) |
| 81 #endif |
| 82 |
| 83 if (isNegative) |
| 84 value = -value; |
| 85 |
| 86 #if COMPILER(MSVC) |
| 87 #pragma warning(pop) |
| 88 #endif |
| 89 |
| 90 // skip trailing space |
| 91 while (length && isSpaceOrNewline(*data)) { |
| 92 --length; |
| 93 ++data; |
| 94 } |
| 95 |
| 96 if (!length) |
| 97 isOk = true; |
| 98 bye: |
| 99 if (ok) |
| 100 *ok = isOk; |
| 101 return isOk ? value : 0; |
| 102 } |
| 103 |
| 104 template <typename CharType> |
| 105 static unsigned lengthOfCharactersAsInteger(const CharType* data, size_t length) |
| 106 { |
| 107 size_t i = 0; |
| 108 |
| 109 // Allow leading spaces. |
| 110 for (; i != length; ++i) { |
| 111 if (!isSpaceOrNewline(data[i])) |
| 112 break; |
| 113 } |
| 114 |
| 115 // Allow sign. |
| 116 if (i != length && (data[i] == '+' || data[i] == '-')) |
| 117 ++i; |
| 118 |
| 119 // Allow digits. |
| 120 for (; i != length; ++i) { |
| 121 if (!isASCIIDigit(data[i])) |
| 122 break; |
| 123 } |
| 124 |
| 125 return i; |
| 126 } |
| 127 |
| 128 int charactersToIntStrict(const LChar* data, size_t length, bool* ok, int base) |
| 129 { |
| 130 return toIntegralType<int, LChar>(data, length, ok, base); |
| 131 } |
| 132 |
| 133 int charactersToIntStrict(const UChar* data, size_t length, bool* ok, int base) |
| 134 { |
| 135 return toIntegralType<int, UChar>(data, length, ok, base); |
| 136 } |
| 137 |
| 138 unsigned charactersToUIntStrict(const LChar* data, size_t length, bool* ok, int
base) |
| 139 { |
| 140 return toIntegralType<unsigned, LChar>(data, length, ok, base); |
| 141 } |
| 142 |
| 143 unsigned charactersToUIntStrict(const UChar* data, size_t length, bool* ok, int
base) |
| 144 { |
| 145 return toIntegralType<unsigned, UChar>(data, length, ok, base); |
| 146 } |
| 147 |
| 148 int64_t charactersToInt64Strict(const LChar* data, size_t length, bool* ok, int
base) |
| 149 { |
| 150 return toIntegralType<int64_t, LChar>(data, length, ok, base); |
| 151 } |
| 152 |
| 153 int64_t charactersToInt64Strict(const UChar* data, size_t length, bool* ok, int
base) |
| 154 { |
| 155 return toIntegralType<int64_t, UChar>(data, length, ok, base); |
| 156 } |
| 157 |
| 158 uint64_t charactersToUInt64Strict(const LChar* data, size_t length, bool* ok, in
t base) |
| 159 { |
| 160 return toIntegralType<uint64_t, LChar>(data, length, ok, base); |
| 161 } |
| 162 |
| 163 uint64_t charactersToUInt64Strict(const UChar* data, size_t length, bool* ok, in
t base) |
| 164 { |
| 165 return toIntegralType<uint64_t, UChar>(data, length, ok, base); |
| 166 } |
| 167 |
| 168 int charactersToInt(const LChar* data, size_t length, bool* ok) |
| 169 { |
| 170 return toIntegralType<int, LChar>(data, lengthOfCharactersAsInteger<LChar>(d
ata, length), ok, 10); |
| 171 } |
| 172 |
| 173 int charactersToInt(const UChar* data, size_t length, bool* ok) |
| 174 { |
| 175 return toIntegralType<int, UChar>(data, lengthOfCharactersAsInteger(data, le
ngth), ok, 10); |
| 176 } |
| 177 |
| 178 unsigned charactersToUInt(const LChar* data, size_t length, bool* ok) |
| 179 { |
| 180 return toIntegralType<unsigned, LChar>(data, lengthOfCharactersAsInteger<LCh
ar>(data, length), ok, 10); |
| 181 } |
| 182 |
| 183 unsigned charactersToUInt(const UChar* data, size_t length, bool* ok) |
| 184 { |
| 185 return toIntegralType<unsigned, UChar>(data, lengthOfCharactersAsInteger<UCh
ar>(data, length), ok, 10); |
| 186 } |
| 187 |
| 188 int64_t charactersToInt64(const LChar* data, size_t length, bool* ok) |
| 189 { |
| 190 return toIntegralType<int64_t, LChar>(data, lengthOfCharactersAsInteger<LCha
r>(data, length), ok, 10); |
| 191 } |
| 192 |
| 193 int64_t charactersToInt64(const UChar* data, size_t length, bool* ok) |
| 194 { |
| 195 return toIntegralType<int64_t, UChar>(data, lengthOfCharactersAsInteger<UCha
r>(data, length), ok, 10); |
| 196 } |
| 197 |
| 198 uint64_t charactersToUInt64(const LChar* data, size_t length, bool* ok) |
| 199 { |
| 200 return toIntegralType<uint64_t, LChar>(data, lengthOfCharactersAsInteger<LCh
ar>(data, length), ok, 10); |
| 201 } |
| 202 |
| 203 uint64_t charactersToUInt64(const UChar* data, size_t length, bool* ok) |
| 204 { |
| 205 return toIntegralType<uint64_t, UChar>(data, lengthOfCharactersAsInteger<UCh
ar>(data, length), ok, 10); |
| 206 } |
| 207 |
| 208 enum TrailingJunkPolicy { DisallowTrailingJunk, AllowTrailingJunk }; |
| 209 |
| 210 template <typename CharType, TrailingJunkPolicy policy> |
| 211 static inline double toDoubleType(const CharType* data, size_t length, bool* ok,
size_t& parsedLength) |
| 212 { |
| 213 size_t leadingSpacesLength = 0; |
| 214 while (leadingSpacesLength < length && isASCIISpace(data[leadingSpacesLength
])) |
| 215 ++leadingSpacesLength; |
| 216 |
| 217 double number = parseDouble(data + leadingSpacesLength, length - leadingSpac
esLength, parsedLength); |
| 218 if (!parsedLength) { |
| 219 if (ok) |
| 220 *ok = false; |
| 221 return 0.0; |
| 222 } |
| 223 |
| 224 parsedLength += leadingSpacesLength; |
| 225 if (ok) |
| 226 *ok = policy == AllowTrailingJunk || parsedLength == length; |
| 227 return number; |
| 228 } |
| 229 |
| 230 double charactersToDouble(const LChar* data, size_t length, bool* ok) |
| 231 { |
| 232 size_t parsedLength; |
| 233 return toDoubleType<LChar, DisallowTrailingJunk>(data, length, ok, parsedLen
gth); |
| 234 } |
| 235 |
| 236 double charactersToDouble(const UChar* data, size_t length, bool* ok) |
| 237 { |
| 238 size_t parsedLength; |
| 239 return toDoubleType<UChar, DisallowTrailingJunk>(data, length, ok, parsedLen
gth); |
| 240 } |
| 241 |
| 242 double charactersToDouble(const LChar* data, size_t length, size_t& parsedLength
) |
| 243 { |
| 244 return toDoubleType<LChar, AllowTrailingJunk>(data, length, nullptr, parsedL
ength); |
| 245 } |
| 246 |
| 247 double charactersToDouble(const UChar* data, size_t length, size_t& parsedLength
) |
| 248 { |
| 249 return toDoubleType<UChar, AllowTrailingJunk>(data, length, nullptr, parsedL
ength); |
| 250 } |
| 251 |
| 252 float charactersToFloat(const LChar* data, size_t length, bool* ok) |
| 253 { |
| 254 // FIXME: This will return ok even when the string fits into a double but |
| 255 // not a float. |
| 256 size_t parsedLength; |
| 257 return static_cast<float>(toDoubleType<LChar, DisallowTrailingJunk>(data, le
ngth, ok, parsedLength)); |
| 258 } |
| 259 |
| 260 float charactersToFloat(const UChar* data, size_t length, bool* ok) |
| 261 { |
| 262 // FIXME: This will return ok even when the string fits into a double but |
| 263 // not a float. |
| 264 size_t parsedLength; |
| 265 return static_cast<float>(toDoubleType<UChar, DisallowTrailingJunk>(data, le
ngth, ok, parsedLength)); |
| 266 } |
| 267 |
| 268 float charactersToFloat(const LChar* data, size_t length, size_t& parsedLength) |
| 269 { |
| 270 // FIXME: This will return ok even when the string fits into a double but |
| 271 // not a float. |
| 272 return static_cast<float>(toDoubleType<LChar, AllowTrailingJunk>(data, lengt
h, 0, parsedLength)); |
| 273 } |
| 274 |
| 275 float charactersToFloat(const UChar* data, size_t length, size_t& parsedLength) |
| 276 { |
| 277 // FIXME: This will return ok even when the string fits into a double but |
| 278 // not a float. |
| 279 return static_cast<float>(toDoubleType<UChar, AllowTrailingJunk>(data, lengt
h, 0, parsedLength)); |
| 280 } |
| 281 |
| 282 } // namespace WTF |
| OLD | NEW |