Changeset 65588 in webkit for trunk/JavaScriptCore/runtime/UString.cpp
- Timestamp:
- Aug 18, 2010, 12:41:22 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/UString.cpp
r65478 r65588 205 205 } 206 206 207 static inline bool isInfinity(double number)208 {209 return number == Inf || number == -Inf;210 }211 212 static bool isInfinity(const UChar* data, const UChar* end)213 {214 return data + 7 < end215 && data[0] == 'I'216 && data[1] == 'n'217 && data[2] == 'f'218 && data[3] == 'i'219 && data[4] == 'n'220 && data[5] == 'i'221 && data[6] == 't'222 && data[7] == 'y';223 }224 225 double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const226 {227 unsigned size = this->length();228 229 if (size == 1) {230 UChar c = characters()[0];231 if (isASCIIDigit(c))232 return c - '0';233 if (isStrWhiteSpace(c) && tolerateEmptyString)234 return 0;235 return NaN;236 }237 238 const UChar* data = this->characters();239 const UChar* end = data + size;240 241 // Skip leading white space.242 for (; data < end; ++data) {243 if (!isStrWhiteSpace(*data))244 break;245 }246 247 // Empty string.248 if (data == end)249 return tolerateEmptyString ? 0.0 : NaN;250 251 double number;252 253 if (data[0] == '0' && data + 2 < end && (data[1] | 0x20) == 'x' && isASCIIHexDigit(data[2])) {254 // Hex number.255 data += 2;256 const UChar* firstDigitPosition = data;257 number = 0;258 while (true) {259 number = number * 16 + toASCIIHexValue(*data);260 ++data;261 if (data == end)262 break;263 if (!isASCIIHexDigit(*data))264 break;265 }266 if (number >= mantissaOverflowLowerBound)267 number = parseIntOverflow(firstDigitPosition, data - firstDigitPosition, 16);268 } else {269 // Decimal number.270 271 // Put into a null-terminated byte buffer.272 Vector<char, 32> byteBuffer;273 for (const UChar* characters = data; characters < end; ++characters) {274 UChar character = *characters;275 byteBuffer.append(isASCII(character) ? character : 0);276 }277 byteBuffer.append(0);278 279 char* byteBufferEnd;280 number = WTF::strtod(byteBuffer.data(), &byteBufferEnd);281 const UChar* pastNumber = data + (byteBufferEnd - byteBuffer.data());282 283 if ((number || pastNumber != data) && !isInfinity(number))284 data = pastNumber;285 else {286 // We used strtod() to do the conversion. However, strtod() handles287 // infinite values slightly differently than JavaScript in that it288 // converts the string "inf" with any capitalization to infinity,289 // whereas the ECMA spec requires that it be converted to NaN.290 291 double signedInfinity = Inf;292 if (data < end) {293 if (*data == '+')294 data++;295 else if (*data == '-') {296 signedInfinity = -Inf;297 data++;298 }299 }300 if (isInfinity(data, end)) {301 number = signedInfinity;302 data += 8;303 } else if (isInfinity(number) && data < end && (*data | 0x20) != 'i')304 data = pastNumber;305 else306 return NaN;307 }308 }309 310 // Look for trailing junk.311 if (!tolerateTrailingJunk) {312 // Allow trailing white space.313 for (; data < end; ++data) {314 if (!isStrWhiteSpace(*data))315 break;316 }317 if (data != end)318 return NaN;319 }320 321 return number;322 }323 324 double UString::toDouble(bool tolerateTrailingJunk) const325 {326 return toDouble(tolerateTrailingJunk, true);327 }328 329 double UString::toDouble() const330 {331 return toDouble(false, true);332 }333 334 uint32_t UString::toUInt32(bool* ok) const335 {336 double d = toDouble();337 bool b = true;338 339 if (d != static_cast<uint32_t>(d)) {340 b = false;341 d = 0;342 }343 344 if (ok)345 *ok = b;346 347 return static_cast<uint32_t>(d);348 }349 350 uint32_t UString::toUInt32(bool* ok, bool tolerateEmptyString) const351 {352 double d = toDouble(false, tolerateEmptyString);353 bool b = true;354 355 if (d != static_cast<uint32_t>(d)) {356 b = false;357 d = 0;358 }359 360 if (ok)361 *ok = b;362 363 return static_cast<uint32_t>(d);364 }365 366 uint32_t UString::toStrictUInt32(bool* ok) const367 {368 if (ok)369 *ok = false;370 371 // Empty string is not OK.372 unsigned len = m_impl->length();373 if (len == 0)374 return 0;375 const UChar* p = m_impl->characters();376 unsigned short c = p[0];377 378 // If the first digit is 0, only 0 itself is OK.379 if (c == '0') {380 if (len == 1 && ok)381 *ok = true;382 return 0;383 }384 385 // Convert to UInt32, checking for overflow.386 uint32_t i = 0;387 while (1) {388 // Process character, turning it into a digit.389 if (c < '0' || c > '9')390 return 0;391 const unsigned d = c - '0';392 393 // Multiply by 10, checking for overflow out of 32 bits.394 if (i > 0xFFFFFFFFU / 10)395 return 0;396 i *= 10;397 398 // Add in the digit, checking for overflow out of 32 bits.399 const unsigned max = 0xFFFFFFFFU - d;400 if (i > max)401 return 0;402 i += d;403 404 // Handle end of string.405 if (--len == 0) {406 if (ok)407 *ok = true;408 return i;409 }410 411 // Get next character.412 c = *(++p);413 }414 }415 416 207 UString UString::substr(unsigned pos, unsigned len) const 417 208 {
Note:
See TracChangeset
for help on using the changeset viewer.