]>
Commit | Line | Data |
---|---|---|
31f18b77 FG |
1 | // JSON filterkey example which populates filtered SAX events into a Document. |
2 | ||
3 | // This example parses JSON text from stdin with validation. | |
4 | // During parsing, specified key will be filtered using a SAX handler. | |
5 | // And finally the filtered events are used to populate a Document. | |
6 | // As an example, the document is written to standard output. | |
7 | ||
8 | #include "rapidjson/document.h" | |
9 | #include "rapidjson/writer.h" | |
10 | #include "rapidjson/filereadstream.h" | |
11 | #include "rapidjson/filewritestream.h" | |
12 | #include "rapidjson/error/en.h" | |
13 | #include <stack> | |
14 | ||
15 | using namespace rapidjson; | |
16 | ||
17 | // This handler forwards event into an output handler, with filtering the descendent events of specified key. | |
18 | template <typename OutputHandler> | |
19 | class FilterKeyHandler { | |
20 | public: | |
21 | typedef char Ch; | |
22 | ||
23 | FilterKeyHandler(OutputHandler& outputHandler, const Ch* keyString, SizeType keyLength) : | |
24 | outputHandler_(outputHandler), keyString_(keyString), keyLength_(keyLength), filterValueDepth_(), filteredKeyCount_() | |
25 | {} | |
26 | ||
27 | bool Null() { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Null() && EndValue(); } | |
28 | bool Bool(bool b) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Bool(b) && EndValue(); } | |
29 | bool Int(int i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int(i) && EndValue(); } | |
30 | bool Uint(unsigned u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint(u) && EndValue(); } | |
31 | bool Int64(int64_t i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int64(i) && EndValue(); } | |
32 | bool Uint64(uint64_t u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint64(u) && EndValue(); } | |
33 | bool Double(double d) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Double(d) && EndValue(); } | |
34 | bool RawNumber(const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.RawNumber(str, len, copy) && EndValue(); } | |
35 | bool String (const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.String (str, len, copy) && EndValue(); } | |
36 | ||
37 | bool StartObject() { | |
38 | if (filterValueDepth_ > 0) { | |
39 | filterValueDepth_++; | |
40 | return true; | |
41 | } | |
42 | else { | |
43 | filteredKeyCount_.push(0); | |
44 | return outputHandler_.StartObject(); | |
45 | } | |
46 | } | |
47 | ||
48 | bool Key(const Ch* str, SizeType len, bool copy) { | |
49 | if (filterValueDepth_ > 0) | |
50 | return true; | |
51 | else if (len == keyLength_ && std::memcmp(str, keyString_, len) == 0) { | |
52 | filterValueDepth_ = 1; | |
53 | return true; | |
54 | } | |
55 | else { | |
56 | ++filteredKeyCount_.top(); | |
57 | return outputHandler_.Key(str, len, copy); | |
58 | } | |
59 | } | |
60 | ||
61 | bool EndObject(SizeType) { | |
62 | if (filterValueDepth_ > 0) { | |
63 | filterValueDepth_--; | |
64 | return EndValue(); | |
65 | } | |
66 | else { | |
67 | // Use our own filtered memberCount | |
68 | SizeType memberCount = filteredKeyCount_.top(); | |
69 | filteredKeyCount_.pop(); | |
70 | return outputHandler_.EndObject(memberCount) && EndValue(); | |
71 | } | |
72 | } | |
73 | ||
74 | bool StartArray() { | |
75 | if (filterValueDepth_ > 0) { | |
76 | filterValueDepth_++; | |
77 | return true; | |
78 | } | |
79 | else | |
80 | return outputHandler_.StartArray(); | |
81 | } | |
82 | ||
83 | bool EndArray(SizeType elementCount) { | |
84 | if (filterValueDepth_ > 0) { | |
85 | filterValueDepth_--; | |
86 | return EndValue(); | |
87 | } | |
88 | else | |
89 | return outputHandler_.EndArray(elementCount) && EndValue(); | |
90 | } | |
91 | ||
92 | private: | |
93 | FilterKeyHandler(const FilterKeyHandler&); | |
94 | FilterKeyHandler& operator=(const FilterKeyHandler&); | |
95 | ||
96 | bool EndValue() { | |
97 | if (filterValueDepth_ == 1) // Just at the end of value after filtered key | |
98 | filterValueDepth_ = 0; | |
99 | return true; | |
100 | } | |
101 | ||
102 | OutputHandler& outputHandler_; | |
103 | const char* keyString_; | |
104 | const SizeType keyLength_; | |
105 | unsigned filterValueDepth_; | |
106 | std::stack<SizeType> filteredKeyCount_; | |
107 | }; | |
108 | ||
109 | // Implements a generator for Document::Populate() | |
110 | template <typename InputStream> | |
111 | class FilterKeyReader { | |
112 | public: | |
113 | typedef char Ch; | |
114 | ||
115 | FilterKeyReader(InputStream& is, const Ch* keyString, SizeType keyLength) : | |
116 | is_(is), keyString_(keyString), keyLength_(keyLength), parseResult_() | |
117 | {} | |
118 | ||
119 | // SAX event flow: reader -> filter -> handler | |
120 | template <typename Handler> | |
121 | bool operator()(Handler& handler) { | |
122 | FilterKeyHandler<Handler> filter(handler, keyString_, keyLength_); | |
123 | Reader reader; | |
124 | parseResult_ = reader.Parse(is_, filter); | |
125 | return parseResult_; | |
126 | } | |
127 | ||
128 | const ParseResult& GetParseResult() const { return parseResult_; } | |
129 | ||
130 | private: | |
131 | FilterKeyReader(const FilterKeyReader&); | |
132 | FilterKeyReader& operator=(const FilterKeyReader&); | |
133 | ||
134 | InputStream& is_; | |
135 | const char* keyString_; | |
136 | const SizeType keyLength_; | |
137 | ParseResult parseResult_; | |
138 | }; | |
139 | ||
140 | int main(int argc, char* argv[]) { | |
141 | if (argc != 2) { | |
142 | fprintf(stderr, "filterkeydom key < input.json > output.json\n"); | |
143 | return 1; | |
144 | } | |
145 | ||
146 | // Prepare input stream. | |
147 | char readBuffer[65536]; | |
148 | FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); | |
149 | ||
150 | // Prepare Filter | |
151 | FilterKeyReader<FileReadStream> reader(is, argv[1], static_cast<SizeType>(strlen(argv[1]))); | |
152 | ||
153 | // Populates the filtered events from reader | |
154 | Document document; | |
155 | document.Populate(reader); | |
156 | ParseResult pr = reader.GetParseResult(); | |
157 | if (!pr) { | |
158 | fprintf(stderr, "\nError(%u): %s\n", static_cast<unsigned>(pr.Offset()), GetParseError_En(pr.Code())); | |
159 | return 1; | |
160 | } | |
161 | ||
162 | // Prepare JSON writer and output stream. | |
163 | char writeBuffer[65536]; | |
164 | FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); | |
165 | Writer<FileWriteStream> writer(os); | |
166 | ||
167 | // Write the document to standard output | |
168 | document.Accept(writer); | |
169 | return 0; | |
170 | } |