Install json_object_private.h file
[platform/upstream/json-c.git] / json_visit.c
1 /*
2  * Copyright (c) 2016 Eric Haszlakiewicz
3  *
4  * This is free software; you can redistribute it and/or modify
5  * it under the terms of the MIT license. See COPYING for details.
6  */
7
8 #include <stdio.h>
9
10 #include "config.h"
11 #include "json_inttypes.h"
12 #include "json_object.h"
13 #include "json_visit.h"
14 #include "linkhash.h"
15
16 static int _json_c_visit(json_object *jso, json_object *parent_jso,
17                          const char *jso_key, size_t *jso_index,
18                          json_c_visit_userfunc *userfunc, void *userarg);
19
20 int json_c_visit(json_object *jso, int future_flags,
21                  json_c_visit_userfunc *userfunc, void *userarg)
22 {
23         int ret = _json_c_visit(jso, NULL, NULL, NULL, userfunc, userarg);
24         switch(ret)
25         {
26         case JSON_C_VISIT_RETURN_CONTINUE:
27         case JSON_C_VISIT_RETURN_SKIP:
28         case JSON_C_VISIT_RETURN_POP:
29         case JSON_C_VISIT_RETURN_STOP:
30                 return 0;
31         default:
32                 return JSON_C_VISIT_RETURN_ERROR;
33         }
34 }
35 static int _json_c_visit(json_object *jso, json_object *parent_jso,
36                          const char *jso_key, size_t *jso_index,
37                          json_c_visit_userfunc *userfunc, void *userarg)
38 {
39         int userret = userfunc(jso, 0, parent_jso, jso_key, jso_index, userarg);
40         switch(userret)
41         {
42         case JSON_C_VISIT_RETURN_CONTINUE:
43                 break;
44         case JSON_C_VISIT_RETURN_SKIP:
45         case JSON_C_VISIT_RETURN_POP:
46         case JSON_C_VISIT_RETURN_STOP:
47         case JSON_C_VISIT_RETURN_ERROR:
48                 return userret;
49         default:
50                 fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n", userret);
51                 return JSON_C_VISIT_RETURN_ERROR;
52         }
53
54         switch(json_object_get_type(jso))
55         {
56         case json_type_null:
57         case json_type_boolean:
58         case json_type_double:
59         case json_type_int:
60         case json_type_string:
61                 // we already called userfunc above, move on to the next object
62                 return JSON_C_VISIT_RETURN_CONTINUE;
63
64         case json_type_object:
65         {
66                 json_object_object_foreach(jso, key, child)
67                 {
68                         userret = _json_c_visit(child, jso, key, NULL, userfunc, userarg);
69                         if (userret == JSON_C_VISIT_RETURN_POP)
70                                 break;
71                         if (userret == JSON_C_VISIT_RETURN_STOP ||
72                                 userret == JSON_C_VISIT_RETURN_ERROR)
73                                 return userret;
74                         if (userret != JSON_C_VISIT_RETURN_CONTINUE &&
75                                 userret != JSON_C_VISIT_RETURN_SKIP)
76                         {
77                                 fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n", userret);
78                                 return JSON_C_VISIT_RETURN_ERROR;
79                         }
80                 }
81                 break;
82         }
83         case json_type_array:
84         {
85                 size_t array_len = json_object_array_length(jso);
86                 size_t ii;
87                 for (ii = 0; ii < array_len; ii++)
88                 {
89                         json_object *child = json_object_array_get_idx(jso, ii);
90                         userret = _json_c_visit(child, jso, NULL, &ii, userfunc, userarg);
91                         if (userret == JSON_C_VISIT_RETURN_POP)
92                                 break;
93                         if (userret == JSON_C_VISIT_RETURN_STOP ||
94                                 userret == JSON_C_VISIT_RETURN_ERROR)
95                                 return userret;
96                         if (userret != JSON_C_VISIT_RETURN_CONTINUE &&
97                                 userret != JSON_C_VISIT_RETURN_SKIP)
98                         {
99                                 fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n", userret);
100                                 return JSON_C_VISIT_RETURN_ERROR;
101                         }
102                 }
103                 break;
104         }
105         default:
106                 fprintf(stderr, "INTERNAL ERROR: _json_c_visit found object of unknown type: %d\n", json_object_get_type(jso));
107                 return JSON_C_VISIT_RETURN_ERROR;
108         }
109
110         // Call userfunc for the second type on container types, after all
111         //  members of the container have been visited.
112         // Non-container types will have already returned before this point.
113
114         userret = userfunc(jso, JSON_C_VISIT_SECOND, parent_jso, jso_key, jso_index, userarg);
115         switch(userret)
116         {
117         case JSON_C_VISIT_RETURN_SKIP:
118         case JSON_C_VISIT_RETURN_POP:
119                 // These are not really sensible during JSON_C_VISIT_SECOND, 
120                 // but map them to JSON_C_VISIT_CONTINUE anyway.
121                 // FALLTHROUGH
122         case JSON_C_VISIT_RETURN_CONTINUE:
123                 return JSON_C_VISIT_RETURN_CONTINUE;
124         case JSON_C_VISIT_RETURN_STOP:
125         case JSON_C_VISIT_RETURN_ERROR:
126                 return userret;
127         default:
128                 fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n", userret);
129                 return JSON_C_VISIT_RETURN_ERROR;
130         }
131         // NOTREACHED
132 }
133