Merge branch 'dev3' of https://github.com/sunchb/cson into dev3

This commit is contained in:
sunchb 2020-07-20 00:57:30 -07:00
commit ca71231aea
7 changed files with 683 additions and 157 deletions

View File

@ -1,9 +1,61 @@
INC += -I../3rd/inc
INC += -I../inc
LIB_PATH += -L../3rd/lib
MD := @mkdir -p
RM := @rm -rf
LIB_PATH += -L../output
CC=gcc
test:test.c main.c
@$(CC) $(INC) $(LIB_PATH) -g -o test test.c test2.c main.c -Wno-int-conversion -lcson -ljansson
INC += -I../inc
OUT_DIR := ./output
TARGET := $(OUT_DIR)/test
## source files
SRC_DIR = ../src
SRC_FILES += $(wildcard $(SRC_DIR)/*.c)
## adapter files
ADAP_DIR = ../adapter/cjson
ADAP_FILES += $(wildcard $(ADAP_DIR)/*.c)
## test source files
TEST_SRC_DIR = .
TEST_SRC_FILES += $(wildcard $(TEST_SRC_DIR)/*.c)
# TEST_SRC_FILES += ./test.c
# TEST_SRC_FILES += ./test5.c
# TEST_SRC_FILES += ./main.c
## *.o
OBJS += $(patsubst $(SRC_DIR)/%.c, $(OUT_DIR)/%.o, $(SRC_FILES))
OBJS += $(patsubst $(TEST_SRC_DIR)/%.c, $(OUT_DIR)/%.o, $(TEST_SRC_FILES))
OBJS += $(patsubst $(ADAP_DIR)/%.c, $(OUT_DIR)/%.o, $(ADAP_FILES))
$(TARGET):$(OBJS)
@$(CC) $(LIB_PATH) -g $(OBJS) -o $(TARGET) -fprofile-arcs -ftest-coverage
## rule for source file
$(OUT_DIR)/%.o:$(SRC_DIR)/%.c
@$(MD) $(OUT_DIR)
$(CC) $(INC) $(CFLAGS) -Wno-int-conversion -fprofile-arcs -ftest-coverage -c -g $< -o $@
$(OUT_DIR)/%.o:$(ADAP_DIR)/%.c
@$(MD) $(OUT_DIR)
$(CC) $(INC) $(CFLAGS) -Wno-int-conversion -fprofile-arcs -ftest-coverage -c -g $< -o $@
## rule for test source file
$(OUT_DIR)/%.o:$(TEST_SRC_DIR)/%.c
@$(MD) $(OUT_DIR)
$(CC) $(INC) $(CFLAGS) -Wno-int-conversion -c -g $< -o $@
.PHONY:report run clean memchk
run:$(TARGET)
$(TARGET)
report:run
lcov -d . -t test -o $(OUT_DIR)/test.info -b . -c --rc lcov_branch_coverage=1
lcov --extract $(OUT_DIR)/test.info '*.c' -o $(OUT_DIR)/finalresult.info --rc lcov_branch_coverage=1
genhtml -o $(OUT_DIR)/result $(OUT_DIR)/finalresult.info --branch-coverage
memchk:$(TARGET)
valgrind --tool=memcheck --leak-check=full $(TARGET)
clean:
@rm -rf test
@rm -rf ./output

View File

@ -1,5 +1,7 @@
extern void test1();
extern void test2();
extern void test5();
#include "cson.h"
#include "stdio.h"
@ -8,5 +10,6 @@ int main()
{
test1();
test2();
test5();
return 0;
}

View File

@ -149,11 +149,11 @@ reflect_item_t song_ref_tbl[] = {
_property_bool(SongInfo, paid),
_property_real(SongInfo, price),
_property_int_ex(SongInfo, lyricNum, _ex_args_all),
_property_array_object(SongInfo, lyric, lyric_ref_tbl, Lyric, lyricNum),
_property_array_object(SongInfo, lyric, lyric_ref_tbl, Lyric, lyricNum, 1),
_property_int_ex(SongInfo, keyNum, _ex_args_all),
_property_array_int(SongInfo, key, int, keyNum),
_property_array_int(SongInfo, key, int, keyNum, 1),
_property_int_ex(SongInfo, strNum, _ex_args_all),
_property_array_string(SongInfo, strList, char*, strNum),
_property_array_string(SongInfo, strList, char*, strNum, 1),
_property_end()
};
@ -167,7 +167,7 @@ reflect_item_t play_list_ref_tbl[] = {
_property_string(PlayList, name),
_property_string(PlayList, creater),
_property_int_ex(PlayList, songNum, _ex_args_all),
_property_array_object(PlayList, songList, song_ref_tbl, SongInfo, songNum),
_property_array_object(PlayList, songList, song_ref_tbl, SongInfo, songNum, 1),
_property_obj(PlayList, extData, ext_data_ref_tbl),
_property_end()
};
@ -199,19 +199,20 @@ void test1()
char* jstrOutput;
ret = csonStruct2JsonStr(&jstrOutput, &playList, play_list_ref_tbl);
CHECK_NUMBER(ret, 0);
printf("encode ret=%d\nJson:%s\n", ret, jstrOutput);
//printf("encode ret=%d\nJson:%s\n", ret, jstrOutput);
/*assert check*/
checkResult(&playList, jstrOutput);
free(jstrOutput);
csonFreePointer(&playList, play_list_ref_tbl);
printf("Successed %s.\n", __FUNCTION__);
}
void checkResult(PlayList* playList, char* jstrOutput){
void checkResult(PlayList* playList, char* jstrOutput)
{
const char* encodeTest = "{\"name\":\"jay zhou\",\"creater\":\"dahuaxia\",\"songList\":[{\"songName\":\"qilixiang\",\"signerName\":\"jay zhou\",\"albumName\":\"qilixiang\",\"url\":\"www.kugou.com\",\"duration\":0,\"paid\":false,\"price\":6.66,\"lyric\":[{\"time\":1,\"text\":\"Sparrow outside the window\"},{\"time\":10,\"text\":\"Multi mouth on the pole\"}],\"key\":[1111,2222,3333]},{\"songName\":\"dongfengpo\",\"signerName\":\"jay zhou\",\"albumName\":\"dongfengpo\",\"url\":\"music.qq.com\",\"duration\":180,\"paid\":true,\"price\":0.88,\"lyric\":[{\"time\":10,\"text\":\"A sad parting, standing alone in the window\"},{\"time\":20,\"text\":\"I'm behind the door pretending you're not gone\"}],\"key\":[1234,5678,9876],\"strList\":[\"abcd\",\"efgh\",\"ijkl\"]}],\"extData\":{\"a\":999,\"b\":1}}";
/* assert test */
@ -258,7 +259,7 @@ void checkResult(PlayList* playList, char* jstrOutput){
CHECK_STRING(playList->songList[1].strList[2], "ijkl");
CHECK_NUMBER(playList->extData.a, 999);
CHECK_REAL(playList->extData.b, 1);
//It is difficult to predict the output due to the accuracy problem.
//CHECK_STRING(jstrOutput, encodeTest);
}
}

View File

@ -49,14 +49,14 @@ reflect_item_t ClassInfoTbl[] = {
_property_int(ClassInfo, id),
_property_string(ClassInfo, name),
_property_int_ex(ClassInfo, childrenNum, _ex_args_all),
_property_array_object(ClassInfo, children, ClassInfoChildTbl, ClassInfoChild, childrenNum),
_property_array_object(ClassInfo, children, ClassInfoChildTbl, ClassInfoChild, childrenNum, 1),
_property_end()
};
reflect_item_t DataTbl[] = {
_property_int(Data, timestamp),
_property_int_ex(Data, infoNum, _ex_args_all),
_property_array_object(Data, info, ClassInfoTbl, ClassInfo, infoNum),
_property_array_object(Data, info, ClassInfoTbl, ClassInfo, infoNum, 1),
_property_end()
};
@ -93,7 +93,7 @@ void test2()
char* jstrOutput;
ret = csonStruct2JsonStr(&jstrOutput, &resp, ResponseTbl);
CHECK_NUMBER(ret, 0);
printf("encode ret=%d\nJson:%s\n", ret, jstrOutput);
//printf("encode ret=%d\nJson:%s\n", ret, jstrOutput);
/*assert check*/
checkResult(&resp, jstrOutput);
@ -104,8 +104,9 @@ void test2()
printf("Successed %s.\n", __FUNCTION__);
}
void checkResult(Response* resp, char* jstrOutput){
void checkResult(Response* resp, char* jstrOutput)
{
CHECK_NUMBER(resp->status, 1);
CHECK_NUMBER(resp->data.timestamp, 1579069151);
CHECK_NUMBER(resp->data.infoNum, 9);

103
demo/test5.c Normal file

File diff suppressed because one or more lines are too long

View File

@ -39,7 +39,7 @@ typedef void* cson_t;
*/
typedef cson_t (*func_cson_object_get)(const cson_t object, const char* key);
typedef cson_type (*func_cson_typeof)(cson_t object);
typedef cson_t (*func_cson_loadb)(const char *buffer, size_t buflen);
typedef cson_t (*func_cson_loadb)(const char* buffer, size_t buflen);
typedef void (*func_cson_decref)(cson_t object);
typedef const char* (*func_cson_string_value)(const cson_t object);
typedef size_t (*func_cson_string_length)(const cson_t object);
@ -96,7 +96,8 @@ typedef struct reflect_item_t {
cson_type type; /**< corresponding json type */
const struct reflect_item_t* reflect_tbl; /**< must be specified when type is object or array */
size_t arrayItemSize; /**< size of per array item. must be specified when type is array */
const char* arrayCountField; /**< field saving array size */
const char* arrayCountField; /**< field saving array size. Valid only for one-dimensional arrays, because the size of a multidimensional array cannot be saved in one number. */
int arrayDimensional; /**< dimension of array */
int exArgs; /**< paser return failure when the field is not found and nullable equals to 0 */
} reflect_item_t;
@ -112,8 +113,8 @@ extern const reflect_item_t realReflectTbl[];
#define _offset(type, field) (size_t)(&(((type*)0)->field))
#define _size(type, field) (sizeof(((type*)0)->field))
#define _property(type, field, jtype, tbl, nullable) {#field, _offset(type, field), _size(type, field), jtype, tbl, 0, NULL, nullable}
#define _property_end() {NULL, 0, 0, CSON_NULL, NULL, 0, NULL, 1}
#define _property(type, field, jtype, tbl, nullable) {#field, _offset(type, field), _size(type, field), jtype, tbl, 0, NULL, 0, nullable}
#define _property_end() {NULL, 0, 0, CSON_NULL, NULL, 0, NULL, 0, 1}
/**
* @brief Declaring integer properties.
@ -169,31 +170,32 @@ extern const reflect_item_t realReflectTbl[];
* @param tbl: property description table of type of array
* @param subType: type of array
* @param count: property to save the array size
* @param dimen: dimension of array
*
*/
#define _property_array(type, field, tbl, subType, count) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, _ex_args_nullable}
#define _property_array_object(type, field, tbl, subType, count) _property_array(type, field, tbl, subType, count)
#define _property_array_int(type, field, subType, count) _property_array(type, field, integerReflectTbl, subType, count)
#define _property_array_string(type, field, subType, count) _property_array(type, field, stringReflectTbl, subType, count)
#define _property_array_real(type, field, subType, count) _property_array(type, field, realReflectTbl, subType, count)
#define _property_array_bool(type, field, subType, count) _property_array(type, field, boolReflectTbl, subType, count)
#define _property_array(type, field, tbl, subType, count, dimen) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, dimen, _ex_args_nullable}
#define _property_array_object(type, field, tbl, subType, count, dimen) _property_array(type, field, tbl, subType, count, dimen)
#define _property_array_int(type, field, subType, count, dimen) _property_array(type, field, integerReflectTbl, subType, count, dimen)
#define _property_array_string(type, field, subType, count, dimen) _property_array(type, field, stringReflectTbl, subType, count, dimen)
#define _property_array_real(type, field, subType, count, dimen) _property_array(type, field, realReflectTbl, subType, count, dimen)
#define _property_array_bool(type, field, subType, count, dimen) _property_array(type, field, boolReflectTbl, subType, count, dimen)
/**
* @brief nonull definitions. parser will stop and return error code when field not found which declared whit it.
*
* @param refer to comment of nullable definition
*/
#define _property_int_nonull(type, field) _property(type, field, CSON_INTEGER, NULL, 0)
#define _property_real_nonull(type, field) _property(type, field, CSON_REAL, NULL, 0)
#define _property_bool_nonull(type, field) _property(type, field, CSON_TRUE, NULL, 0)
#define _property_string_nonull(type, field) _property(type, field, CSON_STRING, NULL, 0)
#define _property_obj_nonull(type, field, tbl) _property(type, field, CSON_OBJECT, tbl, 0)
#define _property_array_nonull(type, field, tbl, subType, count) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, 0}
#define _property_array_object_nonull(type, field, tbl, subType, count) _property_array_nonull(type, field, tbl, subType, count)
#define _property_array_int_nonull(type, field, subType, count) _property_array_nonull(type, field, integerReflectTbl, subType, count)
#define _property_array_string_nonull(type, field, subType, count) _property_array_nonull(type, field, stringReflectTbl, subType, count)
#define _property_array_real_nonull(type, field, subType, count) _property_array_nonull(type, field, realReflectTbl, subType, count)
#define _property_array_bool_nonull(type, field, subType, count) _property_array_nonull(type, field, boolReflectTbl, subType, count)
// #define _property_int_nonull(type, field) _property(type, field, CSON_INTEGER, NULL, 0)
// #define _property_real_nonull(type, field) _property(type, field, CSON_REAL, NULL, 0)
// #define _property_bool_nonull(type, field) _property(type, field, CSON_TRUE, NULL, 0)
// #define _property_string_nonull(type, field) _property(type, field, CSON_STRING, NULL, 0)
// #define _property_obj_nonull(type, field, tbl) _property(type, field, CSON_OBJECT, tbl, 0)
// #define _property_array_nonull(type, field, tbl, subType, count, dimen) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, dimen, 0}
// #define _property_array_object_nonull(type, field, tbl, subType, count, dimen) _property_array_nonull(type, field, tbl, subType, count, dimen)
// #define _property_array_int_nonull(type, field, subType, count, dimen) _property_array_nonull(type, field, integerReflectTbl, subType, count, dimen)
// #define _property_array_string_nonull(type, field, subType, count, dimen) _property_array_nonull(type, field, stringReflectTbl, subType, count, dimen)
// #define _property_array_real_nonull(type, field, subType, count, dimen) _property_array_nonull(type, field, realReflectTbl, subType, count, dimen)
// #define _property_array_bool_nonull(type, field, subType, count, dimen) _property_array_nonull(type, field, boolReflectTbl, subType, count, dimen)
/**
* @brief nonull definitions. parser will stop and return error code when field not found which declared whit it.
@ -206,12 +208,12 @@ extern const reflect_item_t realReflectTbl[];
#define _property_bool_ex(type, field, args) _property(type, field, CSON_TRUE, NULL, args)
#define _property_string_ex(type, field, args) _property(type, field, CSON_STRING, NULL, args)
#define _property_obj_ex(type, field, tbl, args) _property(type, field, CSON_OBJECT, tbl, args)
#define _property_array_ex(type, field, tbl, subType, count, args) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, args}
#define _property_array_object_ex(type, field, tbl, subType, count, args) _property_array_ex(type, field, tbl, subType, count)
#define _property_array_int_ex(type, field, subType, count, args) _property_array_ex(type, field, integerReflectTbl, subType, count)
#define _property_array_string_ex(type, field, subType, count, args) _property_array_ex(type, field, stringReflectTbl, subType, count)
#define _property_array_real_ex(type, field, subType, count, args) _property_array_ex(type, field, realReflectTbl, subType, count)
#define _property_array_bool_ex(type, field, subType, count, args) _property_array_ex(type, field, boolReflectTbl, subType, count)
#define _property_array_ex(type, field, tbl, subType, count, dimen, args) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, dimen, args}
#define _property_array_object_ex(type, field, tbl, subType, count, dimen, args) _property_array_ex(type, field, tbl, subType, count, dimen)
#define _property_array_int_ex(type, field, subType, count, dimen, args) _property_array_ex(type, field, integerReflectTbl, subType, count, dimen)
#define _property_array_string_ex(type, field, subType, count, dimen, args) _property_array_ex(type, field, stringReflectTbl, subType, count, dimen)
#define _property_array_real_ex(type, field, subType, count, dimen, args) _property_array_ex(type, field, realReflectTbl, subType, count, dimen)
#define _property_array_bool_ex(type, field, subType, count, dimen, args) _property_array_ex(type, field, boolReflectTbl, subType, count, dimen)
/**
* @brief function type of csonLoopProperty.
@ -276,4 +278,72 @@ void csonPrintProperty(void* pData, const reflect_item_t* tbl);
*/
void csonFreePointer(void* list, const reflect_item_t* tbl);
/*
for Multidimensional array support
*/
typedef size_t cson_array_size_t;
/**
* @brief get array memory.
*
* @param count: count of array item
* @param sizePerItem: bytes per array time
*
* @return void*.
* @attention Array header information is implied, so don't use malloc directly.
*/
void* csonArrayAlloc(cson_array_size_t count, cson_array_size_t sizePerItem);
/**
* @brief free array memory.
*
* @param ptr: array memory to be free.
*
* @return void.
* @attention Array header information is implied, so don't use free directly.
*/
void csonArrayFree(void* ptr);
/**
* @brief fast alloc multi-dimen array
*
* @param dimen: dimen of array.
* @param sizePerDimen: size of per dimen.
* @param sizeOfItem: size of item.
*
* @return void*.
*/
void* csonAllocMultiDimenArray(int dimen, cson_array_size_t* sizePerDimen, size_t sizeOfItem);
/**
* @brief the description of multidimensional array.
*/
void csonFreeMultiDimenArray(void* p);
typedef struct {
cson_array_size_t size;
cson_array_size_t cap;
int dimen;
} cson_array_header_t;
/**
* @brief get/set size of array
*
* @param p: pointer of array.
*/
#define array_size(p) ((((cson_array_header_t*)p) - 1)->size)
/**
* @brief get/set dimen of array
*
* @param p: pointer of array.
*/
#define array_dimen(p) ((((cson_array_header_t*)p) - 1)->dimen)
/**
* @brief get/set capability of array
*
* @param p: pointer of array.
*/
#define array_cap(p) ((((cson_array_header_t*)p) - 1)->cap)
#endif

View File

@ -144,6 +144,22 @@ json_obj_proc jsonObjDefaultTbl[] = {
static int csonJsonObj2Struct(cson_t jo, void* output, const reflect_item_t* tbl);
typedef struct {
cson_array_header_t header;
void* ptr;
} cson_array_t;
static int getJson1DArray(void* input, const reflect_item_t* tbl, int index, cson_t* obj);
static int parseJson1DArray(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index);
static cson_t getJsonMDArraySub(void* ptr, const reflect_item_t* tbl, int index);
static cson_t getJsonMDArrayTail(void* ptr, const reflect_item_t* tbl, int index);
static int getJsonMDArray(void* input, const reflect_item_t* tbl, int index, cson_t* obj);
static int parseJsonMDArray(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index);
static void* parseJsonMDArraySub(cson_t jo_tmp, const reflect_item_t* tbl, int index, int dimen);
static void* parseJsonMDArrayTail(cson_t jo_tmp, const reflect_item_t* tbl, int index);
static void csonLoopPropertyMDArraySub(void* pProperty, const reflect_item_t* tbl, int i, int dimen, loop_func_t func);
static int invalidCountField(const reflect_item_t* tbl);
int csonStruct2JsonStr(char** jstr, void* input, const reflect_item_t* tbl)
{
cson_t jsonPack = cson_object();
@ -175,7 +191,7 @@ int csonStruct2JsonObj(cson_t obj, void* input, const reflect_item_t* tbl)
while (1) {
if (tbl[i].field == NULL) break;
if(tbl[i].exArgs & _ex_args_exclude_encode){
if (tbl[i].exArgs & _ex_args_exclude_encode) {
i++;
continue;
}
@ -247,51 +263,11 @@ int getJsonObject(void* input, const reflect_item_t* tbl, int index, cson_t* obj
int getJsonArray(void* input, const reflect_item_t* tbl, int index, cson_t* obj)
{
int ret = ERR_NONE;
int countIndex = -1;
char* pSrc = (*(char**)((char*)input + tbl[index].offset));
if (pSrc == NULL) return ERR_MISSING_FIELD;
void* ptr = csonGetProperty(input, tbl[index].arrayCountField, tbl, &countIndex);
if (ptr == NULL || countIndex == -1) {
return ERR_MISSING_FIELD;
}
long long size = getIntegerValueFromPointer(ptr, tbl[countIndex].size);
cson_t joArray = cson_array();
long long successCount = 0;
for (long long i = 0; i < size; i++) {
cson_t jotmp;
if (tbl[index].reflect_tbl[0].field[0] == '0') { /* field start with '0' mean basic types. */
ret = jsonPackTbl[tbl[index].reflect_tbl[0].type](pSrc + (i * tbl[index].arrayItemSize), tbl[index].reflect_tbl, 0, &jotmp);
} else {
jotmp = cson_object();
ret = csonStruct2JsonObj(jotmp, pSrc + (i * tbl[index].arrayItemSize), tbl[index].reflect_tbl);
}
if (ret == ERR_NONE) {
successCount++;
cson_array_add(joArray, jotmp);
} else {
printf("create array item faild.\n");
cson_decref(jotmp);
}
}
if (successCount == 0) {
cson_decref(joArray);
return ERR_MISSING_FIELD;
if (invalidCountField(tbl + index)) {
return getJsonMDArray(input, tbl, index, obj);
} else {
*obj = joArray;
return ERR_NONE;
return getJson1DArray(input, tbl, index, obj);
}
return ret;
}
int getJsonReal(void* input, const reflect_item_t* tbl, int index, cson_t* obj)
@ -354,8 +330,8 @@ int csonJsonObj2Struct(cson_t jo, void* output, const reflect_item_t* tbl)
for (int i = 0;; i++) {
int ret = ERR_NONE;
if (tbl[i].field == NULL) break;
if(tbl[i].exArgs & _ex_args_exclude_decode){
if (tbl[i].exArgs & _ex_args_exclude_decode) {
continue;
}
@ -427,58 +403,10 @@ int parseJsonObject(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int
int parseJsonArray(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index)
{
size_t arraySize = cson_array_size(jo_tmp);
if (arraySize == 0) {
csonSetProperty(output, tbl[index].arrayCountField, &arraySize, tbl);
return ERR_NONE;
}
int countIndex = -1;
csonGetProperty(output, tbl[index].arrayCountField, tbl, &countIndex);
if (countIndex == -1) {
return ERR_MISSING_FIELD;
}
char* pMem = (char*)malloc(arraySize * tbl[index].arrayItemSize);
if (pMem == NULL) return ERR_MEMORY;
memset(pMem, 0, arraySize * tbl[index].arrayItemSize);
long long successCount = 0;
for (size_t j = 0; j < arraySize; j++) {
cson_t item = cson_array_get(jo_tmp, j);
if (item != NULL) {
int ret;
if (tbl[index].reflect_tbl[0].field[0] == '0') { /* field start with '0' mean basic types. */
ret = jsonObjProcTbl[tbl[index].reflect_tbl[0].type](item, pMem + (successCount * tbl[index].arrayItemSize), tbl[index].reflect_tbl, 0);
} else {
ret = csonJsonObj2Struct(item, pMem + (successCount * tbl[index].arrayItemSize), tbl[index].reflect_tbl);
}
if (ret == ERR_NONE) {
successCount++;
}
}
}
integer_val_t val;
if (convertInteger(successCount, tbl[countIndex].size, &val) != ERR_NONE) {
successCount = 0;
}
if (successCount == 0) {
csonSetPropertyFast(output, &successCount, tbl + countIndex);
free(pMem);
pMem = NULL;
csonSetPropertyFast(output, &pMem, tbl + index);
return ERR_MISSING_FIELD;
if (invalidCountField(tbl + index)) {
return parseJsonMDArray(jo_tmp, output, tbl, index);
} else {
csonSetPropertyFast(output, &val, tbl + countIndex);
csonSetPropertyFast(output, &pMem, tbl + index);
return ERR_NONE;
return parseJson1DArray(jo_tmp, output, tbl, index);
}
}
@ -519,8 +447,8 @@ int parseJsonObjectDefault(cson_t jo_tmp, void* output, const reflect_item_t* tb
int i = 0;
while (1) {
if (tbl[i].reflect_tbl[i].field == NULL) break;
if(tbl[i].exArgs & _ex_args_exclude_decode){
if (tbl[i].exArgs & _ex_args_exclude_decode) {
i++;
continue;
}
@ -725,16 +653,24 @@ void csonLoopProperty(void* pData, const reflect_item_t* tbl, loop_func_t func)
char* pProperty = (char*)pData + tbl[i].offset;
if (tbl[i].type == CSON_ARRAY) {
int countIndex = -1;
void* ptr = csonGetProperty(pData, tbl[i].arrayCountField, tbl, &countIndex);
if (invalidCountField(tbl + i)) {
if (pProperty == NULL) {
i++;
continue;
}
csonLoopPropertyMDArraySub(pProperty, tbl, i, tbl[i].arrayDimensional, func);
} else {
int countIndex = -1;
void* ptr = csonGetProperty(pData, tbl[i].arrayCountField, tbl, &countIndex);
if (ptr == NULL || countIndex == -1) {
continue;
}
long long size = getIntegerValueFromPointer(ptr, tbl[countIndex].size);
if (ptr == NULL || countIndex == -1) {
continue;
}
long long size = getIntegerValueFromPointer(ptr, tbl[countIndex].size);
for (long long j = 0; j < size; j++) {
csonLoopProperty(*((char**)pProperty) + j * tbl[i].arrayItemSize, tbl[i].reflect_tbl, func);
for (long long j = 0; j < size; j++) {
csonLoopProperty(*((char**)pProperty) + j * tbl[i].arrayItemSize, tbl[i].reflect_tbl, func);
}
}
} else if (tbl[i].type == CSON_OBJECT) {
csonLoopProperty(pProperty, tbl[i].reflect_tbl, func);
@ -761,22 +697,382 @@ static void* printPropertySub(void* pData, const reflect_item_t* tbl)
static void* freePointerSub(void* pData, const reflect_item_t* tbl)
{
if (tbl->type == CSON_ARRAY || tbl->type == CSON_STRING) {
if (tbl->type == CSON_STRING) {
//printf("free field %s.\n", tbl->field);
free(*(void**)pData);
*(void**)pData = NULL;
} else if (tbl->type == CSON_ARRAY) {
//printf("free field %s.\n", tbl->field);
if (invalidCountField(tbl)) {
csonArrayFree(*(void**)pData);
*(void**)pData = NULL;
} else {
free(*(void**)pData);
*(void**)pData = NULL;
}
} else {
}
return NULL;
}
void csonPrintProperty(void* pData, const reflect_item_t* tbl)
{
/* 调用loopProperty迭代结构体中的属性,完成迭代输出属性值 */
csonLoopProperty(pData, tbl, printPropertySub);
}
void csonFreePointer(void* list, const reflect_item_t* tbl)
{
/* 调用loopProperty迭代结构体中的属性,释放字符串和数组申请的内存空间 */
csonLoopProperty(list, tbl, freePointerSub);
}
int invalidCountField(const reflect_item_t* tbl)
{
return tbl->arrayDimensional > 1 || tbl->arrayCountField == NULL;
}
/* Multidimensional array functions */
cson_t getJsonMDArraySub(void* ptr, const reflect_item_t* tbl, int index)
{
if (array_dimen(ptr) == 1) {
return getJsonMDArrayTail(ptr, tbl, index);
} else {
cson_t joArray = cson_array();
cson_array_size_t size = array_size(ptr);
cson_array_size_t successCount = 0;
for (cson_array_size_t i = 0; i < size; i++) {
void** p = (void**)ptr;
cson_t jotmp = getJsonMDArraySub(p[i], tbl, index);
if (jotmp != NULL) {
successCount++;
cson_array_add(joArray, jotmp);
}
}
if (successCount == 0) {
cson_decref(joArray);
joArray = NULL;
}
return joArray;
}
}
cson_t getJsonMDArrayTail(void* ptr, const reflect_item_t* tbl, int index)
{
cson_array_size_t size = array_size(ptr);
cson_t joArray = cson_array();
cson_array_size_t successCount = 0;
for (cson_array_size_t i = 0; i < size; i++) {
cson_t jotmp;
int ret = ERR_NONE;
if (tbl[index].reflect_tbl[0].field[0] == '0') { /* field start with '0' mean basic types. */
ret = jsonPackTbl[tbl[index].reflect_tbl[0].type](ptr + (i * tbl[index].arrayItemSize), tbl[index].reflect_tbl, 0, &jotmp);
} else {
jotmp = cson_object();
ret = csonStruct2JsonObj(jotmp, ptr + (i * tbl[index].arrayItemSize), tbl[index].reflect_tbl);
}
if (ret == ERR_NONE) {
successCount++;
cson_array_add(joArray, jotmp);
} else {
printf("create array item faild.\n");
cson_decref(jotmp);
}
}
if (successCount == 0) {
cson_decref(joArray);
joArray = NULL;
}
return joArray;
}
int getJsonMDArray(void* input, const reflect_item_t* tbl, int index, cson_t* obj)
{
int ret = ERR_NONE;
int countIndex = -1;
char* pSrc = (*(char**)((char*)input + tbl[index].offset));
if (pSrc == NULL) return ERR_MISSING_FIELD;
*obj = getJsonMDArraySub(pSrc, tbl, index);
if (*obj == NULL) return ERR_MISSING_FIELD;
return ret;
}
int parseJsonMDArray(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index)
{
void* pRet = parseJsonMDArraySub(jo_tmp, tbl, index, tbl[index].arrayDimensional);
csonSetPropertyFast(output, &pRet, tbl + index);
return ERR_NONE;
}
void* parseJsonMDArraySub(cson_t jo_tmp, const reflect_item_t* tbl, int index, int dimen)
{
if (dimen == 1) {
return parseJsonMDArrayTail(jo_tmp, tbl, index);
} else {
cson_array_size_t arraySize = cson_array_size(jo_tmp);
if (arraySize == 0) return NULL;
void** pMem = (void**)csonArrayAlloc(arraySize, sizeof(void*));
array_dimen(pMem) = dimen;
cson_array_size_t successCount = 0;
for (cson_array_size_t i = 0; i < arraySize; i++) {
cson_t item = cson_array_get(jo_tmp, i);
if (cson_typeof(item) != CSON_ARRAY) continue;
void* p = parseJsonMDArraySub(item, tbl, index, dimen - 1);
if (p != NULL) {
pMem[successCount++] = p;
}
}
if (successCount == 0) {
csonArrayFree(pMem);
return NULL;
} else {
array_size(pMem) = successCount;
return (void*)pMem;
}
}
}
void* parseJsonMDArrayTail(cson_t jo_tmp, const reflect_item_t* tbl, int index)
{
size_t arraySize = cson_array_size(jo_tmp);
if (arraySize == 0) {
return NULL;
}
char* pMem = (char*)csonArrayAlloc(arraySize, tbl[index].arrayItemSize);
if (pMem == NULL) return NULL;
memset(pMem, 0, arraySize * tbl[index].arrayItemSize);
array_dimen(pMem) = 1;
cson_array_size_t successCount = 0;
for (cson_array_size_t j = 0; j < arraySize; j++) {
cson_t item = cson_array_get(jo_tmp, j);
if (item != NULL) {
int ret;
if (tbl[index].reflect_tbl[0].field[0] == '0') { /* field start with '0' mean basic types. */
ret = jsonObjProcTbl[tbl[index].reflect_tbl[0].type](item, pMem + (successCount * tbl[index].arrayItemSize), tbl[index].reflect_tbl, 0);
} else {
ret = csonJsonObj2Struct(item, pMem + (successCount * tbl[index].arrayItemSize), tbl[index].reflect_tbl);
}
if (ret == ERR_NONE) {
successCount++;
}
}
}
if (successCount == 0) {
csonArrayFree(pMem);
pMem = NULL;
} else {
array_size(pMem) = successCount;
}
return pMem;
}
void csonLoopPropertyMDArraySub(void* pProperty, const reflect_item_t* tbl, int i, int dimen, loop_func_t func)
{
if (pProperty == NULL) {
return;
}
void* ptr = *((void**)pProperty);
cson_array_size_t size = array_size(ptr);
if (dimen == 1) {
for (cson_array_size_t j = 0; j < size; j++) {
csonLoopProperty(((char*)ptr) + j * tbl[i].arrayItemSize, tbl[i].reflect_tbl, func);
}
} else {
for (cson_array_size_t j = 0; j < size; j++) {
void** p = (void**)ptr;
csonLoopPropertyMDArraySub(p + j, tbl, i, dimen - 1, func);
}
}
func(pProperty, tbl + i);
}
void* csonArrayAlloc(cson_array_size_t count, cson_array_size_t sizePerItem)
{
cson_array_header_t* pMem = (cson_array_header_t*)malloc(count * sizePerItem + sizeof(cson_array_header_t));
if (!pMem) return NULL;
pMem->cap = count;
pMem->size = 0;
return pMem + 1;
}
void csonArrayFree(void* ptr)
{
if (!ptr) return;
free(((cson_array_header_t*)ptr) - 1);
}
void* csonAllocMultiDimenArray(int dimen, cson_array_size_t* sizePerDimen, size_t sizeOfItem)
{
if (dimen <= 0 || !sizePerDimen || sizeOfItem == 0) return NULL;
if (dimen == 1) {
void* p = csonArrayAlloc(sizePerDimen[0], sizeOfItem);
array_dimen(p) = dimen;
array_size(p) = sizePerDimen[0];
return p;
} else {
void** p = (void**)csonArrayAlloc(sizePerDimen[0], sizeof(void*));
for (int i = 0; i < sizePerDimen[0]; i++) {
p[i] = csonAllocMultiDimenArray(dimen - 1, sizePerDimen + 1, sizeOfItem);
}
array_dimen(p) = dimen;
array_size(p) = sizePerDimen[0];
return (void*)p;
}
}
void csonFreeMultiDimenArray(void* p)
{
if (!p) return;
if (array_dimen(p) == 1) {
csonArrayFree(p);
} else {
cson_array_size_t size = array_size(p);
void** ptr = (void**)p;
for (int i = 0; i < size; i++) {
csonFreeMultiDimenArray(ptr[i]);
}
csonArrayFree(p);
}
}
/* one dimensional array functions */
int getJson1DArray(void* input, const reflect_item_t* tbl, int index, cson_t* obj)
{
int ret = ERR_NONE;
int countIndex = -1;
char* pSrc = (*(char**)((char*)input + tbl[index].offset));
if (pSrc == NULL) return ERR_MISSING_FIELD;
void* ptr = csonGetProperty(input, tbl[index].arrayCountField, tbl, &countIndex);
if (ptr == NULL || countIndex == -1) {
return ERR_MISSING_FIELD;
}
long long size = getIntegerValueFromPointer(ptr, tbl[countIndex].size);
cson_t joArray = cson_array();
long long successCount = 0;
for (long long i = 0; i < size; i++) {
cson_t jotmp;
if (tbl[index].reflect_tbl[0].field[0] == '0') { /* field start with '0' mean basic types. */
ret = jsonPackTbl[tbl[index].reflect_tbl[0].type](pSrc + (i * tbl[index].arrayItemSize), tbl[index].reflect_tbl, 0, &jotmp);
} else {
jotmp = cson_object();
ret = csonStruct2JsonObj(jotmp, pSrc + (i * tbl[index].arrayItemSize), tbl[index].reflect_tbl);
}
if (ret == ERR_NONE) {
successCount++;
cson_array_add(joArray, jotmp);
} else {
printf("create array item faild.\n");
cson_decref(jotmp);
}
}
if (successCount == 0) {
cson_decref(joArray);
return ERR_MISSING_FIELD;
} else {
*obj = joArray;
return ERR_NONE;
}
return ret;
}
int parseJson1DArray(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index)
{
size_t arraySize = cson_array_size(jo_tmp);
if (arraySize == 0) {
csonSetProperty(output, tbl[index].arrayCountField, &arraySize, tbl);
return ERR_NONE;
}
int countIndex = -1;
csonGetProperty(output, tbl[index].arrayCountField, tbl, &countIndex);
if (countIndex == -1) {
return ERR_MISSING_FIELD;
}
char* pMem = (char*)malloc(arraySize * tbl[index].arrayItemSize);
if (pMem == NULL) return ERR_MEMORY;
memset(pMem, 0, arraySize * tbl[index].arrayItemSize);
long long successCount = 0;
for (size_t j = 0; j < arraySize; j++) {
cson_t item = cson_array_get(jo_tmp, j);
if (item != NULL) {
int ret;
if (tbl[index].reflect_tbl[0].field[0] == '0') { /* field start with '0' mean basic types. */
ret = jsonObjProcTbl[tbl[index].reflect_tbl[0].type](item, pMem + (successCount * tbl[index].arrayItemSize), tbl[index].reflect_tbl, 0);
} else {
ret = csonJsonObj2Struct(item, pMem + (successCount * tbl[index].arrayItemSize), tbl[index].reflect_tbl);
}
if (ret == ERR_NONE) {
successCount++;
}
}
}
integer_val_t val;
if (convertInteger(successCount, tbl[countIndex].size, &val) != ERR_NONE) {
successCount = 0;
}
if (successCount == 0) {
csonSetPropertyFast(output, &successCount, tbl + countIndex);
free(pMem);
pMem = NULL;
csonSetPropertyFast(output, &pMem, tbl + index);
return ERR_MISSING_FIELD;
} else {
csonSetPropertyFast(output, &val, tbl + countIndex);
csonSetPropertyFast(output, &pMem, tbl + index);
return ERR_NONE;
}
}