| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 if (!decodeString(start, end, &buffer)) | 334 if (!decodeString(start, end, &buffer)) |
| 335 return false; | 335 return false; |
| 336 *output = buffer.toString(); | 336 *output = buffer.toString(); |
| 337 return true; | 337 return true; |
| 338 } | 338 } |
| 339 | 339 |
| 340 template<typename CharType> | 340 template<typename CharType> |
| 341 PassRefPtr<JSONValue> buildValue(const CharType* start, const CharType* end, con
st CharType** valueTokenEnd, int depth) | 341 PassRefPtr<JSONValue> buildValue(const CharType* start, const CharType* end, con
st CharType** valueTokenEnd, int depth) |
| 342 { | 342 { |
| 343 if (depth > stackLimit) | 343 if (depth > stackLimit) |
| 344 return 0; | 344 return nullptr; |
| 345 | 345 |
| 346 RefPtr<JSONValue> result; | 346 RefPtr<JSONValue> result; |
| 347 const CharType* tokenStart; | 347 const CharType* tokenStart; |
| 348 const CharType* tokenEnd; | 348 const CharType* tokenEnd; |
| 349 Token token = parseToken(start, end, &tokenStart, &tokenEnd); | 349 Token token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 350 switch (token) { | 350 switch (token) { |
| 351 case InvalidToken: | 351 case InvalidToken: |
| 352 return 0; | 352 return nullptr; |
| 353 case NullToken: | 353 case NullToken: |
| 354 result = JSONValue::null(); | 354 result = JSONValue::null(); |
| 355 break; | 355 break; |
| 356 case BoolTrue: | 356 case BoolTrue: |
| 357 result = JSONBasicValue::create(true); | 357 result = JSONBasicValue::create(true); |
| 358 break; | 358 break; |
| 359 case BoolFalse: | 359 case BoolFalse: |
| 360 result = JSONBasicValue::create(false); | 360 result = JSONBasicValue::create(false); |
| 361 break; | 361 break; |
| 362 case Number: { | 362 case Number: { |
| 363 bool ok; | 363 bool ok; |
| 364 double value = charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok
); | 364 double value = charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok
); |
| 365 if (!ok) | 365 if (!ok) |
| 366 return 0; | 366 return nullptr; |
| 367 result = JSONBasicValue::create(value); | 367 result = JSONBasicValue::create(value); |
| 368 break; | 368 break; |
| 369 } | 369 } |
| 370 case StringLiteral: { | 370 case StringLiteral: { |
| 371 String value; | 371 String value; |
| 372 bool ok = decodeString(tokenStart + 1, tokenEnd - 1, &value); | 372 bool ok = decodeString(tokenStart + 1, tokenEnd - 1, &value); |
| 373 if (!ok) | 373 if (!ok) |
| 374 return 0; | 374 return nullptr; |
| 375 result = JSONString::create(value); | 375 result = JSONString::create(value); |
| 376 break; | 376 break; |
| 377 } | 377 } |
| 378 case ArrayBegin: { | 378 case ArrayBegin: { |
| 379 RefPtr<JSONArray> array = JSONArray::create(); | 379 RefPtr<JSONArray> array = JSONArray::create(); |
| 380 start = tokenEnd; | 380 start = tokenEnd; |
| 381 token = parseToken(start, end, &tokenStart, &tokenEnd); | 381 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 382 while (token != ArrayEnd) { | 382 while (token != ArrayEnd) { |
| 383 RefPtr<JSONValue> arrayNode = buildValue(start, end, &tokenEnd, dept
h + 1); | 383 RefPtr<JSONValue> arrayNode = buildValue(start, end, &tokenEnd, dept
h + 1); |
| 384 if (!arrayNode) | 384 if (!arrayNode) |
| 385 return 0; | 385 return nullptr; |
| 386 array->pushValue(arrayNode); | 386 array->pushValue(arrayNode); |
| 387 | 387 |
| 388 // After a list value, we expect a comma or the end of the list. | 388 // After a list value, we expect a comma or the end of the list. |
| 389 start = tokenEnd; | 389 start = tokenEnd; |
| 390 token = parseToken(start, end, &tokenStart, &tokenEnd); | 390 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 391 if (token == ListSeparator) { | 391 if (token == ListSeparator) { |
| 392 start = tokenEnd; | 392 start = tokenEnd; |
| 393 token = parseToken(start, end, &tokenStart, &tokenEnd); | 393 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 394 if (token == ArrayEnd) | 394 if (token == ArrayEnd) |
| 395 return 0; | 395 return nullptr; |
| 396 } else if (token != ArrayEnd) { | 396 } else if (token != ArrayEnd) { |
| 397 // Unexpected value after list value. Bail out. | 397 // Unexpected value after list value. Bail out. |
| 398 return 0; | 398 return nullptr; |
| 399 } | 399 } |
| 400 } | 400 } |
| 401 if (token != ArrayEnd) | 401 if (token != ArrayEnd) |
| 402 return 0; | 402 return nullptr; |
| 403 result = array.release(); | 403 result = array.release(); |
| 404 break; | 404 break; |
| 405 } | 405 } |
| 406 case ObjectBegin: { | 406 case ObjectBegin: { |
| 407 RefPtr<JSONObject> object = JSONObject::create(); | 407 RefPtr<JSONObject> object = JSONObject::create(); |
| 408 start = tokenEnd; | 408 start = tokenEnd; |
| 409 token = parseToken(start, end, &tokenStart, &tokenEnd); | 409 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 410 while (token != ObjectEnd) { | 410 while (token != ObjectEnd) { |
| 411 if (token != StringLiteral) | 411 if (token != StringLiteral) |
| 412 return 0; | 412 return nullptr; |
| 413 String key; | 413 String key; |
| 414 if (!decodeString(tokenStart + 1, tokenEnd - 1, &key)) | 414 if (!decodeString(tokenStart + 1, tokenEnd - 1, &key)) |
| 415 return 0; | 415 return nullptr; |
| 416 start = tokenEnd; | 416 start = tokenEnd; |
| 417 | 417 |
| 418 token = parseToken(start, end, &tokenStart, &tokenEnd); | 418 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 419 if (token != ObjectPairSeparator) | 419 if (token != ObjectPairSeparator) |
| 420 return 0; | 420 return nullptr; |
| 421 start = tokenEnd; | 421 start = tokenEnd; |
| 422 | 422 |
| 423 RefPtr<JSONValue> value = buildValue(start, end, &tokenEnd, depth +
1); | 423 RefPtr<JSONValue> value = buildValue(start, end, &tokenEnd, depth +
1); |
| 424 if (!value) | 424 if (!value) |
| 425 return 0; | 425 return nullptr; |
| 426 object->setValue(key, value); | 426 object->setValue(key, value); |
| 427 start = tokenEnd; | 427 start = tokenEnd; |
| 428 | 428 |
| 429 // After a key/value pair, we expect a comma or the end of the | 429 // After a key/value pair, we expect a comma or the end of the |
| 430 // object. | 430 // object. |
| 431 token = parseToken(start, end, &tokenStart, &tokenEnd); | 431 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 432 if (token == ListSeparator) { | 432 if (token == ListSeparator) { |
| 433 start = tokenEnd; | 433 start = tokenEnd; |
| 434 token = parseToken(start, end, &tokenStart, &tokenEnd); | 434 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 435 if (token == ObjectEnd) | 435 if (token == ObjectEnd) |
| 436 return 0; | 436 return nullptr; |
| 437 } else if (token != ObjectEnd) { | 437 } else if (token != ObjectEnd) { |
| 438 // Unexpected value after last object value. Bail out. | 438 // Unexpected value after last object value. Bail out. |
| 439 return 0; | 439 return nullptr; |
| 440 } | 440 } |
| 441 } | 441 } |
| 442 if (token != ObjectEnd) | 442 if (token != ObjectEnd) |
| 443 return 0; | 443 return nullptr; |
| 444 result = object.release(); | 444 result = object.release(); |
| 445 break; | 445 break; |
| 446 } | 446 } |
| 447 | 447 |
| 448 default: | 448 default: |
| 449 // We got a token that's not a value. | 449 // We got a token that's not a value. |
| 450 return 0; | 450 return nullptr; |
| 451 } | 451 } |
| 452 *valueTokenEnd = tokenEnd; | 452 *valueTokenEnd = tokenEnd; |
| 453 return result.release(); | 453 return result.release(); |
| 454 } | 454 } |
| 455 | 455 |
| 456 template<typename CharType> | 456 template<typename CharType> |
| 457 PassRefPtr<JSONValue> parseJSONInternal(const CharType* start, unsigned length) | 457 PassRefPtr<JSONValue> parseJSONInternal(const CharType* start, unsigned length) |
| 458 { | 458 { |
| 459 const CharType* end = start + length; | 459 const CharType* end = start + length; |
| 460 const CharType *tokenEnd; | 460 const CharType *tokenEnd; |
| 461 RefPtr<JSONValue> value = buildValue(start, end, &tokenEnd, 0); | 461 RefPtr<JSONValue> value = buildValue(start, end, &tokenEnd, 0); |
| 462 if (!value || tokenEnd != end) | 462 if (!value || tokenEnd != end) |
| 463 return 0; | 463 return nullptr; |
| 464 return value.release(); | 464 return value.release(); |
| 465 } | 465 } |
| 466 | 466 |
| 467 } // anonymous namespace | 467 } // anonymous namespace |
| 468 | 468 |
| 469 PassRefPtr<JSONValue> parseJSON(const String& json) | 469 PassRefPtr<JSONValue> parseJSON(const String& json) |
| 470 { | 470 { |
| 471 if (json.isEmpty()) | 471 if (json.isEmpty()) |
| 472 return 0; | 472 return nullptr; |
| 473 if (json.is8Bit()) | 473 if (json.is8Bit()) |
| 474 return parseJSONInternal(json.characters8(), json.length()); | 474 return parseJSONInternal(json.characters8(), json.length()); |
| 475 return parseJSONInternal(json.characters16(), json.length()); | 475 return parseJSONInternal(json.characters16(), json.length()); |
| 476 } | 476 } |
| 477 | 477 |
| 478 } // namespace WebCore | 478 } // namespace WebCore |
| OLD | NEW |