LCOV - code coverage report
Current view: top level - runtime/c/c_base/src - json_parser.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 460 0.0 %
Date: 2026-08-27 13:24:42 Functions: 0 41 0.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           0 :     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           0 :     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           0 :     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           0 :             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           0 :             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           0 :     CJsonParser parser;
     687           0 :     InitCJsonParser(&parser, jsonContent, jsonLen);
     688           0 :     return CJsonParseByParser(&parser);
     689             : }
     690             : 
     691           0 : CJsonObj *CJsonFileParse(const char *filePath)
     692             : {
     693           0 :     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           0 :     CJsonParser parser;
     769           0 :     InitCJsonFileParser(&parser, filePath);
     770             : 
     771           0 :     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           0 :     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 1.14