mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-02-27 16:55:41 +00:00

git-subtree-dir: external/rapidjson git-subtree-split: 2e8f5d897d9d461a7273b4b812b0127f321b1dcf
136 lines
4.9 KiB
C++
136 lines
4.9 KiB
C++
// JSON filterkey example with SAX-style API.
|
|
|
|
// This example parses JSON text from stdin with validation.
|
|
// During parsing, specified key will be filtered using a SAX handler.
|
|
// It re-output the JSON content to stdout without whitespace.
|
|
|
|
#include "rapidjson/reader.h"
|
|
#include "rapidjson/writer.h"
|
|
#include "rapidjson/filereadstream.h"
|
|
#include "rapidjson/filewritestream.h"
|
|
#include "rapidjson/error/en.h"
|
|
#include <stack>
|
|
|
|
using namespace rapidjson;
|
|
|
|
// This handler forwards event into an output handler, with filtering the descendent events of specified key.
|
|
template <typename OutputHandler>
|
|
class FilterKeyHandler {
|
|
public:
|
|
typedef char Ch;
|
|
|
|
FilterKeyHandler(OutputHandler& outputHandler, const Ch* keyString, SizeType keyLength) :
|
|
outputHandler_(outputHandler), keyString_(keyString), keyLength_(keyLength), filterValueDepth_(), filteredKeyCount_()
|
|
{}
|
|
|
|
bool Null() { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Null() && EndValue(); }
|
|
bool Bool(bool b) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Bool(b) && EndValue(); }
|
|
bool Int(int i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int(i) && EndValue(); }
|
|
bool Uint(unsigned u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint(u) && EndValue(); }
|
|
bool Int64(int64_t i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int64(i) && EndValue(); }
|
|
bool Uint64(uint64_t u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint64(u) && EndValue(); }
|
|
bool Double(double d) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Double(d) && EndValue(); }
|
|
bool RawNumber(const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.RawNumber(str, len, copy) && EndValue(); }
|
|
bool String (const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.String (str, len, copy) && EndValue(); }
|
|
|
|
bool StartObject() {
|
|
if (filterValueDepth_ > 0) {
|
|
filterValueDepth_++;
|
|
return true;
|
|
}
|
|
else {
|
|
filteredKeyCount_.push(0);
|
|
return outputHandler_.StartObject();
|
|
}
|
|
}
|
|
|
|
bool Key(const Ch* str, SizeType len, bool copy) {
|
|
if (filterValueDepth_ > 0)
|
|
return true;
|
|
else if (len == keyLength_ && std::memcmp(str, keyString_, len) == 0) {
|
|
filterValueDepth_ = 1;
|
|
return true;
|
|
}
|
|
else {
|
|
++filteredKeyCount_.top();
|
|
return outputHandler_.Key(str, len, copy);
|
|
}
|
|
}
|
|
|
|
bool EndObject(SizeType) {
|
|
if (filterValueDepth_ > 0) {
|
|
filterValueDepth_--;
|
|
return EndValue();
|
|
}
|
|
else {
|
|
// Use our own filtered memberCount
|
|
SizeType memberCount = filteredKeyCount_.top();
|
|
filteredKeyCount_.pop();
|
|
return outputHandler_.EndObject(memberCount) && EndValue();
|
|
}
|
|
}
|
|
|
|
bool StartArray() {
|
|
if (filterValueDepth_ > 0) {
|
|
filterValueDepth_++;
|
|
return true;
|
|
}
|
|
else
|
|
return outputHandler_.StartArray();
|
|
}
|
|
|
|
bool EndArray(SizeType elementCount) {
|
|
if (filterValueDepth_ > 0) {
|
|
filterValueDepth_--;
|
|
return EndValue();
|
|
}
|
|
else
|
|
return outputHandler_.EndArray(elementCount) && EndValue();
|
|
}
|
|
|
|
private:
|
|
FilterKeyHandler(const FilterKeyHandler&);
|
|
FilterKeyHandler& operator=(const FilterKeyHandler&);
|
|
|
|
bool EndValue() {
|
|
if (filterValueDepth_ == 1) // Just at the end of value after filtered key
|
|
filterValueDepth_ = 0;
|
|
return true;
|
|
}
|
|
|
|
OutputHandler& outputHandler_;
|
|
const char* keyString_;
|
|
const SizeType keyLength_;
|
|
unsigned filterValueDepth_;
|
|
std::stack<SizeType> filteredKeyCount_;
|
|
};
|
|
|
|
int main(int argc, char* argv[]) {
|
|
if (argc != 2) {
|
|
fprintf(stderr, "filterkey key < input.json > output.json\n");
|
|
return 1;
|
|
}
|
|
|
|
// 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);
|
|
|
|
// Prepare Filter
|
|
FilterKeyHandler<Writer<FileWriteStream> > filter(writer, argv[1], static_cast<SizeType>(strlen(argv[1])));
|
|
|
|
// JSON reader parse from the input stream, filter handler filters the events, and forward to writer.
|
|
// i.e. the events flow is: reader -> filter -> writer
|
|
if (!reader.Parse(is, filter)) {
|
|
fprintf(stderr, "\nError(%u): %s\n", static_cast<unsigned>(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode()));
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|