Skip to content

Commit 87d955e

Browse files
committed
Integrate Poco::Web::JSON parser
1 parent 9ad1167 commit 87d955e

3 files changed

Lines changed: 916 additions & 632 deletions

File tree

‎JSON/include/Poco/JSON/Parser.h‎

Lines changed: 303 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,211 @@
5353
namespace Poco {
5454
namespace JSON {
5555

56+
class JSON_API CharacterFeeder
57+
{
58+
public:
59+
virtual ~CharacterFeeder() {}
60+
virtual bool nextChar(int& c) = 0;
61+
};
62+
63+
64+
class JSON_API StreamCharacterFeeder : public CharacterFeeder
65+
{
66+
public:
67+
StreamCharacterFeeder(std::istream& in) : _in(in) {}
68+
virtual ~StreamCharacterFeeder() {}
69+
70+
bool nextChar(int& c);
71+
72+
private:
73+
74+
std::istream& _in;
75+
};
76+
77+
78+
inline bool StreamCharacterFeeder::nextChar(int& c)
79+
{
80+
if ( _in.good() )
81+
{
82+
c = _in.get();
83+
return _in.good();
84+
}
85+
return false;
86+
}
87+
88+
class JSON_API StringCharacterFeeder : public CharacterFeeder
89+
{
90+
public:
91+
StringCharacterFeeder(std::string::const_iterator begin, std::string::const_iterator end) : _it(begin), _end(end)
92+
{
93+
}
94+
virtual ~StringCharacterFeeder() {}
95+
96+
bool nextChar(int& c);
97+
98+
private:
99+
100+
std::string::const_iterator _it;
101+
std::string::const_iterator _end;
102+
103+
};
104+
105+
106+
inline bool StringCharacterFeeder::nextChar(int& c)
107+
{
108+
if ( _it == _end )
109+
return false;
110+
111+
c = *_it++;
112+
return true;
113+
}
56114

57115
class JSON_API Parser
58116
/// A class for passing JSON strings or streams.
59117
{
60118
public:
61119

120+
enum Classes
121+
{
122+
C_SPACE, /* space */
123+
C_WHITE, /* other whitespace */
124+
C_LCURB, /* { */
125+
C_RCURB, /* } */
126+
C_LSQRB, /* [ */
127+
C_RSQRB, /* ] */
128+
C_COLON, /* : */
129+
C_COMMA, /* , */
130+
C_QUOTE, /* " */
131+
C_BACKS, /* \ */
132+
C_SLASH, /* / */
133+
C_PLUS, /* + */
134+
C_MINUS, /* - */
135+
C_POINT, /* . */
136+
C_ZERO , /* 0 */
137+
C_DIGIT, /* 123456789 */
138+
C_LOW_A, /* a */
139+
C_LOW_B, /* b */
140+
C_LOW_C, /* c */
141+
C_LOW_D, /* d */
142+
C_LOW_E, /* e */
143+
C_LOW_F, /* f */
144+
C_LOW_L, /* l */
145+
C_LOW_N, /* n */
146+
C_LOW_R, /* r */
147+
C_LOW_S, /* s */
148+
C_LOW_T, /* t */
149+
C_LOW_U, /* u */
150+
C_ABCDF, /* ABCDF */
151+
C_E, /* E */
152+
C_ETC, /* everything else */
153+
C_STAR, /* * */
154+
NR_CLASSES
155+
};
156+
157+
enum States
158+
/// State codes
159+
{
160+
GO, /* start */
161+
OK, /* ok */
162+
OB, /* object */
163+
KE, /* key */
164+
CO, /* colon */
165+
VA, /* value */
166+
AR, /* array */
167+
ST, /* string */
168+
ES, /* escape */
169+
U1, /* u1 */
170+
U2, /* u2 */
171+
U3, /* u3 */
172+
U4, /* u4 */
173+
MI, /* minus */
174+
ZE, /* zero */
175+
IT, /* integer */
176+
FR, /* fraction */
177+
E1, /* e */
178+
E2, /* ex */
179+
E3, /* exp */
180+
T1, /* tr */
181+
T2, /* tru */
182+
T3, /* true */
183+
F1, /* fa */
184+
F2, /* fal */
185+
F3, /* fals */
186+
F4, /* false */
187+
N1, /* nu */
188+
N2, /* nul */
189+
N3, /* null */
190+
C1, /* / */
191+
C2, /* / * */
192+
C3, /* * */
193+
FX, /* *.* *eE* */
194+
D1, /* second UTF-16 character decoding started by \ */
195+
D2, /* second UTF-16 character proceeded by u */
196+
NR_STATES
197+
};
198+
199+
enum Modes
200+
/// Modes that can be pushed on the _pStack.
201+
{
202+
MODE_ARRAY = 1,
203+
MODE_DONE = 2,
204+
MODE_KEY = 3,
205+
MODE_OBJECT = 4
206+
};
207+
208+
enum Actions
209+
{
210+
CB = -10, /* _comment begin */
211+
CE = -11, /* _comment end */
212+
FA = -12, /* 0 */
213+
TR = -13, /* 0 */
214+
NU = -14, /* null */
215+
DE = -15, /* double detected by exponent e E */
216+
DF = -16, /* double detected by fraction . */
217+
SB = -17, /* string begin */
218+
MX = -18, /* integer detected by minus */
219+
ZX = -19, /* integer detected by zero */
220+
IX = -20, /* integer detected by 1-9 */
221+
EX = -21, /* next char is _escaped */
222+
UC = -22 /* Unicode character read */
223+
};
224+
225+
enum JSONType
226+
{
227+
JSON_T_NONE = 0,
228+
JSON_T_ARRAY_BEGIN,
229+
JSON_T_ARRAY_END,
230+
JSON_T_OBJECT_BEGIN,
231+
JSON_T_OBJECT_END,
232+
JSON_T_INTEGER,
233+
JSON_T_FLOAT,
234+
JSON_T_NULL,
235+
JSON_T_TRUE,
236+
JSON_T_FALSE,
237+
JSON_T_STRING,
238+
JSON_T_KEY,
239+
JSON_T_VALUE_SEPARATOR,
240+
JSON_T_MAX
241+
};
242+
243+
244+
static const int PARSE_BUFFER_SIZE = 3500;
245+
static const int PARSER_STACK_SIZE = 128;
246+
62247
Parser(const Handler::Ptr& pHandler = new ParseHandler);
63248
/// Constructor.
64249

65250
virtual ~Parser();
66251
/// Destructor.
67252

68-
Dynamic::Var parse(const std::string& source);
253+
254+
void allowComments(bool sw);
255+
/// Allow comments. By default this is false.
256+
257+
void allowNullByte(bool sw);
258+
/// Allow a null byte in strings. By default this is true.
259+
260+
Dynamic::Var parse(const std::string& json);
69261
/// Parses a string.
70262

71263
Dynamic::Var parse(std::istream& in);
@@ -81,33 +273,95 @@ class JSON_API Parser
81273
/// Returns the result of parsing;
82274

83275
private:
84-
const Token* nextToken();
85-
/// Returns the next token.
276+
Handler::Ptr _pHandler;
86277

87-
void readObject();
88-
/// Starts reading an object.
89278

90-
void readArray();
91-
/// Starts reading an array.
279+
typedef Poco::Buffer<char> BufType;
92280

93-
bool readRow(bool firstCall = false);
94-
/// Reads a property value pair. Returns true when a next row is expected.
95281

96-
void readValue(const Token* token);
97-
/// Read a value from the token.
282+
bool push(int mode);
283+
/// Push a mode onto the _pStack. Return false if there is overflow.
98284

99-
bool readElements(bool firstCall = false);
100-
/// Read all elements of an array.
285+
bool pop(int mode);
286+
/// Pops the stack, assuring that the current mode matches the expectation.
287+
/// Returns false if there is underflow or if the modes mismatch.
101288

102-
StreamTokenizer _tokenizer;
103-
Handler::Ptr _pHandler;
289+
void growBuffer();
290+
291+
292+
void clearBuffer();
293+
294+
295+
void parseBufferPushBackChar(char c);
296+
297+
298+
void parseBufferPopBackChar();
299+
300+
301+
void addCharToParseBuffer(int nextChar, int nextClass);
302+
303+
304+
void addEscapedCharToParseBuffer(int nextChar);
305+
306+
307+
int decodeUnicodeChar();
308+
309+
310+
void assertNotStringNullBool();
311+
312+
313+
void assertNonContainer();
314+
315+
316+
void parseBuffer();
317+
318+
319+
bool parseChar(int nextChar);
320+
/// Called for each character (or partial character) in JSON string.
321+
/// It accepts UTF-8, UTF-16, or UTF-32. If it the character is accpeted,
322+
/// it returns true, otherwise false.
323+
324+
bool done();
325+
326+
327+
static int utf8_check_first(char byte);
328+
329+
330+
static const int _asciiClass[128];
331+
/// This array maps the 128 ASCII characters into character classes.
332+
/// The remaining Unicode characters should be mapped to C_ETC.
333+
/// Non-whitespace control characters are errors.
334+
static const int _stateTransitionTable[NR_STATES][NR_CLASSES];
335+
static const int xx = -1;
336+
337+
signed char _state;
338+
signed char _beforeCommentState;
339+
JSONType _type;
340+
signed char _escaped;
341+
signed char _comment;
342+
unsigned short _utf16HighSurrogate;
343+
long _depth;
344+
long _top;
345+
BufType _stack;
346+
BufType _parseBuffer;
347+
size_t _parseBufferCount;
348+
size_t _commentBeginOffset;
349+
char _decimalPoint;
350+
bool _allowNullByte;
351+
bool _allowComments;
352+
SharedPtr<CharacterFeeder> feeder;
104353
};
105354

106355

107-
inline Dynamic::Var Parser::parse(const std::string& source)
356+
inline void Parser::allowComments(bool sw)
357+
{
358+
_allowComments = sw;
359+
}
360+
361+
362+
inline void Parser::allowNullByte(bool sw)
108363
{
109-
std::istringstream is(source);
110-
return parse(is);
364+
_allowNullByte = sw;
111365
}
112366

113367

@@ -129,6 +383,37 @@ inline Dynamic::Var Parser::result() const
129383
}
130384

131385

386+
inline bool Parser::done()
387+
{
388+
return _state == OK && pop(MODE_DONE);
389+
}
390+
391+
392+
inline void Parser::assertNotStringNullBool()
393+
{
394+
poco_assert(_type != JSON_T_FALSE &&
395+
_type != JSON_T_TRUE &&
396+
_type != JSON_T_NULL &&
397+
_type != JSON_T_STRING);
398+
}
399+
400+
401+
inline void Parser::assertNonContainer()
402+
{
403+
poco_assert(_type == JSON_T_NULL ||
404+
_type == JSON_T_FALSE ||
405+
_type == JSON_T_TRUE ||
406+
_type == JSON_T_FLOAT ||
407+
_type == JSON_T_INTEGER ||
408+
_type == JSON_T_STRING);
409+
}
410+
411+
412+
inline void Parser::growBuffer()
413+
{
414+
_parseBuffer.resize(_parseBuffer.size() * 2, true);
415+
}
416+
132417
}} // namespace Poco::JSON
133418

134419

0 commit comments

Comments
 (0)