1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
11 #include "JSON_Tokenizer.hh"
15 static const char TABS
[] =
16 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
17 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
18 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
19 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
20 const size_t MAX_TABS
= sizeof(TABS
) - 1; // 64
22 void JSON_Tokenizer::init(const char* p_buf
, const size_t p_buf_len
)
24 if (p_buf
!= 0 && p_buf_len
!= 0) {
25 buf_ptr
= mcopystrn(p_buf
, p_buf_len
);
32 previous_token
= JSON_TOKEN_NONE
;
35 JSON_Tokenizer::~JSON_Tokenizer()
40 void JSON_Tokenizer::put_c(const char c
)
42 buf_ptr
= mputprintf(buf_ptr
, "%c", c
);
46 void JSON_Tokenizer::put_s(const char* s
)
48 buf_ptr
= mputstr(buf_ptr
, s
);
52 void JSON_Tokenizer::put_depth()
54 put_s(TABS
+ ((depth
> MAX_TABS
) ? 0 : MAX_TABS
- depth
));
57 bool JSON_Tokenizer::skip_white_spaces()
59 while(buf_pos
< buf_len
) {
60 switch(buf_ptr
[buf_pos
]) {
75 bool JSON_Tokenizer::check_for_string()
77 if ('\"' == buf_ptr
[buf_pos
]) {
82 while (buf_pos
< buf_len
) {
83 if ('\"' == buf_ptr
[buf_pos
]) {
86 else if ('\\' == buf_ptr
[buf_pos
]) {
87 // skip escaped character (so escaped quotes (\") are not mistaken for the ending quotes)
95 bool JSON_Tokenizer::check_for_number()
97 bool first_digit
= false; // first non-zero digit reached
98 bool zero
= false; // first zero digit reached
99 bool decimal_point
= false; // decimal point (.) reached
100 bool exponent_mark
= false; // exponential mark (e or E) reached
101 bool exponent_sign
= false; // sign of the exponential (- or +) reached
103 if ('-' == buf_ptr
[buf_pos
]) {
107 while (buf_pos
< buf_len
) {
108 switch(buf_ptr
[buf_pos
]) {
110 if (decimal_point
|| exponent_mark
|| (!first_digit
&& !zero
)) {
113 decimal_point
= true;
119 if (exponent_mark
|| (!first_digit
&& !zero
)) {
122 exponent_mark
= true;
127 if (!first_digit
&& (exponent_mark
|| (!decimal_point
&& zero
))) {
141 if (!first_digit
&& zero
&& (!decimal_point
|| exponent_mark
)) {
148 if (exponent_sign
|| !exponent_mark
|| zero
|| first_digit
) {
151 exponent_sign
= true;
154 return first_digit
|| zero
;
159 return first_digit
|| zero
;
162 bool JSON_Tokenizer::check_for_separator()
164 if (buf_pos
< buf_len
) {
165 switch(buf_ptr
[buf_pos
]) {
182 bool JSON_Tokenizer::check_for_literal(const char* p_literal
)
184 size_t len
= strlen(p_literal
);
185 size_t start_pos
= buf_pos
;
187 if (buf_len
- buf_pos
>= len
&&
188 0 == strncmp(buf_ptr
+ buf_pos
, p_literal
, len
)) {
190 if (!skip_white_spaces() || check_for_separator()) {
193 // must be followed by a separator (or only white spaces until the buffer ends) -> undo buffer action
200 int JSON_Tokenizer::get_next_token(json_token_t
* p_token
, char** p_token_str
, size_t* p_str_len
)
202 size_t start_pos
= buf_pos
;
203 *p_token
= JSON_TOKEN_NONE
;
204 if (0 != p_token_str
&& 0 != p_str_len
) {
209 if (skip_white_spaces()) {
210 char c
= buf_ptr
[buf_pos
];
214 *p_token
= ('{' == c
) ? JSON_TOKEN_OBJECT_START
: JSON_TOKEN_ARRAY_START
;
220 if (skip_white_spaces() && !check_for_separator()) {
221 // must be followed by a separator (or only white spaces until the buffer ends)
222 *p_token
= JSON_TOKEN_ERROR
;
224 *p_token
= ('}' == c
) ? JSON_TOKEN_OBJECT_END
: JSON_TOKEN_ARRAY_END
;
228 // string value or field name
229 size_t string_start_pos
= buf_pos
;
230 if(!check_for_string()) {
231 // invalid string value
232 *p_token
= JSON_TOKEN_ERROR
;
235 size_t string_end_pos
= ++buf_pos
; // step over the string's ending quotes
236 if (skip_white_spaces() && ':' == buf_ptr
[buf_pos
]) {
237 // name token - don't include the starting and ending quotes
238 *p_token
= JSON_TOKEN_NAME
;
239 if (0 != p_token_str
&& 0 != p_str_len
) {
240 *p_token_str
= buf_ptr
+ string_start_pos
+ 1;
241 *p_str_len
= string_end_pos
- string_start_pos
- 2;
244 } else if (check_for_separator()) {
245 // value token - include the starting and ending quotes
246 *p_token
= JSON_TOKEN_STRING
;
247 if (0 != p_token_str
&& 0 != p_str_len
) {
248 *p_token_str
= buf_ptr
+ string_start_pos
;
249 *p_str_len
= string_end_pos
- string_start_pos
;
252 // value token, but there is no separator after it -> error
253 *p_token
= JSON_TOKEN_ERROR
;
257 } // case: string value or field name
259 if (('0' <= buf_ptr
[buf_pos
] && '9' >= buf_ptr
[buf_pos
]) ||
260 '-' == buf_ptr
[buf_pos
]) {
262 size_t number_start_pos
= buf_pos
;
263 if (!check_for_number()) {
265 *p_token
= JSON_TOKEN_ERROR
;
268 size_t number_length
= buf_pos
- number_start_pos
;
269 if (skip_white_spaces() && !check_for_separator()) {
270 // must be followed by a separator (or only white spaces until the buffer ends)
271 *p_token
= JSON_TOKEN_ERROR
;
274 *p_token
= JSON_TOKEN_NUMBER
;
275 if (0 != p_token_str
&& 0 != p_str_len
) {
276 *p_token_str
= buf_ptr
+ number_start_pos
;
277 *p_str_len
= number_length
;
280 } // if (number value)
281 else if (check_for_literal("true")) {
282 *p_token
= JSON_TOKEN_LITERAL_TRUE
;
285 else if (check_for_literal("false")) {
286 *p_token
= JSON_TOKEN_LITERAL_FALSE
;
289 else if (check_for_literal("null")) {
290 *p_token
= JSON_TOKEN_LITERAL_NULL
;
294 *p_token
= JSON_TOKEN_ERROR
;
297 } // switch (current char)
298 } // if (skip_white_spaces())
300 return buf_pos
- start_pos
;
303 void JSON_Tokenizer::put_separator()
305 if (JSON_TOKEN_NAME
!= previous_token
&& JSON_TOKEN_NONE
!= previous_token
&&
306 JSON_TOKEN_ARRAY_START
!= previous_token
&& JSON_TOKEN_OBJECT_START
!= previous_token
) {
315 int JSON_Tokenizer::put_next_token(json_token_t p_token
, const char* p_token_str
)
317 int start_len
= buf_len
;
319 case JSON_TOKEN_OBJECT_START
:
320 case JSON_TOKEN_ARRAY_START
: {
322 put_c( (JSON_TOKEN_OBJECT_START
== p_token
) ? '{' : '[' );
330 case JSON_TOKEN_OBJECT_END
:
331 case JSON_TOKEN_ARRAY_END
: {
333 if (JSON_TOKEN_OBJECT_START
!= previous_token
&& JSON_TOKEN_ARRAY_START
!= previous_token
) {
337 } else if (MAX_TABS
>= depth
) {
338 // empty object or array -> remove the extra tab added at the start token
341 buf_ptr
[buf_len
] = 0;
344 put_c( (JSON_TOKEN_OBJECT_END
== p_token
) ? '}' : ']' );
347 case JSON_TOKEN_NUMBER
:
348 case JSON_TOKEN_STRING
:
352 case JSON_TOKEN_LITERAL_TRUE
:
356 case JSON_TOKEN_LITERAL_FALSE
:
360 case JSON_TOKEN_LITERAL_NULL
:
364 case JSON_TOKEN_NAME
:
378 previous_token
= p_token
;
379 return buf_len
- start_len
;
382 void JSON_Tokenizer::put_raw_data(const char* p_data
, size_t p_len
)
384 buf_ptr
= mputstrn(buf_ptr
, p_data
, p_len
);
388 char* convert_to_json_string(const char* str
)
390 char* ret_val
= mcopystrn("\"", 1);
391 // control characters (like \n) cannot be placed in a JSON string, replace
392 // them with JSON metacharacters
393 // double quotes and backslashes need to be escaped, too
394 size_t str_len
= strlen(str
);
395 for (size_t i
= 0; i
< str_len
; ++i
) {
398 ret_val
= mputstrn(ret_val
, "\\n", 2);
401 ret_val
= mputstrn(ret_val
, "\\r", 2);
404 ret_val
= mputstrn(ret_val
, "\\t", 2);
407 ret_val
= mputstrn(ret_val
, "\\f", 2);
410 ret_val
= mputstrn(ret_val
, "\\b", 2);
413 ret_val
= mputstrn(ret_val
, "\\\"", 2);
416 ret_val
= mputstrn(ret_val
, "\\\\", 2);
419 if (str
[i
] < 32 && str
[i
] > 0) {
420 // use the JSON \uHHHH notation for other control characters
421 // (this is just for esthetic reasons, these wouldn't break the JSON
423 ret_val
= mputprintf(ret_val
, "\\u00%d%c", str
[i
] / 16,
424 (str
[i
] % 16 < 10) ? (str
[i
] % 16 + '0') : (str
[i
] % 16 - 10 + 'A'));
427 ret_val
= mputc(ret_val
, str
[i
]);
432 return mputstrn(ret_val
, "\"", 1);
This page took 0.041047 seconds and 5 git commands to generate.