Coverage Report

Created: 2025-10-10 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/winpr/libwinpr/utils/json/json-c.c
Line
Count
Source
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * JSON parser wrapper
4
 *
5
 * Copyright 2024 Armin Novak <anovak@thincast.com>
6
 * Copyright 2024 Thincast Technologies GmbH
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
#include <math.h>
21
#include <errno.h>
22
23
#include <winpr/file.h>
24
#include <winpr/json.h>
25
#include <winpr/assert.h>
26
27
#if !defined(WITH_JSONC)
28
#error "This file must only be compiled when json-c is enabled"
29
#endif
30
#include <json.h>
31
32
#if JSON_C_MAJOR_VERSION == 0
33
#if JSON_C_MINOR_VERSION < 14
34
static struct json_object* json_object_new_null(void)
35
0
{
36
0
  return NULL;
37
0
}
38
#endif
39
#endif
40
41
int WINPR_JSON_version(char* buffer, size_t len)
42
0
{
43
0
  return _snprintf(buffer, len, "json-c %s", json_c_version());
44
0
}
45
46
WINPR_JSON* WINPR_JSON_Parse(const char* value)
47
0
{
48
0
  return json_tokener_parse(value);
49
0
}
50
51
WINPR_JSON* WINPR_JSON_ParseWithLength(const char* value, size_t buffer_length)
52
0
{
53
0
  WINPR_ASSERT(buffer_length <= INT_MAX);
54
0
  json_tokener* tok = json_tokener_new();
55
0
  if (!tok)
56
0
    return NULL;
57
0
  json_object* obj = json_tokener_parse_ex(tok, value, (int)buffer_length);
58
0
  json_tokener_free(tok);
59
0
  return obj;
60
0
}
61
62
void WINPR_JSON_Delete(WINPR_JSON* item)
63
0
{
64
0
  json_object_put((json_object*)item);
65
0
}
66
67
WINPR_JSON* WINPR_JSON_GetArrayItem(const WINPR_JSON* array, size_t index)
68
0
{
69
0
  return json_object_array_get_idx((const json_object*)array, index);
70
0
}
71
72
size_t WINPR_JSON_GetArraySize(const WINPR_JSON* array)
73
0
{
74
0
  return json_object_array_length((const json_object*)array);
75
0
}
76
77
WINPR_JSON* WINPR_JSON_GetObjectItem(const WINPR_JSON* object, const char* string)
78
0
{
79
0
  struct json_object_iterator it = json_object_iter_begin((const json_object*)object);
80
0
  struct json_object_iterator itEnd = json_object_iter_end((const json_object*)object);
81
0
  while (!json_object_iter_equal(&it, &itEnd))
82
0
  {
83
0
    const char* key = json_object_iter_peek_name(&it);
84
0
    if (_stricmp(key, string) == 0)
85
0
    {
86
0
      return json_object_iter_peek_value(&it);
87
0
    }
88
0
    json_object_iter_next(&it);
89
0
  }
90
0
  return NULL;
91
0
}
92
93
WINPR_JSON* WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON* object, const char* string)
94
0
{
95
0
  return json_object_object_get((const json_object*)object, string);
96
0
}
97
98
BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON* object, const char* string)
99
0
{
100
0
  return json_object_object_get_ex((const json_object*)object, string, NULL);
101
0
}
102
103
const char* WINPR_JSON_GetErrorPtr(void)
104
0
{
105
0
  return json_util_get_last_err();
106
0
}
107
108
const char* WINPR_JSON_GetStringValue(WINPR_JSON* item)
109
0
{
110
0
  return json_object_get_string((json_object*)item);
111
0
}
112
113
double WINPR_JSON_GetNumberValue(const WINPR_JSON* item)
114
0
{
115
0
  return json_object_get_double((const json_object*)item);
116
0
}
117
118
BOOL WINPR_JSON_IsInvalid(const WINPR_JSON* item)
119
0
{
120
0
  if (WINPR_JSON_IsArray(item))
121
0
    return FALSE;
122
0
  if (WINPR_JSON_IsObject(item))
123
0
    return FALSE;
124
0
  if (WINPR_JSON_IsNull(item))
125
0
    return FALSE;
126
0
  if (WINPR_JSON_IsNumber(item))
127
0
    return FALSE;
128
0
  if (WINPR_JSON_IsBool(item))
129
0
    return FALSE;
130
0
  if (WINPR_JSON_IsString(item))
131
0
    return FALSE;
132
0
  return TRUE;
133
0
}
134
135
BOOL WINPR_JSON_IsFalse(const WINPR_JSON* item)
136
0
{
137
0
  if (!json_object_is_type((const json_object*)item, json_type_boolean))
138
0
    return FALSE;
139
0
  json_bool val = json_object_get_boolean((const json_object*)item);
140
0
  return val == 0;
141
0
}
142
143
BOOL WINPR_JSON_IsTrue(const WINPR_JSON* item)
144
0
{
145
0
  if (!json_object_is_type((const json_object*)item, json_type_boolean))
146
0
    return FALSE;
147
0
  json_bool val = json_object_get_boolean((const json_object*)item);
148
0
  return val != 0;
149
0
}
150
151
BOOL WINPR_JSON_IsBool(const WINPR_JSON* item)
152
0
{
153
0
  return json_object_is_type((const json_object*)item, json_type_boolean);
154
0
}
155
156
BOOL WINPR_JSON_IsNull(const WINPR_JSON* item)
157
0
{
158
0
  return json_object_is_type((const json_object*)item, json_type_null);
159
0
}
160
161
BOOL WINPR_JSON_IsNumber(const WINPR_JSON* item)
162
0
{
163
0
  return json_object_is_type((const json_object*)item, json_type_int) ||
164
0
         json_object_is_type((const json_object*)item, json_type_double);
165
0
}
166
167
BOOL WINPR_JSON_IsString(const WINPR_JSON* item)
168
0
{
169
0
  return json_object_is_type((const json_object*)item, json_type_string);
170
0
}
171
172
BOOL WINPR_JSON_IsArray(const WINPR_JSON* item)
173
0
{
174
0
  return json_object_is_type((const json_object*)item, json_type_array);
175
0
}
176
177
BOOL WINPR_JSON_IsObject(const WINPR_JSON* item)
178
0
{
179
0
  return json_object_is_type((const json_object*)item, json_type_object);
180
0
}
181
182
WINPR_JSON* WINPR_JSON_CreateNull(void)
183
0
{
184
0
  return json_object_new_null();
185
0
}
186
187
WINPR_JSON* WINPR_JSON_CreateTrue(void)
188
0
{
189
0
  return json_object_new_boolean(TRUE);
190
0
}
191
192
WINPR_JSON* WINPR_JSON_CreateFalse(void)
193
0
{
194
0
  return json_object_new_boolean(FALSE);
195
0
}
196
197
WINPR_JSON* WINPR_JSON_CreateBool(BOOL boolean)
198
0
{
199
0
  return json_object_new_boolean(boolean);
200
0
}
201
202
WINPR_JSON* WINPR_JSON_CreateNumber(double num)
203
0
{
204
0
  return json_object_new_double(num);
205
0
}
206
207
WINPR_JSON* WINPR_JSON_CreateString(const char* string)
208
0
{
209
0
  return json_object_new_string(string);
210
0
}
211
212
WINPR_JSON* WINPR_JSON_CreateArray(void)
213
0
{
214
0
  return json_object_new_array();
215
0
}
216
217
WINPR_JSON* WINPR_JSON_CreateObject(void)
218
0
{
219
0
  return json_object_new_object();
220
0
}
221
222
WINPR_JSON* WINPR_JSON_AddNullToObject(WINPR_JSON* object, const char* name)
223
0
{
224
0
  struct json_object* obj = json_object_new_null();
225
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
226
0
  {
227
0
    json_object_put(obj);
228
0
    return NULL;
229
0
  }
230
0
  return obj;
231
0
}
232
233
WINPR_JSON* WINPR_JSON_AddTrueToObject(WINPR_JSON* object, const char* name)
234
0
{
235
0
  struct json_object* obj = json_object_new_boolean(TRUE);
236
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
237
0
  {
238
0
    json_object_put(obj);
239
0
    return NULL;
240
0
  }
241
0
  return obj;
242
0
}
243
244
WINPR_JSON* WINPR_JSON_AddFalseToObject(WINPR_JSON* object, const char* name)
245
0
{
246
0
  struct json_object* obj = json_object_new_boolean(FALSE);
247
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
248
0
  {
249
0
    json_object_put(obj);
250
0
    return NULL;
251
0
  }
252
0
  return obj;
253
0
}
254
255
WINPR_JSON* WINPR_JSON_AddBoolToObject(WINPR_JSON* object, const char* name, BOOL boolean)
256
0
{
257
0
  struct json_object* obj = json_object_new_boolean(boolean);
258
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
259
0
  {
260
0
    json_object_put(obj);
261
0
    return NULL;
262
0
  }
263
0
  return obj;
264
0
}
265
266
WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, double number)
267
0
{
268
0
  struct json_object* obj = json_object_new_double(number);
269
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
270
0
  {
271
0
    json_object_put(obj);
272
0
    return NULL;
273
0
  }
274
0
  return obj;
275
0
}
276
277
WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, const char* string)
278
0
{
279
0
  struct json_object* obj = json_object_new_string(string);
280
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
281
0
  {
282
0
    json_object_put(obj);
283
0
    return NULL;
284
0
  }
285
0
  return obj;
286
0
}
287
288
WINPR_JSON* WINPR_JSON_AddObjectToObject(WINPR_JSON* object, const char* name)
289
0
{
290
0
  struct json_object* obj = json_object_new_object();
291
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
292
0
  {
293
0
    json_object_put(obj);
294
0
    return NULL;
295
0
  }
296
0
  return obj;
297
0
}
298
299
BOOL WINPR_JSON_AddItemToArray(WINPR_JSON* array, WINPR_JSON* item)
300
0
{
301
0
  const int rc = json_object_array_add((json_object*)array, (json_object*)item);
302
0
  if (rc != 0)
303
0
    return FALSE;
304
0
  return TRUE;
305
0
}
306
307
WINPR_JSON* WINPR_JSON_AddArrayToObject(WINPR_JSON* object, const char* name)
308
0
{
309
0
  struct json_object* obj = json_object_new_array();
310
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
311
0
  {
312
0
    json_object_put(obj);
313
0
    return NULL;
314
0
  }
315
0
  return obj;
316
0
}
317
318
char* WINPR_JSON_Print(WINPR_JSON* item)
319
0
{
320
0
  const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PRETTY);
321
0
  if (!str)
322
0
    return NULL;
323
0
  return _strdup(str);
324
0
}
325
326
char* WINPR_JSON_PrintUnformatted(WINPR_JSON* item)
327
0
{
328
0
  const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PLAIN);
329
0
  if (!str)
330
0
    return NULL;
331
0
  return _strdup(str);
332
0
}