3 #include "JSON_Tokenizer.hh"
7 static const char TABS
[] =
8 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
9 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
10 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
11 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
12 const size_t MAX_TABS
= sizeof(TABS
) - 1; // 64
14 void JSON_Tokenizer::init(const char* p_buf
, const size_t p_buf_len
)
16 if (p_buf
!= 0 && p_buf_len
!= 0) {
17 buf_ptr
= mcopystrn(p_buf
, p_buf_len
);
24 previous_token
= JSON_TOKEN_NONE
;
27 JSON_Tokenizer::~JSON_Tokenizer()
32 void JSON_Tokenizer::put_c(const char c
)
34 buf_ptr
= mputprintf(buf_ptr
, "%c", c
);
38 void JSON_Tokenizer::put_s(const char* s
)
40 buf_ptr
= mputstr(buf_ptr
, s
);
44 void JSON_Tokenizer::put_depth()
46 put_s(TABS
+ ((depth
> MAX_TABS
) ? 0 : MAX_TABS
- depth
));
49 bool JSON_Tokenizer::skip_white_spaces()
51 while(buf_pos
< buf_len
) {
52 switch(buf_ptr
[buf_pos
]) {
67 bool JSON_Tokenizer::check_for_string()
69 if ('\"' == buf_ptr
[buf_pos
]) {
74 while (buf_pos
< buf_len
) {
75 if ('\"' == buf_ptr
[buf_pos
]) {
78 else if ('\\' == buf_ptr
[buf_pos
]) {
79 // skip escaped character (so escaped quotes (\") are not mistaken for the ending quotes)
87 bool JSON_Tokenizer::check_for_number()
89 bool first_digit
= false; // first non-zero digit reached
90 bool zero
= false; // first zero digit reached
91 bool decimal_point
= false; // decimal point (.) reached
92 bool exponent_mark
= false; // exponential mark (e or E) reached
93 bool exponent_sign
= false; // sign of the exponential (- or +) reached
95 if ('-' == buf_ptr
[buf_pos
]) {
99 while (buf_pos
< buf_len
) {
100 switch(buf_ptr
[buf_pos
]) {
102 if (decimal_point
|| exponent_mark
|| (!first_digit
&& !zero
)) {
105 decimal_point
= true;
111 if (exponent_mark
|| (!first_digit
&& !zero
)) {
114 exponent_mark
= true;
119 if (!first_digit
&& (exponent_mark
|| (!decimal_point
&& zero
))) {
133 if (!first_digit
&& zero
&& (!decimal_point
|| exponent_mark
)) {
140 if (exponent_sign
|| !exponent_mark
|| zero
|| first_digit
) {
143 exponent_sign
= true;
146 return first_digit
|| zero
;
151 return first_digit
|| zero
;
154 bool JSON_Tokenizer::check_for_separator()
156 if (buf_pos
< buf_len
) {
157 switch(buf_ptr
[buf_pos
]) {
174 bool JSON_Tokenizer::check_for_literal(const char* p_literal
)
176 size_t len
= strlen(p_literal
);
177 size_t start_pos
= buf_pos
;
179 if (buf_len
- buf_pos
>= len
&&
180 0 == strncmp(buf_ptr
+ buf_pos
, p_literal
, len
)) {
182 if (!skip_white_spaces() || check_for_separator()) {
185 // must be followed by a separator (or only white spaces until the buffer ends) -> undo buffer action
192 int JSON_Tokenizer::get_next_token(json_token_t
* p_token
, char** p_token_str
, size_t* p_str_len
)
194 size_t start_pos
= buf_pos
;
195 *p_token
= JSON_TOKEN_NONE
;
196 if (0 != p_token_str
&& 0 != p_str_len
) {
201 if (skip_white_spaces()) {
202 char c
= buf_ptr
[buf_pos
];
206 *p_token
= ('{' == c
) ? JSON_TOKEN_OBJECT_START
: JSON_TOKEN_ARRAY_START
;
212 if (skip_white_spaces() && !check_for_separator()) {
213 // must be followed by a separator (or only white spaces until the buffer ends)
214 *p_token
= JSON_TOKEN_ERROR
;
216 *p_token
= ('}' == c
) ? JSON_TOKEN_OBJECT_END
: JSON_TOKEN_ARRAY_END
;
220 // string value or field name
221 size_t string_start_pos
= buf_pos
;
222 if(!check_for_string()) {
223 // invalid string value
224 *p_token
= JSON_TOKEN_ERROR
;
227 size_t string_end_pos
= ++buf_pos
; // step over the string's ending quotes
228 if (skip_white_spaces() && ':' == buf_ptr
[buf_pos
]) {
229 // name token - don't include the starting and ending quotes
230 *p_token
= JSON_TOKEN_NAME
;
231 if (0 != p_token_str
&& 0 != p_str_len
) {
232 *p_token_str
= buf_ptr
+ string_start_pos
+ 1;
233 *p_str_len
= string_end_pos
- string_start_pos
- 2;
236 } else if (check_for_separator()) {
237 // value token - include the starting and ending quotes
238 *p_token
= JSON_TOKEN_STRING
;
239 if (0 != p_token_str
&& 0 != p_str_len
) {
240 *p_token_str
= buf_ptr
+ string_start_pos
;
241 *p_str_len
= string_end_pos
- string_start_pos
;
244 // value token, but there is no separator after it -> error
245 *p_token
= JSON_TOKEN_ERROR
;
249 } // case: string value or field name
251 if (('0' <= buf_ptr
[buf_pos
] && '9' >= buf_ptr
[buf_pos
]) ||
252 '-' == buf_ptr
[buf_pos
]) {
254 size_t number_start_pos
= buf_pos
;
255 if (!check_for_number()) {
257 *p_token
= JSON_TOKEN_ERROR
;
260 size_t number_length
= buf_pos
- number_start_pos
;
261 if (skip_white_spaces() && !check_for_separator()) {
262 // must be followed by a separator (or only white spaces until the buffer ends)
263 *p_token
= JSON_TOKEN_ERROR
;
266 *p_token
= JSON_TOKEN_NUMBER
;
267 if (0 != p_token_str
&& 0 != p_str_len
) {
268 *p_token_str
= buf_ptr
+ number_start_pos
;
269 *p_str_len
= number_length
;
272 } // if (number value)
273 else if (check_for_literal("true")) {
274 *p_token
= JSON_TOKEN_LITERAL_TRUE
;
277 else if (check_for_literal("false")) {
278 *p_token
= JSON_TOKEN_LITERAL_FALSE
;
281 else if (check_for_literal("null")) {
282 *p_token
= JSON_TOKEN_LITERAL_NULL
;
286 *p_token
= JSON_TOKEN_ERROR
;
289 } // switch (current char)
290 } // if (skip_white_spaces())
292 return buf_pos
- start_pos
;
295 void JSON_Tokenizer::put_separator()
297 if (JSON_TOKEN_NAME
!= previous_token
&& JSON_TOKEN_NONE
!= previous_token
&&
298 JSON_TOKEN_ARRAY_START
!= previous_token
&& JSON_TOKEN_OBJECT_START
!= previous_token
) {
307 int JSON_Tokenizer::put_next_token(json_token_t p_token
, const char* p_token_str
)
309 int start_len
= buf_len
;
311 case JSON_TOKEN_OBJECT_START
:
312 case JSON_TOKEN_ARRAY_START
: {
314 put_c( (JSON_TOKEN_OBJECT_START
== p_token
) ? '{' : '[' );
322 case JSON_TOKEN_OBJECT_END
:
323 case JSON_TOKEN_ARRAY_END
: {
325 if (JSON_TOKEN_OBJECT_START
!= previous_token
&& JSON_TOKEN_ARRAY_START
!= previous_token
) {
329 } else if (MAX_TABS
>= depth
) {
330 // empty object or array -> remove the extra tab added at the start token
333 buf_ptr
[buf_len
] = 0;
336 put_c( (JSON_TOKEN_OBJECT_END
== p_token
) ? '}' : ']' );
339 case JSON_TOKEN_NUMBER
:
340 case JSON_TOKEN_STRING
:
344 case JSON_TOKEN_LITERAL_TRUE
:
348 case JSON_TOKEN_LITERAL_FALSE
:
352 case JSON_TOKEN_LITERAL_NULL
:
356 case JSON_TOKEN_NAME
:
370 previous_token
= p_token
;
371 return buf_len
- start_len
;
This page took 0.038811 seconds and 5 git commands to generate.