1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21 #include "zbxjson.h"
22 #include "json_parser.h"
23
24 /******************************************************************************
25 * *
26 * Function: zbx_json_strerror *
27 * *
28 * Purpose: return string describing json error *
29 * *
30 * Return value: pointer to the null terminated string *
31 * *
32 * Author: Eugene Grigorjev *
33 * *
34 ******************************************************************************/
35 #define ZBX_JSON_MAX_STRERROR 255
36
37 static char zbx_json_strerror_message[ZBX_JSON_MAX_STRERROR];
38
zbx_json_strerror(void)39 const char *zbx_json_strerror(void)
40 {
41 return zbx_json_strerror_message;
42 }
43
44 #ifdef HAVE___VA_ARGS__
45 # define zbx_set_json_strerror(fmt, ...) __zbx_zbx_set_json_strerror(ZBX_CONST_STRING(fmt), ##__VA_ARGS__)
46 #else
47 # define zbx_set_json_strerror __zbx_zbx_set_json_strerror
48 #endif
__zbx_zbx_set_json_strerror(const char * fmt,...)49 static void __zbx_zbx_set_json_strerror(const char *fmt, ...)
50 {
51 va_list args;
52
53 va_start(args, fmt);
54
55 zbx_vsnprintf(zbx_json_strerror_message, sizeof(zbx_json_strerror_message), fmt, args);
56
57 va_end(args);
58 }
59
60 /******************************************************************************
61 * *
62 * Function: __zbx_json_realloc *
63 * *
64 * Author: Alexander Vladishev *
65 * *
66 ******************************************************************************/
__zbx_json_realloc(struct zbx_json * j,size_t need)67 static void __zbx_json_realloc(struct zbx_json *j, size_t need)
68 {
69 int realloc = 0;
70
71 if (NULL == j->buffer)
72 {
73 if (need > sizeof(j->buf_stat))
74 {
75 j->buffer_allocated = need;
76 j->buffer = zbx_malloc(j->buffer, j->buffer_allocated);
77 }
78 else
79 {
80 j->buffer_allocated = sizeof(j->buf_stat);
81 j->buffer = j->buf_stat;
82 }
83 return;
84 }
85
86 while (need > j->buffer_allocated)
87 {
88 if (0 == j->buffer_allocated)
89 j->buffer_allocated = 1024;
90 else
91 j->buffer_allocated *= 2;
92 realloc = 1;
93 }
94
95 if (1 == realloc)
96 {
97 if (j->buffer == j->buf_stat)
98 {
99 j->buffer = NULL;
100 j->buffer = zbx_malloc(j->buffer, j->buffer_allocated);
101 memcpy(j->buffer, j->buf_stat, sizeof(j->buf_stat));
102 }
103 else
104 j->buffer = zbx_realloc(j->buffer, j->buffer_allocated);
105 }
106 }
107
zbx_json_init(struct zbx_json * j,size_t allocate)108 void zbx_json_init(struct zbx_json *j, size_t allocate)
109 {
110 assert(j);
111
112 j->buffer = NULL;
113 j->buffer_allocated = 0;
114 j->buffer_offset = 0;
115 j->buffer_size = 0;
116 j->status = ZBX_JSON_EMPTY;
117 j->level = 0;
118 __zbx_json_realloc(j, allocate);
119 *j->buffer = '\0';
120
121 zbx_json_addobject(j, NULL);
122 }
123
zbx_json_clean(struct zbx_json * j)124 void zbx_json_clean(struct zbx_json *j)
125 {
126 assert(j);
127
128 j->buffer_offset = 0;
129 j->buffer_size = 0;
130 j->status = ZBX_JSON_EMPTY;
131 j->level = 0;
132 *j->buffer = '\0';
133
134 zbx_json_addobject(j, NULL);
135 }
136
zbx_json_free(struct zbx_json * j)137 void zbx_json_free(struct zbx_json *j)
138 {
139 assert(j);
140
141 if (j->buffer != j->buf_stat)
142 zbx_free(j->buffer);
143 }
144
__zbx_json_stringsize(const char * string,zbx_json_type_t type)145 static size_t __zbx_json_stringsize(const char *string, zbx_json_type_t type)
146 {
147 size_t len = 0;
148 const char *sptr;
149 char buffer[] = {"null"};
150
151 for (sptr = (NULL != string ? string : buffer); '\0' != *sptr; sptr++)
152 {
153 switch (*sptr)
154 {
155 case '"': /* quotation mark */
156 case '\\': /* reverse solidus */
157 /* We do not escape '/' (solidus). https://www.rfc-editor.org/errata_search.php?rfc=4627 */
158 /* says: "/" and "\/" are both allowed and both produce the same result. */
159 case '\b': /* backspace */
160 case '\f': /* formfeed */
161 case '\n': /* newline */
162 case '\r': /* carriage return */
163 case '\t': /* horizontal tab */
164 len += 2;
165 break;
166 default:
167 /* RFC 8259 requires escaping control characters U+0000 - U+001F */
168 if (0x1f >= (unsigned char)*sptr)
169 len += 6;
170 else
171 len++;
172 }
173 }
174
175 if (NULL != string && ZBX_JSON_TYPE_STRING == type)
176 len += 2; /* "" */
177
178 return len;
179 }
180
__zbx_json_insstring(char * p,const char * string,zbx_json_type_t type)181 static char *__zbx_json_insstring(char *p, const char *string, zbx_json_type_t type)
182 {
183 const char *sptr;
184 char buffer[] = {"null"};
185
186 if (NULL != string && ZBX_JSON_TYPE_STRING == type)
187 *p++ = '"';
188
189 for (sptr = (NULL != string ? string : buffer); '\0' != *sptr; sptr++)
190 {
191 switch (*sptr)
192 {
193 case '"': /* quotation mark */
194 *p++ = '\\';
195 *p++ = '"';
196 break;
197 case '\\': /* reverse solidus */
198 *p++ = '\\';
199 *p++ = '\\';
200 break;
201 /* We do not escape '/' (solidus). https://www.rfc-editor.org/errata_search.php?rfc=4627 */
202 /* says: "/" and "\/" are both allowed and both produce the same result. */
203 case '\b': /* backspace */
204 *p++ = '\\';
205 *p++ = 'b';
206 break;
207 case '\f': /* formfeed */
208 *p++ = '\\';
209 *p++ = 'f';
210 break;
211 case '\n': /* newline */
212 *p++ = '\\';
213 *p++ = 'n';
214 break;
215 case '\r': /* carriage return */
216 *p++ = '\\';
217 *p++ = 'r';
218 break;
219 case '\t': /* horizontal tab */
220 *p++ = '\\';
221 *p++ = 't';
222 break;
223 default:
224 /* RFC 8259 requires escaping control characters U+0000 - U+001F */
225 if (0x1f >= (unsigned char)*sptr)
226 {
227 *p++ = '\\';
228 *p++ = 'u';
229 *p++ = '0';
230 *p++ = '0';
231 *p++ = zbx_num2hex((((unsigned char)*sptr) >> 4) & 0xf);
232 *p++ = zbx_num2hex(((unsigned char)*sptr) & 0xf);
233 }
234 else
235 *p++ = *sptr;
236 }
237 }
238
239 if (NULL != string && ZBX_JSON_TYPE_STRING == type)
240 *p++ = '"';
241
242 return p;
243 }
244
__zbx_json_addobject(struct zbx_json * j,const char * name,int object)245 static void __zbx_json_addobject(struct zbx_json *j, const char *name, int object)
246 {
247 size_t len = 2; /* brackets */
248 char *p, *psrc, *pdst;
249
250 assert(j);
251
252 if (ZBX_JSON_COMMA == j->status)
253 len++; /* , */
254
255 if (NULL != name)
256 {
257 len += __zbx_json_stringsize(name, ZBX_JSON_TYPE_STRING);
258 len += 1; /* : */
259 }
260
261 __zbx_json_realloc(j, j->buffer_size + len + 1/*'\0'*/);
262
263 psrc = j->buffer + j->buffer_offset;
264 pdst = j->buffer + j->buffer_offset + len;
265
266 memmove(pdst, psrc, j->buffer_size - j->buffer_offset + 1/*'\0'*/);
267
268 p = psrc;
269
270 if (ZBX_JSON_COMMA == j->status)
271 *p++ = ',';
272
273 if (NULL != name)
274 {
275 p = __zbx_json_insstring(p, name, ZBX_JSON_TYPE_STRING);
276 *p++ = ':';
277 }
278
279 *p++ = object ? '{' : '[';
280 *p = object ? '}' : ']';
281
282 j->buffer_offset = p - j->buffer;
283 j->buffer_size += len;
284 j->level++;
285 j->status = ZBX_JSON_EMPTY;
286 }
287
zbx_json_addobject(struct zbx_json * j,const char * name)288 void zbx_json_addobject(struct zbx_json *j, const char *name)
289 {
290 __zbx_json_addobject(j, name, 1);
291 }
292
zbx_json_addarray(struct zbx_json * j,const char * name)293 void zbx_json_addarray(struct zbx_json *j, const char *name)
294 {
295 __zbx_json_addobject(j, name, 0);
296 }
297
zbx_json_addstring(struct zbx_json * j,const char * name,const char * string,zbx_json_type_t type)298 void zbx_json_addstring(struct zbx_json *j, const char *name, const char *string, zbx_json_type_t type)
299 {
300 size_t len = 0;
301 char *p, *psrc, *pdst;
302
303 assert(j);
304
305 if (ZBX_JSON_COMMA == j->status)
306 len++; /* , */
307
308 if (NULL != name)
309 {
310 len += __zbx_json_stringsize(name, ZBX_JSON_TYPE_STRING);
311 len += 1; /* : */
312 }
313 len += __zbx_json_stringsize(string, type);
314
315 __zbx_json_realloc(j, j->buffer_size + len + 1/*'\0'*/);
316
317 psrc = j->buffer + j->buffer_offset;
318 pdst = j->buffer + j->buffer_offset + len;
319
320 memmove(pdst, psrc, j->buffer_size - j->buffer_offset + 1/*'\0'*/);
321
322 p = psrc;
323
324 if (ZBX_JSON_COMMA == j->status)
325 *p++ = ',';
326
327 if (NULL != name)
328 {
329 p = __zbx_json_insstring(p, name, ZBX_JSON_TYPE_STRING);
330 *p++ = ':';
331 }
332 p = __zbx_json_insstring(p, string, type);
333
334 j->buffer_offset = p - j->buffer;
335 j->buffer_size += len;
336 j->status = ZBX_JSON_COMMA;
337 }
338
zbx_json_adduint64(struct zbx_json * j,const char * name,zbx_uint64_t value)339 void zbx_json_adduint64(struct zbx_json *j, const char *name, zbx_uint64_t value)
340 {
341 char buffer[MAX_ID_LEN];
342
343 zbx_snprintf(buffer, sizeof(buffer), ZBX_FS_UI64, value);
344 zbx_json_addstring(j, name, buffer, ZBX_JSON_TYPE_INT);
345 }
346
zbx_json_close(struct zbx_json * j)347 int zbx_json_close(struct zbx_json *j)
348 {
349 if (1 == j->level)
350 {
351 zbx_set_json_strerror("cannot close top level object");
352 return FAIL;
353 }
354
355 j->level--;
356 j->buffer_offset++;
357 j->status = ZBX_JSON_COMMA;
358
359 return SUCCEED;
360 }
361
362 /******************************************************************************
363 * *
364 * Function: __zbx_json_type *
365 * *
366 * Purpose: return type of pointed value *
367 * *
368 * Return value: type of pointed value *
369 * *
370 * Author: Alexander Vladishev *
371 * *
372 ******************************************************************************/
__zbx_json_type(const char * p)373 static zbx_json_type_t __zbx_json_type(const char *p)
374 {
375 if ('"' == *p)
376 return ZBX_JSON_TYPE_STRING;
377 if (('0' <= *p && *p <= '9') || '-' == *p)
378 return ZBX_JSON_TYPE_INT;
379 if ('[' == *p)
380 return ZBX_JSON_TYPE_ARRAY;
381 if ('{' == *p)
382 return ZBX_JSON_TYPE_OBJECT;
383 if ('n' == p[0] && 'u' == p[1] && 'l' == p[2] && 'l' == p[3])
384 return ZBX_JSON_TYPE_NULL;
385
386 zbx_set_json_strerror("Invalid type of JSON value \"%.64s\"", p);
387
388 return ZBX_JSON_TYPE_UNKNOWN;
389 }
390
391 /******************************************************************************
392 * *
393 * Function: __zbx_json_rbracket *
394 * *
395 * Purpose: return position of right bracket *
396 * *
397 * Return value: position of right bracket *
398 * NULL - an error occurred *
399 * *
400 * Author: Alexander Vladishev *
401 * *
402 ******************************************************************************/
__zbx_json_rbracket(const char * p)403 static const char *__zbx_json_rbracket(const char *p)
404 {
405 int level = 0;
406 int state = 0; /* 0 - outside string; 1 - inside string */
407 char lbracket, rbracket;
408
409 assert(p);
410
411 lbracket = *p;
412
413 if ('{' != lbracket && '[' != lbracket)
414 return NULL;
415
416 rbracket = ('{' == lbracket ? '}' : ']');
417
418 while ('\0' != *p)
419 {
420 switch (*p)
421 {
422 case '"':
423 state = (0 == state ? 1 : 0);
424 break;
425 case '\\':
426 if (1 == state)
427 if ('\0' == *++p)
428 return NULL;
429 break;
430 case '[':
431 case '{':
432 if (0 == state)
433 level++;
434 break;
435 case ']':
436 case '}':
437 if (0 == state)
438 {
439 level--;
440 if (0 == level)
441 return (rbracket == *p ? p : NULL);
442 }
443 break;
444 }
445 p++;
446 }
447
448 return NULL;
449 }
450
451 /******************************************************************************
452 * *
453 * Function: zbx_json_open *
454 * *
455 * Purpose: open json buffer and check for brackets *
456 * *
457 * Return value: SUCCESS - processed successfully *
458 * FAIL - an error occurred *
459 * *
460 ******************************************************************************/
zbx_json_open(const char * buffer,struct zbx_json_parse * jp)461 int zbx_json_open(const char *buffer, struct zbx_json_parse *jp)
462 {
463 char *error = NULL;
464 int len;
465
466 SKIP_WHITESPACE(buffer);
467
468 /* return immediate failure without logging when opening empty string */
469 if ('\0' == *buffer)
470 return FAIL;
471
472 jp->start = buffer;
473 jp->end = NULL;
474
475 if (0 == (len = zbx_json_validate(jp->start, &error)))
476 {
477 if (NULL != error)
478 {
479 zbx_set_json_strerror("cannot parse as a valid JSON object: %s", error);
480 zbx_free(error);
481 }
482 else
483 zbx_set_json_strerror("cannot parse as a valid JSON object \"%.64s\"", buffer);
484
485 return FAIL;
486 }
487 jp->end = jp->start + len - 1;
488
489 return SUCCEED;
490 }
491
492 /******************************************************************************
493 * *
494 * Function: zbx_json_next *
495 * *
496 * Purpose: locate next pair or element *
497 * *
498 * Return value: NULL - no more values *
499 * NOT NULL - pointer to pair or element *
500 * {"name",... or "array":["name", ... ,1,null] *
501 * p = ^ ^ *
502 * *
503 * Author: Alexander Vladishev *
504 * *
505 ******************************************************************************/
zbx_json_next(const struct zbx_json_parse * jp,const char * p)506 const char *zbx_json_next(const struct zbx_json_parse *jp, const char *p)
507 {
508 int level = 0;
509 int state = 0; /* 0 - outside string; 1 - inside string */
510
511 if (1 == jp->end - jp->start) /* empty object or array */
512 return NULL;
513
514 if (NULL == p)
515 {
516 p = jp->start + 1;
517 SKIP_WHITESPACE(p);
518 return p;
519 }
520
521 while (p <= jp->end)
522 {
523 switch (*p)
524 {
525 case '"':
526 state = (0 == state) ? 1 : 0;
527 break;
528 case '\\':
529 if (1 == state)
530 p++;
531 break;
532 case '[':
533 case '{':
534 if (0 == state)
535 level++;
536 break;
537 case ']':
538 case '}':
539 if (0 == state)
540 {
541 if (0 == level)
542 return NULL;
543 level--;
544 }
545 break;
546 case ',':
547 if (0 == state && 0 == level)
548 {
549 p++;
550 SKIP_WHITESPACE(p);
551 return p;
552 }
553 break;
554 }
555 p++;
556 }
557
558 return NULL;
559 }
560
zbx_json_decodenull(const char * p)561 static const char *zbx_json_decodenull(const char *p)
562 {
563 if ('n' == p[0] && 'u' == p[1] && 'l' == p[2] && 'l' == p[3])
564 return p + 4;
565
566 return NULL;
567 }
568
569 /******************************************************************************
570 * *
571 * Function: zbx_json_decode_character *
572 * *
573 * Purpose: decodes escape character *
574 * *
575 * Parameters: p - [IN/OUT] a pointer to the next character in string *
576 * *
577 * Return value: 0 - invalid escape character *
578 * !0 - the escaped character *
579 * *
580 ******************************************************************************/
zbx_json_decode_character(const char ** p)581 static char zbx_json_decode_character(const char **p)
582 {
583 char out;
584
585 switch (*(++*p))
586 {
587 case '"':
588 out = '"';
589 break;
590 case '\\':
591 out = '\\';
592 break;
593 case '/':
594 out = '/';
595 break;
596 case 'b':
597 out = '\b';
598 break;
599 case 'f':
600 out = '\f';
601 break;
602 case 'n':
603 out = '\n';
604 break;
605 case 'r':
606 out = '\r';
607 break;
608 case 't':
609 out = '\t';
610 break;
611 case 'u':
612 *p += 3; /* "u00" */
613 out = zbx_hex2num(**p) << 4;
614 out += zbx_hex2num(*(++*p));
615 break;
616 default:
617 THIS_SHOULD_NEVER_HAPPEN;
618 return '\0';
619 }
620
621 ++*p;
622
623 return out;
624 }
625
626 /******************************************************************************
627 * *
628 * Function: zbx_json_copy_string *
629 * *
630 * Purpose: copies json name/string value by omitting leading/trailing " and *
631 * converting escape sequences *
632 * *
633 * Parameters: p - [IN] a pointer to the next character in string *
634 * out - [OUT] the output buffer *
635 * size - [IN] the output buffer size *
636 * *
637 * Return value: A pointer to the next character in input string or NULL if *
638 * string copying failed. *
639 * *
640 ******************************************************************************/
zbx_json_copy_string(const char * p,char * out,size_t size)641 static const char *zbx_json_copy_string(const char *p, char *out, size_t size)
642 {
643 char *start = out;
644
645 p++;
646
647 while ('\0' != *p)
648 {
649 switch (*p)
650 {
651 case '\\':
652 if ('\0' != (*out = zbx_json_decode_character(&p)))
653 out++;
654 break;
655 case '"':
656 *out = '\0';
657 return ++p;
658 default:
659 *out++ = *p++;
660 }
661
662 if ((size_t)(out - start) == size)
663 break;
664 }
665
666 return NULL;
667 }
668
669 /******************************************************************************
670 * *
671 * Function: zbx_json_copy_value *
672 * *
673 * Purpose: copies json value *
674 * *
675 * Parameters: p - [IN] a pointer to the next character in string *
676 * len - [IN] the value length *
677 * out - [OUT] the output buffer *
678 * size - [IN] the output buffer size *
679 * *
680 * Return value: A pointer to the next character in input string or NULL if *
681 * string copying failed. *
682 * *
683 * Comments: String values are converted (leading/trailing " dropped and *
684 * escape sequences translated) while other values are simply *
685 * copied. *
686 * *
687 ******************************************************************************/
zbx_json_copy_value(const char * p,size_t len,char * out,size_t size)688 static const char *zbx_json_copy_value(const char *p, size_t len, char *out, size_t size)
689 {
690 if (ZBX_JSON_TYPE_STRING == __zbx_json_type(p))
691 {
692 if (NULL == zbx_json_copy_string(p, out, size))
693 return NULL;
694 }
695 else
696 zbx_strlcpy(out, p, MIN(size, len + 1));
697
698 return p + len;
699 }
700
zbx_json_decodevalue(const char * p,char * string,size_t size,int * is_null)701 static const char *zbx_json_decodevalue(const char *p, char *string, size_t size, int *is_null)
702 {
703 size_t len;
704
705 switch (__zbx_json_type(p))
706 {
707 case ZBX_JSON_TYPE_STRING:
708 case ZBX_JSON_TYPE_INT:
709 if (NULL != is_null)
710 *is_null = 0;
711
712 if (0 == (len = json_parse_value(p, NULL)))
713 return NULL;
714
715 return zbx_json_copy_value(p, len, string, size);
716 case ZBX_JSON_TYPE_NULL:
717 if (NULL != is_null)
718 *is_null = 1;
719 *string = '\0';
720 return zbx_json_decodenull(p);
721 default:
722 return NULL;
723 }
724 }
725
zbx_json_decodevalue_dyn(const char * p,char ** string,size_t * string_alloc,int * is_null)726 static const char *zbx_json_decodevalue_dyn(const char *p, char **string, size_t *string_alloc, int *is_null)
727 {
728 size_t len;
729
730 switch (__zbx_json_type(p))
731 {
732 case ZBX_JSON_TYPE_STRING:
733 case ZBX_JSON_TYPE_INT:
734 if (NULL != is_null)
735 *is_null = 0;
736
737 if (0 == (len = json_parse_value(p, NULL)))
738 return NULL;
739
740 if (*string_alloc <= len)
741 {
742 *string_alloc = len + 1;
743 *string = zbx_realloc(*string, *string_alloc);
744 }
745
746 return zbx_json_copy_value(p, len, *string, *string_alloc);
747 case ZBX_JSON_TYPE_NULL:
748 if (NULL != is_null)
749 *is_null = 1;
750
751 if (*string_alloc < 1)
752 {
753 *string_alloc = 1;
754 *string = zbx_realloc(*string, *string_alloc);
755 }
756
757 **string = '\0';
758
759 return zbx_json_decodenull(p);
760 default:
761 return NULL;
762 }
763 }
764
zbx_json_pair_next(const struct zbx_json_parse * jp,const char * p,char * name,size_t len)765 const char *zbx_json_pair_next(const struct zbx_json_parse *jp, const char *p, char *name, size_t len)
766 {
767 if (NULL == (p = zbx_json_next(jp, p)))
768 return NULL;
769
770 if (ZBX_JSON_TYPE_STRING != __zbx_json_type(p))
771 return NULL;
772
773 if (NULL == (p = zbx_json_copy_string(p, name, len)))
774 return NULL;
775
776 SKIP_WHITESPACE(p);
777
778 if (':' != *p++)
779 return NULL;
780
781 SKIP_WHITESPACE(p);
782
783 return p;
784 }
785
786 /******************************************************************************
787 * *
788 * Function: zbx_json_pair_by_name *
789 * *
790 * Purpose: find pair by name and return pointer to value *
791 * *
792 * Return value: pointer to value *
793 * {"name":["a","b",...]} *
794 * ^ - returned pointer *
795 * *
796 * Author: Alexander Vladishev *
797 * *
798 ******************************************************************************/
zbx_json_pair_by_name(const struct zbx_json_parse * jp,const char * name)799 const char *zbx_json_pair_by_name(const struct zbx_json_parse *jp, const char *name)
800 {
801 char buffer[MAX_STRING_LEN];
802 const char *p = NULL;
803
804 while (NULL != (p = zbx_json_pair_next(jp, p, buffer, sizeof(buffer))))
805 if (0 == strcmp(name, buffer))
806 return p;
807
808 zbx_set_json_strerror("Can't find pair with name \"%s\"", name);
809
810 return NULL;
811 }
812
813 /******************************************************************************
814 * *
815 * Function: zbx_json_next_value *
816 * *
817 * Author: Alexander Vladishev *
818 * *
819 ******************************************************************************/
zbx_json_next_value(const struct zbx_json_parse * jp,const char * p,char * string,size_t len,int * is_null)820 const char *zbx_json_next_value(const struct zbx_json_parse *jp, const char *p, char *string, size_t len, int *is_null)
821 {
822 if (NULL == (p = zbx_json_next(jp, p)))
823 return NULL;
824
825 return zbx_json_decodevalue(p, string, len, is_null);
826 }
827
828 /******************************************************************************
829 * *
830 * Function: zbx_json_next_value_dyn *
831 * *
832 ******************************************************************************/
zbx_json_next_value_dyn(const struct zbx_json_parse * jp,const char * p,char ** string,size_t * string_alloc,int * is_null)833 const char *zbx_json_next_value_dyn(const struct zbx_json_parse *jp, const char *p, char **string,
834 size_t *string_alloc, int *is_null)
835 {
836 if (NULL == (p = zbx_json_next(jp, p)))
837 return NULL;
838
839 return zbx_json_decodevalue_dyn(p, string, string_alloc, is_null);
840 }
841
842 /******************************************************************************
843 * *
844 * Function: zbx_json_value_by_name *
845 * *
846 * Purpose: return value by pair name *
847 * *
848 * Return value: SUCCEED - if value successfully parsed, FAIL - otherwise *
849 * *
850 * Author: Alexander Vladishev *
851 * *
852 ******************************************************************************/
zbx_json_value_by_name(const struct zbx_json_parse * jp,const char * name,char * string,size_t len)853 int zbx_json_value_by_name(const struct zbx_json_parse *jp, const char *name, char *string, size_t len)
854 {
855 const char *p;
856
857 if (NULL == (p = zbx_json_pair_by_name(jp, name)))
858 return FAIL;
859
860 if (NULL == zbx_json_decodevalue(p, string, len, NULL))
861 return FAIL;
862
863 return SUCCEED;
864 }
865
866 /******************************************************************************
867 * *
868 * Function: zbx_json_value_by_name_dyn *
869 * *
870 * Purpose: return value by pair name *
871 * *
872 * Return value: SUCCEED - if value successfully parsed, FAIL - otherwise *
873 * *
874 * Author: Alexander Vladishev *
875 * *
876 ******************************************************************************/
zbx_json_value_by_name_dyn(const struct zbx_json_parse * jp,const char * name,char ** string,size_t * string_alloc)877 int zbx_json_value_by_name_dyn(const struct zbx_json_parse *jp, const char *name, char **string, size_t *string_alloc)
878 {
879 const char *p;
880
881 if (NULL == (p = zbx_json_pair_by_name(jp, name)))
882 return FAIL;
883
884 if (NULL == zbx_json_decodevalue_dyn(p, string, string_alloc, NULL))
885 return FAIL;
886
887 return SUCCEED;
888 }
889
890 /******************************************************************************
891 * *
892 * Function: zbx_json_brackets_open *
893 * *
894 * Return value: SUCCESS - processed successfully *
895 * FAIL - an error occurred *
896 * *
897 * Author: Alexander Vladishev *
898 * *
899 ******************************************************************************/
zbx_json_brackets_open(const char * p,struct zbx_json_parse * jp)900 int zbx_json_brackets_open(const char *p, struct zbx_json_parse *jp)
901 {
902 if (NULL == (jp->end = __zbx_json_rbracket(p)))
903 {
904 zbx_set_json_strerror("Can't open JSON object or array \"%.64s\"", p);
905 return FAIL;
906 }
907
908 SKIP_WHITESPACE(p);
909
910 jp->start = p;
911
912 return SUCCEED;
913 }
914
915 /******************************************************************************
916 * *
917 * Function: zbx_json_brackets_by_name *
918 * *
919 * Return value: SUCCESS - processed successfully *
920 * FAIL - an error occurred *
921 * *
922 * Author: Alexander Vladishev *
923 * *
924 ******************************************************************************/
zbx_json_brackets_by_name(const struct zbx_json_parse * jp,const char * name,struct zbx_json_parse * out)925 int zbx_json_brackets_by_name(const struct zbx_json_parse *jp, const char *name, struct zbx_json_parse *out)
926 {
927 const char *p;
928
929 if (NULL == (p = zbx_json_pair_by_name(jp, name)))
930 return FAIL;
931
932 if (FAIL == zbx_json_brackets_open(p, out))
933 return FAIL;
934
935 return SUCCEED;
936 }
937
938 /******************************************************************************
939 * *
940 * Function: zbx_json_object_is_empty *
941 * *
942 * Return value: SUCCESS - if object is empty *
943 * FAIL - if object contains data *
944 * *
945 * Author: Alexander Vladishev *
946 * *
947 ******************************************************************************/
zbx_json_object_is_empty(const struct zbx_json_parse * jp)948 int zbx_json_object_is_empty(const struct zbx_json_parse *jp)
949 {
950 return jp->end - jp->start > 1 ? FAIL : SUCCEED;
951 }
952
953 /******************************************************************************
954 * *
955 * Function: zbx_json_count *
956 * *
957 * Return value: number of elements in zbx_json_parse object *
958 * *
959 * Author: Alexander Vladishev *
960 * *
961 ******************************************************************************/
zbx_json_count(const struct zbx_json_parse * jp)962 int zbx_json_count(const struct zbx_json_parse *jp)
963 {
964 int num = 0;
965 const char *p = NULL;
966
967 while (NULL != (p = zbx_json_next(jp, p)))
968 num++;
969
970 return num;
971 }
972