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 |