The R Project SVN R-packages

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
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