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 | |
7 #include "platform/v8_inspector/ProtocolPlatform.h" | |
6 | 8 |
7 #include <algorithm> | 9 #include <algorithm> |
8 #include <cctype> | 10 #include <cctype> |
9 #include <cstdio> | 11 #include <cstdio> |
12 #include <cstdlib> | |
13 #include <cstring> | |
10 #include <locale> | 14 #include <locale> |
15 #include <string> | |
11 | 16 |
12 namespace blink { | 17 namespace v8_inspector { |
13 namespace protocol { | 18 |
19 namespace { | |
20 | |
21 bool isASCII(UChar c) | |
22 { | |
23 return !(c & ~0x7F); | |
24 } | |
25 | |
26 bool isSpaceOrNewLine(UChar c) | |
27 { | |
28 return isASCII(c) && c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); | |
29 } | |
30 | |
31 int charactersToInteger(const UChar* characters, size_t length, bool* ok = nullp tr) | |
32 { | |
33 std::vector<char> buffer; | |
34 buffer.reserve(length + 1); | |
35 for (size_t i = 0; i < length; ++i) { | |
36 if (!isASCII(characters[i])) { | |
37 if (ok) | |
38 *ok = false; | |
39 return 0; | |
40 } | |
41 buffer.push_back(static_cast<char>(characters[i])); | |
42 } | |
43 buffer.push_back('\0'); | |
44 | |
45 char* endptr; | |
46 int result = std::strtol(buffer.data(), &endptr, 10); | |
47 if (ok) | |
48 *ok = !(*endptr); | |
49 return result; | |
50 } | |
14 | 51 |
15 const UChar replacementCharacter = 0xFFFD; | 52 const UChar replacementCharacter = 0xFFFD; |
16 using UChar32 = uint32_t; | 53 using UChar32 = uint32_t; |
17 | 54 |
18 inline int inlineUTF8SequenceLengthNonASCII(char b0) | 55 inline int inlineUTF8SequenceLengthNonASCII(char b0) |
19 { | 56 { |
20 if ((b0 & 0xC0) != 0xC0) | 57 if ((b0 & 0xC0) != 0xC0) |
21 return 0; | 58 return 0; |
22 if ((b0 & 0xE0) == 0xC0) | 59 if ((b0 & 0xE0) == 0xC0) |
23 return 2; | 60 return 2; |
24 if ((b0 & 0xF0) == 0xE0) | 61 if ((b0 & 0xF0) == 0xE0) |
25 return 3; | 62 return 3; |
26 if ((b0 & 0xF8) == 0xF0) | 63 if ((b0 & 0xF8) == 0xF0) |
27 return 4; | 64 return 4; |
28 return 0; | 65 return 0; |
29 } | 66 } |
30 | 67 |
31 inline int inlineUTF8SequenceLength(char b0) | 68 inline int inlineUTF8SequenceLength(char b0) |
32 { | 69 { |
33 return String16::isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0); | 70 return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0); |
34 } | 71 } |
35 | 72 |
36 // Once the bits are split out into bytes of UTF-8, this is a mask OR-ed | 73 // 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 | 74 // 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. | 75 // 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 | 76 // (I.e., one byte sequence, two byte... etc.). Remember that sequences |
40 // for *legal* UTF-8 will be 4 or fewer bytes total. | 77 // 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 }; | 78 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0x F8, 0xFC }; |
42 | 79 |
43 typedef enum { | 80 typedef enum { |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
325 | 362 |
326 if (sourceAllASCII) | 363 if (sourceAllASCII) |
327 *sourceAllASCII = !(orAllData & ~0x7f); | 364 *sourceAllASCII = !(orAllData & ~0x7f); |
328 | 365 |
329 return result; | 366 return result; |
330 } | 367 } |
331 | 368 |
332 // Helper to write a three-byte UTF-8 code point to the buffer, caller must chec k room is available. | 369 // 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) | 370 static inline void putUTF8Triple(char*& buffer, UChar ch) |
334 { | 371 { |
335 DCHECK_GE(ch, 0x0800); | |
336 *buffer++ = static_cast<char>(((ch >> 12) & 0x0F) | 0xE0); | 372 *buffer++ = static_cast<char>(((ch >> 12) & 0x0F) | 0xE0); |
337 *buffer++ = static_cast<char>(((ch >> 6) & 0x3F) | 0x80); | 373 *buffer++ = static_cast<char>(((ch >> 6) & 0x3F) | 0x80); |
338 *buffer++ = static_cast<char>((ch & 0x3F) | 0x80); | 374 *buffer++ = static_cast<char>((ch & 0x3F) | 0x80); |
339 } | 375 } |
340 | 376 |
377 } // namespace | |
378 | |
379 // static | |
380 String16 String16::fromInteger(int number) | |
381 { | |
382 const size_t kBufferSize = 50; | |
383 char buffer[kBufferSize]; | |
384 std::snprintf(buffer, kBufferSize, "%d", number); | |
385 return String16(buffer); | |
386 } | |
387 | |
388 // static | |
389 String16 String16::fromDouble(double number) | |
390 { | |
391 const size_t kBufferSize = 100; | |
392 char buffer[kBufferSize]; | |
393 std::snprintf(buffer, kBufferSize, "%f", number); | |
394 return String16(buffer); | |
395 } | |
396 | |
397 // static | |
398 String16 String16::fromDoublePrecision3(double number) | |
399 { | |
400 const size_t kBufferSize = 100; | |
401 char buffer[kBufferSize]; | |
402 std::snprintf(buffer, kBufferSize, "%.3g", number); | |
403 return String16(buffer); | |
404 } | |
405 | |
406 // static | |
407 String16 String16::fromDoublePrecision6(double number) | |
408 { | |
409 const size_t kBufferSize = 100; | |
410 char buffer[kBufferSize]; | |
411 std::snprintf(buffer, kBufferSize, "%.6g", number); | |
412 return String16(buffer); | |
413 } | |
414 | |
415 int String16::toInteger(bool* ok) const | |
416 { | |
417 return charactersToInteger(characters16(), length(), ok); | |
418 } | |
419 | |
420 String16 String16::stripWhiteSpace() const | |
421 { | |
422 if (!length()) | |
423 return String16(); | |
424 | |
425 unsigned start = 0; | |
426 unsigned end = length() - 1; | |
427 | |
428 // skip white space from start | |
429 while (start <= end && isSpaceOrNewLine(characters16()[start])) | |
430 ++start; | |
431 | |
432 // only white space | |
433 if (start > end) | |
434 return String16(); | |
435 | |
436 // skip white space from end | |
437 while (end && isSpaceOrNewLine(characters16()[end])) | |
438 --end; | |
439 | |
440 if (!start && end == length() - 1) | |
441 return *this; | |
442 return String16(characters16() + start, end + 1 - start); | |
443 } | |
444 | |
445 String16Builder::String16Builder() | |
446 { | |
447 } | |
448 | |
449 void String16Builder::append(const String16& s) | |
450 { | |
451 m_buffer.insert(m_buffer.end(), s.characters16(), s.characters16() + s.lengt h()); | |
452 } | |
453 | |
454 void String16Builder::append(UChar c) | |
455 { | |
456 m_buffer.push_back(c); | |
457 } | |
458 | |
459 void String16Builder::append(char c) | |
460 { | |
461 UChar u = c; | |
462 m_buffer.push_back(u); | |
463 } | |
464 | |
465 void String16Builder::append(const UChar* characters, size_t length) | |
466 { | |
467 m_buffer.insert(m_buffer.end(), characters, characters + length); | |
468 } | |
469 | |
470 void String16Builder::append(const char* characters, size_t length) | |
caseq
2016/08/26 19:17:20
just copy-paste the one-line implementation above
dgozman
2016/08/26 21:31:27
Done.
| |
471 { | |
472 m_buffer.reserve(m_buffer.size() + length); | |
473 for (size_t i = 0; i < length; ++i, ++characters) { | |
474 UChar u = *characters; | |
475 m_buffer.push_back(u); | |
476 } | |
477 } | |
478 | |
479 String16 String16Builder::toString() | |
480 { | |
481 return String16(m_buffer.data(), m_buffer.size()); | |
482 } | |
483 | |
484 void String16Builder::reserveCapacity(size_t capacity) | |
485 { | |
486 m_buffer.reserve(capacity); | |
487 } | |
488 | |
341 String16 String16::fromUTF8(const char* stringStart, size_t length) | 489 String16 String16::fromUTF8(const char* stringStart, size_t length) |
342 { | 490 { |
343 if (!stringStart || !length) | 491 if (!stringStart || !length) |
344 return String16(); | 492 return String16(); |
345 | 493 |
346 std::vector<UChar> buffer(length); | 494 std::vector<UChar> buffer(length); |
347 UChar* bufferStart = buffer.data(); | 495 UChar* bufferStart = buffer.data(); |
348 | 496 |
349 UChar* bufferCurrent = bufferStart; | 497 UChar* bufferCurrent = bufferStart; |
350 const char* stringCurrent = stringStart; | 498 const char* stringCurrent = stringStart; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
394 DCHECK((*characters >= 0xD800) && (*characters <= 0xDBFF)); | 542 DCHECK((*characters >= 0xD800) && (*characters <= 0xDBFF)); |
395 // There should be room left, since one UChar hasn't been | 543 // There should be room left, since one UChar hasn't been |
396 // converted. | 544 // converted. |
397 DCHECK((buffer + 3) <= (buffer + bufferVector.size())); | 545 DCHECK((buffer + 3) <= (buffer + bufferVector.size())); |
398 putUTF8Triple(buffer, *characters); | 546 putUTF8Triple(buffer, *characters); |
399 } | 547 } |
400 | 548 |
401 return std::string(bufferVector.data(), buffer - bufferVector.data()); | 549 return std::string(bufferVector.data(), buffer - bufferVector.data()); |
402 } | 550 } |
403 | 551 |
404 } // namespace protocol | 552 } // namespace v8_inspector |
405 } // namespace blink | |
OLD | NEW |