Commit 57e1c875 authored by Kosta's avatar Kosta

add `Key()` method to the `Handler` concept

For more details see: https://github.com/miloyip/rapidjson/issues/132

This commit tries to minimize the required code changes and forwards the `Handler::Key()` calls to `Handler::String()` wherever possible in order to not break existing code; or at least not code deriving from `BaseReaderHandler` when implementing a custom `Handler`.
parent bc9d7866
...@@ -1386,7 +1386,7 @@ int z = a[0u].GetInt(); // This works too. ...@@ -1386,7 +1386,7 @@ int z = a[0u].GetInt(); // This works too.
if (!handler.StartObject()) if (!handler.StartObject())
return false; return false;
for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { 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; return false;
if (!m->value.Accept(handler)) if (!m->value.Accept(handler))
return false; return false;
...@@ -1794,6 +1794,8 @@ private: ...@@ -1794,6 +1794,8 @@ private:
bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; } bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
bool EndObject(SizeType memberCount) { bool EndObject(SizeType memberCount) {
typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount); typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator()); stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
......
...@@ -152,6 +152,7 @@ concept Handler { ...@@ -152,6 +152,7 @@ concept Handler {
bool Double(double d); bool Double(double d);
bool String(const Ch* str, SizeType length, bool copy); bool String(const Ch* str, SizeType length, bool copy);
bool StartObject(); bool StartObject();
bool Key(const Ch* str, SizeType length, bool copy);
bool EndObject(SizeType memberCount); bool EndObject(SizeType memberCount);
bool StartArray(); bool StartArray();
bool EndArray(SizeType elementCount); bool EndArray(SizeType elementCount);
...@@ -181,6 +182,7 @@ struct BaseReaderHandler { ...@@ -181,6 +182,7 @@ struct BaseReaderHandler {
bool Double(double) { return static_cast<Override&>(*this).Default(); } bool Double(double) { return static_cast<Override&>(*this).Default(); }
bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); } bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); }
bool StartObject() { return static_cast<Override&>(*this).Default(); } bool StartObject() { return static_cast<Override&>(*this).Default(); }
bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); }
bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); } bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); }
bool StartArray() { return static_cast<Override&>(*this).Default(); } bool StartArray() { return static_cast<Override&>(*this).Default(); }
bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); } bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); }
...@@ -471,7 +473,7 @@ private: ...@@ -471,7 +473,7 @@ private:
if (is.Peek() != '"') if (is.Peek() != '"')
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
ParseString<parseFlags>(is, handler); ParseKey<parseFlags>(is, handler);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
SkipWhitespace(is); SkipWhitespace(is);
...@@ -576,7 +578,7 @@ private: ...@@ -576,7 +578,7 @@ private:
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
} }
// Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). // Helper function to parse four hexidecimal digits in \uXXXX in ParseStringOrKey().
template<typename InputStream> template<typename InputStream>
unsigned ParseHex4(InputStream& is) { unsigned ParseHex4(InputStream& is) {
unsigned codepoint = 0; unsigned codepoint = 0;
...@@ -616,8 +618,8 @@ private: ...@@ -616,8 +618,8 @@ private:
}; };
// Parse string and generate String event. Different code paths for kParseInsituFlag. // Parse string and generate String event. Different code paths for kParseInsituFlag.
template<unsigned parseFlags, typename InputStream, typename Handler> template<unsigned parseFlags, bool isKey, typename InputStream, typename Handler>
void ParseString(InputStream& is, Handler& handler) { void ParseStringOrKey(InputStream& is, Handler& handler) {
internal::StreamLocalCopy<InputStream> copy(is); internal::StreamLocalCopy<InputStream> copy(is);
InputStream& s(copy.s); InputStream& s(copy.s);
...@@ -627,18 +629,38 @@ private: ...@@ -627,18 +629,38 @@ private:
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
size_t length = s.PutEnd(head) - 1; size_t length = s.PutEnd(head) - 1;
RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
if (!handler.String((typename TargetEncoding::Ch*)head, SizeType(length), false)) if (isKey) {
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); if (!handler.Key((typename TargetEncoding::Ch*)head, SizeType(length), false))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
} else {
if (!handler.String((typename TargetEncoding::Ch*)head, SizeType(length), false))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
}
} }
else { else {
StackStream stackStream(stack_); StackStream stackStream(stack_);
ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream); ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
if (!handler.String(stack_.template Pop<typename TargetEncoding::Ch>(stackStream.length_), stackStream.length_ - 1, true)) if (isKey) {
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); if (!handler.Key(stack_.template Pop<typename TargetEncoding::Ch>(stackStream.length_), stackStream.length_ - 1, true))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
} else {
if (!handler.String(stack_.template Pop<typename TargetEncoding::Ch>(stackStream.length_), stackStream.length_ - 1, true))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
}
} }
} }
template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseKey(InputStream& is, Handler& handler) {
return ParseStringOrKey<parseFlags, true>(is, handler);
}
template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseString(InputStream& is, Handler& handler) {
return ParseStringOrKey<parseFlags, false>(is, handler);
}
// Parse string to an output is // Parse string to an output is
// This function handles the prefix/suffix double quotes, escaping, and optional encoding validation. // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream> template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
...@@ -1194,7 +1216,7 @@ private: ...@@ -1194,7 +1216,7 @@ private:
} }
case IterativeParsingMemberKeyState: case IterativeParsingMemberKeyState:
ParseString<parseFlags>(is, handler); ParseKey<parseFlags>(is, handler);
if (HasParseError()) if (HasParseError())
return IterativeParsingErrorState; return IterativeParsingErrorState;
else else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment