Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project 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 "src/inspector/String16.h" | 5 #include "src/inspector/String16.h" |
| 6 | 6 |
| 7 #include "src/inspector/ProtocolPlatform.h" | 7 #include "src/inspector/ProtocolPlatform.h" |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <cctype> | 10 #include <cctype> |
| 11 #include <cstdio> | 11 #include <cstdio> |
| 12 #include <cstdlib> | 12 #include <cstdlib> |
| 13 #include <cstring> | 13 #include <cstring> |
| 14 #include <limits> | |
| 14 #include <locale> | 15 #include <locale> |
| 15 #include <string> | 16 #include <string> |
| 16 | 17 |
| 17 namespace v8_inspector { | 18 namespace v8_inspector { |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| 20 | 21 |
| 21 bool isASCII(UChar c) { return !(c & ~0x7F); } | 22 bool isASCII(UChar c) { return !(c & ~0x7F); } |
| 22 | 23 |
| 23 bool isSpaceOrNewLine(UChar c) { | 24 bool isSpaceOrNewLine(UChar c) { |
| 24 return isASCII(c) && c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); | 25 return isASCII(c) && c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); |
| 25 } | 26 } |
| 26 | 27 |
| 27 int charactersToInteger(const UChar* characters, size_t length, | 28 int charactersToInteger(const UChar* characters, size_t length, |
| 28 bool* ok = nullptr) { | 29 bool* ok = nullptr) { |
| 29 std::vector<char> buffer; | 30 std::vector<char> buffer; |
| 30 buffer.reserve(length + 1); | 31 buffer.reserve(length + 1); |
| 31 for (size_t i = 0; i < length; ++i) { | 32 for (size_t i = 0; i < length; ++i) { |
| 32 if (!isASCII(characters[i])) { | 33 if (!isASCII(characters[i])) { |
| 33 if (ok) *ok = false; | 34 if (ok) *ok = false; |
| 34 return 0; | 35 return 0; |
| 35 } | 36 } |
| 36 buffer.push_back(static_cast<char>(characters[i])); | 37 buffer.push_back(static_cast<char>(characters[i])); |
| 37 } | 38 } |
| 38 buffer.push_back('\0'); | 39 buffer.push_back('\0'); |
| 39 | 40 |
| 40 char* endptr; | 41 char* endptr; |
| 41 int result = std::strtol(buffer.data(), &endptr, 10); | 42 long result = std::strtol(buffer.data(), &endptr, 10); |
| 42 if (ok) *ok = !(*endptr); | 43 if (ok) { |
| 43 return result; | 44 *ok = !(*endptr) && result <= std::numeric_limits<int>::max() && |
| 45 result >= std::numeric_limits<int>::min(); | |
| 46 } | |
| 47 return static_cast<int>(result); | |
| 44 } | 48 } |
| 45 | 49 |
| 46 const UChar replacementCharacter = 0xFFFD; | 50 const UChar replacementCharacter = 0xFFFD; |
| 47 using UChar32 = uint32_t; | 51 using UChar32 = uint32_t; |
| 48 | 52 |
| 49 inline int inlineUTF8SequenceLengthNonASCII(char b0) { | 53 inline int inlineUTF8SequenceLengthNonASCII(char b0) { |
| 50 if ((b0 & 0xC0) != 0xC0) return 0; | 54 if ((b0 & 0xC0) != 0xC0) return 0; |
| 51 if ((b0 & 0xE0) == 0xC0) return 2; | 55 if ((b0 & 0xE0) == 0xC0) return 2; |
| 52 if ((b0 & 0xF0) == 0xE0) return 3; | 56 if ((b0 & 0xF0) == 0xE0) return 3; |
| 53 if ((b0 & 0xF8) == 0xF0) return 4; | 57 if ((b0 & 0xF8) == 0xF0) return 4; |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 242 // Magic values subtracted from a buffer value during UTF8 conversion. | 246 // Magic values subtracted from a buffer value during UTF8 conversion. |
| 243 // This table contains as many values as there might be trailing bytes | 247 // This table contains as many values as there might be trailing bytes |
| 244 // in a UTF-8 sequence. | 248 // in a UTF-8 sequence. |
| 245 static const UChar32 offsetsFromUTF8[6] = {0x00000000UL, | 249 static const UChar32 offsetsFromUTF8[6] = {0x00000000UL, |
| 246 0x00003080UL, | 250 0x00003080UL, |
| 247 0x000E2080UL, | 251 0x000E2080UL, |
| 248 0x03C82080UL, | 252 0x03C82080UL, |
| 249 static_cast<UChar32>(0xFA082080UL), | 253 static_cast<UChar32>(0xFA082080UL), |
| 250 static_cast<UChar32>(0x82082080UL)}; | 254 static_cast<UChar32>(0x82082080UL)}; |
| 251 | 255 |
| 252 static inline UChar32 readUTF8Sequence(const char*& sequence, unsigned length) { | 256 static inline UChar32 readUTF8Sequence(const char*& sequence, size_t length) { |
| 253 UChar32 character = 0; | 257 UChar32 character = 0; |
| 254 | 258 |
| 255 // The cases all fall through. | 259 // The cases all fall through. |
| 256 switch (length) { | 260 switch (length) { |
| 257 case 6: | 261 case 6: |
| 258 character += static_cast<unsigned char>(*sequence++); | 262 character += static_cast<unsigned char>(*sequence++); |
| 259 character <<= 6; | 263 character <<= 6; |
| 260 case 5: | 264 case 5: |
| 261 character += static_cast<unsigned char>(*sequence++); | 265 character += static_cast<unsigned char>(*sequence++); |
| 262 character <<= 6; | 266 character <<= 6; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 360 | 364 |
| 361 // static | 365 // static |
| 362 String16 String16::fromInteger(int number) { | 366 String16 String16::fromInteger(int number) { |
| 363 const size_t kBufferSize = 50; | 367 const size_t kBufferSize = 50; |
| 364 char buffer[kBufferSize]; | 368 char buffer[kBufferSize]; |
| 365 std::snprintf(buffer, kBufferSize, "%d", number); | 369 std::snprintf(buffer, kBufferSize, "%d", number); |
| 366 return String16(buffer); | 370 return String16(buffer); |
| 367 } | 371 } |
| 368 | 372 |
| 369 // static | 373 // static |
| 374 String16 String16::fromInteger(size_t number) { | |
| 375 const size_t kBufferSize = 50; | |
| 376 char buffer[kBufferSize]; | |
| 377 std::snprintf(buffer, kBufferSize, "%zu", number); | |
|
alph
2016/09/13 00:46:48
v8 uses OS::SNPrintF
kozy
2016/09/13 01:00:20
I'll replace it in follow-up.
| |
| 378 return String16(buffer); | |
| 379 } | |
| 380 | |
| 381 // static | |
| 370 String16 String16::fromDouble(double number) { | 382 String16 String16::fromDouble(double number) { |
| 371 const size_t kBufferSize = 100; | 383 const size_t kBufferSize = 100; |
| 372 char buffer[kBufferSize]; | 384 char buffer[kBufferSize]; |
| 373 std::snprintf(buffer, kBufferSize, "%f", number); | 385 std::snprintf(buffer, kBufferSize, "%f", number); |
| 374 return String16(buffer); | 386 return String16(buffer); |
| 375 } | 387 } |
| 376 | 388 |
| 377 // static | 389 // static |
| 378 String16 String16::fromDoublePrecision3(double number) { | 390 String16 String16::fromDoublePrecision3(double number) { |
| 379 const size_t kBufferSize = 100; | 391 const size_t kBufferSize = 100; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 390 return String16(buffer); | 402 return String16(buffer); |
| 391 } | 403 } |
| 392 | 404 |
| 393 int String16::toInteger(bool* ok) const { | 405 int String16::toInteger(bool* ok) const { |
| 394 return charactersToInteger(characters16(), length(), ok); | 406 return charactersToInteger(characters16(), length(), ok); |
| 395 } | 407 } |
| 396 | 408 |
| 397 String16 String16::stripWhiteSpace() const { | 409 String16 String16::stripWhiteSpace() const { |
| 398 if (!length()) return String16(); | 410 if (!length()) return String16(); |
| 399 | 411 |
| 400 unsigned start = 0; | 412 size_t start = 0; |
| 401 unsigned end = length() - 1; | 413 size_t end = length() - 1; |
| 402 | 414 |
| 403 // skip white space from start | 415 // skip white space from start |
| 404 while (start <= end && isSpaceOrNewLine(characters16()[start])) ++start; | 416 while (start <= end && isSpaceOrNewLine(characters16()[start])) ++start; |
| 405 | 417 |
| 406 // only white space | 418 // only white space |
| 407 if (start > end) return String16(); | 419 if (start > end) return String16(); |
| 408 | 420 |
| 409 // skip white space from end | 421 // skip white space from end |
| 410 while (end && isSpaceOrNewLine(characters16()[end])) --end; | 422 while (end && isSpaceOrNewLine(characters16()[end])) --end; |
| 411 | 423 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 449 std::vector<UChar> buffer(length); | 461 std::vector<UChar> buffer(length); |
| 450 UChar* bufferStart = buffer.data(); | 462 UChar* bufferStart = buffer.data(); |
| 451 | 463 |
| 452 UChar* bufferCurrent = bufferStart; | 464 UChar* bufferCurrent = bufferStart; |
| 453 const char* stringCurrent = stringStart; | 465 const char* stringCurrent = stringStart; |
| 454 if (convertUTF8ToUTF16(&stringCurrent, stringStart + length, &bufferCurrent, | 466 if (convertUTF8ToUTF16(&stringCurrent, stringStart + length, &bufferCurrent, |
| 455 bufferCurrent + buffer.size(), 0, | 467 bufferCurrent + buffer.size(), 0, |
| 456 true) != conversionOK) | 468 true) != conversionOK) |
| 457 return String16(); | 469 return String16(); |
| 458 | 470 |
| 459 unsigned utf16Length = bufferCurrent - bufferStart; | 471 size_t utf16Length = bufferCurrent - bufferStart; |
| 460 return String16(bufferStart, utf16Length); | 472 return String16(bufferStart, utf16Length); |
| 461 } | 473 } |
| 462 | 474 |
| 463 std::string String16::utf8() const { | 475 std::string String16::utf8() const { |
| 464 unsigned length = this->length(); | 476 size_t length = this->length(); |
| 465 | 477 |
| 466 if (!length) return std::string(""); | 478 if (!length) return std::string(""); |
| 467 | 479 |
| 468 // Allocate a buffer big enough to hold all the characters | 480 // Allocate a buffer big enough to hold all the characters |
| 469 // (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes). | 481 // (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes). |
| 470 // Optimization ideas, if we find this function is hot: | 482 // Optimization ideas, if we find this function is hot: |
| 471 // * We could speculatively create a CStringBuffer to contain 'length' | 483 // * We could speculatively create a CStringBuffer to contain 'length' |
| 472 // characters, and resize if necessary (i.e. if the buffer contains | 484 // characters, and resize if necessary (i.e. if the buffer contains |
| 473 // non-ascii characters). (Alternatively, scan the buffer first for | 485 // non-ascii characters). (Alternatively, scan the buffer first for |
| 474 // ascii characters, so we know this will be sufficient). | 486 // ascii characters, so we know this will be sufficient). |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 501 // There should be room left, since one UChar hasn't been | 513 // There should be room left, since one UChar hasn't been |
| 502 // converted. | 514 // converted. |
| 503 DCHECK((buffer + 3) <= (buffer + bufferVector.size())); | 515 DCHECK((buffer + 3) <= (buffer + bufferVector.size())); |
| 504 putUTF8Triple(buffer, *characters); | 516 putUTF8Triple(buffer, *characters); |
| 505 } | 517 } |
| 506 | 518 |
| 507 return std::string(bufferVector.data(), buffer - bufferVector.data()); | 519 return std::string(bufferVector.data(), buffer - bufferVector.data()); |
| 508 } | 520 } |
| 509 | 521 |
| 510 } // namespace v8_inspector | 522 } // namespace v8_inspector |
| OLD | NEW |