| #include "archiver.h" |
| #include <cassert> |
| #include <stack> |
| #include "rapidjson/document.h" |
| #include "rapidjson/prettywriter.h" |
| #include "rapidjson/stringbuffer.h" |
| |
| using namespace rapidjson; |
| |
| struct JsonReaderStackItem { |
| enum State { |
| BeforeStart, //!< An object/array is in the stack but it is not yet called by StartObject()/StartArray(). |
| Started, //!< An object/array is called by StartObject()/StartArray(). |
| Closed //!< An array is closed after read all element, but before EndArray(). |
| }; |
| |
| JsonReaderStackItem(const Value* value, State state) : value(value), state(state), index() {} |
| |
| const Value* value; |
| State state; |
| SizeType index; // For array iteration |
| }; |
| |
| typedef std::stack<JsonReaderStackItem> JsonReaderStack; |
| |
| #define DOCUMENT reinterpret_cast<Document*>(mDocument) |
| #define STACK (reinterpret_cast<JsonReaderStack*>(mStack)) |
| #define TOP (STACK->top()) |
| #define CURRENT (*TOP.value) |
| |
| JsonReader::JsonReader(const char* json) : mDocument(), mStack(), mError(false) { |
| mDocument = new Document; |
| DOCUMENT->Parse(json); |
| if (DOCUMENT->HasParseError()) |
| mError = true; |
| else { |
| mStack = new JsonReaderStack; |
| STACK->push(JsonReaderStackItem(DOCUMENT, JsonReaderStackItem::BeforeStart)); |
| } |
| } |
| |
| JsonReader::~JsonReader() { |
| delete DOCUMENT; |
| delete STACK; |
| } |
| |
| // Archive concept |
| JsonReader& JsonReader::StartObject() { |
| if (!mError) { |
| if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::BeforeStart) |
| TOP.state = JsonReaderStackItem::Started; |
| else |
| mError = true; |
| } |
| return *this; |
| } |
| |
| JsonReader& JsonReader::EndObject() { |
| if (!mError) { |
| if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started) |
| Next(); |
| else |
| mError = true; |
| } |
| return *this; |
| } |
| |
| JsonReader& JsonReader::Member(const char* name) { |
| if (!mError) { |
| if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started) { |
| Value::ConstMemberIterator memberItr = CURRENT.FindMember(name); |
| if (memberItr != CURRENT.MemberEnd()) |
| STACK->push(JsonReaderStackItem(&memberItr->value, JsonReaderStackItem::BeforeStart)); |
| else |
| mError = true; |
| } |
| else |
| mError = true; |
| } |
| return *this; |
| } |
| |
| bool JsonReader::HasMember(const char* name) const { |
| if (!mError && CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started) |
| return CURRENT.HasMember(name); |
| return false; |
| } |
| |
| JsonReader& JsonReader::StartArray(size_t* size) { |
| if (!mError) { |
| if (CURRENT.IsArray() && TOP.state == JsonReaderStackItem::BeforeStart) { |
| TOP.state = JsonReaderStackItem::Started; |
| if (size) |
| *size = CURRENT.Size(); |
| |
| if (!CURRENT.Empty()) { |
| const Value* value = &CURRENT[TOP.index]; |
| STACK->push(JsonReaderStackItem(value, JsonReaderStackItem::BeforeStart)); |
| } |
| else |
| TOP.state = JsonReaderStackItem::Closed; |
| } |
| else |
| mError = true; |
| } |
| return *this; |
| } |
| |
| JsonReader& JsonReader::EndArray() { |
| if (!mError) { |
| if (CURRENT.IsArray() && TOP.state == JsonReaderStackItem::Closed) |
| Next(); |
| else |
| mError = true; |
| } |
| return *this; |
| } |
| |
| JsonReader& JsonReader::operator&(bool& b) { |
| if (!mError) { |
| if (CURRENT.IsBool()) { |
| b = CURRENT.GetBool(); |
| Next(); |
| } |
| else |
| mError = true; |
| } |
| return *this; |
| } |
| |
| JsonReader& JsonReader::operator&(unsigned& u) { |
| if (!mError) { |
| if (CURRENT.IsUint()) { |
| u = CURRENT.GetUint(); |
| Next(); |
| } |
| else |
| mError = true; |
| } |
| return *this; |
| } |
| |
| JsonReader& JsonReader::operator&(int& i) { |
| if (!mError) { |
| if (CURRENT.IsInt()) { |
| i = CURRENT.GetInt(); |
| Next(); |
| } |
| else |
| mError = true; |
| } |
| return *this; |
| } |
| |
| JsonReader& JsonReader::operator&(double& d) { |
| if (!mError) { |
| if (CURRENT.IsNumber()) { |
| d = CURRENT.GetDouble(); |
| Next(); |
| } |
| else |
| mError = true; |
| } |
| return *this; |
| } |
| |
| JsonReader& JsonReader::operator&(std::string& s) { |
| if (!mError) { |
| if (CURRENT.IsString()) { |
| s = CURRENT.GetString(); |
| Next(); |
| } |
| else |
| mError = true; |
| } |
| return *this; |
| } |
| |
| JsonReader& JsonReader::SetNull() { |
| // This function is for JsonWriter only. |
| mError = true; |
| return *this; |
| } |
| |
| void JsonReader::Next() { |
| if (!mError) { |
| assert(!STACK->empty()); |
| STACK->pop(); |
| |
| if (!STACK->empty() && CURRENT.IsArray()) { |
| if (TOP.state == JsonReaderStackItem::Started) { // Otherwise means reading array item pass end |
| if (TOP.index < CURRENT.Size() - 1) { |
| const Value* value = &CURRENT[++TOP.index]; |
| STACK->push(JsonReaderStackItem(value, JsonReaderStackItem::BeforeStart)); |
| } |
| else |
| TOP.state = JsonReaderStackItem::Closed; |
| } |
| else |
| mError = true; |
| } |
| } |
| } |
| |
| #undef DOCUMENT |
| #undef STACK |
| #undef TOP |
| #undef CURRENT |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // JsonWriter |
| |
| #define WRITER reinterpret_cast<PrettyWriter<StringBuffer>*>(mWriter) |
| #define STREAM reinterpret_cast<StringBuffer*>(mStream) |
| |
| JsonWriter::JsonWriter() : mWriter(), mStream() { |
| mStream = new StringBuffer; |
| mWriter = new PrettyWriter<StringBuffer>(*STREAM); |
| } |
| |
| JsonWriter::~JsonWriter() { |
| delete WRITER; |
| delete STREAM; |
| } |
| |
| const char* JsonWriter::GetString() const { |
| return STREAM->GetString(); |
| } |
| |
| JsonWriter& JsonWriter::StartObject() { |
| WRITER->StartObject(); |
| return *this; |
| } |
| |
| JsonWriter& JsonWriter::EndObject() { |
| WRITER->EndObject(); |
| return *this; |
| } |
| |
| JsonWriter& JsonWriter::Member(const char* name) { |
| WRITER->String(name, static_cast<SizeType>(strlen(name))); |
| return *this; |
| } |
| |
| bool JsonWriter::HasMember(const char*) const { |
| // This function is for JsonReader only. |
| assert(false); |
| return false; |
| } |
| |
| JsonWriter& JsonWriter::StartArray(size_t*) { |
| WRITER->StartArray(); |
| return *this; |
| } |
| |
| JsonWriter& JsonWriter::EndArray() { |
| WRITER->EndArray(); |
| return *this; |
| } |
| |
| JsonWriter& JsonWriter::operator&(bool& b) { |
| WRITER->Bool(b); |
| return *this; |
| } |
| |
| JsonWriter& JsonWriter::operator&(unsigned& u) { |
| WRITER->Uint(u); |
| return *this; |
| } |
| |
| JsonWriter& JsonWriter::operator&(int& i) { |
| WRITER->Int(i); |
| return *this; |
| } |
| |
| JsonWriter& JsonWriter::operator&(double& d) { |
| WRITER->Double(d); |
| return *this; |
| } |
| |
| JsonWriter& JsonWriter::operator&(std::string& s) { |
| WRITER->String(s.c_str(), static_cast<SizeType>(s.size())); |
| return *this; |
| } |
| |
| JsonWriter& JsonWriter::SetNull() { |
| WRITER->Null(); |
| return *this; |
| } |
| |
| #undef STREAM |
| #undef WRITER |