Chromium Code Reviews| 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 "platform/inspector_protocol/InspectorProtocol.h" | 5 #include "platform/v8_inspector/String16.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cctype> | 8 #include <cctype> |
| 9 #include <cstdio> | 9 #include <cstdio> |
| 10 #include <cstdlib> | |
| 11 #include <cstring> | |
| 10 #include <locale> | 12 #include <locale> |
| 13 #include <string> | |
| 11 | 14 |
| 12 namespace blink { | 15 namespace v8_inspector { |
| 13 namespace protocol { | 16 |
| 17 namespace { | |
| 18 | |
| 19 bool isASCII(UChar c) | |
| 20 { | |
| 21 return !(c & ~0x7F); | |
| 22 } | |
| 23 | |
| 24 bool isSpaceOrNewLine(UChar c) | |
| 25 { | |
| 26 return isASCII(c) && c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); | |
| 27 } | |
| 28 | |
| 29 double charactersToDouble(const UChar* characters, size_t length, bool* ok = nul lptr) | |
| 30 { | |
| 31 std::vector<char> buffer; | |
| 32 buffer.reserve(length + 1); | |
| 33 for (size_t i = 0; i < length; ++i) { | |
| 34 if (!isASCII(characters[i])) { | |
| 35 if (ok) | |
| 36 *ok = false; | |
| 37 return 0; | |
| 38 } | |
| 39 buffer.push_back(static_cast<char>(characters[i])); | |
| 40 } | |
| 41 buffer.push_back('\0'); | |
| 42 | |
| 43 char* endptr; | |
| 44 double result = std::strtod(buffer.data(), &endptr); | |
| 45 if (ok) | |
| 46 *ok = !(*endptr); | |
| 47 return result; | |
| 48 } | |
| 49 | |
| 50 int charactersToInteger(const UChar* characters, size_t length, bool* ok = nullp tr) | |
| 51 { | |
| 52 std::vector<char> buffer; | |
| 53 buffer.reserve(length + 1); | |
| 54 for (size_t i = 0; i < length; ++i) { | |
| 55 if (!isASCII(characters[i])) { | |
| 56 if (ok) | |
| 57 *ok = false; | |
| 58 return 0; | |
| 59 } | |
| 60 buffer.push_back(static_cast<char>(characters[i])); | |
| 61 } | |
| 62 buffer.push_back('\0'); | |
| 63 | |
| 64 char* endptr; | |
| 65 int result = std::strtol(buffer.data(), &endptr, 10); | |
| 66 if (ok) | |
| 67 *ok = !(*endptr); | |
| 68 return result; | |
| 69 } | |
| 14 | 70 |
| 15 const UChar replacementCharacter = 0xFFFD; | 71 const UChar replacementCharacter = 0xFFFD; |
| 16 using UChar32 = uint32_t; | 72 using UChar32 = uint32_t; |
| 17 | 73 |
| 18 inline int inlineUTF8SequenceLengthNonASCII(char b0) | 74 inline int inlineUTF8SequenceLengthNonASCII(char b0) |
| 19 { | 75 { |
| 20 if ((b0 & 0xC0) != 0xC0) | 76 if ((b0 & 0xC0) != 0xC0) |
| 21 return 0; | 77 return 0; |
| 22 if ((b0 & 0xE0) == 0xC0) | 78 if ((b0 & 0xE0) == 0xC0) |
| 23 return 2; | 79 return 2; |
| 24 if ((b0 & 0xF0) == 0xE0) | 80 if ((b0 & 0xF0) == 0xE0) |
| 25 return 3; | 81 return 3; |
| 26 if ((b0 & 0xF8) == 0xF0) | 82 if ((b0 & 0xF8) == 0xF0) |
| 27 return 4; | 83 return 4; |
| 28 return 0; | 84 return 0; |
| 29 } | 85 } |
| 30 | 86 |
| 31 inline int inlineUTF8SequenceLength(char b0) | 87 inline int inlineUTF8SequenceLength(char b0) |
| 32 { | 88 { |
| 33 return String16::isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0); | 89 return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0); |
| 34 } | 90 } |
| 35 | 91 |
| 36 // Once the bits are split out into bytes of UTF-8, this is a mask OR-ed | 92 // Once the bits are split out into bytes of UTF-8, this is a mask OR-ed |
| 37 // into the first byte, depending on how many bytes follow. There are | 93 // into the first byte, depending on how many bytes follow. There are |
| 38 // as many entries in this table as there are UTF-8 sequence types. | 94 // as many entries in this table as there are UTF-8 sequence types. |
| 39 // (I.e., one byte sequence, two byte... etc.). Remember that sequences | 95 // (I.e., one byte sequence, two byte... etc.). Remember that sequences |
| 40 // for *legal* UTF-8 will be 4 or fewer bytes total. | 96 // for *legal* UTF-8 will be 4 or fewer bytes total. |
| 41 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0x F8, 0xFC }; | 97 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0x F8, 0xFC }; |
| 42 | 98 |
| 43 typedef enum { | 99 typedef enum { |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 325 | 381 |
| 326 if (sourceAllASCII) | 382 if (sourceAllASCII) |
| 327 *sourceAllASCII = !(orAllData & ~0x7f); | 383 *sourceAllASCII = !(orAllData & ~0x7f); |
| 328 | 384 |
| 329 return result; | 385 return result; |
| 330 } | 386 } |
| 331 | 387 |
| 332 // Helper to write a three-byte UTF-8 code point to the buffer, caller must chec k room is available. | 388 // Helper to write a three-byte UTF-8 code point to the buffer, caller must chec k room is available. |
| 333 static inline void putUTF8Triple(char*& buffer, UChar ch) | 389 static inline void putUTF8Triple(char*& buffer, UChar ch) |
| 334 { | 390 { |
| 335 DCHECK_GE(ch, 0x0800); | |
| 336 *buffer++ = static_cast<char>(((ch >> 12) & 0x0F) | 0xE0); | 391 *buffer++ = static_cast<char>(((ch >> 12) & 0x0F) | 0xE0); |
| 337 *buffer++ = static_cast<char>(((ch >> 6) & 0x3F) | 0x80); | 392 *buffer++ = static_cast<char>(((ch >> 6) & 0x3F) | 0x80); |
| 338 *buffer++ = static_cast<char>((ch & 0x3F) | 0x80); | 393 *buffer++ = static_cast<char>((ch & 0x3F) | 0x80); |
| 339 } | 394 } |
| 340 | 395 |
| 396 } // namespace | |
| 397 | |
| 398 // static | |
| 399 String16 String16::fromInteger(int number) | |
| 400 { | |
| 401 const size_t kBufferSize = 50; | |
| 402 char buffer[kBufferSize]; | |
| 403 std::snprintf(buffer, kBufferSize, "%d", number); | |
| 404 return String16(buffer); | |
| 405 } | |
| 406 | |
| 407 // static | |
| 408 String16 String16::fromDouble(double number) | |
| 409 { | |
| 410 const size_t kBufferSize = 100; | |
|
caseq
2016/08/19 02:50:36
100 looks like overkill :-)
| |
| 411 char buffer[kBufferSize]; | |
| 412 std::snprintf(buffer, kBufferSize, "%f", number); | |
| 413 return String16(buffer); | |
| 414 } | |
| 415 | |
| 416 // static | |
| 417 String16 String16::fromDoublePrecision3(double number) | |
| 418 { | |
| 419 const size_t kBufferSize = 100; | |
| 420 char buffer[kBufferSize]; | |
| 421 std::snprintf(buffer, kBufferSize, "%.3g", number); | |
| 422 return String16(buffer); | |
| 423 } | |
| 424 | |
| 425 // static | |
| 426 String16 String16::fromDoublePrecision6(double number) | |
| 427 { | |
| 428 const size_t kBufferSize = 100; | |
| 429 char buffer[kBufferSize]; | |
| 430 std::snprintf(buffer, kBufferSize, "%.6g", number); | |
| 431 return String16(buffer); | |
| 432 } | |
| 433 | |
| 434 double String16::toDouble(bool* ok) const | |
| 435 { | |
| 436 return charactersToDouble(characters16(), length(), ok); | |
| 437 } | |
| 438 | |
| 439 int String16::toInteger(bool* ok) const | |
| 440 { | |
| 441 return charactersToInteger(characters16(), length(), ok); | |
| 442 } | |
| 443 | |
| 444 String16 String16::stripWhiteSpace() const | |
| 445 { | |
| 446 if (!length()) | |
| 447 return String16(); | |
| 448 | |
| 449 unsigned start = 0; | |
| 450 unsigned end = length() - 1; | |
| 451 | |
| 452 // skip white space from start | |
| 453 while (start <= end && isSpaceOrNewLine(characters16()[start])) | |
| 454 ++start; | |
| 455 | |
| 456 // only white space | |
| 457 if (start > end) | |
| 458 return String16(); | |
| 459 | |
| 460 // skip white space from end | |
| 461 while (end && isSpaceOrNewLine(characters16()[end])) | |
| 462 --end; | |
| 463 | |
| 464 if (!start && end == length() - 1) | |
| 465 return *this; | |
| 466 return String16(characters16() + start, end + 1 - start); | |
| 467 } | |
| 468 | |
| 469 bool String16::startsWith(const char* prefix) const | |
| 470 { | |
| 471 for (size_t i = 0, j = 0; prefix[j] && i < length(); ++i, ++j) { | |
| 472 if (characters16()[i] != prefix[j]) | |
| 473 return false; | |
| 474 } | |
| 475 return true; | |
| 476 } | |
| 477 | |
| 478 String16Builder::String16Builder() | |
| 479 { | |
| 480 } | |
| 481 | |
| 482 void String16Builder::append(const String16& s) | |
| 483 { | |
| 484 m_buffer.insert(m_buffer.end(), s.characters16(), s.characters16() + s.lengt h()); | |
| 485 } | |
| 486 | |
| 487 void String16Builder::append(UChar c) | |
| 488 { | |
| 489 m_buffer.push_back(c); | |
| 490 } | |
| 491 | |
| 492 void String16Builder::append(char c) | |
| 493 { | |
| 494 UChar u = c; | |
| 495 m_buffer.push_back(u); | |
| 496 } | |
| 497 | |
| 498 void String16Builder::append(const UChar* characters, size_t length) | |
| 499 { | |
| 500 m_buffer.insert(m_buffer.end(), characters, characters + length); | |
| 501 } | |
| 502 | |
| 503 void String16Builder::append(const char* characters, size_t length) | |
| 504 { | |
| 505 m_buffer.reserve(m_buffer.size() + length); | |
| 506 for (size_t i = 0; i < length; ++i, ++characters) { | |
| 507 UChar u = *characters; | |
| 508 m_buffer.push_back(u); | |
| 509 } | |
| 510 } | |
| 511 | |
| 512 String16 String16Builder::toString() | |
| 513 { | |
| 514 return String16(m_buffer.data(), m_buffer.size()); | |
| 515 } | |
| 516 | |
| 517 void String16Builder::reserveCapacity(size_t capacity) | |
| 518 { | |
| 519 m_buffer.reserve(capacity); | |
| 520 } | |
| 521 | |
| 341 String16 String16::fromUTF8(const char* stringStart, size_t length) | 522 String16 String16::fromUTF8(const char* stringStart, size_t length) |
| 342 { | 523 { |
| 343 if (!stringStart || !length) | 524 if (!stringStart || !length) |
| 344 return String16(); | 525 return String16(); |
| 345 | 526 |
| 346 std::vector<UChar> buffer(length); | 527 std::vector<UChar> buffer(length); |
| 347 UChar* bufferStart = buffer.data(); | 528 UChar* bufferStart = buffer.data(); |
| 348 | 529 |
| 349 UChar* bufferCurrent = bufferStart; | 530 UChar* bufferCurrent = bufferStart; |
| 350 const char* stringCurrent = stringStart; | 531 const char* stringCurrent = stringStart; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 372 // * We could allocate a CStringBuffer with an appropriate size to | 553 // * We could allocate a CStringBuffer with an appropriate size to |
| 373 // have a good chance of being able to write the string into the | 554 // have a good chance of being able to write the string into the |
| 374 // buffer without reallocing (say, 1.5 x length). | 555 // buffer without reallocing (say, 1.5 x length). |
| 375 if (length > std::numeric_limits<unsigned>::max() / 3) | 556 if (length > std::numeric_limits<unsigned>::max() / 3) |
| 376 return std::string(); | 557 return std::string(); |
| 377 std::vector<char> bufferVector(length * 3); | 558 std::vector<char> bufferVector(length * 3); |
| 378 char* buffer = bufferVector.data(); | 559 char* buffer = bufferVector.data(); |
| 379 const UChar* characters = m_impl.data(); | 560 const UChar* characters = m_impl.data(); |
| 380 | 561 |
| 381 ConversionResult result = convertUTF16ToUTF8(&characters, characters + lengt h, &buffer, buffer + bufferVector.size(), false); | 562 ConversionResult result = convertUTF16ToUTF8(&characters, characters + lengt h, &buffer, buffer + bufferVector.size(), false); |
| 382 DCHECK(result != targetExhausted); // (length * 3) should be sufficient for any conversion | |
| 383 | |
| 384 // Only produced from strict conversion. | |
| 385 DCHECK(result != sourceIllegal); | |
| 386 | 563 |
| 387 // Check for an unconverted high surrogate. | 564 // Check for an unconverted high surrogate. |
| 388 if (result == sourceExhausted) { | 565 if (result == sourceExhausted) |
| 389 // This should be one unpaired high surrogate. Treat it the same | |
| 390 // was as an unpaired high surrogate would have been handled in | |
| 391 // the middle of a string with non-strict conversion - which is | |
| 392 // to say, simply encode it to UTF-8. | |
| 393 DCHECK((characters + 1) == (m_impl.data() + length)); | |
| 394 DCHECK((*characters >= 0xD800) && (*characters <= 0xDBFF)); | |
| 395 // There should be room left, since one UChar hasn't been | |
| 396 // converted. | |
| 397 DCHECK((buffer + 3) <= (buffer + bufferVector.size())); | |
| 398 putUTF8Triple(buffer, *characters); | 566 putUTF8Triple(buffer, *characters); |
| 399 } | |
| 400 | 567 |
| 401 return std::string(bufferVector.data(), buffer - bufferVector.data()); | 568 return std::string(bufferVector.data(), buffer - bufferVector.data()); |
| 402 } | 569 } |
| 403 | 570 |
| 404 } // namespace protocol | 571 } // namespace v8_inspector |
| 405 } // namespace blink | |
| OLD | NEW |