diff --git a/example/capitalize/capitalize.cpp b/example/capitalize/capitalize.cpp index b8d6086..dd94d24 100644 --- a/example/capitalize/capitalize.cpp +++ b/example/capitalize/capitalize.cpp @@ -31,6 +31,7 @@ struct CapitalizeFilter { return out_.String(&buffer_.front(), length, true); // true = output handler need to copy the string } bool StartObject() { return out_.StartObject(); } + bool Key(const char* str, SizeType length, bool copy) { return String(str, length, copy); } bool EndObject(SizeType memberCount) { return out_.EndObject(memberCount); } bool StartArray() { return out_.StartArray(); } bool EndArray(SizeType elementCount) { return out_.EndArray(elementCount); } diff --git a/example/simplereader/simplereader.cpp b/example/simplereader/simplereader.cpp index 9914253..edbdb63 100644 --- a/example/simplereader/simplereader.cpp +++ b/example/simplereader/simplereader.cpp @@ -17,6 +17,10 @@ struct MyHandler { return true; } bool StartObject() { cout << "StartObject()" << endl; return true; } + bool Key(const char* str, SizeType length, bool copy) { + cout << "Key(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl; + return true; + } bool EndObject(SizeType memberCount) { cout << "EndObject(" << memberCount << ")" << endl; return true; } bool StartArray() { cout << "StartArray()" << endl; return true; } bool EndArray(SizeType elementCount) { cout << "EndArray(" << elementCount << ")" << endl; return true; } diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 13acb38..310fc71 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1386,7 +1386,7 @@ int z = a[0u].GetInt(); // This works too. if (!handler.StartObject()) return false; for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { - if (!handler.String(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0)) + if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0)) return false; if (!m->value.Accept(handler)) return false; @@ -1794,6 +1794,8 @@ private: bool StartObject() { new (stack_.template Push()) ValueType(kObjectType); return true; } + bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); } + bool EndObject(SizeType memberCount) { typename ValueType::Member* members = stack_.template Pop(memberCount); stack_.template Top()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator()); diff --git a/include/rapidjson/prettywriter.h b/include/rapidjson/prettywriter.h index f89be1b..4eac8d7 100644 --- a/include/rapidjson/prettywriter.h +++ b/include/rapidjson/prettywriter.h @@ -88,6 +88,8 @@ public: return Base::WriteStartObject(); } + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + bool EndObject(SizeType memberCount = 0) { (void)memberCount; RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); @@ -135,6 +137,7 @@ public: //! Simpler but slower overload. bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } //@} protected: diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 701255f..f41ba2f 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -152,6 +152,7 @@ concept Handler { bool Double(double d); bool String(const Ch* str, SizeType length, bool copy); bool StartObject(); + bool Key(const Ch* str, SizeType length, bool copy); bool EndObject(SizeType memberCount); bool StartArray(); bool EndArray(SizeType elementCount); @@ -181,6 +182,7 @@ struct BaseReaderHandler { bool Double(double) { return static_cast(*this).Default(); } bool String(const Ch*, SizeType, bool) { return static_cast(*this).Default(); } bool StartObject() { return static_cast(*this).Default(); } + bool Key(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } bool EndObject(SizeType) { return static_cast(*this).Default(); } bool StartArray() { return static_cast(*this).Default(); } bool EndArray(SizeType) { return static_cast(*this).Default(); } @@ -471,7 +473,7 @@ private: if (is.Peek() != '"') RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); - ParseString(is, handler); + ParseString(is, handler, true); RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; SkipWhitespace(is); @@ -617,26 +619,29 @@ private: // Parse string and generate String event. Different code paths for kParseInsituFlag. template - void ParseString(InputStream& is, Handler& handler) { + void ParseString(InputStream& is, Handler& handler, bool isKey = false) { internal::StreamLocalCopy copy(is); InputStream& s(copy.s); + bool success = false; if (parseFlags & kParseInsituFlag) { typename InputStream::Ch *head = s.PutBegin(); ParseStringToStream(s, s); RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; size_t length = s.PutEnd(head) - 1; RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); - if (!handler.String((typename TargetEncoding::Ch*)head, SizeType(length), false)) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + const typename TargetEncoding::Ch* const str = (typename TargetEncoding::Ch*)head; + success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); } else { StackStream stackStream(stack_); ParseStringToStream(s, stackStream); RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - if (!handler.String(stack_.template Pop(stackStream.length_), stackStream.length_ - 1, true)) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + const typename TargetEncoding::Ch* const str = stack_.template Pop(stackStream.length_); + success = (isKey ? handler.Key(str, stackStream.length_ - 1, true) : handler.String(str, stackStream.length_ - 1, true)); } + if (!success) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); } // Parse string to an output is @@ -1194,7 +1199,7 @@ private: } case IterativeParsingMemberKeyState: - ParseString(is, handler); + ParseString(is, handler, true); if (HasParseError()) return IterativeParsingErrorState; else diff --git a/include/rapidjson/writer.h b/include/rapidjson/writer.h index 73e4aff..fb6601e 100644 --- a/include/rapidjson/writer.h +++ b/include/rapidjson/writer.h @@ -131,6 +131,8 @@ public: return WriteStartObject(); } + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + bool EndObject(SizeType memberCount = 0) { (void)memberCount; RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); @@ -165,6 +167,7 @@ public: //! Simpler but slower overload. bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } //@} diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 09560d8..b42d832 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -819,9 +819,10 @@ struct IterativeParsingReaderHandler { const static int LOG_DOUBLE = -7; const static int LOG_STRING = -8; const static int LOG_STARTOBJECT = -9; - const static int LOG_ENDOBJECT = -10; - const static int LOG_STARTARRAY = -11; - const static int LOG_ENDARRAY = -12; + const static int LOG_KEY = -10; + const static int LOG_ENDOBJECT = -11; + const static int LOG_STARTARRAY = -12; + const static int LOG_ENDARRAY = -13; const static size_t LogCapacity = 256; int Logs[LogCapacity]; @@ -848,6 +849,8 @@ struct IterativeParsingReaderHandler { bool StartObject() { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_STARTOBJECT; return true; } + bool Key (const Ch*, SizeType, bool) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_KEY; return true; } + bool EndObject(SizeType c) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_ENDOBJECT; @@ -880,7 +883,7 @@ TEST(Reader, IterativeParsing_General) { handler.LOG_STARTARRAY, handler.LOG_INT, handler.LOG_STARTOBJECT, - handler.LOG_STRING, + handler.LOG_KEY, handler.LOG_STARTARRAY, handler.LOG_INT, handler.LOG_INT, @@ -918,7 +921,7 @@ TEST(Reader, IterativeParsing_Count) { handler.LOG_STARTOBJECT, handler.LOG_ENDOBJECT, 0, handler.LOG_STARTOBJECT, - handler.LOG_STRING, + handler.LOG_KEY, handler.LOG_INT, handler.LOG_ENDOBJECT, 1, handler.LOG_STARTARRAY,