| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/scoped_ptr.h" | 9 #include "base/scoped_ptr.h" |
| 10 #include "base/string_number_conversions.h" | 10 #include "base/string_number_conversions.h" |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 "Trailing comma not allowed."; | 74 "Trailing comma not allowed."; |
| 75 const char* JSONReader::kTooMuchNesting = | 75 const char* JSONReader::kTooMuchNesting = |
| 76 "Too much nesting."; | 76 "Too much nesting."; |
| 77 const char* JSONReader::kUnexpectedDataAfterRoot = | 77 const char* JSONReader::kUnexpectedDataAfterRoot = |
| 78 "Unexpected data after root element."; | 78 "Unexpected data after root element."; |
| 79 const char* JSONReader::kUnsupportedEncoding = | 79 const char* JSONReader::kUnsupportedEncoding = |
| 80 "Unsupported encoding. JSON must be UTF-8."; | 80 "Unsupported encoding. JSON must be UTF-8."; |
| 81 const char* JSONReader::kUnquotedDictionaryKey = | 81 const char* JSONReader::kUnquotedDictionaryKey = |
| 82 "Dictionary keys must be quoted."; | 82 "Dictionary keys must be quoted."; |
| 83 | 83 |
| 84 JSONReader::JSONReader() |
| 85 : start_pos_(NULL), json_pos_(NULL), stack_depth_(0), |
| 86 allow_trailing_comma_(false), |
| 87 error_code_(JSON_NO_ERROR), error_line_(0), error_col_(0) {} |
| 88 |
| 84 /* static */ | 89 /* static */ |
| 85 Value* JSONReader::Read(const std::string& json, | 90 Value* JSONReader::Read(const std::string& json, |
| 86 bool allow_trailing_comma) { | 91 bool allow_trailing_comma) { |
| 87 return ReadAndReturnError(json, allow_trailing_comma, NULL, NULL); | 92 return ReadAndReturnError(json, allow_trailing_comma, NULL, NULL); |
| 88 } | 93 } |
| 89 | 94 |
| 90 /* static */ | 95 /* static */ |
| 91 Value* JSONReader::ReadAndReturnError(const std::string& json, | 96 Value* JSONReader::ReadAndReturnError(const std::string& json, |
| 92 bool allow_trailing_comma, | 97 bool allow_trailing_comma, |
| 93 int* error_code_out, | 98 int* error_code_out, |
| 94 std::string* error_msg_out) { | 99 std::string* error_msg_out) { |
| 95 JSONReader reader = JSONReader(); | 100 JSONReader reader = JSONReader(); |
| 96 Value* root = reader.JsonToValue(json, true, allow_trailing_comma); | 101 Value* root = reader.JsonToValue(json, true, allow_trailing_comma); |
| 97 if (root) | 102 if (root) |
| 98 return root; | 103 return root; |
| 99 | 104 |
| 100 if (error_code_out) | 105 if (error_code_out) |
| 101 *error_code_out = reader.error_code(); | 106 *error_code_out = reader.error_code(); |
| 102 if (error_msg_out) | 107 if (error_msg_out) |
| 103 *error_msg_out = reader.GetErrorMessage(); | 108 *error_msg_out = reader.GetErrorMessage(); |
| 104 | 109 |
| 105 return NULL; | 110 return NULL; |
| 106 } | 111 } |
| 107 | 112 |
| 108 /* static */ | 113 /* static */ |
| 109 std::string JSONReader::FormatErrorMessage(int line, int column, | |
| 110 const std::string& description) { | |
| 111 if (line || column) { | |
| 112 return StringPrintf("Line: %i, column: %i, %s", | |
| 113 line, column, description.c_str()); | |
| 114 } | |
| 115 return description; | |
| 116 } | |
| 117 | |
| 118 /* static */ | |
| 119 std::string JSONReader::ErrorCodeToString(JsonParseError error_code) { | 114 std::string JSONReader::ErrorCodeToString(JsonParseError error_code) { |
| 120 switch (error_code) { | 115 switch (error_code) { |
| 121 case JSON_NO_ERROR: | 116 case JSON_NO_ERROR: |
| 122 return std::string(); | 117 return std::string(); |
| 123 case JSON_BAD_ROOT_ELEMENT_TYPE: | 118 case JSON_BAD_ROOT_ELEMENT_TYPE: |
| 124 return kBadRootElementType; | 119 return kBadRootElementType; |
| 125 case JSON_INVALID_ESCAPE: | 120 case JSON_INVALID_ESCAPE: |
| 126 return kInvalidEscape; | 121 return kInvalidEscape; |
| 127 case JSON_SYNTAX_ERROR: | 122 case JSON_SYNTAX_ERROR: |
| 128 return kSyntaxError; | 123 return kSyntaxError; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 140 NOTREACHED(); | 135 NOTREACHED(); |
| 141 return std::string(); | 136 return std::string(); |
| 142 } | 137 } |
| 143 } | 138 } |
| 144 | 139 |
| 145 std::string JSONReader::GetErrorMessage() const { | 140 std::string JSONReader::GetErrorMessage() const { |
| 146 return FormatErrorMessage(error_line_, error_col_, | 141 return FormatErrorMessage(error_line_, error_col_, |
| 147 ErrorCodeToString(error_code_)); | 142 ErrorCodeToString(error_code_)); |
| 148 } | 143 } |
| 149 | 144 |
| 150 JSONReader::JSONReader() | |
| 151 : start_pos_(NULL), json_pos_(NULL), stack_depth_(0), | |
| 152 allow_trailing_comma_(false), | |
| 153 error_code_(JSON_NO_ERROR), error_line_(0), error_col_(0) {} | |
| 154 | |
| 155 Value* JSONReader::JsonToValue(const std::string& json, bool check_root, | 145 Value* JSONReader::JsonToValue(const std::string& json, bool check_root, |
| 156 bool allow_trailing_comma) { | 146 bool allow_trailing_comma) { |
| 157 // The input must be in UTF-8. | 147 // The input must be in UTF-8. |
| 158 if (!IsStringUTF8(json.c_str())) { | 148 if (!IsStringUTF8(json.c_str())) { |
| 159 error_code_ = JSON_UNSUPPORTED_ENCODING; | 149 error_code_ = JSON_UNSUPPORTED_ENCODING; |
| 160 return NULL; | 150 return NULL; |
| 161 } | 151 } |
| 162 | 152 |
| 163 // The conversion from UTF8 to wstring removes null bytes for us | 153 // The conversion from UTF8 to wstring removes null bytes for us |
| 164 // (a good thing). | 154 // (a good thing). |
| (...skipping 23 matching lines...) Expand all Loading... |
| 188 } | 178 } |
| 189 } | 179 } |
| 190 | 180 |
| 191 // Default to calling errors "syntax errors". | 181 // Default to calling errors "syntax errors". |
| 192 if (error_code_ == 0) | 182 if (error_code_ == 0) |
| 193 SetErrorCode(JSON_SYNTAX_ERROR, json_pos_); | 183 SetErrorCode(JSON_SYNTAX_ERROR, json_pos_); |
| 194 | 184 |
| 195 return NULL; | 185 return NULL; |
| 196 } | 186 } |
| 197 | 187 |
| 188 /* static */ |
| 189 std::string JSONReader::FormatErrorMessage(int line, int column, |
| 190 const std::string& description) { |
| 191 if (line || column) { |
| 192 return StringPrintf("Line: %i, column: %i, %s", |
| 193 line, column, description.c_str()); |
| 194 } |
| 195 return description; |
| 196 } |
| 197 |
| 198 Value* JSONReader::BuildValue(bool is_root) { | 198 Value* JSONReader::BuildValue(bool is_root) { |
| 199 ++stack_depth_; | 199 ++stack_depth_; |
| 200 if (stack_depth_ > kStackLimit) { | 200 if (stack_depth_ > kStackLimit) { |
| 201 SetErrorCode(JSON_TOO_MUCH_NESTING, json_pos_); | 201 SetErrorCode(JSON_TOO_MUCH_NESTING, json_pos_); |
| 202 return NULL; | 202 return NULL; |
| 203 } | 203 } |
| 204 | 204 |
| 205 Token token = ParseToken(); | 205 Token token = ParseToken(); |
| 206 // The root token must be an array or an object. | 206 // The root token must be an array or an object. |
| 207 if (is_root && token.type != Token::OBJECT_BEGIN && | 207 if (is_root && token.type != Token::OBJECT_BEGIN && |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 token = ParseNumberToken(); | 573 token = ParseNumberToken(); |
| 574 break; | 574 break; |
| 575 | 575 |
| 576 case '"': | 576 case '"': |
| 577 token = ParseStringToken(); | 577 token = ParseStringToken(); |
| 578 break; | 578 break; |
| 579 } | 579 } |
| 580 return token; | 580 return token; |
| 581 } | 581 } |
| 582 | 582 |
| 583 bool JSONReader::NextStringMatch(const std::wstring& str) { | |
| 584 for (size_t i = 0; i < str.length(); ++i) { | |
| 585 if ('\0' == *json_pos_) | |
| 586 return false; | |
| 587 if (*(json_pos_ + i) != str[i]) | |
| 588 return false; | |
| 589 } | |
| 590 return true; | |
| 591 } | |
| 592 | |
| 593 void JSONReader::EatWhitespaceAndComments() { | 583 void JSONReader::EatWhitespaceAndComments() { |
| 594 while ('\0' != *json_pos_) { | 584 while ('\0' != *json_pos_) { |
| 595 switch (*json_pos_) { | 585 switch (*json_pos_) { |
| 596 case ' ': | 586 case ' ': |
| 597 case '\n': | 587 case '\n': |
| 598 case '\r': | 588 case '\r': |
| 599 case '\t': | 589 case '\t': |
| 600 ++json_pos_; | 590 ++json_pos_; |
| 601 break; | 591 break; |
| 602 case '/': | 592 case '/': |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 return true; | 628 return true; |
| 639 } | 629 } |
| 640 ++json_pos_; | 630 ++json_pos_; |
| 641 } | 631 } |
| 642 } else { | 632 } else { |
| 643 return false; | 633 return false; |
| 644 } | 634 } |
| 645 return true; | 635 return true; |
| 646 } | 636 } |
| 647 | 637 |
| 638 bool JSONReader::NextStringMatch(const std::wstring& str) { |
| 639 for (size_t i = 0; i < str.length(); ++i) { |
| 640 if ('\0' == *json_pos_) |
| 641 return false; |
| 642 if (*(json_pos_ + i) != str[i]) |
| 643 return false; |
| 644 } |
| 645 return true; |
| 646 } |
| 647 |
| 648 void JSONReader::SetErrorCode(JsonParseError error, | 648 void JSONReader::SetErrorCode(JsonParseError error, |
| 649 const wchar_t* error_pos) { | 649 const wchar_t* error_pos) { |
| 650 int line_number = 1; | 650 int line_number = 1; |
| 651 int column_number = 1; | 651 int column_number = 1; |
| 652 | 652 |
| 653 // Figure out the line and column the error occured at. | 653 // Figure out the line and column the error occured at. |
| 654 for (const wchar_t* pos = start_pos_; pos != error_pos; ++pos) { | 654 for (const wchar_t* pos = start_pos_; pos != error_pos; ++pos) { |
| 655 if (*pos == '\0') { | 655 if (*pos == '\0') { |
| 656 NOTREACHED(); | 656 NOTREACHED(); |
| 657 return; | 657 return; |
| 658 } | 658 } |
| 659 | 659 |
| 660 if (*pos == '\n') { | 660 if (*pos == '\n') { |
| 661 ++line_number; | 661 ++line_number; |
| 662 column_number = 1; | 662 column_number = 1; |
| 663 } else { | 663 } else { |
| 664 ++column_number; | 664 ++column_number; |
| 665 } | 665 } |
| 666 } | 666 } |
| 667 | 667 |
| 668 error_line_ = line_number; | 668 error_line_ = line_number; |
| 669 error_col_ = column_number; | 669 error_col_ = column_number; |
| 670 error_code_ = error; | 670 error_code_ = error; |
| 671 } | 671 } |
| 672 | 672 |
| 673 } // namespace base | 673 } // namespace base |
| OLD | NEW |