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 |