1 /******************************************************************************
2 * Copyright (c) 2000-2016 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
12 ******************************************************************************/
16 #include "JSON_Tokenizer.hh"
20 static const char TABS
[] =
21 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
22 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
23 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
24 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
25 const size_t MAX_TABS
= sizeof(TABS
) - 1; // 64
27 void JSON_Tokenizer::init(const char* p_buf
, const size_t p_buf_len
)
29 if (p_buf
!= 0 && p_buf_len
!= 0) {
30 buf_ptr
= mcopystrn(p_buf
, p_buf_len
);
37 previous_token
= JSON_TOKEN_NONE
;
40 JSON_Tokenizer::~JSON_Tokenizer()
45 void JSON_Tokenizer::put_c(const char c
)
47 buf_ptr
= mputprintf(buf_ptr
, "%c", c
);
51 void JSON_Tokenizer::put_s(const char* s
)
53 buf_ptr
= mputstr(buf_ptr
, s
);
57 void JSON_Tokenizer::put_depth()
59 put_s(TABS
+ ((depth
> MAX_TABS
) ? 0 : MAX_TABS
- depth
));
62 bool JSON_Tokenizer::skip_white_spaces()
64 while(buf_pos
< buf_len
) {
65 switch(buf_ptr
[buf_pos
]) {
80 bool JSON_Tokenizer::check_for_string()
82 if ('\"' == buf_ptr
[buf_pos
]) {
87 while (buf_pos
< buf_len
) {
88 if ('\"' == buf_ptr
[buf_pos
]) {
91 else if ('\\' == buf_ptr
[buf_pos
]) {
92 // skip escaped character (so escaped quotes (\") are not mistaken for the ending quotes)
100 bool JSON_Tokenizer::check_for_number()
102 bool first_digit
= false; // first non-zero digit reached
103 bool zero
= false; // first zero digit reached
104 bool decimal_point
= false; // decimal point (.) reached
105 bool exponent_mark
= false; // exponential mark (e or E) reached
106 bool exponent_sign
= false; // sign of the exponential (- or +) reached
108 if ('-' == buf_ptr
[buf_pos
]) {
112 while (buf_pos
< buf_len
) {
113 switch(buf_ptr
[buf_pos
]) {
115 if (decimal_point
|| exponent_mark
|| (!first_digit
&& !zero
)) {
118 decimal_point
= true;
124 if (exponent_mark
|| (!first_digit
&& !zero
)) {
127 exponent_mark
= true;
132 if (!first_digit
&& (exponent_mark
|| (!decimal_point
&& zero
))) {
146 if (!first_digit
&& zero
&& (!decimal_point
|| exponent_mark
)) {
153 if (exponent_sign
|| !exponent_mark
|| zero
|| first_digit
) {
156 exponent_sign
= true;
159 return first_digit
|| zero
;
164 return first_digit
|| zero
;
167 bool JSON_Tokenizer::check_for_separator()
169 if (buf_pos
< buf_len
) {
170 switch(buf_ptr
[buf_pos
]) {
187 bool JSON_Tokenizer::check_for_literal(const char* p_literal
)
189 size_t len
= strlen(p_literal
);
190 size_t start_pos
= buf_pos
;
192 if (buf_len
- buf_pos
>= len
&&
193 0 == strncmp(buf_ptr
+ buf_pos
, p_literal
, len
)) {
195 if (!skip_white_spaces() || check_for_separator()) {
198 // must be followed by a separator (or only white spaces until the buffer ends) -> undo buffer action
205 int JSON_Tokenizer::get_next_token(json_token_t
* p_token
, char** p_token_str
, size_t* p_str_len
)
207 size_t start_pos
= buf_pos
;
208 *p_token
= JSON_TOKEN_NONE
;
209 if (0 != p_token_str
&& 0 != p_str_len
) {
214 if (skip_white_spaces()) {
215 char c
= buf_ptr
[buf_pos
];
219 *p_token
= ('{' == c
) ? JSON_TOKEN_OBJECT_START
: JSON_TOKEN_ARRAY_START
;
225 if (skip_white_spaces() && !check_for_separator()) {
226 // must be followed by a separator (or only white spaces until the buffer ends)
227 *p_token
= JSON_TOKEN_ERROR
;
229 *p_token
= ('}' == c
) ? JSON_TOKEN_OBJECT_END
: JSON_TOKEN_ARRAY_END
;
233 // string value or field name
234 size_t string_start_pos
= buf_pos
;
235 if(!check_for_string()) {
236 // invalid string value
237 *p_token
= JSON_TOKEN_ERROR
;
240 size_t string_end_pos
= ++buf_pos
; // step over the string's ending quotes
241 if (skip_white_spaces() && ':' == buf_ptr
[buf_pos
]) {
242 // name token - don't include the starting and ending quotes
243 *p_token
= JSON_TOKEN_NAME
;
244 if (0 != p_token_str
&& 0 != p_str_len
) {
245 *p_token_str
= buf_ptr
+ string_start_pos
+ 1;
246 *p_str_len
= string_end_pos
- string_start_pos
- 2;
249 } else if (check_for_separator()) {
250 // value token - include the starting and ending quotes
251 *p_token
= JSON_TOKEN_STRING
;
252 if (0 != p_token_str
&& 0 != p_str_len
) {
253 *p_token_str
= buf_ptr
+ string_start_pos
;
254 *p_str_len
= string_end_pos
- string_start_pos
;
257 // value token, but there is no separator after it -> error
258 *p_token
= JSON_TOKEN_ERROR
;
262 } // case: string value or field name
264 if (('0' <= buf_ptr
[buf_pos
] && '9' >= buf_ptr
[buf_pos
]) ||
265 '-' == buf_ptr
[buf_pos
]) {
267 size_t number_start_pos
= buf_pos
;
268 if (!check_for_number()) {
270 *p_token
= JSON_TOKEN_ERROR
;
273 size_t number_length
= buf_pos
- number_start_pos
;
274 if (skip_white_spaces() && !check_for_separator()) {
275 // must be followed by a separator (or only white spaces until the buffer ends)
276 *p_token
= JSON_TOKEN_ERROR
;
279 *p_token
= JSON_TOKEN_NUMBER
;
280 if (0 != p_token_str
&& 0 != p_str_len
) {
281 *p_token_str
= buf_ptr
+ number_start_pos
;
282 *p_str_len
= number_length
;
285 } // if (number value)
286 else if (check_for_literal("true")) {
287 *p_token
= JSON_TOKEN_LITERAL_TRUE
;
290 else if (check_for_literal("false")) {
291 *p_token
= JSON_TOKEN_LITERAL_FALSE
;
294 else if (check_for_literal("null")) {
295 *p_token
= JSON_TOKEN_LITERAL_NULL
;
299 *p_token
= JSON_TOKEN_ERROR
;
302 } // switch (current char)
303 } // if (skip_white_spaces())
305 return buf_pos
- start_pos
;
308 void JSON_Tokenizer::put_separator()
310 if (JSON_TOKEN_NAME
!= previous_token
&& JSON_TOKEN_NONE
!= previous_token
&&
311 JSON_TOKEN_ARRAY_START
!= previous_token
&& JSON_TOKEN_OBJECT_START
!= previous_token
) {
320 int JSON_Tokenizer::put_next_token(json_token_t p_token
, const char* p_token_str
)
322 int start_len
= buf_len
;
324 case JSON_TOKEN_OBJECT_START
:
325 case JSON_TOKEN_ARRAY_START
: {
327 put_c( (JSON_TOKEN_OBJECT_START
== p_token
) ? '{' : '[' );
335 case JSON_TOKEN_OBJECT_END
:
336 case JSON_TOKEN_ARRAY_END
: {
338 if (JSON_TOKEN_OBJECT_START
!= previous_token
&& JSON_TOKEN_ARRAY_START
!= previous_token
) {
342 } else if (MAX_TABS
>= depth
) {
343 // empty object or array -> remove the extra tab added at the start token
346 buf_ptr
[buf_len
] = 0;
349 put_c( (JSON_TOKEN_OBJECT_END
== p_token
) ? '}' : ']' );
352 case JSON_TOKEN_NUMBER
:
353 case JSON_TOKEN_STRING
:
357 case JSON_TOKEN_LITERAL_TRUE
:
361 case JSON_TOKEN_LITERAL_FALSE
:
365 case JSON_TOKEN_LITERAL_NULL
:
369 case JSON_TOKEN_NAME
:
383 previous_token
= p_token
;
384 return buf_len
- start_len
;
387 void JSON_Tokenizer::put_raw_data(const char* p_data
, size_t p_len
)
389 buf_ptr
= mputstrn(buf_ptr
, p_data
, p_len
);
393 char* convert_to_json_string(const char* str
)
395 char* ret_val
= mcopystrn("\"", 1);
396 // control characters (like \n) cannot be placed in a JSON string, replace
397 // them with JSON metacharacters
398 // double quotes and backslashes need to be escaped, too
399 size_t str_len
= strlen(str
);
400 for (size_t i
= 0; i
< str_len
; ++i
) {
403 ret_val
= mputstrn(ret_val
, "\\n", 2);
406 ret_val
= mputstrn(ret_val
, "\\r", 2);
409 ret_val
= mputstrn(ret_val
, "\\t", 2);
412 ret_val
= mputstrn(ret_val
, "\\f", 2);
415 ret_val
= mputstrn(ret_val
, "\\b", 2);
418 ret_val
= mputstrn(ret_val
, "\\\"", 2);
421 ret_val
= mputstrn(ret_val
, "\\\\", 2);
424 if (str
[i
] < 32 && str
[i
] > 0) {
425 // use the JSON \uHHHH notation for other control characters
426 // (this is just for esthetic reasons, these wouldn't break the JSON
428 ret_val
= mputprintf(ret_val
, "\\u00%d%c", str
[i
] / 16,
429 (str
[i
] % 16 < 10) ? (str
[i
] % 16 + '0') : (str
[i
] % 16 - 10 + 'A'));
432 ret_val
= mputc(ret_val
, str
[i
]);
437 return mputstrn(ret_val
, "\"", 1);
This page took 0.051958 seconds and 5 git commands to generate.