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