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/Parser.h" | 5 #include "platform/inspector_protocol/Parser.h" |
6 | 6 |
7 #include "platform/Decimal.h" | 7 #include "platform/inspector_protocol/String16.h" |
8 #include "platform/inspector_protocol/Values.h" | 8 #include "platform/inspector_protocol/Values.h" |
9 #include "wtf/text/StringBuilder.h" | |
10 #include "wtf/text/UTF8.h" | |
11 | 9 |
12 namespace blink { | 10 namespace blink { |
13 namespace protocol { | 11 namespace protocol { |
14 | 12 |
15 namespace { | 13 namespace { |
16 | 14 |
17 const int stackLimit = 1000; | 15 const int stackLimit = 1000; |
18 | 16 |
19 enum Token { | 17 enum Token { |
20 ObjectBegin, | 18 ObjectBegin, |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 return c - '0'; | 290 return c - '0'; |
293 if ('A' <= c && c <= 'F') | 291 if ('A' <= c && c <= 'F') |
294 return c - 'A' + 10; | 292 return c - 'A' + 10; |
295 if ('a' <= c && c <= 'f') | 293 if ('a' <= c && c <= 'f') |
296 return c - 'a' + 10; | 294 return c - 'a' + 10; |
297 ASSERT_NOT_REACHED(); | 295 ASSERT_NOT_REACHED(); |
298 return 0; | 296 return 0; |
299 } | 297 } |
300 | 298 |
301 template<typename CharType> | 299 template<typename CharType> |
302 bool decodeUTF8(const CharType* start, const CharType* end, const CharType** utf
8charEnd, StringBuilder* output) | 300 bool decodeUTF8(const CharType* start, const CharType* end, const CharType** utf
8charEnd, String16Builder* output) |
303 { | 301 { |
304 UChar utf16[4] = {0}; | 302 UChar utf16[4] = {0}; |
305 char utf8[6] = {0}; | 303 char utf8[6] = {0}; |
306 size_t utf8count = 0; | 304 size_t utf8count = 0; |
307 | 305 |
308 while (start < end) { | 306 while (start < end) { |
309 if (start + 1 >= end || *start != '\\' || *(start + 1) != 'x') | 307 if (start + 1 >= end || *start != '\\' || *(start + 1) != 'x') |
310 return false; | 308 return false; |
311 start += 2; | 309 start += 2; |
312 | 310 |
313 // Accumulate one more utf8 character and try converting to utf16. | 311 // Accumulate one more utf8 character and try converting to utf16. |
314 if (start + 1 >= end) | 312 if (start + 1 >= end) |
315 return false; | 313 return false; |
316 utf8[utf8count++] = (hexToInt(*start) << 4) + hexToInt(*(start + 1)); | 314 utf8[utf8count++] = (hexToInt(*start) << 4) + hexToInt(*(start + 1)); |
317 start += 2; | 315 start += 2; |
318 | 316 |
319 const char* utf8start = utf8; | 317 const char* utf8start = utf8; |
320 UChar* utf16start = utf16; | 318 UChar* utf16start = utf16; |
321 WTF::Unicode::ConversionResult conversionResult = WTF::Unicode::convertU
TF8ToUTF16(&utf8start, utf8start + utf8count, &utf16start, utf16start + WTF_ARRA
Y_LENGTH(utf16), nullptr, true); | 319 String16::ConversionResult conversionResult = String16::convertUTF8ToUTF
16(&utf8start, utf8start + utf8count, &utf16start, utf16start + 4, nullptr, true
); |
322 | 320 |
323 if (conversionResult == WTF::Unicode::sourceIllegal) | 321 if (conversionResult == String16::sourceIllegal) |
324 return false; | 322 return false; |
325 | 323 |
326 if (conversionResult == WTF::Unicode::conversionOK) { | 324 if (conversionResult == String16::conversionOK) { |
327 // Not all utf8 characters were consumed - failed parsing. | 325 // Not all utf8 characters were consumed - failed parsing. |
328 if (utf8start != utf8 + utf8count) | 326 if (utf8start != utf8 + utf8count) |
329 return false; | 327 return false; |
330 | 328 |
331 size_t utf16length = utf16start - utf16; | 329 size_t utf16length = utf16start - utf16; |
332 output->append(utf16, utf16length); | 330 output->append(utf16, utf16length); |
333 *utf8charEnd = start; | 331 *utf8charEnd = start; |
334 return true; | 332 return true; |
335 } | 333 } |
336 | 334 |
337 // Keep accumulating utf8 characters up to buffer length (6 should be en
ough). | 335 // Keep accumulating utf8 characters up to buffer length (6 should be en
ough). |
338 if (utf8count >= WTF_ARRAY_LENGTH(utf8)) | 336 if (utf8count >= 6) |
339 return false; | 337 return false; |
340 } | 338 } |
341 | 339 |
342 return false; | 340 return false; |
343 } | 341 } |
344 | 342 |
345 template<typename CharType> | 343 template<typename CharType> |
346 bool decodeString(const CharType* start, const CharType* end, StringBuilder* out
put) | 344 bool decodeString(const CharType* start, const CharType* end, String16Builder* o
utput) |
347 { | 345 { |
348 while (start < end) { | 346 while (start < end) { |
349 UChar c = *start++; | 347 UChar c = *start++; |
350 if ('\\' != c) { | 348 if ('\\' != c) { |
351 output->append(c); | 349 output->append(c); |
352 continue; | 350 continue; |
353 } | 351 } |
354 c = *start++; | 352 c = *start++; |
355 | 353 |
356 if (c == 'x') { | 354 if (c == 'x') { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 break; | 390 break; |
393 default: | 391 default: |
394 return false; | 392 return false; |
395 } | 393 } |
396 output->append(c); | 394 output->append(c); |
397 } | 395 } |
398 return true; | 396 return true; |
399 } | 397 } |
400 | 398 |
401 template<typename CharType> | 399 template<typename CharType> |
402 bool decodeString(const CharType* start, const CharType* end, String* output) | 400 bool decodeString(const CharType* start, const CharType* end, String16* output) |
403 { | 401 { |
404 if (start == end) { | 402 if (start == end) { |
405 *output = ""; | 403 *output = ""; |
406 return true; | 404 return true; |
407 } | 405 } |
408 if (start > end) | 406 if (start > end) |
409 return false; | 407 return false; |
410 StringBuilder buffer; | 408 String16Builder buffer; |
411 buffer.reserveCapacity(end - start); | 409 buffer.reserveCapacity(end - start); |
412 if (!decodeString(start, end, &buffer)) | 410 if (!decodeString(start, end, &buffer)) |
413 return false; | 411 return false; |
414 *output = buffer.toString(); | 412 *output = buffer.toString(); |
415 // Validate constructed utf16 string. | 413 // Validate constructed utf16 string. |
416 if (output->utf8(StrictUTF8Conversion).isNull()) | 414 if (!output->validateUTF8()) |
417 return false; | 415 return false; |
418 return true; | 416 return true; |
419 } | 417 } |
420 | 418 |
421 template<typename CharType> | 419 template<typename CharType> |
422 PassOwnPtr<Value> buildValue(const CharType* start, const CharType* end, const C
harType** valueTokenEnd, int depth) | 420 PassOwnPtr<Value> buildValue(const CharType* start, const CharType* end, const C
harType** valueTokenEnd, int depth) |
423 { | 421 { |
424 if (depth > stackLimit) | 422 if (depth > stackLimit) |
425 return nullptr; | 423 return nullptr; |
426 | 424 |
427 OwnPtr<Value> result; | 425 OwnPtr<Value> result; |
428 const CharType* tokenStart; | 426 const CharType* tokenStart; |
429 const CharType* tokenEnd; | 427 const CharType* tokenEnd; |
430 Token token = parseToken(start, end, &tokenStart, &tokenEnd); | 428 Token token = parseToken(start, end, &tokenStart, &tokenEnd); |
431 switch (token) { | 429 switch (token) { |
432 case InvalidToken: | 430 case InvalidToken: |
433 return nullptr; | 431 return nullptr; |
434 case NullToken: | 432 case NullToken: |
435 result = Value::null(); | 433 result = Value::null(); |
436 break; | 434 break; |
437 case BoolTrue: | 435 case BoolTrue: |
438 result = FundamentalValue::create(true); | 436 result = FundamentalValue::create(true); |
439 break; | 437 break; |
440 case BoolFalse: | 438 case BoolFalse: |
441 result = FundamentalValue::create(false); | 439 result = FundamentalValue::create(false); |
442 break; | 440 break; |
443 case Number: { | 441 case Number: { |
444 bool ok; | 442 bool ok; |
445 double value = charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok
); | 443 double value = String16::charactersToDouble(tokenStart, tokenEnd - token
Start, &ok); |
446 if (Decimal::fromDouble(value).isInfinity()) | |
447 ok = false; | |
448 if (!ok) | 444 if (!ok) |
449 return nullptr; | 445 return nullptr; |
450 result = FundamentalValue::create(value); | 446 result = FundamentalValue::create(value); |
451 break; | 447 break; |
452 } | 448 } |
453 case StringLiteral: { | 449 case StringLiteral: { |
454 String value; | 450 String16 value; |
455 bool ok = decodeString(tokenStart + 1, tokenEnd - 1, &value); | 451 bool ok = decodeString(tokenStart + 1, tokenEnd - 1, &value); |
456 if (!ok) | 452 if (!ok) |
457 return nullptr; | 453 return nullptr; |
458 result = StringValue::create(value); | 454 result = StringValue::create(value); |
459 break; | 455 break; |
460 } | 456 } |
461 case ArrayBegin: { | 457 case ArrayBegin: { |
462 OwnPtr<ListValue> array = ListValue::create(); | 458 OwnPtr<ListValue> array = ListValue::create(); |
463 start = tokenEnd; | 459 start = tokenEnd; |
464 token = parseToken(start, end, &tokenStart, &tokenEnd); | 460 token = parseToken(start, end, &tokenStart, &tokenEnd); |
(...skipping 21 matching lines...) Expand all Loading... |
486 result = array.release(); | 482 result = array.release(); |
487 break; | 483 break; |
488 } | 484 } |
489 case ObjectBegin: { | 485 case ObjectBegin: { |
490 OwnPtr<DictionaryValue> object = DictionaryValue::create(); | 486 OwnPtr<DictionaryValue> object = DictionaryValue::create(); |
491 start = tokenEnd; | 487 start = tokenEnd; |
492 token = parseToken(start, end, &tokenStart, &tokenEnd); | 488 token = parseToken(start, end, &tokenStart, &tokenEnd); |
493 while (token != ObjectEnd) { | 489 while (token != ObjectEnd) { |
494 if (token != StringLiteral) | 490 if (token != StringLiteral) |
495 return nullptr; | 491 return nullptr; |
496 String key; | 492 String16 key; |
497 if (!decodeString(tokenStart + 1, tokenEnd - 1, &key)) | 493 if (!decodeString(tokenStart + 1, tokenEnd - 1, &key)) |
498 return nullptr; | 494 return nullptr; |
499 start = tokenEnd; | 495 start = tokenEnd; |
500 | 496 |
501 token = parseToken(start, end, &tokenStart, &tokenEnd); | 497 token = parseToken(start, end, &tokenStart, &tokenEnd); |
502 if (token != ObjectPairSeparator) | 498 if (token != ObjectPairSeparator) |
503 return nullptr; | 499 return nullptr; |
504 start = tokenEnd; | 500 start = tokenEnd; |
505 | 501 |
506 OwnPtr<Value> value = buildValue(start, end, &tokenEnd, depth + 1); | 502 OwnPtr<Value> value = buildValue(start, end, &tokenEnd, depth + 1); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 const CharType* end = start + length; | 539 const CharType* end = start + length; |
544 const CharType *tokenEnd; | 540 const CharType *tokenEnd; |
545 OwnPtr<Value> value = buildValue(start, end, &tokenEnd, 0); | 541 OwnPtr<Value> value = buildValue(start, end, &tokenEnd, 0); |
546 if (!value || tokenEnd != end) | 542 if (!value || tokenEnd != end) |
547 return nullptr; | 543 return nullptr; |
548 return value.release(); | 544 return value.release(); |
549 } | 545 } |
550 | 546 |
551 } // anonymous namespace | 547 } // anonymous namespace |
552 | 548 |
553 PassOwnPtr<Value> parseJSON(const String& json) | 549 PassOwnPtr<Value> parseJSON(const String16& json) |
554 { | 550 { |
555 if (json.isEmpty()) | 551 if (json.isEmpty()) |
556 return nullptr; | 552 return nullptr; |
557 if (json.is8Bit()) | 553 if (json.is8Bit()) |
558 return parseJSONInternal(json.characters8(), json.length()); | 554 return parseJSONInternal(json.characters8(), json.length()); |
559 return parseJSONInternal(json.characters16(), json.length()); | 555 return parseJSONInternal(json.characters16(), json.length()); |
560 } | 556 } |
561 | 557 |
562 } // namespace protocol | 558 } // namespace protocol |
563 } // namespace blink | 559 } // namespace blink |
OLD | NEW |