Nyx Node
Loading...
Searching...
No Matches
json_dict.c
1/* NyxNode
2 * Author: Jérôme ODIER <jerome.odier@lpsc.in2p3.fr>
3 * SPDX-License-Identifier: GPL-2.0-only (Mongoose backend) or GPL-3.0+
4 */
5
6/*--------------------------------------------------------------------------------------------------------------------*/
7
8#include <string.h>
9
10#include "../nyx_node_internal.h"
11
12/*--------------------------------------------------------------------------------------------------------------------*/
13
14static void internal_dict_clear(
15 nyx_dict_t *object
16);
17
18/*--------------------------------------------------------------------------------------------------------------------*/
19
21{
22 /*----------------------------------------------------------------------------------------------------------------*/
23
24 nyx_dict_t *object = nyx_memory_alloc(sizeof(nyx_dict_t));
25
26 /*----------------------------------------------------------------------------------------------------------------*/
27
28 object->base = NYX_OBJECT(NYX_TYPE_DICT);
29
30 /*----------------------------------------------------------------------------------------------------------------*/
31
32 object->head = NULL;
33 object->tail = NULL;
34
35 /*----------------------------------------------------------------------------------------------------------------*/
36
37 return object;
38}
39
40/*--------------------------------------------------------------------------------------------------------------------*/
41
42void nyx_dict_free(nyx_dict_t *object)
43{
44 internal_dict_clear(object);
45
46 nyx_memory_free(object);
47}
48
49/*--------------------------------------------------------------------------------------------------------------------*/
50
51static void internal_dict_clear(nyx_dict_t *object)
52{
53 /*----------------------------------------------------------------------------------------------------------------*/
54
55 for(nyx_dict_node_t *node = object->head; node != NULL;)
56 {
57 /*------------------------------------------------------------------------------------------------------------*/
58
59 nyx_dict_node_t *temp = node;
60
61 node = node->next;
62
63 /*------------------------------------------------------------------------------------------------------------*/
64
65 temp->value->parent = NULL;
66
67 nyx_object_unref(temp->value);
68
69 nyx_memory_free(temp);
70
71 /*------------------------------------------------------------------------------------------------------------*/
72 }
73
74 /*----------------------------------------------------------------------------------------------------------------*/
75
76 object->head = NULL;
77 object->tail = NULL;
78
79 /*----------------------------------------------------------------------------------------------------------------*/
80}
81
82/*--------------------------------------------------------------------------------------------------------------------*/
83
85{
86 internal_dict_clear(object);
87}
88
89/*--------------------------------------------------------------------------------------------------------------------*/
90
91void nyx_dict_del(nyx_dict_t *object, STR_t key)
92{
93 /*----------------------------------------------------------------------------------------------------------------*/
94
95 for(nyx_dict_node_t *prev_node = NULL, *curr_node = object->head; curr_node != NULL; prev_node = curr_node, curr_node = curr_node->next)
96 {
97 if(strcmp(curr_node->key, key) == 0)
98 {
99 /*--------------------------------------------------------------------------------------------------------*/
100
101 if(prev_node == NULL)
102 {
103 object->head = curr_node->next;
104 }
105 else
106 {
107 prev_node->next = curr_node->next;
108 }
109
110 /*--------------------------------------------------------------------------------------------------------*/
111
112 if(curr_node == object->tail)
113 {
114 object->tail = prev_node;
115 }
116
117 /*--------------------------------------------------------------------------------------------------------*/
118
119 curr_node->value->parent = NULL;
120
121 nyx_object_unref(curr_node->value);
122
123 nyx_memory_free(curr_node);
124
125 /*--------------------------------------------------------------------------------------------------------*/
126
127 break;
128 }
129 }
130
131 /*----------------------------------------------------------------------------------------------------------------*/
132}
133
134/*--------------------------------------------------------------------------------------------------------------------*/
135
137{
138 if(iter->head != NULL)
139 {
140 if(key != NULL) {
141 *key = iter->head->key;
142 }
143
144 if(object != NULL) {
145 *object = iter->head->value;
146 }
147
148 iter->idx += 0x0000000000001;
149 iter->head = iter->head->next;
150
151 return true;
152 }
153
154 return false;
155}
156
157/*--------------------------------------------------------------------------------------------------------------------*/
158
160{
161 /*----------------------------------------------------------------------------------------------------------------*/
162
163 for(nyx_dict_node_t *curr_node = object->head; curr_node != NULL; curr_node = curr_node->next)
164 {
165 if(strcmp(curr_node->key, key) == 0)
166 {
167 return curr_node->value;
168 }
169 }
170
171 /*----------------------------------------------------------------------------------------------------------------*/
172
173 return NULL;
174}
175
176/*--------------------------------------------------------------------------------------------------------------------*/
177
178bool nyx_dict_set(nyx_dict_t *object, STR_t key, void *value)
179{
180 /*----------------------------------------------------------------------------------------------------------------*/
181
182 if(!NYX_OBJECT_CHECK_MAGIC(value))
183 {
184 NYX_LOG_FATAL("Invalid object");
185 }
186
187 /*----------------------------------------------------------------------------------------------------------------*/
188
189 if(((nyx_object_t *) value)->parent != NULL)
190 {
191 NYX_LOG_ERROR("Object already has a parent");
192
193 return false;
194 }
195
196 for(nyx_object_t *parent = (nyx_object_t *) object; parent != NULL; parent = parent->parent)
197 {
198 if(parent == (nyx_object_t *) value)
199 {
200 NYX_LOG_ERROR("An object cannot be its own parent");
201
202 return false;
203 }
204 }
205
206 /*----------------------------------------------------------------------------------------------------------------*/
207
208 bool modified = true;
209
210 for(nyx_dict_node_t *curr_node = /* NOSONAR */ object->head; curr_node != NULL; curr_node = curr_node->next)
211 {
212 if(strcmp(curr_node->key, key) == 0)
213 {
214 modified = !nyx_object_equal(curr_node->value, value);
215
216 curr_node->value->parent = NULL;
217
218 nyx_object_ref(/*-*/ value /*-*/);
219 nyx_object_unref(curr_node->value);
220
221 curr_node->value = value;
222
223 goto _ok;
224 }
225 }
226
227 /*----------------------------------------------------------------------------------------------------------------*/
228
229 nyx_dict_node_t *node = nyx_memory_alloc(sizeof(nyx_dict_node_t) + strlen(key) + 1);
230
231 node->key = strcpy((str_t) (node + 1), key);
232
233 nyx_object_ref(value);
234
235 node->value = value;
236 node->next = NULL;
237
238 /*----------------------------------------------------------------------------------------------------------------*/
239
240 if(object->head == NULL)
241 {
242 object->head = node;
243 object->tail = node;
244 }
245 else
246 {
247 object->tail->next = node;
248 object->tail /*-*/ = node;
249 }
250
251 /*----------------------------------------------------------------------------------------------------------------*/
252_ok:
253 ((nyx_object_t *) value)->parent = (nyx_object_t *) object;
254
255 return modified;
256}
257
258/*--------------------------------------------------------------------------------------------------------------------*/
259
260size_t nyx_dict_size(const nyx_dict_t *object)
261{
262 size_t result = 0;
263
264 /*----------------------------------------------------------------------------------------------------------------*/
265
266 for(nyx_dict_node_t *node = object->head; node != NULL; node = node->next, result++) { /* NOSONAR */ }
267
268 /*----------------------------------------------------------------------------------------------------------------*/
269
270 return result;
271}
272
273/*--------------------------------------------------------------------------------------------------------------------*/
274
276{
277 nyx_string_builder_t *sb = nyx_string_builder_new();
278
279 /**/ nyx_string_builder_append(sb, NYX_SB_NO_ESCAPE, "{");
280 /**/
281 /**/ for(nyx_dict_node_t *curr_node = object->head; curr_node != NULL; curr_node = curr_node->next)
282 /**/ {
283 /**/ /*----------------------------------------------------------------------------------------------------*/
284 /**/
285 /**/ str_t curr_node_val = nyx_object_to_string(curr_node->value);
286 /**/
287 /**/ nyx_string_builder_append(sb, NYX_SB_NO_ESCAPE, "\"");
288 /**/ nyx_string_builder_append(sb, NYX_SB_ESCAPE_JSON, curr_node->key);
289 /**/ nyx_string_builder_append(sb, NYX_SB_NO_ESCAPE, "\"", ":", curr_node_val);
290 /**/
291 /**/ nyx_memory_free(curr_node_val);
292 /**/
293 /**/ /*----------------------------------------------------------------------------------------------------*/
294 /**/
295 /**/ if(curr_node->next != NULL)
296 /**/ {
297 /**/ nyx_string_builder_append(sb, NYX_SB_NO_ESCAPE, ",");
298 /**/ }
299 /**/
300 /**/ /*----------------------------------------------------------------------------------------------------*/
301 /**/ }
302 /**/
303 /**/ nyx_string_builder_append(sb, NYX_SB_NO_ESCAPE, "}");
304
305 str_t result = nyx_string_builder_to_string(sb);
306
307 nyx_string_builder_free(sb);
308
309 return result;
310}
311
312/*--------------------------------------------------------------------------------------------------------------------*/
size_t idx
Current zero-based iteration index.
Definition nyx_node.h:1113
struct nyx_dict_node_s * head
Next JSON object to visit.
Definition nyx_node.h:1115
size_t nyx_dict_size(const nyx_dict_t *object)
Gets the number of items in the provided JSON dict object.
Definition json_dict.c:260
bool nyx_dict_set(nyx_dict_t *object, STR_t key, void *value)
Sets a JSON object in the provided JSON dict object.
Definition json_dict.c:178
bool nyx_dict_iterate(nyx_dict_iter_t *iter, STR_t *key, nyx_object_t **object)
Iterates over a JSON dict object.
Definition json_dict.c:136
str_t nyx_dict_to_string(const nyx_dict_t *object)
Returns a string representing the provided JSON dict object.
Definition json_dict.c:275
nyx_object_t * nyx_dict_get(const nyx_dict_t *object, STR_t key)
Gets the JSON object of the provided key.
Definition json_dict.c:159
void nyx_dict_del(nyx_dict_t *object, STR_t key)
Deletes the entry of the provided key.
Definition json_dict.c:91
void nyx_dict_clear(nyx_dict_t *object)
Clears the content of the provided JSON dict object.
Definition json_dict.c:84
nyx_dict_t * nyx_dict_new(void)
Allocates a new JSON dict object.
Definition json_dict.c:20
Struct describing a JSON dict iterator.
Definition nyx_node.h:1112
Struct describing a JSON dict object.
#define NYX_LOG_FATAL(fmt,...)
Logs a fatal message.
Definition nyx_node.h:208
#define NYX_LOG_ERROR(fmt,...)
Logs an error message.
Definition nyx_node.h:219
#define STR_t
Alias for const char *.
Definition nyx_node.h:71
__NYX_NULLABLE__ buff_t nyx_memory_alloc(__NYX_ZEROABLE__ size_t size)
Similar to libc malloc except that a memory overflow causes the node to stop.
__NYX_ZEROABLE__ size_t nyx_memory_free(__NYX_NULLABLE__ buff_t buff)
Similar to libc free except that it returns the amount of memory freed.
#define str_t
Alias for char *.
Definition nyx_node.h:70
@ NYX_TYPE_DICT
Dict object.
Definition nyx_node.h:438
Struct describing a JSON object.