Greenbone Vulnerability Management Libraries: util/jsonpull.c Source File

Greenbone Vulnerability Management Libraries 23.1.2

jsonpull.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Greenbone AG
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
6#include "jsonpull.h"
7
8#include <assert.h>
9
10#define GVM_JSON_CHAR_EOF -1
11#define GVM_JSON_CHAR_ERROR -2
12#define GVM_JSON_CHAR_UNDEFINED -3
13
22 gvm_json_path_elem_t *
23gvm_json_pull_path_elem_new (gvm_json_pull_container_type_t parent_type,
24 int depth)
25{
26 gvm_json_path_elem_t *new_elem = g_malloc0 (sizeof (gvm_json_path_elem_t));
27 new_elem->parent_type = parent_type;
28 new_elem->depth = depth;
29 return new_elem;
30}
31
37void
38gvm_json_pull_path_elem_free (gvm_json_path_elem_t *elem)
39{
40 g_free (elem->key);
41 g_free (elem);
42}
43
49void
50gvm_json_pull_event_init (gvm_json_pull_event_t *event)
51{
52 memset (event, 0, sizeof (gvm_json_pull_event_t));
53}
54
60void
61gvm_json_pull_event_cleanup (gvm_json_pull_event_t *event)
62{
63 cJSON_Delete (event->value);
64 g_free (event->error_message);
65 memset (event, 0, sizeof (gvm_json_pull_event_t));
66}
67
76void
77gvm_json_pull_parser_init_full (gvm_json_pull_parser_t *parser,
78 FILE *input_stream, size_t parse_buffer_limit,
79 size_t read_buffer_size)
80{
81 assert (parser);
82 assert (input_stream);
83 memset (parser, 0, sizeof (gvm_json_pull_parser_t));
84
85 if (parse_buffer_limit <= 0)
86 parse_buffer_limit = GVM_JSON_PULL_PARSE_BUFFER_LIMIT;
87
88 if (read_buffer_size <= 0)
89 read_buffer_size = GVM_JSON_PULL_READ_BUFFER_SIZE;
90
91 parser->input_stream = input_stream;
92 parser->path = g_queue_new ();
93 parser->expect = GVM_JSON_PULL_EXPECT_VALUE;
94 parser->parse_buffer_limit = parse_buffer_limit;
95 parser->parse_buffer = g_string_new ("");
96 parser->read_buffer_size = read_buffer_size;
97 parser->read_buffer = g_malloc0 (read_buffer_size);
98 parser->last_read_char = GVM_JSON_CHAR_UNDEFINED;
99}
100
107void
108gvm_json_pull_parser_init (gvm_json_pull_parser_t *parser, FILE *input_stream)
109{
110 gvm_json_pull_parser_init_full (parser, input_stream, 0, 0);
111}
112
118void
119gvm_json_pull_parser_cleanup (gvm_json_pull_parser_t *parser)
120{
121 assert (parser);
122 g_queue_free_full (parser->path,
123 (GDestroyNotify) gvm_json_pull_path_elem_free);
124 g_string_free (parser->parse_buffer, TRUE);
125 g_free (parser->read_buffer);
126 memset (parser, 0, sizeof (gvm_json_pull_parser_t));
127}
128
134static gchar *
135gvm_json_read_stream_error_str ()
136{
137 return g_strdup_printf ("error reading JSON stream: %s", strerror (errno));
138}
139
149static int
150gvm_json_pull_check_parse_buffer_size (const char *value_type,
151 gvm_json_pull_parser_t *parser,
152 gvm_json_pull_event_t *event)
153{
154 if (parser->parse_buffer->len >= parser->parse_buffer_limit)
155 {
156 event->error_message =
157 g_strdup_printf ("%s exceeds size limit of %zu bytes", value_type,
158 parser->parse_buffer_limit);
159 event->type = GVM_JSON_PULL_EVENT_ERROR;
160 return 1;
161 }
162 return 0;
163}
164
172static int
173gvm_json_pull_parser_next_char (gvm_json_pull_parser_t *parser)
174{
175 parser->read_pos++;
176 if (parser->read_pos < parser->last_read_size)
177 {
178 parser->last_read_char =
179 (unsigned char) parser->read_buffer[parser->read_pos];
180 return parser->last_read_char;
181 }
182 else
183 {
184 parser->read_pos = 0;
185 parser->last_read_size = fread (
186 parser->read_buffer, 1, parser->read_buffer_size, parser->input_stream);
187 if (ferror (parser->input_stream))
188 parser->last_read_char = GVM_JSON_CHAR_ERROR;
189 else if (parser->last_read_size <= 0)
190 parser->last_read_char = GVM_JSON_CHAR_EOF;
191 else
192 parser->last_read_char =
193 (unsigned char) parser->read_buffer[parser->read_pos];
194 return parser->last_read_char;
195 }
196}
197
209static int
210gvm_json_pull_parse_buffered (gvm_json_pull_parser_t *parser,
211 gvm_json_pull_event_t *event,
212 const char *value_name,
213 cJSON_bool (*validate_func) (const cJSON *const),
214 cJSON **cjson_value)
215{
216 cJSON *parsed_value = cJSON_Parse (parser->parse_buffer->str);
217 *cjson_value = NULL;
218 if (validate_func (parsed_value) == 0)
219 {
220 event->type = GVM_JSON_PULL_EVENT_ERROR;
221 event->error_message = g_strdup_printf ("error parsing %s", value_name);
222 cJSON_free (parsed_value);
223 return 1;
224 }
225 *cjson_value = parsed_value;
226 return 0;
227}
228
236static void
237gvm_json_pull_handle_read_end (gvm_json_pull_parser_t *parser,
238 gvm_json_pull_event_t *event, gboolean allow_eof)
239{
240 if (parser->last_read_char == GVM_JSON_CHAR_ERROR)
241 {
242 event->error_message = gvm_json_read_stream_error_str ();
243 event->type = GVM_JSON_PULL_EVENT_ERROR;
244 }
245 else if (allow_eof)
246 event->type = GVM_JSON_PULL_EVENT_EOF;
247 else
248 {
249 event->error_message = g_strdup ("unexpected EOF");
250 event->type = GVM_JSON_PULL_EVENT_ERROR;
251 }
252}
253
265static int
266gvm_json_pull_skip_space (gvm_json_pull_parser_t *parser,
267 gvm_json_pull_event_t *event, gboolean allow_eof)
268{
269 while (g_ascii_isspace (parser->last_read_char))
270 gvm_json_pull_parser_next_char (parser);
271 if (parser->last_read_char < 0)
272 {
273 gvm_json_pull_handle_read_end (parser, event, allow_eof);
274 return 1;
275 }
276 return 0;
277}
278
291static int
292gvm_json_pull_parse_string (gvm_json_pull_parser_t *parser,
293 gvm_json_pull_event_t *event, cJSON **cjson_value)
294{
295 gboolean escape_next_char = FALSE;
296 g_string_truncate (parser->parse_buffer, 0);
297 g_string_append_c (parser->parse_buffer, '"');
298 while (gvm_json_pull_parser_next_char (parser) >= 0)
299 {
300 if (gvm_json_pull_check_parse_buffer_size ("string", parser, event))
301 return 1;
302 g_string_append_c (parser->parse_buffer, parser->last_read_char);
303 if (escape_next_char)
304 escape_next_char = FALSE;
305 else if (parser->last_read_char == '\\')
306 escape_next_char = TRUE;
307 else if (parser->last_read_char == '"')
308 break;
309 }
310
311 if (parser->last_read_char < 0)
312 {
313 gvm_json_pull_handle_read_end (parser, event, FALSE);
314 return 1;
315 }
316
317 gvm_json_pull_parser_next_char (parser);
318
319 return gvm_json_pull_parse_buffered (parser, event, "string", cJSON_IsString,
320 cjson_value);
321}
322
335static int
336gvm_json_pull_parse_number (gvm_json_pull_parser_t *parser,
337 gvm_json_pull_event_t *event, cJSON **cjson_value)
338{
339 g_string_truncate (parser->parse_buffer, 0);
340 g_string_append_c (parser->parse_buffer, parser->last_read_char);
341 while (gvm_json_pull_parser_next_char (parser) >= 0)
342 {
343 if (gvm_json_pull_check_parse_buffer_size ("number", parser, event))
344 return 1;
345 if (g_ascii_isdigit (parser->last_read_char)
346 || parser->last_read_char == '.' || parser->last_read_char == 'e'
347 || parser->last_read_char == '-' || parser->last_read_char == '+')
348 g_string_append_c (parser->parse_buffer, parser->last_read_char);
349 else
350 break;
351 }
352
353 if (parser->last_read_char == GVM_JSON_CHAR_ERROR)
354 {
355 event->error_message = gvm_json_read_stream_error_str ();
356 event->type = GVM_JSON_PULL_EVENT_ERROR;
357 return 1;
358 }
359
360 return gvm_json_pull_parse_buffered (parser, event, "number", cJSON_IsNumber,
361 cjson_value);
362}
363
376static int
377gvm_json_pull_parse_keyword (gvm_json_pull_parser_t *parser,
378 gvm_json_pull_event_t *event, const char *keyword)
379{
380 for (size_t i = 0; i < strlen (keyword); i++)
381 {
382 if (parser->last_read_char < 0)
383 {
384 gvm_json_pull_handle_read_end (parser, event, FALSE);
385 return 1;
386 }
387 else if (parser->last_read_char != keyword[i])
388 {
389 event->type = GVM_JSON_PULL_EVENT_ERROR;
390 event->error_message =
391 g_strdup_printf ("misspelled keyword '%s'", keyword);
392 return 1;
393 }
394 gvm_json_pull_parser_next_char (parser);
395 }
396 return 0;
397}
398
404static void
405parse_value_next_expect (gvm_json_pull_parser_t *parser)
406{
407 if (parser->path->length)
408 parser->expect = GVM_JSON_PULL_EXPECT_COMMA;
409 else
410 parser->expect = GVM_JSON_PULL_EXPECT_EOF;
411}
412
424static int
425gvm_json_pull_parse_key (gvm_json_pull_parser_t *parser,
426 gvm_json_pull_event_t *event)
427{
428 if (gvm_json_pull_skip_space (parser, event, FALSE))
429 return 1;
430
431 cJSON *key_cjson = NULL;
432 gchar *key_str;
433 gvm_json_path_elem_t *path_elem;
434
435 switch (parser->last_read_char)
436 {
437 case '"':
438 if (gvm_json_pull_parse_string (parser, event, &key_cjson))
439 return 1;
440 key_str = g_strdup (key_cjson->valuestring);
441 cJSON_Delete (key_cjson);
442
443 // Expect colon:
444 if (gvm_json_pull_skip_space (parser, event, FALSE))
445 {
446 g_free (key_str);
447 return 1;
448 }
449 if (parser->last_read_char != ':')
450 {
451 event->type = GVM_JSON_PULL_EVENT_ERROR;
452 event->error_message = g_strdup_printf ("expected colon");
453 g_free (key_str);
454 return 1;
455 }
456 gvm_json_pull_parser_next_char (parser);
457
458 path_elem = g_queue_peek_tail (parser->path);
459 g_free (path_elem->key);
460 path_elem->key = key_str;
461 parser->expect = GVM_JSON_PULL_EXPECT_VALUE;
462
463 break;
464 case '}':
465 event->type = GVM_JSON_PULL_EVENT_OBJECT_END;
466 event->value = NULL;
467 gvm_json_pull_path_elem_free (g_queue_pop_tail (parser->path));
468 parse_value_next_expect (parser);
469 gvm_json_pull_parser_next_char (parser);
470 break;
471 case ']':
472 event->type = GVM_JSON_PULL_EVENT_ERROR;
473 event->error_message = g_strdup ("unexpected closing square bracket");
474 return 1;
475 default:
476 event->type = GVM_JSON_PULL_EVENT_ERROR;
477 event->error_message = g_strdup ("unexpected character");
478 return 1;
479 }
480
481 return 0;
482}
483
495static int
496gvm_json_pull_parse_comma (gvm_json_pull_parser_t *parser,
497 gvm_json_pull_event_t *event)
498{
499 if (gvm_json_pull_skip_space (parser, event, FALSE))
500 return 1;
501
502 gvm_json_path_elem_t *path_elem = NULL;
503 switch (parser->last_read_char)
504 {
505 case ',':
506 path_elem = g_queue_peek_tail (parser->path);
507 path_elem->index++;
508 if (path_elem->parent_type == GVM_JSON_PULL_CONTAINER_OBJECT)
509 parser->expect = GVM_JSON_PULL_EXPECT_KEY;
510 else
511 parser->expect = GVM_JSON_PULL_EXPECT_VALUE;
512 gvm_json_pull_parser_next_char (parser);
513 break;
514 case ']':
515 path_elem = g_queue_peek_tail (parser->path);
516 if (path_elem == NULL
517 || path_elem->parent_type != GVM_JSON_PULL_CONTAINER_ARRAY)
518 {
519 event->type = GVM_JSON_PULL_EVENT_ERROR;
520 event->error_message = g_strdup ("unexpected closing square bracket");
521 return 1;
522 }
523 event->type = GVM_JSON_PULL_EVENT_ARRAY_END;
524 event->value = NULL;
525 gvm_json_pull_path_elem_free (g_queue_pop_tail (parser->path));
526 parse_value_next_expect (parser);
527 gvm_json_pull_parser_next_char (parser);
528 break;
529 case '}':
530 path_elem = g_queue_peek_tail (parser->path);
531 if (path_elem == NULL
532 || path_elem->parent_type != GVM_JSON_PULL_CONTAINER_OBJECT)
533 {
534 event->type = GVM_JSON_PULL_EVENT_ERROR;
535 event->error_message = g_strdup ("unexpected closing curly brace");
536 return 1;
537 }
538 event->type = GVM_JSON_PULL_EVENT_OBJECT_END;
539 event->value = NULL;
540 gvm_json_pull_path_elem_free (g_queue_pop_tail (parser->path));
541 parse_value_next_expect (parser);
542 gvm_json_pull_parser_next_char (parser);
543 break;
544 default:
545 event->error_message = g_strdup ("expected comma or end of container");
546 event->type = GVM_JSON_PULL_EVENT_ERROR;
547 return 1;
548 }
549 return 0;
550}
551
563static int
564gvm_json_pull_parse_value (gvm_json_pull_parser_t *parser,
565 gvm_json_pull_event_t *event)
566{
567 if (gvm_json_pull_skip_space (parser, event, FALSE))
568 return 1;
569
570 cJSON *cjson_value = NULL;
571 gvm_json_path_elem_t *path_elem = NULL;
572
573 switch (parser->last_read_char)
574 {
575 case '"':
576 if (gvm_json_pull_parse_string (parser, event, &cjson_value))
577 return 1;
578 event->type = GVM_JSON_PULL_EVENT_STRING;
579 event->value = cjson_value;
580 parse_value_next_expect (parser);
581 break;
582 case 'n':
583 if (gvm_json_pull_parse_keyword (parser, event, "null"))
584 return 1;
585 event->type = GVM_JSON_PULL_EVENT_NULL;
586 event->value = cJSON_CreateNull ();
587 parse_value_next_expect (parser);
588 break;
589 case 'f':
590 if (gvm_json_pull_parse_keyword (parser, event, "false"))
591 return 1;
592 event->type = GVM_JSON_PULL_EVENT_BOOLEAN;
593 event->value = cJSON_CreateFalse ();
594 parse_value_next_expect (parser);
595 break;
596 case 't':
597 if (gvm_json_pull_parse_keyword (parser, event, "true"))
598 return 1;
599 event->type = GVM_JSON_PULL_EVENT_BOOLEAN;
600 event->value = cJSON_CreateTrue ();
601 parse_value_next_expect (parser);
602 break;
603 case '[':
604 event->type = GVM_JSON_PULL_EVENT_ARRAY_START;
605 event->value = NULL;
606 parser->path_add = gvm_json_pull_path_elem_new (
607 GVM_JSON_PULL_CONTAINER_ARRAY, parser->path->length);
608 parser->expect = GVM_JSON_PULL_EXPECT_VALUE;
609 gvm_json_pull_parser_next_char (parser);
610 break;
611 case ']':
612 path_elem = g_queue_peek_tail (parser->path);
613 if (path_elem == NULL
614 || path_elem->parent_type != GVM_JSON_PULL_CONTAINER_ARRAY)
615 {
616 event->type = GVM_JSON_PULL_EVENT_ERROR;
617 event->error_message = g_strdup ("unexpected closing square bracket");
618 return 1;
619 }
620 event->type = GVM_JSON_PULL_EVENT_ARRAY_END;
621 event->value = NULL;
622 gvm_json_pull_path_elem_free (g_queue_pop_tail (parser->path));
623 parse_value_next_expect (parser);
624 gvm_json_pull_parser_next_char (parser);
625 break;
626 case '{':
627 event->type = GVM_JSON_PULL_EVENT_OBJECT_START;
628 event->value = NULL;
629 parser->path_add = gvm_json_pull_path_elem_new (
630 GVM_JSON_PULL_CONTAINER_OBJECT, parser->path->length);
631 parser->expect = GVM_JSON_PULL_EXPECT_KEY;
632 gvm_json_pull_parser_next_char (parser);
633 break;
634 case '}':
635 event->type = GVM_JSON_PULL_EVENT_ERROR;
636 event->error_message = g_strdup ("unexpected closing curly brace");
637 return 1;
638 break;
639 default:
640 if (g_ascii_isdigit (parser->last_read_char)
641 || parser->last_read_char == '-')
642 {
643 if (gvm_json_pull_parse_number (parser, event, &cjson_value))
644 return 1;
645 event->type = GVM_JSON_PULL_EVENT_NUMBER;
646 event->value = cjson_value;
647 parse_value_next_expect (parser);
648 }
649 else
650 {
651 event->type = GVM_JSON_PULL_EVENT_ERROR;
652 event->error_message = g_strdup ("unexpected character");
653 return 1;
654 }
655 }
656 return 0;
657}
658
667void
668gvm_json_pull_parser_next (gvm_json_pull_parser_t *parser,
669 gvm_json_pull_event_t *event)
670{
671 assert (parser);
672 assert (event);
673
674 gvm_json_pull_event_cleanup (event);
675 if (parser->last_read_char == GVM_JSON_CHAR_UNDEFINED)
676 {
677 // Handle first read of the stream
678 if (gvm_json_pull_parser_next_char (parser) < 0)
679 {
680 gvm_json_pull_handle_read_end (parser, event, TRUE);
681 return;
682 }
683 }
684
685 event->path = parser->path;
686
687 // Delayed addition to path after a container start element
688 if (parser->path_add)
689 {
690 g_queue_push_tail (parser->path, parser->path_add);
691 parser->path_add = NULL;
692 }
693
694 // Check for expected end of file
695 if (parser->expect == GVM_JSON_PULL_EXPECT_EOF)
696 {
697 if (gvm_json_pull_skip_space (parser, event, TRUE))
698 {
699 // EOF was reached, or an error occurred.
700 // The event type is already set, and if an error occurred, then
701 // error_message is also already set.
702 return;
703 }
704
705 // Skipping space succeeded. Check for unexpected characters at EOF.
706
707 if (parser->last_read_char == GVM_JSON_CHAR_EOF)
708 return;
709
710 event->type = GVM_JSON_PULL_EVENT_ERROR;
711 event->error_message = g_strdup_printf (
712 "unexpected character at end of file (%d)", parser->last_read_char);
713 return;
714 }
715
716 if (parser->expect == GVM_JSON_PULL_EXPECT_COMMA)
717 {
718 if (gvm_json_pull_parse_comma (parser, event))
719 return;
720 }
721
722 if (parser->expect == GVM_JSON_PULL_EXPECT_KEY)
723 {
724 if (gvm_json_pull_parse_key (parser, event))
725 return;
726 }
727
728 if (parser->expect == GVM_JSON_PULL_EXPECT_VALUE)
729 {
730 gvm_json_pull_parse_value (parser, event);
731 }
732}
733
744cJSON *
745gvm_json_pull_expand_container (gvm_json_pull_parser_t *parser,
746 gchar **error_message)
747{
748 gvm_json_path_elem_t *path_tail = NULL;
749
750 int start_depth;
751 gboolean in_string, escape_next_char, in_expanded_container;
752 cJSON *expanded;
753
754 g_string_truncate (parser->parse_buffer, 0);
755
756 if (error_message)
757 *error_message = NULL;
758
759 // require "path_add" to only allow expansion at start of container
760 if (parser->path_add)
761 {
762 path_tail = parser->path_add;
763 g_queue_push_tail (parser->path, path_tail);
764 parser->path_add = NULL;
765 }
766
767 if (path_tail && path_tail->parent_type == GVM_JSON_PULL_CONTAINER_ARRAY)
768 g_string_append_c (parser->parse_buffer, '[');
769 else if (path_tail
770 && path_tail->parent_type == GVM_JSON_PULL_CONTAINER_OBJECT)
771 g_string_append_c (parser->parse_buffer, '{');
772 else
773 {
774 if (error_message)
775 *error_message =
776 g_strdup ("can only expand after array or object start");
777 return NULL;
778 }
779
780 start_depth = path_tail->depth;
781 in_string = escape_next_char = FALSE;
782 in_expanded_container = TRUE;
783
784 while (parser->last_read_char >= 0 && in_expanded_container)
785 {
786 if (parser->parse_buffer->len >= parser->parse_buffer_limit)
787 {
788 if (error_message)
789 *error_message =
790 g_strdup_printf ("container exceeds size limit of %zu bytes",
791 parser->parse_buffer_limit);
792 return NULL;
793 }
794
795 g_string_append_c (parser->parse_buffer, parser->last_read_char);
796
797 if (escape_next_char)
798 {
799 escape_next_char = FALSE;
800 }
801 else if (in_string)
802 {
803 escape_next_char = (parser->last_read_char == '\\');
804 in_string = (parser->last_read_char != '"');
805 }
806 else
807 {
808 switch (parser->last_read_char)
809 {
810 case '"':
811 in_string = TRUE;
812 break;
813 case '[':
814 path_tail = gvm_json_pull_path_elem_new (
815 GVM_JSON_PULL_CONTAINER_ARRAY, parser->path->length);
816 g_queue_push_tail (parser->path, path_tail);
817 break;
818 case '{':
819 path_tail = gvm_json_pull_path_elem_new (
820 GVM_JSON_PULL_CONTAINER_OBJECT, parser->path->length);
821 g_queue_push_tail (parser->path, path_tail);
822 break;
823 case ']':
824 path_tail = g_queue_pop_tail (parser->path);
825 if (path_tail->parent_type != GVM_JSON_PULL_CONTAINER_ARRAY)
826 {
827 if (error_message)
828 *error_message =
829 g_strdup ("unexpected closing square bracket");
830 gvm_json_pull_path_elem_free (path_tail);
831 return NULL;
832 }
833 if (path_tail->depth == start_depth)
834 in_expanded_container = FALSE;
835
836 gvm_json_pull_path_elem_free (path_tail);
837 break;
838 case '}':
839 path_tail = g_queue_pop_tail (parser->path);
840 if (path_tail->parent_type != GVM_JSON_PULL_CONTAINER_OBJECT)
841 {
842 if (error_message)
843 *error_message =
844 g_strdup ("unexpected closing curly brace");
845 gvm_json_pull_path_elem_free (path_tail);
846 return NULL;
847 }
848 if (path_tail->depth == start_depth)
849 in_expanded_container = FALSE;
850
851 gvm_json_pull_path_elem_free (path_tail);
852 break;
853 }
854 }
855 gvm_json_pull_parser_next_char (parser);
856 }
857
858 if (parser->last_read_char == GVM_JSON_CHAR_ERROR)
859 {
860 if (error_message)
861 *error_message = gvm_json_read_stream_error_str ();
862 return NULL;
863 }
864 else if (in_expanded_container && parser->last_read_char == GVM_JSON_CHAR_EOF)
865 {
866 if (error_message)
867 *error_message = g_strdup ("unexpected EOF");
868 return NULL;
869 }
870
871 expanded = cJSON_Parse (parser->parse_buffer->str);
872 g_string_truncate (parser->parse_buffer, 0);
873 parse_value_next_expect (parser);
874
875 if (expanded == NULL && error_message)
876 *error_message = g_strdup ("could not parse expanded container");
877
878 return expanded;
879}
880
887static void
888gvm_json_path_string_add_elem (gvm_json_path_elem_t *path_elem,
889 GString *path_string)
890{
891 if (path_elem->parent_type == GVM_JSON_PULL_CONTAINER_OBJECT)
892 {
893 gchar *escaped_key = gvm_json_string_escape (path_elem->key, TRUE);
894 g_string_append_printf (path_string, "['%s']", escaped_key);
895 g_free (escaped_key);
896 }
897 else
898 g_string_append_printf (path_string, "[%d]", path_elem->index);
899}
900
908gchar *
909gvm_json_path_to_string (GQueue *path)
910{
911 GString *path_string = g_string_new ("$");
912 g_queue_foreach (path, (GFunc) gvm_json_path_string_add_elem, path_string);
913 return g_string_free (path_string, FALSE);
914}
gvm_json_string_escape
gchar * gvm_json_string_escape(const char *string, gboolean single_quote)
Escapes a string according to the JSON or JSONPath standard.
Definition json.c:17
gvm_json_pull_parse_number
static int gvm_json_pull_parse_number(gvm_json_pull_parser_t *parser, gvm_json_pull_event_t *event, cJSON **cjson_value)
Parses a number in a JSON pull parser.
Definition jsonpull.c:336
gvm_json_pull_parser_cleanup
void gvm_json_pull_parser_cleanup(gvm_json_pull_parser_t *parser)
Frees the data of a JSON pull parser.
Definition jsonpull.c:119
gvm_json_pull_parser_init_full
void gvm_json_pull_parser_init_full(gvm_json_pull_parser_t *parser, FILE *input_stream, size_t parse_buffer_limit, size_t read_buffer_size)
Initializes a JSON pull parser.
Definition jsonpull.c:77
gvm_json_pull_parse_string
static int gvm_json_pull_parse_string(gvm_json_pull_parser_t *parser, gvm_json_pull_event_t *event, cJSON **cjson_value)
Parses a string in a JSON pull parser.
Definition jsonpull.c:292
gvm_json_pull_skip_space
static int gvm_json_pull_skip_space(gvm_json_pull_parser_t *parser, gvm_json_pull_event_t *event, gboolean allow_eof)
Skips whitespaces in the input stream of a JSON pull parser.
Definition jsonpull.c:266
gvm_json_pull_parse_comma
static int gvm_json_pull_parse_comma(gvm_json_pull_parser_t *parser, gvm_json_pull_event_t *event)
Handles the case that a comma is expected in a JSON pull parser.
Definition jsonpull.c:496
gvm_json_pull_parser_next_char
static int gvm_json_pull_parser_next_char(gvm_json_pull_parser_t *parser)
Reads the next character in a pull parser input stream.
Definition jsonpull.c:173
gvm_json_pull_event_cleanup
void gvm_json_pull_event_cleanup(gvm_json_pull_event_t *event)
Frees all data of JSON pull event data structure.
Definition jsonpull.c:61
gvm_json_pull_parse_value
static int gvm_json_pull_parse_value(gvm_json_pull_parser_t *parser, gvm_json_pull_event_t *event)
Handles the case that a value is expected in a JSON pull parser.
Definition jsonpull.c:564
gvm_json_pull_parser_next
void gvm_json_pull_parser_next(gvm_json_pull_parser_t *parser, gvm_json_pull_event_t *event)
Get the next event from a JSON pull parser.
Definition jsonpull.c:668
GVM_JSON_CHAR_UNDEFINED
#define GVM_JSON_CHAR_UNDEFINED
Undefined state.
Definition jsonpull.c:12
gvm_json_pull_parser_init
void gvm_json_pull_parser_init(gvm_json_pull_parser_t *parser, FILE *input_stream)
Initializes a JSON pull parser with default buffer sizes.
Definition jsonpull.c:108
gvm_json_pull_parse_key
static int gvm_json_pull_parse_key(gvm_json_pull_parser_t *parser, gvm_json_pull_event_t *event)
Handles the case that an object key is expected in a JSON pull parser.
Definition jsonpull.c:425
gvm_json_pull_handle_read_end
static void gvm_json_pull_handle_read_end(gvm_json_pull_parser_t *parser, gvm_json_pull_event_t *event, gboolean allow_eof)
Handles error or EOF after reading a character in JSON pull parser.
Definition jsonpull.c:237
gvm_json_path_to_string
gchar * gvm_json_path_to_string(GQueue *path)
Converts a path as used by a JSON pull parser to a JSONPath string.
Definition jsonpull.c:909
GVM_JSON_CHAR_ERROR
#define GVM_JSON_CHAR_ERROR
Error reading file.
Definition jsonpull.c:11
gvm_json_pull_expand_container
cJSON * gvm_json_pull_expand_container(gvm_json_pull_parser_t *parser, gchar **error_message)
Expands the current array or object of a JSON pull parser.
Definition jsonpull.c:745
gvm_json_pull_parse_keyword
static int gvm_json_pull_parse_keyword(gvm_json_pull_parser_t *parser, gvm_json_pull_event_t *event, const char *keyword)
Parses a keyword value in a JSON pull parser.
Definition jsonpull.c:377
gvm_json_path_string_add_elem
static void gvm_json_path_string_add_elem(gvm_json_path_elem_t *path_elem, GString *path_string)
Appends a string path element to a JSONPath string.
Definition jsonpull.c:888
gvm_json_pull_parse_buffered
static int gvm_json_pull_parse_buffered(gvm_json_pull_parser_t *parser, gvm_json_pull_event_t *event, const char *value_name, cJSON_bool(*validate_func)(const cJSON *const), cJSON **cjson_value)
Tries to parse the buffer content of a JSON pull parser.
Definition jsonpull.c:210
parse_value_next_expect
static void parse_value_next_expect(gvm_json_pull_parser_t *parser)
Updates the expectation for a JSON pull parser according to the path.
Definition jsonpull.c:405
GVM_JSON_CHAR_EOF
#define GVM_JSON_CHAR_EOF
End of file.
Definition jsonpull.c:10
gvm_json_pull_check_parse_buffer_size
static int gvm_json_pull_check_parse_buffer_size(const char *value_type, gvm_json_pull_parser_t *parser, gvm_json_pull_event_t *event)
Checks if the parse buffer limit of a JSON pull parser is reached.
Definition jsonpull.c:150
gvm_json_pull_path_elem_free
void gvm_json_pull_path_elem_free(gvm_json_path_elem_t *elem)
Frees a JSON path element.
Definition jsonpull.c:38
gvm_json_pull_path_elem_new
gvm_json_path_elem_t * gvm_json_pull_path_elem_new(gvm_json_pull_container_type_t parent_type, int depth)
Creates a new JSON path element.
Definition jsonpull.c:23
gvm_json_pull_event_init
void gvm_json_pull_event_init(gvm_json_pull_event_t *event)
Initializes a JSON pull event data structure.
Definition jsonpull.c:50
gvm_json_read_stream_error_str
static gchar * gvm_json_read_stream_error_str()
Generates message for an error that occurred reading the JSON stream.
Definition jsonpull.c:135
jsonpull.h
GVM_JSON_PULL_READ_BUFFER_SIZE
#define GVM_JSON_PULL_READ_BUFFER_SIZE
Definition jsonpull.h:80
GVM_JSON_PULL_PARSE_BUFFER_LIMIT
#define GVM_JSON_PULL_PARSE_BUFFER_LIMIT
Definition jsonpull.h:78
gvm_json_pull_container_type_t
gvm_json_pull_container_type_t
Type of container the parser is currently in.
Definition jsonpull.h:20
GVM_JSON_PULL_CONTAINER_OBJECT
@ GVM_JSON_PULL_CONTAINER_OBJECT
Object.
Definition jsonpull.h:23
GVM_JSON_PULL_CONTAINER_ARRAY
@ GVM_JSON_PULL_CONTAINER_ARRAY
Array.
Definition jsonpull.h:22
GVM_JSON_PULL_EXPECT_VALUE
@ GVM_JSON_PULL_EXPECT_VALUE
Expect start of a value.
Definition jsonpull.h:72
GVM_JSON_PULL_EXPECT_KEY
@ GVM_JSON_PULL_EXPECT_KEY
Expect start of a key.
Definition jsonpull.h:73
GVM_JSON_PULL_EXPECT_EOF
@ GVM_JSON_PULL_EXPECT_EOF
Expect end of file.
Definition jsonpull.h:75
GVM_JSON_PULL_EXPECT_COMMA
@ GVM_JSON_PULL_EXPECT_COMMA
Expect comma or container end brace.
Definition jsonpull.h:74
GVM_JSON_PULL_EVENT_STRING
@ GVM_JSON_PULL_EVENT_STRING
Definition jsonpull.h:47
GVM_JSON_PULL_EVENT_OBJECT_START
@ GVM_JSON_PULL_EVENT_OBJECT_START
Definition jsonpull.h:45
GVM_JSON_PULL_EVENT_ERROR
@ GVM_JSON_PULL_EVENT_ERROR
Definition jsonpull.h:52
GVM_JSON_PULL_EVENT_NULL
@ GVM_JSON_PULL_EVENT_NULL
Definition jsonpull.h:50
GVM_JSON_PULL_EVENT_EOF
@ GVM_JSON_PULL_EVENT_EOF
Definition jsonpull.h:51
GVM_JSON_PULL_EVENT_NUMBER
@ GVM_JSON_PULL_EVENT_NUMBER
Definition jsonpull.h:48
GVM_JSON_PULL_EVENT_ARRAY_END
@ GVM_JSON_PULL_EVENT_ARRAY_END
Definition jsonpull.h:44
GVM_JSON_PULL_EVENT_OBJECT_END
@ GVM_JSON_PULL_EVENT_OBJECT_END
Definition jsonpull.h:46
GVM_JSON_PULL_EVENT_ARRAY_START
@ GVM_JSON_PULL_EVENT_ARRAY_START
Definition jsonpull.h:43
GVM_JSON_PULL_EVENT_BOOLEAN
@ GVM_JSON_PULL_EVENT_BOOLEAN
Definition jsonpull.h:49
gvm_json_path_elem_t
struct gvm_json_path_elem gvm_json_path_elem_t
Path element types for the JSON pull parser.
gvm_json_path_elem::depth
int depth
Number of ancestor elements.
Definition jsonpull.h:34
gvm_json_path_elem::index
int index
Index of the element within the parent.
Definition jsonpull.h:32
gvm_json_path_elem::key
char * key
Key if element is in an object.
Definition jsonpull.h:33
gvm_json_path_elem::parent_type
gvm_json_pull_container_type_t parent_type
parent container type
Definition jsonpull.h:31
gvm_json_pull_event_t
Event generated by the JSON pull parser.
Definition jsonpull.h:59
gvm_json_pull_event_t::error_message
gchar * error_message
Error message, NULL on success.
Definition jsonpull.h:63
gvm_json_pull_event_t::value
cJSON * value
Value for non-container value events.
Definition jsonpull.h:62
gvm_json_pull_parser_t
A json pull parser.
Definition jsonpull.h:86
gvm_json_pull_parser_t::read_buffer
char * read_buffer
Stream reading buffer.
Definition jsonpull.h:92
gvm_json_pull_parser_t::read_buffer_size
size_t read_buffer_size
Size of the stream reading buffer.
Definition jsonpull.h:93
gvm_json_pull_parser_t::expect
gvm_json_pull_expect_t expect
Current expected token.
Definition jsonpull.h:89
gvm_json_pull_parser_t::last_read_size
size_t last_read_size
Size of last stream read.
Definition jsonpull.h:94
gvm_json_pull_parser_t::parse_buffer
GString * parse_buffer
Buffer for parsing values and object keys.
Definition jsonpull.h:97
gvm_json_pull_parser_t::parse_buffer_limit
size_t parse_buffer_limit
Maximum parse buffer size.
Definition jsonpull.h:98
gvm_json_pull_parser_t::path_add
gvm_json_path_elem_t * path_add
Path elem to add in next step.
Definition jsonpull.h:88
gvm_json_pull_parser_t::read_pos
size_t read_pos
Position in current read.
Definition jsonpull.h:96
gvm_json_pull_parser_t::path
GQueue * path
Path to the current value.
Definition jsonpull.h:87
gvm_json_pull_parser_t::last_read_char
int last_read_char
Character last read from stream.
Definition jsonpull.h:95
gvm_json_pull_parser_t::input_stream
FILE * input_stream
Input stream.
Definition jsonpull.h:91