Fixes #59 by adding bool return value for each event handler function
This commit is contained in:
parent
63d054349a
commit
cc04219e36
@ -1015,44 +1015,45 @@ int z = a[0u].GetInt(); // This works too.
|
||||
\param handler An object implementing concept Handler.
|
||||
*/
|
||||
template <typename Handler>
|
||||
const GenericValue& Accept(Handler& handler) const {
|
||||
bool Accept(Handler& handler) const {
|
||||
switch(GetType()) {
|
||||
case kNullType: handler.Null(); break;
|
||||
case kFalseType: handler.Bool(false); break;
|
||||
case kTrueType: handler.Bool(true); break;
|
||||
case kNullType: return handler.Null();
|
||||
case kFalseType: return handler.Bool(false);
|
||||
case kTrueType: return handler.Bool(true);
|
||||
|
||||
case kObjectType:
|
||||
handler.StartObject();
|
||||
if (!handler.StartObject())
|
||||
return false;
|
||||
for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
|
||||
handler.String(m->name.data_.s.str, m->name.data_.s.length, (m->name.flags_ & kCopyFlag) != 0);
|
||||
m->value.Accept(handler);
|
||||
if (!handler.String(m->name.data_.s.str, m->name.data_.s.length, (m->name.flags_ & kCopyFlag) != 0))
|
||||
return false;
|
||||
if (!m->value.Accept(handler))
|
||||
return false;
|
||||
}
|
||||
handler.EndObject(data_.o.size);
|
||||
break;
|
||||
return handler.EndObject(data_.o.size);
|
||||
|
||||
case kArrayType:
|
||||
handler.StartArray();
|
||||
if (!handler.StartArray())
|
||||
return false;
|
||||
for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
|
||||
v->Accept(handler);
|
||||
handler.EndArray(data_.a.size);
|
||||
break;
|
||||
if (!v->Accept(handler))
|
||||
return false;
|
||||
return handler.EndArray(data_.a.size);
|
||||
|
||||
case kStringType:
|
||||
handler.String(data_.s.str, data_.s.length, (flags_ & kCopyFlag) != 0);
|
||||
break;
|
||||
return handler.String(data_.s.str, data_.s.length, (flags_ & kCopyFlag) != 0);
|
||||
|
||||
case kNumberType:
|
||||
if (IsInt()) handler.Int(data_.n.i.i);
|
||||
else if (IsUint()) handler.Uint(data_.n.u.u);
|
||||
else if (IsInt64()) handler.Int64(data_.n.i64);
|
||||
else if (IsUint64()) handler.Uint64(data_.n.u64);
|
||||
else handler.Double(data_.n.d);
|
||||
break;
|
||||
if (IsInt()) return handler.Int(data_.n.i.i);
|
||||
else if (IsUint()) return handler.Uint(data_.n.u.u);
|
||||
else if (IsInt64()) return handler.Int64(data_.n.i64);
|
||||
else if (IsUint64()) return handler.Uint64(data_.n.u64);
|
||||
else return handler.Double(data_.n.d);
|
||||
|
||||
default:
|
||||
RAPIDJSON_ASSERT(false);
|
||||
}
|
||||
return *this;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1354,33 +1355,36 @@ private:
|
||||
friend class GenericValue<Encoding,Allocator>; // for deep copying
|
||||
|
||||
// Implementation of Handler
|
||||
void Null() { new (stack_.template Push<ValueType>()) ValueType(); }
|
||||
void Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); }
|
||||
void Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); }
|
||||
void Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); }
|
||||
void Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); }
|
||||
void Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); }
|
||||
void Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); }
|
||||
bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
|
||||
bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
|
||||
bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
|
||||
bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
|
||||
bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
|
||||
bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
|
||||
bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
|
||||
|
||||
void String(const Ch* str, SizeType length, bool copy) {
|
||||
bool String(const Ch* str, SizeType length, bool copy) {
|
||||
if (copy)
|
||||
new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
|
||||
else
|
||||
new (stack_.template Push<ValueType>()) ValueType(str, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
void StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); }
|
||||
bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
|
||||
|
||||
void EndObject(SizeType memberCount) {
|
||||
bool EndObject(SizeType memberCount) {
|
||||
typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
|
||||
stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
|
||||
return true;
|
||||
}
|
||||
|
||||
void StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); }
|
||||
bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
|
||||
|
||||
void EndArray(SizeType elementCount) {
|
||||
bool EndArray(SizeType elementCount) {
|
||||
ValueType* elements = stack_.template Pop<ValueType>(elementCount);
|
||||
stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -51,29 +51,27 @@ public:
|
||||
*/
|
||||
//@{
|
||||
|
||||
PrettyWriter& Null() { PrettyPrefix(kNullType); Base::WriteNull(); return *this; }
|
||||
PrettyWriter& Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); Base::WriteBool(b); return *this; }
|
||||
PrettyWriter& Int(int i) { PrettyPrefix(kNumberType); Base::WriteInt(i); return *this; }
|
||||
PrettyWriter& Uint(unsigned u) { PrettyPrefix(kNumberType); Base::WriteUint(u); return *this; }
|
||||
PrettyWriter& Int64(int64_t i64) { PrettyPrefix(kNumberType); Base::WriteInt64(i64); return *this; }
|
||||
PrettyWriter& Uint64(uint64_t u64) { PrettyPrefix(kNumberType); Base::WriteUint64(u64); return *this; }
|
||||
PrettyWriter& Double(double d) { PrettyPrefix(kNumberType); Base::WriteDouble(d); return *this; }
|
||||
bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
|
||||
bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
|
||||
bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
|
||||
bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
|
||||
bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
|
||||
bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
|
||||
bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
|
||||
|
||||
PrettyWriter& String(const Ch* str, SizeType length, bool copy = false) {
|
||||
bool String(const Ch* str, SizeType length, bool copy = false) {
|
||||
(void)copy;
|
||||
PrettyPrefix(kStringType);
|
||||
Base::WriteString(str, length);
|
||||
return *this;
|
||||
return Base::WriteString(str, length);
|
||||
}
|
||||
|
||||
PrettyWriter& StartObject() {
|
||||
bool StartObject() {
|
||||
PrettyPrefix(kObjectType);
|
||||
new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
|
||||
Base::WriteStartObject();
|
||||
return *this;
|
||||
return Base::WriteStartObject();
|
||||
}
|
||||
|
||||
PrettyWriter& EndObject(SizeType memberCount = 0) {
|
||||
bool EndObject(SizeType memberCount = 0) {
|
||||
(void)memberCount;
|
||||
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
|
||||
RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
|
||||
@ -83,20 +81,20 @@ public:
|
||||
Base::os_.Put('\n');
|
||||
WriteIndent();
|
||||
}
|
||||
Base::WriteEndObject();
|
||||
if (!Base::WriteEndObject())
|
||||
return false;
|
||||
if (Base::level_stack_.Empty()) // end of json text
|
||||
Base::os_.Flush();
|
||||
return *this;
|
||||
return true;
|
||||
}
|
||||
|
||||
PrettyWriter& StartArray() {
|
||||
bool StartArray() {
|
||||
PrettyPrefix(kArrayType);
|
||||
new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
|
||||
Base::WriteStartArray();
|
||||
return *this;
|
||||
return Base::WriteStartArray();
|
||||
}
|
||||
|
||||
PrettyWriter& EndArray(SizeType memberCount = 0) {
|
||||
bool EndArray(SizeType memberCount = 0) {
|
||||
(void)memberCount;
|
||||
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
|
||||
RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
|
||||
@ -106,10 +104,11 @@ public:
|
||||
Base::os_.Put('\n');
|
||||
WriteIndent();
|
||||
}
|
||||
Base::WriteEndArray();
|
||||
if (!Base::WriteEndArray())
|
||||
return false;
|
||||
if (Base::level_stack_.Empty()) // end of json text
|
||||
Base::os_.Flush();
|
||||
return *this;
|
||||
return true;
|
||||
}
|
||||
|
||||
//@}
|
||||
@ -118,12 +117,15 @@ public:
|
||||
//@{
|
||||
|
||||
//! Simpler but slower overload.
|
||||
PrettyWriter& String(const Ch* str) { return String(str, internal::StrLen(str)); }
|
||||
bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
|
||||
|
||||
//! Overridden for fluent API, see \ref Writer::Double()
|
||||
PrettyWriter& Double(double d, int precision) {
|
||||
bool Double(double d, int precision) {
|
||||
int oldPrecision = Base::GetDoublePrecision();
|
||||
return SetDoublePrecision(precision).Double(d).SetDoublePrecision(oldPrecision);
|
||||
SetDoublePrecision(precision);
|
||||
bool ret = Double(d);
|
||||
SetDoublePrecision(oldPrecision);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
@ -75,7 +75,9 @@ enum ParseErrorCode {
|
||||
|
||||
kParseErrorNumberTooBig, //!< Number too big to be stored in double.
|
||||
kParseErrorNumberMissFraction, //!< Miss fraction part in number.
|
||||
kParseErrorNumberMissExponent //!< Miss exponent in number.
|
||||
kParseErrorNumberMissExponent, //!< Miss exponent in number.
|
||||
|
||||
kParseErrorTermination //!< Parsing was terminated.
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -83,22 +85,24 @@ enum ParseErrorCode {
|
||||
|
||||
/*! \class rapidjson::Handler
|
||||
\brief Concept for receiving events from GenericReader upon parsing.
|
||||
The functions return true if no error occurs. If they return false,
|
||||
the event publisher should terminate the process.
|
||||
\code
|
||||
concept Handler {
|
||||
typename Ch;
|
||||
|
||||
void Null();
|
||||
void Bool(bool b);
|
||||
void Int(int i);
|
||||
void Uint(unsigned i);
|
||||
void Int64(int64_t i);
|
||||
void Uint64(uint64_t i);
|
||||
void Double(double d);
|
||||
void String(const Ch* str, SizeType length, bool copy);
|
||||
void StartObject();
|
||||
void EndObject(SizeType memberCount);
|
||||
void StartArray();
|
||||
void EndArray(SizeType elementCount);
|
||||
bool Null();
|
||||
bool Bool(bool b);
|
||||
bool Int(int i);
|
||||
bool Uint(unsigned i);
|
||||
bool Int64(int64_t i);
|
||||
bool Uint64(uint64_t i);
|
||||
bool Double(double d);
|
||||
bool String(const Ch* str, SizeType length, bool copy);
|
||||
bool StartObject();
|
||||
bool EndObject(SizeType memberCount);
|
||||
bool StartArray();
|
||||
bool EndArray(SizeType elementCount);
|
||||
};
|
||||
\endcode
|
||||
*/
|
||||
@ -113,19 +117,19 @@ template<typename Encoding = UTF8<> >
|
||||
struct BaseReaderHandler {
|
||||
typedef typename Encoding::Ch Ch;
|
||||
|
||||
void Default() {}
|
||||
void Null() { Default(); }
|
||||
void Bool(bool) { Default(); }
|
||||
void Int(int) { Default(); }
|
||||
void Uint(unsigned) { Default(); }
|
||||
void Int64(int64_t) { Default(); }
|
||||
void Uint64(uint64_t) { Default(); }
|
||||
void Double(double) { Default(); }
|
||||
void String(const Ch*, SizeType, bool) { Default(); }
|
||||
void StartObject() { Default(); }
|
||||
void EndObject(SizeType) { Default(); }
|
||||
void StartArray() { Default(); }
|
||||
void EndArray(SizeType) { Default(); }
|
||||
bool Default() { return true; }
|
||||
bool Null() { return Default(); }
|
||||
bool Bool(bool) { return Default(); }
|
||||
bool Int(int) { return Default(); }
|
||||
bool Uint(unsigned) { return Default(); }
|
||||
bool Int64(int64_t) { return Default(); }
|
||||
bool Uint64(uint64_t) { return Default(); }
|
||||
bool Double(double) { return Default(); }
|
||||
bool String(const Ch*, SizeType, bool) { return Default(); }
|
||||
bool StartObject() { return Default(); }
|
||||
bool EndObject(SizeType) { return Default(); }
|
||||
bool StartArray() { return Default(); }
|
||||
bool EndArray(SizeType) { return Default(); }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -351,12 +355,16 @@ private:
|
||||
void ParseObject(InputStream& is, Handler& handler) {
|
||||
RAPIDJSON_ASSERT(is.Peek() == '{');
|
||||
is.Take(); // Skip '{'
|
||||
handler.StartObject();
|
||||
|
||||
if (!handler.StartObject())
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||
|
||||
SkipWhitespace(is);
|
||||
|
||||
if (is.Peek() == '}') {
|
||||
is.Take();
|
||||
handler.EndObject(0); // empty object
|
||||
if (!handler.EndObject(0)) // empty object
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -385,7 +393,11 @@ private:
|
||||
|
||||
switch (is.Take()) {
|
||||
case ',': SkipWhitespace(is); break;
|
||||
case '}': handler.EndObject(memberCount); return;
|
||||
case '}':
|
||||
if (!handler.EndObject(memberCount))
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||
else
|
||||
return;
|
||||
default: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
|
||||
}
|
||||
}
|
||||
@ -396,12 +408,16 @@ private:
|
||||
void ParseArray(InputStream& is, Handler& handler) {
|
||||
RAPIDJSON_ASSERT(is.Peek() == '[');
|
||||
is.Take(); // Skip '['
|
||||
handler.StartArray();
|
||||
|
||||
if (!handler.StartArray())
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||
|
||||
SkipWhitespace(is);
|
||||
|
||||
if (is.Peek() == ']') {
|
||||
is.Take();
|
||||
handler.EndArray(0); // empty array
|
||||
if (!handler.EndArray(0)) // empty array
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -415,7 +431,11 @@ private:
|
||||
|
||||
switch (is.Take()) {
|
||||
case ',': SkipWhitespace(is); break;
|
||||
case ']': handler.EndArray(elementCount); return;
|
||||
case ']':
|
||||
if (!handler.EndArray(elementCount))
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||
else
|
||||
return;
|
||||
default: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
|
||||
}
|
||||
}
|
||||
@ -426,8 +446,10 @@ private:
|
||||
RAPIDJSON_ASSERT(is.Peek() == 'n');
|
||||
is.Take();
|
||||
|
||||
if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l')
|
||||
handler.Null();
|
||||
if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l') {
|
||||
if (!handler.Null())
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||
}
|
||||
else
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
|
||||
}
|
||||
@ -437,10 +459,12 @@ private:
|
||||
RAPIDJSON_ASSERT(is.Peek() == 't');
|
||||
is.Take();
|
||||
|
||||
if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e')
|
||||
handler.Bool(true);
|
||||
if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e') {
|
||||
if (!handler.Bool(true))
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||
}
|
||||
else
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
|
||||
}
|
||||
|
||||
template<unsigned parseFlags, typename InputStream, typename Handler>
|
||||
@ -448,8 +472,10 @@ private:
|
||||
RAPIDJSON_ASSERT(is.Peek() == 'f');
|
||||
is.Take();
|
||||
|
||||
if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e')
|
||||
handler.Bool(false);
|
||||
if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e') {
|
||||
if (!handler.Bool(false))
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||
}
|
||||
else
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
|
||||
}
|
||||
@ -506,14 +532,16 @@ private:
|
||||
return;
|
||||
size_t length = s.PutEnd(head) - 1;
|
||||
RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
|
||||
handler.String((typename TargetEncoding::Ch*)head, SizeType(length), false);
|
||||
if (!handler.String((typename TargetEncoding::Ch*)head, SizeType(length), false))
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
|
||||
}
|
||||
else {
|
||||
StackStream stackStream(stack_);
|
||||
ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
|
||||
if (HasParseError())
|
||||
return;
|
||||
handler.String(stack_.template Pop<typename TargetEncoding::Ch>(stackStream.length_), stackStream.length_ - 1, true);
|
||||
if (!handler.String(stack_.template Pop<typename TargetEncoding::Ch>(stackStream.length_), stackStream.length_ - 1, true))
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
|
||||
}
|
||||
}
|
||||
|
||||
@ -715,6 +743,7 @@ private:
|
||||
}
|
||||
|
||||
// Finish parsing, call event according to the type of number.
|
||||
bool cont = true;
|
||||
if (useDouble) {
|
||||
int expSum = exp + expFrac;
|
||||
if (expSum < -308) {
|
||||
@ -725,22 +754,24 @@ private:
|
||||
else
|
||||
d *= internal::Pow10(expSum);
|
||||
|
||||
handler.Double(minus ? -d : d);
|
||||
cont = handler.Double(minus ? -d : d);
|
||||
}
|
||||
else {
|
||||
if (try64bit) {
|
||||
if (minus)
|
||||
handler.Int64(-(int64_t)i64);
|
||||
cont = handler.Int64(-(int64_t)i64);
|
||||
else
|
||||
handler.Uint64(i64);
|
||||
cont = handler.Uint64(i64);
|
||||
}
|
||||
else {
|
||||
if (minus)
|
||||
handler.Int(-(int)i);
|
||||
cont = handler.Int(-(int)i);
|
||||
else
|
||||
handler.Uint(i);
|
||||
cont = handler.Uint(i);
|
||||
}
|
||||
}
|
||||
if (!cont)
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
|
||||
}
|
||||
|
||||
// Parse any JSON value
|
||||
|
@ -64,12 +64,12 @@ public:
|
||||
*/
|
||||
//@{
|
||||
|
||||
Writer& Null() { Prefix(kNullType); WriteNull(); return *this; }
|
||||
Writer& Bool(bool b) { Prefix(b ? kTrueType : kFalseType); WriteBool(b); return *this; }
|
||||
Writer& Int(int i) { Prefix(kNumberType); WriteInt(i); return *this; }
|
||||
Writer& Uint(unsigned u) { Prefix(kNumberType); WriteUint(u); return *this; }
|
||||
Writer& Int64(int64_t i64) { Prefix(kNumberType); WriteInt64(i64); return *this; }
|
||||
Writer& Uint64(uint64_t u64) { Prefix(kNumberType); WriteUint64(u64); return *this; }
|
||||
bool Null() { Prefix(kNullType); return WriteNull(); }
|
||||
bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); }
|
||||
bool Int(int i) { Prefix(kNumberType); return WriteInt(i); }
|
||||
bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); }
|
||||
bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); }
|
||||
bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); }
|
||||
|
||||
//! Writes the given \c double value to the stream
|
||||
/*!
|
||||
@ -80,51 +80,48 @@ public:
|
||||
writer.SetDoublePrecision(12).Double(M_PI);
|
||||
\endcode
|
||||
\param d The value to be written.
|
||||
\return The Writer itself for fluent API.
|
||||
\return Whether it is succeed.
|
||||
*/
|
||||
Writer& Double(double d) { Prefix(kNumberType); WriteDouble(d); return *this; }
|
||||
bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); }
|
||||
|
||||
Writer& String(const Ch* str, SizeType length, bool copy = false) {
|
||||
bool String(const Ch* str, SizeType length, bool copy = false) {
|
||||
(void)copy;
|
||||
Prefix(kStringType);
|
||||
WriteString(str, length);
|
||||
return *this;
|
||||
return WriteString(str, length);
|
||||
}
|
||||
|
||||
Writer& StartObject() {
|
||||
bool StartObject() {
|
||||
Prefix(kObjectType);
|
||||
new (level_stack_.template Push<Level>()) Level(false);
|
||||
WriteStartObject();
|
||||
return *this;
|
||||
return WriteStartObject();
|
||||
}
|
||||
|
||||
Writer& EndObject(SizeType memberCount = 0) {
|
||||
bool EndObject(SizeType memberCount = 0) {
|
||||
(void)memberCount;
|
||||
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
|
||||
RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
|
||||
level_stack_.template Pop<Level>(1);
|
||||
WriteEndObject();
|
||||
bool ret = WriteEndObject();
|
||||
if (level_stack_.Empty()) // end of json text
|
||||
os_.Flush();
|
||||
return *this;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Writer& StartArray() {
|
||||
bool StartArray() {
|
||||
Prefix(kArrayType);
|
||||
new (level_stack_.template Push<Level>()) Level(true);
|
||||
WriteStartArray();
|
||||
return *this;
|
||||
return WriteStartArray();
|
||||
}
|
||||
|
||||
Writer& EndArray(SizeType elementCount = 0) {
|
||||
bool EndArray(SizeType elementCount = 0) {
|
||||
(void)elementCount;
|
||||
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
|
||||
RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
|
||||
level_stack_.template Pop<Level>(1);
|
||||
WriteEndArray();
|
||||
bool ret = WriteEndArray();
|
||||
if (level_stack_.Empty()) // end of json text
|
||||
os_.Flush();
|
||||
return *this;
|
||||
return ret;
|
||||
}
|
||||
//@}
|
||||
|
||||
@ -138,15 +135,18 @@ public:
|
||||
\see Double(), SetDoublePrecision(), GetDoublePrecision()
|
||||
\param d The value to be written
|
||||
\param precision The number of significant digits for this value
|
||||
\return The Writer itself for fluent API.
|
||||
\return Whether it is succeeded.
|
||||
*/
|
||||
Writer& Double(double d, int precision) {
|
||||
bool Double(double d, int precision) {
|
||||
int oldPrecision = GetDoublePrecision();
|
||||
return SetDoublePrecision(precision).Double(d).SetDoublePrecision(oldPrecision);
|
||||
SetDoublePrecision(precision);
|
||||
bool ret = Double(d);
|
||||
SetDoublePrecision(oldPrecision);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! Simpler but slower overload.
|
||||
Writer& String(const Ch* str) { return String(str, internal::StrLen(str)); }
|
||||
bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
|
||||
|
||||
//@}
|
||||
|
||||
@ -160,28 +160,29 @@ protected:
|
||||
|
||||
static const size_t kDefaultLevelDepth = 32;
|
||||
|
||||
void WriteNull() {
|
||||
os_.Put('n'); os_.Put('u'); os_.Put('l'); os_.Put('l');
|
||||
bool WriteNull() {
|
||||
os_.Put('n'); os_.Put('u'); os_.Put('l'); os_.Put('l'); return true;
|
||||
}
|
||||
|
||||
void WriteBool(bool b) {
|
||||
bool WriteBool(bool b) {
|
||||
if (b) {
|
||||
os_.Put('t'); os_.Put('r'); os_.Put('u'); os_.Put('e');
|
||||
}
|
||||
else {
|
||||
os_.Put('f'); os_.Put('a'); os_.Put('l'); os_.Put('s'); os_.Put('e');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WriteInt(int i) {
|
||||
bool WriteInt(int i) {
|
||||
if (i < 0) {
|
||||
os_.Put('-');
|
||||
i = -i;
|
||||
}
|
||||
WriteUint((unsigned)i);
|
||||
return WriteUint((unsigned)i);
|
||||
}
|
||||
|
||||
void WriteUint(unsigned u) {
|
||||
bool WriteUint(unsigned u) {
|
||||
char buffer[10];
|
||||
char *p = buffer;
|
||||
do {
|
||||
@ -193,17 +194,19 @@ protected:
|
||||
--p;
|
||||
os_.Put(*p);
|
||||
} while (p != buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WriteInt64(int64_t i64) {
|
||||
bool WriteInt64(int64_t i64) {
|
||||
if (i64 < 0) {
|
||||
os_.Put('-');
|
||||
i64 = -i64;
|
||||
}
|
||||
WriteUint64((uint64_t)i64);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WriteUint64(uint64_t u64) {
|
||||
bool WriteUint64(uint64_t u64) {
|
||||
char buffer[20];
|
||||
char *p = buffer;
|
||||
do {
|
||||
@ -215,6 +218,7 @@ protected:
|
||||
--p;
|
||||
os_.Put(*p);
|
||||
} while (p != buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@ -224,16 +228,17 @@ protected:
|
||||
#endif
|
||||
|
||||
//! \todo Optimization with custom double-to-string converter.
|
||||
void WriteDouble(double d) {
|
||||
bool WriteDouble(double d) {
|
||||
char buffer[100];
|
||||
int ret = RAPIDJSON_SNPRINTF(buffer, sizeof(buffer), "%.*g", doublePrecision_, d);
|
||||
RAPIDJSON_ASSERT(ret >= 1);
|
||||
for (int i = 0; i < ret; i++)
|
||||
os_.Put(buffer[i]);
|
||||
return true;
|
||||
}
|
||||
#undef RAPIDJSON_SNPRINTF
|
||||
|
||||
void WriteString(const Ch* str, SizeType length) {
|
||||
bool WriteString(const Ch* str, SizeType length) {
|
||||
static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
static const char escape[256] = {
|
||||
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
@ -266,12 +271,13 @@ protected:
|
||||
Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, os_);
|
||||
}
|
||||
os_.Put('\"');
|
||||
return true;
|
||||
}
|
||||
|
||||
void WriteStartObject() { os_.Put('{'); }
|
||||
void WriteEndObject() { os_.Put('}'); }
|
||||
void WriteStartArray() { os_.Put('['); }
|
||||
void WriteEndArray() { os_.Put(']'); }
|
||||
bool WriteStartObject() { os_.Put('{'); return true; }
|
||||
bool WriteEndObject() { os_.Put('}'); return true; }
|
||||
bool WriteStartArray() { os_.Put('['); return true; }
|
||||
bool WriteEndArray() { os_.Put(']'); return true; }
|
||||
|
||||
void Prefix(Type type) {
|
||||
(void)type;
|
||||
|
@ -8,7 +8,11 @@
|
||||
#define TEST_PLATFORM 0
|
||||
#define TEST_MISC 0
|
||||
|
||||
#if TEST_RAPIDJSON
|
||||
#define TEST_VERSION_CODE(x,y,z) \
|
||||
(((x)*100000) + ((y)*100) + (z))
|
||||
|
||||
// Only gcc >4.3 supports SSE4.2
|
||||
#if TEST_RAPIDJSON && !(defined(__GNUC__) && TEST_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) < TEST_VERSION_CODE(4,3,0))
|
||||
//#define RAPIDJSON_SSE2
|
||||
#define RAPIDJSON_SSE42
|
||||
#endif
|
||||
|
@ -179,8 +179,8 @@ RAPIDJSON_DIAG_OFF(effc++)
|
||||
struct ValueCounter : public BaseReaderHandler<> {
|
||||
ValueCounter() : count_(1) {} // root
|
||||
|
||||
void EndObject(SizeType memberCount) { count_ += memberCount * 2; }
|
||||
void EndArray(SizeType elementCount) { count_ += elementCount; }
|
||||
bool EndObject(SizeType memberCount) { count_ += memberCount * 2; return true; }
|
||||
bool EndArray(SizeType elementCount) { count_ += elementCount; return true; }
|
||||
|
||||
SizeType count_;
|
||||
};
|
||||
|
@ -13,10 +13,10 @@ RAPIDJSON_DIAG_OFF(effc++)
|
||||
template<bool expect>
|
||||
struct ParseBoolHandler : BaseReaderHandler<> {
|
||||
ParseBoolHandler() : step_(0) {}
|
||||
void Default() { FAIL(); }
|
||||
bool Default() { FAIL(); }
|
||||
// gcc 4.8.x generates warning in EXPECT_EQ(bool, bool) on this gtest version.
|
||||
// Workaround with EXPECT_TRUE().
|
||||
void Bool(bool b) { /*EXPECT_EQ(expect, b); */EXPECT_TRUE(expect == b); ++step_; }
|
||||
bool Bool(bool b) { /*EXPECT_EQ(expect, b); */EXPECT_TRUE(expect == b); ++step_; return true; }
|
||||
|
||||
unsigned step_;
|
||||
};
|
||||
@ -39,8 +39,8 @@ TEST(Reader, ParseFalse) {
|
||||
|
||||
struct ParseIntHandler : BaseReaderHandler<> {
|
||||
ParseIntHandler() : step_(0), actual_() {}
|
||||
void Default() { FAIL(); }
|
||||
void Int(int i) { actual_ = i; step_++; }
|
||||
bool Default() { ADD_FAILURE(); return false; }
|
||||
bool Int(int i) { actual_ = i; step_++; return true; }
|
||||
|
||||
unsigned step_;
|
||||
int actual_;
|
||||
@ -48,8 +48,8 @@ struct ParseIntHandler : BaseReaderHandler<> {
|
||||
|
||||
struct ParseUintHandler : BaseReaderHandler<> {
|
||||
ParseUintHandler() : step_(0), actual_() {}
|
||||
void Default() { FAIL(); }
|
||||
void Uint(unsigned i) { actual_ = i; step_++; }
|
||||
bool Default() { ADD_FAILURE(); return false; }
|
||||
bool Uint(unsigned i) { actual_ = i; step_++; return true; }
|
||||
|
||||
unsigned step_;
|
||||
unsigned actual_;
|
||||
@ -57,8 +57,8 @@ struct ParseUintHandler : BaseReaderHandler<> {
|
||||
|
||||
struct ParseInt64Handler : BaseReaderHandler<> {
|
||||
ParseInt64Handler() : step_(0), actual_() {}
|
||||
void Default() { FAIL(); }
|
||||
void Int64(int64_t i) { actual_ = i; step_++; }
|
||||
bool Default() { ADD_FAILURE(); return false; }
|
||||
bool Int64(int64_t i) { actual_ = i; step_++; return true; }
|
||||
|
||||
unsigned step_;
|
||||
int64_t actual_;
|
||||
@ -66,8 +66,8 @@ struct ParseInt64Handler : BaseReaderHandler<> {
|
||||
|
||||
struct ParseUint64Handler : BaseReaderHandler<> {
|
||||
ParseUint64Handler() : step_(0), actual_() {}
|
||||
void Default() { FAIL(); }
|
||||
void Uint64(uint64_t i) { actual_ = i; step_++; }
|
||||
bool Default() { ADD_FAILURE(); return false; }
|
||||
bool Uint64(uint64_t i) { actual_ = i; step_++; return true; }
|
||||
|
||||
unsigned step_;
|
||||
uint64_t actual_;
|
||||
@ -75,8 +75,8 @@ struct ParseUint64Handler : BaseReaderHandler<> {
|
||||
|
||||
struct ParseDoubleHandler : BaseReaderHandler<> {
|
||||
ParseDoubleHandler() : step_(0), actual_() {}
|
||||
void Default() { FAIL(); }
|
||||
void Double(double d) { actual_ = d; step_++; }
|
||||
bool Default() { ADD_FAILURE(); return false; }
|
||||
bool Double(double d) { actual_ = d; step_++; return true; }
|
||||
|
||||
unsigned step_;
|
||||
double actual_;
|
||||
@ -194,8 +194,8 @@ struct ParseStringHandler : BaseReaderHandler<Encoding> {
|
||||
ParseStringHandler(const ParseStringHandler&);
|
||||
ParseStringHandler& operator=(const ParseStringHandler&);
|
||||
|
||||
void Default() { FAIL(); }
|
||||
void String(const typename Encoding::Ch* str, size_t length, bool copy) {
|
||||
bool Default() { ADD_FAILURE(); return false; }
|
||||
bool String(const typename Encoding::Ch* str, size_t length, bool copy) {
|
||||
EXPECT_EQ(0, str_);
|
||||
if (copy) {
|
||||
str_ = (typename Encoding::Ch*)malloc((length + 1) * sizeof(typename Encoding::Ch));
|
||||
@ -205,6 +205,7 @@ struct ParseStringHandler : BaseReaderHandler<Encoding> {
|
||||
str_ = str;
|
||||
length_ = length;
|
||||
copy_ = copy;
|
||||
return true;
|
||||
}
|
||||
|
||||
const typename Encoding::Ch* str_;
|
||||
@ -411,10 +412,10 @@ template <unsigned count>
|
||||
struct ParseArrayHandler : BaseReaderHandler<> {
|
||||
ParseArrayHandler() : step_(0) {}
|
||||
|
||||
void Default() { FAIL(); }
|
||||
void Uint(unsigned i) { EXPECT_EQ(step_, i); step_++; }
|
||||
void StartArray() { EXPECT_EQ(0u, step_); step_++; }
|
||||
void EndArray(SizeType) { step_++; }
|
||||
bool Default() { ADD_FAILURE(); return false; }
|
||||
bool Uint(unsigned i) { EXPECT_EQ(step_, i); step_++; return true; }
|
||||
bool StartArray() { EXPECT_EQ(0u, step_); step_++; return true; }
|
||||
bool EndArray(SizeType) { step_++; return true; }
|
||||
|
||||
unsigned step_;
|
||||
};
|
||||
@ -462,42 +463,42 @@ TEST(Reader, ParseArray_Error) {
|
||||
struct ParseObjectHandler : BaseReaderHandler<> {
|
||||
ParseObjectHandler() : step_(0) {}
|
||||
|
||||
void Null() { EXPECT_EQ(8u, step_); step_++; }
|
||||
void Bool(bool b) {
|
||||
bool Null() { EXPECT_EQ(8u, step_); step_++; return true; }
|
||||
bool Bool(bool b) {
|
||||
switch(step_) {
|
||||
case 4: EXPECT_TRUE(b); step_++; break;
|
||||
case 6: EXPECT_FALSE(b); step_++; break;
|
||||
default: FAIL();
|
||||
case 4: EXPECT_TRUE(b); step_++; return true;
|
||||
case 6: EXPECT_FALSE(b); step_++; return true;
|
||||
default: ADD_FAILURE(); return false;
|
||||
}
|
||||
}
|
||||
void Int(int i) {
|
||||
bool Int(int i) {
|
||||
switch(step_) {
|
||||
case 10: EXPECT_EQ(123, i); step_++; break;
|
||||
case 15: EXPECT_EQ(1, i); step_++; break;
|
||||
case 16: EXPECT_EQ(2, i); step_++; break;
|
||||
case 17: EXPECT_EQ(3, i); step_++; break;
|
||||
default: FAIL();
|
||||
case 10: EXPECT_EQ(123, i); step_++; return true;
|
||||
case 15: EXPECT_EQ(1, i); step_++; return true;
|
||||
case 16: EXPECT_EQ(2, i); step_++; return true;
|
||||
case 17: EXPECT_EQ(3, i); step_++; return true;
|
||||
default: ADD_FAILURE(); return false;
|
||||
}
|
||||
}
|
||||
void Uint(unsigned i) { Int(i); }
|
||||
void Double(double d) { EXPECT_EQ(12u, step_); EXPECT_EQ(3.1416, d); step_++; }
|
||||
void String(const char* str, size_t, bool) {
|
||||
bool Uint(unsigned i) { return Int(i); }
|
||||
bool Double(double d) { EXPECT_EQ(12u, step_); EXPECT_EQ(3.1416, d); step_++; return true; }
|
||||
bool String(const char* str, size_t, bool) {
|
||||
switch(step_) {
|
||||
case 1: EXPECT_STREQ("hello", str); step_++; break;
|
||||
case 2: EXPECT_STREQ("world", str); step_++; break;
|
||||
case 3: EXPECT_STREQ("t", str); step_++; break;
|
||||
case 5: EXPECT_STREQ("f", str); step_++; break;
|
||||
case 7: EXPECT_STREQ("n", str); step_++; break;
|
||||
case 9: EXPECT_STREQ("i", str); step_++; break;
|
||||
case 11: EXPECT_STREQ("pi", str); step_++; break;
|
||||
case 13: EXPECT_STREQ("a", str); step_++; break;
|
||||
default: FAIL();
|
||||
case 1: EXPECT_STREQ("hello", str); step_++; return true;
|
||||
case 2: EXPECT_STREQ("world", str); step_++; return true;
|
||||
case 3: EXPECT_STREQ("t", str); step_++; return true;
|
||||
case 5: EXPECT_STREQ("f", str); step_++; return true;
|
||||
case 7: EXPECT_STREQ("n", str); step_++; return true;
|
||||
case 9: EXPECT_STREQ("i", str); step_++; return true;
|
||||
case 11: EXPECT_STREQ("pi", str); step_++; return true;
|
||||
case 13: EXPECT_STREQ("a", str); step_++; return true;
|
||||
default: ADD_FAILURE(); return false;
|
||||
}
|
||||
}
|
||||
void StartObject() { EXPECT_EQ(0u, step_); step_++; }
|
||||
void EndObject(SizeType memberCount) { EXPECT_EQ(19u, step_); EXPECT_EQ(7u, memberCount); step_++;}
|
||||
void StartArray() { EXPECT_EQ(14u, step_); step_++; }
|
||||
void EndArray(SizeType elementCount) { EXPECT_EQ(18u, step_); EXPECT_EQ(3u, elementCount); step_++;}
|
||||
bool StartObject() { EXPECT_EQ(0u, step_); step_++; return true; }
|
||||
bool EndObject(SizeType memberCount) { EXPECT_EQ(19u, step_); EXPECT_EQ(7u, memberCount); step_++; return true; }
|
||||
bool StartArray() { EXPECT_EQ(14u, step_); step_++; return true; }
|
||||
bool EndArray(SizeType elementCount) { EXPECT_EQ(18u, step_); EXPECT_EQ(3u, elementCount); step_++; return true; }
|
||||
|
||||
unsigned step_;
|
||||
};
|
||||
@ -529,9 +530,9 @@ TEST(Reader, ParseObject) {
|
||||
struct ParseEmptyObjectHandler : BaseReaderHandler<> {
|
||||
ParseEmptyObjectHandler() : step_(0) {}
|
||||
|
||||
void Default() { FAIL(); }
|
||||
void StartObject() { EXPECT_EQ(0u, step_); step_++; }
|
||||
void EndObject(SizeType) { EXPECT_EQ(1u, step_); step_++; }
|
||||
bool Default() { ADD_FAILURE(); return false; }
|
||||
bool StartObject() { EXPECT_EQ(0u, step_); step_++; return true; }
|
||||
bool EndObject(SizeType) { EXPECT_EQ(1u, step_); step_++; return true; }
|
||||
|
||||
unsigned step_;
|
||||
};
|
||||
|
@ -83,13 +83,13 @@ TEST(Writer,DoublePrecision) {
|
||||
buffer.Clear();
|
||||
}
|
||||
{ // explicit individual double precisions
|
||||
writer.SetDoublePrecision(2)
|
||||
.StartArray()
|
||||
.Double(1.2345,5)
|
||||
.Double(1.2345678,9)
|
||||
.Double(0.123456789012,12)
|
||||
.Double(1234567.8,8)
|
||||
.EndArray();
|
||||
writer.SetDoublePrecision(2);
|
||||
writer.StartArray();
|
||||
writer.Double(1.2345, 5);
|
||||
writer.Double(1.2345678, 9);
|
||||
writer.Double(0.123456789012, 12);
|
||||
writer.Double(1234567.8, 8);
|
||||
writer.EndArray();
|
||||
|
||||
EXPECT_EQ(writer.GetDoublePrecision(), 2);
|
||||
EXPECT_STREQ(json, buffer.GetString());
|
||||
|
Loading…
x
Reference in New Issue
Block a user