]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - LinuxGUI/Ventoy2Disk/Core/ventoy_json.c
Update languages.json (viva l' ventoy) (#2372)
[Ventoy.git] / LinuxGUI / Ventoy2Disk / Core / ventoy_json.c
1 /******************************************************************************
2 * ventoy_json.c
3 *
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdint.h>
24 #include <string.h>
25 #include <stdarg.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <linux/limits.h>
30 #include <ventoy_define.h>
31 #include <ventoy_util.h>
32 #include <ventoy_json.h>
33
34 static void vtoy_json_free(VTOY_JSON *pstJsonHead)
35 {
36 VTOY_JSON *pstNext = NULL;
37
38 while (NULL != pstJsonHead)
39 {
40 pstNext = pstJsonHead->pstNext;
41 if ((pstJsonHead->enDataType < JSON_TYPE_BUTT) && (NULL != pstJsonHead->pstChild))
42 {
43 vtoy_json_free(pstJsonHead->pstChild);
44 }
45
46 free(pstJsonHead);
47 pstJsonHead = pstNext;
48 }
49
50 return;
51 }
52
53 static char *vtoy_json_skip(const char *pcData)
54 {
55 while ((NULL != pcData) && ('\0' != *pcData) && (*pcData <= 32))
56 {
57 pcData++;
58 }
59
60 return (char *)pcData;
61 }
62
63 VTOY_JSON *vtoy_json_find_item
64 (
65 VTOY_JSON *pstJson,
66 JSON_TYPE enDataType,
67 const char *szKey
68 )
69 {
70 while (NULL != pstJson)
71 {
72 if ((enDataType == pstJson->enDataType) &&
73 (0 == strcmp(szKey, pstJson->pcName)))
74 {
75 return pstJson;
76 }
77 pstJson = pstJson->pstNext;
78 }
79
80 return NULL;
81 }
82
83 static int vtoy_json_parse_number
84 (
85 VTOY_JSON *pstJson,
86 const char *pcData,
87 const char **ppcEnd
88 )
89 {
90 unsigned long Value;
91
92 Value = strtoul(pcData, (char **)ppcEnd, 10);
93 if (*ppcEnd == pcData)
94 {
95 vdebug("Failed to parse json number %s.\n", pcData);
96 return JSON_FAILED;
97 }
98
99 pstJson->enDataType = JSON_TYPE_NUMBER;
100 pstJson->unData.lValue = Value;
101
102 return JSON_SUCCESS;
103 }
104
105 static int vtoy_json_parse_string
106 (
107 char *pcNewStart,
108 char *pcRawStart,
109 VTOY_JSON *pstJson,
110 const char *pcData,
111 const char **ppcEnd
112 )
113 {
114 uint32_t uiLen = 0;
115 const char *pcPos = NULL;
116 const char *pcTmp = pcData + 1;
117
118 *ppcEnd = pcData;
119
120 if ('\"' != *pcData)
121 {
122 return JSON_FAILED;
123 }
124
125 pcPos = strchr(pcTmp, '\"');
126 if ((NULL == pcPos) || (pcPos < pcTmp))
127 {
128 vdebug("Invalid string %s.\n", pcData);
129 return JSON_FAILED;
130 }
131
132 *ppcEnd = pcPos + 1;
133 uiLen = (uint32_t)(unsigned long)(pcPos - pcTmp);
134
135 pstJson->enDataType = JSON_TYPE_STRING;
136 pstJson->unData.pcStrVal = pcNewStart + (pcTmp - pcRawStart);
137 pstJson->unData.pcStrVal[uiLen] = '\0';
138
139 return JSON_SUCCESS;
140 }
141
142 static int vtoy_json_parse_array
143 (
144 char *pcNewStart,
145 char *pcRawStart,
146 VTOY_JSON *pstJson,
147 const char *pcData,
148 const char **ppcEnd
149 )
150 {
151 int Ret = JSON_SUCCESS;
152 VTOY_JSON *pstJsonChild = NULL;
153 VTOY_JSON *pstJsonItem = NULL;
154 const char *pcTmp = pcData + 1;
155
156 *ppcEnd = pcData;
157 pstJson->enDataType = JSON_TYPE_ARRAY;
158
159 if ('[' != *pcData)
160 {
161 return JSON_FAILED;
162 }
163
164 pcTmp = vtoy_json_skip(pcTmp);
165
166 if (']' == *pcTmp)
167 {
168 *ppcEnd = pcTmp + 1;
169 return JSON_SUCCESS;
170 }
171
172 JSON_NEW_ITEM(pstJson->pstChild, JSON_FAILED);
173
174 Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJson->pstChild, pcTmp, ppcEnd);
175 if (JSON_SUCCESS != Ret)
176 {
177 vdebug("Failed to parse array child.\n");
178 return JSON_FAILED;
179 }
180
181 pstJsonChild = pstJson->pstChild;
182 pcTmp = vtoy_json_skip(*ppcEnd);
183 while ((NULL != pcTmp) && (',' == *pcTmp))
184 {
185 JSON_NEW_ITEM(pstJsonItem, JSON_FAILED);
186 pstJsonChild->pstNext = pstJsonItem;
187 pstJsonItem->pstPrev = pstJsonChild;
188 pstJsonChild = pstJsonItem;
189
190 Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
191 if (JSON_SUCCESS != Ret)
192 {
193 vdebug("Failed to parse array child.\n");
194 return JSON_FAILED;
195 }
196 pcTmp = vtoy_json_skip(*ppcEnd);
197 }
198
199 if ((NULL != pcTmp) && (']' == *pcTmp))
200 {
201 *ppcEnd = pcTmp + 1;
202 return JSON_SUCCESS;
203 }
204 else
205 {
206 *ppcEnd = pcTmp;
207 return JSON_FAILED;
208 }
209 }
210
211 static int vtoy_json_parse_object
212 (
213 char *pcNewStart,
214 char *pcRawStart,
215 VTOY_JSON *pstJson,
216 const char *pcData,
217 const char **ppcEnd
218 )
219 {
220 int Ret = JSON_SUCCESS;
221 VTOY_JSON *pstJsonChild = NULL;
222 VTOY_JSON *pstJsonItem = NULL;
223 const char *pcTmp = pcData + 1;
224
225 *ppcEnd = pcData;
226 pstJson->enDataType = JSON_TYPE_OBJECT;
227
228 if ('{' != *pcData)
229 {
230 return JSON_FAILED;
231 }
232
233 pcTmp = vtoy_json_skip(pcTmp);
234 if ('}' == *pcTmp)
235 {
236 *ppcEnd = pcTmp + 1;
237 return JSON_SUCCESS;
238 }
239
240 JSON_NEW_ITEM(pstJson->pstChild, JSON_FAILED);
241
242 Ret = vtoy_json_parse_string(pcNewStart, pcRawStart, pstJson->pstChild, pcTmp, ppcEnd);
243 if (JSON_SUCCESS != Ret)
244 {
245 vdebug("Failed to parse array child.\n");
246 return JSON_FAILED;
247 }
248
249 pstJsonChild = pstJson->pstChild;
250 pstJsonChild->pcName = pstJsonChild->unData.pcStrVal;
251 pstJsonChild->unData.pcStrVal = NULL;
252
253 pcTmp = vtoy_json_skip(*ppcEnd);
254 if ((NULL == pcTmp) || (':' != *pcTmp))
255 {
256 *ppcEnd = pcTmp;
257 return JSON_FAILED;
258 }
259
260 Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
261 if (JSON_SUCCESS != Ret)
262 {
263 vdebug("Failed to parse array child.\n");
264 return JSON_FAILED;
265 }
266
267 pcTmp = vtoy_json_skip(*ppcEnd);
268 while ((NULL != pcTmp) && (',' == *pcTmp))
269 {
270 JSON_NEW_ITEM(pstJsonItem, JSON_FAILED);
271 pstJsonChild->pstNext = pstJsonItem;
272 pstJsonItem->pstPrev = pstJsonChild;
273 pstJsonChild = pstJsonItem;
274
275 Ret = vtoy_json_parse_string(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
276 if (JSON_SUCCESS != Ret)
277 {
278 vdebug("Failed to parse array child.\n");
279 return JSON_FAILED;
280 }
281
282 pcTmp = vtoy_json_skip(*ppcEnd);
283 pstJsonChild->pcName = pstJsonChild->unData.pcStrVal;
284 pstJsonChild->unData.pcStrVal = NULL;
285 if ((NULL == pcTmp) || (':' != *pcTmp))
286 {
287 *ppcEnd = pcTmp;
288 return JSON_FAILED;
289 }
290
291 Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
292 if (JSON_SUCCESS != Ret)
293 {
294 vdebug("Failed to parse array child.\n");
295 return JSON_FAILED;
296 }
297
298 pcTmp = vtoy_json_skip(*ppcEnd);
299 }
300
301 if ((NULL != pcTmp) && ('}' == *pcTmp))
302 {
303 *ppcEnd = pcTmp + 1;
304 return JSON_SUCCESS;
305 }
306 else
307 {
308 *ppcEnd = pcTmp;
309 return JSON_FAILED;
310 }
311 }
312
313 int vtoy_json_parse_value
314 (
315 char *pcNewStart,
316 char *pcRawStart,
317 VTOY_JSON *pstJson,
318 const char *pcData,
319 const char **ppcEnd
320 )
321 {
322 pcData = vtoy_json_skip(pcData);
323
324 switch (*pcData)
325 {
326 case 'n':
327 {
328 if (0 == strncmp(pcData, "null", 4))
329 {
330 pstJson->enDataType = JSON_TYPE_NULL;
331 *ppcEnd = pcData + 4;
332 return JSON_SUCCESS;
333 }
334 break;
335 }
336 case 'f':
337 {
338 if (0 == strncmp(pcData, "false", 5))
339 {
340 pstJson->enDataType = JSON_TYPE_BOOL;
341 pstJson->unData.lValue = 0;
342 *ppcEnd = pcData + 5;
343 return JSON_SUCCESS;
344 }
345 break;
346 }
347 case 't':
348 {
349 if (0 == strncmp(pcData, "true", 4))
350 {
351 pstJson->enDataType = JSON_TYPE_BOOL;
352 pstJson->unData.lValue = 1;
353 *ppcEnd = pcData + 4;
354 return JSON_SUCCESS;
355 }
356 break;
357 }
358 case '\"':
359 {
360 return vtoy_json_parse_string(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd);
361 }
362 case '[':
363 {
364 return vtoy_json_parse_array(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd);
365 }
366 case '{':
367 {
368 return vtoy_json_parse_object(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd);
369 }
370 case '-':
371 {
372 return vtoy_json_parse_number(pstJson, pcData, ppcEnd);
373 }
374 default :
375 {
376 if (*pcData >= '0' && *pcData <= '9')
377 {
378 return vtoy_json_parse_number(pstJson, pcData, ppcEnd);
379 }
380 }
381 }
382
383 *ppcEnd = pcData;
384 vdebug("Invalid json data %u.\n", (uint8_t)(*pcData));
385 return JSON_FAILED;
386 }
387
388 VTOY_JSON * vtoy_json_create(void)
389 {
390 VTOY_JSON *pstJson = NULL;
391
392 pstJson = (VTOY_JSON *)zalloc(sizeof(VTOY_JSON));
393 if (NULL == pstJson)
394 {
395 return NULL;
396 }
397
398 return pstJson;
399 }
400
401 int vtoy_json_parse(VTOY_JSON *pstJson, const char *szJsonData)
402 {
403 uint32_t uiMemSize = 0;
404 int Ret = JSON_SUCCESS;
405 char *pcNewBuf = NULL;
406 const char *pcEnd = NULL;
407
408 uiMemSize = strlen(szJsonData) + 1;
409 pcNewBuf = (char *)malloc(uiMemSize);
410 if (NULL == pcNewBuf)
411 {
412 vdebug("Failed to alloc new buf.\n");
413 return JSON_FAILED;
414 }
415 memcpy(pcNewBuf, szJsonData, uiMemSize);
416 pcNewBuf[uiMemSize - 1] = 0;
417
418 Ret = vtoy_json_parse_value(pcNewBuf, (char *)szJsonData, pstJson, szJsonData, &pcEnd);
419 if (JSON_SUCCESS != Ret)
420 {
421 vdebug("Failed to parse json data %s start=%p, end=%p:%s.\n",
422 szJsonData, szJsonData, pcEnd, pcEnd);
423 return JSON_FAILED;
424 }
425
426 return JSON_SUCCESS;
427 }
428
429 int vtoy_json_scan_parse
430 (
431 const VTOY_JSON *pstJson,
432 uint32_t uiParseNum,
433 VTOY_JSON_PARSE_S *pstJsonParse
434 )
435 {
436 uint32_t i = 0;
437 const VTOY_JSON *pstJsonCur = NULL;
438 VTOY_JSON_PARSE_S *pstCurParse = NULL;
439
440 for (pstJsonCur = pstJson; NULL != pstJsonCur; pstJsonCur = pstJsonCur->pstNext)
441 {
442 if ((JSON_TYPE_OBJECT == pstJsonCur->enDataType) ||
443 (JSON_TYPE_ARRAY == pstJsonCur->enDataType))
444 {
445 continue;
446 }
447
448 for (i = 0, pstCurParse = NULL; i < uiParseNum; i++)
449 {
450 if (0 == strcmp(pstJsonParse[i].pcKey, pstJsonCur->pcName))
451 {
452 pstCurParse = pstJsonParse + i;
453 break;
454 }
455 }
456
457 if (NULL == pstCurParse)
458 {
459 continue;
460 }
461
462 switch (pstJsonCur->enDataType)
463 {
464 case JSON_TYPE_NUMBER:
465 {
466 if (sizeof(uint32_t) == pstCurParse->uiBufSize)
467 {
468 *(uint32_t *)(pstCurParse->pDataBuf) = (uint32_t)pstJsonCur->unData.lValue;
469 }
470 else if (sizeof(uint16_t) == pstCurParse->uiBufSize)
471 {
472 *(uint16_t *)(pstCurParse->pDataBuf) = (uint16_t)pstJsonCur->unData.lValue;
473 }
474 else if (sizeof(uint8_t) == pstCurParse->uiBufSize)
475 {
476 *(uint8_t *)(pstCurParse->pDataBuf) = (uint8_t)pstJsonCur->unData.lValue;
477 }
478 else if ((pstCurParse->uiBufSize > sizeof(uint64_t)))
479 {
480 snprintf((char *)pstCurParse->pDataBuf, pstCurParse->uiBufSize, "%llu",
481 (unsigned long long)(pstJsonCur->unData.lValue));
482 }
483 else
484 {
485 vdebug("Invalid number data buf size %u.\n", pstCurParse->uiBufSize);
486 }
487 break;
488 }
489 case JSON_TYPE_STRING:
490 {
491 strncpy((char *)pstCurParse->pDataBuf, pstJsonCur->unData.pcStrVal, pstCurParse->uiBufSize);
492 break;
493 }
494 case JSON_TYPE_BOOL:
495 {
496 *(uint8_t *)(pstCurParse->pDataBuf) = (pstJsonCur->unData.lValue) > 0 ? 1 : 0;
497 break;
498 }
499 default :
500 {
501 break;
502 }
503 }
504 }
505
506 return JSON_SUCCESS;
507 }
508
509 int vtoy_json_scan_array
510 (
511 VTOY_JSON *pstJson,
512 const char *szKey,
513 VTOY_JSON **ppstArrayItem
514 )
515 {
516 VTOY_JSON *pstJsonItem = NULL;
517
518 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_ARRAY, szKey);
519 if (NULL == pstJsonItem)
520 {
521 vdebug("Key %s is not found in json data.\n", szKey);
522 return JSON_NOT_FOUND;
523 }
524
525 *ppstArrayItem = pstJsonItem;
526
527 return JSON_SUCCESS;
528 }
529
530 int vtoy_json_scan_array_ex
531 (
532 VTOY_JSON *pstJson,
533 const char *szKey,
534 VTOY_JSON **ppstArrayItem
535 )
536 {
537 VTOY_JSON *pstJsonItem = NULL;
538
539 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_ARRAY, szKey);
540 if (NULL == pstJsonItem)
541 {
542 vdebug("Key %s is not found in json data.\n", szKey);
543 return JSON_NOT_FOUND;
544 }
545
546 *ppstArrayItem = pstJsonItem->pstChild;
547
548 return JSON_SUCCESS;
549 }
550
551 int vtoy_json_scan_object
552 (
553 VTOY_JSON *pstJson,
554 const char *szKey,
555 VTOY_JSON **ppstObjectItem
556 )
557 {
558 VTOY_JSON *pstJsonItem = NULL;
559
560 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_OBJECT, szKey);
561 if (NULL == pstJsonItem)
562 {
563 vdebug("Key %s is not found in json data.\n", szKey);
564 return JSON_NOT_FOUND;
565 }
566
567 *ppstObjectItem = pstJsonItem;
568
569 return JSON_SUCCESS;
570 }
571
572 int vtoy_json_get_int
573 (
574 VTOY_JSON *pstJson,
575 const char *szKey,
576 int *piValue
577 )
578 {
579 VTOY_JSON *pstJsonItem = NULL;
580
581 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
582 if (NULL == pstJsonItem)
583 {
584 vdebug("Key %s is not found in json data.\n", szKey);
585 return JSON_NOT_FOUND;
586 }
587
588 *piValue = (int)pstJsonItem->unData.lValue;
589
590 return JSON_SUCCESS;
591 }
592
593 int vtoy_json_get_uint
594 (
595 VTOY_JSON *pstJson,
596 const char *szKey,
597 uint32_t *puiValue
598 )
599 {
600 VTOY_JSON *pstJsonItem = NULL;
601
602 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
603 if (NULL == pstJsonItem)
604 {
605 vdebug("Key %s is not found in json data.\n", szKey);
606 return JSON_NOT_FOUND;
607 }
608
609 *puiValue = (uint32_t)pstJsonItem->unData.lValue;
610
611 return JSON_SUCCESS;
612 }
613
614 int vtoy_json_get_uint64
615 (
616 VTOY_JSON *pstJson,
617 const char *szKey,
618 uint64_t *pui64Value
619 )
620 {
621 VTOY_JSON *pstJsonItem = NULL;
622
623 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
624 if (NULL == pstJsonItem)
625 {
626 vdebug("Key %s is not found in json data.\n", szKey);
627 return JSON_NOT_FOUND;
628 }
629
630 *pui64Value = (uint64_t)pstJsonItem->unData.lValue;
631
632 return JSON_SUCCESS;
633 }
634
635 int vtoy_json_get_bool
636 (
637 VTOY_JSON *pstJson,
638 const char *szKey,
639 uint8_t *pbValue
640 )
641 {
642 VTOY_JSON *pstJsonItem = NULL;
643
644 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_BOOL, szKey);
645 if (NULL == pstJsonItem)
646 {
647 vdebug("Key %s is not found in json data.\n", szKey);
648 return JSON_NOT_FOUND;
649 }
650
651 *pbValue = pstJsonItem->unData.lValue > 0 ? 1 : 0;
652
653 return JSON_SUCCESS;
654 }
655
656 int vtoy_json_get_string
657 (
658 VTOY_JSON *pstJson,
659 const char *szKey,
660 uint32_t uiBufLen,
661 char *pcBuf
662 )
663 {
664 VTOY_JSON *pstJsonItem = NULL;
665
666 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_STRING, szKey);
667 if (NULL == pstJsonItem)
668 {
669 vdebug("Key %s is not found in json data.\n", szKey);
670 return JSON_NOT_FOUND;
671 }
672
673 strncpy(pcBuf, pstJsonItem->unData.pcStrVal, uiBufLen);
674
675 return JSON_SUCCESS;
676 }
677
678 const char * vtoy_json_get_string_ex(VTOY_JSON *pstJson, const char *szKey)
679 {
680 VTOY_JSON *pstJsonItem = NULL;
681
682 if ((NULL == pstJson) || (NULL == szKey))
683 {
684 return NULL;
685 }
686
687 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_STRING, szKey);
688 if (NULL == pstJsonItem)
689 {
690 vdebug("Key %s is not found in json data.\n", szKey);
691 return NULL;
692 }
693
694 return pstJsonItem->unData.pcStrVal;
695 }
696
697 int vtoy_json_destroy(VTOY_JSON *pstJson)
698 {
699 if (NULL == pstJson)
700 {
701 return JSON_SUCCESS;
702 }
703
704 if (NULL != pstJson->pstChild)
705 {
706 vtoy_json_free(pstJson->pstChild);
707 }
708
709 if (NULL != pstJson->pstNext)
710 {
711 vtoy_json_free(pstJson->pstNext);
712 }
713
714 free(pstJson);
715
716 return JSON_SUCCESS;
717 }
718