Coverage Report

Created: 2026-06-10 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupd/fwupd-json-array.c
Line
Count
Source
1
/*
2
 * Copyright 2025 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
#include "config.h"
8
9
#include "fwupd-error.h"
10
#include "fwupd-json-array-private.h"
11
#include "fwupd-json-common-private.h"
12
#include "fwupd-json-node-private.h"
13
#include "fwupd-json-object-private.h"
14
15
/**
16
 * FwupdJsonArray:
17
 *
18
 * A JSON array.
19
 *
20
 * See also: [struct@FwupdJsonObject] [struct@FwupdJsonNode]
21
 */
22
23
struct FwupdJsonArray {
24
  grefcount refcount;
25
  GPtrArray *nodes; /* of FwupdJsonNode */
26
};
27
28
/**
29
 * fwupd_json_array_new: (skip):
30
 *
31
 * Creates a new JSON array.
32
 *
33
 * Returns: (transfer full): a #FwupdJsonArray
34
 *
35
 * Since: 2.1.1
36
 **/
37
FwupdJsonArray *
38
fwupd_json_array_new(void)
39
10.9k
{
40
10.9k
  FwupdJsonArray *self = g_new0(FwupdJsonArray, 1);
41
10.9k
  g_ref_count_init(&self->refcount);
42
10.9k
  self->nodes = g_ptr_array_new_with_free_func((GDestroyNotify)fwupd_json_node_unref);
43
10.9k
  return self;
44
10.9k
}
45
46
/**
47
 * fwupd_json_array_ref: (skip):
48
 * @self: a #FwupdJsonArray
49
 *
50
 * Increases the reference count of a JSON array.
51
 *
52
 * Returns: (transfer full): a #FwupdJsonArray
53
 *
54
 * Since: 2.1.1
55
 **/
56
FwupdJsonArray *
57
fwupd_json_array_ref(FwupdJsonArray *self)
58
15.1k
{
59
15.1k
  g_return_val_if_fail(self != NULL, NULL);
60
15.1k
  g_ref_count_inc(&self->refcount);
61
15.1k
  return self;
62
15.1k
}
63
64
/**
65
 * fwupd_json_array_unref: (skip):
66
 * @self: a #FwupdJsonArray
67
 *
68
 * Decreases the reference count of a JSON array.
69
 *
70
 * Returns: (transfer none): a #FwupdJsonArray, or %NULL
71
 *
72
 * Since: 2.1.1
73
 **/
74
FwupdJsonArray *
75
fwupd_json_array_unref(FwupdJsonArray *self)
76
26.1k
{
77
26.1k
  g_return_val_if_fail(self != NULL, NULL);
78
26.1k
  if (!g_ref_count_dec(&self->refcount))
79
15.1k
    return self;
80
10.9k
  g_ptr_array_unref(self->nodes);
81
10.9k
  g_free(self);
82
10.9k
  return NULL;
83
26.1k
}
84
85
/**
86
 * fwupd_json_array_get_size:
87
 * @self: a #FwupdJsonArray
88
 *
89
 * Gets the size of the JSON array.
90
 *
91
 * Returns: number of elements added
92
 *
93
 * Since: 2.1.1
94
 **/
95
guint
96
fwupd_json_array_get_size(FwupdJsonArray *self)
97
20.7k
{
98
20.7k
  g_return_val_if_fail(self != NULL, G_MAXUINT);
99
20.7k
  return self->nodes->len;
100
20.7k
}
101
102
/**
103
 * fwupd_json_array_get_node: (skip):
104
 * @self: a #FwupdJsonArray
105
 * @idx: index into the array
106
 * @error: (nullable): optional return location for an error
107
 *
108
 * Gets a node from a JSON array.
109
 *
110
 * Returns: (transfer full): a #FwupdJsonObject, or %NULL for error
111
 *
112
 * Since: 2.1.1
113
 **/
114
FwupdJsonNode *
115
fwupd_json_array_get_node(FwupdJsonArray *self, guint idx, GError **error)
116
0
{
117
0
  g_return_val_if_fail(self != NULL, NULL);
118
0
  g_return_val_if_fail(error == NULL || *error == NULL, NULL);
119
120
  /* sanity check */
121
0
  if (idx >= self->nodes->len) {
122
0
    g_set_error(error,
123
0
          FWUPD_ERROR,
124
0
          FWUPD_ERROR_NOT_FOUND,
125
0
          "index %u is larger than array size",
126
0
          idx);
127
0
    return NULL;
128
0
  }
129
0
  return fwupd_json_node_ref(g_ptr_array_index(self->nodes, idx));
130
0
}
131
132
/**
133
 * fwupd_json_array_get_raw: (skip):
134
 * @self: a #FwupdJsonArray
135
 * @idx: index into the array
136
 * @error: (nullable): optional return location for an error
137
 *
138
 * Gets a raw value from a JSON array.
139
 *
140
 * Returns: a string, or %NULL for error
141
 *
142
 * Since: 2.1.1
143
 **/
144
GRefString *
145
fwupd_json_array_get_raw(FwupdJsonArray *self, guint idx, GError **error)
146
0
{
147
0
  g_autoptr(FwupdJsonNode) json_node = NULL;
148
149
0
  g_return_val_if_fail(self != NULL, NULL);
150
0
  g_return_val_if_fail(error == NULL || *error == NULL, NULL);
151
152
0
  json_node = fwupd_json_array_get_node(self, idx, error);
153
0
  if (json_node == NULL)
154
0
    return NULL;
155
0
  return fwupd_json_node_get_raw(json_node, error);
156
0
}
157
158
/**
159
 * fwupd_json_array_get_string: (skip):
160
 * @self: a #FwupdJsonArray
161
 * @idx: index into the array
162
 * @error: (nullable): optional return location for an error
163
 *
164
 * Gets a string from a JSON array.
165
 *
166
 * Returns: a string, or %NULL for error
167
 *
168
 * Since: 2.1.1
169
 **/
170
GRefString *
171
fwupd_json_array_get_string(FwupdJsonArray *self, guint idx, GError **error)
172
0
{
173
0
  g_autoptr(FwupdJsonNode) json_node = NULL;
174
175
0
  g_return_val_if_fail(self != NULL, NULL);
176
0
  g_return_val_if_fail(error == NULL || *error == NULL, NULL);
177
178
0
  json_node = fwupd_json_array_get_node(self, idx, error);
179
0
  if (json_node == NULL)
180
0
    return NULL;
181
0
  return fwupd_json_node_get_string(json_node, error);
182
0
}
183
184
/**
185
 * fwupd_json_array_get_object: (skip):
186
 * @self: a #FwupdJsonArray
187
 * @idx: index into the array
188
 * @error: (nullable): optional return location for an error
189
 *
190
 * Gets an object from a JSON array.
191
 *
192
 * Returns: (transfer full): a #FwupdJsonObject, or %NULL for error
193
 *
194
 * Since: 2.1.1
195
 **/
196
FwupdJsonObject *
197
fwupd_json_array_get_object(FwupdJsonArray *self, guint idx, GError **error)
198
0
{
199
0
  g_autoptr(FwupdJsonNode) json_node = NULL;
200
201
0
  g_return_val_if_fail(self != NULL, NULL);
202
0
  g_return_val_if_fail(error == NULL || *error == NULL, NULL);
203
204
0
  json_node = fwupd_json_array_get_node(self, idx, error);
205
0
  if (json_node == NULL)
206
0
    return NULL;
207
0
  return fwupd_json_node_get_object(json_node, error);
208
0
}
209
210
/**
211
 * fwupd_json_array_get_array: (skip):
212
 * @self: a #FwupdJsonArray
213
 * @idx: index into the array
214
 * @error: (nullable): optional return location for an error
215
 *
216
 * Gets another array from a JSON array.
217
 *
218
 * Returns: (transfer full): a #FwupdJsonArray, or %NULL for error
219
 *
220
 * Since: 2.1.1
221
 **/
222
FwupdJsonArray *
223
fwupd_json_array_get_array(FwupdJsonArray *self, guint idx, GError **error)
224
0
{
225
0
  g_autoptr(FwupdJsonNode) json_node = NULL;
226
227
0
  g_return_val_if_fail(self != NULL, NULL);
228
0
  g_return_val_if_fail(error == NULL || *error == NULL, NULL);
229
230
0
  json_node = fwupd_json_array_get_node(self, idx, error);
231
0
  if (json_node == NULL)
232
0
    return NULL;
233
0
  return fwupd_json_node_get_array(json_node, error);
234
0
}
235
236
void
237
fwupd_json_array_add_string_internal(FwupdJsonArray *self, GRefString *value)
238
3.10k
{
239
3.10k
  g_ptr_array_add(self->nodes, fwupd_json_node_new_string_internal(value));
240
3.10k
}
241
242
/**
243
 * fwupd_json_array_add_node:
244
 * @self: a #FwupdJsonArray
245
 * @json_node: (not nullable): string value
246
 *
247
 * Adds a node to a JSON array.
248
 *
249
 * Since: 2.1.1
250
 **/
251
void
252
fwupd_json_array_add_node(FwupdJsonArray *self, FwupdJsonNode *json_node)
253
0
{
254
0
  g_return_if_fail(self != NULL);
255
0
  g_return_if_fail(json_node != NULL);
256
0
  g_ptr_array_add(self->nodes, fwupd_json_node_ref(json_node));
257
0
}
258
259
/**
260
 * fwupd_json_array_add_string:
261
 * @self: a #FwupdJsonArray
262
 * @value: (not nullable): string value
263
 *
264
 * Adds a string to a JSON array.
265
 *
266
 * Since: 2.1.1
267
 **/
268
void
269
fwupd_json_array_add_string(FwupdJsonArray *self, const gchar *value)
270
0
{
271
0
  g_return_if_fail(self != NULL);
272
0
  g_return_if_fail(value != NULL);
273
0
  g_ptr_array_add(self->nodes, fwupd_json_node_new_string(value));
274
0
}
275
276
void
277
fwupd_json_array_add_raw_internal(FwupdJsonArray *self, GRefString *value)
278
5.84k
{
279
5.84k
  g_ptr_array_add(self->nodes, fwupd_json_node_new_raw_internal(value));
280
5.84k
}
281
282
/**
283
 * fwupd_json_array_add_raw:
284
 * @self: a #FwupdJsonArray
285
 * @value: (not nullable): string value
286
 *
287
 * Adds a raw value to a JSON array.
288
 *
289
 * Since: 2.1.1
290
 **/
291
void
292
fwupd_json_array_add_raw(FwupdJsonArray *self, const gchar *value)
293
0
{
294
0
  g_return_if_fail(self != NULL);
295
0
  g_return_if_fail(value != NULL);
296
0
  g_ptr_array_add(self->nodes, fwupd_json_node_new_raw(value));
297
0
}
298
299
/**
300
 * fwupd_json_array_add_object:
301
 * @self: a #FwupdJsonArray
302
 * @json_obj: a #FwupdJsonObject
303
 *
304
 * Adds an object to a JSON array.
305
 *
306
 * Since: 2.1.1
307
 **/
308
void
309
fwupd_json_array_add_object(FwupdJsonArray *self, FwupdJsonObject *json_obj)
310
3.97k
{
311
3.97k
  g_return_if_fail(self != NULL);
312
3.97k
  g_return_if_fail(json_obj != NULL);
313
3.97k
  g_ptr_array_add(self->nodes, fwupd_json_node_new_object(json_obj));
314
3.97k
}
315
316
/**
317
 * fwupd_json_array_add_array:
318
 * @self: a #FwupdJsonArray
319
 * @json_arr: a #FwupdJsonArray
320
 *
321
 * Adds a different array to a JSON array.
322
 *
323
 * Since: 2.1.1
324
 **/
325
void
326
fwupd_json_array_add_array(FwupdJsonArray *self, FwupdJsonArray *json_arr)
327
7.86k
{
328
7.86k
  g_return_if_fail(self != NULL);
329
7.86k
  g_return_if_fail(json_arr != NULL);
330
7.86k
  g_return_if_fail(self != json_arr);
331
7.86k
  g_ptr_array_add(self->nodes, fwupd_json_node_new_array(json_arr));
332
7.86k
}
333
334
/**
335
 * fwupd_json_array_add_bytes:
336
 * @self: a #FwupdJsonArray
337
 * @value: (not nullable): string value
338
 *
339
 * Adds bytes to a JSON array. They will be base64 encoded as a string.
340
 *
341
 * Since: 2.1.1
342
 **/
343
void
344
fwupd_json_array_add_bytes(FwupdJsonArray *self, GBytes *value)
345
0
{
346
0
  g_autofree gchar *b64data = NULL;
347
0
  const guint8 *buf;
348
0
  gsize bufsz = 0;
349
350
0
  g_return_if_fail(self != NULL);
351
0
  g_return_if_fail(value != NULL);
352
353
0
  buf = g_bytes_get_data(value, &bufsz);
354
0
  if (buf == NULL) {
355
0
    g_ptr_array_add(self->nodes, fwupd_json_node_new_string(""));
356
0
    return;
357
0
  }
358
  /* nocheck:blocked */
359
0
  b64data = g_base64_encode(buf, bufsz);
360
361
0
  g_ptr_array_add(self->nodes, fwupd_json_node_new_string(b64data));
362
0
}
363
364
/**
365
 * fwupd_json_array_append_string:
366
 * @self: a #FwupdJsonArray
367
 * @str: a #GString
368
 * @depth: current depth, where 0 is the root json_node
369
 * @flags: some #FwupdJsonExportFlags e.g. #FWUPD_JSON_EXPORT_FLAG_INDENT
370
 *
371
 * Appends the JSON array to existing string.
372
 *
373
 * Since: 2.1.1
374
 **/
375
void
376
fwupd_json_array_append_string(FwupdJsonArray *self,
377
             GString *str,
378
             guint depth,
379
             FwupdJsonExportFlags flags)
380
4.76k
{
381
4.76k
  g_return_if_fail(self != NULL);
382
4.76k
  g_return_if_fail(str != NULL);
383
384
  /* start */
385
4.76k
  g_string_append_c(str, '[');
386
4.76k
  if (flags & FWUPD_JSON_EXPORT_FLAG_INDENT)
387
0
    g_string_append_c(str, '\n');
388
389
16.6k
  for (guint i = 0; i < self->nodes->len; i++) {
390
11.8k
    FwupdJsonNode *json_node = g_ptr_array_index(self->nodes, i);
391
11.8k
    if (flags & FWUPD_JSON_EXPORT_FLAG_INDENT)
392
0
      fwupd_json_indent(str, depth + 1);
393
11.8k
    fwupd_json_node_append_string(json_node, str, depth + 1, flags);
394
11.8k
    if (flags & FWUPD_JSON_EXPORT_FLAG_INDENT) {
395
0
      if (i != self->nodes->len - 1)
396
0
        g_string_append_c(str, ',');
397
0
      g_string_append_c(str, '\n');
398
11.8k
    } else {
399
11.8k
      if (i != self->nodes->len - 1)
400
8.79k
        g_string_append(str, ", ");
401
11.8k
    }
402
11.8k
  }
403
404
  /* end */
405
4.76k
  if (flags & FWUPD_JSON_EXPORT_FLAG_INDENT)
406
0
    fwupd_json_indent(str, depth);
407
4.76k
  g_string_append_c(str, ']');
408
4.76k
}
409
410
/**
411
 * fwupd_json_array_to_string:
412
 * @self: a #FwupdJsonArray
413
 * @flags: some #FwupdJsonExportFlags e.g. #FWUPD_JSON_EXPORT_FLAG_INDENT
414
 *
415
 * Converts the JSON array to a string representation.
416
 *
417
 * Returns: (transfer full): a #GString
418
 *
419
 * Since: 2.1.1
420
 **/
421
GString *
422
fwupd_json_array_to_string(FwupdJsonArray *self, FwupdJsonExportFlags flags)
423
0
{
424
  GString *str = g_string_new(NULL);
425
0
  fwupd_json_array_append_string(self, str, 0, flags);
426
0
  return str;
427
0
}