5353namespace Poco {
5454namespace 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
57115class JSON_API Parser
58116 // / A class for passing JSON strings or streams.
59117{
60118public:
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
83275private:
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