]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - LinuxGUI/Ventoy2Disk/Core/ventoy_json.c
1 /******************************************************************************
4 * Copyright (c) 2021, 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/>.
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>
34 static void vtoy_json_free(VTOY_JSON
*pstJsonHead
)
36 VTOY_JSON
*pstNext
= NULL
;
38 while (NULL
!= pstJsonHead
)
40 pstNext
= pstJsonHead
->pstNext
;
41 if ((pstJsonHead
->enDataType
< JSON_TYPE_BUTT
) && (NULL
!= pstJsonHead
->pstChild
))
43 vtoy_json_free(pstJsonHead
->pstChild
);
47 pstJsonHead
= pstNext
;
53 static char *vtoy_json_skip(const char *pcData
)
55 while ((NULL
!= pcData
) && ('\0' != *pcData
) && (*pcData
<= 32))
60 return (char *)pcData
;
63 VTOY_JSON
*vtoy_json_find_item
70 while (NULL
!= pstJson
)
72 if ((enDataType
== pstJson
->enDataType
) &&
73 (0 == strcmp(szKey
, pstJson
->pcName
)))
77 pstJson
= pstJson
->pstNext
;
83 static int vtoy_json_parse_number
92 Value
= strtoul(pcData
, (char **)ppcEnd
, 10);
93 if (*ppcEnd
== pcData
)
95 vdebug("Failed to parse json number %s.\n", pcData
);
99 pstJson
->enDataType
= JSON_TYPE_NUMBER
;
100 pstJson
->unData
.lValue
= Value
;
105 static int vtoy_json_parse_string
115 const char *pcPos
= NULL
;
116 const char *pcTmp
= pcData
+ 1;
125 pcPos
= strchr(pcTmp
, '\"');
126 if ((NULL
== pcPos
) || (pcPos
< pcTmp
))
128 vdebug("Invalid string %s.\n", pcData
);
133 uiLen
= (uint32_t)(unsigned long)(pcPos
- pcTmp
);
135 pstJson
->enDataType
= JSON_TYPE_STRING
;
136 pstJson
->unData
.pcStrVal
= pcNewStart
+ (pcTmp
- pcRawStart
);
137 pstJson
->unData
.pcStrVal
[uiLen
] = '\0';
142 static int vtoy_json_parse_array
151 int Ret
= JSON_SUCCESS
;
152 VTOY_JSON
*pstJsonChild
= NULL
;
153 VTOY_JSON
*pstJsonItem
= NULL
;
154 const char *pcTmp
= pcData
+ 1;
157 pstJson
->enDataType
= JSON_TYPE_ARRAY
;
164 pcTmp
= vtoy_json_skip(pcTmp
);
172 JSON_NEW_ITEM(pstJson
->pstChild
, JSON_FAILED
);
174 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJson
->pstChild
, pcTmp
, ppcEnd
);
175 if (JSON_SUCCESS
!= Ret
)
177 vdebug("Failed to parse array child.\n");
181 pstJsonChild
= pstJson
->pstChild
;
182 pcTmp
= vtoy_json_skip(*ppcEnd
);
183 while ((NULL
!= pcTmp
) && (',' == *pcTmp
))
185 JSON_NEW_ITEM(pstJsonItem
, JSON_FAILED
);
186 pstJsonChild
->pstNext
= pstJsonItem
;
187 pstJsonItem
->pstPrev
= pstJsonChild
;
188 pstJsonChild
= pstJsonItem
;
190 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
191 if (JSON_SUCCESS
!= Ret
)
193 vdebug("Failed to parse array child.\n");
196 pcTmp
= vtoy_json_skip(*ppcEnd
);
199 if ((NULL
!= pcTmp
) && (']' == *pcTmp
))
211 static int vtoy_json_parse_object
220 int Ret
= JSON_SUCCESS
;
221 VTOY_JSON
*pstJsonChild
= NULL
;
222 VTOY_JSON
*pstJsonItem
= NULL
;
223 const char *pcTmp
= pcData
+ 1;
226 pstJson
->enDataType
= JSON_TYPE_OBJECT
;
233 pcTmp
= vtoy_json_skip(pcTmp
);
240 JSON_NEW_ITEM(pstJson
->pstChild
, JSON_FAILED
);
242 Ret
= vtoy_json_parse_string(pcNewStart
, pcRawStart
, pstJson
->pstChild
, pcTmp
, ppcEnd
);
243 if (JSON_SUCCESS
!= Ret
)
245 vdebug("Failed to parse array child.\n");
249 pstJsonChild
= pstJson
->pstChild
;
250 pstJsonChild
->pcName
= pstJsonChild
->unData
.pcStrVal
;
251 pstJsonChild
->unData
.pcStrVal
= NULL
;
253 pcTmp
= vtoy_json_skip(*ppcEnd
);
254 if ((NULL
== pcTmp
) || (':' != *pcTmp
))
260 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
261 if (JSON_SUCCESS
!= Ret
)
263 vdebug("Failed to parse array child.\n");
267 pcTmp
= vtoy_json_skip(*ppcEnd
);
268 while ((NULL
!= pcTmp
) && (',' == *pcTmp
))
270 JSON_NEW_ITEM(pstJsonItem
, JSON_FAILED
);
271 pstJsonChild
->pstNext
= pstJsonItem
;
272 pstJsonItem
->pstPrev
= pstJsonChild
;
273 pstJsonChild
= pstJsonItem
;
275 Ret
= vtoy_json_parse_string(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
276 if (JSON_SUCCESS
!= Ret
)
278 vdebug("Failed to parse array child.\n");
282 pcTmp
= vtoy_json_skip(*ppcEnd
);
283 pstJsonChild
->pcName
= pstJsonChild
->unData
.pcStrVal
;
284 pstJsonChild
->unData
.pcStrVal
= NULL
;
285 if ((NULL
== pcTmp
) || (':' != *pcTmp
))
291 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
292 if (JSON_SUCCESS
!= Ret
)
294 vdebug("Failed to parse array child.\n");
298 pcTmp
= vtoy_json_skip(*ppcEnd
);
301 if ((NULL
!= pcTmp
) && ('}' == *pcTmp
))
313 int vtoy_json_parse_value
322 pcData
= vtoy_json_skip(pcData
);
328 if (0 == strncmp(pcData
, "null", 4))
330 pstJson
->enDataType
= JSON_TYPE_NULL
;
331 *ppcEnd
= pcData
+ 4;
338 if (0 == strncmp(pcData
, "false", 5))
340 pstJson
->enDataType
= JSON_TYPE_BOOL
;
341 pstJson
->unData
.lValue
= 0;
342 *ppcEnd
= pcData
+ 5;
349 if (0 == strncmp(pcData
, "true", 4))
351 pstJson
->enDataType
= JSON_TYPE_BOOL
;
352 pstJson
->unData
.lValue
= 1;
353 *ppcEnd
= pcData
+ 4;
360 return vtoy_json_parse_string(pcNewStart
, pcRawStart
, pstJson
, pcData
, ppcEnd
);
364 return vtoy_json_parse_array(pcNewStart
, pcRawStart
, pstJson
, pcData
, ppcEnd
);
368 return vtoy_json_parse_object(pcNewStart
, pcRawStart
, pstJson
, pcData
, ppcEnd
);
372 return vtoy_json_parse_number(pstJson
, pcData
, ppcEnd
);
376 if (*pcData
>= '0' && *pcData
<= '9')
378 return vtoy_json_parse_number(pstJson
, pcData
, ppcEnd
);
384 vdebug("Invalid json data %u.\n", (uint8_t)(*pcData
));
388 VTOY_JSON
* vtoy_json_create(void)
390 VTOY_JSON
*pstJson
= NULL
;
392 pstJson
= (VTOY_JSON
*)zalloc(sizeof(VTOY_JSON
));
401 int vtoy_json_parse(VTOY_JSON
*pstJson
, const char *szJsonData
)
403 uint32_t uiMemSize
= 0;
404 int Ret
= JSON_SUCCESS
;
405 char *pcNewBuf
= NULL
;
406 const char *pcEnd
= NULL
;
408 uiMemSize
= strlen(szJsonData
) + 1;
409 pcNewBuf
= (char *)malloc(uiMemSize
);
410 if (NULL
== pcNewBuf
)
412 vdebug("Failed to alloc new buf.\n");
415 memcpy(pcNewBuf
, szJsonData
, uiMemSize
);
416 pcNewBuf
[uiMemSize
- 1] = 0;
418 Ret
= vtoy_json_parse_value(pcNewBuf
, (char *)szJsonData
, pstJson
, szJsonData
, &pcEnd
);
419 if (JSON_SUCCESS
!= Ret
)
421 vdebug("Failed to parse json data %s start=%p, end=%p:%s.\n",
422 szJsonData
, szJsonData
, pcEnd
, pcEnd
);
429 int vtoy_json_scan_parse
431 const VTOY_JSON
*pstJson
,
433 VTOY_JSON_PARSE_S
*pstJsonParse
437 const VTOY_JSON
*pstJsonCur
= NULL
;
438 VTOY_JSON_PARSE_S
*pstCurParse
= NULL
;
440 for (pstJsonCur
= pstJson
; NULL
!= pstJsonCur
; pstJsonCur
= pstJsonCur
->pstNext
)
442 if ((JSON_TYPE_OBJECT
== pstJsonCur
->enDataType
) ||
443 (JSON_TYPE_ARRAY
== pstJsonCur
->enDataType
))
448 for (i
= 0, pstCurParse
= NULL
; i
< uiParseNum
; i
++)
450 if (0 == strcmp(pstJsonParse
[i
].pcKey
, pstJsonCur
->pcName
))
452 pstCurParse
= pstJsonParse
+ i
;
457 if (NULL
== pstCurParse
)
462 switch (pstJsonCur
->enDataType
)
464 case JSON_TYPE_NUMBER
:
466 if (sizeof(uint32_t) == pstCurParse
->uiBufSize
)
468 *(uint32_t *)(pstCurParse
->pDataBuf
) = (uint32_t)pstJsonCur
->unData
.lValue
;
470 else if (sizeof(uint16_t) == pstCurParse
->uiBufSize
)
472 *(uint16_t *)(pstCurParse
->pDataBuf
) = (uint16_t)pstJsonCur
->unData
.lValue
;
474 else if (sizeof(uint8_t) == pstCurParse
->uiBufSize
)
476 *(uint8_t *)(pstCurParse
->pDataBuf
) = (uint8_t)pstJsonCur
->unData
.lValue
;
478 else if ((pstCurParse
->uiBufSize
> sizeof(uint64_t)))
480 snprintf((char *)pstCurParse
->pDataBuf
, pstCurParse
->uiBufSize
, "%llu",
481 (unsigned long long)(pstJsonCur
->unData
.lValue
));
485 vdebug("Invalid number data buf size %u.\n", pstCurParse
->uiBufSize
);
489 case JSON_TYPE_STRING
:
491 strncpy((char *)pstCurParse
->pDataBuf
, pstJsonCur
->unData
.pcStrVal
, pstCurParse
->uiBufSize
);
496 *(uint8_t *)(pstCurParse
->pDataBuf
) = (pstJsonCur
->unData
.lValue
) > 0 ? 1 : 0;
509 int vtoy_json_scan_array
513 VTOY_JSON
**ppstArrayItem
516 VTOY_JSON
*pstJsonItem
= NULL
;
518 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_ARRAY
, szKey
);
519 if (NULL
== pstJsonItem
)
521 vdebug("Key %s is not found in json data.\n", szKey
);
522 return JSON_NOT_FOUND
;
525 *ppstArrayItem
= pstJsonItem
;
530 int vtoy_json_scan_array_ex
534 VTOY_JSON
**ppstArrayItem
537 VTOY_JSON
*pstJsonItem
= NULL
;
539 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_ARRAY
, szKey
);
540 if (NULL
== pstJsonItem
)
542 vdebug("Key %s is not found in json data.\n", szKey
);
543 return JSON_NOT_FOUND
;
546 *ppstArrayItem
= pstJsonItem
->pstChild
;
551 int vtoy_json_scan_object
555 VTOY_JSON
**ppstObjectItem
558 VTOY_JSON
*pstJsonItem
= NULL
;
560 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_OBJECT
, szKey
);
561 if (NULL
== pstJsonItem
)
563 vdebug("Key %s is not found in json data.\n", szKey
);
564 return JSON_NOT_FOUND
;
567 *ppstObjectItem
= pstJsonItem
;
572 int vtoy_json_get_int
579 VTOY_JSON
*pstJsonItem
= NULL
;
581 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_NUMBER
, szKey
);
582 if (NULL
== pstJsonItem
)
584 vdebug("Key %s is not found in json data.\n", szKey
);
585 return JSON_NOT_FOUND
;
588 *piValue
= (int)pstJsonItem
->unData
.lValue
;
593 int vtoy_json_get_uint
600 VTOY_JSON
*pstJsonItem
= NULL
;
602 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_NUMBER
, szKey
);
603 if (NULL
== pstJsonItem
)
605 vdebug("Key %s is not found in json data.\n", szKey
);
606 return JSON_NOT_FOUND
;
609 *puiValue
= (uint32_t)pstJsonItem
->unData
.lValue
;
614 int vtoy_json_get_uint64
621 VTOY_JSON
*pstJsonItem
= NULL
;
623 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_NUMBER
, szKey
);
624 if (NULL
== pstJsonItem
)
626 vdebug("Key %s is not found in json data.\n", szKey
);
627 return JSON_NOT_FOUND
;
630 *pui64Value
= (uint64_t)pstJsonItem
->unData
.lValue
;
635 int vtoy_json_get_bool
642 VTOY_JSON
*pstJsonItem
= NULL
;
644 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_BOOL
, szKey
);
645 if (NULL
== pstJsonItem
)
647 vdebug("Key %s is not found in json data.\n", szKey
);
648 return JSON_NOT_FOUND
;
651 *pbValue
= pstJsonItem
->unData
.lValue
> 0 ? 1 : 0;
656 int vtoy_json_get_string
664 VTOY_JSON
*pstJsonItem
= NULL
;
666 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_STRING
, szKey
);
667 if (NULL
== pstJsonItem
)
669 vdebug("Key %s is not found in json data.\n", szKey
);
670 return JSON_NOT_FOUND
;
673 strncpy(pcBuf
, pstJsonItem
->unData
.pcStrVal
, uiBufLen
);
678 const char * vtoy_json_get_string_ex(VTOY_JSON
*pstJson
, const char *szKey
)
680 VTOY_JSON
*pstJsonItem
= NULL
;
682 if ((NULL
== pstJson
) || (NULL
== szKey
))
687 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_STRING
, szKey
);
688 if (NULL
== pstJsonItem
)
690 vdebug("Key %s is not found in json data.\n", szKey
);
694 return pstJsonItem
->unData
.pcStrVal
;
697 int vtoy_json_destroy(VTOY_JSON
*pstJson
)
704 if (NULL
!= pstJson
->pstChild
)
706 vtoy_json_free(pstJson
->pstChild
);
709 if (NULL
!= pstJson
->pstNext
)
711 vtoy_json_free(pstJson
->pstNext
);