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