]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - Plugson/src/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/>.
27 #if defined(_MSC_VER) || defined(WIN32)
30 #include <sys/types.h>
31 #include <linux/limits.h>
33 #include <ventoy_define.h>
34 #include <ventoy_util.h>
35 #include <ventoy_json.h>
37 static void vtoy_json_free(VTOY_JSON
*pstJsonHead
)
39 VTOY_JSON
*pstNext
= NULL
;
41 while (NULL
!= pstJsonHead
)
43 pstNext
= pstJsonHead
->pstNext
;
44 if ((pstJsonHead
->enDataType
< JSON_TYPE_BUTT
) && (NULL
!= pstJsonHead
->pstChild
))
46 vtoy_json_free(pstJsonHead
->pstChild
);
50 pstJsonHead
= pstNext
;
56 static char *vtoy_json_skip(const char *pcData
)
58 while ((NULL
!= pcData
) && ('\0' != *pcData
) && (*pcData
<= 32))
63 return (char *)pcData
;
66 VTOY_JSON
*vtoy_json_find_item
73 while (NULL
!= pstJson
)
75 if ((enDataType
== pstJson
->enDataType
) &&
76 (0 == strcmp(szKey
, pstJson
->pcName
)))
80 pstJson
= pstJson
->pstNext
;
86 static int vtoy_json_parse_number
95 Value
= strtoul(pcData
, (char **)ppcEnd
, 10);
96 if (*ppcEnd
== pcData
)
98 vdebug("Failed to parse json number %s.\n", pcData
);
102 pstJson
->enDataType
= JSON_TYPE_NUMBER
;
103 pstJson
->unData
.lValue
= Value
;
108 static int vtoy_json_parse_string
118 const char *pcPos
= NULL
;
119 const char *pcTmp
= pcData
+ 1;
128 pcPos
= strchr(pcTmp
, '\"');
129 if ((NULL
== pcPos
) || (pcPos
< pcTmp
))
131 vdebug("Invalid string %s.\n", pcData
);
135 if (*(pcPos
- 1) == '\\')
137 for (pcPos
++; *pcPos
; pcPos
++)
139 if (*pcPos
== '"' && *(pcPos
- 1) != '\\')
145 if (*pcPos
== 0 || pcPos
< pcTmp
)
147 vdebug("Invalid quotes string %s.", pcData
);
153 uiLen
= (uint32_t)(unsigned long)(pcPos
- pcTmp
);
155 pstJson
->enDataType
= JSON_TYPE_STRING
;
156 pstJson
->unData
.pcStrVal
= pcNewStart
+ (pcTmp
- pcRawStart
);
157 pstJson
->unData
.pcStrVal
[uiLen
] = '\0';
162 static int vtoy_json_parse_array
171 int Ret
= JSON_SUCCESS
;
172 VTOY_JSON
*pstJsonChild
= NULL
;
173 VTOY_JSON
*pstJsonItem
= NULL
;
174 const char *pcTmp
= pcData
+ 1;
177 pstJson
->enDataType
= JSON_TYPE_ARRAY
;
184 pcTmp
= vtoy_json_skip(pcTmp
);
192 JSON_NEW_ITEM(pstJson
->pstChild
, JSON_FAILED
);
194 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJson
->pstChild
, pcTmp
, ppcEnd
);
195 if (JSON_SUCCESS
!= Ret
)
197 vdebug("Failed to parse array child.\n");
201 pstJsonChild
= pstJson
->pstChild
;
202 pcTmp
= vtoy_json_skip(*ppcEnd
);
203 while ((NULL
!= pcTmp
) && (',' == *pcTmp
))
205 JSON_NEW_ITEM(pstJsonItem
, JSON_FAILED
);
206 pstJsonChild
->pstNext
= pstJsonItem
;
207 pstJsonItem
->pstPrev
= pstJsonChild
;
208 pstJsonChild
= pstJsonItem
;
210 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
211 if (JSON_SUCCESS
!= Ret
)
213 vdebug("Failed to parse array child.\n");
216 pcTmp
= vtoy_json_skip(*ppcEnd
);
219 if ((NULL
!= pcTmp
) && (']' == *pcTmp
))
231 static int vtoy_json_parse_object
240 int Ret
= JSON_SUCCESS
;
241 VTOY_JSON
*pstJsonChild
= NULL
;
242 VTOY_JSON
*pstJsonItem
= NULL
;
243 const char *pcTmp
= pcData
+ 1;
246 pstJson
->enDataType
= JSON_TYPE_OBJECT
;
253 pcTmp
= vtoy_json_skip(pcTmp
);
260 JSON_NEW_ITEM(pstJson
->pstChild
, JSON_FAILED
);
262 Ret
= vtoy_json_parse_string(pcNewStart
, pcRawStart
, pstJson
->pstChild
, pcTmp
, ppcEnd
);
263 if (JSON_SUCCESS
!= Ret
)
265 vdebug("Failed to parse array child.\n");
269 pstJsonChild
= pstJson
->pstChild
;
270 pstJsonChild
->pcName
= pstJsonChild
->unData
.pcStrVal
;
271 pstJsonChild
->unData
.pcStrVal
= NULL
;
273 pcTmp
= vtoy_json_skip(*ppcEnd
);
274 if ((NULL
== pcTmp
) || (':' != *pcTmp
))
280 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
281 if (JSON_SUCCESS
!= Ret
)
283 vdebug("Failed to parse array child.\n");
287 pcTmp
= vtoy_json_skip(*ppcEnd
);
288 while ((NULL
!= pcTmp
) && (',' == *pcTmp
))
290 JSON_NEW_ITEM(pstJsonItem
, JSON_FAILED
);
291 pstJsonChild
->pstNext
= pstJsonItem
;
292 pstJsonItem
->pstPrev
= pstJsonChild
;
293 pstJsonChild
= pstJsonItem
;
295 Ret
= vtoy_json_parse_string(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
296 if (JSON_SUCCESS
!= Ret
)
298 vdebug("Failed to parse array child.\n");
302 pcTmp
= vtoy_json_skip(*ppcEnd
);
303 pstJsonChild
->pcName
= pstJsonChild
->unData
.pcStrVal
;
304 pstJsonChild
->unData
.pcStrVal
= NULL
;
305 if ((NULL
== pcTmp
) || (':' != *pcTmp
))
311 Ret
= vtoy_json_parse_value(pcNewStart
, pcRawStart
, pstJsonChild
, vtoy_json_skip(pcTmp
+ 1), ppcEnd
);
312 if (JSON_SUCCESS
!= Ret
)
314 vdebug("Failed to parse array child.\n");
318 pcTmp
= vtoy_json_skip(*ppcEnd
);
321 if ((NULL
!= pcTmp
) && ('}' == *pcTmp
))
333 int vtoy_json_parse_value
342 pcData
= vtoy_json_skip(pcData
);
348 if (0 == strncmp(pcData
, "null", 4))
350 pstJson
->enDataType
= JSON_TYPE_NULL
;
351 *ppcEnd
= pcData
+ 4;
358 if (0 == strncmp(pcData
, "false", 5))
360 pstJson
->enDataType
= JSON_TYPE_BOOL
;
361 pstJson
->unData
.lValue
= 0;
362 *ppcEnd
= pcData
+ 5;
369 if (0 == strncmp(pcData
, "true", 4))
371 pstJson
->enDataType
= JSON_TYPE_BOOL
;
372 pstJson
->unData
.lValue
= 1;
373 *ppcEnd
= pcData
+ 4;
380 return vtoy_json_parse_string(pcNewStart
, pcRawStart
, pstJson
, pcData
, ppcEnd
);
384 return vtoy_json_parse_array(pcNewStart
, pcRawStart
, pstJson
, pcData
, ppcEnd
);
388 return vtoy_json_parse_object(pcNewStart
, pcRawStart
, pstJson
, pcData
, ppcEnd
);
392 return vtoy_json_parse_number(pstJson
, pcData
, ppcEnd
);
396 if (*pcData
>= '0' && *pcData
<= '9')
398 return vtoy_json_parse_number(pstJson
, pcData
, ppcEnd
);
404 vdebug("Invalid json data %u.\n", (uint8_t)(*pcData
));
408 VTOY_JSON
* vtoy_json_create(void)
410 VTOY_JSON
*pstJson
= NULL
;
412 pstJson
= (VTOY_JSON
*)zalloc(sizeof(VTOY_JSON
));
421 int vtoy_json_parse(VTOY_JSON
*pstJson
, const char *szJsonData
)
423 uint32_t uiMemSize
= 0;
424 int Ret
= JSON_SUCCESS
;
425 char *pcNewBuf
= NULL
;
426 const char *pcEnd
= NULL
;
428 uiMemSize
= strlen(szJsonData
) + 1;
429 pcNewBuf
= (char *)malloc(uiMemSize
);
430 if (NULL
== pcNewBuf
)
432 vdebug("Failed to alloc new buf.\n");
435 memcpy(pcNewBuf
, szJsonData
, uiMemSize
);
436 pcNewBuf
[uiMemSize
- 1] = 0;
438 Ret
= vtoy_json_parse_value(pcNewBuf
, (char *)szJsonData
, pstJson
, szJsonData
, &pcEnd
);
439 if (JSON_SUCCESS
!= Ret
)
441 vdebug("Failed to parse json data start=%p, end=%p.\n", szJsonData
, pcEnd
);
448 int vtoy_json_parse_ex(VTOY_JSON
*pstJson
, const char *szJsonData
, int szLen
)
450 uint32_t uiMemSize
= 0;
451 int Ret
= JSON_SUCCESS
;
452 char *pcNewBuf
= NULL
;
453 const char *pcEnd
= NULL
;
455 uiMemSize
= (uint32_t)szLen
;
456 pcNewBuf
= (char *)malloc(uiMemSize
+ 1);
457 if (NULL
== pcNewBuf
)
459 vdebug("Failed to alloc new buf.\n");
462 memcpy(pcNewBuf
, szJsonData
, szLen
);
463 pcNewBuf
[uiMemSize
] = 0;
465 Ret
= vtoy_json_parse_value(pcNewBuf
, (char *)szJsonData
, pstJson
, szJsonData
, &pcEnd
);
466 if (JSON_SUCCESS
!= Ret
)
468 vdebug("Failed to parse json data start=%p, end=%p\n", szJsonData
, pcEnd
);
475 int vtoy_json_scan_parse
477 const VTOY_JSON
*pstJson
,
479 VTOY_JSON_PARSE_S
*pstJsonParse
483 const VTOY_JSON
*pstJsonCur
= NULL
;
484 VTOY_JSON_PARSE_S
*pstCurParse
= NULL
;
486 for (pstJsonCur
= pstJson
; NULL
!= pstJsonCur
; pstJsonCur
= pstJsonCur
->pstNext
)
488 if ((JSON_TYPE_OBJECT
== pstJsonCur
->enDataType
) ||
489 (JSON_TYPE_ARRAY
== pstJsonCur
->enDataType
))
494 for (i
= 0, pstCurParse
= NULL
; i
< uiParseNum
; i
++)
496 if (0 == strcmp(pstJsonParse
[i
].pcKey
, pstJsonCur
->pcName
))
498 pstCurParse
= pstJsonParse
+ i
;
503 if (NULL
== pstCurParse
)
508 switch (pstJsonCur
->enDataType
)
510 case JSON_TYPE_NUMBER
:
512 if (sizeof(uint32_t) == pstCurParse
->uiBufSize
)
514 *(uint32_t *)(pstCurParse
->pDataBuf
) = (uint32_t)pstJsonCur
->unData
.lValue
;
516 else if (sizeof(uint16_t) == pstCurParse
->uiBufSize
)
518 *(uint16_t *)(pstCurParse
->pDataBuf
) = (uint16_t)pstJsonCur
->unData
.lValue
;
520 else if (sizeof(uint8_t) == pstCurParse
->uiBufSize
)
522 *(uint8_t *)(pstCurParse
->pDataBuf
) = (uint8_t)pstJsonCur
->unData
.lValue
;
524 else if ((pstCurParse
->uiBufSize
> sizeof(uint64_t)))
526 scnprintf((char *)pstCurParse
->pDataBuf
, pstCurParse
->uiBufSize
, "%llu",
527 (unsigned long long)(pstJsonCur
->unData
.lValue
));
531 vdebug("Invalid number data buf size %u.\n", pstCurParse
->uiBufSize
);
535 case JSON_TYPE_STRING
:
537 scnprintf((char *)pstCurParse
->pDataBuf
, pstCurParse
->uiBufSize
, "%s", pstJsonCur
->unData
.pcStrVal
);
542 *(uint8_t *)(pstCurParse
->pDataBuf
) = (pstJsonCur
->unData
.lValue
) > 0 ? 1 : 0;
555 int vtoy_json_scan_array
559 VTOY_JSON
**ppstArrayItem
562 VTOY_JSON
*pstJsonItem
= NULL
;
564 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_ARRAY
, szKey
);
565 if (NULL
== pstJsonItem
)
567 vdebug("Key %s is not found in json data.\n", szKey
);
568 return JSON_NOT_FOUND
;
571 *ppstArrayItem
= pstJsonItem
;
576 int vtoy_json_scan_array_ex
580 VTOY_JSON
**ppstArrayItem
583 VTOY_JSON
*pstJsonItem
= NULL
;
585 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_ARRAY
, szKey
);
586 if (NULL
== pstJsonItem
)
588 vdebug("Key %s is not found in json data.\n", szKey
);
589 return JSON_NOT_FOUND
;
592 *ppstArrayItem
= pstJsonItem
->pstChild
;
597 int vtoy_json_scan_object
601 VTOY_JSON
**ppstObjectItem
604 VTOY_JSON
*pstJsonItem
= NULL
;
606 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_OBJECT
, szKey
);
607 if (NULL
== pstJsonItem
)
609 vdebug("Key %s is not found in json data.\n", szKey
);
610 return JSON_NOT_FOUND
;
613 *ppstObjectItem
= pstJsonItem
;
618 int vtoy_json_get_int
625 VTOY_JSON
*pstJsonItem
= NULL
;
627 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_NUMBER
, szKey
);
628 if (NULL
== pstJsonItem
)
630 //vdebug("Key %s is not found in json data.\n", szKey);
631 return JSON_NOT_FOUND
;
634 *piValue
= (int)pstJsonItem
->unData
.lValue
;
639 int vtoy_json_get_uint
646 VTOY_JSON
*pstJsonItem
= NULL
;
648 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_NUMBER
, szKey
);
649 if (NULL
== pstJsonItem
)
651 vdebug("Key %s is not found in json data.\n", szKey
);
652 return JSON_NOT_FOUND
;
655 *puiValue
= (uint32_t)pstJsonItem
->unData
.lValue
;
660 int vtoy_json_get_uint64
667 VTOY_JSON
*pstJsonItem
= NULL
;
669 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_NUMBER
, szKey
);
670 if (NULL
== pstJsonItem
)
672 vdebug("Key %s is not found in json data.\n", szKey
);
673 return JSON_NOT_FOUND
;
676 *pui64Value
= (uint64_t)pstJsonItem
->unData
.lValue
;
681 int vtoy_json_get_bool
688 VTOY_JSON
*pstJsonItem
= NULL
;
690 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_BOOL
, szKey
);
691 if (NULL
== pstJsonItem
)
693 vdebug("Key %s is not found in json data.\n", szKey
);
694 return JSON_NOT_FOUND
;
697 *pbValue
= pstJsonItem
->unData
.lValue
> 0 ? 1 : 0;
702 int vtoy_json_get_string
710 VTOY_JSON
*pstJsonItem
= NULL
;
712 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_STRING
, szKey
);
713 if (NULL
== pstJsonItem
)
715 //vdebug("Key %s is not found in json data.\n", szKey);
716 return JSON_NOT_FOUND
;
719 scnprintf(pcBuf
, uiBufLen
, "%s", pstJsonItem
->unData
.pcStrVal
);
724 const char * vtoy_json_get_string_ex(VTOY_JSON
*pstJson
, const char *szKey
)
726 VTOY_JSON
*pstJsonItem
= NULL
;
728 if ((NULL
== pstJson
) || (NULL
== szKey
))
733 pstJsonItem
= vtoy_json_find_item(pstJson
, JSON_TYPE_STRING
, szKey
);
734 if (NULL
== pstJsonItem
)
736 //vdebug("Key %s is not found in json data.\n", szKey);
740 return pstJsonItem
->unData
.pcStrVal
;
743 int vtoy_json_destroy(VTOY_JSON
*pstJson
)
750 if (NULL
!= pstJson
->pstChild
)
752 vtoy_json_free(pstJson
->pstChild
);
755 if (NULL
!= pstJson
->pstNext
)
757 vtoy_json_free(pstJson
->pstNext
);
765 int vtoy_json_escape_string(char *buf
, int buflen
, const char *str
, int newline
)
775 if (*str
== '"' && last
!= '\\')