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

Unified Diff: base/json/json_reader.h

Issue 10035042: Rewrite base::JSONReader to be 35-40% faster, depending on the input string. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Really fix Windows, address comments Created 8 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/json/json_parser_unittest.cc ('k') | base/json/json_reader.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/json/json_reader.h
diff --git a/base/json/json_reader.h b/base/json/json_reader.h
index 35ee7d3e1c67a8c4306ea144dd2041d47eb2cb76..e0811754b1957f36a4cd01b462aa835810671f25 100644
--- a/base/json/json_reader.h
+++ b/base/json/json_reader.h
@@ -33,23 +33,18 @@
#include "base/base_export.h"
#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
-// Chromium and Chromium OS check out gtest to different places, so we're
-// unable to compile on both if we include gtest_prod.h here. Instead, include
-// its only contents -- this will need to be updated if the macro ever changes.
-#define FRIEND_TEST(test_case_name, test_name)\
-friend class test_case_name##_##test_name##_Test
+namespace base {
+class Value;
-#define FRIEND_TEST_ALL_PREFIXES(test_case_name, test_name) \
- FRIEND_TEST(test_case_name, test_name); \
- FRIEND_TEST(test_case_name, DISABLED_##test_name); \
- FRIEND_TEST(test_case_name, FLAKY_##test_name); \
- FRIEND_TEST(test_case_name, FAILS_##test_name)
+namespace internal {
+class JSONParser;
+}
+}
namespace base {
-class Value;
-
enum JSONParserOptions {
// Parses the input strictly according to RFC 4627, except for where noted
// above.
@@ -57,56 +52,22 @@ enum JSONParserOptions {
// Allows commas to exist after the last element in structures.
JSON_ALLOW_TRAILING_COMMAS = 1 << 0,
+
+ // The parser can perform optimizations by placing hidden data in the root of
+ // the JSON object, which speeds up certain operations on children. However,
+ // if the child is Remove()d from root, it would result in use-after-free
+ // unless it is DeepCopy()ed or this option is used.
+ JSON_DETACHABLE_CHILDREN = 1 << 1,
};
class BASE_EXPORT JSONReader {
public:
- // A struct to hold a JS token.
- class Token {
- public:
- enum Type {
- OBJECT_BEGIN, // {
- OBJECT_END, // }
- ARRAY_BEGIN, // [
- ARRAY_END, // ]
- STRING,
- NUMBER,
- BOOL_TRUE, // true
- BOOL_FALSE, // false
- NULL_TOKEN, // null
- LIST_SEPARATOR, // ,
- OBJECT_PAIR_SEPARATOR, // :
- END_OF_INPUT,
- INVALID_TOKEN,
- };
-
- Token(Type t, const char* b, int len)
- : type(t), begin(b), length(len) {}
-
- // Get the character that's one past the end of this token.
- char NextChar() {
- return *(begin + length);
- }
-
- static Token CreateInvalidToken() {
- return Token(INVALID_TOKEN, 0, 0);
- }
-
- Type type;
-
- // A pointer into JSONReader::json_pos_ that's the beginning of this token.
- const char* begin;
-
- // End should be one char past the end of the token.
- int length;
- };
-
// Error codes during parsing.
enum JsonParseError {
JSON_NO_ERROR = 0,
- JSON_BAD_ROOT_ELEMENT_TYPE,
JSON_INVALID_ESCAPE,
JSON_SYNTAX_ERROR,
+ JSON_UNEXPECTED_TOKEN,
JSON_TRAILING_COMMA,
JSON_TOO_MUCH_NESTING,
JSON_UNEXPECTED_DATA_AFTER_ROOT,
@@ -115,17 +76,23 @@ class BASE_EXPORT JSONReader {
};
// String versions of parse error codes.
- static const char* kBadRootElementType;
static const char* kInvalidEscape;
static const char* kSyntaxError;
+ static const char* kUnexpectedToken;
static const char* kTrailingComma;
static const char* kTooMuchNesting;
static const char* kUnexpectedDataAfterRoot;
static const char* kUnsupportedEncoding;
static const char* kUnquotedDictionaryKey;
+ // Constructs a reader with the default options, JSON_PARSE_RFC.
JSONReader();
+ // Constructs a reader with custom options.
+ explicit JSONReader(int options);
+
+ ~JSONReader();
+
// Reads and parses |json|, returning a Value. The caller owns the returned
// instance. If |json| is not a properly formed JSON string, returns NULL.
static Value* Read(const std::string& json);
@@ -148,106 +115,19 @@ class BASE_EXPORT JSONReader {
// Returns an empty string if error_code is JSON_NO_ERROR.
static std::string ErrorCodeToString(JsonParseError error_code);
- // Returns the error code if the last call to JsonToValue() failed.
+ // Parses an input string into a Value that is owned by the caller.
+ Value* ReadToValue(const std::string& json);
+
+ // Returns the error code if the last call to ReadToValue() failed.
// Returns JSON_NO_ERROR otherwise.
- JsonParseError error_code() const { return error_code_; }
+ JsonParseError error_code() const;
// Converts error_code_ to a human-readable string, including line and column
// numbers if appropriate.
std::string GetErrorMessage() const;
- // Reads and parses |json|, returning a Value. The caller owns the returned
- // instance. If |json| is not a properly formed JSON string, returns NULL and
- // a detailed error can be retrieved from |error_message()|.
- // If |check_root| is true, we require that the root object be an object or
- // array. Otherwise, it can be any valid JSON type.
- // If |allow_trailing_comma| is true, we will ignore trailing commas in
- // objects and arrays even though this goes against the RFC.
- Value* JsonToValue(const std::string& json, bool check_root,
- bool allow_trailing_comma);
-
private:
- FRIEND_TEST_ALL_PREFIXES(JSONReaderTest, Reading);
- FRIEND_TEST_ALL_PREFIXES(JSONReaderTest, ErrorMessages);
-
- static std::string FormatErrorMessage(int line, int column,
- const std::string& description);
-
- // Recursively build Value. Returns NULL if we don't have a valid JSON
- // string. If |is_root| is true, we verify that the root element is either
- // an object or an array.
- Value* BuildValue(bool is_root);
-
- // Parses a sequence of characters into a Token::NUMBER. If the sequence of
- // characters is not a valid number, returns a Token::INVALID_TOKEN. Note
- // that DecodeNumber is used to actually convert from a string to an
- // int/double.
- Token ParseNumberToken();
-
- // Try and convert the substring that token holds into an int or a double. If
- // we can (ie., no overflow), return the value, else return NULL.
- Value* DecodeNumber(const Token& token);
-
- // Parses a sequence of characters into a Token::STRING. If the sequence of
- // characters is not a valid string, returns a Token::INVALID_TOKEN. Note
- // that DecodeString is used to actually decode the escaped string into an
- // actual wstring.
- Token ParseStringToken();
-
- // Convert the substring into a value string. This should always succeed
- // (otherwise ParseStringToken would have failed).
- Value* DecodeString(const Token& token);
-
- // Helper function for DecodeString that consumes UTF16 [0,2] code units and
- // convers them to UTF8 code untis. |token| is the string token in which the
- // units should be read, |i| is the position in the token at which the first
- // code unit starts, immediately after the |\u|. This will be mutated if code
- // units are consumed. |dest_string| is a string to which the UTF8 code unit
- // should be appended. Returns true on success and false if there's an
- // encoding error.
- bool ConvertUTF16Units(const Token& token,
- int* i,
- std::string* dest_string);
-
- // Grabs the next token in the JSON stream. This does not increment the
- // stream so it can be used to look ahead at the next token.
- Token ParseToken();
-
- // Increments |json_pos_| past leading whitespace and comments.
- void EatWhitespaceAndComments();
-
- // If |json_pos_| is at the start of a comment, eat it, otherwise, returns
- // false.
- bool EatComment();
-
- // Checks if |json_pos_| matches str.
- bool NextStringMatch(const char* str, size_t length);
-
- // Sets the error code that will be returned to the caller. The current
- // line and column are determined and added into the final message.
- void SetErrorCode(const JsonParseError error, const char* error_pos);
-
- // Pointer to the starting position in the input string.
- const char* start_pos_;
-
- // Pointer to the current position in the input string.
- const char* json_pos_;
-
- // Pointer to the last position in the input string.
- const char* end_pos_;
-
- // Used to keep track of how many nested lists/dicts there are.
- int stack_depth_;
-
- // A parser flag that allows trailing commas in objects and arrays.
- bool allow_trailing_comma_;
-
- // Contains the error code for the last call to JsonToValue(), if any.
- JsonParseError error_code_;
- int error_line_;
- int error_col_;
-
- DISALLOW_COPY_AND_ASSIGN(JSONReader);
+ scoped_ptr<internal::JSONParser> parser_;
};
} // namespace base
« no previous file with comments | « base/json/json_parser_unittest.cc ('k') | base/json/json_reader.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698