Skip to content

Commit e7fd707

Browse files
committed
Improve LookaheadParser
Fix clang -Wswitch-enum warnings. Made NextArrayValue() more robust—now handles error state correctly, will enter error state if an unexpected state is reached. Made separate states for each value type to simplify getters. Simplified implementation of skipping arrays and objects. Skipping an object now works whether you’ve retrieved the key or not.
1 parent 33a9f58 commit e7fd707

File tree

1 file changed

+97
-63
lines changed

1 file changed

+97
-63
lines changed

example/lookaheadparser/lookaheadparser.cpp

Lines changed: 97 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919
//
2020
// After calling EnterObject, you retrieve keys via NextObjectKey() and values via
2121
// the normal getters. When NextObjectKey() returns null, you have exited the
22-
// object, or you can call ExitObject() to skip to the end of the object
22+
// object, or you can call SkipObject() to skip to the end of the object
2323
// immediately. If you fetch the entire object (i.e. NextObjectKey() returned null),
24-
// you should not call ExitObject().
24+
// you should not call SkipObject().
2525
//
2626
// After calling EnterArray(), you must alternate between calling NextArrayValue()
2727
// to see if the array has more data, and then retrieving values via the normal
28-
// getters. You can call ExitArray() to skip to the end of the array immediately.
28+
// getters. You can call SkipArray() to skip to the end of the array immediately.
2929
// If you fetch the entire array (i.e. NextArrayValue() returned null),
30-
// you should not call ExitArray().
30+
// you should not call SkipArray().
3131
//
3232
// This parser uses in-situ strings, so the JSON buffer will be altered during the
3333
// parse.
@@ -37,15 +37,15 @@ using namespace rapidjson;
3737

3838
class LookaheadParserHandler {
3939
public:
40-
bool Null() { st_ = kHasValue; v_.SetNull(); return true; }
41-
bool Bool(bool b) { st_ = kHasValue; v_.SetBool(b); return true; }
42-
bool Int(int i) { st_ = kHasValue; v_.SetInt(i); return true; }
43-
bool Uint(unsigned u) { st_ = kHasValue; v_.SetUint(u); return true; }
44-
bool Int64(int64_t i) { st_ = kHasValue; v_.SetInt64(i); return true; }
45-
bool Uint64(uint64_t u) { st_ = kHasValue; v_.SetUint64(u); return true; }
46-
bool Double(double d) { st_ = kHasValue; v_.SetDouble(d); return true; }
40+
bool Null() { st_ = kHasNull; v_.SetNull(); return true; }
41+
bool Bool(bool b) { st_ = kHasBool; v_.SetBool(b); return true; }
42+
bool Int(int i) { st_ = kHasNumber; v_.SetInt(i); return true; }
43+
bool Uint(unsigned u) { st_ = kHasNumber; v_.SetUint(u); return true; }
44+
bool Int64(int64_t i) { st_ = kHasNumber; v_.SetInt64(i); return true; }
45+
bool Uint64(uint64_t u) { st_ = kHasNumber; v_.SetUint64(u); return true; }
46+
bool Double(double d) { st_ = kHasNumber; v_.SetDouble(d); return true; }
4747
bool RawNumber(const char*, SizeType, bool) { return false; }
48-
bool String(const char* str, SizeType length, bool) { st_ = kHasValue; v_.SetString(str, length); return true; }
48+
bool String(const char* str, SizeType length, bool) { st_ = kHasString; v_.SetString(str, length); return true; }
4949
bool StartObject() { st_ = kEnteringObject; return true; }
5050
bool Key(const char* str, SizeType length, bool) { st_ = kHasKey; v_.SetString(str, length); return true; }
5151
bool EndObject(SizeType) { st_ = kExitingObject; return true; }
@@ -59,7 +59,10 @@ class LookaheadParserHandler {
5959
protected:
6060
enum LookaheadParsingState {
6161
kError,
62-
kHasValue,
62+
kHasNull,
63+
kHasBool,
64+
kHasNumber,
65+
kHasString,
6366
kHasKey,
6467
kEnteringObject,
6568
kExitingObject,
@@ -93,10 +96,8 @@ class LookaheadParser : protected LookaheadParserHandler {
9396
public:
9497
LookaheadParser(char* str) : LookaheadParserHandler(str) {}
9598

96-
void EnterObject();
97-
void EnterArray();
98-
void ExitObject();
99-
void ExitArray();
99+
bool EnterObject();
100+
bool EnterArray();
100101
const char* NextObjectKey();
101102
bool NextArrayValue();
102103
int GetInt();
@@ -105,70 +106,87 @@ class LookaheadParser : protected LookaheadParserHandler {
105106
bool GetBool();
106107
void GetNull();
107108

109+
void SkipObject();
110+
void SkipArray();
108111
void SkipValue();
109112
Value* PeekValue();
110113
int PeekType(); // returns a rapidjson::Type, or -1 for no value (at end of object/array)
111114

112115
bool IsValid() { return st_ != kError; }
116+
117+
protected:
118+
void SkipOut(int depth);
113119
};
114120

115-
void LookaheadParser::EnterObject() {
121+
bool LookaheadParser::EnterObject() {
116122
if (st_ != kEnteringObject) {
117123
st_ = kError;
118-
return;
124+
return false;
119125
}
120126

121127
ParseNext();
128+
return true;
122129
}
123130

124-
void LookaheadParser::EnterArray() {
131+
bool LookaheadParser::EnterArray() {
125132
if (st_ != kEnteringArray) {
126133
st_ = kError;
127-
return;
134+
return false;
128135
}
129136

130137
ParseNext();
131-
}
132-
133-
void LookaheadParser::ExitObject() {
134-
while (NextObjectKey()) {
135-
SkipValue();
136-
}
137-
}
138-
139-
void LookaheadParser::ExitArray() {
140-
while (NextArrayValue()) {
141-
SkipValue();
142-
}
138+
return true;
143139
}
144140

145141
const char* LookaheadParser::NextObjectKey() {
146-
if (st_ == kExitingObject) {
147-
ParseNext();
148-
return 0;
149-
}
150-
151-
if (st_ != kHasKey || !v_.IsString()) {
152-
st_ = kError;
153-
return 0;
142+
switch (st_) {
143+
case kHasKey: {
144+
const char* result = v_.GetString();
145+
ParseNext();
146+
return result;
147+
}
148+
149+
case kExitingObject:
150+
ParseNext();
151+
return 0;
152+
153+
case kError:
154+
case kHasNull:
155+
case kHasBool:
156+
case kHasNumber:
157+
case kHasString:
158+
case kEnteringObject:
159+
case kEnteringArray:
160+
case kExitingArray:
161+
st_ = kError;
162+
return 0;
154163
}
155-
156-
const char* result = v_.GetString();
157-
ParseNext();
158-
return result;
159164
}
160165

161166
bool LookaheadParser::NextArrayValue() {
162-
if (st_ == kExitingArray) {
163-
ParseNext();
164-
return false;
167+
switch (st_) {
168+
case kExitingArray:
169+
ParseNext();
170+
return false;
171+
172+
case kError:
173+
case kExitingObject:
174+
case kHasKey:
175+
st_ = kError;
176+
return false;
177+
178+
case kHasNull:
179+
case kHasBool:
180+
case kHasNumber:
181+
case kHasString:
182+
case kEnteringObject:
183+
case kEnteringArray:
184+
return true;
165185
}
166-
167-
return true;
168186
}
169187

170188
int LookaheadParser::GetInt() {
171-
if (st_ != kHasValue || !v_.IsInt()) {
189+
if (st_ != kHasNumber || !v_.IsInt()) {
172190
st_ = kError;
173191
return 0;
174192
}
@@ -179,7 +197,7 @@ int LookaheadParser::GetInt() {
179197
}
180198

181199
double LookaheadParser::GetDouble() {
182-
if (st_ != kHasValue || !v_.IsNumber()) {
200+
if (st_ != kHasNumber || !v_.IsNumber()) {
183201
st_ = kError;
184202
return 0.;
185203
}
@@ -190,7 +208,7 @@ double LookaheadParser::GetDouble() {
190208
}
191209

192210
bool LookaheadParser::GetBool() {
193-
if (st_ != kHasValue || !v_.IsBool()) {
211+
if (st_ != kHasBool) {
194212
st_ = kError;
195213
return false;
196214
}
@@ -201,7 +219,7 @@ bool LookaheadParser::GetBool() {
201219
}
202220

203221
void LookaheadParser::GetNull() {
204-
if (st_ != kHasValue || !v_.IsNull()) {
222+
if (st_ != kHasNull) {
205223
st_ = kError;
206224
return;
207225
}
@@ -210,7 +228,7 @@ void LookaheadParser::GetNull() {
210228
}
211229

212230
const char* LookaheadParser::GetString() {
213-
if (st_ != kHasValue || !v_.IsString()) {
231+
if (st_ != kHasString) {
214232
st_ = kError;
215233
return 0;
216234
}
@@ -220,8 +238,7 @@ const char* LookaheadParser::GetString() {
220238
return result;
221239
}
222240

223-
void LookaheadParser::SkipValue() {
224-
int depth = 0;
241+
void LookaheadParser::SkipOut(int depth) {
225242
do {
226243
switch (st_) {
227244
case kEnteringArray:
@@ -237,17 +254,32 @@ void LookaheadParser::SkipValue() {
237254
case kError:
238255
return;
239256

240-
case kHasKey:
241-
case kHasValue:
257+
case kHasNull:
258+
case kHasBool:
259+
case kHasNumber:
260+
case kHasString:
261+
case kHasKey:
242262
break;
243263
}
244264
ParseNext();
245265
}
246266
while (depth > 0);
247267
}
248268

269+
void LookaheadParser::SkipValue() {
270+
SkipOut(0);
271+
}
272+
273+
void LookaheadParser::SkipArray() {
274+
SkipOut(1);
275+
}
276+
277+
void LookaheadParser::SkipObject() {
278+
SkipOut(1);
279+
}
280+
249281
Value* LookaheadParser::PeekValue() {
250-
if (st_ == kHasValue || st_ == kHasKey) {
282+
if (st_ >= kHasNull && st_ <= kHasKey) {
251283
return &v_;
252284
}
253285

@@ -256,7 +288,10 @@ Value* LookaheadParser::PeekValue() {
256288

257289
int LookaheadParser::PeekType() {
258290
switch (st_) {
259-
case kHasValue:
291+
case kHasNull:
292+
case kHasBool:
293+
case kHasNumber:
294+
case kHasString:
260295
case kHasKey:
261296
return v_.GetType();
262297

@@ -269,7 +304,6 @@ int LookaheadParser::PeekType() {
269304
case kExitingArray:
270305
case kExitingObject:
271306
case kError:
272-
default:
273307
return -1;
274308
}
275309
}
@@ -325,7 +359,7 @@ int main() {
325359
cout << r.GetString() << " ";
326360
}
327361
else {
328-
r.ExitArray();
362+
r.SkipArray();
329363
break;
330364
}
331365
}

0 commit comments

Comments
 (0)