| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- #include "JSONStream.h"
- #ifdef JSON_STREAM
- #include "JSONWorker.h"
- #include "JSONValidator.h"
- 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) {
- LIBJSON_CTOR;
- }
- 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){
- LIBJSON_COPY_CTOR;
- }
- JSONStream & JSONStream::operator =(const JSONStream & orig) json_nothrow {
- LIBJSON_ASSIGNMENT;
- err_call = orig.err_call;
- call = orig.call;
- state = orig.state;
- buffer = orig.buffer;
- callback_identifier = orig.callback_identifier;
- return *this;
- }
- #ifdef JSON_LIBRARY
- JSONStream & JSONStream::operator << (const json_char * str) json_nothrow {
- #else
- JSONStream & JSONStream::operator << (const json_string & str) json_nothrow {
- #endif
- if (state){
- buffer += str;
- parse();
- }
- return *this;
- }
- #define QUOTECASE_STREAM()\
- case JSON_TEXT('\"'):\
- while (*(++p) != JSON_TEXT('\"')){\
- if (json_unlikely(*p == JSON_TEXT('\0'))) return json_string::npos;\
- }\
- break;
- #define NULLCASE_STREAM()\
- case JSON_TEXT('\0'):\
- return json_string::npos;\
- #define BRACKET_STREAM(left, right)\
- case left: {\
- size_t brac = 1;\
- while (brac){\
- switch (*(++p)){\
- case right:\
- --brac;\
- break;\
- case left:\
- ++brac;\
- break;\
- QUOTECASE_STREAM()\
- NULLCASE_STREAM()\
- }\
- }\
- break;}\
- case right:\
- return json_string::npos;
- #if (JSON_READ_PRIORITY == HIGH) && (!(defined(JSON_LESS_MEMORY)))
- #define STREAM_FIND_NEXT_RELEVANT(ch, vt, po) FindNextRelevant<ch>(vt, po)
- template<json_char ch>
- size_t JSONStream::FindNextRelevant(const json_string & value_t, const size_t pos) json_nothrow {
- #else
- #define STREAM_FIND_NEXT_RELEVANT(ch, vt, po) FindNextRelevant(ch, vt, po)
- size_t JSONStream::FindNextRelevant(json_char ch, const json_string & value_t, const size_t pos) json_nothrow {
- #endif
- const json_char * start = value_t.c_str();
- for (const json_char * p = start + pos; *p; ++p){
- if (json_unlikely(*p == ch)) return p - start;
- switch (*p){
- BRACKET_STREAM(JSON_TEXT('['), JSON_TEXT(']'))
- BRACKET_STREAM(JSON_TEXT('{'), JSON_TEXT('}'))
- QUOTECASE_STREAM()
- }
- };
- return json_string::npos;
- }
- void JSONStream::parse(void) json_nothrow {
- #ifdef JSON_SECURITY_MAX_STREAM_OBJECTS
- size_t objects = 0;
- #endif
- for(;;){
- size_t pos = buffer.find_first_of(JSON_TEXT("{["));
- if (json_likely(pos != json_string::npos)){
- 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);
- if (end != json_string::npos){
- #ifdef JSON_SECURITY_MAX_STREAM_OBJECTS
- if (++objects > JSON_SECURITY_MAX_STREAM_OBJECTS){
- JSON_FAIL(JSON_TEXT("Maximum number of json objects for a stream at once has been reached"));
- if (err_call) err_call(getIdentifier());
- state = false;
- return;
- }
- #endif
- START_MEM_SCOPE
- JSONNode temp(JSONWorker::parse(buffer.substr(pos, end - pos + 1)));
- #ifndef JSON_LIBRARY
- call(temp, getIdentifier());
- #else
- call(&temp, getIdentifier());
- #endif
- END_MEM_SCOPE
- json_string::iterator beginning = buffer.begin();
- buffer.erase(beginning, beginning + end);
- continue; //parse(); //parse the next object too
- }
- #ifdef JSON_SAFE
- else {
- //verify that what's in there is at least valid so far
- #ifndef JSON_VALIDATE
- #error In order to use safe mode and streams, JSON_VALIDATE needs to be defined
- #endif
-
- json_auto<json_char> s;
- size_t len;
- s.set(JSONWorker::RemoveWhiteSpace(json_string(buffer.c_str() + pos), len, false));
-
-
- if (!JSONValidator::isValidPartialRoot(s.ptr)){
- if (err_call) err_call(getIdentifier());
- state = false;
- }
- }
- #endif
- }
- break;
- }
- }
- #endif
|