]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - Ventoy2Disk/Ventoy2Disk/VentoyJson.c
Update issue_template.yml
[Ventoy.git] / Ventoy2Disk / Ventoy2Disk / VentoyJson.c
1 /******************************************************************************
2 * VentoyJson.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 #ifdef FOR_VTOY_JSON_CHECK
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #else
26 #include <Windows.h>
27 #include "Ventoy2Disk.h"
28 #endif
29
30 #include "VentoyJson.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 Log("Failed to parse json number %s.", 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 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 Log("Invalid string %s.", pcData);
127 return JSON_FAILED;
128 }
129
130 *ppcEnd = pcPos + 1;
131 uiLen = (UINT32)(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 Log("Failed to parse array child.");
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 Log("Failed to parse array child.");
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 Log("Failed to parse array child.");
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 Log("Failed to parse array child.");
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 Log("Failed to parse array child.");
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 Log("Failed to parse array child.");
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 Log("Invalid json data %u.", (UINT8)(*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 *)malloc(sizeof(VTOY_JSON));
391 if (NULL == pstJson)
392 {
393 return NULL;
394 }
395 memset(pstJson, 0, sizeof(VTOY_JSON));
396 return pstJson;
397 }
398
399 int vtoy_json_parse(VTOY_JSON *pstJson, const char *szJsonData)
400 {
401 UINT32 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 Log("Failed to alloc new buf.");
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 Log("Failed to parse json data start=%p, end=%p", szJsonData, pcEnd);
420 return JSON_FAILED;
421 }
422
423 return JSON_SUCCESS;
424 }
425
426 int vtoy_json_scan_parse
427 (
428 const VTOY_JSON *pstJson,
429 UINT32 uiParseNum,
430 JSON_PARSE *pstJsonParse
431 )
432 {
433 UINT32 i = 0;
434 const VTOY_JSON *pstJsonCur = NULL;
435 JSON_PARSE *pstCurParse = NULL;
436
437 for (pstJsonCur = pstJson; NULL != pstJsonCur; pstJsonCur = pstJsonCur->pstNext)
438 {
439 if ((JSON_TYPE_OBJECT == pstJsonCur->enDataType) ||
440 (JSON_TYPE_ARRAY == pstJsonCur->enDataType))
441 {
442 continue;
443 }
444
445 for (i = 0, pstCurParse = NULL; i < uiParseNum; i++)
446 {
447 if (0 == strcmp(pstJsonParse[i].pcKey, pstJsonCur->pcName))
448 {
449 pstCurParse = pstJsonParse + i;
450 break;
451 }
452 }
453
454 if (NULL == pstCurParse)
455 {
456 continue;
457 }
458
459 switch (pstJsonCur->enDataType)
460 {
461 case JSON_TYPE_NUMBER:
462 {
463 if (sizeof(UINT32) == pstCurParse->uiBufSize)
464 {
465 *(UINT32 *)(pstCurParse->pDataBuf) = (UINT32)pstJsonCur->unData.lValue;
466 }
467 else if (sizeof(UINT16) == pstCurParse->uiBufSize)
468 {
469 *(UINT16 *)(pstCurParse->pDataBuf) = (UINT16)pstJsonCur->unData.lValue;
470 }
471 else if (sizeof(UINT8) == pstCurParse->uiBufSize)
472 {
473 *(UINT8 *)(pstCurParse->pDataBuf) = (UINT8)pstJsonCur->unData.lValue;
474 }
475 else if ((pstCurParse->uiBufSize > sizeof(UINT64)))
476 {
477 sprintf_s((char *)pstCurParse->pDataBuf, pstCurParse->uiBufSize, "%llu",
478 (unsigned long long)(pstJsonCur->unData.lValue));
479 }
480 else
481 {
482 Log("Invalid number data buf size %u.", pstCurParse->uiBufSize);
483 }
484 break;
485 }
486 case JSON_TYPE_STRING:
487 {
488 strcpy_s((char *)pstCurParse->pDataBuf, pstCurParse->uiBufSize, pstJsonCur->unData.pcStrVal);
489 break;
490 }
491 case JSON_TYPE_BOOL:
492 {
493 *(UINT8 *)(pstCurParse->pDataBuf) = (pstJsonCur->unData.lValue) > 0 ? 1 : 0;
494 break;
495 }
496 default :
497 {
498 break;
499 }
500 }
501 }
502
503 return JSON_SUCCESS;
504 }
505
506 int vtoy_json_scan_array
507 (
508 VTOY_JSON *pstJson,
509 const char *szKey,
510 VTOY_JSON **ppstArrayItem
511 )
512 {
513 VTOY_JSON *pstJsonItem = NULL;
514
515 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_ARRAY, szKey);
516 if (NULL == pstJsonItem)
517 {
518 Log("Key %s is not found in json data.", szKey);
519 return JSON_NOT_FOUND;
520 }
521
522 *ppstArrayItem = pstJsonItem;
523
524 return JSON_SUCCESS;
525 }
526
527 int vtoy_json_scan_array_ex
528 (
529 VTOY_JSON *pstJson,
530 const char *szKey,
531 VTOY_JSON **ppstArrayItem
532 )
533 {
534 VTOY_JSON *pstJsonItem = NULL;
535
536 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_ARRAY, szKey);
537 if (NULL == pstJsonItem)
538 {
539 Log("Key %s is not found in json data.", szKey);
540 return JSON_NOT_FOUND;
541 }
542
543 *ppstArrayItem = pstJsonItem->pstChild;
544
545 return JSON_SUCCESS;
546 }
547
548 int vtoy_json_scan_object
549 (
550 VTOY_JSON *pstJson,
551 const char *szKey,
552 VTOY_JSON **ppstObjectItem
553 )
554 {
555 VTOY_JSON *pstJsonItem = NULL;
556
557 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_OBJECT, szKey);
558 if (NULL == pstJsonItem)
559 {
560 Log("Key %s is not found in json data.", szKey);
561 return JSON_NOT_FOUND;
562 }
563
564 *ppstObjectItem = pstJsonItem;
565
566 return JSON_SUCCESS;
567 }
568
569 int vtoy_json_get_int
570 (
571 VTOY_JSON *pstJson,
572 const char *szKey,
573 int *piValue
574 )
575 {
576 VTOY_JSON *pstJsonItem = NULL;
577
578 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
579 if (NULL == pstJsonItem)
580 {
581 Log("Key %s is not found in json data.", szKey);
582 return JSON_NOT_FOUND;
583 }
584
585 *piValue = (int)pstJsonItem->unData.lValue;
586
587 return JSON_SUCCESS;
588 }
589
590 int vtoy_json_get_uint
591 (
592 VTOY_JSON *pstJson,
593 const char *szKey,
594 UINT32 *puiValue
595 )
596 {
597 VTOY_JSON *pstJsonItem = NULL;
598
599 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
600 if (NULL == pstJsonItem)
601 {
602 Log("Key %s is not found in json data.", szKey);
603 return JSON_NOT_FOUND;
604 }
605
606 *puiValue = (UINT32)pstJsonItem->unData.lValue;
607
608 return JSON_SUCCESS;
609 }
610
611 int vtoy_json_get_uint64
612 (
613 VTOY_JSON *pstJson,
614 const char *szKey,
615 UINT64 *pui64Value
616 )
617 {
618 VTOY_JSON *pstJsonItem = NULL;
619
620 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
621 if (NULL == pstJsonItem)
622 {
623 Log("Key %s is not found in json data.", szKey);
624 return JSON_NOT_FOUND;
625 }
626
627 *pui64Value = (UINT64)pstJsonItem->unData.lValue;
628
629 return JSON_SUCCESS;
630 }
631
632 int vtoy_json_get_bool
633 (
634 VTOY_JSON *pstJson,
635 const char *szKey,
636 UINT8 *pbValue
637 )
638 {
639 VTOY_JSON *pstJsonItem = NULL;
640
641 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_BOOL, szKey);
642 if (NULL == pstJsonItem)
643 {
644 Log("Key %s is not found in json data.", szKey);
645 return JSON_NOT_FOUND;
646 }
647
648 *pbValue = pstJsonItem->unData.lValue > 0 ? 1 : 0;
649
650 return JSON_SUCCESS;
651 }
652
653 int vtoy_json_get_string
654 (
655 VTOY_JSON *pstJson,
656 const char *szKey,
657 UINT32 uiBufLen,
658 char *pcBuf
659 )
660 {
661 VTOY_JSON *pstJsonItem = NULL;
662
663 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_STRING, szKey);
664 if (NULL == pstJsonItem)
665 {
666 Log("Key %s is not found in json data.", szKey);
667 return JSON_NOT_FOUND;
668 }
669
670 strcpy_s(pcBuf, uiBufLen, pstJsonItem->unData.pcStrVal);
671
672 return JSON_SUCCESS;
673 }
674
675 const char * vtoy_json_get_string_ex(VTOY_JSON *pstJson, const char *szKey)
676 {
677 VTOY_JSON *pstJsonItem = NULL;
678
679 if ((NULL == pstJson) || (NULL == szKey))
680 {
681 return NULL;
682 }
683
684 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_STRING, szKey);
685 if (NULL == pstJsonItem)
686 {
687 Log("Key %s is not found in json data.", szKey);
688 return NULL;
689 }
690
691 return pstJsonItem->unData.pcStrVal;
692 }
693
694 int vtoy_json_destroy(VTOY_JSON *pstJson)
695 {
696 if (NULL == pstJson)
697 {
698 return JSON_SUCCESS;
699 }
700
701 if (NULL != pstJson->pstChild)
702 {
703 vtoy_json_free(pstJson->pstChild);
704 }
705
706 if (NULL != pstJson->pstNext)
707 {
708 vtoy_json_free(pstJson->pstNext);
709 }
710
711 free(pstJson);
712
713 return JSON_SUCCESS;
714 }
715
716
717 #ifdef FOR_VTOY_JSON_CHECK
718
719 int main(int argc, char**argv)
720 {
721 int ret = 1;
722 int FileSize;
723 FILE *fp;
724 void *Data = NULL;
725 VTOY_JSON *json = NULL;
726
727 fp = fopen(argv[1], "rb");
728 if (!fp)
729 {
730 Log("Failed to open %s\n", argv[1]);
731 goto out;
732 }
733
734 fseek(fp, 0, SEEK_END);
735 FileSize = (int)ftell(fp);
736 fseek(fp, 0, SEEK_SET);
737
738 Data = malloc(FileSize + 4);
739 if (!Data)
740 {
741 Log("Failed to malloc %d\n", FileSize + 4);
742 goto out;
743 }
744 *((char *)Data + FileSize) = 0;
745
746 fread(Data, 1, FileSize, fp);
747
748 json = vtoy_json_create();
749 if (!json)
750 {
751 Log("Failed vtoy_json_create\n");
752 goto out;
753 }
754
755 if (vtoy_json_parse(json, (char *)Data) != JSON_SUCCESS)
756 {
757 goto out;
758 }
759
760 ret = 0;
761
762 out:
763 if (fp) fclose(fp);
764 if (Data) free(Data);
765 if (json) vtoy_json_destroy(json);
766
767 printf("\n");
768 return ret;
769 }
770
771 #endif