Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 : #include <limits.h>
11 : #include <stdlib.h>
12 : #include <math.h>
13 : #include <ctype.h>
14 : #include "securec.h"
15 : #include "mmpa_api.h"
16 : #include "json_parser.h"
17 : #ifdef __cplusplus
18 : extern "C" {
19 : #endif
20 :
21 : #define JSON_CONTANT_LEN_MAX 0x7FFFFFFFU
22 : typedef struct {
23 : const char *jsonContent;
24 : size_t contentLen;
25 : size_t parserIndex;
26 : bool fileJson;
27 : } CJsonParser;
28 :
29 : typedef struct {
30 : char *key;
31 : CJsonObj value;
32 : } CJsonKeyObj;
33 :
34 : typedef struct {
35 : const char *data;
36 : size_t len;
37 : size_t escapeCharNum;
38 : } CJsonString;
39 :
40 : static char g_decimalPoint = '.';
41 :
42 0 : CJsonObj *CJsonArrayAt(CJsonObj *obj, size_t i)
43 : {
44 0 : return (CJsonObj *)((obj->type != CJSON_ARRAY) ? NULL : VectorAt(&obj->value.array, i));
45 : }
46 :
47 0 : static inline char GetDecimalPoint(void)
48 : {
49 0 : return g_decimalPoint;
50 : }
51 :
52 0 : static inline void InitCJsonParseZero(CJsonParser *parser)
53 : {
54 0 : parser->contentLen = 0;
55 0 : parser->jsonContent = NULL;
56 0 : parser->parserIndex = 0;
57 0 : parser->fileJson = false;
58 0 : }
59 :
60 0 : static void InitCJsonParser(CJsonParser *parser, const char *jsonContent, size_t jsonLen)
61 : {
62 0 : parser->contentLen = jsonLen;
63 0 : parser->jsonContent = jsonContent;
64 0 : parser->parserIndex = 0;
65 0 : parser->fileJson = false;
66 0 : }
67 :
68 0 : static void InitCJsonFileParser(CJsonParser *parser, const char *filePath)
69 : {
70 : char resolvedPath[PATH_MAX];
71 0 : int32_t ret = mmRealPath(filePath, resolvedPath, PATH_MAX);
72 0 : InitCJsonParseZero(parser);
73 0 : if (ret != EN_OK) {
74 0 : return;
75 : }
76 0 : mmFileHandle *fd = mmOpenFile(resolvedPath, FILE_READ);
77 0 : if (fd == NULL) {
78 0 : return;
79 : }
80 0 : (void)mmSeekFile(fd, 0, MM_SEEK_FILE_END);
81 0 : long contentLen = mmTellFile(fd);
82 0 : if ((contentLen > 0) && ((uint32_t)contentLen <= JSON_CONTANT_LEN_MAX)) {
83 0 : if (mmSeekFile(fd, 0, MM_SEEK_FILE_BEGIN) == EN_OK) {
84 0 : char *jsonContent = (char *)mmMalloc((unsigned long long)contentLen);
85 0 : if (jsonContent == NULL) {
86 0 : mmCloseFile(fd);
87 0 : return;
88 : }
89 0 : mmReadFile(jsonContent, sizeof(char), (int32_t)contentLen, fd);
90 0 : parser->jsonContent = jsonContent;
91 0 : parser->contentLen = (size_t)contentLen;
92 0 : parser->fileJson = (parser->jsonContent != NULL);
93 : }
94 : }
95 :
96 0 : mmCloseFile(fd);
97 0 : return;
98 : }
99 :
100 0 : static void DeInitCJsonParser(CJsonParser *parser)
101 : {
102 0 : if (parser->fileJson) {
103 0 : (void)mmFree((void *)parser->jsonContent);
104 0 : parser->jsonContent = NULL;
105 0 : parser->contentLen = 0;
106 : }
107 0 : InitCJsonParseZero(parser);
108 0 : }
109 :
110 0 : static inline bool CheckValidSpace(CJsonParser *parser, size_t space)
111 : {
112 0 : return (space <= (parser->contentLen - parser->parserIndex));
113 : }
114 :
115 0 : static inline const char *ParseContent(CJsonParser *parser)
116 : {
117 0 : return &parser->jsonContent[parser->parserIndex];
118 : }
119 :
120 0 : static inline bool CheckCJsonKey(CJsonParser *parser, const char *key, size_t keyLen)
121 : {
122 0 : return CheckValidSpace(parser, keyLen) ? (strncmp(ParseContent(parser), key, keyLen) == 0) : false;
123 : }
124 :
125 0 : static inline bool CheckCJsonKeyChar(CJsonParser *parser, char key)
126 : {
127 0 : return (CheckValidSpace(parser, 1) && (ParseContent(parser)[0] == key));
128 : }
129 :
130 0 : static inline void SkipUtf8Bom(CJsonParser *parser)
131 : {
132 0 : const char *bom = "\xEF\xBB\xBF";
133 0 : const size_t bomlen = 3;
134 0 : if (CheckCJsonKey(parser, bom, bomlen)) {
135 0 : parser->parserIndex += bomlen;
136 : }
137 0 : }
138 :
139 0 : static inline void SkipWhiteSpace(CJsonParser *parser)
140 : {
141 : #define MIN_VISIBLE_CHAR 33
142 0 : size_t index = parser->parserIndex;
143 0 : while ((index < parser->contentLen) && (parser->jsonContent[index] < MIN_VISIBLE_CHAR)) {
144 0 : index++;
145 : }
146 0 : parser->parserIndex = index;
147 0 : }
148 :
149 0 : static inline bool ParseNullKey(CJsonParser *parser, CJsonObj *value)
150 : {
151 : #define KEY_NULL_LEN 4UL
152 0 : if (CheckCJsonKey(parser, "null", KEY_NULL_LEN)) {
153 0 : parser->parserIndex += KEY_NULL_LEN;
154 0 : if (value != NULL) {
155 0 : value->type = CJSON_NULL;
156 : }
157 0 : return true;
158 : }
159 0 : return false;
160 : }
161 :
162 0 : static inline bool ParseTrueKey(CJsonParser *parser, CJsonObj *value)
163 : {
164 : #define KEY_TRUE_LEN 4UL
165 0 : if (CheckCJsonKey(parser, "true", KEY_TRUE_LEN)) {
166 0 : parser->parserIndex += KEY_TRUE_LEN;
167 0 : if (value != NULL) {
168 0 : value->type = CJSON_BOOL;
169 0 : value->value.value = true;
170 : }
171 0 : return true;
172 : }
173 0 : return false;
174 : }
175 :
176 0 : static inline bool ParseFalseKey(CJsonParser *parser, CJsonObj *value)
177 : {
178 : #define KEY_FALSE_LEN 5UL
179 0 : if (CheckCJsonKey(parser, "false", KEY_FALSE_LEN)) {
180 0 : parser->parserIndex += KEY_FALSE_LEN;
181 0 : if (value != NULL) {
182 0 : value->type = CJSON_BOOL;
183 0 : value->value.value = false;
184 : }
185 0 : return true;
186 : }
187 0 : return false;
188 : }
189 :
190 0 : static double StrTod(char *str, char **endPtr)
191 : {
192 : #define TEN 10
193 0 : char *strIn = str;
194 0 : int32_t sign = 1;
195 0 : double result = 0.0;
196 0 : int32_t decimalPoint = 0;
197 0 : int32_t exponent = 0;
198 0 : int32_t expSign = 1;
199 :
200 : // 跳过空白字符
201 0 : while (isspace((int32_t)(*strIn))) {
202 0 : ++strIn;
203 : }
204 :
205 : // 处理正负号
206 0 : if (*strIn == '+') {
207 0 : ++strIn;
208 0 : } else if (*strIn == '-') {
209 0 : sign = -1;
210 0 : ++strIn;
211 : }
212 :
213 : // 转换整数部分
214 0 : while (isdigit((int32_t)(*strIn))) {
215 0 : result = result * TEN + (*strIn - '0');
216 0 : ++strIn;
217 : }
218 :
219 : // 处理小数点
220 0 : if (*strIn == '.') {
221 0 : ++strIn;
222 0 : while (isdigit((int32_t)(*strIn))) {
223 0 : ++decimalPoint;
224 0 : result = result * TEN + (*strIn - '0');
225 0 : ++strIn;
226 : }
227 0 : result /= pow(TEN, decimalPoint);
228 : }
229 :
230 : // 处理指数
231 0 : if (*strIn == 'e' || *strIn == 'E') {
232 0 : ++strIn;
233 0 : if (*strIn == '+') {
234 0 : ++strIn;
235 0 : } else if (*strIn == '-') {
236 0 : expSign = -1;
237 0 : ++strIn;
238 : }
239 0 : while (isdigit((int32_t)(*strIn))) {
240 0 : exponent = exponent * TEN + (*strIn - '0');
241 0 : ++strIn;
242 : }
243 0 : result *= pow(TEN, exponent * expSign);
244 : }
245 :
246 : // 设置endPtr
247 0 : if (endPtr != NULL) {
248 0 : *endPtr = strIn;
249 : }
250 :
251 0 : return sign * result;
252 : }
253 :
254 0 : static bool ParseNumber(CJsonParser *parser, CJsonObj *value)
255 : {
256 : #define MAX_NUMBER_LEN 64U
257 0 : char numStr[MAX_NUMBER_LEN + 1] = "\0";
258 0 : size_t end = parser->contentLen - parser->parserIndex;
259 0 : const char *data = &parser->jsonContent[parser->parserIndex];
260 : size_t i;
261 0 : CJSON_TYPE type = CJSON_INT;
262 :
263 0 : end = (end > MAX_NUMBER_LEN) ? MAX_NUMBER_LEN : end;
264 0 : for (i = 0; i < end; i++, data++) {
265 0 : if (((*data >= '0') && (*data <= '9')) || (*data == '+') || (*data == '-')) {
266 0 : numStr[i] = *data;
267 0 : continue;
268 : }
269 :
270 0 : if ((*data == 'e') || (*data == 'E')) {
271 0 : type = CJSON_DOUBLE;
272 0 : numStr[i] = *data;
273 0 : continue;
274 : }
275 :
276 0 : if (*data == '.') {
277 0 : numStr[i] = GetDecimalPoint();
278 0 : type = CJSON_DOUBLE;
279 0 : continue;
280 : }
281 :
282 0 : break;
283 : }
284 0 : if (i == 0) {
285 0 : return false;
286 : }
287 :
288 0 : numStr[i] = '\0';
289 0 : char *afterEnd = numStr;
290 0 : int64_t iNumber = 0;
291 0 : double fNumber = 0;
292 0 : if (type == CJSON_INT) {
293 0 : iNumber = strtoll(numStr, &afterEnd, 0);
294 : } else {
295 0 : fNumber = StrTod(numStr, &afterEnd);
296 : }
297 0 : if (numStr == afterEnd) {
298 0 : return false;
299 : }
300 :
301 0 : if (value != NULL) {
302 0 : value->type = type;
303 0 : if (type == CJSON_INT) {
304 0 : value->value.iNumber = iNumber;
305 : } else {
306 0 : value->value.fNumber = fNumber;
307 : }
308 : }
309 :
310 0 : parser->parserIndex += afterEnd - numStr;
311 0 : return true;
312 : }
313 :
314 0 : static char *NewCStringByJsonString(CJsonString *jsonString)
315 : {
316 0 : size_t validLen = jsonString->len - jsonString->escapeCharNum;
317 0 : char *string = (char *)mmMalloc(validLen + 1);
318 0 : if (string == NULL) {
319 0 : return NULL;
320 : }
321 :
322 0 : if (jsonString->escapeCharNum == 0) {
323 0 : errno_t ret = memcpy_s(string, validLen, jsonString->data, jsonString->len);
324 0 : if (ret != EOK) {
325 0 : mmFree(string);
326 0 : return NULL;
327 : }
328 0 : string[validLen] = '\0';
329 0 : return string;
330 : }
331 :
332 0 : size_t index = 0;
333 0 : const char *endData = jsonString->data + jsonString->len;
334 0 : for (const char *srcString = jsonString->data; (srcString < endData) && (index < validLen); srcString++, index++) {
335 0 : if (*srcString != '\\') {
336 0 : string[index] = *(srcString);
337 0 : continue;
338 : }
339 :
340 0 : srcString++;
341 0 : switch (*srcString) {
342 0 : case 'b':
343 0 : string[index] = '\b';
344 0 : break;
345 0 : case 'f':
346 0 : string[index] = '\f';
347 0 : break;
348 0 : case 'n':
349 0 : string[index] = '\n';
350 0 : break;
351 0 : case 'r':
352 0 : string[index] = '\r';
353 0 : break;
354 0 : case 't':
355 0 : string[index] = '\t';
356 0 : break;
357 0 : case '\"':
358 : case '\\':
359 : case '/':
360 0 : string[index] = *srcString;
361 0 : break;
362 : // 暂不支持 utf16
363 0 : default:
364 0 : mmFree(string);
365 0 : return NULL;
366 : }
367 : }
368 0 : string[index] = '\0';
369 0 : return string;
370 : }
371 :
372 0 : static bool ParseCJsonString(CJsonParser *parser, CJsonString *string)
373 : {
374 0 : if (!CheckCJsonKeyChar(parser, '\"')) {
375 0 : return false;
376 : }
377 :
378 0 : size_t index = parser->parserIndex + 1;
379 0 : const char *data = &parser->jsonContent[index];
380 0 : string->escapeCharNum = 0;
381 0 : while ((index < parser->contentLen) && (*data != '\"')) {
382 0 : if (*data == '\\') {
383 0 : (string->escapeCharNum)++;
384 0 : index++;
385 0 : data++;
386 0 : if (index >= parser->contentLen) {
387 0 : return false;
388 : }
389 : }
390 0 : index++;
391 0 : data++;
392 : }
393 :
394 0 : if ((index >= parser->contentLen) || (*data != '\"')) {
395 0 : return false;
396 : }
397 :
398 0 : parser->parserIndex++;
399 0 : string->data = &parser->jsonContent[parser->parserIndex];
400 0 : string->len = (size_t)(((uintptr_t)data) - ((uintptr_t)string->data));
401 0 : parser->parserIndex = index + 1;
402 0 : return true;
403 : }
404 :
405 0 : static bool ParseString(CJsonParser *parser, CJsonObj *value)
406 : {
407 : CJsonString jsonString;
408 0 : if (!ParseCJsonString(parser, &jsonString)) {
409 0 : return false;
410 : }
411 :
412 0 : if (value == NULL) {
413 0 : return true;
414 : }
415 0 : value->value.string = NewCStringByJsonString(&jsonString);
416 0 : if (value->value.string == NULL) {
417 0 : return false;
418 : }
419 0 : value->type = CJSON_STRING;
420 0 : return true;
421 : }
422 :
423 0 : static int CJsonKeyCmp(void *a, void *b, void *appInfo)
424 : {
425 : (void)appInfo;
426 0 : return strcmp(((CJsonKeyObj *)a)->key, ((CJsonKeyObj *)b)->key);
427 : }
428 :
429 0 : static inline CJsonObj *NewCJsonObj(void)
430 : {
431 0 : CJsonObj *obj = (CJsonObj *)mmMalloc(sizeof(CJsonObj));
432 0 : if (obj != NULL) {
433 0 : obj->type = CJSON_NULL;
434 : }
435 0 : return obj;
436 : }
437 :
438 0 : static inline void DeInitCJsonObj(CJsonObj *obj)
439 : {
440 0 : switch (obj->type) {
441 0 : case CJSON_STRING:
442 0 : mmFree(obj->value.string);
443 0 : break;
444 0 : case CJSON_OBJ:
445 0 : DeInitSortVector(&obj->value.objs);
446 0 : break;
447 0 : case CJSON_ARRAY:
448 0 : DeInitVector(&obj->value.array);
449 0 : break;
450 0 : default:
451 0 : break;
452 : }
453 0 : }
454 :
455 0 : void FreeCJsonObj(CJsonObj *obj)
456 : {
457 0 : if (obj == NULL) {
458 0 : return;
459 : }
460 0 : DeInitCJsonObj(obj);
461 0 : mmFree((void *)obj);
462 : }
463 :
464 : typedef bool (*PFN_ParseValue)(CJsonParser *parser, CJsonObj *value);
465 : typedef struct {
466 : char key;
467 : PFN_ParseValue pfnParse;
468 : } KeyCharParsePair;
469 :
470 0 : static inline bool ParseKey(CJsonParser *parser, char **key)
471 : {
472 : CJsonString jsonString;
473 0 : if (!ParseCJsonString(parser, &jsonString)) {
474 0 : return false;
475 : }
476 :
477 0 : if (key == NULL) {
478 0 : return true;
479 : }
480 :
481 0 : *key = NewCStringByJsonString(&jsonString);
482 0 : return (*key != NULL);
483 : }
484 :
485 0 : static bool ParseSimpleValue(CJsonParser *parser, CJsonObj *value)
486 : {
487 : static PFN_ParseValue keyValueParse[] = {ParseNullKey, ParseTrueKey, ParseFalseKey, ParseNumber};
488 : static size_t count = sizeof(keyValueParse) / sizeof(keyValueParse[0]);
489 0 : for (size_t i = 0; i < count; i++) {
490 0 : if (keyValueParse[i](parser, value)) {
491 0 : return true;
492 : }
493 : }
494 0 : return false;
495 : }
496 :
497 : extern bool ParseCJsonObj(CJsonParser *parser, CJsonObj *value);
498 0 : static inline size_t ParseKeyValuePair(CJsonParser *parser, char **key, CJsonObj *obj)
499 : {
500 : // parse key
501 0 : if (!ParseKey(parser, key)) {
502 0 : return 0;
503 : }
504 :
505 : // parse :
506 0 : SkipWhiteSpace(parser);
507 0 : bool validJson = CheckValidSpace(parser, 1) && (ParseContent(parser)[0] == ':');
508 0 : size_t valueIndex = 0;
509 0 : if (validJson) {
510 0 : parser->parserIndex++;
511 :
512 : // parse value
513 0 : SkipWhiteSpace(parser);
514 0 : valueIndex = parser->parserIndex;
515 0 : validJson = ParseCJsonObj(parser, obj);
516 : }
517 :
518 0 : if (!validJson && (key != NULL) && (*key != NULL)) {
519 0 : mmFree(*key);
520 : }
521 0 : return validJson ? valueIndex : 0;
522 : }
523 :
524 0 : static void DeInitCJsonKeyObj(void *item)
525 : {
526 0 : CJsonKeyObj *obj = (CJsonKeyObj *)item;
527 0 : if (obj->key != NULL) {
528 0 : mmFree(obj->key);
529 0 : DeInitCJsonObj(&obj->value);
530 : }
531 0 : }
532 :
533 0 : static bool ParseObj(CJsonParser *parser, CJsonObj *value)
534 : {
535 : // skip {
536 0 : parser->parserIndex++;
537 :
538 0 : if (value != NULL) {
539 0 : value->type = CJSON_OBJ;
540 0 : InitSortVector(&value->value.objs, sizeof(CJsonKeyObj), CJsonKeyCmp, NULL);
541 0 : SetSortVectorDestroyItem(&value->value.objs, DeInitCJsonKeyObj);
542 : }
543 :
544 0 : size_t itemSize = 0;
545 0 : bool validJson = true;
546 0 : SkipWhiteSpace(parser);
547 0 : while (validJson && CheckValidSpace(parser, 1) && (ParseContent(parser)[0] != '}')) {
548 0 : if (itemSize > 0) {
549 : // parse ,
550 0 : if (CheckValidSpace(parser, 1) && (ParseContent(parser)[0] != ',')) {
551 0 : validJson = false;
552 0 : break;
553 : }
554 0 : parser->parserIndex++;
555 0 : SkipWhiteSpace(parser);
556 : }
557 :
558 0 : if (value != NULL) {
559 : CJsonKeyObj obj;
560 0 : validJson = (ParseKeyValuePair(parser, &obj.key, &obj.value) != 0);
561 0 : if (!validJson) {
562 0 : break;
563 : }
564 0 : if (EmplaceSortVector(&value->value.objs, &obj) == NULL) {
565 0 : DeInitCJsonKeyObj(&obj);
566 0 : validJson = false;
567 0 : break;
568 : }
569 : } else {
570 0 : validJson = (ParseKeyValuePair(parser, NULL, NULL) != 0);
571 : }
572 :
573 0 : itemSize++;
574 0 : SkipWhiteSpace(parser);
575 : }
576 :
577 0 : if ((!validJson) || (!CheckCJsonKeyChar(parser, '}'))) {
578 0 : if (value != NULL) {
579 0 : DeInitSortVector(&value->value.objs);
580 : }
581 0 : return false;
582 : }
583 :
584 0 : parser->parserIndex++;
585 0 : return true;
586 : }
587 :
588 0 : static void DestroyCJsonArrayItem(void *item)
589 : {
590 0 : DeInitCJsonObj((CJsonObj *)item);
591 0 : }
592 :
593 0 : static bool ParseArray(CJsonParser *parser, CJsonObj *value)
594 : {
595 0 : parser->parserIndex++;
596 :
597 0 : Vector *array = NULL;
598 0 : if (value != NULL) {
599 0 : value->type = CJSON_ARRAY;
600 0 : array = &value->value.array;
601 0 : InitVector(array, sizeof(CJsonObj));
602 0 : SetVectorDestroyItem(array, DestroyCJsonArrayItem);
603 : }
604 :
605 0 : size_t itemSize = 0;
606 0 : bool validJson = true;
607 0 : SkipWhiteSpace(parser);
608 0 : while (validJson && CheckValidSpace(parser, 1) && (ParseContent(parser)[0] != ']')) {
609 0 : if (itemSize > 0) {
610 0 : if (!CheckCJsonKeyChar(parser, ',')) {
611 0 : validJson = false;
612 0 : break;
613 : }
614 0 : parser->parserIndex++;
615 0 : SkipWhiteSpace(parser);
616 : }
617 0 : if (array != NULL) {
618 : CJsonObj obj;
619 0 : validJson = ParseCJsonObj(parser, &obj);
620 0 : if (!validJson) {
621 0 : break;
622 : }
623 0 : if (EmplaceBackVector(array, &obj) == NULL) {
624 0 : validJson = false;
625 0 : DeInitCJsonObj(&obj);
626 0 : break;
627 : }
628 : } else {
629 0 : validJson = ParseCJsonObj(parser, NULL);
630 : }
631 :
632 0 : itemSize++;
633 0 : SkipWhiteSpace(parser);
634 : }
635 :
636 0 : if ((!validJson) || (!CheckCJsonKeyChar(parser, ']'))) {
637 0 : if (array != NULL) {
638 0 : DeInitVector(array);
639 : }
640 0 : return false;
641 : }
642 :
643 0 : parser->parserIndex++;
644 0 : return true;
645 : }
646 :
647 0 : static bool ParseStructValue(CJsonParser *parser, CJsonObj *value)
648 : {
649 : static KeyCharParsePair keyCharParsePair[] = {{'\"', ParseString}, {'{', ParseObj}, {'[', ParseArray}};
650 : static const size_t count = sizeof(keyCharParsePair) / sizeof(keyCharParsePair[0]);
651 0 : for (size_t i = 0; i < count; i++) {
652 0 : if (CheckCJsonKeyChar(parser, keyCharParsePair[i].key)) {
653 0 : return keyCharParsePair[i].pfnParse(parser, value);
654 : }
655 : }
656 0 : return false;
657 : }
658 :
659 0 : bool ParseCJsonObj(CJsonParser *parser, CJsonObj *value)
660 : {
661 0 : SkipWhiteSpace(parser);
662 0 : if (ParseSimpleValue(parser, value)) {
663 0 : return true;
664 : }
665 :
666 0 : return ParseStructValue(parser, value);
667 : }
668 :
669 0 : static CJsonObj *CJsonParseByParser(CJsonParser *parser)
670 : {
671 0 : CJsonObj *obj = NewCJsonObj();
672 0 : if (obj == NULL) {
673 0 : return NULL;
674 : }
675 :
676 0 : SkipUtf8Bom(parser);
677 0 : if (!ParseCJsonObj(parser, obj) || (parser->parserIndex != parser->contentLen)) {
678 0 : FreeCJsonObj(obj);
679 0 : return NULL;
680 : }
681 0 : return obj;
682 : }
683 :
684 0 : CJsonObj *CJsonParse(const char *jsonContent, size_t jsonLen)
685 : {
686 : CJsonParser parser;
687 0 : InitCJsonParser(&parser, jsonContent, jsonLen);
688 0 : return CJsonParseByParser(&parser);
689 : }
690 :
691 0 : CJsonObj *CJsonFileParse(const char *filePath)
692 : {
693 : CJsonParser parser;
694 0 : InitCJsonFileParser(&parser, filePath);
695 0 : CJsonObj *jsonObj = CJsonParseByParser(&parser);
696 0 : DeInitCJsonParser(&parser);
697 0 : return jsonObj;
698 : }
699 :
700 0 : CJsonObj *GetCJsonSubObj(CJsonObj *obj, const char *key)
701 : {
702 0 : if (obj->type != CJSON_OBJ) {
703 0 : return NULL;
704 : }
705 0 : CJsonKeyObj cmpKey = {(char*)key, {0}};
706 0 : CJsonKeyObj *keyObj = (CJsonKeyObj *)SortVectorAtKey(&obj->value.objs, &cmpKey);
707 0 : if (keyObj == NULL) {
708 0 : return NULL;
709 : }
710 0 : return &keyObj->value;
711 : }
712 :
713 0 : static size_t ParseObjSubKeyPosition(CJsonParser *parser, const char *key, size_t *offset)
714 : {
715 : // skip {
716 0 : parser->parserIndex++;
717 :
718 0 : size_t objSize = 0;
719 0 : size_t len = 0;
720 0 : SkipWhiteSpace(parser);
721 0 : while (CheckValidSpace(parser, 1) && (ParseContent(parser)[0] != '}')) {
722 0 : if (objSize > 0) {
723 : // parse ,
724 0 : if (CheckValidSpace(parser, 1) && (ParseContent(parser)[0] != ',')) {
725 0 : return 0;
726 : }
727 0 : parser->parserIndex++;
728 0 : SkipWhiteSpace(parser);
729 : }
730 :
731 0 : char *curkey = NULL;
732 0 : size_t valueIndex = ParseKeyValuePair(parser, &curkey, NULL);
733 0 : if (valueIndex == 0) {
734 0 : return 0;
735 : }
736 :
737 0 : if (strcmp(curkey, key) == 0) {
738 0 : *offset = valueIndex;
739 0 : len = parser->parserIndex - valueIndex;
740 : }
741 :
742 0 : objSize++;
743 0 : SkipWhiteSpace(parser);
744 0 : mmFree(curkey);
745 : }
746 :
747 0 : if (!CheckCJsonKeyChar(parser, '}')) {
748 0 : return 0;
749 : }
750 :
751 0 : parser->parserIndex++;
752 0 : return len;
753 : }
754 :
755 0 : static size_t ParseCJsonKeyObjPosition(CJsonParser *parser, const char *key, size_t *offset)
756 : {
757 0 : SkipUtf8Bom(parser);
758 0 : SkipWhiteSpace(parser);
759 :
760 0 : if (!CheckCJsonKeyChar(parser, '{')) {
761 0 : return 0;
762 : }
763 0 : return ParseObjSubKeyPosition(parser, key, offset);
764 : }
765 :
766 0 : char *CJsonFileParseKey(const char *filePath, const char *key)
767 : {
768 : CJsonParser parser;
769 0 : InitCJsonFileParser(&parser, filePath);
770 :
771 : size_t offset;
772 0 : size_t len = ParseCJsonKeyObjPosition(&parser, key, &offset);
773 0 : char *value = NULL;
774 0 : if (len > 0) {
775 0 : value = (char *)mmMalloc(len + 1);
776 0 : if (value != NULL) {
777 0 : errno_t ret = memcpy_s(value, len, parser.jsonContent + offset, len);
778 0 : if (ret != EOK) {
779 0 : mmFree(value);
780 0 : value = NULL;
781 : } else {
782 0 : value[len] = '\0';
783 : }
784 : }
785 : }
786 0 : DeInitCJsonParser(&parser);
787 0 : return value;
788 : }
789 :
790 0 : size_t CJsonParseKeyPosition(const char *jsonContent, size_t jsonLen, const char *key, size_t *offset)
791 : {
792 : CJsonParser parser;
793 0 : InitCJsonParser(&parser, jsonContent, jsonLen);
794 0 : return ParseCJsonKeyObjPosition(&parser, key, offset);
795 : }
796 :
797 : #ifdef __cplusplus
798 : }
799 : #endif
|