LCOV - code coverage report
Current view: top level - runtime_compact/c_base/src - json_parser.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 450 0
Test Date: 2026-08-06 15:29:52 Functions: 0.0 % 41 0

            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
        

Generated by: LCOV version 2.0-1