GCC Code Coverage Report


Directory: src/
File: src/json.c
Date: 2024-04-25 03:45:42
Exec Total Coverage
Lines: 112 153 73.2%
Branches: 22 70 31.4%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2023 Egor Tensin <egor@tensin.name>
3 * This file is part of the "cimple" project.
4 * For details, see https://github.com/egor-tensin/cimple.
5 * Distributed under the MIT License.
6 */
7
8 #include "json.h"
9 #include "buf.h"
10 #include "log.h"
11 #include "net.h"
12
13 #include <json-c/json_object.h>
14 #include <json-c/json_tokener.h>
15
16 #include <errno.h>
17 #include <stdint.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 #define libjson_errno(fn) \
22 do { \
23 log_err("JSON: %s failed\n", fn); \
24 } while (0)
25
26 110424 void libjson_free(struct json_object *obj)
27 {
28 110424 json_object_put(obj);
29 110424 }
30
31 55212 static const char *libjson_to_string_internal(struct json_object *obj, int flags)
32 {
33 55212 const char *result = json_object_to_json_string_ext(obj, flags);
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55212 times.
55212 if (!result) {
35 libjson_errno("json_object_to_json_string");
36 return NULL;
37 }
38 55212 return result;
39 }
40
41 46006 const char *libjson_to_string(struct json_object *obj)
42 {
43 46006 return libjson_to_string_internal(obj, JSON_C_TO_STRING_SPACED);
44 }
45
46 9206 const char *libjson_to_string_pretty(struct json_object *obj)
47 {
48 9206 return libjson_to_string_internal(obj, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
49 }
50
51 46006 struct json_object *libjson_from_string(const char *src)
52 {
53 enum json_tokener_error error;
54
55 46006 struct json_object *result = json_tokener_parse_verbose(src, &error);
56
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46006 times.
46006 if (!result) {
57 libjson_errno("json_tokener_parse_verbose");
58 log_err("JSON: parsing failed: %s\n", json_tokener_error_desc(error));
59 return NULL;
60 }
61
62 46006 return result;
63 }
64
65 27618 int libjson_clone(const struct json_object *obj, const char *key, struct json_object **_value)
66 {
67 27618 int ret = 0;
68
69 27618 struct json_object *old_value = NULL;
70 27618 ret = libjson_get(obj, key, &old_value);
71
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27618 times.
27618 if (ret < 0)
72 return ret;
73
74 27618 struct json_object *new_value = NULL;
75 27618 ret = json_object_deep_copy(old_value, &new_value, NULL);
76
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27618 times.
27618 if (ret < 0)
77 return ret;
78
79 27618 *_value = new_value;
80 27618 return ret;
81 }
82
83 46006 int libjson_send(struct json_object *obj, int fd)
84 {
85 46006 int ret = 0;
86
87 46006 const char *str = libjson_to_string(obj);
88
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46006 times.
46006 if (!str)
89 return -1;
90
91 46006 struct buf *buf = NULL;
92 46006 ret = buf_create_from_string(&buf, str);
93
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46006 times.
46006 if (ret < 0)
94 return ret;
95
96 46006 ret = net_send_buf(fd, buf);
97 46006 buf_destroy(buf);
98 46006 return ret;
99 }
100
101 46006 struct json_object *libjson_recv(int fd)
102 {
103 46006 struct json_object *result = NULL;
104 46006 int ret = 0;
105
106 46006 struct buf *buf = NULL;
107 46006 ret = net_recv_buf(fd, &buf);
108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46006 times.
46006 if (ret < 0)
109 return NULL;
110
111 46006 result = libjson_from_string((const char *)buf_get_data(buf));
112
1/2
✓ Branch 0 taken 46006 times.
✗ Branch 1 not taken.
46006 if (!result)
113 goto destroy_buf;
114
115 46006 destroy_buf:
116 46006 free((void *)buf_get_data(buf));
117 46006 buf_destroy(buf);
118
119 46006 return result;
120 }
121
122 110344 int libjson_new_object(struct json_object **_obj)
123 {
124 110344 struct json_object *obj = json_object_new_object();
125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110344 times.
110344 if (!obj) {
126 libjson_errno("json_object_new_object");
127 return -1;
128 }
129 110344 *_obj = obj;
130 110344 return 0;
131 }
132
133 26 int libjson_new_array(struct json_object **_arr)
134 {
135 26 struct json_object *arr = json_object_new_array();
136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (!arr) {
137 libjson_errno("json_object_new_array");
138 return -1;
139 }
140 26 *_arr = arr;
141 26 return 0;
142 }
143
144 606620 int libjson_has(const struct json_object *obj, const char *key)
145 {
146 606620 return json_object_object_get_ex(obj, key, NULL);
147 }
148
149 385956 int libjson_get(const struct json_object *obj, const char *key, struct json_object **value)
150 {
151
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 385956 times.
385956 if (!libjson_has(obj, key)) {
152 log_err("JSON: key is missing: %s\n", key);
153 return -1;
154 }
155
156 385956 return json_object_object_get_ex(obj, key, value);
157 }
158
159 165506 int libjson_get_string(const struct json_object *obj, const char *key, const char **_value)
160 {
161 165506 struct json_object *value = NULL;
162
163 165506 int ret = libjson_get(obj, key, &value);
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165506 times.
165506 if (ret < 0)
165 return ret;
166
167
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 165506 times.
165506 if (!json_object_is_type(value, json_type_string)) {
168 log_err("JSON: key is not a string: %s\n", key);
169 return -1;
170 }
171
172 165506 *_value = json_object_get_string(value);
173 165506 return 0;
174 }
175
176 27540 int libjson_get_int(const struct json_object *obj, const char *key, int64_t *_value)
177 {
178 27540 struct json_object *value = NULL;
179
180 27540 int ret = libjson_get(obj, key, &value);
181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27540 times.
27540 if (ret < 0)
182 return ret;
183
184
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 27540 times.
27540 if (!json_object_is_type(value, json_type_int)) {
185 log_err("JSON: key is not an integer: %s\n", key);
186 return -1;
187 }
188
189 27540 errno = 0;
190 27540 int64_t tmp = json_object_get_int64(value);
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27540 times.
27540 if (errno) {
192 log_err("JSON: failed to parse integer from key: %s\n", key);
193 return -1;
194 }
195
196 27540 *_value = tmp;
197 27540 return 0;
198 }
199
200 321772 static int libjson_set_internal(struct json_object *obj, const char *key, struct json_object *value,
201 unsigned flags)
202 {
203 321772 int ret = 0;
204
205 321772 ret = json_object_object_add_ex(obj, key, value, flags);
206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 321772 times.
321772 if (ret < 0) {
207 libjson_errno("json_object_object_add_ex");
208 return ret;
209 }
210
211 321772 return 0;
212 }
213
214 174684 static int libjson_set_string_internal(struct json_object *obj, const char *key, const char *_value,
215 unsigned flags)
216 {
217 174684 struct json_object *value = json_object_new_string(_value);
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 174684 times.
174684 if (!value) {
219 libjson_errno("json_object_new_string");
220 return -1;
221 }
222
223 174684 int ret = libjson_set_internal(obj, key, value, flags);
224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 174684 times.
174684 if (ret < 0)
225 goto free_value;
226
227 174684 return ret;
228
229 free_value:
230 json_object_put(value);
231
232 return ret;
233 }
234
235 64312 static int libjson_set_int_internal(struct json_object *obj, const char *key, int64_t _value,
236 unsigned flags)
237 {
238 64312 struct json_object *value = json_object_new_int64(_value);
239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64312 times.
64312 if (!value) {
240 libjson_errno("json_object_new_int");
241 return -1;
242 }
243
244 64312 int ret = libjson_set_internal(obj, key, value, flags);
245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64312 times.
64312 if (ret < 0)
246 goto free_value;
247
248 64312 return ret;
249
250 free_value:
251 json_object_put(value);
252
253 return ret;
254 }
255
256 55158 int libjson_set(struct json_object *obj, const char *key, struct json_object *value)
257 {
258 55158 return libjson_set_internal(obj, key, value, 0);
259 }
260
261 45900 int libjson_set_string(struct json_object *obj, const char *key, const char *value)
262 {
263 45900 return libjson_set_string_internal(obj, key, value, 0);
264 }
265
266 27540 int libjson_set_int(struct json_object *obj, const char *key, int64_t value)
267 {
268 27540 return libjson_set_int_internal(obj, key, value, 0);
269 }
270
271 #ifndef JSON_C_OBJECT_ADD_CONSTANT_KEY
272 #define JSON_C_OBJECT_ADD_CONSTANT_KEY JSON_C_OBJECT_KEY_IS_CONSTANT
273 #endif
274 static const unsigned json_const_key_flags = JSON_C_OBJECT_ADD_CONSTANT_KEY;
275
276 27618 int libjson_set_const_key(struct json_object *obj, const char *key, struct json_object *value)
277 {
278 27618 return libjson_set_internal(obj, key, value, json_const_key_flags);
279 }
280
281 128784 int libjson_set_string_const_key(struct json_object *obj, const char *key, const char *value)
282 {
283 128784 return libjson_set_string_internal(obj, key, value, json_const_key_flags);
284 }
285
286 36772 int libjson_set_int_const_key(struct json_object *obj, const char *key, int64_t value)
287 {
288 36772 return libjson_set_int_internal(obj, key, value, json_const_key_flags);
289 }
290
291 9180 int libjson_append(struct json_object *arr, struct json_object *elem)
292 {
293 9180 int ret = json_object_array_add(arr, elem);
294
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0) {
295 libjson_errno("json_object_array_add");
296 return ret;
297 }
298 9180 return ret;
299 }
300