Nyx Node
Loading...
Searching...
No Matches
string_builder.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
14typedef struct nyx_string_builder_node_s
15{
16 size_t len;
17
18 uint32_t flags;
19
20 struct nyx_string_builder_node_s *next;
21
22} node_t;
23
24/*--------------------------------------------------------------------------------------------------------------------*/
25
26nyx_string_builder_t *nyx_string_builder_new()
27{
28 /*----------------------------------------------------------------------------------------------------------------*/
29
30 nyx_string_builder_t *sb = nyx_memory_alloc(sizeof(nyx_string_builder_t));
31
32 /*----------------------------------------------------------------------------------------------------------------*/
33
34 sb->head = NULL;
35 sb->tail = NULL;
36
37 /*----------------------------------------------------------------------------------------------------------------*/
38
39 return sb;
40}
41
42/*--------------------------------------------------------------------------------------------------------------------*/
43
44void nyx_string_builder_free(nyx_string_builder_t *sb)
45{
46 nyx_string_builder_clear(sb);
47
49}
50
51/*--------------------------------------------------------------------------------------------------------------------*/
52
53void nyx_string_builder_clear(nyx_string_builder_t *sb)
54{
55 /*----------------------------------------------------------------------------------------------------------------*/
56
57 for(node_t *node = sb->head; node != NULL;)
58 {
59 /*------------------------------------------------------------------------------------------------------------*/
60
61 node_t *temp = node;
62
63 node = node->next;
64
65 /*------------------------------------------------------------------------------------------------------------*/
66
67 nyx_memory_free(temp);
68
69 /*------------------------------------------------------------------------------------------------------------*/
70 }
71
72 /*----------------------------------------------------------------------------------------------------------------*/
73
74 sb->head = NULL;
75 sb->tail = NULL;
76
77 /*----------------------------------------------------------------------------------------------------------------*/
78}
79
80/*--------------------------------------------------------------------------------------------------------------------*/
81
82void nyx_string_builder_append_buff(nyx_string_builder_t *sb, uint32_t flags, size_t len, STR_t str)
83{
84 /*----------------------------------------------------------------------------------------------------------------*/
85
86 node_t *node = nyx_memory_alloc(sizeof(node_t) + len + 1);
87
88 memcpy((str_t) (node + 1), str, len);
89
90 /*----------------------------------------------------------------------------------------------------------------*/
91
92 node->len = len;
93 node->flags = flags;
94 node->next = NULL;
95
96 /*----------------------------------------------------------------------------------------------------------------*/
97
98 if(sb->head == NULL)
99 {
100 sb->head = node;
101 sb->tail = node;
102 }
103 else
104 {
105 sb->tail->next = node;
106 sb->tail /*-*/ = node;
107 }
108
109 /*----------------------------------------------------------------------------------------------------------------*/
110}
111
112/*--------------------------------------------------------------------------------------------------------------------*/
113
114void nyx_string_builder_append_n(nyx_string_builder_t *sb, uint32_t flags, STR_t args[], size_t n)
115{
116 for(size_t i = 0; i < n; i++)
117 {
118 STR_t str = args[i];
119
120 if(str == NULL)
121 {
122 nyx_string_builder_append_buff(sb, NYX_SB_NO_ESCAPE, 6, "(null)");
123 }
124 else
125 {
126 nyx_string_builder_append_buff(sb, flags, strlen(str), str);
127 }
128 }
129}
130
131/*--------------------------------------------------------------------------------------------------------------------*/
132
133size_t nyx_string_builder_length(const nyx_string_builder_t *sb)
134{
135 size_t result = 0;
136
137 /*----------------------------------------------------------------------------------------------------------------*/
138
139 for(node_t *node = sb->head; node != NULL; node = node->next)
140 {
141 str_t q = (str_t) (node + 1);
142
143 size_t len = node->len;
144
145 if((node->flags & NYX_SB_ESCAPE_JSON) != 0)
146 {
147 if((node->flags & NYX_SB_ESCAPE_XML) != 0)
148 {
149 /*----------------------------------------------------------------------------------------------------*/
150
151 for(; len > 0; len--)
152 {
153 switch(*q++)
154 {
155 case '<':
156 case '>':
157 result += 4;
158 break;
159
160 case '&':
161 result += 5;
162 break;
163
164 case '\"':
165 case '\'':
166 result += 6;
167 break;
168
169 case '\\':
170 case '\b':
171 case '\f':
172 case '\n':
173 case '\r':
174 case '\t':
175 result += 2;
176 break;
177
178 default:
179 result += 1;
180 break;
181 }
182 }
183
184 /*----------------------------------------------------------------------------------------------------*/
185 }
186 else
187 {
188 /*----------------------------------------------------------------------------------------------------*/
189
190 for(; len > 0; len--)
191 {
192 switch(*q++)
193 {
194 case '\"':
195 case '\\':
196 case '\b':
197 case '\f':
198 case '\n':
199 case '\r':
200 case '\t':
201 result += 2;
202 break;
203
204 default:
205 result += 1;
206 break;
207 }
208 }
209
210 /*----------------------------------------------------------------------------------------------------*/
211 }
212 }
213 else
214 {
215 if((node->flags & NYX_SB_ESCAPE_XML) != 0)
216 {
217 /*----------------------------------------------------------------------------------------------------*/
218
219 for(; len > 0; len--)
220 {
221 switch(*q++)
222 {
223 case '<':
224 case '>':
225 result += 4;
226 break;
227
228 case '&':
229 result += 5;
230 break;
231
232 case '\"':
233 case '\'':
234 result += 6;
235 break;
236
237 default:
238 result += 1;
239 break;
240 }
241 }
242 }
243 else
244 {
245 /*----------------------------------------------------------------------------------------------------*/
246
247 result += len;
248
249 /*----------------------------------------------------------------------------------------------------*/
250 }
251 }
252 }
253
254 /*----------------------------------------------------------------------------------------------------------------*/
255
256 return result;
257}
258
259/*--------------------------------------------------------------------------------------------------------------------*/
260
261str_t nyx_string_builder_to_string(const nyx_string_builder_t *sb)
262{
263 /*----------------------------------------------------------------------------------------------------------------*/
264
265 str_t result = nyx_memory_alloc(nyx_string_builder_length(sb) + 1), /* NOSONAR */ *p = result;
266
267 /*----------------------------------------------------------------------------------------------------------------*/
268
269 char c;
270
271 for(node_t *node = sb->head; node != NULL; node = node->next)
272 {
273 str_t q = (str_t) (node + 1);
274
275 size_t len = node->len;
276
277 if((node->flags & NYX_SB_ESCAPE_JSON) != 0)
278 {
279 if((node->flags & NYX_SB_ESCAPE_XML) != 0)
280 {
281 /*----------------------------------------------------------------------------------------------------*/
282
283 for(; len > 0; len--)
284 {
285 switch(c = *q++)
286 {
287 case '<':
288 *p++ = '&'; *p++ = 'l'; *p++ = 't'; *p++ = ';'; break;
289
290 case '>':
291 *p++ = '&'; *p++ = 'g'; *p++ = 't'; *p++ = ';'; break;
292
293 case '&':
294 *p++ = '&'; *p++ = 'a'; *p++ = 'm'; *p++ = 'p'; *p++ = ';'; break;
295
296 case '\"':
297 *p++ = '&'; *p++ = 'q'; *p++ = 'u'; *p++ = 'o'; *p++ = 't'; *p++ = ';'; break;
298
299 case '\'':
300 *p++ = '&'; *p++ = 'a'; *p++ = 'p'; *p++ = 'o'; *p++ = 's'; *p++ = ';'; break;
301
302 case '\\': *p++ = '\\'; *p++ = '\\'; break;
303 case '\b': *p++ = '\\'; *p++ = 'b'; break;
304 case '\f': *p++ = '\\'; *p++ = 'f'; break;
305 case '\n': *p++ = '\\'; *p++ = 'n'; break;
306 case '\r': *p++ = '\\'; *p++ = 'r'; break;
307 case '\t': *p++ = '\\'; *p++ = 't'; break;
308
309 default:
310 *p++ = c;
311 break;
312 }
313 }
314
315 /*----------------------------------------------------------------------------------------------------*/
316 }
317 else
318 {
319 /*----------------------------------------------------------------------------------------------------*/
320
321 for(; len > 0; len--)
322 {
323 switch(c = *q++)
324 {
325 case '\"': *p++ = '\\'; *p++ = '\"'; break;
326 case '\\': *p++ = '\\'; *p++ = '\\'; break;
327 case '\b': *p++ = '\\'; *p++ = 'b'; break;
328 case '\f': *p++ = '\\'; *p++ = 'f'; break;
329 case '\n': *p++ = '\\'; *p++ = 'n'; break;
330 case '\r': *p++ = '\\'; *p++ = 'r'; break;
331 case '\t': *p++ = '\\'; *p++ = 't'; break;
332
333 default:
334 *p++ = c;
335 break;
336 }
337 }
338
339 /*----------------------------------------------------------------------------------------------------*/
340 }
341 }
342 else
343 {
344 if((node->flags & NYX_SB_ESCAPE_XML) != 0)
345 {
346 /*----------------------------------------------------------------------------------------------------*/
347
348 for(; len > 0; len--)
349 {
350 switch(c = *q++)
351 {
352 case '<':
353 *p++ = '&'; *p++ = 'l'; *p++ = 't'; *p++ = ';'; break;
354
355 case '>':
356 *p++ = '&'; *p++ = 'g'; *p++ = 't'; *p++ = ';'; break;
357
358 case '&':
359 *p++ = '&'; *p++ = 'a'; *p++ = 'm'; *p++ = 'p'; *p++ = ';'; break;
360
361 case '\"':
362 *p++ = '&'; *p++ = 'q'; *p++ = 'u'; *p++ = 'o'; *p++ = 't'; *p++ = ';'; break;
363
364 case '\'':
365 *p++ = '&'; *p++ = 'a'; *p++ = 'p'; *p++ = 'o'; *p++ = 's'; *p++ = ';'; break;
366
367 default:
368 *p++ = c;
369 break;
370 }
371 }
372
373 /*----------------------------------------------------------------------------------------------------*/
374 }
375 else
376 {
377 /*----------------------------------------------------------------------------------------------------*/
378
379 p = (str_t) memcpy(p, q, len) + len;
380
381 /*----------------------------------------------------------------------------------------------------*/
382 }
383 }
384 }
385
386 /*----------------------------------------------------------------------------------------------------------------*/
387
388 *p = '\0';
389
390 /*----------------------------------------------------------------------------------------------------------------*/
391
392 return result;
393}
394
395/*--------------------------------------------------------------------------------------------------------------------*/
#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