summaryrefslogtreecommitdiff
path: root/src/jsonapi/jsonapi_document.c
diff options
context:
space:
mode:
authorMartin Schanzenbach <mschanzenbach@posteo.de>2016-05-04 17:18:02 +0000
committerMartin Schanzenbach <mschanzenbach@posteo.de>2016-05-04 17:18:02 +0000
commita44744499d8f3df64cc1d15cd6b40b4b0e4a3683 (patch)
tree27621a6ee20cbe8e344ffdc18c05754e67d67bf3 /src/jsonapi/jsonapi_document.c
parentca11046195a840932edb04900669a38cd60ae682 (diff)
downloadgnunet-a44744499d8f3df64cc1d15cd6b40b4b0e4a3683.tar.gz
gnunet-a44744499d8f3df64cc1d15cd6b40b4b0e4a3683.zip
Update jsonapi to current specs, refactor
Diffstat (limited to 'src/jsonapi/jsonapi_document.c')
-rw-r--r--src/jsonapi/jsonapi_document.c374
1 files changed, 374 insertions, 0 deletions
diff --git a/src/jsonapi/jsonapi_document.c b/src/jsonapi/jsonapi_document.c
new file mode 100644
index 000000000..4837ee2be
--- /dev/null
+++ b/src/jsonapi/jsonapi_document.c
@@ -0,0 +1,374 @@
1
2#include "platform.h"
3#include "gnunet_util_lib.h"
4#include "gnunet_json_lib.h"
5#include "jsonapi_objects.h"
6
7/**
8 * Get a JSON API object resource count
9 *
10 * @param resp the JSON API object
11 * @return the number of resources
12 */
13int
14GNUNET_JSONAPI_document_resource_count (struct GNUNET_JSONAPI_Document *doc)
15{
16 return doc->res_count;
17}
18
19/**
20 * Get a JSON API object resource by index
21 *
22 * @param resp the JSON API object
23 * @param idx index of the resource
24 * @return the resource
25 */
26struct GNUNET_JSONAPI_Resource*
27GNUNET_JSONAPI_document_get_resource (struct GNUNET_JSONAPI_Document *doc,
28 int idx)
29{
30 struct GNUNET_JSONAPI_Resource *res;
31 int i;
32
33 if ((0 == doc->res_count) ||
34 (idx >= doc->res_count))
35 return NULL;
36 res = doc->res_list_head;
37 for (i = 0; i < idx; i++)
38 {
39 res = res->next;
40 }
41 return res;
42}
43
44/**
45 * Delete a JSON API primary data
46 *
47 * @param type the JSON API resource type
48 * @param id the JSON API resource id
49 * @return a new JSON API resource or NULL on error.
50 */
51void
52GNUNET_JSONAPI_document_delete (struct GNUNET_JSONAPI_Document *doc)
53{
54 struct GNUNET_JSONAPI_Resource *res;
55 struct GNUNET_JSONAPI_Resource *res_next;
56
57
58 for (res = doc->res_list_head;
59 res != NULL;)
60 {
61 res_next = res->next;
62 GNUNET_CONTAINER_DLL_remove (doc->res_list_head,
63 doc->res_list_tail,
64 res);
65 GNUNET_JSONAPI_resource_delete (res);
66 res = res_next;
67 }
68 GNUNET_free (doc);
69 doc = NULL;
70}
71
72/**
73 * Create a JSON API primary data
74 *
75 * @return a new JSON API resource or NULL on error.
76 */
77struct GNUNET_JSONAPI_Document*
78GNUNET_JSONAPI_document_new ()
79{
80 struct GNUNET_JSONAPI_Document *result;
81
82 result = GNUNET_new (struct GNUNET_JSONAPI_Document);
83 result->res_count = 0;
84 result->err_count = 0;
85 result->meta = 0;
86 return result;
87}
88
89/**
90 * Add a JSON API error to document
91 *
92 * @param data The JSON API document to add to
93 * @param res the JSON API error to add
94 * @return the new number of resources
95 */
96void
97GNUNET_JSONAPI_document_error_add (struct GNUNET_JSONAPI_Document *doc,
98 struct GNUNET_JSONAPI_Error *err)
99{
100 GNUNET_CONTAINER_DLL_insert (doc->err_list_head,
101 doc->err_list_tail,
102 err);
103
104 doc->err_count++;
105}
106
107/**
108 * Add a JSON API resource to primary data
109 *
110 * @param data The JSON API data to add to
111 * @param res the JSON API resource to add
112 * @return the new number of resources
113 */
114void
115GNUNET_JSONAPI_document_resource_add (struct GNUNET_JSONAPI_Document *doc,
116 struct GNUNET_JSONAPI_Resource *res)
117{
118 GNUNET_CONTAINER_DLL_insert (doc->res_list_head,
119 doc->res_list_tail,
120 res);
121
122 doc->res_count++;
123}
124
125
126/**
127 * Parse given JSON object to jsonapi document.
128 *
129 * @param cls closure, NULL
130 * @param root the json object representing data
131 * @param[out] spec where to write the data
132 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
133 */
134static int
135parse_jsonapiobject (void *cls,
136 json_t *root,
137 struct GNUNET_JSON_Specification *spec)
138{
139 struct GNUNET_JSONAPI_Document *result;
140 struct GNUNET_JSONAPI_Error *error;
141 struct GNUNET_JSONAPI_Resource *resource;
142 json_t *meta_json;
143 json_t *resource_json;
144 json_t *errors_json;
145 json_t *value;
146 size_t index;
147
148 struct GNUNET_JSON_Specification jsonapispecerrors[] = {
149 GNUNET_JSON_spec_json (GNUNET_JSONAPI_KEY_ERRORS, &errors_json),
150 GNUNET_JSON_spec_end()
151 };
152 if (GNUNET_OK !=
153 GNUNET_JSON_parse (root, jsonapispecerrors,
154 NULL, NULL))
155 {
156 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
157 "JSONAPI document does not contain error objects\n");
158 } else if (!json_is_array (errors_json))
159 {
160 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
161 "Error object is not array!\n");
162 GNUNET_JSON_parse_free (jsonapispecerrors);
163 return GNUNET_SYSERR;
164 }
165 struct GNUNET_JSON_Specification jsonapispecmeta[] = {
166 GNUNET_JSON_spec_json (GNUNET_JSONAPI_KEY_META, &meta_json),
167 GNUNET_JSON_spec_end()
168 };
169 if (GNUNET_OK !=
170 GNUNET_JSON_parse (root, jsonapispecmeta,
171 NULL, NULL))
172 {
173 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
174 "JSONAPI document does not contain error objects\n");
175 }
176 struct GNUNET_JSON_Specification jsonapispecresource[] = {
177 GNUNET_JSON_spec_json (GNUNET_JSONAPI_KEY_DATA, &resource_json),
178 GNUNET_JSON_spec_end()
179 };
180 if (GNUNET_OK !=
181 GNUNET_JSON_parse (root, jsonapispecresource,
182 NULL, NULL))
183 {
184 if (NULL == errors_json)
185 {
186 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
187 "JSONAPI document contains neither error nor data!\n");
188 GNUNET_JSON_parse_free (jsonapispecerrors);
189 GNUNET_JSON_parse_free (jsonapispecmeta);
190 return GNUNET_SYSERR;
191 }
192 } else {
193 if (NULL != errors_json)
194 {
195 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
196 "JSONAPI document contains both error and data!\n");
197 GNUNET_JSON_parse_free (jsonapispecerrors);
198 GNUNET_JSON_parse_free (jsonapispecmeta);
199 GNUNET_JSON_parse_free (jsonapispecresource);
200 return GNUNET_SYSERR;
201 }
202 }
203
204 result = GNUNET_new (struct GNUNET_JSONAPI_Document);
205 result->res_count = 0;
206 result->err_count = 0;
207 if (NULL != meta_json)
208 result->meta = json_deep_copy (meta_json);
209 if (NULL != errors_json) {
210 json_array_foreach(errors_json, index, value) {
211 GNUNET_assert (GNUNET_OK ==
212 GNUNET_JSONAPI_json_to_error (value,
213 &error));
214 GNUNET_JSONAPI_document_error_add (result, error);
215 }
216 }
217 if (NULL != resource_json) {
218 if (0 != json_is_array (resource_json))
219 {
220 json_array_foreach(resource_json, index, value) {
221 GNUNET_assert (GNUNET_OK ==
222 GNUNET_JSONAPI_json_to_resource (value,
223 &resource));
224 GNUNET_JSONAPI_document_resource_add (result, resource);
225 }
226 } else {
227 GNUNET_assert (GNUNET_OK ==
228 GNUNET_JSONAPI_json_to_resource (resource_json,
229 &resource));
230 GNUNET_JSONAPI_document_resource_add (result, resource);
231 }
232 }
233 if (NULL != errors_json)
234 GNUNET_JSON_parse_free (jsonapispecerrors);
235 if (NULL != resource)
236 GNUNET_JSON_parse_free (jsonapispecresource);
237 if (NULL != meta_json)
238 GNUNET_JSON_parse_free (jsonapispecmeta);
239 *(struct GNUNET_JSONAPI_Document **) spec->ptr = result;
240 return GNUNET_OK;
241}
242
243
244/**
245 * Cleanup data left from parsing RSA public key.
246 *
247 * @param cls closure, NULL
248 * @param[out] spec where to free the data
249 */
250static void
251clean_jsonapiobject (void *cls,
252 struct GNUNET_JSON_Specification *spec)
253{
254 struct GNUNET_JSONAPI_Document **jsonapi_obj;
255 jsonapi_obj = (struct GNUNET_JSONAPI_Document **) spec->ptr;
256 if (NULL != *jsonapi_obj)
257 {
258 GNUNET_JSONAPI_document_delete (*jsonapi_obj);
259 *jsonapi_obj = NULL;
260 }
261}
262
263/**
264 * Add a JSON API resource to primary data
265 *
266 * @param data The JSON API data to add to
267 * @param res the JSON API resource to add
268 * @return the new number of resources
269 */
270void
271GNUNET_JSONAPI_document_resource_remove (struct GNUNET_JSONAPI_Document *resp,
272 struct GNUNET_JSONAPI_Resource *res)
273{
274 GNUNET_CONTAINER_DLL_remove (resp->res_list_head,
275 resp->res_list_tail,
276 res);
277 resp->res_count--;
278}
279
280
281/**
282 * String serialze jsonapi primary data
283 *
284 * @param data the JSON API primary data
285 * @param result where to store the result
286 * @return GNUNET_SYSERR on error else GNUNET_OK
287 */
288int
289GNUNET_JSONAPI_document_serialize (const struct GNUNET_JSONAPI_Document *doc,
290 char **result)
291{
292 struct GNUNET_JSONAPI_Resource *res;
293 struct GNUNET_JSONAPI_Error *error;
294 json_t *root_json;
295 json_t *res_json;
296 json_t *res_json_tmp;
297
298 if ((NULL == doc))
299 return GNUNET_SYSERR;
300
301 root_json = json_object ();
302
303 //Check for errors first
304 if (doc->err_count != 0)
305 {
306 res_json = json_array ();
307 for (error = doc->err_list_head;
308 error != NULL;
309 error = error->next)
310 {
311 GNUNET_assert (GNUNET_OK ==
312 GNUNET_JSONAPI_error_to_json (error,
313 &res_json_tmp));
314 json_array_append (res_json, res_json_tmp);
315 }
316 json_object_set (root_json, GNUNET_JSONAPI_KEY_ERRORS, res_json);
317 } else {
318 switch (doc->res_count)
319 {
320 case 0:
321 res_json = json_null();
322 break;
323 case 1:
324 GNUNET_assert (GNUNET_OK ==
325 GNUNET_JSONAPI_resource_to_json (doc->res_list_head,
326 &res_json));
327 break;
328 default:
329 res_json = json_array ();
330 for (res = doc->res_list_head;
331 res != NULL;
332 res = res->next)
333 {
334 GNUNET_assert (GNUNET_OK ==
335 GNUNET_JSONAPI_resource_to_json (res,
336 &res_json_tmp));
337 json_array_append (res_json, res_json_tmp);
338 }
339 break;
340 }
341 json_object_set (root_json, GNUNET_JSONAPI_KEY_DATA, res_json);
342 }
343
344 //Add meta
345 json_object_set (root_json, GNUNET_JSONAPI_KEY_META, doc->meta);
346 *result = json_dumps (root_json, JSON_INDENT(2));
347 json_decref (root_json);
348 json_decref (res_json);
349 return GNUNET_OK;
350}
351
352/**
353 * JSON object.
354 *
355 * @param name name of the JSON field
356 * @param[out] jsonp where to store the JSON found under @a name
357 */
358struct GNUNET_JSON_Specification
359GNUNET_JSON_spec_jsonapi_document (struct GNUNET_JSONAPI_Document **jsonapi_object)
360{
361 struct GNUNET_JSON_Specification ret = {
362 .parser = &parse_jsonapiobject,
363 .cleaner = &clean_jsonapiobject,
364 .cls = NULL,
365 .field = NULL,
366 .ptr = jsonapi_object,
367 .ptr_size = 0,
368 .size_ptr = NULL
369 };
370 *jsonapi_object = NULL;
371 return ret;
372}
373
374