| 7747 |
ripley |
1 |
#include "JSONStream.h"
|
|
|
2 |
|
|
|
3 |
#ifdef JSON_STREAM
|
|
|
4 |
#include "JSONWorker.h"
|
|
|
5 |
#include "JSONValidator.h"
|
|
|
6 |
|
|
|
7 |
|
|
|
8 |
JSONStream::JSONStream(json_stream_callback_t call_p, json_stream_e_callback_t call_e, void * callbackIdentifier) json_nothrow : state(true), call(call_p), err_call(call_e), buffer(), callback_identifier(callbackIdentifier) {
|
|
|
9 |
LIBJSON_CTOR;
|
|
|
10 |
}
|
|
|
11 |
|
|
|
12 |
JSONStream::JSONStream(const JSONStream & orig) json_nothrow : state(orig.state), call(orig.call), err_call(orig.err_call), buffer(orig.buffer), callback_identifier(orig.callback_identifier){
|
|
|
13 |
LIBJSON_COPY_CTOR;
|
|
|
14 |
}
|
|
|
15 |
|
|
|
16 |
JSONStream & JSONStream::operator =(const JSONStream & orig) json_nothrow {
|
|
|
17 |
LIBJSON_ASSIGNMENT;
|
|
|
18 |
err_call = orig.err_call;
|
|
|
19 |
call = orig.call;
|
|
|
20 |
state = orig.state;
|
|
|
21 |
buffer = orig.buffer;
|
|
|
22 |
callback_identifier = orig.callback_identifier;
|
|
|
23 |
return *this;
|
|
|
24 |
}
|
|
|
25 |
|
|
|
26 |
#ifdef JSON_LIBRARY
|
|
|
27 |
JSONStream & JSONStream::operator << (const json_char * str) json_nothrow {
|
|
|
28 |
#else
|
|
|
29 |
JSONStream & JSONStream::operator << (const json_string & str) json_nothrow {
|
|
|
30 |
#endif
|
|
|
31 |
if (state){
|
|
|
32 |
buffer += str;
|
|
|
33 |
parse();
|
|
|
34 |
}
|
|
|
35 |
return *this;
|
|
|
36 |
}
|
|
|
37 |
|
|
|
38 |
|
|
|
39 |
#define QUOTECASE_STREAM()\
|
|
|
40 |
case JSON_TEXT('\"'):\
|
|
|
41 |
while (*(++p) != JSON_TEXT('\"')){\
|
|
|
42 |
if (json_unlikely(*p == JSON_TEXT('\0'))) return json_string::npos;\
|
|
|
43 |
}\
|
|
|
44 |
break;
|
|
|
45 |
|
|
|
46 |
|
|
|
47 |
#define NULLCASE_STREAM()\
|
|
|
48 |
case JSON_TEXT('\0'):\
|
|
|
49 |
return json_string::npos;\
|
|
|
50 |
|
|
|
51 |
|
|
|
52 |
#define BRACKET_STREAM(left, right)\
|
|
|
53 |
case left: {\
|
|
|
54 |
size_t brac = 1;\
|
|
|
55 |
while (brac){\
|
|
|
56 |
switch (*(++p)){\
|
|
|
57 |
case right:\
|
|
|
58 |
--brac;\
|
|
|
59 |
break;\
|
|
|
60 |
case left:\
|
|
|
61 |
++brac;\
|
|
|
62 |
break;\
|
|
|
63 |
QUOTECASE_STREAM()\
|
|
|
64 |
NULLCASE_STREAM()\
|
|
|
65 |
}\
|
|
|
66 |
}\
|
|
|
67 |
break;}\
|
|
|
68 |
case right:\
|
|
|
69 |
return json_string::npos;
|
|
|
70 |
|
|
|
71 |
#if (JSON_READ_PRIORITY == HIGH) && (!(defined(JSON_LESS_MEMORY)))
|
|
|
72 |
#define STREAM_FIND_NEXT_RELEVANT(ch, vt, po) FindNextRelevant<ch>(vt, po)
|
|
|
73 |
template<json_char ch>
|
|
|
74 |
size_t JSONStream::FindNextRelevant(const json_string & value_t, const size_t pos) json_nothrow {
|
|
|
75 |
#else
|
|
|
76 |
#define STREAM_FIND_NEXT_RELEVANT(ch, vt, po) FindNextRelevant(ch, vt, po)
|
|
|
77 |
size_t JSONStream::FindNextRelevant(json_char ch, const json_string & value_t, const size_t pos) json_nothrow {
|
|
|
78 |
#endif
|
|
|
79 |
const json_char * start = value_t.c_str();
|
|
|
80 |
for (const json_char * p = start + pos; *p; ++p){
|
|
|
81 |
if (json_unlikely(*p == ch)) return p - start;
|
|
|
82 |
switch (*p){
|
|
|
83 |
BRACKET_STREAM(JSON_TEXT('['), JSON_TEXT(']'))
|
|
|
84 |
BRACKET_STREAM(JSON_TEXT('{'), JSON_TEXT('}'))
|
|
|
85 |
QUOTECASE_STREAM()
|
|
|
86 |
}
|
|
|
87 |
};
|
|
|
88 |
return json_string::npos;
|
|
|
89 |
}
|
|
|
90 |
|
|
|
91 |
void JSONStream::parse(void) json_nothrow {
|
|
|
92 |
#ifdef JSON_SECURITY_MAX_STREAM_OBJECTS
|
|
|
93 |
size_t objects = 0;
|
|
|
94 |
#endif
|
|
|
95 |
for(;;){
|
|
|
96 |
size_t pos = buffer.find_first_of(JSON_TEXT("{["));
|
|
|
97 |
if (json_likely(pos != json_string::npos)){
|
|
|
98 |
size_t end = (buffer[pos] == JSON_TEXT('[')) ? STREAM_FIND_NEXT_RELEVANT(JSON_TEXT(']'), buffer, pos + 1) : STREAM_FIND_NEXT_RELEVANT(JSON_TEXT('}'), buffer, pos + 1);
|
|
|
99 |
if (end != json_string::npos){
|
|
|
100 |
#ifdef JSON_SECURITY_MAX_STREAM_OBJECTS
|
|
|
101 |
if (++objects > JSON_SECURITY_MAX_STREAM_OBJECTS){
|
|
|
102 |
JSON_FAIL(JSON_TEXT("Maximum number of json objects for a stream at once has been reached"));
|
|
|
103 |
if (err_call) err_call(getIdentifier());
|
|
|
104 |
state = false;
|
|
|
105 |
return;
|
|
|
106 |
}
|
|
|
107 |
#endif
|
|
|
108 |
START_MEM_SCOPE
|
|
|
109 |
JSONNode temp(JSONWorker::parse(buffer.substr(pos, end - pos + 1)));
|
|
|
110 |
#ifndef JSON_LIBRARY
|
|
|
111 |
call(temp, getIdentifier());
|
|
|
112 |
#else
|
|
|
113 |
call(&temp, getIdentifier());
|
|
|
114 |
#endif
|
|
|
115 |
END_MEM_SCOPE
|
|
|
116 |
json_string::iterator beginning = buffer.begin();
|
|
|
117 |
buffer.erase(beginning, beginning + end);
|
|
|
118 |
continue; //parse(); //parse the next object too
|
|
|
119 |
}
|
|
|
120 |
#ifdef JSON_SAFE
|
|
|
121 |
else {
|
|
|
122 |
//verify that what's in there is at least valid so far
|
|
|
123 |
#ifndef JSON_VALIDATE
|
|
|
124 |
#error In order to use safe mode and streams, JSON_VALIDATE needs to be defined
|
|
|
125 |
#endif
|
|
|
126 |
|
|
|
127 |
json_auto<json_char> s;
|
|
|
128 |
size_t len;
|
|
|
129 |
s.set(JSONWorker::RemoveWhiteSpace(json_string(buffer.c_str() + pos), len, false));
|
|
|
130 |
|
|
|
131 |
|
|
|
132 |
if (!JSONValidator::isValidPartialRoot(s.ptr)){
|
|
|
133 |
if (err_call) err_call(getIdentifier());
|
|
|
134 |
state = false;
|
|
|
135 |
}
|
|
|
136 |
}
|
|
|
137 |
#endif
|
|
|
138 |
}
|
|
|
139 |
break;
|
|
|
140 |
}
|
|
|
141 |
}
|
|
|
142 |
|
|
|
143 |
#endif
|