xref: /freebsd/contrib/pkgconf/cli/spdxtool/serialize.h (revision 592efe252472a3385acf36b1f49ecf710a7f3d9c)
1 /*
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  *​ Copyright (c) 2025 The FreeBSD Foundation
5  *​
6  *​ Portions of this software were developed by
7  * Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from
8  * the FreeBSD Foundation
9  *​
10  *​ Copyright (C) 2026 Elizabeth Ashford.
11  */
12 
13 #include <stdlib.h>
14 #include <string.h>
15 #include "util.h"
16 
17 #ifndef CLI__SPDXTOOL__SERIALIZE_H
18 #define CLI__SPDXTOOL__SERIALIZE_H
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 typedef enum spdxtool_serialize_type_
25 {
26 	SPDXTOOL_SERIALIZE_TYPE_STRING, // JSON string type
27 	SPDXTOOL_SERIALIZE_TYPE_INT, // JSON number type (int)
28 	SPDXTOOL_SERIALIZE_TYPE_BOOL, // JSON bool type
29 	SPDXTOOL_SERIALIZE_TYPE_NULL, // JSON null type
30 	SPDXTOOL_SERIALIZE_TYPE_OBJECT, // JSON object type
31 	SPDXTOOL_SERIALIZE_TYPE_ARRAY // JSON array type
32 } spdxtool_serialize_type_t;
33 
34 typedef struct spdxtool_serialize_value_ {
35 	spdxtool_serialize_type_t type;
36 	union {
37 		char *s;
38 		int i;
39 		bool b;
40 		struct spdxtool_serialize_object_list_ *o;
41 		struct spdxtool_serialize_array_ *a;
42 	} value;
43 } spdxtool_serialize_value_t;
44 
45 typedef struct spdxtool_serialize_object_ {
46 	char *key;
47 	spdxtool_serialize_value_t *value;
48 } spdxtool_serialize_object_t;
49 
50 typedef struct spdxtool_serialize_object_list_ {
51 	pkgconf_list_t entries;
52 } spdxtool_serialize_object_list_t;
53 
54 typedef struct spdxtool_serialize_array_ {
55 	pkgconf_list_t items;
56 } spdxtool_serialize_array_t;
57 
58 bool
59 spdxtool_serialize_value_to_buf(pkgconf_buffer_t *buffer, spdxtool_serialize_value_t *value, unsigned int indent);
60 
61 spdxtool_serialize_value_t *
62 spdxtool_serialize_value_dup(const spdxtool_serialize_value_t *value);
63 
64 spdxtool_serialize_value_t *
65 spdxtool_serialize_object_add_take(spdxtool_serialize_object_list_t *object_list, const char *key, spdxtool_serialize_value_t* value);
66 
67 spdxtool_serialize_object_list_t *
68 spdxtool_serialize_object_list_new(void);
69 
70 spdxtool_serialize_array_t *
71 spdxtool_serialize_array_new(void);
72 
73 spdxtool_serialize_value_t *
74 spdxtool_serialize_array_add_take(spdxtool_serialize_array_t *array, spdxtool_serialize_value_t* value);
75 
76 void
77 spdxtool_serialize_value_free(spdxtool_serialize_value_t *value);
78 
79 void
80 spdxtool_serialize_object_list_free(spdxtool_serialize_object_list_t *object_list);
81 
82 void
83 spdxtool_serialize_object_free(spdxtool_serialize_object_t *object);
84 
85 void
86 spdxtool_serialize_array_free(spdxtool_serialize_array_t *array);
87 
88 /*
89  * !doc
90  *
91  * .. c:function:: spdxtool_serialize_value_t * spdxtool_serialize_value_string(const char *s)
92  *
93  *    Construct a JSON string value. The string is copied internally.
94  *    If this return value is not stolen, it must be freed with spdxtool_serialize_value_free().
95  *
96  *    :param const char *s: String to copy. May be NULL, in which case the value holds NULL.
97  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_STRING.
98  */
99 static inline spdxtool_serialize_value_t *
spdxtool_serialize_value_string(const char * s)100 spdxtool_serialize_value_string(const char *s)
101 {
102 	if (!s)
103 		return NULL;
104 
105 	char *sv = strdup(s);
106 	if (!sv)
107 		return NULL;
108 
109 	spdxtool_serialize_value_t *value = calloc(1, sizeof(spdxtool_serialize_value_t));
110 	if (!value)
111 	{
112 		free(sv);
113 		return NULL;
114 	}
115 
116 	value->type = SPDXTOOL_SERIALIZE_TYPE_STRING;
117 	value->value.s = sv;
118 	return value;
119 }
120 
121 /*
122  * !doc
123  *
124  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_value_int(int d)
125  *
126  *    Construct a JSON integer value.
127  *    If this return value is not stolen, it must be freed with spdxtool_serialize_value_free().
128  *
129  *    :param int d: int value.
130  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_INT.
131  */
132 static inline spdxtool_serialize_value_t *
spdxtool_serialize_value_int(int i)133 spdxtool_serialize_value_int(int i)
134 {
135 	spdxtool_serialize_value_t *value = calloc(1, sizeof(spdxtool_serialize_value_t));
136 	if (!value)
137 		return NULL;
138 
139 	value->type = SPDXTOOL_SERIALIZE_TYPE_INT;
140 	value->value.i = i;
141 	return value;
142 }
143 
144 /*
145  * !doc
146  *
147  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_value_bool(bool b)
148  *
149  *    Construct a JSON boolean value.
150  *    If this return value is not stolen, it must be freed with spdxtool_serialize_value_free().
151  *
152  *    :param bool b: Boolean value.
153  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_BOOL.
154  */
155 static inline spdxtool_serialize_value_t *
spdxtool_serialize_value_bool(bool b)156 spdxtool_serialize_value_bool(bool b)
157 {
158 	spdxtool_serialize_value_t *value = calloc(1, sizeof(spdxtool_serialize_value_t));
159 	if (!value)
160 		return NULL;
161 
162 	value->type = SPDXTOOL_SERIALIZE_TYPE_BOOL;
163 	value->value.b = b;
164 	return value;
165 }
166 
167 /*
168  * !doc
169  *
170  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_value_null(void)
171  *
172  *    Construct a JSON null value.
173  *    If this return value is not stolen, it must be freed with spdxtool_serialize_value_free().
174  *
175  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_NULL.
176  */
177 static inline spdxtool_serialize_value_t *
spdxtool_serialize_value_null(void)178 spdxtool_serialize_value_null(void)
179 {
180 	spdxtool_serialize_value_t *value = calloc(1, sizeof(spdxtool_serialize_value_t));
181 	if (!value)
182 		return NULL;
183 
184 	value->type = SPDXTOOL_SERIALIZE_TYPE_NULL;
185 	return value;
186 }
187 
188 
189 /*
190  * !doc
191  *
192  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_value_object(spdxtool_serialize_object_list_t *object_list)
193  *
194  *    Construct a JSON object value wrapping an existing object list.
195  *    The returned value takes ownership of the object list.
196  *    If this return value is not stolen, it must be freed with spdxtool_serialize_value_free().
197  *
198  *    :param spdxtool_serialize_object_list_t *object_list: Object list to wrap. Ownership transfers to the returned value.
199  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_OBJECT.
200  */
201 static inline spdxtool_serialize_value_t *
spdxtool_serialize_value_object(spdxtool_serialize_object_list_t * object_list)202 spdxtool_serialize_value_object(spdxtool_serialize_object_list_t *object_list)
203 {
204 	spdxtool_serialize_value_t *value = calloc(1, sizeof(spdxtool_serialize_value_t));
205 	if (!value)
206 	{
207 		spdxtool_serialize_object_list_free(object_list);
208 		return NULL;
209 	}
210 
211 	value->type = SPDXTOOL_SERIALIZE_TYPE_OBJECT;
212 	value->value.o = object_list;
213 	return value;
214 }
215 
216 /*
217  * !doc
218  *
219  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_value_array(spdxtool_serialize_array_t *array)
220  *
221  *    Construct a JSON array value wrapping an existing array.
222  *    The returned value takes ownership of the array.
223  *    If this return value is not stolen, it must be freed with spdxtool_serialize_value_free().
224  *
225  *    :param spdxtool_serialize_array_t *array: Array to wrap. Ownership transfers to the returned value.
226  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_ARRAY.
227  */
228 static inline spdxtool_serialize_value_t *
spdxtool_serialize_value_array(spdxtool_serialize_array_t * array)229 spdxtool_serialize_value_array(spdxtool_serialize_array_t *array)
230 {
231 	spdxtool_serialize_value_t *value = calloc(1, sizeof(spdxtool_serialize_value_t));
232 	if (!value)
233 	{
234 		spdxtool_serialize_array_free(array);
235 		return NULL;
236 	}
237 
238 	value->type = SPDXTOOL_SERIALIZE_TYPE_ARRAY;
239 	value->value.a = array;
240 	return value;
241 }
242 
243 /*
244  * !doc
245  *
246  * .. c:function:: void spdxtool_serialize_object_add_string(spdxtool_serialize_object_list_t *object_list, const char *key, const char *value)
247  *
248  *    Add a string key-value pair to a JSON object. The string is copied internally.
249  *    Unconditionally adds the key even if value is NULL.
250  *
251  *    :param spdxtool_serialize_object_list_t *object_list: Object list to add to.
252  *    :param const char *key: Key string.
253  *    :param const char *value: String value to copy.
254  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_STRING, located in the object.
255  *             This object is not owned by the caller.
256  */
257 static inline spdxtool_serialize_value_t *
spdxtool_serialize_object_add_string(spdxtool_serialize_object_list_t * object_list,const char * key,const char * value)258 spdxtool_serialize_object_add_string(spdxtool_serialize_object_list_t *object_list, const char *key, const char *value)
259 {
260 	return spdxtool_serialize_object_add_take(object_list, key, spdxtool_serialize_value_string(value));
261 }
262 
263 /*
264  * !doc
265  *
266  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_object_add_string_opt(spdxtool_serialize_object_list_t *object_list, const char *key, const char *value)
267  *
268  *    Add a string key-value pair to a JSON object only if value is non-NULL.
269  *    Use this for optional fields that should be omitted entirely when absent.
270  *
271  *    :param spdxtool_serialize_object_list_t *object_list: Object list to add to.
272  *    :param const char *key: Key string.
273  *    :param const char *value: String value to copy, or NULL to skip.
274  *    :return: If value is set: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_STRING, located in the object.
275  *             This object is not owned by the caller.
276  *             If value is not set: NULL.
277  */
278 static inline spdxtool_serialize_value_t *
spdxtool_serialize_object_add_string_opt(spdxtool_serialize_object_list_t * object_list,const char * key,const char * value)279 spdxtool_serialize_object_add_string_opt(spdxtool_serialize_object_list_t *object_list, const char *key, const char *value)
280 {
281 	if (value)
282 		return spdxtool_serialize_object_add_take(object_list, key, spdxtool_serialize_value_string(value));
283 
284 	return NULL;
285 }
286 
287 /*
288  * !doc
289  *
290  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_object_add_int(spdxtool_serialize_object_list_t *object_list, const char *key, int value)
291  *
292  *    Add a int key-value pair to a JSON object.
293  *
294  *    :param spdxtool_serialize_object_list_t *object_list: Object list to add to.
295  *    :param const char *key: Key string.
296  *    :param int value: Integer value.
297  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_INT, located in the object.
298  *             This object is not owned by the caller.
299  */
300 static inline spdxtool_serialize_value_t *
spdxtool_serialize_object_add_int(spdxtool_serialize_object_list_t * object_list,const char * key,int value)301 spdxtool_serialize_object_add_int(spdxtool_serialize_object_list_t *object_list, const char *key, int value)
302 {
303 	return spdxtool_serialize_object_add_take(object_list, key, spdxtool_serialize_value_int(value));
304 }
305 
306 /*
307  * !doc
308  *
309  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_object_add_bool(spdxtool_serialize_object_list_t *object_list, const char *key, bool value)
310  *
311  *    Add a boolean key-value pair to a JSON object.
312  *
313  *    :param spdxtool_serialize_object_list_t *object_list: Object list to add to.
314  *    :param const char *key: Key string.
315  *    :param bool value: Boolean value.
316  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_BOOL, located in the object.
317  *             This object is not owned by the caller.
318  */
319 static inline spdxtool_serialize_value_t *
spdxtool_serialize_object_add_bool(spdxtool_serialize_object_list_t * object_list,const char * key,bool value)320 spdxtool_serialize_object_add_bool(spdxtool_serialize_object_list_t *object_list, const char *key, bool value)
321 {
322 	return spdxtool_serialize_object_add_take(object_list, key, spdxtool_serialize_value_bool(value));
323 }
324 
325 /*
326  * !doc
327  *
328  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_object_add_null(spdxtool_serialize_object_list_t *object_list, const char *key)
329  *
330  *    Add a null key-value pair to a JSON object.
331  *
332  *    :param spdxtool_serialize_object_list_t *object_list: Object list to add to.
333  *    :param const char *key: Key string.
334  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_NULL, located in the object.
335  *             This object is not owned by the caller.
336  */
337 static inline spdxtool_serialize_value_t *
spdxtool_serialize_object_add_null(spdxtool_serialize_object_list_t * object_list,const char * key)338 spdxtool_serialize_object_add_null(spdxtool_serialize_object_list_t *object_list, const char *key)
339 {
340 	return spdxtool_serialize_object_add_take(object_list, key, spdxtool_serialize_value_null());
341 }
342 
343 /*
344  * !doc
345  *
346  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_object_add_object(spdxtool_serialize_object_list_t *object_list, const char *key, spdxtool_serialize_object_list_t *value)
347  *
348  *    Add an object key-value pair to a JSON object.
349  *    This takes ownership of the object in value unconditionally, freeing on failure.
350  *
351  *    :param spdxtool_serialize_object_list_t *object_list: Object list to add to.
352  *    :param const char *key: Key string.
353  *    :param spdxtool_serialize_object_list_t *value: Object value to add.
354  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_OBJECT, located in the object.
355  *             This object is not owned by the caller.
356  */
357 static inline spdxtool_serialize_value_t *
spdxtool_serialize_object_add_object(spdxtool_serialize_object_list_t * object_list,const char * key,spdxtool_serialize_object_list_t * value)358 spdxtool_serialize_object_add_object(spdxtool_serialize_object_list_t *object_list, const char *key, spdxtool_serialize_object_list_t *value)
359 {
360 	return spdxtool_serialize_object_add_take(object_list, key, spdxtool_serialize_value_object(value));
361 }
362 
363 /*
364  * !doc
365  *
366  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_object_add_array(spdxtool_serialize_object_list_t *object_list, const char *key, spdxtool_serialize_array_t *value)
367  *
368  *    Add an array key-value pair to a JSON object.
369  *    This takes ownership of the array in value unconditionally, freeing on failure.
370  *
371  *    :param spdxtool_serialize_object_list_t *object_list: Object list to add to.
372  *    :param const char *key: Key string.
373  *    :param spdxtool_serialize_array_t *value: Array value to add.
374  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_ARRAY, located in the object.
375  *             This object is not owned by the caller.
376  */
377 static inline spdxtool_serialize_value_t *
spdxtool_serialize_object_add_array(spdxtool_serialize_object_list_t * object_list,const char * key,spdxtool_serialize_array_t * value)378 spdxtool_serialize_object_add_array(spdxtool_serialize_object_list_t *object_list, const char *key, spdxtool_serialize_array_t *value)
379 {
380 	return spdxtool_serialize_object_add_take(object_list, key, spdxtool_serialize_value_array(value));
381 }
382 
383 /*
384  * !doc
385  *
386  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_array_add_string(spdxtool_serialize_array_t *array, const char *value)
387  *
388  *    Append a string value to a JSON array. The string is copied internally.
389  *    Unconditionally appends even if value is NULL.
390  *
391  *    :param spdxtool_serialize_array_t *array: Array to append to.
392  *    :param const char *value: String value to copy.
393  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_STRING, located in the array.
394  *             This object is not owned by the caller.
395  */
396 static inline spdxtool_serialize_value_t *
spdxtool_serialize_array_add_string(spdxtool_serialize_array_t * array,const char * value)397 spdxtool_serialize_array_add_string(spdxtool_serialize_array_t *array, const char *value)
398 {
399 	return spdxtool_serialize_array_add_take(array, spdxtool_serialize_value_string(value));
400 }
401 
402 /*
403  * !doc
404  *
405  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_array_add_string_opt(spdxtool_serialize_array_t *a, const char *value)
406  *
407  *    Append a string value to a JSON array only if value is non-NULL.
408  *    Use this for optional array entries that should be omitted when absent.
409  *
410  *    :param spdxtool_serialize_array_t *a: Array to append to.
411  *    :param const char *value: String value to copy, or NULL to skip.
412  *    :return: If value is set: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_STRING, located in the array.
413  *             This object is not owned by the caller.
414  *             If value is not set: NULL.
415  */
416 static inline spdxtool_serialize_value_t *
spdxtool_serialize_array_add_string_opt(spdxtool_serialize_array_t * array,const char * value)417 spdxtool_serialize_array_add_string_opt(spdxtool_serialize_array_t *array, const char *value)
418 {
419 	if (value)
420 		return spdxtool_serialize_array_add_take(array, spdxtool_serialize_value_string(value));
421 
422 	return NULL;
423 }
424 
425 /*
426  * !doc
427  *
428  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_array_add_int(spdxtool_serialize_array_t *array, int value)
429  *
430  *    Append a int value to a JSON array.
431  *
432  *    :param spdxtool_serialize_array_t *array: Array to append to.
433  *    :param int value: integer value.
434  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_INT, located in the array.
435  *             This object is not owned by the caller.
436  */
437 static inline spdxtool_serialize_value_t *
spdxtool_serialize_array_add_int(spdxtool_serialize_array_t * array,int value)438 spdxtool_serialize_array_add_int(spdxtool_serialize_array_t *array, int value)
439 {
440 	return spdxtool_serialize_array_add_take(array, spdxtool_serialize_value_int(value));
441 }
442 
443 /*
444  * !doc
445  *
446  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_array_add_bool(spdxtool_serialize_array_t *array, bool value)
447  *
448  *    Append a boolean value to a JSON array.
449  *
450  *    :param spdxtool_serialize_array_t *array: Array to append to.
451  *    :param bool value: Boolean value.
452  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_BOOL, located in the array.
453  *             This object is not owned by the caller.
454  */
455 static inline spdxtool_serialize_value_t *
spdxtool_serialize_array_add_bool(spdxtool_serialize_array_t * array,bool value)456 spdxtool_serialize_array_add_bool(spdxtool_serialize_array_t *array, bool value)
457 {
458 	return spdxtool_serialize_array_add_take(array, spdxtool_serialize_value_bool(value));
459 }
460 
461 /*
462  * !doc
463  *
464  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_array_add_null(spdxtool_serialize_array_t *array)
465  *
466  *    Append a null value to a JSON array.
467  *
468  *    :param spdxtool_serialize_array_t *array: Array to append to.
469  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_NULL, located in the array.
470  *             This object is not owned by the caller.
471  */
472 static inline spdxtool_serialize_value_t *
spdxtool_serialize_array_add_null(spdxtool_serialize_array_t * array)473 spdxtool_serialize_array_add_null(spdxtool_serialize_array_t *array)
474 {
475 	return spdxtool_serialize_array_add_take(array, spdxtool_serialize_value_null());
476 }
477 
478 /*
479  * !doc
480  *
481  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_array_add_object(spdxtool_serialize_array_t *array, spdxtool_serialize_object_list_t *value)
482  *
483  *    Append an object value to a JSON array.
484  *    This takes ownership of the object in value unconditionally, freeing on failure.
485  *
486  *    :param spdxtool_serialize_array_t *array: Array to append to.
487  *    :param spdxtool_serialize_object_list_t *value: Object value.
488  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_OBJECT, located in the array.
489  *             This object is not owned by the caller.
490  */
491 static inline spdxtool_serialize_value_t *
spdxtool_serialize_array_add_object(spdxtool_serialize_array_t * array,spdxtool_serialize_object_list_t * value)492 spdxtool_serialize_array_add_object(spdxtool_serialize_array_t *array, spdxtool_serialize_object_list_t *value)
493 {
494 	if (!value)
495 		return NULL;
496 
497 	spdxtool_serialize_value_t *ret = spdxtool_serialize_value_object(value);
498 	if (!ret)
499 	{
500 		// Since we take possession of the pointer unconditionally, clean up.
501 		spdxtool_serialize_object_list_free(value);
502 		return NULL;
503 	}
504 
505 	return spdxtool_serialize_array_add_take(array, ret);
506 }
507 
508 /*
509  * !doc
510  *
511  * .. c:function:: spdxtool_serialize_value_t *spdxtool_serialize_array_add_array(spdxtool_serialize_array_t *array, spdxtool_serialize_array_t *value)
512  *
513  *    Append an array value to a JSON array.
514  *    This takes ownership of the array in value unconditionally, freeing on failure.
515  *
516  *    :param spdxtool_serialize_array_t *array: Array to append to.
517  *    :param spdxtool_serialize_array_t *value: Array value.
518  *    :return: spdxtool_serialize_value_t * of type SPDXTOOL_SERIALIZE_TYPE_ARRAY, located in the array.
519  *             This object is not owned by the caller.
520  */
521 static inline spdxtool_serialize_value_t *
spdxtool_serialize_array_add_array(spdxtool_serialize_array_t * array,spdxtool_serialize_array_t * value)522 spdxtool_serialize_array_add_array(spdxtool_serialize_array_t *array, spdxtool_serialize_array_t *value)
523 {
524 	if (!value)
525 		return NULL;
526 
527 	spdxtool_serialize_value_t *ret = spdxtool_serialize_value_array(value);
528 	if (!ret)
529 	{
530 		// Since we take possession of the pointer unconditionally, clean up.
531 		spdxtool_serialize_array_free(value);
532 		return NULL;
533 	}
534 
535 	return spdxtool_serialize_array_add_take(array, ret);
536 }
537 
538 spdxtool_serialize_value_t *
539 spdxtool_serialize_sbom(pkgconf_client_t *client, spdxtool_core_agent_t *agent, spdxtool_core_creation_info_t *creation, spdxtool_core_spdx_document_t *spdx);
540 
541 #ifdef __cplusplus
542 }
543 #endif
544 
545 #endif
546