diff options
Diffstat (limited to 'src/json')
-rw-r--r-- | src/json/Makefile.am | 12 | ||||
-rw-r--r-- | src/json/json.c | 37 | ||||
-rw-r--r-- | src/json/json_pack.c | 325 |
3 files changed, 333 insertions, 41 deletions
diff --git a/src/json/Makefile.am b/src/json/Makefile.am index d4ea38adf..2e97cecb9 100644 --- a/src/json/Makefile.am +++ b/src/json/Makefile.am | |||
@@ -13,21 +13,21 @@ libgnunetjson_la_LDFLAGS = \ | |||
13 | $(GN_LIBINTL) \ | 13 | $(GN_LIBINTL) \ |
14 | -version-info 0:0:0 \ | 14 | -version-info 0:0:0 \ |
15 | -no-undefined | 15 | -no-undefined |
16 | libgnunetjson_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS) | 16 | libgnunetjson_la_CFLAGS = \ |
17 | $(MHD_CFLAGS) \ | ||
18 | $(AM_CFLAGS) | ||
17 | libgnunetjson_la_SOURCES = \ | 19 | libgnunetjson_la_SOURCES = \ |
18 | json.c \ | 20 | json.c \ |
19 | json_mhd.c \ | ||
20 | json_generator.c \ | 21 | json_generator.c \ |
21 | json_helper.c | 22 | json_helper.c \ |
23 | json_mhd.c \ | ||
24 | json_pack.c | ||
22 | libgnunetjson_la_LIBADD = \ | 25 | libgnunetjson_la_LIBADD = \ |
23 | $(top_builddir)/src/util/libgnunetutil.la \ | 26 | $(top_builddir)/src/util/libgnunetutil.la \ |
24 | -ljansson \ | 27 | -ljansson \ |
25 | $(MHD_LIBS) \ | 28 | $(MHD_LIBS) \ |
26 | $(XLIB) \ | 29 | $(XLIB) \ |
27 | $(Z_LIBS) | 30 | $(Z_LIBS) |
28 | libgnunetjson_la_DEPENDENCIES = \ | ||
29 | $(top_builddir)/src/util/libgnunetutil.la | ||
30 | |||
31 | 31 | ||
32 | check_PROGRAMS = \ | 32 | check_PROGRAMS = \ |
33 | test_json \ | 33 | test_json \ |
diff --git a/src/json/json.c b/src/json/json.c index d55189804..51d5c0c72 100644 --- a/src/json/json.c +++ b/src/json/json.c | |||
@@ -28,19 +28,6 @@ | |||
28 | #include "gnunet_json_lib.h" | 28 | #include "gnunet_json_lib.h" |
29 | 29 | ||
30 | 30 | ||
31 | /** | ||
32 | * Navigate and parse data in a JSON tree. Tries to parse the @a root | ||
33 | * to find all of the values given in the @a spec. If one of the | ||
34 | * entries in @a spec cannot be found or parsed, the name of the JSON | ||
35 | * field is returned in @a error_json_name, and the offset of the | ||
36 | * entry in @a spec is returned in @a error_line. | ||
37 | * | ||
38 | * @param root the JSON node to start the navigation at. | ||
39 | * @param spec parse specification array | ||
40 | * @param[out] error_json_name which JSON field was problematic | ||
41 | * @param[out] which index into @a spec did we encounter an error | ||
42 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
43 | */ | ||
44 | enum GNUNET_GenericReturnValue | 31 | enum GNUNET_GenericReturnValue |
45 | GNUNET_JSON_parse (const json_t *root, | 32 | GNUNET_JSON_parse (const json_t *root, |
46 | struct GNUNET_JSON_Specification *spec, | 33 | struct GNUNET_JSON_Specification *spec, |
@@ -85,12 +72,6 @@ GNUNET_JSON_parse (const json_t *root, | |||
85 | } | 72 | } |
86 | 73 | ||
87 | 74 | ||
88 | /** | ||
89 | * Set the "optional" flag for a parser specification entry. | ||
90 | * | ||
91 | * @param spec specification to modify | ||
92 | * @return spec copy of @a spec with optional bit set | ||
93 | */ | ||
94 | struct GNUNET_JSON_Specification | 75 | struct GNUNET_JSON_Specification |
95 | GNUNET_JSON_spec_mark_optional (struct GNUNET_JSON_Specification spec) | 76 | GNUNET_JSON_spec_mark_optional (struct GNUNET_JSON_Specification spec) |
96 | { | 77 | { |
@@ -101,18 +82,13 @@ GNUNET_JSON_spec_mark_optional (struct GNUNET_JSON_Specification spec) | |||
101 | } | 82 | } |
102 | 83 | ||
103 | 84 | ||
104 | /** | ||
105 | * Frees all elements allocated during a #GNUNET_JSON_parse() | ||
106 | * operation. | ||
107 | * | ||
108 | * @param spec specification of the parse operation | ||
109 | */ | ||
110 | void | 85 | void |
111 | GNUNET_JSON_parse_free (struct GNUNET_JSON_Specification *spec) | 86 | GNUNET_JSON_parse_free (struct GNUNET_JSON_Specification *spec) |
112 | { | 87 | { |
113 | for (unsigned int i = 0; NULL != spec[i].parser; i++) | 88 | for (unsigned int i = 0; NULL != spec[i].parser; i++) |
114 | if (NULL != spec[i].cleaner) | 89 | if (NULL != spec[i].cleaner) |
115 | spec[i].cleaner (spec[i].cls, &spec[i]); | 90 | spec[i].cleaner (spec[i].cls, |
91 | &spec[i]); | ||
116 | } | 92 | } |
117 | 93 | ||
118 | 94 | ||
@@ -151,15 +127,6 @@ set_json (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, | |||
151 | } | 127 | } |
152 | 128 | ||
153 | 129 | ||
154 | /** | ||
155 | * Allow user to specify a JSON input value. | ||
156 | * | ||
157 | * @param shortName short name of the option | ||
158 | * @param name long name of the option | ||
159 | * @param argumentHelp help text for the option argument | ||
160 | * @param description long help text for the option | ||
161 | * @param[out] val set to the JSON specified at the command line | ||
162 | */ | ||
163 | struct GNUNET_GETOPT_CommandLineOption | 130 | struct GNUNET_GETOPT_CommandLineOption |
164 | GNUNET_JSON_getopt (char shortName, | 131 | GNUNET_JSON_getopt (char shortName, |
165 | const char *name, | 132 | const char *name, |
diff --git a/src/json/json_pack.c b/src/json/json_pack.c new file mode 100644 index 000000000..92f8b4535 --- /dev/null +++ b/src/json/json_pack.c | |||
@@ -0,0 +1,325 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2021 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file json/json_pack.c | ||
22 | * @brief functions to pack JSON objects | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_json_lib.h" | ||
27 | |||
28 | |||
29 | json_t * | ||
30 | GNUNET_JSON_pack_ (struct GNUNET_JSON_PackSpec spec[]) | ||
31 | { | ||
32 | json_t *ret; | ||
33 | |||
34 | ret = json_object (); | ||
35 | GNUNET_assert (NULL != ret); | ||
36 | for (unsigned int i = 0; | ||
37 | NULL != spec[i].field_name; | ||
38 | i++) | ||
39 | { | ||
40 | if (NULL == spec[i].object) | ||
41 | { | ||
42 | GNUNET_assert (spec[i].allow_null); | ||
43 | } | ||
44 | else | ||
45 | { | ||
46 | GNUNET_assert (0 == | ||
47 | json_object_set_new (ret, | ||
48 | spec[i].field_name, | ||
49 | spec[i].object)); | ||
50 | spec[i].object = NULL; | ||
51 | } | ||
52 | } | ||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | |||
57 | struct GNUNET_JSON_PackSpec | ||
58 | GNUNET_JSON_pack_end_ (void) | ||
59 | { | ||
60 | struct GNUNET_JSON_PackSpec ps = { | ||
61 | .field_name = NULL | ||
62 | }; | ||
63 | |||
64 | return ps; | ||
65 | } | ||
66 | |||
67 | |||
68 | struct GNUNET_JSON_PackSpec | ||
69 | GNUNET_JSON_pack_allow_null (struct GNUNET_JSON_PackSpec in) | ||
70 | { | ||
71 | in.allow_null = true; | ||
72 | return in; | ||
73 | } | ||
74 | |||
75 | |||
76 | struct GNUNET_JSON_PackSpec | ||
77 | GNUNET_JSON_pack_bool (const char *name, | ||
78 | bool b) | ||
79 | { | ||
80 | struct GNUNET_JSON_PackSpec ps = { | ||
81 | .field_name = name, | ||
82 | .object = json_boolean (b) | ||
83 | }; | ||
84 | |||
85 | return ps; | ||
86 | } | ||
87 | |||
88 | |||
89 | struct GNUNET_JSON_PackSpec | ||
90 | GNUNET_JSON_pack_string (const char *name, | ||
91 | const char *s) | ||
92 | { | ||
93 | struct GNUNET_JSON_PackSpec ps = { | ||
94 | .field_name = name, | ||
95 | .object = json_string (s) | ||
96 | }; | ||
97 | |||
98 | return ps; | ||
99 | } | ||
100 | |||
101 | |||
102 | struct GNUNET_JSON_PackSpec | ||
103 | GNUNET_JSON_pack_uint64 (const char *name, | ||
104 | uint64_t num) | ||
105 | { | ||
106 | struct GNUNET_JSON_PackSpec ps = { | ||
107 | .field_name = name, | ||
108 | .object = json_integer ((json_int_t) num) | ||
109 | }; | ||
110 | |||
111 | #if JSON_INTEGER_IS_LONG_LONG | ||
112 | GNUNET_assert (num <= LLONG_MAX); | ||
113 | #else | ||
114 | GNUNET_assert (num <= LONG_MAX); | ||
115 | #endif | ||
116 | return ps; | ||
117 | } | ||
118 | |||
119 | |||
120 | struct GNUNET_JSON_PackSpec | ||
121 | GNUNET_JSON_pack_int64 (const char *name, | ||
122 | int64_t num) | ||
123 | { | ||
124 | struct GNUNET_JSON_PackSpec ps = { | ||
125 | .field_name = name, | ||
126 | .object = json_integer ((json_int_t) num) | ||
127 | }; | ||
128 | |||
129 | #if JSON_INTEGER_IS_LONG_LONG | ||
130 | GNUNET_assert (num <= LLONG_MAX); | ||
131 | GNUNET_assert (num >= LLONG_MIN); | ||
132 | #else | ||
133 | GNUNET_assert (num <= LONG_MAX); | ||
134 | GNUNET_assert (num >= LONG_MIN); | ||
135 | #endif | ||
136 | return ps; | ||
137 | } | ||
138 | |||
139 | |||
140 | struct GNUNET_JSON_PackSpec | ||
141 | GNUNET_JSON_pack_object_steal (const char *name, | ||
142 | json_t *o) | ||
143 | { | ||
144 | struct GNUNET_JSON_PackSpec ps = { | ||
145 | .field_name = name, | ||
146 | .object = o | ||
147 | }; | ||
148 | |||
149 | if (NULL == o) | ||
150 | return ps; | ||
151 | if (! json_is_object (o)) | ||
152 | { | ||
153 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
154 | "Expected JSON object for field `%s'\n", | ||
155 | name); | ||
156 | GNUNET_assert (0); | ||
157 | } | ||
158 | return ps; | ||
159 | } | ||
160 | |||
161 | |||
162 | struct GNUNET_JSON_PackSpec | ||
163 | GNUNET_JSON_pack_object_incref (const char *name, | ||
164 | json_t *o) | ||
165 | { | ||
166 | struct GNUNET_JSON_PackSpec ps = { | ||
167 | .field_name = name, | ||
168 | .object = o | ||
169 | }; | ||
170 | |||
171 | if (NULL == o) | ||
172 | return ps; | ||
173 | (void) json_incref (o); | ||
174 | if (! json_is_object (o)) | ||
175 | { | ||
176 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
177 | "Expected JSON object for field `%s'\n", | ||
178 | name); | ||
179 | GNUNET_assert (0); | ||
180 | } | ||
181 | return ps; | ||
182 | } | ||
183 | |||
184 | |||
185 | struct GNUNET_JSON_PackSpec | ||
186 | GNUNET_JSON_pack_array_steal (const char *name, | ||
187 | json_t *a) | ||
188 | { | ||
189 | struct GNUNET_JSON_PackSpec ps = { | ||
190 | .field_name = name, | ||
191 | .object = a | ||
192 | }; | ||
193 | |||
194 | if (NULL == a) | ||
195 | return ps; | ||
196 | if (! json_is_array (a)) | ||
197 | { | ||
198 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
199 | "Expected JSON array for field `%s'\n", | ||
200 | name); | ||
201 | GNUNET_assert (0); | ||
202 | } | ||
203 | return ps; | ||
204 | } | ||
205 | |||
206 | |||
207 | struct GNUNET_JSON_PackSpec | ||
208 | GNUNET_JSON_pack_array_incref (const char *name, | ||
209 | json_t *a) | ||
210 | { | ||
211 | struct GNUNET_JSON_PackSpec ps = { | ||
212 | .field_name = name, | ||
213 | .object = a | ||
214 | }; | ||
215 | |||
216 | if (NULL == a) | ||
217 | return ps; | ||
218 | (void) json_incref (a); | ||
219 | if (! json_is_array (a)) | ||
220 | { | ||
221 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
222 | "Expected JSON array for field `%s'\n", | ||
223 | name); | ||
224 | GNUNET_assert (0); | ||
225 | } | ||
226 | return ps; | ||
227 | } | ||
228 | |||
229 | |||
230 | struct GNUNET_JSON_PackSpec | ||
231 | GNUNET_JSON_pack_data_varsize (const char *name, | ||
232 | const void *blob, | ||
233 | size_t blob_size) | ||
234 | { | ||
235 | struct GNUNET_JSON_PackSpec ps = { | ||
236 | .field_name = name, | ||
237 | .object = (NULL != blob) | ||
238 | ? GNUNET_JSON_from_data (blob, | ||
239 | blob_size) | ||
240 | : NULL | ||
241 | }; | ||
242 | |||
243 | return ps; | ||
244 | } | ||
245 | |||
246 | |||
247 | struct GNUNET_JSON_PackSpec | ||
248 | GNUNET_JSON_pack_time_abs (const char *name, | ||
249 | struct GNUNET_TIME_Absolute at) | ||
250 | { | ||
251 | struct GNUNET_JSON_PackSpec ps = { | ||
252 | .field_name = name | ||
253 | }; | ||
254 | |||
255 | if (0 != at.abs_value_us) | ||
256 | { | ||
257 | ps.object = GNUNET_JSON_from_time_abs (at); | ||
258 | GNUNET_assert (NULL != ps.object); | ||
259 | } | ||
260 | else | ||
261 | { | ||
262 | ps.object = NULL; | ||
263 | } | ||
264 | return ps; | ||
265 | } | ||
266 | |||
267 | |||
268 | struct GNUNET_JSON_PackSpec | ||
269 | GNUNET_JSON_pack_time_abs_nbo (const char *name, | ||
270 | struct GNUNET_TIME_AbsoluteNBO at) | ||
271 | { | ||
272 | return GNUNET_JSON_pack_time_abs (name, | ||
273 | GNUNET_TIME_absolute_ntoh (at)); | ||
274 | } | ||
275 | |||
276 | |||
277 | struct GNUNET_JSON_PackSpec | ||
278 | GNUNET_JSON_pack_time_rel (const char *name, | ||
279 | struct GNUNET_TIME_Relative rt) | ||
280 | { | ||
281 | json_t *json; | ||
282 | |||
283 | json = GNUNET_JSON_from_time_rel (rt); | ||
284 | GNUNET_assert (NULL != json); | ||
285 | return GNUNET_JSON_pack_object_steal (name, | ||
286 | json); | ||
287 | } | ||
288 | |||
289 | |||
290 | struct GNUNET_JSON_PackSpec | ||
291 | GNUNET_JSON_pack_time_rel_nbo (const char *name, | ||
292 | struct GNUNET_TIME_RelativeNBO rt) | ||
293 | { | ||
294 | return GNUNET_JSON_pack_time_rel (name, | ||
295 | GNUNET_TIME_relative_ntoh (rt)); | ||
296 | } | ||
297 | |||
298 | |||
299 | struct GNUNET_JSON_PackSpec | ||
300 | GNUNET_JSON_pack_rsa_public_key (const char *name, | ||
301 | const struct GNUNET_CRYPTO_RsaPublicKey *pk) | ||
302 | { | ||
303 | struct GNUNET_JSON_PackSpec ps = { | ||
304 | .field_name = name, | ||
305 | .object = GNUNET_JSON_from_rsa_public_key (pk) | ||
306 | }; | ||
307 | |||
308 | return ps; | ||
309 | } | ||
310 | |||
311 | |||
312 | struct GNUNET_JSON_PackSpec | ||
313 | GNUNET_JSON_pack_rsa_signature (const char *name, | ||
314 | const struct GNUNET_CRYPTO_RsaSignature *sig) | ||
315 | { | ||
316 | struct GNUNET_JSON_PackSpec ps = { | ||
317 | .field_name = name, | ||
318 | .object = GNUNET_JSON_from_rsa_signature (sig) | ||
319 | }; | ||
320 | |||
321 | return ps; | ||
322 | } | ||
323 | |||
324 | |||
325 | /* end of json_pack.c */ | ||