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