Commit 152db11a authored by Philipp A. Hartmann's avatar Philipp A. Hartmann

Merge branch 'upstream/master' into feature/exception-support

Conflicts:
	include/rapidjson/reader.h
parents 418a5829 b55fcbd3
...@@ -6,10 +6,12 @@ compiler: ...@@ -6,10 +6,12 @@ compiler:
env: env:
matrix: matrix:
- config=debug64 config_suffix=debug_x64_gmake - CONF=debug
- config=release64 config_suffix=release_x64_gmake - CONF=release
global: global:
secure: "CR3yKliFhwQLX+Zs1PCRcGej6jr4DIZsCqs9x6J2NN+U9Aow0gd/uiPBho/utgm+/TmSBji5n8FO/J3ORo34q4gC6EebTEaN4gCHNXVlIBJFw9x+Gs/lML5i8F2AoweFJY334OVaOf9qC8ZVJ8Z1nEwxj77fq3gcSLzRU3pIaS8=" # prepare for 32/64 bit multi-arch support
- BITS=64
- secure: "HrsaCb+N66EG1HR+LWH1u51SjaJyRwJEDzqJGYMB7LJ/bfqb9mWKF1fLvZGk46W5t7TVaXRDD5KHFx9DPWvKn4gRUVkwTHEy262ah5ORh8M6n/6VVVajeV/AYt2C0sswdkDBDO4Xq+xy5gdw3G8s1A4Inbm73pUh+6vx+7ltBbk="
before_install: before_install:
- sudo add-apt-repository -y ppa:codegear/release - sudo add-apt-repository -y ppa:codegear/release
...@@ -22,11 +24,11 @@ before_script: ...@@ -22,11 +24,11 @@ before_script:
- pushd build && premake4 'gmake' && popd - pushd build && premake4 'gmake' && popd
script: script:
- make -C build/gmake -f test.make - make -C build/gmake -f test.make config=${CONF}${BITS}
- make -C build/gmake -f example.make - make -C build/gmake -f example.make config=${CONF}${BITS}
- pushd bin - pushd bin
- ./unittest_${config_suffix} - ./unittest_${CONF}_x${BITS}_gmake
- valgrind --leak-check=full --error-exitcode=1 ./unittest_${config_suffix} - valgrind --leak-check=full --error-exitcode=1 ./unittest_${CONF}_x${BITS}_gmake
- if [ "$config" = "release64" ]; then ./perftest_${config_suffix}; fi - if [ "$CONF" = "release" ]; then ./perftest_${CONF}_x${BITS}_gmake; fi
- popd - popd
- ./build/travis-doxygen.sh; - ./build/travis-doxygen.sh;
...@@ -156,32 +156,10 @@ solution "example" ...@@ -156,32 +156,10 @@ solution "example"
configuration "gmake" configuration "gmake"
buildoptions "-Werror -Wall -Wextra -Weffc++ -Wswitch-default" buildoptions "-Werror -Wall -Wextra -Weffc++ -Wswitch-default"
project "condense" local examplepaths = os.matchdirs("../example/*")
kind "ConsoleApp" for _, examplepath in ipairs(examplepaths) do
files "../example/condense/*" project(path.getname(examplepath))
setTargetObjDir("../bin") kind "ConsoleApp"
files(examplepath .. "/*")
project "pretty" setTargetObjDir("../bin")
kind "ConsoleApp" end
files "../example/pretty/*"
setTargetObjDir("../bin")
project "prettyauto"
kind "ConsoleApp"
files "../example/prettyauto/*"
setTargetObjDir("../bin")
project "tutorial"
kind "ConsoleApp"
files "../example/tutorial/*"
setTargetObjDir("../bin")
project "serialize"
kind "ConsoleApp"
files "../example/serialize/*"
setTargetObjDir("../bin")
project "simpledom"
kind "ConsoleApp"
files "../example/simpledom/*"
setTargetObjDir("../bin")
...@@ -64,8 +64,8 @@ gh_pages_prepare() ...@@ -64,8 +64,8 @@ gh_pages_prepare()
git clone --single-branch -b gh-pages ${GHPAGES_URL} html git clone --single-branch -b gh-pages ${GHPAGES_URL} html
cd html cd html
# setup git config (with defaults) # setup git config (with defaults)
git config user.name "${GIT_NAME-travis}" git config --global user.name "${GIT_NAME-travis}"
git config user.email "${GIT_EMAIL-"travis@localhost"}" git config --global user.email "${GIT_EMAIL-"travis@localhost"}"
# clean working dir # clean working dir
rm -f .git/index rm -f .git/index
git clean -df git clean -df
...@@ -81,15 +81,19 @@ gh_pages_push() { ...@@ -81,15 +81,19 @@ gh_pages_push() {
# check for secure variables # check for secure variables
[ "${TRAVIS_SECURE_ENV_VARS}" = "true" ] || \ [ "${TRAVIS_SECURE_ENV_VARS}" = "true" ] || \
skip "Secure variables not available, not updating GitHub pages." skip "Secure variables not available, not updating GitHub pages."
# check for GitHub access token
[ "${GH_TOKEN+set}" = set ] || \ [ "${GH_TOKEN+set}" = set ] || \
skip "GitHub access token not available, not updating GitHub pages." skip "GitHub access token not available, not updating GitHub pages."
[ "${#GH_TOKEN}" -eq 40 ] || \
abort "GitHub token invalid: found ${#GH_TOKEN} characters, expected 40."
cd "${TRAVIS_BUILD_DIR}/doc/html"; cd "${TRAVIS_BUILD_DIR}/doc/html";
# setup credentials (hide in "set -x" mode) # setup credentials (hide in "set -x" mode)
git config core.askpass /bin/true git config core.askpass /bin/true
( set +x ; git config credential.${GHPAGES_URL}.username "${GH_TOKEN}" ) ( set +x ; git config credential.${GHPAGES_URL}.username "${GH_TOKEN}" )
# push to GitHub # push to GitHub
git push origin gh-pages git push origin gh-pages || \
skip "GitHub pages update failed, temporarily ignored."
} }
doxygen_install doxygen_install
......
#include "rapidjson/reader.h"
#include <iostream>
using namespace rapidjson;
using namespace std;
struct MyHandler {
bool Null() { cout << "Null()" << endl; return true; }
bool Bool(bool b) { cout << "Bool(" << boolalpha << b << ")" << endl; return true; }
bool Int(int i) { cout << "Int(" << i << ")" << endl; return true; }
bool Uint(unsigned u) { cout << "Uint(" << u << ")" << endl; return true; }
bool Int64(int64_t i) { cout << "Int64(" << i << ")" << endl; return true; }
bool Uint64(uint64_t u) { cout << "Uint64(" << u << ")" << endl; return true; }
bool Double(double d) { cout << "Double(" << d << ")" << endl; return true; }
bool String(const char* str, SizeType length, bool copy) {
cout << "String(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl;
return true;
}
bool StartObject() { cout << "StartObject()" << 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; }
};
int main() {
const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
MyHandler handler;
Reader reader;
StringStream ss(json);
reader.Parse(ss, handler);
return 0;
}
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include <iostream>
using namespace rapidjson;
using namespace std;
int main() {
StringBuffer s;
Writer<StringBuffer> writer(s);
writer.StartObject();
writer.String("hello");
writer.String("world");
writer.String("t");
writer.Bool(true);
writer.String("f");
writer.Bool(false);
writer.String("n");
writer.Null();
writer.String("i");
writer.Uint(123);
writer.String("pi");
writer.Double(3.1416);
writer.String("a");
writer.StartArray();
for (unsigned i = 0; i < 4; i++)
writer.Uint(i);
writer.EndArray();
writer.EndObject();
cout << s.GetString() << endl;
return 0;
}
...@@ -1015,44 +1015,45 @@ int z = a[0u].GetInt(); // This works too. ...@@ -1015,44 +1015,45 @@ int z = a[0u].GetInt(); // This works too.
\param handler An object implementing concept Handler. \param handler An object implementing concept Handler.
*/ */
template <typename Handler> template <typename Handler>
const GenericValue& Accept(Handler& handler) const { bool Accept(Handler& handler) const {
switch(GetType()) { switch(GetType()) {
case kNullType: handler.Null(); break; case kNullType: return handler.Null();
case kFalseType: handler.Bool(false); break; case kFalseType: return handler.Bool(false);
case kTrueType: handler.Bool(true); break; case kTrueType: return handler.Bool(true);
case kObjectType: case kObjectType:
handler.StartObject(); if (!handler.StartObject())
return false;
for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
handler.String(m->name.data_.s.str, m->name.data_.s.length, (m->name.flags_ & kCopyFlag) != 0); if (!handler.String(m->name.data_.s.str, m->name.data_.s.length, (m->name.flags_ & kCopyFlag) != 0))
m->value.Accept(handler); return false;
if (!m->value.Accept(handler))
return false;
} }
handler.EndObject(data_.o.size); return handler.EndObject(data_.o.size);
break;
case kArrayType: case kArrayType:
handler.StartArray(); if (!handler.StartArray())
return false;
for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
v->Accept(handler); if (!v->Accept(handler))
handler.EndArray(data_.a.size); return false;
break; return handler.EndArray(data_.a.size);
case kStringType: case kStringType:
handler.String(data_.s.str, data_.s.length, (flags_ & kCopyFlag) != 0); return handler.String(data_.s.str, data_.s.length, (flags_ & kCopyFlag) != 0);
break;
case kNumberType: case kNumberType:
if (IsInt()) handler.Int(data_.n.i.i); if (IsInt()) return handler.Int(data_.n.i.i);
else if (IsUint()) handler.Uint(data_.n.u.u); else if (IsUint()) return handler.Uint(data_.n.u.u);
else if (IsInt64()) handler.Int64(data_.n.i64); else if (IsInt64()) return handler.Int64(data_.n.i64);
else if (IsUint64()) handler.Uint64(data_.n.u64); else if (IsUint64()) return handler.Uint64(data_.n.u64);
else handler.Double(data_.n.d); else return handler.Double(data_.n.d);
break;
default: default:
RAPIDJSON_ASSERT(false); RAPIDJSON_ASSERT(false);
} }
return *this; return false;
} }
private: private:
...@@ -1357,33 +1358,36 @@ private: ...@@ -1357,33 +1358,36 @@ private:
friend class GenericValue<Encoding,Allocator>; // for deep copying friend class GenericValue<Encoding,Allocator>; // for deep copying
// Implementation of Handler // Implementation of Handler
void Null() { new (stack_.template Push<ValueType>()) ValueType(); } bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
void Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); } bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
void Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); } bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
void Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); } bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
void Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); } bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
void Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); } bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
void Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); } 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) if (copy)
new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator()); new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
else else
new (stack_.template Push<ValueType>()) ValueType(str, length); 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); 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());
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); ValueType* elements = stack_.template Pop<ValueType>(elementCount);
stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator()); stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
return true;
} }
private: private:
......
...@@ -51,29 +51,27 @@ public: ...@@ -51,29 +51,27 @@ public:
*/ */
//@{ //@{
PrettyWriter& Null() { PrettyPrefix(kNullType); Base::WriteNull(); return *this; } bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
PrettyWriter& Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); Base::WriteBool(b); return *this; } bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
PrettyWriter& Int(int i) { PrettyPrefix(kNumberType); Base::WriteInt(i); return *this; } bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
PrettyWriter& Uint(unsigned u) { PrettyPrefix(kNumberType); Base::WriteUint(u); return *this; } bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
PrettyWriter& Int64(int64_t i64) { PrettyPrefix(kNumberType); Base::WriteInt64(i64); return *this; } bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
PrettyWriter& Uint64(uint64_t u64) { PrettyPrefix(kNumberType); Base::WriteUint64(u64); return *this; } bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
PrettyWriter& Double(double d) { PrettyPrefix(kNumberType); Base::WriteDouble(d); return *this; } 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; (void)copy;
PrettyPrefix(kStringType); PrettyPrefix(kStringType);
Base::WriteString(str, length); return Base::WriteString(str, length);
return *this;
} }
PrettyWriter& StartObject() { bool StartObject() {
PrettyPrefix(kObjectType); PrettyPrefix(kObjectType);
new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false); new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
Base::WriteStartObject(); return Base::WriteStartObject();
return *this;
} }
PrettyWriter& EndObject(SizeType memberCount = 0) { bool EndObject(SizeType memberCount = 0) {
(void)memberCount; (void)memberCount;
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
...@@ -83,20 +81,20 @@ public: ...@@ -83,20 +81,20 @@ public:
Base::os_.Put('\n'); Base::os_.Put('\n');
WriteIndent(); WriteIndent();
} }
Base::WriteEndObject(); if (!Base::WriteEndObject())
return false;
if (Base::level_stack_.Empty()) // end of json text if (Base::level_stack_.Empty()) // end of json text
Base::os_.Flush(); Base::os_.Flush();
return *this; return true;
} }
PrettyWriter& StartArray() { bool StartArray() {
PrettyPrefix(kArrayType); PrettyPrefix(kArrayType);
new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true); new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
Base::WriteStartArray(); return Base::WriteStartArray();
return *this;
} }
PrettyWriter& EndArray(SizeType memberCount = 0) { bool EndArray(SizeType memberCount = 0) {
(void)memberCount; (void)memberCount;
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray); RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
...@@ -106,10 +104,11 @@ public: ...@@ -106,10 +104,11 @@ public:
Base::os_.Put('\n'); Base::os_.Put('\n');
WriteIndent(); WriteIndent();
} }
Base::WriteEndArray(); if (!Base::WriteEndArray())
return false;
if (Base::level_stack_.Empty()) // end of json text if (Base::level_stack_.Empty()) // end of json text
Base::os_.Flush(); Base::os_.Flush();
return *this; return true;
} }
//@} //@}
...@@ -118,12 +117,15 @@ public: ...@@ -118,12 +117,15 @@ public:
//@{ //@{
//! Simpler but slower overload. //! 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() //! Overridden for fluent API, see \ref Writer::Double()
PrettyWriter& Double(double d, int precision) { bool Double(double d, int precision) {
int oldPrecision = Base::GetDoublePrecision(); int oldPrecision = Base::GetDoublePrecision();
return SetDoublePrecision(precision).Double(d).SetDoublePrecision(oldPrecision); SetDoublePrecision(precision);
bool ret = Double(d);
SetDoublePrecision(oldPrecision);
return ret;
} }
//@} //@}
......
...@@ -71,22 +71,24 @@ enum ParseFlag { ...@@ -71,22 +71,24 @@ enum ParseFlag {
/*! \class rapidjson::Handler /*! \class rapidjson::Handler
\brief Concept for receiving events from GenericReader upon parsing. \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 \code
concept Handler { concept Handler {
typename Ch; typename Ch;
void Null(); bool Null();
void Bool(bool b); bool Bool(bool b);
void Int(int i); bool Int(int i);
void Uint(unsigned i); bool Uint(unsigned i);
void Int64(int64_t i); bool Int64(int64_t i);
void Uint64(uint64_t i); bool Uint64(uint64_t i);
void Double(double d); bool Double(double d);
void String(const Ch* str, SizeType length, bool copy); bool String(const Ch* str, SizeType length, bool copy);
void StartObject(); bool StartObject();
void EndObject(SizeType memberCount); bool EndObject(SizeType memberCount);
void StartArray(); bool StartArray();
void EndArray(SizeType elementCount); bool EndArray(SizeType elementCount);
}; };
\endcode \endcode
*/ */
...@@ -101,19 +103,19 @@ template<typename Encoding = UTF8<> > ...@@ -101,19 +103,19 @@ template<typename Encoding = UTF8<> >
struct BaseReaderHandler { struct BaseReaderHandler {
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
void Default() {} bool Default() { return true; }
void Null() { Default(); } bool Null() { return Default(); }
void Bool(bool) { Default(); } bool Bool(bool) { return Default(); }
void Int(int) { Default(); } bool Int(int) { return Default(); }
void Uint(unsigned) { Default(); } bool Uint(unsigned) { return Default(); }
void Int64(int64_t) { Default(); } bool Int64(int64_t) { return Default(); }
void Uint64(uint64_t) { Default(); } bool Uint64(uint64_t) { return Default(); }
void Double(double) { Default(); } bool Double(double) { return Default(); }
void String(const Ch*, SizeType, bool) { Default(); } bool String(const Ch*, SizeType, bool) { return Default(); }
void StartObject() { Default(); } bool StartObject() { return Default(); }
void EndObject(SizeType) { Default(); } bool EndObject(SizeType) { return Default(); }
void StartArray() { Default(); } bool StartArray() { return Default(); }
void EndArray(SizeType) { Default(); } bool EndArray(SizeType) { return Default(); }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -353,12 +355,16 @@ private: ...@@ -353,12 +355,16 @@ private:
void ParseObject(InputStream& is, Handler& handler) { void ParseObject(InputStream& is, Handler& handler) {
RAPIDJSON_ASSERT(is.Peek() == '{'); RAPIDJSON_ASSERT(is.Peek() == '{');
is.Take(); // Skip '{' is.Take(); // Skip '{'
handler.StartObject();
if (!handler.StartObject())
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
SkipWhitespace(is); SkipWhitespace(is);
if (is.Peek() == '}') { if (is.Peek() == '}') {
is.Take(); is.Take();
handler.EndObject(0); // empty object if (!handler.EndObject(0)) // empty object
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
return; return;
} }
...@@ -383,9 +389,13 @@ private: ...@@ -383,9 +389,13 @@ private:
++memberCount; ++memberCount;
switch(is.Take()) { switch (is.Take()) {
case ',': SkipWhitespace(is); break; 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()); default: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
} }
} }
...@@ -396,12 +406,16 @@ private: ...@@ -396,12 +406,16 @@ private:
void ParseArray(InputStream& is, Handler& handler) { void ParseArray(InputStream& is, Handler& handler) {
RAPIDJSON_ASSERT(is.Peek() == '['); RAPIDJSON_ASSERT(is.Peek() == '[');
is.Take(); // Skip '[' is.Take(); // Skip '['
handler.StartArray();
if (!handler.StartArray())
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
SkipWhitespace(is); SkipWhitespace(is);
if (is.Peek() == ']') { if (is.Peek() == ']') {
is.Take(); is.Take();
handler.EndArray(0); // empty array if (!handler.EndArray(0)) // empty array
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
return; return;
} }
...@@ -414,7 +428,11 @@ private: ...@@ -414,7 +428,11 @@ private:
switch (is.Take()) { switch (is.Take()) {
case ',': SkipWhitespace(is); break; 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()); default: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
} }
} }
...@@ -425,8 +443,10 @@ private: ...@@ -425,8 +443,10 @@ private:
RAPIDJSON_ASSERT(is.Peek() == 'n'); RAPIDJSON_ASSERT(is.Peek() == 'n');
is.Take(); is.Take();
if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l') if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l') {
handler.Null(); if (!handler.Null())
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
}
else else
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
} }
...@@ -436,10 +456,12 @@ private: ...@@ -436,10 +456,12 @@ private:
RAPIDJSON_ASSERT(is.Peek() == 't'); RAPIDJSON_ASSERT(is.Peek() == 't');
is.Take(); is.Take();
if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e') if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e') {
handler.Bool(true); if (!handler.Bool(true))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
}
else else
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
} }
template<unsigned parseFlags, typename InputStream, typename Handler> template<unsigned parseFlags, typename InputStream, typename Handler>
...@@ -447,8 +469,10 @@ private: ...@@ -447,8 +469,10 @@ private:
RAPIDJSON_ASSERT(is.Peek() == 'f'); RAPIDJSON_ASSERT(is.Peek() == 'f');
is.Take(); is.Take();
if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e') if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e') {
handler.Bool(false); if (!handler.Bool(false))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
}
else else
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
} }
...@@ -504,13 +528,15 @@ private: ...@@ -504,13 +528,15 @@ 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);
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 { 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;
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());
} }
} }
...@@ -712,6 +738,7 @@ private: ...@@ -712,6 +738,7 @@ private:
} }
// Finish parsing, call event according to the type of number. // Finish parsing, call event according to the type of number.
bool cont = true;
if (useDouble) { if (useDouble) {
int expSum = exp + expFrac; int expSum = exp + expFrac;
if (expSum < -308) { if (expSum < -308) {
...@@ -722,22 +749,24 @@ private: ...@@ -722,22 +749,24 @@ private:
else else
d *= internal::Pow10(expSum); d *= internal::Pow10(expSum);
handler.Double(minus ? -d : d); cont = handler.Double(minus ? -d : d);
} }
else { else {
if (try64bit) { if (try64bit) {
if (minus) if (minus)
handler.Int64(-(int64_t)i64); cont = handler.Int64(-(int64_t)i64);
else else
handler.Uint64(i64); cont = handler.Uint64(i64);
} }
else { else {
if (minus) if (minus)
handler.Int(-(int)i); cont = handler.Int(-(int)i);
else else
handler.Uint(i); cont = handler.Uint(i);
} }
} }
if (!cont)
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
} }
// Parse any JSON value // Parse any JSON value
......
...@@ -64,12 +64,12 @@ public: ...@@ -64,12 +64,12 @@ public:
*/ */
//@{ //@{
Writer& Null() { Prefix(kNullType); WriteNull(); return *this; } bool Null() { Prefix(kNullType); return WriteNull(); }
Writer& Bool(bool b) { Prefix(b ? kTrueType : kFalseType); WriteBool(b); return *this; } bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); }
Writer& Int(int i) { Prefix(kNumberType); WriteInt(i); return *this; } bool Int(int i) { Prefix(kNumberType); return WriteInt(i); }
Writer& Uint(unsigned u) { Prefix(kNumberType); WriteUint(u); return *this; } bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); }
Writer& Int64(int64_t i64) { Prefix(kNumberType); WriteInt64(i64); return *this; } bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); }
Writer& Uint64(uint64_t u64) { Prefix(kNumberType); WriteUint64(u64); return *this; } bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); }
//! Writes the given \c double value to the stream //! Writes the given \c double value to the stream
/*! /*!
...@@ -80,51 +80,48 @@ public: ...@@ -80,51 +80,48 @@ public:
writer.SetDoublePrecision(12).Double(M_PI); writer.SetDoublePrecision(12).Double(M_PI);
\endcode \endcode
\param d The value to be written. \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; (void)copy;
Prefix(kStringType); Prefix(kStringType);
WriteString(str, length); return WriteString(str, length);
return *this;
} }
Writer& StartObject() { bool StartObject() {
Prefix(kObjectType); Prefix(kObjectType);
new (level_stack_.template Push<Level>()) Level(false); new (level_stack_.template Push<Level>()) Level(false);
WriteStartObject(); return WriteStartObject();
return *this;
} }
Writer& EndObject(SizeType memberCount = 0) { bool EndObject(SizeType memberCount = 0) {
(void)memberCount; (void)memberCount;
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
level_stack_.template Pop<Level>(1); level_stack_.template Pop<Level>(1);
WriteEndObject(); bool ret = WriteEndObject();
if (level_stack_.Empty()) // end of json text if (level_stack_.Empty()) // end of json text
os_.Flush(); os_.Flush();
return *this; return ret;
} }
Writer& StartArray() { bool StartArray() {
Prefix(kArrayType); Prefix(kArrayType);
new (level_stack_.template Push<Level>()) Level(true); new (level_stack_.template Push<Level>()) Level(true);
WriteStartArray(); return WriteStartArray();
return *this;
} }
Writer& EndArray(SizeType elementCount = 0) { bool EndArray(SizeType elementCount = 0) {
(void)elementCount; (void)elementCount;
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray); RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
level_stack_.template Pop<Level>(1); level_stack_.template Pop<Level>(1);
WriteEndArray(); bool ret = WriteEndArray();
if (level_stack_.Empty()) // end of json text if (level_stack_.Empty()) // end of json text
os_.Flush(); os_.Flush();
return *this; return ret;
} }
//@} //@}
...@@ -138,15 +135,18 @@ public: ...@@ -138,15 +135,18 @@ public:
\see Double(), SetDoublePrecision(), GetDoublePrecision() \see Double(), SetDoublePrecision(), GetDoublePrecision()
\param d The value to be written \param d The value to be written
\param precision The number of significant digits for this value \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(); int oldPrecision = GetDoublePrecision();
return SetDoublePrecision(precision).Double(d).SetDoublePrecision(oldPrecision); SetDoublePrecision(precision);
bool ret = Double(d);
SetDoublePrecision(oldPrecision);
return ret;
} }
//! Simpler but slower overload. //! 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: ...@@ -160,28 +160,29 @@ protected:
static const size_t kDefaultLevelDepth = 32; static const size_t kDefaultLevelDepth = 32;
void WriteNull() { bool WriteNull() {
os_.Put('n'); os_.Put('u'); os_.Put('l'); os_.Put('l'); os_.Put('n'); os_.Put('u'); os_.Put('l'); os_.Put('l'); return true;
} }
void WriteBool(bool b) { bool WriteBool(bool b) {
if (b) { if (b) {
os_.Put('t'); os_.Put('r'); os_.Put('u'); os_.Put('e'); os_.Put('t'); os_.Put('r'); os_.Put('u'); os_.Put('e');
} }
else { else {
os_.Put('f'); os_.Put('a'); os_.Put('l'); os_.Put('s'); os_.Put('e'); 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) { if (i < 0) {
os_.Put('-'); os_.Put('-');
i = -i; i = -i;
} }
WriteUint((unsigned)i); return WriteUint((unsigned)i);
} }
void WriteUint(unsigned u) { bool WriteUint(unsigned u) {
char buffer[10]; char buffer[10];
char *p = buffer; char *p = buffer;
do { do {
...@@ -193,17 +194,19 @@ protected: ...@@ -193,17 +194,19 @@ protected:
--p; --p;
os_.Put(*p); os_.Put(*p);
} while (p != buffer); } while (p != buffer);
return true;
} }
void WriteInt64(int64_t i64) { bool WriteInt64(int64_t i64) {
if (i64 < 0) { if (i64 < 0) {
os_.Put('-'); os_.Put('-');
i64 = -i64; i64 = -i64;
} }
WriteUint64((uint64_t)i64); WriteUint64((uint64_t)i64);
return true;
} }
void WriteUint64(uint64_t u64) { bool WriteUint64(uint64_t u64) {
char buffer[20]; char buffer[20];
char *p = buffer; char *p = buffer;
do { do {
...@@ -215,6 +218,7 @@ protected: ...@@ -215,6 +218,7 @@ protected:
--p; --p;
os_.Put(*p); os_.Put(*p);
} while (p != buffer); } while (p != buffer);
return true;
} }
#ifdef _MSC_VER #ifdef _MSC_VER
...@@ -224,16 +228,17 @@ protected: ...@@ -224,16 +228,17 @@ protected:
#endif #endif
//! \todo Optimization with custom double-to-string converter. //! \todo Optimization with custom double-to-string converter.
void WriteDouble(double d) { bool WriteDouble(double d) {
char buffer[100]; char buffer[100];
int ret = RAPIDJSON_SNPRINTF(buffer, sizeof(buffer), "%.*g", doublePrecision_, d); int ret = RAPIDJSON_SNPRINTF(buffer, sizeof(buffer), "%.*g", doublePrecision_, d);
RAPIDJSON_ASSERT(ret >= 1); RAPIDJSON_ASSERT(ret >= 1);
for (int i = 0; i < ret; i++) for (int i = 0; i < ret; i++)
os_.Put(buffer[i]); os_.Put(buffer[i]);
return true;
} }
#undef RAPIDJSON_SNPRINTF #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 hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
static const char escape[256] = { static const char escape[256] = {
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
...@@ -266,12 +271,13 @@ protected: ...@@ -266,12 +271,13 @@ protected:
Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, os_); Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, os_);
} }
os_.Put('\"'); os_.Put('\"');
return true;
} }
void WriteStartObject() { os_.Put('{'); } bool WriteStartObject() { os_.Put('{'); return true; }
void WriteEndObject() { os_.Put('}'); } bool WriteEndObject() { os_.Put('}'); return true; }
void WriteStartArray() { os_.Put('['); } bool WriteStartArray() { os_.Put('['); return true; }
void WriteEndArray() { os_.Put(']'); } bool WriteEndArray() { os_.Put(']'); return true; }
void Prefix(Type type) { void Prefix(Type type) {
(void)type; (void)type;
......
...@@ -8,7 +8,11 @@ ...@@ -8,7 +8,11 @@
#define TEST_PLATFORM 0 #define TEST_PLATFORM 0
#define TEST_MISC 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_SSE2
#define RAPIDJSON_SSE42 #define RAPIDJSON_SSE42
#endif #endif
......
...@@ -179,8 +179,8 @@ RAPIDJSON_DIAG_OFF(effc++) ...@@ -179,8 +179,8 @@ RAPIDJSON_DIAG_OFF(effc++)
struct ValueCounter : public BaseReaderHandler<> { struct ValueCounter : public BaseReaderHandler<> {
ValueCounter() : count_(1) {} // root ValueCounter() : count_(1) {} // root
void EndObject(SizeType memberCount) { count_ += memberCount * 2; } bool EndObject(SizeType memberCount) { count_ += memberCount * 2; return true; }
void EndArray(SizeType elementCount) { count_ += elementCount; } bool EndArray(SizeType elementCount) { count_ += elementCount; return true; }
SizeType count_; SizeType count_;
}; };
......
...@@ -13,10 +13,10 @@ RAPIDJSON_DIAG_OFF(effc++) ...@@ -13,10 +13,10 @@ RAPIDJSON_DIAG_OFF(effc++)
template<bool expect> template<bool expect>
struct ParseBoolHandler : BaseReaderHandler<> { struct ParseBoolHandler : BaseReaderHandler<> {
ParseBoolHandler() : step_(0) {} ParseBoolHandler() : step_(0) {}
void Default() { FAIL(); } bool Default() { ADD_FAILURE(); return false; }
// gcc 4.8.x generates warning in EXPECT_EQ(bool, bool) on this gtest version. // gcc 4.8.x generates warning in EXPECT_EQ(bool, bool) on this gtest version.
// Workaround with EXPECT_TRUE(). // 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_; unsigned step_;
}; };
...@@ -39,8 +39,8 @@ TEST(Reader, ParseFalse) { ...@@ -39,8 +39,8 @@ TEST(Reader, ParseFalse) {
struct ParseIntHandler : BaseReaderHandler<> { struct ParseIntHandler : BaseReaderHandler<> {
ParseIntHandler() : step_(0), actual_() {} ParseIntHandler() : step_(0), actual_() {}
void Default() { FAIL(); } bool Default() { ADD_FAILURE(); return false; }
void Int(int i) { actual_ = i; step_++; } bool Int(int i) { actual_ = i; step_++; return true; }
unsigned step_; unsigned step_;
int actual_; int actual_;
...@@ -48,8 +48,8 @@ struct ParseIntHandler : BaseReaderHandler<> { ...@@ -48,8 +48,8 @@ struct ParseIntHandler : BaseReaderHandler<> {
struct ParseUintHandler : BaseReaderHandler<> { struct ParseUintHandler : BaseReaderHandler<> {
ParseUintHandler() : step_(0), actual_() {} ParseUintHandler() : step_(0), actual_() {}
void Default() { FAIL(); } bool Default() { ADD_FAILURE(); return false; }
void Uint(unsigned i) { actual_ = i; step_++; } bool Uint(unsigned i) { actual_ = i; step_++; return true; }
unsigned step_; unsigned step_;
unsigned actual_; unsigned actual_;
...@@ -57,8 +57,8 @@ struct ParseUintHandler : BaseReaderHandler<> { ...@@ -57,8 +57,8 @@ struct ParseUintHandler : BaseReaderHandler<> {
struct ParseInt64Handler : BaseReaderHandler<> { struct ParseInt64Handler : BaseReaderHandler<> {
ParseInt64Handler() : step_(0), actual_() {} ParseInt64Handler() : step_(0), actual_() {}
void Default() { FAIL(); } bool Default() { ADD_FAILURE(); return false; }
void Int64(int64_t i) { actual_ = i; step_++; } bool Int64(int64_t i) { actual_ = i; step_++; return true; }
unsigned step_; unsigned step_;
int64_t actual_; int64_t actual_;
...@@ -66,8 +66,8 @@ struct ParseInt64Handler : BaseReaderHandler<> { ...@@ -66,8 +66,8 @@ struct ParseInt64Handler : BaseReaderHandler<> {
struct ParseUint64Handler : BaseReaderHandler<> { struct ParseUint64Handler : BaseReaderHandler<> {
ParseUint64Handler() : step_(0), actual_() {} ParseUint64Handler() : step_(0), actual_() {}
void Default() { FAIL(); } bool Default() { ADD_FAILURE(); return false; }
void Uint64(uint64_t i) { actual_ = i; step_++; } bool Uint64(uint64_t i) { actual_ = i; step_++; return true; }
unsigned step_; unsigned step_;
uint64_t actual_; uint64_t actual_;
...@@ -75,8 +75,8 @@ struct ParseUint64Handler : BaseReaderHandler<> { ...@@ -75,8 +75,8 @@ struct ParseUint64Handler : BaseReaderHandler<> {
struct ParseDoubleHandler : BaseReaderHandler<> { struct ParseDoubleHandler : BaseReaderHandler<> {
ParseDoubleHandler() : step_(0), actual_() {} ParseDoubleHandler() : step_(0), actual_() {}
void Default() { FAIL(); } bool Default() { ADD_FAILURE(); return false; }
void Double(double d) { actual_ = d; step_++; } bool Double(double d) { actual_ = d; step_++; return true; }
unsigned step_; unsigned step_;
double actual_; double actual_;
...@@ -194,8 +194,8 @@ struct ParseStringHandler : BaseReaderHandler<Encoding> { ...@@ -194,8 +194,8 @@ struct ParseStringHandler : BaseReaderHandler<Encoding> {
ParseStringHandler(const ParseStringHandler&); ParseStringHandler(const ParseStringHandler&);
ParseStringHandler& operator=(const ParseStringHandler&); ParseStringHandler& operator=(const ParseStringHandler&);
void Default() { FAIL(); } bool Default() { ADD_FAILURE(); return false; }
void String(const typename Encoding::Ch* str, size_t length, bool copy) { bool String(const typename Encoding::Ch* str, size_t length, bool copy) {
EXPECT_EQ(0, str_); EXPECT_EQ(0, str_);
if (copy) { if (copy) {
str_ = (typename Encoding::Ch*)malloc((length + 1) * sizeof(typename Encoding::Ch)); str_ = (typename Encoding::Ch*)malloc((length + 1) * sizeof(typename Encoding::Ch));
...@@ -204,7 +204,8 @@ struct ParseStringHandler : BaseReaderHandler<Encoding> { ...@@ -204,7 +204,8 @@ struct ParseStringHandler : BaseReaderHandler<Encoding> {
else else
str_ = str; str_ = str;
length_ = length; length_ = length;
copy_ = copy; copy_ = copy;
return true;
} }
const typename Encoding::Ch* str_; const typename Encoding::Ch* str_;
...@@ -411,10 +412,10 @@ template <unsigned count> ...@@ -411,10 +412,10 @@ template <unsigned count>
struct ParseArrayHandler : BaseReaderHandler<> { struct ParseArrayHandler : BaseReaderHandler<> {
ParseArrayHandler() : step_(0) {} ParseArrayHandler() : step_(0) {}
void Default() { FAIL(); } bool Default() { ADD_FAILURE(); return false; }
void Uint(unsigned i) { EXPECT_EQ(step_, i); step_++; } bool Uint(unsigned i) { EXPECT_EQ(step_, i); step_++; return true; }
void StartArray() { EXPECT_EQ(0u, step_); step_++; } bool StartArray() { EXPECT_EQ(0u, step_); step_++; return true; }
void EndArray(SizeType) { step_++; } bool EndArray(SizeType) { step_++; return true; }
unsigned step_; unsigned step_;
}; };
...@@ -462,42 +463,42 @@ TEST(Reader, ParseArray_Error) { ...@@ -462,42 +463,42 @@ TEST(Reader, ParseArray_Error) {
struct ParseObjectHandler : BaseReaderHandler<> { struct ParseObjectHandler : BaseReaderHandler<> {
ParseObjectHandler() : step_(0) {} ParseObjectHandler() : step_(0) {}
void Null() { EXPECT_EQ(8u, step_); step_++; } bool Null() { EXPECT_EQ(8u, step_); step_++; return true; }
void Bool(bool b) { bool Bool(bool b) {
switch(step_) { switch(step_) {
case 4: EXPECT_TRUE(b); step_++; break; case 4: EXPECT_TRUE(b); step_++; return true;
case 6: EXPECT_FALSE(b); step_++; break; case 6: EXPECT_FALSE(b); step_++; return true;
default: FAIL(); default: ADD_FAILURE(); return false;
} }
} }
void Int(int i) { bool Int(int i) {
switch(step_) { switch(step_) {
case 10: EXPECT_EQ(123, i); step_++; break; case 10: EXPECT_EQ(123, i); step_++; return true;
case 15: EXPECT_EQ(1, i); step_++; break; case 15: EXPECT_EQ(1, i); step_++; return true;
case 16: EXPECT_EQ(2, i); step_++; break; case 16: EXPECT_EQ(2, i); step_++; return true;
case 17: EXPECT_EQ(3, i); step_++; break; case 17: EXPECT_EQ(3, i); step_++; return true;
default: FAIL(); default: ADD_FAILURE(); return false;
} }
} }
void Uint(unsigned i) { Int(i); } bool Uint(unsigned i) { return Int(i); }
void Double(double d) { EXPECT_EQ(12u, step_); EXPECT_EQ(3.1416, d); step_++; } bool Double(double d) { EXPECT_EQ(12u, step_); EXPECT_EQ(3.1416, d); step_++; return true; }
void String(const char* str, size_t, bool) { bool String(const char* str, size_t, bool) {
switch(step_) { switch(step_) {
case 1: EXPECT_STREQ("hello", str); step_++; break; case 1: EXPECT_STREQ("hello", str); step_++; return true;
case 2: EXPECT_STREQ("world", str); step_++; break; case 2: EXPECT_STREQ("world", str); step_++; return true;
case 3: EXPECT_STREQ("t", str); step_++; break; case 3: EXPECT_STREQ("t", str); step_++; return true;
case 5: EXPECT_STREQ("f", str); step_++; break; case 5: EXPECT_STREQ("f", str); step_++; return true;
case 7: EXPECT_STREQ("n", str); step_++; break; case 7: EXPECT_STREQ("n", str); step_++; return true;
case 9: EXPECT_STREQ("i", str); step_++; break; case 9: EXPECT_STREQ("i", str); step_++; return true;
case 11: EXPECT_STREQ("pi", str); step_++; break; case 11: EXPECT_STREQ("pi", str); step_++; return true;
case 13: EXPECT_STREQ("a", str); step_++; break; case 13: EXPECT_STREQ("a", str); step_++; return true;
default: FAIL(); default: ADD_FAILURE(); return false;
} }
} }
void StartObject() { EXPECT_EQ(0u, step_); step_++; } bool StartObject() { EXPECT_EQ(0u, step_); step_++; return true; }
void EndObject(SizeType memberCount) { EXPECT_EQ(19u, step_); EXPECT_EQ(7u, memberCount); step_++;} bool EndObject(SizeType memberCount) { EXPECT_EQ(19u, step_); EXPECT_EQ(7u, memberCount); step_++; return true; }
void StartArray() { EXPECT_EQ(14u, step_); step_++; } bool StartArray() { EXPECT_EQ(14u, step_); step_++; return true; }
void EndArray(SizeType elementCount) { EXPECT_EQ(18u, step_); EXPECT_EQ(3u, elementCount); step_++;} bool EndArray(SizeType elementCount) { EXPECT_EQ(18u, step_); EXPECT_EQ(3u, elementCount); step_++; return true; }
unsigned step_; unsigned step_;
}; };
...@@ -529,9 +530,9 @@ TEST(Reader, ParseObject) { ...@@ -529,9 +530,9 @@ TEST(Reader, ParseObject) {
struct ParseEmptyObjectHandler : BaseReaderHandler<> { struct ParseEmptyObjectHandler : BaseReaderHandler<> {
ParseEmptyObjectHandler() : step_(0) {} ParseEmptyObjectHandler() : step_(0) {}
void Default() { FAIL(); } bool Default() { ADD_FAILURE(); return false; }
void StartObject() { EXPECT_EQ(0u, step_); step_++; } bool StartObject() { EXPECT_EQ(0u, step_); step_++; return true; }
void EndObject(SizeType) { EXPECT_EQ(1u, step_); step_++; } bool EndObject(SizeType) { EXPECT_EQ(1u, step_); step_++; return true; }
unsigned step_; unsigned step_;
}; };
......
...@@ -83,13 +83,13 @@ TEST(Writer,DoublePrecision) { ...@@ -83,13 +83,13 @@ TEST(Writer,DoublePrecision) {
buffer.Clear(); buffer.Clear();
} }
{ // explicit individual double precisions { // explicit individual double precisions
writer.SetDoublePrecision(2) writer.SetDoublePrecision(2);
.StartArray() writer.StartArray();
.Double(1.2345,5) writer.Double(1.2345, 5);
.Double(1.2345678,9) writer.Double(1.2345678, 9);
.Double(0.123456789012,12) writer.Double(0.123456789012, 12);
.Double(1234567.8,8) writer.Double(1234567.8, 8);
.EndArray(); writer.EndArray();
EXPECT_EQ(writer.GetDoublePrecision(), 2); EXPECT_EQ(writer.GetDoublePrecision(), 2);
EXPECT_STREQ(json, buffer.GetString()); EXPECT_STREQ(json, buffer.GetString());
......
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