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

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: add CreateInvalidToken() 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 : 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
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
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
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
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
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