summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/rapidjson/example
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/rapidjson/example')
-rw-r--r--3rdparty/rapidjson/example/CMakeLists.txt10
-rw-r--r--3rdparty/rapidjson/example/archiver/archiver.cpp292
-rw-r--r--3rdparty/rapidjson/example/archiver/archiver.h145
-rw-r--r--3rdparty/rapidjson/example/archiver/archivertest.cpp287
-rw-r--r--3rdparty/rapidjson/example/jsonx/jsonx.cpp2
-rw-r--r--3rdparty/rapidjson/example/lookaheadparser/lookaheadparser.cpp350
-rw-r--r--3rdparty/rapidjson/example/parsebyparts/parsebyparts.cpp9
-rw-r--r--3rdparty/rapidjson/example/schemavalidator/schemavalidator.cpp127
-rw-r--r--3rdparty/rapidjson/example/simplepullreader/simplepullreader.cpp53
-rw-r--r--3rdparty/rapidjson/example/sortkeys/sortkeys.cpp62
-rw-r--r--3rdparty/rapidjson/example/traverseaspointer.cpp39
-rw-r--r--3rdparty/rapidjson/example/tutorial/tutorial.cpp2
12 files changed, 1370 insertions, 8 deletions
diff --git a/3rdparty/rapidjson/example/CMakeLists.txt b/3rdparty/rapidjson/example/CMakeLists.txt
index 4d448ccc0f4..9f53c9aadc6 100644
--- a/3rdparty/rapidjson/example/CMakeLists.txt
+++ b/3rdparty/rapidjson/example/CMakeLists.txt
@@ -10,6 +10,7 @@ set(EXAMPLES
filterkey
filterkeydom
jsonx
+ lookaheadparser
messagereader
parsebyparts
pretty
@@ -18,19 +19,22 @@ set(EXAMPLES
serialize
simpledom
simplereader
+ simplepullreader
simplewriter
+ sortkeys
tutorial)
include_directories("../include/")
add_definitions(-D__STDC_FORMAT_MACROS)
+set_property(DIRECTORY PROPERTY COMPILE_OPTIONS ${EXTRA_CXX_FLAGS})
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -Werror -Wall -Wextra -Weffc++ -Wswitch-default")
-elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal -Wimplicit-fallthrough -Weverything")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
+add_executable(archivertest archiver/archiver.cpp archiver/archivertest.cpp)
+
foreach (example ${EXAMPLES})
add_executable(${example} ${example}/${example}.cpp)
endforeach()
diff --git a/3rdparty/rapidjson/example/archiver/archiver.cpp b/3rdparty/rapidjson/example/archiver/archiver.cpp
new file mode 100644
index 00000000000..59ae4c41016
--- /dev/null
+++ b/3rdparty/rapidjson/example/archiver/archiver.cpp
@@ -0,0 +1,292 @@
+#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
diff --git a/3rdparty/rapidjson/example/archiver/archiver.h b/3rdparty/rapidjson/example/archiver/archiver.h
new file mode 100644
index 00000000000..285ca73d6ab
--- /dev/null
+++ b/3rdparty/rapidjson/example/archiver/archiver.h
@@ -0,0 +1,145 @@
+#ifndef ARCHIVER_H_
+#define ARCHIVER_H_
+
+#include <cstddef>
+#include <string>
+
+/**
+\class Archiver
+\brief Archiver concept
+
+Archiver can be a reader or writer for serialization or deserialization respectively.
+
+class Archiver {
+public:
+ /// \returns true if the archiver is in normal state. false if it has errors.
+ operator bool() const;
+
+ /// Starts an object
+ Archiver& StartObject();
+
+ /// After calling StartObject(), assign a member with a name
+ Archiver& Member(const char* name);
+
+ /// After calling StartObject(), check if a member presents
+ bool HasMember(const char* name) const;
+
+ /// Ends an object
+ Archiver& EndObject();
+
+ /// Starts an array
+ /// \param size If Archiver::IsReader is true, the size of array is written.
+ Archiver& StartArray(size_t* size = 0);
+
+ /// Ends an array
+ Archiver& EndArray();
+
+ /// Read/Write primitive types.
+ Archiver& operator&(bool& b);
+ Archiver& operator&(unsigned& u);
+ Archiver& operator&(int& i);
+ Archiver& operator&(double& d);
+ Archiver& operator&(std::string& s);
+
+ /// Write primitive types.
+ Archiver& SetNull();
+
+ //! Whether it is a reader.
+ static const bool IsReader;
+
+ //! Whether it is a writer.
+ static const bool IsWriter;
+};
+*/
+
+/// Represents a JSON reader which implements Archiver concept.
+class JsonReader {
+public:
+ /// Constructor.
+ /**
+ \param json A non-const source json string for in-situ parsing.
+ \note in-situ means the source JSON string will be modified after parsing.
+ */
+ JsonReader(const char* json);
+
+ /// Destructor.
+ ~JsonReader();
+
+ // Archive concept
+
+ operator bool() const { return !mError; }
+
+ JsonReader& StartObject();
+ JsonReader& Member(const char* name);
+ bool HasMember(const char* name) const;
+ JsonReader& EndObject();
+
+ JsonReader& StartArray(size_t* size = 0);
+ JsonReader& EndArray();
+
+ JsonReader& operator&(bool& b);
+ JsonReader& operator&(unsigned& u);
+ JsonReader& operator&(int& i);
+ JsonReader& operator&(double& d);
+ JsonReader& operator&(std::string& s);
+
+ JsonReader& SetNull();
+
+ static const bool IsReader = true;
+ static const bool IsWriter = !IsReader;
+
+private:
+ JsonReader(const JsonReader&);
+ JsonReader& operator=(const JsonReader&);
+
+ void Next();
+
+ // PIMPL
+ void* mDocument; ///< DOM result of parsing.
+ void* mStack; ///< Stack for iterating the DOM
+ bool mError; ///< Whether an error has occurred.
+};
+
+class JsonWriter {
+public:
+ /// Constructor.
+ JsonWriter();
+
+ /// Destructor.
+ ~JsonWriter();
+
+ /// Obtains the serialized JSON string.
+ const char* GetString() const;
+
+ // Archive concept
+
+ operator bool() const { return true; }
+
+ JsonWriter& StartObject();
+ JsonWriter& Member(const char* name);
+ bool HasMember(const char* name) const;
+ JsonWriter& EndObject();
+
+ JsonWriter& StartArray(size_t* size = 0);
+ JsonWriter& EndArray();
+
+ JsonWriter& operator&(bool& b);
+ JsonWriter& operator&(unsigned& u);
+ JsonWriter& operator&(int& i);
+ JsonWriter& operator&(double& d);
+ JsonWriter& operator&(std::string& s);
+ JsonWriter& SetNull();
+
+ static const bool IsReader = false;
+ static const bool IsWriter = !IsReader;
+
+private:
+ JsonWriter(const JsonWriter&);
+ JsonWriter& operator=(const JsonWriter&);
+
+ // PIMPL idiom
+ void* mWriter; ///< JSON writer.
+ void* mStream; ///< Stream buffer.
+};
+
+#endif // ARCHIVER_H__
diff --git a/3rdparty/rapidjson/example/archiver/archivertest.cpp b/3rdparty/rapidjson/example/archiver/archivertest.cpp
new file mode 100644
index 00000000000..417a421a318
--- /dev/null
+++ b/3rdparty/rapidjson/example/archiver/archivertest.cpp
@@ -0,0 +1,287 @@
+#include "archiver.h"
+#include <iostream>
+#include <vector>
+
+//////////////////////////////////////////////////////////////////////////////
+// Test1: simple object
+
+struct Student {
+ Student() : name(), age(), height(), canSwim() {}
+ Student(const std::string name, unsigned age, double height, bool canSwim) :
+ name(name), age(age), height(height), canSwim(canSwim)
+ {}
+
+ std::string name;
+ unsigned age;
+ double height;
+ bool canSwim;
+};
+
+template <typename Archiver>
+Archiver& operator&(Archiver& ar, Student& s) {
+ ar.StartObject();
+ ar.Member("name") & s.name;
+ ar.Member("age") & s.age;
+ ar.Member("height") & s.height;
+ ar.Member("canSwim") & s.canSwim;
+ return ar.EndObject();
+}
+
+std::ostream& operator<<(std::ostream& os, const Student& s) {
+ return os << s.name << " " << s.age << " " << s.height << " " << s.canSwim;
+}
+
+void test1() {
+ std::string json;
+
+ // Serialize
+ {
+ Student s("Lua", 9, 150.5, true);
+
+ JsonWriter writer;
+ writer & s;
+ json = writer.GetString();
+ std::cout << json << std::endl;
+ }
+
+ // Deserialize
+ {
+ Student s;
+ JsonReader reader(json.c_str());
+ reader & s;
+ std::cout << s << std::endl;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Test2: std::vector <=> JSON array
+//
+// You can map a JSON array to other data structures as well
+
+struct Group {
+ Group() : groupName(), students() {}
+ std::string groupName;
+ std::vector<Student> students;
+};
+
+template <typename Archiver>
+Archiver& operator&(Archiver& ar, Group& g) {
+ ar.StartObject();
+
+ ar.Member("groupName");
+ ar & g.groupName;
+
+ ar.Member("students");
+ size_t studentCount = g.students.size();
+ ar.StartArray(&studentCount);
+ if (ar.IsReader)
+ g.students.resize(studentCount);
+ for (size_t i = 0; i < studentCount; i++)
+ ar & g.students[i];
+ ar.EndArray();
+
+ return ar.EndObject();
+}
+
+std::ostream& operator<<(std::ostream& os, const Group& g) {
+ os << g.groupName << std::endl;
+ for (std::vector<Student>::const_iterator itr = g.students.begin(); itr != g.students.end(); ++itr)
+ os << *itr << std::endl;
+ return os;
+}
+
+void test2() {
+ std::string json;
+
+ // Serialize
+ {
+ Group g;
+ g.groupName = "Rainbow";
+
+ Student s1("Lua", 9, 150.5, true);
+ Student s2("Mio", 7, 120.0, false);
+ g.students.push_back(s1);
+ g.students.push_back(s2);
+
+ JsonWriter writer;
+ writer & g;
+ json = writer.GetString();
+ std::cout << json << std::endl;
+ }
+
+ // Deserialize
+ {
+ Group g;
+ JsonReader reader(json.c_str());
+ reader & g;
+ std::cout << g << std::endl;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Test3: polymorphism & friend
+//
+// Note that friendship is not necessary but make things simpler.
+
+class Shape {
+public:
+ virtual ~Shape() {}
+ virtual const char* GetType() const = 0;
+ virtual void Print(std::ostream& os) const = 0;
+
+protected:
+ Shape() : x_(), y_() {}
+ Shape(double x, double y) : x_(x), y_(y) {}
+
+ template <typename Archiver>
+ friend Archiver& operator&(Archiver& ar, Shape& s);
+
+ double x_, y_;
+};
+
+template <typename Archiver>
+Archiver& operator&(Archiver& ar, Shape& s) {
+ ar.Member("x") & s.x_;
+ ar.Member("y") & s.y_;
+ return ar;
+}
+
+class Circle : public Shape {
+public:
+ Circle() : radius_() {}
+ Circle(double x, double y, double radius) : Shape(x, y), radius_(radius) {}
+ ~Circle() {}
+
+ const char* GetType() const { return "Circle"; }
+
+ void Print(std::ostream& os) const {
+ os << "Circle (" << x_ << ", " << y_ << ")" << " radius = " << radius_;
+ }
+
+private:
+ template <typename Archiver>
+ friend Archiver& operator&(Archiver& ar, Circle& c);
+
+ double radius_;
+};
+
+template <typename Archiver>
+Archiver& operator&(Archiver& ar, Circle& c) {
+ ar & static_cast<Shape&>(c);
+ ar.Member("radius") & c.radius_;
+ return ar;
+}
+
+class Box : public Shape {
+public:
+ Box() : width_(), height_() {}
+ Box(double x, double y, double width, double height) : Shape(x, y), width_(width), height_(height) {}
+ ~Box() {}
+
+ const char* GetType() const { return "Box"; }
+
+ void Print(std::ostream& os) const {
+ os << "Box (" << x_ << ", " << y_ << ")" << " width = " << width_ << " height = " << height_;
+ }
+
+private:
+ template <typename Archiver>
+ friend Archiver& operator&(Archiver& ar, Box& b);
+
+ double width_, height_;
+};
+
+template <typename Archiver>
+Archiver& operator&(Archiver& ar, Box& b) {
+ ar & static_cast<Shape&>(b);
+ ar.Member("width") & b.width_;
+ ar.Member("height") & b.height_;
+ return ar;
+}
+
+class Canvas {
+public:
+ Canvas() : shapes_() {}
+ ~Canvas() { Clear(); }
+
+ void Clear() {
+ for (std::vector<Shape*>::iterator itr = shapes_.begin(); itr != shapes_.end(); ++itr)
+ delete *itr;
+ }
+
+ void AddShape(Shape* shape) { shapes_.push_back(shape); }
+
+ void Print(std::ostream& os) {
+ for (std::vector<Shape*>::iterator itr = shapes_.begin(); itr != shapes_.end(); ++itr) {
+ (*itr)->Print(os);
+ std::cout << std::endl;
+ }
+ }
+
+private:
+ template <typename Archiver>
+ friend Archiver& operator&(Archiver& ar, Canvas& c);
+
+ std::vector<Shape*> shapes_;
+};
+
+template <typename Archiver>
+Archiver& operator&(Archiver& ar, Shape*& shape) {
+ std::string type = ar.IsReader ? "" : shape->GetType();
+ ar.StartObject();
+ ar.Member("type") & type;
+ if (type == "Circle") {
+ if (ar.IsReader) shape = new Circle;
+ ar & static_cast<Circle&>(*shape);
+ }
+ else if (type == "Box") {
+ if (ar.IsReader) shape = new Box;
+ ar & static_cast<Box&>(*shape);
+ }
+ return ar.EndObject();
+}
+
+template <typename Archiver>
+Archiver& operator&(Archiver& ar, Canvas& c) {
+ size_t shapeCount = c.shapes_.size();
+ ar.StartArray(&shapeCount);
+ if (ar.IsReader) {
+ c.Clear();
+ c.shapes_.resize(shapeCount);
+ }
+ for (size_t i = 0; i < shapeCount; i++)
+ ar & c.shapes_[i];
+ return ar.EndArray();
+}
+
+void test3() {
+ std::string json;
+
+ // Serialize
+ {
+ Canvas c;
+ c.AddShape(new Circle(1.0, 2.0, 3.0));
+ c.AddShape(new Box(4.0, 5.0, 6.0, 7.0));
+
+ JsonWriter writer;
+ writer & c;
+ json = writer.GetString();
+ std::cout << json << std::endl;
+ }
+
+ // Deserialize
+ {
+ Canvas c;
+ JsonReader reader(json.c_str());
+ reader & c;
+ c.Print(std::cout);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+int main() {
+ test1();
+ test2();
+ test3();
+}
diff --git a/3rdparty/rapidjson/example/jsonx/jsonx.cpp b/3rdparty/rapidjson/example/jsonx/jsonx.cpp
index 1346b578c39..954aa2b9077 100644
--- a/3rdparty/rapidjson/example/jsonx/jsonx.cpp
+++ b/3rdparty/rapidjson/example/jsonx/jsonx.cpp
@@ -1,4 +1,4 @@
-// JSON to JSONx conversion exmaple, using SAX API.
+// JSON to JSONx conversion example, using SAX API.
// JSONx is an IBM standard format to represent JSON as XML.
// https://www-01.ibm.com/support/knowledgecenter/SS9H2Y_7.1.0/com.ibm.dp.doc/json_jsonx.html
// This example parses JSON text from stdin with validation,
diff --git a/3rdparty/rapidjson/example/lookaheadparser/lookaheadparser.cpp b/3rdparty/rapidjson/example/lookaheadparser/lookaheadparser.cpp
new file mode 100644
index 00000000000..f627f4d8636
--- /dev/null
+++ b/3rdparty/rapidjson/example/lookaheadparser/lookaheadparser.cpp
@@ -0,0 +1,350 @@
+#include "rapidjson/reader.h"
+#include "rapidjson/document.h"
+#include <iostream>
+
+RAPIDJSON_DIAG_PUSH
+#ifdef __GNUC__
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+// This example demonstrates JSON token-by-token parsing with an API that is
+// more direct; you don't need to design your logic around a handler object and
+// callbacks. Instead, you retrieve values from the JSON stream by calling
+// GetInt(), GetDouble(), GetString() and GetBool(), traverse into structures
+// by calling EnterObject() and EnterArray(), and skip over unwanted data by
+// calling SkipValue(). When you know your JSON's structure, this can be quite
+// convenient.
+//
+// If you aren't sure of what's next in the JSON data, you can use PeekType() and
+// PeekValue() to look ahead to the next object before reading it.
+//
+// If you call the wrong retrieval method--e.g. GetInt when the next JSON token is
+// not an int, EnterObject or EnterArray when there isn't actually an object or array
+// to read--the stream parsing will end immediately and no more data will be delivered.
+//
+// After calling EnterObject, you retrieve keys via NextObjectKey() and values via
+// the normal getters. When NextObjectKey() returns null, you have exited the
+// object, or you can call SkipObject() to skip to the end of the object
+// immediately. If you fetch the entire object (i.e. NextObjectKey() returned null),
+// you should not call SkipObject().
+//
+// After calling EnterArray(), you must alternate between calling NextArrayValue()
+// to see if the array has more data, and then retrieving values via the normal
+// getters. You can call SkipArray() to skip to the end of the array immediately.
+// If you fetch the entire array (i.e. NextArrayValue() returned null),
+// you should not call SkipArray().
+//
+// This parser uses in-situ strings, so the JSON buffer will be altered during the
+// parse.
+
+using namespace rapidjson;
+
+
+class LookaheadParserHandler {
+public:
+ bool Null() { st_ = kHasNull; v_.SetNull(); return true; }
+ bool Bool(bool b) { st_ = kHasBool; v_.SetBool(b); return true; }
+ bool Int(int i) { st_ = kHasNumber; v_.SetInt(i); return true; }
+ bool Uint(unsigned u) { st_ = kHasNumber; v_.SetUint(u); return true; }
+ bool Int64(int64_t i) { st_ = kHasNumber; v_.SetInt64(i); return true; }
+ bool Uint64(uint64_t u) { st_ = kHasNumber; v_.SetUint64(u); return true; }
+ bool Double(double d) { st_ = kHasNumber; v_.SetDouble(d); return true; }
+ bool RawNumber(const char*, SizeType, bool) { return false; }
+ bool String(const char* str, SizeType length, bool) { st_ = kHasString; v_.SetString(str, length); return true; }
+ bool StartObject() { st_ = kEnteringObject; return true; }
+ bool Key(const char* str, SizeType length, bool) { st_ = kHasKey; v_.SetString(str, length); return true; }
+ bool EndObject(SizeType) { st_ = kExitingObject; return true; }
+ bool StartArray() { st_ = kEnteringArray; return true; }
+ bool EndArray(SizeType) { st_ = kExitingArray; return true; }
+
+protected:
+ LookaheadParserHandler(char* str);
+ void ParseNext();
+
+protected:
+ enum LookaheadParsingState {
+ kInit,
+ kError,
+ kHasNull,
+ kHasBool,
+ kHasNumber,
+ kHasString,
+ kHasKey,
+ kEnteringObject,
+ kExitingObject,
+ kEnteringArray,
+ kExitingArray
+ };
+
+ Value v_;
+ LookaheadParsingState st_;
+ Reader r_;
+ InsituStringStream ss_;
+
+ static const int parseFlags = kParseDefaultFlags | kParseInsituFlag;
+};
+
+LookaheadParserHandler::LookaheadParserHandler(char* str) : v_(), st_(kInit), r_(), ss_(str) {
+ r_.IterativeParseInit();
+ ParseNext();
+}
+
+void LookaheadParserHandler::ParseNext() {
+ if (r_.HasParseError()) {
+ st_ = kError;
+ return;
+ }
+
+ r_.IterativeParseNext<parseFlags>(ss_, *this);
+}
+
+class LookaheadParser : protected LookaheadParserHandler {
+public:
+ LookaheadParser(char* str) : LookaheadParserHandler(str) {}
+
+ bool EnterObject();
+ bool EnterArray();
+ const char* NextObjectKey();
+ bool NextArrayValue();
+ int GetInt();
+ double GetDouble();
+ const char* GetString();
+ bool GetBool();
+ void GetNull();
+
+ void SkipObject();
+ void SkipArray();
+ void SkipValue();
+ Value* PeekValue();
+ int PeekType(); // returns a rapidjson::Type, or -1 for no value (at end of object/array)
+
+ bool IsValid() { return st_ != kError; }
+
+protected:
+ void SkipOut(int depth);
+};
+
+bool LookaheadParser::EnterObject() {
+ if (st_ != kEnteringObject) {
+ st_ = kError;
+ return false;
+ }
+
+ ParseNext();
+ return true;
+}
+
+bool LookaheadParser::EnterArray() {
+ if (st_ != kEnteringArray) {
+ st_ = kError;
+ return false;
+ }
+
+ ParseNext();
+ return true;
+}
+
+const char* LookaheadParser::NextObjectKey() {
+ if (st_ == kHasKey) {
+ const char* result = v_.GetString();
+ ParseNext();
+ return result;
+ }
+
+ if (st_ != kExitingObject) {
+ st_ = kError;
+ return 0;
+ }
+
+ ParseNext();
+ return 0;
+}
+
+bool LookaheadParser::NextArrayValue() {
+ if (st_ == kExitingArray) {
+ ParseNext();
+ return false;
+ }
+
+ if (st_ == kError || st_ == kExitingObject || st_ == kHasKey) {
+ st_ = kError;
+ return false;
+ }
+
+ return true;
+}
+
+int LookaheadParser::GetInt() {
+ if (st_ != kHasNumber || !v_.IsInt()) {
+ st_ = kError;
+ return 0;
+ }
+
+ int result = v_.GetInt();
+ ParseNext();
+ return result;
+}
+
+double LookaheadParser::GetDouble() {
+ if (st_ != kHasNumber) {
+ st_ = kError;
+ return 0.;
+ }
+
+ double result = v_.GetDouble();
+ ParseNext();
+ return result;
+}
+
+bool LookaheadParser::GetBool() {
+ if (st_ != kHasBool) {
+ st_ = kError;
+ return false;
+ }
+
+ bool result = v_.GetBool();
+ ParseNext();
+ return result;
+}
+
+void LookaheadParser::GetNull() {
+ if (st_ != kHasNull) {
+ st_ = kError;
+ return;
+ }
+
+ ParseNext();
+}
+
+const char* LookaheadParser::GetString() {
+ if (st_ != kHasString) {
+ st_ = kError;
+ return 0;
+ }
+
+ const char* result = v_.GetString();
+ ParseNext();
+ return result;
+}
+
+void LookaheadParser::SkipOut(int depth) {
+ do {
+ if (st_ == kEnteringArray || st_ == kEnteringObject) {
+ ++depth;
+ }
+ else if (st_ == kExitingArray || st_ == kExitingObject) {
+ --depth;
+ }
+ else if (st_ == kError) {
+ return;
+ }
+
+ ParseNext();
+ }
+ while (depth > 0);
+}
+
+void LookaheadParser::SkipValue() {
+ SkipOut(0);
+}
+
+void LookaheadParser::SkipArray() {
+ SkipOut(1);
+}
+
+void LookaheadParser::SkipObject() {
+ SkipOut(1);
+}
+
+Value* LookaheadParser::PeekValue() {
+ if (st_ >= kHasNull && st_ <= kHasKey) {
+ return &v_;
+ }
+
+ return 0;
+}
+
+int LookaheadParser::PeekType() {
+ if (st_ >= kHasNull && st_ <= kHasKey) {
+ return v_.GetType();
+ }
+
+ if (st_ == kEnteringArray) {
+ return kArrayType;
+ }
+
+ if (st_ == kEnteringObject) {
+ return kObjectType;
+ }
+
+ return -1;
+}
+
+//-------------------------------------------------------------------------
+
+int main() {
+ using namespace std;
+
+ char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null,"
+ "\"i\":123, \"pi\": 3.1416, \"a\":[-1, 2, 3, 4, \"array\", []], \"skipArrays\":[1, 2, [[[3]]]], "
+ "\"skipObject\":{ \"i\":0, \"t\":true, \"n\":null, \"d\":123.45 }, "
+ "\"skipNested\":[[[[{\"\":0}, {\"\":[-9.87]}]]], [], []], "
+ "\"skipString\":\"zzz\", \"reachedEnd\":null, \"t\":true }";
+
+ LookaheadParser r(json);
+
+ RAPIDJSON_ASSERT(r.PeekType() == kObjectType);
+
+ r.EnterObject();
+ while (const char* key = r.NextObjectKey()) {
+ if (0 == strcmp(key, "hello")) {
+ RAPIDJSON_ASSERT(r.PeekType() == kStringType);
+ cout << key << ":" << r.GetString() << endl;
+ }
+ else if (0 == strcmp(key, "t") || 0 == strcmp(key, "f")) {
+ RAPIDJSON_ASSERT(r.PeekType() == kTrueType || r.PeekType() == kFalseType);
+ cout << key << ":" << r.GetBool() << endl;
+ continue;
+ }
+ else if (0 == strcmp(key, "n")) {
+ RAPIDJSON_ASSERT(r.PeekType() == kNullType);
+ r.GetNull();
+ cout << key << endl;
+ continue;
+ }
+ else if (0 == strcmp(key, "pi")) {
+ RAPIDJSON_ASSERT(r.PeekType() == kNumberType);
+ cout << key << ":" << r.GetDouble() << endl;
+ continue;
+ }
+ else if (0 == strcmp(key, "a")) {
+ RAPIDJSON_ASSERT(r.PeekType() == kArrayType);
+
+ r.EnterArray();
+
+ cout << key << ":[ ";
+ while (r.NextArrayValue()) {
+ if (r.PeekType() == kNumberType) {
+ cout << r.GetDouble() << " ";
+ }
+ else if (r.PeekType() == kStringType) {
+ cout << r.GetString() << " ";
+ }
+ else {
+ r.SkipArray();
+ break;
+ }
+ }
+
+ cout << "]" << endl;
+ }
+ else {
+ cout << key << ":skipped" << endl;
+ r.SkipValue();
+ }
+ }
+
+ return 0;
+}
+
+RAPIDJSON_DIAG_POP
diff --git a/3rdparty/rapidjson/example/parsebyparts/parsebyparts.cpp b/3rdparty/rapidjson/example/parsebyparts/parsebyparts.cpp
index 57eed005dea..ff735394ec9 100644
--- a/3rdparty/rapidjson/example/parsebyparts/parsebyparts.cpp
+++ b/3rdparty/rapidjson/example/parsebyparts/parsebyparts.cpp
@@ -21,12 +21,15 @@ public:
AsyncDocumentParser(Document& d)
: stream_(*this)
, d_(d)
- , parseThread_(&AsyncDocumentParser::Parse, this)
+ , parseThread_()
, mutex_()
, notEmpty_()
, finish_()
, completed_()
- {}
+ {
+ // Create and execute thread after all member variables are initialized.
+ parseThread_ = std::thread(&AsyncDocumentParser::Parse, this);
+ }
~AsyncDocumentParser() {
if (!parseThread_.joinable())
@@ -140,7 +143,7 @@ int main() {
AsyncDocumentParser<> parser(d);
const char json1[] = " { \"hello\" : \"world\", \"t\" : tr";
- //const char json1[] = " { \"hello\" : \"world\", \"t\" : trX"; // Fot test parsing error
+ //const char json1[] = " { \"hello\" : \"world\", \"t\" : trX"; // For test parsing error
const char json2[] = "ue, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.14";
const char json3[] = "16, \"a\":[1, 2, 3, 4] } ";
diff --git a/3rdparty/rapidjson/example/schemavalidator/schemavalidator.cpp b/3rdparty/rapidjson/example/schemavalidator/schemavalidator.cpp
index ce36ea95f00..6ce3c39e597 100644
--- a/3rdparty/rapidjson/example/schemavalidator/schemavalidator.cpp
+++ b/3rdparty/rapidjson/example/schemavalidator/schemavalidator.cpp
@@ -2,13 +2,132 @@
// The example validates JSON text from stdin with a JSON schema specified in the argument.
+#define RAPIDJSON_HAS_STDSTRING 1
+
#include "rapidjson/error/en.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/schema.h"
#include "rapidjson/stringbuffer.h"
+#include "rapidjson/prettywriter.h"
+#include <string>
+#include <iostream>
+#include <sstream>
using namespace rapidjson;
+typedef GenericValue<UTF8<>, CrtAllocator > ValueType;
+
+// Forward ref
+static void CreateErrorMessages(const ValueType& errors, size_t depth, const char* context);
+
+// Convert GenericValue to std::string
+static std::string GetString(const ValueType& val) {
+ std::ostringstream s;
+ if (val.IsString())
+ s << val.GetString();
+ else if (val.IsDouble())
+ s << val.GetDouble();
+ else if (val.IsUint())
+ s << val.GetUint();
+ else if (val.IsInt())
+ s << val.GetInt();
+ else if (val.IsUint64())
+ s << val.GetUint64();
+ else if (val.IsInt64())
+ s << val.GetInt64();
+ else if (val.IsBool() && val.GetBool())
+ s << "true";
+ else if (val.IsBool())
+ s << "false";
+ else if (val.IsFloat())
+ s << val.GetFloat();
+ return s.str();
+}
+
+// Create the error message for a named error
+// The error object can either be empty or contain at least member properties:
+// {"errorCode": <code>, "instanceRef": "<pointer>", "schemaRef": "<pointer>" }
+// Additional properties may be present for use as inserts.
+// An "errors" property may be present if there are child errors.
+static void HandleError(const char* errorName, const ValueType& error, size_t depth, const char* context) {
+ if (!error.ObjectEmpty()) {
+ // Get error code and look up error message text (English)
+ int code = error["errorCode"].GetInt();
+ std::string message(GetValidateError_En(static_cast<ValidateErrorCode>(code)));
+ // For each member property in the error, see if its name exists as an insert in the error message and if so replace with the stringified property value
+ // So for example - "Number '%actual' is not a multiple of the 'multipleOf' value '%expected'." - we would expect "actual" and "expected" members.
+ for (ValueType::ConstMemberIterator insertsItr = error.MemberBegin();
+ insertsItr != error.MemberEnd(); ++insertsItr) {
+ std::string insertName("%");
+ insertName += insertsItr->name.GetString(); // eg "%actual"
+ size_t insertPos = message.find(insertName);
+ if (insertPos != std::string::npos) {
+ std::string insertString("");
+ const ValueType &insert = insertsItr->value;
+ if (insert.IsArray()) {
+ // Member is an array so create comma-separated list of items for the insert string
+ for (ValueType::ConstValueIterator itemsItr = insert.Begin(); itemsItr != insert.End(); ++itemsItr) {
+ if (itemsItr != insert.Begin()) insertString += ",";
+ insertString += GetString(*itemsItr);
+ }
+ } else {
+ insertString += GetString(insert);
+ }
+ message.replace(insertPos, insertName.length(), insertString);
+ }
+ }
+ // Output error message, references, context
+ std::string indent(depth * 2, ' ');
+ std::cout << indent << "Error Name: " << errorName << std::endl;
+ std::cout << indent << "Message: " << message.c_str() << std::endl;
+ std::cout << indent << "Instance: " << error["instanceRef"].GetString() << std::endl;
+ std::cout << indent << "Schema: " << error["schemaRef"].GetString() << std::endl;
+ if (depth > 0) std::cout << indent << "Context: " << context << std::endl;
+ std::cout << std::endl;
+
+ // If child errors exist, apply the process recursively to each error structure.
+ // This occurs for "oneOf", "allOf", "anyOf" and "dependencies" errors, so pass the error name as context.
+ if (error.HasMember("errors")) {
+ depth++;
+ const ValueType &childErrors = error["errors"];
+ if (childErrors.IsArray()) {
+ // Array - each item is an error structure - example
+ // "anyOf": {"errorCode": ..., "errors":[{"pattern": {"errorCode\": ...\"}}, {"pattern": {"errorCode\": ...}}]
+ for (ValueType::ConstValueIterator errorsItr = childErrors.Begin();
+ errorsItr != childErrors.End(); ++errorsItr) {
+ CreateErrorMessages(*errorsItr, depth, errorName);
+ }
+ } else if (childErrors.IsObject()) {
+ // Object - each member is an error structure - example
+ // "dependencies": {"errorCode": ..., "errors": {"address": {"required": {"errorCode": ...}}, "name": {"required": {"errorCode": ...}}}
+ for (ValueType::ConstMemberIterator propsItr = childErrors.MemberBegin();
+ propsItr != childErrors.MemberEnd(); ++propsItr) {
+ CreateErrorMessages(propsItr->value, depth, errorName);
+ }
+ }
+ }
+ }
+}
+
+// Create error message for all errors in an error structure
+// Context is used to indicate whether the error structure has a parent 'dependencies', 'allOf', 'anyOf' or 'oneOf' error
+static void CreateErrorMessages(const ValueType& errors, size_t depth = 0, const char* context = 0) {
+ // Each member property contains one or more errors of a given type
+ for (ValueType::ConstMemberIterator errorTypeItr = errors.MemberBegin(); errorTypeItr != errors.MemberEnd(); ++errorTypeItr) {
+ const char* errorName = errorTypeItr->name.GetString();
+ const ValueType& errorContent = errorTypeItr->value;
+ if (errorContent.IsArray()) {
+ // Member is an array where each item is an error - eg "type": [{"errorCode": ...}, {"errorCode": ...}]
+ for (ValueType::ConstValueIterator contentItr = errorContent.Begin(); contentItr != errorContent.End(); ++contentItr) {
+ HandleError(errorName, *contentItr, depth, context);
+ }
+ } else if (errorContent.IsObject()) {
+ // Member is an object which is a single error - eg "type": {"errorCode": ... }
+ HandleError(errorName, errorContent, depth, context);
+ }
+ }
+}
+
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: schemavalidator schema.json < input.json\n");
@@ -64,9 +183,17 @@ int main(int argc, char *argv[]) {
validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
fprintf(stderr, "Invalid schema: %s\n", sb.GetString());
fprintf(stderr, "Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());
+ fprintf(stderr, "Invalid code: %d\n", validator.GetInvalidSchemaCode());
+ fprintf(stderr, "Invalid message: %s\n", GetValidateError_En(validator.GetInvalidSchemaCode()));
sb.Clear();
validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
fprintf(stderr, "Invalid document: %s\n", sb.GetString());
+ // Detailed violation report is available as a JSON value
+ sb.Clear();
+ PrettyWriter<StringBuffer> w(sb);
+ validator.GetError().Accept(w);
+ fprintf(stderr, "Error report:\n%s\n", sb.GetString());
+ CreateErrorMessages(validator.GetError());
return EXIT_FAILURE;
}
}
diff --git a/3rdparty/rapidjson/example/simplepullreader/simplepullreader.cpp b/3rdparty/rapidjson/example/simplepullreader/simplepullreader.cpp
new file mode 100644
index 00000000000..a4fb1161a4c
--- /dev/null
+++ b/3rdparty/rapidjson/example/simplepullreader/simplepullreader.cpp
@@ -0,0 +1,53 @@
+#include "rapidjson/reader.h"
+#include <iostream>
+#include <sstream>
+
+using namespace rapidjson;
+using namespace std;
+
+// If you can require C++11, you could use std::to_string here
+template <typename T> std::string stringify(T x) {
+ std::stringstream ss;
+ ss << x;
+ return ss.str();
+}
+
+struct MyHandler {
+ const char* type;
+ std::string data;
+
+ MyHandler() : type(), data() {}
+
+ bool Null() { type = "Null"; data.clear(); return true; }
+ bool Bool(bool b) { type = "Bool:"; data = b? "true": "false"; return true; }
+ bool Int(int i) { type = "Int:"; data = stringify(i); return true; }
+ bool Uint(unsigned u) { type = "Uint:"; data = stringify(u); return true; }
+ bool Int64(int64_t i) { type = "Int64:"; data = stringify(i); return true; }
+ bool Uint64(uint64_t u) { type = "Uint64:"; data = stringify(u); return true; }
+ bool Double(double d) { type = "Double:"; data = stringify(d); return true; }
+ bool RawNumber(const char* str, SizeType length, bool) { type = "Number:"; data = std::string(str, length); return true; }
+ bool String(const char* str, SizeType length, bool) { type = "String:"; data = std::string(str, length); return true; }
+ bool StartObject() { type = "StartObject"; data.clear(); return true; }
+ bool Key(const char* str, SizeType length, bool) { type = "Key:"; data = std::string(str, length); return true; }
+ bool EndObject(SizeType memberCount) { type = "EndObject:"; data = stringify(memberCount); return true; }
+ bool StartArray() { type = "StartArray"; data.clear(); return true; }
+ bool EndArray(SizeType elementCount) { type = "EndArray:"; data = stringify(elementCount); return true; }
+private:
+ MyHandler(const MyHandler& noCopyConstruction);
+ MyHandler& operator=(const MyHandler& noAssignment);
+};
+
+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.IterativeParseInit();
+ while (!reader.IterativeParseComplete()) {
+ reader.IterativeParseNext<kParseDefaultFlags>(ss, handler);
+ cout << handler.type << handler.data << endl;
+ }
+
+ return 0;
+}
diff --git a/3rdparty/rapidjson/example/sortkeys/sortkeys.cpp b/3rdparty/rapidjson/example/sortkeys/sortkeys.cpp
new file mode 100644
index 00000000000..7ede9fb938b
--- /dev/null
+++ b/3rdparty/rapidjson/example/sortkeys/sortkeys.cpp
@@ -0,0 +1,62 @@
+#include "rapidjson/document.h"
+#include "rapidjson/filewritestream.h"
+#include <rapidjson/prettywriter.h>
+
+#include <algorithm>
+#include <iostream>
+
+using namespace rapidjson;
+using namespace std;
+
+static void printIt(const Value &doc) {
+ char writeBuffer[65536];
+ FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer));
+ PrettyWriter<FileWriteStream> writer(os);
+ doc.Accept(writer);
+ cout << endl;
+}
+
+struct NameComparator {
+ bool operator()(const Value::Member &lhs, const Value::Member &rhs) const {
+ return (strcmp(lhs.name.GetString(), rhs.name.GetString()) < 0);
+ }
+};
+
+int main() {
+ Document d(kObjectType);
+ Document::AllocatorType &allocator = d.GetAllocator();
+
+ d.AddMember("zeta", Value().SetBool(false), allocator);
+ d.AddMember("gama", Value().SetString("test string", allocator), allocator);
+ d.AddMember("delta", Value().SetInt(123), allocator);
+ d.AddMember("alpha", Value(kArrayType).Move(), allocator);
+
+ printIt(d);
+
+/*
+{
+ "zeta": false,
+ "gama": "test string",
+ "delta": 123,
+ "alpha": []
+}
+*/
+
+// C++11 supports std::move() of Value so it always have no problem for std::sort().
+// Some C++03 implementations of std::sort() requires copy constructor which causes compilation error.
+// Needs a sorting function only depends on std::swap() instead.
+#if __cplusplus >= 201103L || (!defined(__GLIBCXX__) && (!defined(_MSC_VER) || _MSC_VER >= 1900))
+ std::sort(d.MemberBegin(), d.MemberEnd(), NameComparator());
+
+ printIt(d);
+
+/*
+{
+ "alpha": [],
+ "delta": 123,
+ "gama": "test string",
+ "zeta": false
+}
+*/
+#endif
+}
diff --git a/3rdparty/rapidjson/example/traverseaspointer.cpp b/3rdparty/rapidjson/example/traverseaspointer.cpp
new file mode 100644
index 00000000000..7e0c89923e4
--- /dev/null
+++ b/3rdparty/rapidjson/example/traverseaspointer.cpp
@@ -0,0 +1,39 @@
+#include "rapidjson/document.h"
+#include "rapidjson/filereadstream.h"
+#include "rapidjson/pointer.h"
+#include "rapidjson/stringbuffer.h"
+#include <iostream>
+
+using namespace rapidjson;
+
+void traverse(const Value& v, const Pointer& p) {
+ StringBuffer sb;
+ p.Stringify(sb);
+ std::cout << sb.GetString() << std::endl;
+
+ switch (v.GetType()) {
+ case kArrayType:
+ for (SizeType i = 0; i != v.Size(); ++i)
+ traverse(v[i], p.Append(i));
+ break;
+ case kObjectType:
+ for (Value::ConstMemberIterator m = v.MemberBegin(); m != v.MemberEnd(); ++m)
+ traverse(m->value, p.Append(m->name.GetString(), m->name.GetStringLength()));
+ break;
+ default:
+ break;
+ }
+}
+
+int main(int, char*[]) {
+ char readBuffer[65536];
+ FileReadStream is(stdin, readBuffer, sizeof(readBuffer));
+
+ Document d;
+ d.ParseStream(is);
+
+ Pointer root;
+ traverse(d, root);
+
+ return 0;
+}
diff --git a/3rdparty/rapidjson/example/tutorial/tutorial.cpp b/3rdparty/rapidjson/example/tutorial/tutorial.cpp
index c8bfcc14c18..d6021c66891 100644
--- a/3rdparty/rapidjson/example/tutorial/tutorial.cpp
+++ b/3rdparty/rapidjson/example/tutorial/tutorial.cpp
@@ -57,7 +57,7 @@ int main(int, char*[]) {
printf("n = %s\n", document["n"].IsNull() ? "null" : "?");
assert(document["i"].IsNumber()); // Number is a JSON type, but C++ needs more specific type.
- assert(document["i"].IsInt()); // In this case, IsUint()/IsInt64()/IsUInt64() also return true.
+ assert(document["i"].IsInt()); // In this case, IsUint()/IsInt64()/IsUint64() also return true.
printf("i = %d\n", document["i"].GetInt()); // Alternative (int)document["i"]
assert(document["pi"].IsNumber());