| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/json/json_reader.h" | 5 #include "base/json/json_reader.h" |
| 6 | 6 |
| 7 #include "base/float_util.h" | 7 #include "base/float_util.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
| 11 #include "base/string_number_conversions.h" | 11 #include "base/string_number_conversions.h" |
| 12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
| 13 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
| 14 #include "base/values.h" | 14 #include "base/values.h" |
| 15 | 15 |
| 16 namespace { | 16 namespace { |
| 17 | 17 |
| 18 const wchar_t kNullString[] = L"null"; | 18 const wchar_t kNullString[] = L"null"; |
| 19 const wchar_t kTrueString[] = L"true"; | 19 const wchar_t kTrueString[] = L"true"; |
| 20 const wchar_t kFalseString[] = L"false"; | 20 const wchar_t kFalseString[] = L"false"; |
| 21 | 21 |
| 22 const int kStackLimit = 100; | 22 const int kStackLimit = 100; |
| 23 | 23 |
| 24 } // namespace | |
| 25 | |
| 26 namespace base { | |
| 27 | |
| 28 static const JSONReader::Token kInvalidToken(JSONReader::Token::INVALID_TOKEN, | |
| 29 0, 0); | |
| 30 namespace { | |
| 31 | |
| 32 // A helper method for ParseNumberToken. It reads an int from the end of | 24 // A helper method for ParseNumberToken. It reads an int from the end of |
| 33 // token. The method returns false if there is no valid integer at the end of | 25 // token. The method returns false if there is no valid integer at the end of |
| 34 // the token. | 26 // the token. |
| 35 bool ReadInt(JSONReader::Token& token, bool can_have_leading_zeros) { | 27 bool ReadInt(base::JSONReader::Token& token, bool can_have_leading_zeros) { |
| 36 wchar_t first = token.NextChar(); | 28 wchar_t first = token.NextChar(); |
| 37 int len = 0; | 29 int len = 0; |
| 38 | 30 |
| 39 // Read in more digits | 31 // Read in more digits |
| 40 wchar_t c = first; | 32 wchar_t c = first; |
| 41 while ('\0' != c && '0' <= c && c <= '9') { | 33 while ('\0' != c && '0' <= c && c <= '9') { |
| 42 ++token.length; | 34 ++token.length; |
| 43 ++len; | 35 ++len; |
| 44 c = token.NextChar(); | 36 c = token.NextChar(); |
| 45 } | 37 } |
| 46 // We need at least 1 digit. | 38 // We need at least 1 digit. |
| 47 if (len == 0) | 39 if (len == 0) |
| 48 return false; | 40 return false; |
| 49 | 41 |
| 50 if (!can_have_leading_zeros && len > 1 && '0' == first) | 42 if (!can_have_leading_zeros && len > 1 && '0' == first) |
| 51 return false; | 43 return false; |
| 52 | 44 |
| 53 return true; | 45 return true; |
| 54 } | 46 } |
| 55 | 47 |
| 56 // A helper method for ParseStringToken. It reads |digits| hex digits from the | 48 // A helper method for ParseStringToken. It reads |digits| hex digits from the |
| 57 // token. If the sequence if digits is not valid (contains other characters), | 49 // token. If the sequence if digits is not valid (contains other characters), |
| 58 // the method returns false. | 50 // the method returns false. |
| 59 bool ReadHexDigits(JSONReader::Token& token, int digits) { | 51 bool ReadHexDigits(base::JSONReader::Token& token, int digits) { |
| 60 for (int i = 1; i <= digits; ++i) { | 52 for (int i = 1; i <= digits; ++i) { |
| 61 wchar_t c = *(token.begin + token.length + i); | 53 wchar_t c = *(token.begin + token.length + i); |
| 62 if ('\0' == c) | 54 if ('\0' == c) |
| 63 return false; | 55 return false; |
| 64 if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || | 56 if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || |
| 65 ('A' <= c && c <= 'F'))) { | 57 ('A' <= c && c <= 'F'))) { |
| 66 return false; | 58 return false; |
| 67 } | 59 } |
| 68 } | 60 } |
| 69 | 61 |
| 70 token.length += digits; | 62 token.length += digits; |
| 71 return true; | 63 return true; |
| 72 } | 64 } |
| 73 | 65 |
| 74 } // namespace | 66 } // namespace |
| 75 | 67 |
| 68 namespace base { |
| 69 |
| 76 const char* JSONReader::kBadRootElementType = | 70 const char* JSONReader::kBadRootElementType = |
| 77 "Root value must be an array or object."; | 71 "Root value must be an array or object."; |
| 78 const char* JSONReader::kInvalidEscape = | 72 const char* JSONReader::kInvalidEscape = |
| 79 "Invalid escape sequence."; | 73 "Invalid escape sequence."; |
| 80 const char* JSONReader::kSyntaxError = | 74 const char* JSONReader::kSyntaxError = |
| 81 "Syntax error."; | 75 "Syntax error."; |
| 82 const char* JSONReader::kTrailingComma = | 76 const char* JSONReader::kTrailingComma = |
| 83 "Trailing comma not allowed."; | 77 "Trailing comma not allowed."; |
| 84 const char* JSONReader::kTooMuchNesting = | 78 const char* JSONReader::kTooMuchNesting = |
| 85 "Too much nesting."; | 79 "Too much nesting."; |
| 86 const char* JSONReader::kUnexpectedDataAfterRoot = | 80 const char* JSONReader::kUnexpectedDataAfterRoot = |
| 87 "Unexpected data after root element."; | 81 "Unexpected data after root element."; |
| 88 const char* JSONReader::kUnsupportedEncoding = | 82 const char* JSONReader::kUnsupportedEncoding = |
| 89 "Unsupported encoding. JSON must be UTF-8."; | 83 "Unsupported encoding. JSON must be UTF-8."; |
| 90 const char* JSONReader::kUnquotedDictionaryKey = | 84 const char* JSONReader::kUnquotedDictionaryKey = |
| 91 "Dictionary keys must be quoted."; | 85 "Dictionary keys must be quoted."; |
| 92 | 86 |
| 93 JSONReader::JSONReader() | 87 JSONReader::JSONReader() |
| 94 : start_pos_(NULL), json_pos_(NULL), stack_depth_(0), | 88 : start_pos_(NULL), |
| 89 json_pos_(NULL), |
| 90 stack_depth_(0), |
| 95 allow_trailing_comma_(false), | 91 allow_trailing_comma_(false), |
| 96 error_code_(JSON_NO_ERROR), error_line_(0), error_col_(0) {} | 92 error_code_(JSON_NO_ERROR), |
| 93 error_line_(0), |
| 94 error_col_(0) {} |
| 97 | 95 |
| 98 /* static */ | 96 // static |
| 99 Value* JSONReader::Read(const std::string& json, | 97 Value* JSONReader::Read(const std::string& json, |
| 100 bool allow_trailing_comma) { | 98 bool allow_trailing_comma) { |
| 101 return ReadAndReturnError(json, allow_trailing_comma, NULL, NULL); | 99 return ReadAndReturnError(json, allow_trailing_comma, NULL, NULL); |
| 102 } | 100 } |
| 103 | 101 |
| 104 /* static */ | 102 // static |
| 105 Value* JSONReader::ReadAndReturnError(const std::string& json, | 103 Value* JSONReader::ReadAndReturnError(const std::string& json, |
| 106 bool allow_trailing_comma, | 104 bool allow_trailing_comma, |
| 107 int* error_code_out, | 105 int* error_code_out, |
| 108 std::string* error_msg_out) { | 106 std::string* error_msg_out) { |
| 109 JSONReader reader = JSONReader(); | 107 JSONReader reader = JSONReader(); |
| 110 Value* root = reader.JsonToValue(json, true, allow_trailing_comma); | 108 Value* root = reader.JsonToValue(json, true, allow_trailing_comma); |
| 111 if (root) | 109 if (root) |
| 112 return root; | 110 return root; |
| 113 | 111 |
| 114 if (error_code_out) | 112 if (error_code_out) |
| 115 *error_code_out = reader.error_code(); | 113 *error_code_out = reader.error_code(); |
| 116 if (error_msg_out) | 114 if (error_msg_out) |
| 117 *error_msg_out = reader.GetErrorMessage(); | 115 *error_msg_out = reader.GetErrorMessage(); |
| 118 | 116 |
| 119 return NULL; | 117 return NULL; |
| 120 } | 118 } |
| 121 | 119 |
| 122 /* static */ | 120 // static |
| 123 std::string JSONReader::ErrorCodeToString(JsonParseError error_code) { | 121 std::string JSONReader::ErrorCodeToString(JsonParseError error_code) { |
| 124 switch (error_code) { | 122 switch (error_code) { |
| 125 case JSON_NO_ERROR: | 123 case JSON_NO_ERROR: |
| 126 return std::string(); | 124 return std::string(); |
| 127 case JSON_BAD_ROOT_ELEMENT_TYPE: | 125 case JSON_BAD_ROOT_ELEMENT_TYPE: |
| 128 return kBadRootElementType; | 126 return kBadRootElementType; |
| 129 case JSON_INVALID_ESCAPE: | 127 case JSON_INVALID_ESCAPE: |
| 130 return kInvalidEscape; | 128 return kInvalidEscape; |
| 131 case JSON_SYNTAX_ERROR: | 129 case JSON_SYNTAX_ERROR: |
| 132 return kSyntaxError; | 130 return kSyntaxError; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 } | 185 } |
| 188 } | 186 } |
| 189 | 187 |
| 190 // Default to calling errors "syntax errors". | 188 // Default to calling errors "syntax errors". |
| 191 if (error_code_ == 0) | 189 if (error_code_ == 0) |
| 192 SetErrorCode(JSON_SYNTAX_ERROR, json_pos_); | 190 SetErrorCode(JSON_SYNTAX_ERROR, json_pos_); |
| 193 | 191 |
| 194 return NULL; | 192 return NULL; |
| 195 } | 193 } |
| 196 | 194 |
| 197 /* static */ | 195 // static |
| 198 std::string JSONReader::FormatErrorMessage(int line, int column, | 196 std::string JSONReader::FormatErrorMessage(int line, int column, |
| 199 const std::string& description) { | 197 const std::string& description) { |
| 200 if (line || column) { | 198 if (line || column) { |
| 201 return base::StringPrintf( | 199 return base::StringPrintf( |
| 202 "Line: %i, column: %i, %s", line, column, description.c_str()); | 200 "Line: %i, column: %i, %s", line, column, description.c_str()); |
| 203 } | 201 } |
| 204 return description; | 202 return description; |
| 205 } | 203 } |
| 206 | 204 |
| 207 Value* JSONReader::BuildValue(bool is_root) { | 205 Value* JSONReader::BuildValue(bool is_root) { |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 // We just grab the number here. We validate the size in DecodeNumber. | 360 // We just grab the number here. We validate the size in DecodeNumber. |
| 363 // According to RFC4627, a valid number is: [minus] int [frac] [exp] | 361 // According to RFC4627, a valid number is: [minus] int [frac] [exp] |
| 364 Token token(Token::NUMBER, json_pos_, 0); | 362 Token token(Token::NUMBER, json_pos_, 0); |
| 365 wchar_t c = *json_pos_; | 363 wchar_t c = *json_pos_; |
| 366 if ('-' == c) { | 364 if ('-' == c) { |
| 367 ++token.length; | 365 ++token.length; |
| 368 c = token.NextChar(); | 366 c = token.NextChar(); |
| 369 } | 367 } |
| 370 | 368 |
| 371 if (!ReadInt(token, false)) | 369 if (!ReadInt(token, false)) |
| 372 return kInvalidToken; | 370 return Token::CreateInvalidToken(); |
| 373 | 371 |
| 374 // Optional fraction part | 372 // Optional fraction part |
| 375 c = token.NextChar(); | 373 c = token.NextChar(); |
| 376 if ('.' == c) { | 374 if ('.' == c) { |
| 377 ++token.length; | 375 ++token.length; |
| 378 if (!ReadInt(token, true)) | 376 if (!ReadInt(token, true)) |
| 379 return kInvalidToken; | 377 return Token::CreateInvalidToken(); |
| 380 c = token.NextChar(); | 378 c = token.NextChar(); |
| 381 } | 379 } |
| 382 | 380 |
| 383 // Optional exponent part | 381 // Optional exponent part |
| 384 if ('e' == c || 'E' == c) { | 382 if ('e' == c || 'E' == c) { |
| 385 ++token.length; | 383 ++token.length; |
| 386 c = token.NextChar(); | 384 c = token.NextChar(); |
| 387 if ('-' == c || '+' == c) { | 385 if ('-' == c || '+' == c) { |
| 388 ++token.length; | 386 ++token.length; |
| 389 c = token.NextChar(); | 387 c = token.NextChar(); |
| 390 } | 388 } |
| 391 if (!ReadInt(token, true)) | 389 if (!ReadInt(token, true)) |
| 392 return kInvalidToken; | 390 return Token::CreateInvalidToken(); |
| 393 } | 391 } |
| 394 | 392 |
| 395 return token; | 393 return token; |
| 396 } | 394 } |
| 397 | 395 |
| 398 Value* JSONReader::DecodeNumber(const Token& token) { | 396 Value* JSONReader::DecodeNumber(const Token& token) { |
| 399 const std::wstring num_string(token.begin, token.length); | 397 const std::wstring num_string(token.begin, token.length); |
| 400 | 398 |
| 401 int num_int; | 399 int num_int; |
| 402 if (StringToInt(WideToUTF8(num_string), &num_int)) | 400 if (StringToInt(WideToUTF8(num_string), &num_int)) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 415 wchar_t c = token.NextChar(); | 413 wchar_t c = token.NextChar(); |
| 416 while ('\0' != c) { | 414 while ('\0' != c) { |
| 417 if ('\\' == c) { | 415 if ('\\' == c) { |
| 418 ++token.length; | 416 ++token.length; |
| 419 c = token.NextChar(); | 417 c = token.NextChar(); |
| 420 // Make sure the escaped char is valid. | 418 // Make sure the escaped char is valid. |
| 421 switch (c) { | 419 switch (c) { |
| 422 case 'x': | 420 case 'x': |
| 423 if (!ReadHexDigits(token, 2)) { | 421 if (!ReadHexDigits(token, 2)) { |
| 424 SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length); | 422 SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length); |
| 425 return kInvalidToken; | 423 return Token::CreateInvalidToken(); |
| 426 } | 424 } |
| 427 break; | 425 break; |
| 428 case 'u': | 426 case 'u': |
| 429 if (!ReadHexDigits(token, 4)) { | 427 if (!ReadHexDigits(token, 4)) { |
| 430 SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length); | 428 SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length); |
| 431 return kInvalidToken; | 429 return Token::CreateInvalidToken(); |
| 432 } | 430 } |
| 433 break; | 431 break; |
| 434 case '\\': | 432 case '\\': |
| 435 case '/': | 433 case '/': |
| 436 case 'b': | 434 case 'b': |
| 437 case 'f': | 435 case 'f': |
| 438 case 'n': | 436 case 'n': |
| 439 case 'r': | 437 case 'r': |
| 440 case 't': | 438 case 't': |
| 441 case 'v': | 439 case 'v': |
| 442 case '"': | 440 case '"': |
| 443 break; | 441 break; |
| 444 default: | 442 default: |
| 445 SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length); | 443 SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length); |
| 446 return kInvalidToken; | 444 return Token::CreateInvalidToken(); |
| 447 } | 445 } |
| 448 } else if ('"' == c) { | 446 } else if ('"' == c) { |
| 449 ++token.length; | 447 ++token.length; |
| 450 return token; | 448 return token; |
| 451 } | 449 } |
| 452 ++token.length; | 450 ++token.length; |
| 453 c = token.NextChar(); | 451 c = token.NextChar(); |
| 454 } | 452 } |
| 455 return kInvalidToken; | 453 return Token::CreateInvalidToken(); |
| 456 } | 454 } |
| 457 | 455 |
| 458 Value* JSONReader::DecodeString(const Token& token) { | 456 Value* JSONReader::DecodeString(const Token& token) { |
| 459 std::wstring decoded_str; | 457 std::wstring decoded_str; |
| 460 decoded_str.reserve(token.length - 2); | 458 decoded_str.reserve(token.length - 2); |
| 461 | 459 |
| 462 for (int i = 1; i < token.length - 1; ++i) { | 460 for (int i = 1; i < token.length - 1; ++i) { |
| 463 wchar_t c = *(token.begin + i); | 461 wchar_t c = *(token.begin + i); |
| 464 if ('\\' == c) { | 462 if ('\\' == c) { |
| 465 ++i; | 463 ++i; |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 ++column_number; | 661 ++column_number; |
| 664 } | 662 } |
| 665 } | 663 } |
| 666 | 664 |
| 667 error_line_ = line_number; | 665 error_line_ = line_number; |
| 668 error_col_ = column_number; | 666 error_col_ = column_number; |
| 669 error_code_ = error; | 667 error_code_ = error; |
| 670 } | 668 } |
| 671 | 669 |
| 672 } // namespace base | 670 } // namespace base |
| OLD | NEW |