]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_json.c
b9e4a743490d78548fa4fd509f2c81245cebea6d
1 /******************************************************************************
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
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.
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.
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/>.
20 #include <grub/types.h>
21 #include <grub/misc.h>
25 #include <grub/disk.h>
26 #include <grub/device.h>
27 #include <grub/term.h>
28 #include <grub/partition.h>
29 #include <grub/file.h>
30 #include <grub/normal.h>
31 #include <grub/extcmd.h>
32 #include <grub/datetime.h>
33 #include <grub/i18n.h>
35 #include <grub/time.h>
36 #include <grub/ventoy.h>
37 #include "ventoy_def.h"
39 GRUB_MOD_LICENSE ("GPLv3+");
41 static void json_debug(const char *fmt
, ...)
45 if (g_ventoy_debug
== 0)
51 grub_vprintf (fmt
, args
);
57 static void vtoy_json_free(VTOY_JSON
*pstJsonHead
)
59 VTOY_JSON
*pstNext
= NULL
;
61 while (NULL
!= pstJsonHead
)
63 pstNext
= pstJsonHead
->pstNext
;
64 if ((pstJsonHead
->enDataType
< JSON_TYPE_BUTT
) && (NULL
!= pstJsonHead
->pstChild
))
66 vtoy_json_free(pstJsonHead
->pstChild
);
69 grub_free(pstJsonHead
);
70 pstJsonHead
= pstNext
;
76 static char *vtoy_json_skip(const char *pcData
)
78 while ((NULL
!= pcData
) && ('\0' != *pcData
) && (*pcData
<= 32))
83 return (char *)pcData
;
86 VTOY_JSON
*vtoy_json_find_item
93 while (NULL
!= pstJson
)
95 if ((enDataType
== pstJson
->enDataType
) &&
96 (0 == grub_strcmp(szKey
, pstJson
->pcName
)))
100 pstJson
= pstJson
->pstNext
;
106 static int vtoy_json_parse_number
115 Value
= grub_strtoul(pcData
, (char **)ppcEnd
, 10);
116 if (*ppcEnd
== pcData
)
118 json_debug("Failed to parse json number %s.", pcData
);
122 pstJson
->enDataType
= JSON_TYPE_NUMBER
;
123 pstJson
->unData
.lValue
= Value
;
128 static int vtoy_json_parse_string
137 grub_uint32_t uiLen
= 0;
138 const char *pcPos
= NULL
;
139 const char *pcTmp
= pcData
+ 1;
148 pcPos
= grub_strchr(pcTmp
, '\"');
149 if ((NULL
== pcPos
) || (pcPos
< pcTmp
))
151 json_debug("Invalid string %s.", pcData
);
156 uiLen
= (grub_uint32_t
)(unsigned long)(pcPos
- pcTmp
);
158 pstJson
->enDataType
= JSON_TYPE_STRING
;
159 pstJson
->unData
.pcStrVal
= pcNewStart
+ (pcTmp
- pcRawStart
);
160 pstJson
->unData
.pcStrVal
[uiLen
] = '\0';
165 static int vtoy_json_parse_array
174 int Ret
= JSON_SUCCESS
;
175 VTOY_JSON
*pstJsonChild
= NULL
;
176 VTOY_JSON
*pstJsonItem
= NULL
;
177 const char *pcTmp
= pcData
+ 1;
180 pstJson
->enDataType
= JSON_TYPE_ARRAY
;
187 pcTmp
= vtoy_json_skip(pcTmp
);
195 JSON_NEW_ITEM(pstJson
->pstChild
, JSON_FAILED
);
197 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJson
->pstChild
, pcTmp
, ppcEnd
);
198 if (JSON_SUCCESS
!= Ret
)
200 json_debug("Failed to parse array child.");
204 pstJsonChild
= pstJson
->pstChild
;
205 pcTmp
= vtoy_json_skip(*ppcEnd
);
206 while ((NULL
!= pcTmp
) && (',' == *pcTmp
))
208 JSON_NEW_ITEM(pstJsonItem
, JSON_FAILED
);
209 pstJsonChild
->pstNext
= pstJsonItem
;
210 pstJsonItem
->pstPrev
= pstJsonChild
;
211 pstJsonChild
= pstJsonItem
;
213 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
214 if (JSON_SUCCESS
!= Ret
)
216 json_debug("Failed to parse array child.");
219 pcTmp
= vtoy_json_skip(*ppcEnd
);
222 if ((NULL
!= pcTmp
) && (']' == *pcTmp
))
234 static int vtoy_json_parse_object
243 int Ret
= JSON_SUCCESS
;
244 VTOY_JSON
*pstJsonChild
= NULL
;
245 VTOY_JSON
*pstJsonItem
= NULL
;
246 const char *pcTmp
= pcData
+ 1;
249 pstJson
->enDataType
= JSON_TYPE_OBJECT
;
256 pcTmp
= vtoy_json_skip(pcTmp
);
263 JSON_NEW_ITEM(pstJson
->pstChild
, JSON_FAILED
);
265 Ret
= vtoy_json_parse_string(pcNewStart
, pcRawStart
, pstJson
->pstChild
, pcTmp
, ppcEnd
);
266 if (JSON_SUCCESS
!= Ret
)
268 json_debug("Failed to parse array child.");
272 pstJsonChild
= pstJson
->pstChild
;
273 pstJsonChild
->pcName
= pstJsonChild
->unData
.pcStrVal
;
274 pstJsonChild
->unData
.pcStrVal
= NULL
;
276 pcTmp
= vtoy_json_skip(*ppcEnd
);
277 if ((NULL
== pcTmp
) || (':' != *pcTmp
))
283 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
284 if (JSON_SUCCESS
!= Ret
)
286 json_debug("Failed to parse array child.");
290 pcTmp
= vtoy_json_skip(*ppcEnd
);
291 while ((NULL
!= pcTmp
) && (',' == *pcTmp
))
293 JSON_NEW_ITEM(pstJsonItem
, JSON_FAILED
);
294 pstJsonChild
->pstNext
= pstJsonItem
;
295 pstJsonItem
->pstPrev
= pstJsonChild
;
296 pstJsonChild
= pstJsonItem
;
298 Ret
= vtoy_json_parse_string(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
299 if (JSON_SUCCESS
!= Ret
)
301 json_debug("Failed to parse array child.");
305 pcTmp
= vtoy_json_skip(*ppcEnd
);
306 pstJsonChild
->pcName
= pstJsonChild
->unData
.pcStrVal
;
307 pstJsonChild
->unData
.pcStrVal
= NULL
;
308 if ((NULL
== pcTmp
) || (':' != *pcTmp
))
314 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
315 if (JSON_SUCCESS
!= Ret
)
317 json_debug("Failed to parse array child.");
321 pcTmp
= vtoy_json_skip(*ppcEnd
);
324 if ((NULL
!= pcTmp
) && ('}' == *pcTmp
))
336 int vtoy_json_parse_value
345 pcData
= vtoy_json_skip(pcData
);
351 if (0 == grub_strncmp(pcData
, "null", 4))
353 pstJson
->enDataType
= JSON_TYPE_NULL
;
354 *ppcEnd
= pcData
+ 4;
361 if (0 == grub_strncmp(pcData
, "false", 5))
363 pstJson
->enDataType
= JSON_TYPE_BOOL
;
364 pstJson
->unData
.lValue
= 0;
365 *ppcEnd
= pcData
+ 5;
372 if (0 == grub_strncmp(pcData
, "true", 4))
374 pstJson
->enDataType
= JSON_TYPE_BOOL
;
375 pstJson
->unData
.lValue
= 1;
376 *ppcEnd
= pcData
+ 4;
383 return vtoy_json_parse_string(pcNewStart
, pcRawStart
, pstJson
, pcData
, ppcEnd
);
387 return vtoy_json_parse_array(pcNewStart
, pcRawStart
, pstJson
, pcData
, ppcEnd
);
391 return vtoy_json_parse_object(pcNewStart
, pcRawStart
, pstJson
, pcData
, ppcEnd
);
395 return vtoy_json_parse_number(pstJson
, pcData
, ppcEnd
);
399 if (*pcData
>= '0' && *pcData
<= '9')
401 return vtoy_json_parse_number(pstJson
, pcData
, ppcEnd
);
407 json_debug("Invalid json data %u.", (grub_uint8_t
)(*pcData
));
411 VTOY_JSON
* vtoy_json_create(void)
413 VTOY_JSON
*pstJson
= NULL
;
415 pstJson
= (VTOY_JSON
*)grub_zalloc(sizeof(VTOY_JSON
));
424 int vtoy_json_parse(VTOY_JSON
*pstJson
, const char *szJsonData
)
426 grub_uint32_t uiMemSize
= 0;
427 int Ret
= JSON_SUCCESS
;
428 char *pcNewBuf
= NULL
;
429 const char *pcEnd
= NULL
;
431 uiMemSize
= grub_strlen(szJsonData
) + 1;
432 pcNewBuf
= (char *)grub_malloc(uiMemSize
);
433 if (NULL
== pcNewBuf
)
435 json_debug("Failed to alloc new buf.");
438 grub_memcpy(pcNewBuf
, szJsonData
, uiMemSize
);
439 pcNewBuf
[uiMemSize
- 1] = 0;
441 Ret
= vtoy_json_parse_value(pcNewBuf
, (char *)szJsonData
, pstJson
, szJsonData
, &pcEnd
);
442 if (JSON_SUCCESS
!= Ret
)
444 json_debug("Failed to parse json data %s start=%p, end=%p:%s.",
445 szJsonData
, szJsonData
, pcEnd
, pcEnd
);
452 int vtoy_json_scan_parse
454 const VTOY_JSON
*pstJson
,
455 grub_uint32_t uiParseNum
,
456 JSON_PARSE
*pstJsonParse
460 const VTOY_JSON
*pstJsonCur
= NULL
;
461 JSON_PARSE
*pstCurParse
= NULL
;
463 for (pstJsonCur
= pstJson
; NULL
!= pstJsonCur
; pstJsonCur
= pstJsonCur
->pstNext
)
465 if ((JSON_TYPE_OBJECT
== pstJsonCur
->enDataType
) ||
466 (JSON_TYPE_ARRAY
== pstJsonCur
->enDataType
))
471 for (i
= 0, pstCurParse
= NULL
; i
< uiParseNum
; i
++)
473 if (0 == grub_strcmp(pstJsonParse
[i
].pcKey
, pstJsonCur
->pcName
))
475 pstCurParse
= pstJsonParse
+ i
;
480 if (NULL
== pstCurParse
)
485 switch (pstJsonCur
->enDataType
)
487 case JSON_TYPE_NUMBER
:
489 if (sizeof(grub_uint32_t
) == pstCurParse
->uiBufSize
)
491 *(grub_uint32_t
*)(pstCurParse
->pDataBuf
) = (grub_uint32_t
)pstJsonCur
->unData
.lValue
;
493 else if (sizeof(grub_uint16_t
) == pstCurParse
->uiBufSize
)
495 *(grub_uint16_t
*)(pstCurParse
->pDataBuf
) = (grub_uint16_t
)pstJsonCur
->unData
.lValue
;
497 else if (sizeof(grub_uint8_t
) == pstCurParse
->uiBufSize
)
499 *(grub_uint8_t
*)(pstCurParse
->pDataBuf
) = (grub_uint8_t
)pstJsonCur
->unData
.lValue
;
501 else if ((pstCurParse
->uiBufSize
> sizeof(grub_uint64_t
)))
503 grub_snprintf((char *)pstCurParse
->pDataBuf
, pstCurParse
->uiBufSize
, "%llu",
504 (unsigned long long)(pstJsonCur
->unData
.lValue
));
508 json_debug("Invalid number data buf size %u.", pstCurParse
->uiBufSize
);
512 case JSON_TYPE_STRING
:
514 grub_strncpy((char *)pstCurParse
->pDataBuf
, pstJsonCur
->unData
.pcStrVal
, pstCurParse
->uiBufSize
);
519 *(grub_uint8_t
*)(pstCurParse
->pDataBuf
) = (pstJsonCur
->unData
.lValue
) > 0 ? 1 : 0;
532 int vtoy_json_scan_array
536 VTOY_JSON
**ppstArrayItem
539 VTOY_JSON
*pstJsonItem
= NULL
;
541 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_ARRAY
, szKey
);
542 if (NULL
== pstJsonItem
)
544 json_debug("Key %s is not found in json data.", szKey
);
545 return JSON_NOT_FOUND
;
548 *ppstArrayItem
= pstJsonItem
;
553 int vtoy_json_scan_array_ex
557 VTOY_JSON
**ppstArrayItem
560 VTOY_JSON
*pstJsonItem
= NULL
;
562 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_ARRAY
, szKey
);
563 if (NULL
== pstJsonItem
)
565 json_debug("Key %s is not found in json data.", szKey
);
566 return JSON_NOT_FOUND
;
569 *ppstArrayItem
= pstJsonItem
->pstChild
;
574 int vtoy_json_scan_object
578 VTOY_JSON
**ppstObjectItem
581 VTOY_JSON
*pstJsonItem
= NULL
;
583 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_OBJECT
, szKey
);
584 if (NULL
== pstJsonItem
)
586 json_debug("Key %s is not found in json data.", szKey
);
587 return JSON_NOT_FOUND
;
590 *ppstObjectItem
= pstJsonItem
;
595 int vtoy_json_get_int
602 VTOY_JSON
*pstJsonItem
= NULL
;
604 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_NUMBER
, szKey
);
605 if (NULL
== pstJsonItem
)
607 json_debug("Key %s is not found in json data.", szKey
);
608 return JSON_NOT_FOUND
;
611 *piValue
= (int)pstJsonItem
->unData
.lValue
;
616 int vtoy_json_get_uint
620 grub_uint32_t
*puiValue
623 VTOY_JSON
*pstJsonItem
= NULL
;
625 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_NUMBER
, szKey
);
626 if (NULL
== pstJsonItem
)
628 json_debug("Key %s is not found in json data.", szKey
);
629 return JSON_NOT_FOUND
;
632 *puiValue
= (grub_uint32_t
)pstJsonItem
->unData
.lValue
;
637 int vtoy_json_get_uint64
641 grub_uint64_t
*pui64Value
644 VTOY_JSON
*pstJsonItem
= NULL
;
646 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_NUMBER
, szKey
);
647 if (NULL
== pstJsonItem
)
649 json_debug("Key %s is not found in json data.", szKey
);
650 return JSON_NOT_FOUND
;
653 *pui64Value
= (grub_uint64_t
)pstJsonItem
->unData
.lValue
;
658 int vtoy_json_get_bool
662 grub_uint8_t
*pbValue
665 VTOY_JSON
*pstJsonItem
= NULL
;
667 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_BOOL
, szKey
);
668 if (NULL
== pstJsonItem
)
670 json_debug("Key %s is not found in json data.", szKey
);
671 return JSON_NOT_FOUND
;
674 *pbValue
= pstJsonItem
->unData
.lValue
> 0 ? 1 : 0;
679 int vtoy_json_get_string
683 grub_uint32_t uiBufLen
,
687 VTOY_JSON
*pstJsonItem
= NULL
;
689 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_STRING
, szKey
);
690 if (NULL
== pstJsonItem
)
692 json_debug("Key %s is not found in json data.", szKey
);
693 return JSON_NOT_FOUND
;
696 grub_strncpy(pcBuf
, pstJsonItem
->unData
.pcStrVal
, uiBufLen
);
701 const char * vtoy_json_get_string_ex(VTOY_JSON
*pstJson
, const char *szKey
)
703 VTOY_JSON
*pstJsonItem
= NULL
;
705 if ((NULL
== pstJson
) || (NULL
== szKey
))
710 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_STRING
, szKey
);
711 if (NULL
== pstJsonItem
)
713 json_debug("Key %s is not found in json data.", szKey
);
717 return pstJsonItem
->unData
.pcStrVal
;
720 int vtoy_json_destroy(VTOY_JSON
*pstJson
)
727 if (NULL
!= pstJson
->pstChild
)
729 vtoy_json_free(pstJson
->pstChild
);
732 if (NULL
!= pstJson
->pstNext
)
734 vtoy_json_free(pstJson
->pstNext
);