diff options
author | Christian Grothoff <grothoff@gnunet.org> | 2021-07-26 16:32:34 +0200 |
---|---|---|
committer | Christian Grothoff <grothoff@gnunet.org> | 2021-07-26 16:32:34 +0200 |
commit | 90095d19b4da40e79dce43a31af398a8925bcc4a (patch) | |
tree | cd8b5eaf6073963fae7c428d4ce0797253e88fd5 /src/json | |
parent | 089fe579a913bda293d2c1579972a64657242660 (diff) | |
download | gnunet-90095d19b4da40e79dce43a31af398a8925bcc4a.tar.gz gnunet-90095d19b4da40e79dce43a31af398a8925bcc4a.zip |
implement typed JSON packer
Diffstat (limited to 'src/json')
-rw-r--r-- | src/json/Makefile.am | 5 | ||||
-rw-r--r-- | src/json/json.c | 34 | ||||
-rw-r--r-- | src/json/json_pack.c | 291 |
3 files changed, 294 insertions, 36 deletions
diff --git a/src/json/Makefile.am b/src/json/Makefile.am index d4ea38adf..3c19f96bf 100644 --- a/src/json/Makefile.am +++ b/src/json/Makefile.am | |||
@@ -16,9 +16,10 @@ libgnunetjson_la_LDFLAGS = \ | |||
16 | libgnunetjson_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS) | 16 | libgnunetjson_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS) |
17 | libgnunetjson_la_SOURCES = \ | 17 | libgnunetjson_la_SOURCES = \ |
18 | json.c \ | 18 | json.c \ |
19 | json_mhd.c \ | ||
20 | json_generator.c \ | 19 | json_generator.c \ |
21 | json_helper.c | 20 | json_helper.c \ |
21 | json_mhd.c \ | ||
22 | json_pack.c | ||
22 | libgnunetjson_la_LIBADD = \ | 23 | libgnunetjson_la_LIBADD = \ |
23 | $(top_builddir)/src/util/libgnunetutil.la \ | 24 | $(top_builddir)/src/util/libgnunetutil.la \ |
24 | -ljansson \ | 25 | -ljansson \ |
diff --git a/src/json/json.c b/src/json/json.c index d55189804..4dabd4d22 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,12 +82,6 @@ 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 | { |
@@ -151,15 +126,6 @@ set_json (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, | |||
151 | } | 126 | } |
152 | 127 | ||
153 | 128 | ||
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 | 129 | struct GNUNET_GETOPT_CommandLineOption |
164 | GNUNET_JSON_getopt (char shortName, | 130 | GNUNET_JSON_getopt (char shortName, |
165 | const char *name, | 131 | const char *name, |
diff --git a/src/json/json_pack.c b/src/json/json_pack.c new file mode 100644 index 000000000..88edaca5f --- /dev/null +++ b/src/json/json_pack.c | |||
@@ -0,0 +1,291 @@ | |||
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 <= LONG_LONG_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 <= LONG_LONG_MAX); | ||
131 | GNUNET_assert (num >= LONG_LONG_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 | GNUNET_assert (json_is_object (o)); | ||
152 | return ps; | ||
153 | } | ||
154 | |||
155 | |||
156 | struct GNUNET_JSON_PackSpec | ||
157 | GNUNET_JSON_pack_object_incref (const char *name, | ||
158 | json_t *o) | ||
159 | { | ||
160 | struct GNUNET_JSON_PackSpec ps = { | ||
161 | .field_name = name, | ||
162 | .object = o | ||
163 | }; | ||
164 | |||
165 | if (NULL == o) | ||
166 | return ps; | ||
167 | (void) json_incref (o); | ||
168 | GNUNET_assert (json_is_object (o)); | ||
169 | return ps; | ||
170 | } | ||
171 | |||
172 | |||
173 | struct GNUNET_JSON_PackSpec | ||
174 | GNUNET_JSON_pack_array_steal (const char *name, | ||
175 | json_t *a) | ||
176 | { | ||
177 | struct GNUNET_JSON_PackSpec ps = { | ||
178 | .field_name = name, | ||
179 | .object = a | ||
180 | }; | ||
181 | |||
182 | if (NULL == a) | ||
183 | return ps; | ||
184 | GNUNET_assert (json_is_array (a)); | ||
185 | return ps; | ||
186 | } | ||
187 | |||
188 | |||
189 | struct GNUNET_JSON_PackSpec | ||
190 | GNUNET_JSON_pack_array_incref (const char *name, | ||
191 | json_t *a) | ||
192 | { | ||
193 | struct GNUNET_JSON_PackSpec ps = { | ||
194 | .field_name = name, | ||
195 | .object = a | ||
196 | }; | ||
197 | |||
198 | if (NULL == a) | ||
199 | return ps; | ||
200 | (void) json_incref (a); | ||
201 | GNUNET_assert (json_is_array (a)); | ||
202 | return ps; | ||
203 | } | ||
204 | |||
205 | |||
206 | struct GNUNET_JSON_PackSpec | ||
207 | GNUNET_JSON_pack_data_varsize (const char *name, | ||
208 | const void *blob, | ||
209 | size_t blob_size) | ||
210 | { | ||
211 | json_t *json; | ||
212 | |||
213 | json = GNUNET_JSON_from_data (blob, | ||
214 | blob_size); | ||
215 | GNUNET_assert (NULL != json); | ||
216 | return GNUNET_JSON_pack_object_steal (name, | ||
217 | json); | ||
218 | } | ||
219 | |||
220 | |||
221 | struct GNUNET_JSON_PackSpec | ||
222 | GNUNET_JSON_pack_time_abs (const char *name, | ||
223 | struct GNUNET_TIME_Absolute at) | ||
224 | { | ||
225 | json_t *json; | ||
226 | |||
227 | json = GNUNET_JSON_from_time_abs (at); | ||
228 | GNUNET_assert (NULL != json); | ||
229 | return GNUNET_JSON_pack_object_steal (name, | ||
230 | json); | ||
231 | } | ||
232 | |||
233 | |||
234 | struct GNUNET_JSON_PackSpec | ||
235 | GNUNET_JSON_pack_time_abs_nbo (const char *name, | ||
236 | struct GNUNET_TIME_AbsoluteNBO at) | ||
237 | { | ||
238 | return GNUNET_JSON_pack_time_abs (name, | ||
239 | GNUNET_TIME_absolute_ntoh (at)); | ||
240 | } | ||
241 | |||
242 | |||
243 | struct GNUNET_JSON_PackSpec | ||
244 | GNUNET_JSON_pack_time_rel (const char *name, | ||
245 | struct GNUNET_TIME_Relative rt) | ||
246 | { | ||
247 | json_t *json; | ||
248 | |||
249 | json = GNUNET_JSON_from_time_rel (rt); | ||
250 | GNUNET_assert (NULL != json); | ||
251 | return GNUNET_JSON_pack_object_steal (name, | ||
252 | json); | ||
253 | } | ||
254 | |||
255 | |||
256 | struct GNUNET_JSON_PackSpec | ||
257 | GNUNET_JSON_pack_time_rel_nbo (const char *name, | ||
258 | struct GNUNET_TIME_RelativeNBO rt) | ||
259 | { | ||
260 | return GNUNET_JSON_pack_time_rel (name, | ||
261 | GNUNET_TIME_relative_ntoh (rt)); | ||
262 | } | ||
263 | |||
264 | |||
265 | struct GNUNET_JSON_PackSpec | ||
266 | GNUNET_JSON_pack_rsa_public_key (const char *name, | ||
267 | const struct GNUNET_CRYPTO_RsaPublicKey *pk) | ||
268 | { | ||
269 | json_t *json; | ||
270 | |||
271 | json = GNUNET_JSON_from_rsa_public_key (pk); | ||
272 | GNUNET_assert (NULL != json); | ||
273 | return GNUNET_JSON_pack_object_steal (name, | ||
274 | json); | ||
275 | } | ||
276 | |||
277 | |||
278 | struct GNUNET_JSON_PackSpec | ||
279 | GNUNET_JSON_pack_rsa_signature (const char *name, | ||
280 | const struct GNUNET_CRYPTO_RsaSignature *sig) | ||
281 | { | ||
282 | json_t *json; | ||
283 | |||
284 | json = GNUNET_JSON_from_rsa_signature (sig); | ||
285 | GNUNET_assert (NULL != json); | ||
286 | return GNUNET_JSON_pack_object_steal (name, | ||
287 | json); | ||
288 | } | ||
289 | |||
290 | |||
291 | /* end of json_pack.c */ | ||