Commit d4da07c5 authored by thebusytypist's avatar thebusytypist

Merge upstream/master.

parents face7240 2e0b3de8
...@@ -6,10 +6,13 @@ compiler: ...@@ -6,10 +6,13 @@ 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=" - GITHUB_REPO='miloyip/rapidjson'
# 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 +25,11 @@ before_script: ...@@ -22,11 +25,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")
...@@ -10,8 +10,13 @@ DOXYGEN_TAR=${DOXYGEN_VER}.linux.bin.tar.gz ...@@ -10,8 +10,13 @@ DOXYGEN_TAR=${DOXYGEN_VER}.linux.bin.tar.gz
DOXYGEN_URL="http://ftp.stack.nl/pub/users/dimitri/${DOXYGEN_TAR}" DOXYGEN_URL="http://ftp.stack.nl/pub/users/dimitri/${DOXYGEN_TAR}"
DOXYGEN_BIN="/usr/local/bin/doxygen" DOXYGEN_BIN="/usr/local/bin/doxygen"
GHPAGES_REPO="miloyip/rapidjson" : ${GITHUB_REPO:="miloyip/rapidjson"}
GHPAGES_URL="https://github.com/${GHPAGES_REPO}" GITHUB_HOST="github.com"
GITHUB_CLONE="git://${GITHUB_HOST}/${GITHUB_REPO}"
GITHUB_URL="https://${GITHUB_HOST}/${GITHUB_PUSH-${GITHUB_REPO}}"
# if not set, ignore password
#GIT_ASKPASS="${TRAVIS_BUILD_DIR}/gh_ignore_askpass.sh"
skip() { skip() {
echo "$@" 1>&2 echo "$@" 1>&2
...@@ -61,7 +66,8 @@ gh_pages_prepare() ...@@ -61,7 +66,8 @@ gh_pages_prepare()
cd "${TRAVIS_BUILD_DIR}/doc"; cd "${TRAVIS_BUILD_DIR}/doc";
[ ! -d "html" ] || \ [ ! -d "html" ] || \
abort "Doxygen target directory already exists." abort "Doxygen target directory already exists."
git clone --single-branch -b gh-pages ${GHPAGES_URL} html git --version
git clone --single-branch -b gh-pages "${GITHUB_CLONE}" html
cd html cd html
# setup git config (with defaults) # setup git config (with defaults)
git config user.name "${GIT_NAME-travis}" git config user.name "${GIT_NAME-travis}"
...@@ -77,17 +83,33 @@ gh_pages_commit() { ...@@ -77,17 +83,33 @@ gh_pages_commit() {
git diff-index --quiet HEAD || git commit -m "Automatic doxygen build"; git diff-index --quiet HEAD || git commit -m "Automatic doxygen build";
} }
gh_setup_askpass() {
cat > ${GIT_ASKPASS} <<EOF
#!/bin/bash
echo
exit 0
EOF
chmod a+x "$GIT_ASKPASS"
}
gh_pages_push() { 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 remote set-url --push origin "${GITHUB_URL}"
( set +x ; git config credential.${GHPAGES_URL}.username "${GH_TOKEN}" ) git config credential.helper 'store'
# ( set +x ; git config credential.username "${GH_TOKEN}" )
( set +x ; \
echo "https://${GH_TOKEN}:@${GITHUB_HOST}" > ${HOME}/.git-credentials ; \
chmod go-rw ${HOME}/.git-credentials )
# push to GitHub # push to GitHub
git push origin gh-pages git push origin gh-pages
} }
......
This diff is collapsed.
// JSON condenser exmaple
// This example parses JSON from stdin with validation,
// and re-output the JSON content to stdout with all string capitalized, and without whitespace.
#include "rapidjson/reader.h"
#include "rapidjson/writer.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/error/en.h"
#include <vector>
#include <cctype>
using namespace rapidjson;
template<typename OutputHandler>
struct CapitalizeFilter {
CapitalizeFilter(OutputHandler& out) : out_(out), buffer_() {}
bool Null() { return out_.Null(); }
bool Bool(bool b) { return out_.Bool(b); }
bool Int(int i) { return out_.Int(i); }
bool Uint(unsigned u) { return out_.Uint(u); }
bool Int64(int64_t i) { return out_.Int64(i); }
bool Uint64(uint64_t u) { return out_.Uint64(u); }
bool Double(double d) { return out_.Double(d); }
bool String(const char* str, SizeType length, bool) {
buffer_.clear();
for (SizeType i = 0; i < length; i++)
buffer_.push_back(std::toupper(str[i]));
return out_.String(&buffer_.front(), length, true); // true = output handler need to copy the string
}
bool StartObject() { return out_.StartObject(); }
bool EndObject(SizeType memberCount) { return out_.EndObject(memberCount); }
bool StartArray() { return out_.StartArray(); }
bool EndArray(SizeType elementCount) { return out_.EndArray(elementCount); }
OutputHandler& out_;
std::vector<char> buffer_;
private:
CapitalizeFilter(const CapitalizeFilter&);
CapitalizeFilter& operator=(const CapitalizeFilter&);
};
int main(int, char*[]) {
// Prepare JSON reader and input stream.
Reader reader;
char readBuffer[65536];
FileReadStream is(stdin, readBuffer, sizeof(readBuffer));
// Prepare JSON writer and output stream.
char writeBuffer[65536];
FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer));
Writer<FileWriteStream> writer(os);
// JSON reader parse from the input stream and let writer generate the output.
CapitalizeFilter<Writer<FileWriteStream> > filter(writer);
if (!reader.Parse(is, filter)) {
fprintf(stderr, "\nError(%u): %s\n", (unsigned)reader.GetErrorOffset(), GetParseError_En(reader.GetParseErrorCode()));
return 1;
}
return 0;
}
// Reading a message JSON with Reader (SAX-style API).
// The JSON should be an object with key-string pairs.
#include "rapidjson/reader.h"
#include "rapidjson/error/en.h"
#include <iostream>
#include <string>
#include <map>
using namespace std;
using namespace rapidjson;
typedef map<string, string> MessageMap;
#if defined(__GNUC__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
struct MessageHandler : public BaseReaderHandler<> {
MessageHandler() : messages_(), state_(kExpectObjectStart), name_() {}
bool StartObject() {
switch (state_) {
case kExpectObjectStart:
state_ = kExpectNameOrObjectEnd;
return true;
default:
return false;
}
}
bool String(const char* str, SizeType length, bool) {
switch (state_) {
case kExpectNameOrObjectEnd:
name_ = string(str, length);
state_ = kExpectValue;
return true;
case kExpectValue:
messages_.insert(MessageMap::value_type(name_, string(str, length)));
state_ = kExpectNameOrObjectEnd;
return true;
default:
return false;
}
}
bool EndObject(SizeType) { return state_ == kExpectNameOrObjectEnd; }
bool Default() { return false; } // All other events are invalid.
MessageMap messages_;
enum State {
kExpectObjectStart,
kExpectNameOrObjectEnd,
kExpectValue,
}state_;
std::string name_;
};
#if defined(__GNUC__)
RAPIDJSON_DIAG_POP
#endif
void ParseMessages(const char* json, MessageMap& messages) {
Reader reader;
MessageHandler handler;
StringStream ss(json);
if (reader.Parse(ss, handler))
messages.swap(handler.messages_); // Only change it if success.
else {
ParseErrorCode e = reader.GetParseErrorCode();
size_t o = reader.GetErrorOffset();
cout << "Error: " << GetParseError_En(e) << endl;;
cout << " at offset " << o << " near '" << string(json).substr(o, 10) << "...'" << endl;
}
}
int main() {
MessageMap messages;
const char* json1 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\" }";
cout << json1 << endl;
ParseMessages(json1, messages);
for (MessageMap::const_iterator itr = messages.begin(); itr != messages.end(); ++itr)
cout << itr->first << ": " << itr->second << endl;
cout << endl << "Parse a JSON with invalid schema." << endl;
const char* json2 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\", \"foo\" : {} }";
cout << json2 << endl;
ParseMessages(json2, messages);
return 0;
}
#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;
}
...@@ -501,7 +501,8 @@ public: ...@@ -501,7 +501,8 @@ public:
\see GenericStringRef, operator=(T) \see GenericStringRef, operator=(T)
*/ */
GenericValue& operator=(StringRefType str) { GenericValue& operator=(StringRefType str) {
return (*this).operator=<StringRefType>(str); GenericValue s(str);
return *this = s;
} }
//! Assignment with primitive types. //! Assignment with primitive types.
...@@ -519,9 +520,8 @@ public: ...@@ -519,9 +520,8 @@ public:
template <typename T> template <typename T>
RAPIDJSON_DISABLEIF_RETURN(internal::IsPointer<T>,GenericValue&) RAPIDJSON_DISABLEIF_RETURN(internal::IsPointer<T>,GenericValue&)
operator=(T value) { operator=(T value) {
this->~GenericValue(); GenericValue v(value);
new (this) GenericValue(value); return *this = v;
return *this;
} }
//! Deep-copy assignment from Value //! Deep-copy assignment from Value
...@@ -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:
...@@ -1210,7 +1211,7 @@ public: ...@@ -1210,7 +1211,7 @@ public:
/*! \param allocator Optional allocator for allocating stack memory. /*! \param allocator Optional allocator for allocating stack memory.
\param stackCapacity Initial capacity of stack in bytes. \param stackCapacity Initial capacity of stack in bytes.
*/ */
GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseErrorCode_(kParseErrorNone), errorOffset_(0) {} GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseResult_() {}
//!@name Parse from stream //!@name Parse from stream
//!@{ //!@{
...@@ -1226,16 +1227,11 @@ public: ...@@ -1226,16 +1227,11 @@ public:
GenericDocument& ParseStream(InputStream& is) { GenericDocument& ParseStream(InputStream& is) {
ValueType::SetNull(); // Remove existing root if exist ValueType::SetNull(); // Remove existing root if exist
GenericReader<SourceEncoding, Encoding, Allocator> reader(&GetAllocator()); GenericReader<SourceEncoding, Encoding, Allocator> reader(&GetAllocator());
if (reader.template Parse<parseFlags>(is, *this)) { ClearStackOnExit scope(*this);
parseResult_ = reader.template Parse<parseFlags>(is, *this);
if (parseResult_) {
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13. this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13.
parseErrorCode_ = kParseErrorNone;
errorOffset_ = 0;
}
else {
parseErrorCode_ = reader.GetParseErrorCode();
errorOffset_ = reader.GetErrorOffset();
ClearStack();
} }
return *this; return *this;
} }
...@@ -1331,14 +1327,14 @@ public: ...@@ -1331,14 +1327,14 @@ public:
//!@name Handling parse errors //!@name Handling parse errors
//!@{ //!@{
//! Whether a parse error was occured in the last parsing. //! Whether a parse error has occured in the last parsing.
bool HasParseError() const { return parseErrorCode_ != kParseErrorNone; } bool HasParseError() const { return parseResult_.IsError(); }
//! Get the message of parsing error. //! Get the \ref ParseErrorCode of last parsing.
ParseErrorCode GetParseError() const { return parseErrorCode_; } ParseErrorCode GetParseError() const { return parseResult_.Code(); }
//! Get the offset in character of the parsing error. //! Get the position of last parsing error in input, 0 otherwise.
size_t GetErrorOffset() const { return errorOffset_; } size_t GetErrorOffset() const { return parseResult_.Offset(); }
//!@} //!@}
...@@ -1349,38 +1345,51 @@ public: ...@@ -1349,38 +1345,51 @@ public:
size_t GetStackCapacity() const { return stack_.GetCapacity(); } size_t GetStackCapacity() const { return stack_.GetCapacity(); }
private: private:
// clear stack on any exit from ParseStream, e.g. due to exception
struct ClearStackOnExit {
explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
~ClearStackOnExit() { d_.ClearStack(); }
private:
ClearStackOnExit(const ClearStackOnExit&);
ClearStackOnExit& operator=(const ClearStackOnExit&);
GenericDocument& d_;
};
// callers of the following private Handler functions // callers of the following private Handler functions
template <typename,typename,typename> friend class GenericReader; // for parsing template <typename,typename,typename> friend class GenericReader; // for parsing
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:
...@@ -1397,8 +1406,7 @@ private: ...@@ -1397,8 +1406,7 @@ private:
static const size_t kDefaultStackCapacity = 1024; static const size_t kDefaultStackCapacity = 1024;
internal::Stack<Allocator> stack_; internal::Stack<Allocator> stack_;
ParseErrorCode parseErrorCode_; ParseResult parseResult_;
size_t errorOffset_;
}; };
//! GenericDocument with UTF8 encoding //! GenericDocument with UTF8 encoding
......
...@@ -32,12 +32,13 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro ...@@ -32,12 +32,13 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro
case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoidng in string."); case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
default: default:
......
#ifndef RAPIDJSON_ERROR_ERROR_H__ #ifndef RAPIDJSON_ERROR_ERROR_H__
#define RAPIDJSON_ERROR_ERROR_H__ #define RAPIDJSON_ERROR_ERROR_H__
#include "../reader.h" // ParseErrorCode
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_ERROR_CHARTYPE // RAPIDJSON_ERROR_CHARTYPE
...@@ -29,6 +27,85 @@ ...@@ -29,6 +27,85 @@
namespace rapidjson { namespace rapidjson {
///////////////////////////////////////////////////////////////////////////////
// ParseErrorCode
//! Error code of parsing.
/*! \see GenericReader::Parse, GenericReader::GetParseErrorCode
*/
enum ParseErrorCode {
kParseErrorNone = 0, //!< No error.
kParseErrorDocumentEmpty, //!< The document is empty.
kParseErrorDocumentRootNotObjectOrArray, //!< The document root must be either object or array.
kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values.
kParseErrorValueInvalid, //!< Invalid value.
kParseErrorObjectMissName, //!< Missing a name for object member.
kParseErrorObjectMissColon, //!< Missing a colon after a name of object member.
kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member.
kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element.
kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string.
kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid.
kParseErrorStringEscapeInvalid, //!< Invalid escape character in string.
kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string.
kParseErrorStringInvalidEncoding, //!< Invalid encoding in string.
kParseErrorNumberTooBig, //!< Number too big to be stored in double.
kParseErrorNumberMissFraction, //!< Miss fraction part in number.
kParseErrorNumberMissExponent, //!< Miss exponent in number.
kParseErrorTermination, //!< Parsing was terminated.
kParseErrorUnspecificSyntaxError //!< Unspecific syntax error.
};
//! Result of parsing (wraps ParseErrorCode)
/*!
\code
Document doc;
ParseResult ok = doc.Parse("[42]");
if (!ok) {
fprintf(stderr, "JSON parse error: %s (%u)",
GetParseError_En(ok.Code()), ok.Offset());
exit(EXIT_FAILURE);
}
\endcode
\see GenericReader::Parse, GenericDocument::Parse
*/
struct ParseResult {
//! Default constructor, no error.
ParseResult() : code_(kParseErrorNone), offset_(0) {}
//! Constructor to set an error.
ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
//! Get the error code.
ParseErrorCode Code() const { return code_; }
//! Get the error offset, if \ref IsError(), 0 otherwise.
size_t Offset() const { return offset_; }
//! Conversion to \c bool, returns \c true, iff !\ref IsError().
operator bool() const { return !IsError(); }
//! Whether the result is an error.
bool IsError() const { return code_ != kParseErrorNone; }
bool operator==(const ParseResult& that) const { return code_ == that.code_; }
bool operator==(ParseErrorCode code) const { return code_ == code; }
friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
//! Reset error code.
void Clear() { Set(kParseErrorNone); }
//! Update error code and offset.
void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
private:
ParseErrorCode code_;
size_t offset_;
};
//! Function pointer type of GetParseError(). //! Function pointer type of GetParseError().
/*! This is the prototype for GetParseError_X(), where X is a locale. /*! This is the prototype for GetParseError_X(), where X is a locale.
User can dynamically change locale in runtime, e.g.: User can dynamically change locale in runtime, e.g.:
......
...@@ -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;
} }
//@} //@}
......
This diff is collapsed.
...@@ -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
......
...@@ -197,8 +197,8 @@ RAPIDJSON_DIAG_OFF(effc++) ...@@ -197,8 +197,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_;
}; };
...@@ -756,42 +757,42 @@ struct IterativeParsingReaderHandler { ...@@ -756,42 +757,42 @@ struct IterativeParsingReaderHandler {
} }
bool IsNullTriggered; bool IsNullTriggered;
void Null() { IsNullTriggered = true; } bool Null() { IsNullTriggered = true; return true; }
bool IsBoolTriggered; bool IsBoolTriggered;
void Bool(bool) { IsBoolTriggered = true; } bool Bool(bool) { IsBoolTriggered = true; return true; }
bool IsIntTriggered; bool IsIntTriggered;
void Int(int) { IsIntTriggered = true; } bool Int(int) { IsIntTriggered = true; return true; }
bool IsUintTriggered; bool IsUintTriggered;
void Uint(unsigned) { IsUintTriggered = true; } bool Uint(unsigned) { IsUintTriggered = true; return true; }
bool IsInt64Triggered; bool IsInt64Triggered;
void Int64(int64_t) { IsInt64Triggered = true; } bool Int64(int64_t) { IsInt64Triggered = true; return true; }
bool IsUint64Triggered; bool IsUint64Triggered;
void Uint64(uint64_t) { IsUint64Triggered = true; } bool Uint64(uint64_t) { IsUint64Triggered = true; return true; }
bool IsDoubleTriggered; bool IsDoubleTriggered;
void Double(double) { IsDoubleTriggered = true; } bool Double(double) { IsDoubleTriggered = true; return true; }
bool IsStringTriggered; bool IsStringTriggered;
void String(const Ch*, SizeType, bool) { IsStringTriggered = true; } bool String(const Ch*, SizeType, bool) { IsStringTriggered = true; return true; }
bool IsStartObjectTriggered; bool IsStartObjectTriggered;
void StartObject() { IsStartObjectTriggered = true; } bool StartObject() { IsStartObjectTriggered = true; return true; }
bool IsEndObjectTriggered; bool IsEndObjectTriggered;
SizeType MemberCount; SizeType MemberCount;
void EndObject(SizeType c) { IsEndObjectTriggered = true; MemberCount = c; } bool EndObject(SizeType c) { IsEndObjectTriggered = true; MemberCount = c; return true; }
bool IsStartArrayTriggered; bool IsStartArrayTriggered;
void StartArray() { IsStartArrayTriggered = true; } bool StartArray() { IsStartArrayTriggered = true; return true; }
bool IsEndArrayTriggered; bool IsEndArrayTriggered;
SizeType ElementCount; SizeType ElementCount;
void EndArray(SizeType c) { IsEndArrayTriggered = true; ElementCount = c; } bool EndArray(SizeType c) { IsEndArrayTriggered = true; ElementCount = c; return true; }
}; };
#define ITERATIVE_PARSING_PREPARE_STATE_UNTIL(text, pos)\ #define ITERATIVE_PARSING_PREPARE_STATE_UNTIL(text, pos)\
......
...@@ -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