-
Notifications
You must be signed in to change notification settings - Fork 3.5k
/
filterkeydom.cpp
170 lines (144 loc) · 5.81 KB
/
filterkeydom.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// JSON filterkey example which populates filtered SAX events into a Document.
// This example parses JSON text from stdin with validation.
// During parsing, specified key will be filtered using a SAX handler.
// And finally the filtered events are used to populate a Document.
// As an example, the document is written to standard output.
#include "rapidjson/document.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_;
};
// Implements a generator for Document::Populate()
template <typename InputStream>
class FilterKeyReader {
public:
typedef char Ch;
FilterKeyReader(InputStream& is, const Ch* keyString, SizeType keyLength) :
is_(is), keyString_(keyString), keyLength_(keyLength), parseResult_()
{}
// SAX event flow: reader -> filter -> handler
template <typename Handler>
bool operator()(Handler& handler) {
FilterKeyHandler<Handler> filter(handler, keyString_, keyLength_);
Reader reader;
parseResult_ = reader.Parse(is_, filter);
return parseResult_;
}
const ParseResult& GetParseResult() const { return parseResult_; }
private:
FilterKeyReader(const FilterKeyReader&);
FilterKeyReader& operator=(const FilterKeyReader&);
InputStream& is_;
const char* keyString_;
const SizeType keyLength_;
ParseResult parseResult_;
};
int main(int argc, char* argv[]) {
if (argc != 2) {
fprintf(stderr, "filterkeydom key < input.json > output.json\n");
return 1;
}
// Prepare input stream.
char readBuffer[65536];
FileReadStream is(stdin, readBuffer, sizeof(readBuffer));
// Prepare Filter
FilterKeyReader<FileReadStream> reader(is, argv[1], static_cast<SizeType>(strlen(argv[1])));
// Populates the filtered events from reader
Document document;
document.Populate(reader);
ParseResult pr = reader.GetParseResult();
if (!pr) {
fprintf(stderr, "\nError(%u): %s\n", static_cast<unsigned>(pr.Offset()), GetParseError_En(pr.Code()));
return 1;
}
// Prepare JSON writer and output stream.
char writeBuffer[65536];
FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer));
Writer<FileWriteStream> writer(os);
// Write the document to standard output
document.Accept(writer);
return 0;
}