Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: base/json/json_reader.cc

Issue 7756022: base/json: Get rid of static initializer in JSONReader. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/json/json_reader.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 : kInvalidToken(new Token(Token::INVALID_TOKEN, 0, 0)),
tfarina 2011/09/01 01:21:07 I'm not convinced this is the best way to do this.
tony 2011/09/01 01:48:11 I think we should just get rid of kInvalidToken an
89 start_pos_(NULL),
90 json_pos_(NULL),
91 stack_depth_(0),
95 allow_trailing_comma_(false), 92 allow_trailing_comma_(false),
96 error_code_(JSON_NO_ERROR), error_line_(0), error_col_(0) {} 93 error_code_(JSON_NO_ERROR),
94 error_line_(0),
95 error_col_(0) {}
97 96
98 /* static */ 97 // static
99 Value* JSONReader::Read(const std::string& json, 98 Value* JSONReader::Read(const std::string& json,
100 bool allow_trailing_comma) { 99 bool allow_trailing_comma) {
101 return ReadAndReturnError(json, allow_trailing_comma, NULL, NULL); 100 return ReadAndReturnError(json, allow_trailing_comma, NULL, NULL);
102 } 101 }
103 102
104 /* static */ 103 // static
105 Value* JSONReader::ReadAndReturnError(const std::string& json, 104 Value* JSONReader::ReadAndReturnError(const std::string& json,
106 bool allow_trailing_comma, 105 bool allow_trailing_comma,
107 int* error_code_out, 106 int* error_code_out,
108 std::string* error_msg_out) { 107 std::string* error_msg_out) {
109 JSONReader reader = JSONReader(); 108 JSONReader reader = JSONReader();
110 Value* root = reader.JsonToValue(json, true, allow_trailing_comma); 109 Value* root = reader.JsonToValue(json, true, allow_trailing_comma);
111 if (root) 110 if (root)
112 return root; 111 return root;
113 112
114 if (error_code_out) 113 if (error_code_out)
115 *error_code_out = reader.error_code(); 114 *error_code_out = reader.error_code();
116 if (error_msg_out) 115 if (error_msg_out)
117 *error_msg_out = reader.GetErrorMessage(); 116 *error_msg_out = reader.GetErrorMessage();
118 117
119 return NULL; 118 return NULL;
120 } 119 }
121 120
122 /* static */ 121 // static
123 std::string JSONReader::ErrorCodeToString(JsonParseError error_code) { 122 std::string JSONReader::ErrorCodeToString(JsonParseError error_code) {
124 switch (error_code) { 123 switch (error_code) {
125 case JSON_NO_ERROR: 124 case JSON_NO_ERROR:
126 return std::string(); 125 return std::string();
127 case JSON_BAD_ROOT_ELEMENT_TYPE: 126 case JSON_BAD_ROOT_ELEMENT_TYPE:
128 return kBadRootElementType; 127 return kBadRootElementType;
129 case JSON_INVALID_ESCAPE: 128 case JSON_INVALID_ESCAPE:
130 return kInvalidEscape; 129 return kInvalidEscape;
131 case JSON_SYNTAX_ERROR: 130 case JSON_SYNTAX_ERROR:
132 return kSyntaxError; 131 return kSyntaxError;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 } 186 }
188 } 187 }
189 188
190 // Default to calling errors "syntax errors". 189 // Default to calling errors "syntax errors".
191 if (error_code_ == 0) 190 if (error_code_ == 0)
192 SetErrorCode(JSON_SYNTAX_ERROR, json_pos_); 191 SetErrorCode(JSON_SYNTAX_ERROR, json_pos_);
193 192
194 return NULL; 193 return NULL;
195 } 194 }
196 195
197 /* static */ 196 // static
198 std::string JSONReader::FormatErrorMessage(int line, int column, 197 std::string JSONReader::FormatErrorMessage(int line, int column,
199 const std::string& description) { 198 const std::string& description) {
200 if (line || column) { 199 if (line || column) {
201 return base::StringPrintf( 200 return base::StringPrintf(
202 "Line: %i, column: %i, %s", line, column, description.c_str()); 201 "Line: %i, column: %i, %s", line, column, description.c_str());
203 } 202 }
204 return description; 203 return description;
205 } 204 }
206 205
207 Value* JSONReader::BuildValue(bool is_root) { 206 Value* JSONReader::BuildValue(bool is_root) {
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 // We just grab the number here. We validate the size in DecodeNumber. 361 // We just grab the number here. We validate the size in DecodeNumber.
363 // According to RFC4627, a valid number is: [minus] int [frac] [exp] 362 // According to RFC4627, a valid number is: [minus] int [frac] [exp]
364 Token token(Token::NUMBER, json_pos_, 0); 363 Token token(Token::NUMBER, json_pos_, 0);
365 wchar_t c = *json_pos_; 364 wchar_t c = *json_pos_;
366 if ('-' == c) { 365 if ('-' == c) {
367 ++token.length; 366 ++token.length;
368 c = token.NextChar(); 367 c = token.NextChar();
369 } 368 }
370 369
371 if (!ReadInt(token, false)) 370 if (!ReadInt(token, false))
372 return kInvalidToken; 371 return *kInvalidToken;
373 372
374 // Optional fraction part 373 // Optional fraction part
375 c = token.NextChar(); 374 c = token.NextChar();
376 if ('.' == c) { 375 if ('.' == c) {
377 ++token.length; 376 ++token.length;
378 if (!ReadInt(token, true)) 377 if (!ReadInt(token, true))
379 return kInvalidToken; 378 return *kInvalidToken;
380 c = token.NextChar(); 379 c = token.NextChar();
381 } 380 }
382 381
383 // Optional exponent part 382 // Optional exponent part
384 if ('e' == c || 'E' == c) { 383 if ('e' == c || 'E' == c) {
385 ++token.length; 384 ++token.length;
386 c = token.NextChar(); 385 c = token.NextChar();
387 if ('-' == c || '+' == c) { 386 if ('-' == c || '+' == c) {
388 ++token.length; 387 ++token.length;
389 c = token.NextChar(); 388 c = token.NextChar();
390 } 389 }
391 if (!ReadInt(token, true)) 390 if (!ReadInt(token, true))
392 return kInvalidToken; 391 return *kInvalidToken;
393 } 392 }
394 393
395 return token; 394 return token;
396 } 395 }
397 396
398 Value* JSONReader::DecodeNumber(const Token& token) { 397 Value* JSONReader::DecodeNumber(const Token& token) {
399 const std::wstring num_string(token.begin, token.length); 398 const std::wstring num_string(token.begin, token.length);
400 399
401 int num_int; 400 int num_int;
402 if (StringToInt(WideToUTF8(num_string), &num_int)) 401 if (StringToInt(WideToUTF8(num_string), &num_int))
(...skipping 12 matching lines...) Expand all
415 wchar_t c = token.NextChar(); 414 wchar_t c = token.NextChar();
416 while ('\0' != c) { 415 while ('\0' != c) {
417 if ('\\' == c) { 416 if ('\\' == c) {
418 ++token.length; 417 ++token.length;
419 c = token.NextChar(); 418 c = token.NextChar();
420 // Make sure the escaped char is valid. 419 // Make sure the escaped char is valid.
421 switch (c) { 420 switch (c) {
422 case 'x': 421 case 'x':
423 if (!ReadHexDigits(token, 2)) { 422 if (!ReadHexDigits(token, 2)) {
424 SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length); 423 SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length);
425 return kInvalidToken; 424 return *kInvalidToken;
426 } 425 }
427 break; 426 break;
428 case 'u': 427 case 'u':
429 if (!ReadHexDigits(token, 4)) { 428 if (!ReadHexDigits(token, 4)) {
430 SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length); 429 SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length);
431 return kInvalidToken; 430 return *kInvalidToken;
432 } 431 }
433 break; 432 break;
434 case '\\': 433 case '\\':
435 case '/': 434 case '/':
436 case 'b': 435 case 'b':
437 case 'f': 436 case 'f':
438 case 'n': 437 case 'n':
439 case 'r': 438 case 'r':
440 case 't': 439 case 't':
441 case 'v': 440 case 'v':
442 case '"': 441 case '"':
443 break; 442 break;
444 default: 443 default:
445 SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length); 444 SetErrorCode(JSON_INVALID_ESCAPE, json_pos_ + token.length);
446 return kInvalidToken; 445 return *kInvalidToken;
447 } 446 }
448 } else if ('"' == c) { 447 } else if ('"' == c) {
449 ++token.length; 448 ++token.length;
450 return token; 449 return token;
451 } 450 }
452 ++token.length; 451 ++token.length;
453 c = token.NextChar(); 452 c = token.NextChar();
454 } 453 }
455 return kInvalidToken; 454 return *kInvalidToken;
456 } 455 }
457 456
458 Value* JSONReader::DecodeString(const Token& token) { 457 Value* JSONReader::DecodeString(const Token& token) {
459 std::wstring decoded_str; 458 std::wstring decoded_str;
460 decoded_str.reserve(token.length - 2); 459 decoded_str.reserve(token.length - 2);
461 460
462 for (int i = 1; i < token.length - 1; ++i) { 461 for (int i = 1; i < token.length - 1; ++i) {
463 wchar_t c = *(token.begin + i); 462 wchar_t c = *(token.begin + i);
464 if ('\\' == c) { 463 if ('\\' == c) {
465 ++i; 464 ++i;
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 ++column_number; 662 ++column_number;
664 } 663 }
665 } 664 }
666 665
667 error_line_ = line_number; 666 error_line_ = line_number;
668 error_col_ = column_number; 667 error_col_ = column_number;
669 error_code_ = error; 668 error_code_ = error;
670 } 669 }
671 670
672 } // namespace base 671 } // namespace base
OLDNEW
« no previous file with comments | « base/json/json_reader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698