mirror of
https://github.com/Tencent/rapidjson.git
synced 2025-03-06 13:41:35 +01:00
Merge branch 'upstream/master' into feature/exception-support
Conflicts: include/rapidjson/reader.h
This commit is contained in:
commit
152db11ad6
18
.travis.yml
18
.travis.yml
@ -6,10 +6,12 @@ compiler:
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- config=debug64 config_suffix=debug_x64_gmake
|
||||
- config=release64 config_suffix=release_x64_gmake
|
||||
- CONF=debug
|
||||
- CONF=release
|
||||
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:
|
||||
- sudo add-apt-repository -y ppa:codegear/release
|
||||
@ -22,11 +24,11 @@ before_script:
|
||||
- pushd build && premake4 'gmake' && popd
|
||||
|
||||
script:
|
||||
- make -C build/gmake -f test.make
|
||||
- make -C build/gmake -f example.make
|
||||
- make -C build/gmake -f test.make config=${CONF}${BITS}
|
||||
- make -C build/gmake -f example.make config=${CONF}${BITS}
|
||||
- pushd bin
|
||||
- ./unittest_${config_suffix}
|
||||
- valgrind --leak-check=full --error-exitcode=1 ./unittest_${config_suffix}
|
||||
- if [ "$config" = "release64" ]; then ./perftest_${config_suffix}; fi
|
||||
- ./unittest_${CONF}_x${BITS}_gmake
|
||||
- valgrind --leak-check=full --error-exitcode=1 ./unittest_${CONF}_x${BITS}_gmake
|
||||
- if [ "$CONF" = "release" ]; then ./perftest_${CONF}_x${BITS}_gmake; fi
|
||||
- popd
|
||||
- ./build/travis-doxygen.sh;
|
||||
|
@ -156,32 +156,10 @@ solution "example"
|
||||
configuration "gmake"
|
||||
buildoptions "-Werror -Wall -Wextra -Weffc++ -Wswitch-default"
|
||||
|
||||
project "condense"
|
||||
kind "ConsoleApp"
|
||||
files "../example/condense/*"
|
||||
setTargetObjDir("../bin")
|
||||
|
||||
project "pretty"
|
||||
kind "ConsoleApp"
|
||||
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")
|
||||
local examplepaths = os.matchdirs("../example/*")
|
||||
for _, examplepath in ipairs(examplepaths) do
|
||||
project(path.getname(examplepath))
|
||||
kind "ConsoleApp"
|
||||
files(examplepath .. "/*")
|
||||
setTargetObjDir("../bin")
|
||||
end
|
||||
|
@ -64,8 +64,8 @@ gh_pages_prepare()
|
||||
git clone --single-branch -b gh-pages ${GHPAGES_URL} html
|
||||
cd html
|
||||
# setup git config (with defaults)
|
||||
git config user.name "${GIT_NAME-travis}"
|
||||
git config user.email "${GIT_EMAIL-"travis@localhost"}"
|
||||
git config --global user.name "${GIT_NAME-travis}"
|
||||
git config --global user.email "${GIT_EMAIL-"travis@localhost"}"
|
||||
# clean working dir
|
||||
rm -f .git/index
|
||||
git clean -df
|
||||
@ -81,15 +81,19 @@ gh_pages_push() {
|
||||
# check for secure variables
|
||||
[ "${TRAVIS_SECURE_ENV_VARS}" = "true" ] || \
|
||||
skip "Secure variables not available, not updating GitHub pages."
|
||||
# check for GitHub access token
|
||||
[ "${GH_TOKEN+set}" = set ] || \
|
||||
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";
|
||||
# setup credentials (hide in "set -x" mode)
|
||||
git config core.askpass /bin/true
|
||||
( set +x ; git config credential.${GHPAGES_URL}.username "${GH_TOKEN}" )
|
||||
# push to GitHub
|
||||
git push origin gh-pages
|
||||
git push origin gh-pages || \
|
||||
skip "GitHub pages update failed, temporarily ignored."
|
||||
}
|
||||
|
||||
doxygen_install
|
||||
|
34
example/simplereader/simplereader.cpp
Normal file
34
example/simplereader/simplereader.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#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;
|
||||
}
|
35
example/simplewriter/simplewriter.cpp
Normal file
35
example/simplewriter/simplewriter.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#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.
|
||||
\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:
|
||||
@ -1357,33 +1358,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;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
@ -71,22 +71,24 @@ enum ParseFlag {
|
||||
|
||||
/*! \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
|
||||
*/
|
||||
@ -101,19 +103,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(); }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -353,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;
|
||||
}
|
||||
|
||||
@ -383,9 +389,13 @@ private:
|
||||
|
||||
++memberCount;
|
||||
|
||||
switch(is.Take()) {
|
||||
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 +406,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;
|
||||
}
|
||||
|
||||
@ -414,7 +428,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());
|
||||
}
|
||||
}
|
||||
@ -425,8 +443,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);
|
||||
}
|
||||
@ -436,10 +456,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>
|
||||
@ -447,8 +469,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);
|
||||
}
|
||||
@ -504,13 +528,15 @@ private:
|
||||
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||
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);
|
||||
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:
|
||||
}
|
||||
|
||||
// Finish parsing, call event according to the type of number.
|
||||
bool cont = true;
|
||||
if (useDouble) {
|
||||
int expSum = exp + expFrac;
|
||||
if (expSum < -308) {
|
||||
@ -722,22 +749,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() { ADD_FAILURE(); return false; }
|
||||
// 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));
|
||||
@ -204,7 +204,8 @@ struct ParseStringHandler : BaseReaderHandler<Encoding> {
|
||||
else
|
||||
str_ = str;
|
||||
length_ = length;
|
||||
copy_ = copy;
|
||||
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