Commit d4da07c5 authored by thebusytypist's avatar thebusytypist

Merge upstream/master.

parents face7240 2e0b3de8
......@@ -6,10 +6,13 @@ 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="
- 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:
- sudo add-apt-repository -y ppa:codegear/release
......@@ -22,11 +25,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
......@@ -10,8 +10,13 @@ DOXYGEN_TAR=${DOXYGEN_VER}.linux.bin.tar.gz
DOXYGEN_URL="http://ftp.stack.nl/pub/users/dimitri/${DOXYGEN_TAR}"
DOXYGEN_BIN="/usr/local/bin/doxygen"
GHPAGES_REPO="miloyip/rapidjson"
GHPAGES_URL="https://github.com/${GHPAGES_REPO}"
: ${GITHUB_REPO:="miloyip/rapidjson"}
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() {
echo "$@" 1>&2
......@@ -61,7 +66,8 @@ gh_pages_prepare()
cd "${TRAVIS_BUILD_DIR}/doc";
[ ! -d "html" ] || \
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
# setup git config (with defaults)
git config user.name "${GIT_NAME-travis}"
......@@ -77,17 +83,33 @@ gh_pages_commit() {
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() {
# 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}" )
git remote set-url --push origin "${GITHUB_URL}"
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
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:
\see GenericStringRef, operator=(T)
*/
GenericValue& operator=(StringRefType str) {
return (*this).operator=<StringRefType>(str);
GenericValue s(str);
return *this = s;
}
//! Assignment with primitive types.
......@@ -519,9 +520,8 @@ public:
template <typename T>
RAPIDJSON_DISABLEIF_RETURN(internal::IsPointer<T>,GenericValue&)
operator=(T value) {
this->~GenericValue();
new (this) GenericValue(value);
return *this;
GenericValue v(value);
return *this = v;
}
//! Deep-copy assignment from Value
......@@ -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:
......@@ -1210,7 +1211,7 @@ public:
/*! \param allocator Optional allocator for allocating stack memory.
\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
//!@{
......@@ -1226,16 +1227,11 @@ public:
GenericDocument& ParseStream(InputStream& is) {
ValueType::SetNull(); // Remove existing root if exist
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
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;
}
......@@ -1331,14 +1327,14 @@ public:
//!@name Handling parse errors
//!@{
//! Whether a parse error was occured in the last parsing.
bool HasParseError() const { return parseErrorCode_ != kParseErrorNone; }
//! Whether a parse error has occured in the last parsing.
bool HasParseError() const { return parseResult_.IsError(); }
//! Get the message of parsing error.
ParseErrorCode GetParseError() const { return parseErrorCode_; }
//! Get the \ref ParseErrorCode of last parsing.
ParseErrorCode GetParseError() const { return parseResult_.Code(); }
//! Get the offset in character of the parsing error.
size_t GetErrorOffset() const { return errorOffset_; }
//! Get the position of last parsing error in input, 0 otherwise.
size_t GetErrorOffset() const { return parseResult_.Offset(); }
//!@}
......@@ -1349,38 +1345,51 @@ public:
size_t GetStackCapacity() const { return stack_.GetCapacity(); }
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
template <typename,typename,typename> friend class GenericReader; // for parsing
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); }
void String(const Ch* str, SizeType length, bool copy) {
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; }
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:
......@@ -1397,8 +1406,7 @@ private:
static const size_t kDefaultStackCapacity = 1024;
internal::Stack<Allocator> stack_;
ParseErrorCode parseErrorCode_;
size_t errorOffset_;
ParseResult parseResult_;
};
//! GenericDocument with UTF8 encoding
......
......@@ -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 kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character 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 kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part 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.");
default:
......
#ifndef RAPIDJSON_ERROR_ERROR_H__
#define RAPIDJSON_ERROR_ERROR_H__
#include "../reader.h" // ParseErrorCode
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_ERROR_CHARTYPE
......@@ -29,6 +27,85 @@
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().
/*! This is the prototype for GetParseError_X(), where X is a locale.
User can dynamically change locale in runtime, e.g.:
......
......@@ -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; }
PrettyWriter& String(const Ch* str, SizeType length, bool copy = false) {
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); }
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;
}
//@}
......
This diff is collapsed.
......@@ -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
......
......@@ -197,8 +197,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_;
};
......@@ -756,42 +757,42 @@ struct IterativeParsingReaderHandler {
}
bool IsNullTriggered;
void Null() { IsNullTriggered = true; }
bool Null() { IsNullTriggered = true; return true; }
bool IsBoolTriggered;
void Bool(bool) { IsBoolTriggered = true; }
bool Bool(bool) { IsBoolTriggered = true; return true; }
bool IsIntTriggered;
void Int(int) { IsIntTriggered = true; }
bool Int(int) { IsIntTriggered = true; return true; }
bool IsUintTriggered;
void Uint(unsigned) { IsUintTriggered = true; }
bool Uint(unsigned) { IsUintTriggered = true; return true; }
bool IsInt64Triggered;
void Int64(int64_t) { IsInt64Triggered = true; }
bool Int64(int64_t) { IsInt64Triggered = true; return true; }
bool IsUint64Triggered;
void Uint64(uint64_t) { IsUint64Triggered = true; }
bool Uint64(uint64_t) { IsUint64Triggered = true; return true; }
bool IsDoubleTriggered;
void Double(double) { IsDoubleTriggered = true; }
bool Double(double) { IsDoubleTriggered = true; return true; }
bool IsStringTriggered;
void String(const Ch*, SizeType, bool) { IsStringTriggered = true; }
bool String(const Ch*, SizeType, bool) { IsStringTriggered = true; return true; }
bool IsStartObjectTriggered;
void StartObject() { IsStartObjectTriggered = true; }
bool StartObject() { IsStartObjectTriggered = true; return true; }
bool IsEndObjectTriggered;
SizeType MemberCount;
void EndObject(SizeType c) { IsEndObjectTriggered = true; MemberCount = c; }
bool EndObject(SizeType c) { IsEndObjectTriggered = true; MemberCount = c; return true; }
bool IsStartArrayTriggered;
void StartArray() { IsStartArrayTriggered = true; }
bool StartArray() { IsStartArrayTriggered = true; return true; }
bool IsEndArrayTriggered;
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)\
......
......@@ -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());
......
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