]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/grub-2.04/grub-core/ventoy/ventoy_json.c
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
, ...)
46 grub_vprintf (fmt
, args
);
52 static void vtoy_json_free(VTOY_JSON
*pstJsonHead
)
54 VTOY_JSON
*pstNext
= NULL
;
56 while (NULL
!= pstJsonHead
)
58 pstNext
= pstJsonHead
->pstNext
;
59 if ((pstJsonHead
->enDataType
< JSON_TYPE_BUTT
) && (NULL
!= pstJsonHead
->pstChild
))
61 vtoy_json_free(pstJsonHead
->pstChild
);
64 grub_free(pstJsonHead
);
65 pstJsonHead
= pstNext
;
71 static char *vtoy_json_skip(const char *pcData
)
73 while ((NULL
!= pcData
) && ('\0' != *pcData
) && (*pcData
<= 32))
78 return (char *)pcData
;
81 VTOY_JSON
*vtoy_json_find_item
88 while (NULL
!= pstJson
)
90 if ((enDataType
== pstJson
->enDataType
) &&
91 (0 == grub_strcmp(szKey
, pstJson
->pcName
)))
95 pstJson
= pstJson
->pstNext
;
101 static int vtoy_json_parse_number
110 Value
= grub_strtoul(pcData
, (char **)ppcEnd
, 10);
111 if (*ppcEnd
== pcData
)
113 json_debug("Failed to parse json number %s.", pcData
);
117 pstJson
->enDataType
= JSON_TYPE_NUMBER
;
118 pstJson
->unData
.lValue
= Value
;
123 static int vtoy_json_parse_string
132 grub_uint32_t uiLen
= 0;
133 const char *pcPos
= NULL
;
134 const char *pcTmp
= pcData
+ 1;
143 pcPos
= grub_strchr(pcTmp
, '\"');
144 if ((NULL
== pcPos
) || (pcPos
< pcTmp
))
146 json_debug("Invalid string %s.", pcData
);
151 uiLen
= (grub_uint32_t
)(unsigned long)(pcPos
- pcTmp
);
153 pstJson
->enDataType
= JSON_TYPE_STRING
;
154 pstJson
->unData
.pcStrVal
= pcNewStart
+ (pcTmp
- pcRawStart
);
155 pstJson
->unData
.pcStrVal
[uiLen
] = '\0';
160 static int vtoy_json_parse_array
169 int Ret
= JSON_SUCCESS
;
170 VTOY_JSON
*pstJsonChild
= NULL
;
171 VTOY_JSON
*pstJsonItem
= NULL
;
172 const char *pcTmp
= pcData
+ 1;
175 pstJson
->enDataType
= JSON_TYPE_ARRAY
;
182 pcTmp
= vtoy_json_skip(pcTmp
);
190 JSON_NEW_ITEM(pstJson
->pstChild
, JSON_FAILED
);
192 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJson
->pstChild
, pcTmp
, ppcEnd
);
193 if (JSON_SUCCESS
!= Ret
)
195 json_debug("Failed to parse array child.");
199 pstJsonChild
= pstJson
->pstChild
;
200 pcTmp
= vtoy_json_skip(*ppcEnd
);
201 while ((NULL
!= pcTmp
) && (',' == *pcTmp
))
203 JSON_NEW_ITEM(pstJsonItem
, JSON_FAILED
);
204 pstJsonChild
->pstNext
= pstJsonItem
;
205 pstJsonItem
->pstPrev
= pstJsonChild
;
206 pstJsonChild
= pstJsonItem
;
208 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
209 if (JSON_SUCCESS
!= Ret
)
211 json_debug("Failed to parse array child.");
214 pcTmp
= vtoy_json_skip(*ppcEnd
);
217 if ((NULL
!= pcTmp
) && (']' == *pcTmp
))
229 static int vtoy_json_parse_object
238 int Ret
= JSON_SUCCESS
;
239 VTOY_JSON
*pstJsonChild
= NULL
;
240 VTOY_JSON
*pstJsonItem
= NULL
;
241 const char *pcTmp
= pcData
+ 1;
244 pstJson
->enDataType
= JSON_TYPE_OBJECT
;
251 pcTmp
= vtoy_json_skip(pcTmp
);
258 JSON_NEW_ITEM(pstJson
->pstChild
, JSON_FAILED
);
260 Ret
= vtoy_json_parse_string(pcNewStart
, pcRawStart
, pstJson
->pstChild
, pcTmp
, ppcEnd
);
261 if (JSON_SUCCESS
!= Ret
)
263 json_debug("Failed to parse array child.");
267 pstJsonChild
= pstJson
->pstChild
;
268 pstJsonChild
->pcName
= pstJsonChild
->unData
.pcStrVal
;
269 pstJsonChild
->unData
.pcStrVal
= NULL
;
271 pcTmp
= vtoy_json_skip(*ppcEnd
);
272 if ((NULL
== pcTmp
) || (':' != *pcTmp
))
278 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
279 if (JSON_SUCCESS
!= Ret
)
281 json_debug("Failed to parse array child.");
285 pcTmp
= vtoy_json_skip(*ppcEnd
);
286 while ((NULL
!= pcTmp
) && (',' == *pcTmp
))
288 JSON_NEW_ITEM(pstJsonItem
, JSON_FAILED
);
289 pstJsonChild
->pstNext
= pstJsonItem
;
290 pstJsonItem
->pstPrev
= pstJsonChild
;
291 pstJsonChild
= pstJsonItem
;
293 Ret
= vtoy_json_parse_string(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
294 if (JSON_SUCCESS
!= Ret
)
296 json_debug("Failed to parse array child.");
300 pcTmp
= vtoy_json_skip(*ppcEnd
);
301 pstJsonChild
->pcName
= pstJsonChild
->unData
.pcStrVal
;
302 pstJsonChild
->unData
.pcStrVal
= NULL
;
303 if ((NULL
== pcTmp
) || (':' != *pcTmp
))
309 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
310 if (JSON_SUCCESS
!= Ret
)
312 json_debug("Failed to parse array child.");
316 pcTmp
= vtoy_json_skip(*ppcEnd
);
319 if ((NULL
!= pcTmp
) && ('}' == *pcTmp
))
331 int vtoy_json_parse_value
340 pcData
= vtoy_json_skip(pcData
);
346 if (0 == grub_strncmp(pcData
, "null", 4))
348 pstJson
->enDataType
= JSON_TYPE_NULL
;
349 *ppcEnd
= pcData
+ 4;
356 if (0 == grub_strncmp(pcData
, "false", 5))
358 pstJson
->enDataType
= JSON_TYPE_BOOL
;
359 pstJson
->unData
.lValue
= 0;
360 *ppcEnd
= pcData
+ 5;
367 if (0 == grub_strncmp(pcData
, "true", 4))
369 pstJson
->enDataType
= JSON_TYPE_BOOL
;
370 pstJson
->unData
.lValue
= 1;
371 *ppcEnd
= pcData
+ 4;
378 return vtoy_json_parse_string(pcNewStart
, pcRawStart
, pstJson
, pcData
, ppcEnd
);
382 return vtoy_json_parse_array(pcNewStart
, pcRawStart
, pstJson
, pcData
, ppcEnd
);
386 return vtoy_json_parse_object(pcNewStart
, pcRawStart
, pstJson
, pcData
, ppcEnd
);
390 return vtoy_json_parse_number(pstJson
, pcData
, ppcEnd
);
394 if (*pcData
>= '0' && *pcData
<= '9')
396 return vtoy_json_parse_number(pstJson
, pcData
, ppcEnd
);
402 json_debug("Invalid json data %u.", (grub_uint8_t
)(*pcData
));
406 VTOY_JSON
* vtoy_json_create(void)
408 VTOY_JSON
*pstJson
= NULL
;
410 pstJson
= (VTOY_JSON
*)grub_zalloc(sizeof(VTOY_JSON
));
419 int vtoy_json_parse(VTOY_JSON
*pstJson
, const char *szJsonData
)
421 grub_uint32_t uiMemSize
= 0;
422 int Ret
= JSON_SUCCESS
;
423 char *pcNewBuf
= NULL
;
424 const char *pcEnd
= NULL
;
426 uiMemSize
= grub_strlen(szJsonData
) + 1;
427 pcNewBuf
= (char *)grub_malloc(uiMemSize
);
428 if (NULL
== pcNewBuf
)
430 json_debug("Failed to alloc new buf.");
433 grub_memcpy(pcNewBuf
, szJsonData
, uiMemSize
);
434 pcNewBuf
[uiMemSize
- 1] = 0;
436 Ret
= vtoy_json_parse_value(pcNewBuf
, (char *)szJsonData
, pstJson
, szJsonData
, &pcEnd
);
437 if (JSON_SUCCESS
!= Ret
)
439 json_debug("Failed to parse json data %s start=%p, end=%p:%s.",
440 szJsonData
, szJsonData
, pcEnd
, pcEnd
);
447 int vtoy_json_scan_parse
449 const VTOY_JSON
*pstJson
,
450 grub_uint32_t uiParseNum
,
451 JSON_PARSE
*pstJsonParse
455 const VTOY_JSON
*pstJsonCur
= NULL
;
456 JSON_PARSE
*pstCurParse
= NULL
;
458 for (pstJsonCur
= pstJson
; NULL
!= pstJsonCur
; pstJsonCur
= pstJsonCur
->pstNext
)
460 if ((JSON_TYPE_OBJECT
== pstJsonCur
->enDataType
) ||
461 (JSON_TYPE_ARRAY
== pstJsonCur
->enDataType
))
466 for (i
= 0, pstCurParse
= NULL
; i
< uiParseNum
; i
++)
468 if (0 == grub_strcmp(pstJsonParse
[i
].pcKey
, pstJsonCur
->pcName
))
470 pstCurParse
= pstJsonParse
+ i
;
475 if (NULL
== pstCurParse
)
480 switch (pstJsonCur
->enDataType
)
482 case JSON_TYPE_NUMBER
:
484 if (sizeof(grub_uint32_t
) == pstCurParse
->uiBufSize
)
486 *(grub_uint32_t
*)(pstCurParse
->pDataBuf
) = (grub_uint32_t
)pstJsonCur
->unData
.lValue
;
488 else if (sizeof(grub_uint16_t
) == pstCurParse
->uiBufSize
)
490 *(grub_uint16_t
*)(pstCurParse
->pDataBuf
) = (grub_uint16_t
)pstJsonCur
->unData
.lValue
;
492 else if (sizeof(grub_uint8_t
) == pstCurParse
->uiBufSize
)
494 *(grub_uint8_t
*)(pstCurParse
->pDataBuf
) = (grub_uint8_t
)pstJsonCur
->unData
.lValue
;
496 else if ((pstCurParse
->uiBufSize
> sizeof(grub_uint64_t
)))
498 grub_snprintf((char *)pstCurParse
->pDataBuf
, pstCurParse
->uiBufSize
, "%llu",
499 (unsigned long long)(pstJsonCur
->unData
.lValue
));
503 json_debug("Invalid number data buf size %u.", pstCurParse
->uiBufSize
);
507 case JSON_TYPE_STRING
:
509 grub_strncpy((char *)pstCurParse
->pDataBuf
, pstJsonCur
->unData
.pcStrVal
, pstCurParse
->uiBufSize
);
514 *(grub_uint8_t
*)(pstCurParse
->pDataBuf
) = (pstJsonCur
->unData
.lValue
) > 0 ? 1 : 0;
527 int vtoy_json_scan_array
531 VTOY_JSON
**ppstArrayItem
534 VTOY_JSON
*pstJsonItem
= NULL
;
536 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_ARRAY
, szKey
);
537 if (NULL
== pstJsonItem
)
539 json_debug("Key %s is not found in json data.", szKey
);
540 return JSON_NOT_FOUND
;
543 *ppstArrayItem
= pstJsonItem
;
548 int vtoy_json_scan_array_ex
552 VTOY_JSON
**ppstArrayItem
555 VTOY_JSON
*pstJsonItem
= NULL
;
557 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_ARRAY
, szKey
);
558 if (NULL
== pstJsonItem
)
560 json_debug("Key %s is not found in json data.", szKey
);
561 return JSON_NOT_FOUND
;
564 *ppstArrayItem
= pstJsonItem
->pstChild
;
569 int vtoy_json_scan_object
573 VTOY_JSON
**ppstObjectItem
576 VTOY_JSON
*pstJsonItem
= NULL
;
578 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_OBJECT
, szKey
);
579 if (NULL
== pstJsonItem
)
581 json_debug("Key %s is not found in json data.", szKey
);
582 return JSON_NOT_FOUND
;
585 *ppstObjectItem
= pstJsonItem
;
590 int vtoy_json_get_int
597 VTOY_JSON
*pstJsonItem
= NULL
;
599 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_NUMBER
, szKey
);
600 if (NULL
== pstJsonItem
)
602 json_debug("Key %s is not found in json data.", szKey
);
603 return JSON_NOT_FOUND
;
606 *piValue
= (int)pstJsonItem
->unData
.lValue
;
611 int vtoy_json_get_uint
615 grub_uint32_t
*puiValue
618 VTOY_JSON
*pstJsonItem
= NULL
;
620 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_NUMBER
, szKey
);
621 if (NULL
== pstJsonItem
)
623 json_debug("Key %s is not found in json data.", szKey
);
624 return JSON_NOT_FOUND
;
627 *puiValue
= (grub_uint32_t
)pstJsonItem
->unData
.lValue
;
632 int vtoy_json_get_uint64
636 grub_uint64_t
*pui64Value
639 VTOY_JSON
*pstJsonItem
= NULL
;
641 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_NUMBER
, szKey
);
642 if (NULL
== pstJsonItem
)
644 json_debug("Key %s is not found in json data.", szKey
);
645 return JSON_NOT_FOUND
;
648 *pui64Value
= (grub_uint64_t
)pstJsonItem
->unData
.lValue
;
653 int vtoy_json_get_bool
657 grub_uint8_t
*pbValue
660 VTOY_JSON
*pstJsonItem
= NULL
;
662 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_BOOL
, szKey
);
663 if (NULL
== pstJsonItem
)
665 json_debug("Key %s is not found in json data.", szKey
);
666 return JSON_NOT_FOUND
;
669 *pbValue
= pstJsonItem
->unData
.lValue
> 0 ? 1 : 0;
674 int vtoy_json_get_string
678 grub_uint32_t uiBufLen
,
682 VTOY_JSON
*pstJsonItem
= NULL
;
684 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_STRING
, szKey
);
685 if (NULL
== pstJsonItem
)
687 json_debug("Key %s is not found in json data.", szKey
);
688 return JSON_NOT_FOUND
;
691 grub_strncpy(pcBuf
, pstJsonItem
->unData
.pcStrVal
, uiBufLen
);
696 const char * vtoy_json_get_string_ex(VTOY_JSON
*pstJson
, const char *szKey
)
698 VTOY_JSON
*pstJsonItem
= NULL
;
700 if ((NULL
== pstJson
) || (NULL
== szKey
))
705 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_STRING
, szKey
);
706 if (NULL
== pstJsonItem
)
708 json_debug("Key %s is not found in json data.", szKey
);
712 return pstJsonItem
->unData
.pcStrVal
;
715 int vtoy_json_destroy(VTOY_JSON
*pstJson
)
722 if (NULL
!= pstJson
->pstChild
)
724 vtoy_json_free(pstJson
->pstChild
);
727 if (NULL
!= pstJson
->pstNext
)
729 vtoy_json_free(pstJson
->pstNext
);