| 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 namespace blink { | 5 {% for namespace in config.protocol.namespace %} |
| 6 namespace protocol { | 6 namespace {{namespace}} { |
| 7 {% endfor %} |
| 7 | 8 |
| 8 namespace { | 9 namespace { |
| 9 | 10 |
| 10 const int stackLimit = 1000; | 11 const int stackLimit = 1000; |
| 11 | 12 |
| 12 enum Token { | 13 enum Token { |
| 13 ObjectBegin, | 14 ObjectBegin, |
| 14 ObjectEnd, | 15 ObjectEnd, |
| 15 ArrayBegin, | 16 ArrayBegin, |
| 16 ArrayEnd, | 17 ArrayEnd, |
| 17 StringLiteral, | 18 StringLiteral, |
| 18 Number, | 19 Number, |
| 19 BoolTrue, | 20 BoolTrue, |
| 20 BoolFalse, | 21 BoolFalse, |
| 21 NullToken, | 22 NullToken, |
| 22 ListSeparator, | 23 ListSeparator, |
| 23 ObjectPairSeparator, | 24 ObjectPairSeparator, |
| 24 InvalidToken, | 25 InvalidToken, |
| 25 }; | 26 }; |
| 26 | 27 |
| 27 const char* const nullString = "null"; | 28 const char* const nullString = "null"; |
| 28 const char* const trueString = "true"; | 29 const char* const trueString = "true"; |
| 29 const char* const falseString = "false"; | 30 const char* const falseString = "false"; |
| 30 | 31 |
| 32 bool isASCII(UChar c) |
| 33 { |
| 34 return !(c & ~0x7F); |
| 35 } |
| 36 |
| 37 bool isSpaceOrNewLine(UChar c) |
| 38 { |
| 39 return isASCII(c) && c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); |
| 40 } |
| 41 |
| 42 double charactersToDouble(const UChar* characters, size_t length, bool* ok) |
| 43 { |
| 44 std::vector<char> buffer; |
| 45 buffer.reserve(length + 1); |
| 46 for (size_t i = 0; i < length; ++i) { |
| 47 if (!isASCII(characters[i])) { |
| 48 *ok = false; |
| 49 return 0; |
| 50 } |
| 51 buffer.push_back(static_cast<char>(characters[i])); |
| 52 } |
| 53 buffer.push_back('\0'); |
| 54 |
| 55 char* endptr; |
| 56 double result = std::strtod(buffer.data(), &endptr); |
| 57 *ok = !(*endptr); |
| 58 return result; |
| 59 } |
| 60 |
| 31 bool parseConstToken(const UChar* start, const UChar* end, const UChar** tokenEn
d, const char* token) | 61 bool parseConstToken(const UChar* start, const UChar* end, const UChar** tokenEn
d, const char* token) |
| 32 { | 62 { |
| 33 while (start < end && *token != '\0' && *start++ == *token++) { } | 63 while (start < end && *token != '\0' && *start++ == *token++) { } |
| 34 if (*token != '\0') | 64 if (*token != '\0') |
| 35 return false; | 65 return false; |
| 36 *tokenEnd = start; | 66 *tokenEnd = start; |
| 37 return true; | 67 return true; |
| 38 } | 68 } |
| 39 | 69 |
| 40 bool readInt(const UChar* start, const UChar* end, const UChar** tokenEnd, bool
canHaveLeadingZeros) | 70 bool readInt(const UChar* start, const UChar* end, const UChar** tokenEnd, bool
canHaveLeadingZeros) |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 // Block comment must close before end-of-input. | 218 // Block comment must close before end-of-input. |
| 189 return false; | 219 return false; |
| 190 } | 220 } |
| 191 | 221 |
| 192 return false; | 222 return false; |
| 193 } | 223 } |
| 194 | 224 |
| 195 void skipWhitespaceAndComments(const UChar* start, const UChar* end, const UChar
** whitespaceEnd) | 225 void skipWhitespaceAndComments(const UChar* start, const UChar* end, const UChar
** whitespaceEnd) |
| 196 { | 226 { |
| 197 while (start < end) { | 227 while (start < end) { |
| 198 if (String16::isSpaceOrNewLine(*start)) { | 228 if (isSpaceOrNewLine(*start)) { |
| 199 ++start; | 229 ++start; |
| 200 } else if (*start == '/') { | 230 } else if (*start == '/') { |
| 201 const UChar* commentEnd; | 231 const UChar* commentEnd; |
| 202 if (!skipComment(start, end, &commentEnd)) | 232 if (!skipComment(start, end, &commentEnd)) |
| 203 break; | 233 break; |
| 204 start = commentEnd; | 234 start = commentEnd; |
| 205 } else { | 235 } else { |
| 206 break; | 236 break; |
| 207 } | 237 } |
| 208 } | 238 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 if ('0' <= c && c <= '9') | 305 if ('0' <= c && c <= '9') |
| 276 return c - '0'; | 306 return c - '0'; |
| 277 if ('A' <= c && c <= 'F') | 307 if ('A' <= c && c <= 'F') |
| 278 return c - 'A' + 10; | 308 return c - 'A' + 10; |
| 279 if ('a' <= c && c <= 'f') | 309 if ('a' <= c && c <= 'f') |
| 280 return c - 'a' + 10; | 310 return c - 'a' + 10; |
| 281 NOTREACHED(); | 311 NOTREACHED(); |
| 282 return 0; | 312 return 0; |
| 283 } | 313 } |
| 284 | 314 |
| 285 bool decodeString(const UChar* start, const UChar* end, String16Builder* output) | 315 bool decodeString(const UChar* start, const UChar* end, StringBuilder* output) |
| 286 { | 316 { |
| 287 while (start < end) { | 317 while (start < end) { |
| 288 UChar c = *start++; | 318 UChar c = *start++; |
| 289 if ('\\' != c) { | 319 if ('\\' != c) { |
| 290 output->append(c); | 320 output->append(c); |
| 291 continue; | 321 continue; |
| 292 } | 322 } |
| 293 c = *start++; | 323 c = *start++; |
| 294 | 324 |
| 295 if (c == 'x') { | 325 if (c == 'x') { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 start += 4; | 358 start += 4; |
| 329 break; | 359 break; |
| 330 default: | 360 default: |
| 331 return false; | 361 return false; |
| 332 } | 362 } |
| 333 output->append(c); | 363 output->append(c); |
| 334 } | 364 } |
| 335 return true; | 365 return true; |
| 336 } | 366 } |
| 337 | 367 |
| 338 bool decodeString(const UChar* start, const UChar* end, String16* output) | 368 bool decodeString(const UChar* start, const UChar* end, String* output) |
| 339 { | 369 { |
| 340 if (start == end) { | 370 if (start == end) { |
| 341 *output = ""; | 371 *output = ""; |
| 342 return true; | 372 return true; |
| 343 } | 373 } |
| 344 if (start > end) | 374 if (start > end) |
| 345 return false; | 375 return false; |
| 346 String16Builder buffer; | 376 StringBuilder buffer; |
| 347 buffer.reserveCapacity(end - start); | 377 StringUtil::builderReserve(buffer, end - start); |
| 348 if (!decodeString(start, end, &buffer)) | 378 if (!decodeString(start, end, &buffer)) |
| 349 return false; | 379 return false; |
| 350 *output = buffer.toString(); | 380 *output = buffer.toString(); |
| 351 return true; | 381 return true; |
| 352 } | 382 } |
| 353 | 383 |
| 354 std::unique_ptr<Value> buildValue(const UChar* start, const UChar* end, const UC
har** valueTokenEnd, int depth) | 384 std::unique_ptr<Value> buildValue(const UChar* start, const UChar* end, const UC
har** valueTokenEnd, int depth) |
| 355 { | 385 { |
| 356 if (depth > stackLimit) | 386 if (depth > stackLimit) |
| 357 return nullptr; | 387 return nullptr; |
| 358 | 388 |
| 359 std::unique_ptr<Value> result; | 389 std::unique_ptr<Value> result; |
| 360 const UChar* tokenStart; | 390 const UChar* tokenStart; |
| 361 const UChar* tokenEnd; | 391 const UChar* tokenEnd; |
| 362 Token token = parseToken(start, end, &tokenStart, &tokenEnd); | 392 Token token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 363 switch (token) { | 393 switch (token) { |
| 364 case InvalidToken: | 394 case InvalidToken: |
| 365 return nullptr; | 395 return nullptr; |
| 366 case NullToken: | 396 case NullToken: |
| 367 result = Value::null(); | 397 result = Value::null(); |
| 368 break; | 398 break; |
| 369 case BoolTrue: | 399 case BoolTrue: |
| 370 result = FundamentalValue::create(true); | 400 result = FundamentalValue::create(true); |
| 371 break; | 401 break; |
| 372 case BoolFalse: | 402 case BoolFalse: |
| 373 result = FundamentalValue::create(false); | 403 result = FundamentalValue::create(false); |
| 374 break; | 404 break; |
| 375 case Number: { | 405 case Number: { |
| 376 bool ok; | 406 bool ok; |
| 377 double value = String16::charactersToDouble(tokenStart, tokenEnd - token
Start, &ok); | 407 double value = charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok
); |
| 378 if (!ok) | 408 if (!ok) |
| 379 return nullptr; | 409 return nullptr; |
| 380 int number = static_cast<int>(value); | 410 int number = static_cast<int>(value); |
| 381 if (number == value) | 411 if (number == value) |
| 382 result = FundamentalValue::create(number); | 412 result = FundamentalValue::create(number); |
| 383 else | 413 else |
| 384 result = FundamentalValue::create(value); | 414 result = FundamentalValue::create(value); |
| 385 break; | 415 break; |
| 386 } | 416 } |
| 387 case StringLiteral: { | 417 case StringLiteral: { |
| 388 String16 value; | 418 String value; |
| 389 bool ok = decodeString(tokenStart + 1, tokenEnd - 1, &value); | 419 bool ok = decodeString(tokenStart + 1, tokenEnd - 1, &value); |
| 390 if (!ok) | 420 if (!ok) |
| 391 return nullptr; | 421 return nullptr; |
| 392 result = StringValue::create(value); | 422 result = StringValue::create(value); |
| 393 break; | 423 break; |
| 394 } | 424 } |
| 395 case ArrayBegin: { | 425 case ArrayBegin: { |
| 396 std::unique_ptr<ListValue> array = ListValue::create(); | 426 std::unique_ptr<ListValue> array = ListValue::create(); |
| 397 start = tokenEnd; | 427 start = tokenEnd; |
| 398 token = parseToken(start, end, &tokenStart, &tokenEnd); | 428 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 420 result = std::move(array); | 450 result = std::move(array); |
| 421 break; | 451 break; |
| 422 } | 452 } |
| 423 case ObjectBegin: { | 453 case ObjectBegin: { |
| 424 std::unique_ptr<DictionaryValue> object = DictionaryValue::create(); | 454 std::unique_ptr<DictionaryValue> object = DictionaryValue::create(); |
| 425 start = tokenEnd; | 455 start = tokenEnd; |
| 426 token = parseToken(start, end, &tokenStart, &tokenEnd); | 456 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 427 while (token != ObjectEnd) { | 457 while (token != ObjectEnd) { |
| 428 if (token != StringLiteral) | 458 if (token != StringLiteral) |
| 429 return nullptr; | 459 return nullptr; |
| 430 String16 key; | 460 String key; |
| 431 if (!decodeString(tokenStart + 1, tokenEnd - 1, &key)) | 461 if (!decodeString(tokenStart + 1, tokenEnd - 1, &key)) |
| 432 return nullptr; | 462 return nullptr; |
| 433 start = tokenEnd; | 463 start = tokenEnd; |
| 434 | 464 |
| 435 token = parseToken(start, end, &tokenStart, &tokenEnd); | 465 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 436 if (token != ObjectPairSeparator) | 466 if (token != ObjectPairSeparator) |
| 437 return nullptr; | 467 return nullptr; |
| 438 start = tokenEnd; | 468 start = tokenEnd; |
| 439 | 469 |
| 440 std::unique_ptr<Value> value = buildValue(start, end, &tokenEnd, dep
th + 1); | 470 std::unique_ptr<Value> value = buildValue(start, end, &tokenEnd, dep
th + 1); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 const UChar* end = start + length; | 506 const UChar* end = start + length; |
| 477 const UChar *tokenEnd; | 507 const UChar *tokenEnd; |
| 478 std::unique_ptr<Value> value = buildValue(start, end, &tokenEnd, 0); | 508 std::unique_ptr<Value> value = buildValue(start, end, &tokenEnd, 0); |
| 479 if (!value || tokenEnd != end) | 509 if (!value || tokenEnd != end) |
| 480 return nullptr; | 510 return nullptr; |
| 481 return value; | 511 return value; |
| 482 } | 512 } |
| 483 | 513 |
| 484 } // anonymous namespace | 514 } // anonymous namespace |
| 485 | 515 |
| 486 std::unique_ptr<Value> parseJSON(const String16& json) | 516 std::unique_ptr<Value> parseJSON(const String& json) |
| 487 { | 517 { |
| 488 if (json.isEmpty()) | 518 const UChar* characters = nullptr; |
| 519 size_t length = 0; |
| 520 StringUtil::toCharacters(json, &characters, &length); |
| 521 if (!length) |
| 489 return nullptr; | 522 return nullptr; |
| 490 return parseJSONInternal(json.characters16(), json.length()); | 523 return parseJSONInternal(characters, length); |
| 491 } | 524 } |
| 492 | 525 |
| 493 } // namespace protocol | 526 {% for namespace in config.protocol.namespace %} |
| 494 } // namespace blink | 527 } // namespace {{namespace}} |
| 528 {% endfor %} |
| OLD | NEW |