Blame | Last modification | View Log | Download | RSS feed
#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_LIBRARYJSONStream & JSONStream::operator << (const json_char * str) json_nothrow {#elseJSONStream & JSONStream::operator << (const json_string & str) json_nothrow {#endifif (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 {#endifconst 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_OBJECTSsize_t objects = 0;#endiffor(;;){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_OBJECTSif (++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;}#endifSTART_MEM_SCOPEJSONNode temp(JSONWorker::parse(buffer.substr(pos, end - pos + 1)));#ifndef JSON_LIBRARYcall(temp, getIdentifier());#elsecall(&temp, getIdentifier());#endifEND_MEM_SCOPEjson_string::iterator beginning = buffer.begin();buffer.erase(beginning, beginning + end);continue; //parse(); //parse the next object too}#ifdef JSON_SAFEelse {//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#endifjson_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