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 % 446 0
Test Date: 2026-07-28 10:53:01 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) { 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
        

Generated by: LCOV version 2.0-1