diff --git a/demo/test.c b/demo/test.c index dcbb739..ee30712 100644 --- a/demo/test.c +++ b/demo/test.c @@ -104,11 +104,9 @@ typedef struct { int duration; int paid; double price; - size_t lyricNum; Lyric* lyric; size_t keyNum; int* key; - size_t strNum; char** strList; } SongInfo; @@ -120,7 +118,6 @@ typedef struct { typedef struct { char* name; char* creater; - size_t songNum; SongInfo* songList; ExtData extData; } PlayList; @@ -142,12 +139,10 @@ reflect_item_t song_ref_tbl[] = { _property_int(SongInfo, duration), _property_bool(SongInfo, paid), _property_real(SongInfo, price), - _property_int(SongInfo, lyricNum), - _property_array_object(SongInfo, lyric, lyric_ref_tbl, Lyric, lyricNum), + _property_array_object(SongInfo, lyric, lyric_ref_tbl, Lyric), _property_int(SongInfo, keyNum), - _property_array_int(SongInfo, key, int, keyNum), - _property_int(SongInfo, strNum), - _property_array_string(SongInfo, strList, char*, strNum), + _property_array_int(SongInfo, key, int), + _property_array_string(SongInfo, strList, char*), _property_end() }; @@ -160,8 +155,7 @@ reflect_item_t ext_data_ref_tbl[] = { reflect_item_t play_list_ref_tbl[] = { _property_string(PlayList, name), _property_string(PlayList, creater), - _property_int(PlayList, songNum), - _property_array_object(PlayList, songList, song_ref_tbl, SongInfo, songNum), + _property_array_object(PlayList, songList, song_ref_tbl, SongInfo), _property_obj(PlayList, extData, ext_data_ref_tbl), _property_end() }; @@ -187,6 +181,8 @@ void test1() printf("ret=%d\n", ret); csonPrintProperty(&playList, play_list_ref_tbl); + size_t s = csonGetArraySizeByField(&playList, "songList", play_list_ref_tbl); + char* jstrOutput; ret = csonStruct2JsonStr(&jstrOutput, &playList, play_list_ref_tbl); printf("ret=%d\nJson:%s\n", ret, jstrOutput); diff --git a/demo/test2.c b/demo/test2.c index 720bc36..ae14e7a 100644 --- a/demo/test2.c +++ b/demo/test2.c @@ -12,13 +12,11 @@ typedef struct { char* icon; int id; char* name; - char childrenNum; ClassInfoChild* children; } ClassInfo; typedef struct { long long timestamp; - int infoNum; ClassInfo* info; } Data; @@ -39,15 +37,13 @@ reflect_item_t ClassInfoTbl[] = { _property_string(ClassInfo, icon), _property_int(ClassInfo, id), _property_string(ClassInfo, name), - _property_int(ClassInfo, childrenNum), - _property_array_object(ClassInfo, children, ClassInfoChildTbl, ClassInfoChild, childrenNum), + _property_array_object(ClassInfo, children, ClassInfoChildTbl, ClassInfoChild), _property_end() }; reflect_item_t DataTbl[] = { _property_int(Data, timestamp), - _property_int(Data, infoNum), - _property_array_object(Data, info, ClassInfoTbl, ClassInfo, infoNum), + _property_array_object(Data, info, ClassInfoTbl, ClassInfo), _property_end() }; diff --git a/inc/cson.h b/inc/cson.h index e7b719c..c5f3bae 100644 --- a/inc/cson.h +++ b/inc/cson.h @@ -34,6 +34,8 @@ typedef enum { typedef void* cson_t; +typedef size_t cson_array_size_t; + /** * @brief define the function type of json parse/pack function group */ @@ -95,8 +97,7 @@ typedef struct reflect_item_t { size_t size; /**< size of property */ 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 */ - char* arrayCountField; /**< field saving array size */ + size_t arrayItemSize; /**< size of per array item. must be specified when type is array */ int nullable; /**< paser return failure when the field is not found and nullable equals to 0 */ } reflect_item_t; @@ -107,8 +108,8 @@ extern const reflect_item_t realReflectTbl[]; #define _offset(type, field) (&(((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, nullable} +#define _property_end() {NULL, 0, 0, CSON_NULL, NULL, 0, 1} /** * @brief Declaring integer properties. @@ -163,15 +164,14 @@ extern const reflect_item_t realReflectTbl[]; * @param field: field name of properties * @param tbl: property description table of type of array * @param subType: type of array - * @param count: property to save the array size * */ -#define _property_array(type, field, tbl, subType, count) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, 1} -#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) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), 1} +#define _property_array_object(type, field, tbl, subType) _property_array(type, field, tbl, subType) +#define _property_array_int(type, field, subType) _property_array(type, field, integerReflectTbl, subType) +#define _property_array_string(type, field, subType) _property_array(type, field, stringReflectTbl, subType) +#define _property_array_real(type, field, subType) _property_array(type, field, realReflectTbl, subType) +#define _property_array_bool(type, field, subType) _property_array(type, field, boolReflectTbl, subType) /** * @brief nonull definitions. parser will stop and return error code when field not found which declared whit it. @@ -183,12 +183,12 @@ extern const reflect_item_t realReflectTbl[]; #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_array_nonull(type, field, tbl, subType) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), 0} +#define _property_array_object_nonull(type, field, tbl, subType) _property_array_nonull(type, field, tbl, subType, count) +#define _property_array_int_nonull(type, field, subType) _property_array_nonull(type, field, integerReflectTbl, subType) +#define _property_array_string_nonull(type, field, subType) _property_array_nonull(type, field, stringReflectTbl, subType) +#define _property_array_real_nonull(type, field, subType) _property_array_nonull(type, field, realReflectTbl, subType) +#define _property_array_bool_nonull(type, field, subType) _property_array_nonull(type, field, boolReflectTbl, subType) /** * @brief function type of csonLoopProperty. @@ -253,4 +253,9 @@ void csonPrintProperty(void* pData, const reflect_item_t* tbl); */ void csonFreePointer(void* list, const reflect_item_t* tbl); + +cson_array_size_t csonGetArraySize(void* pArray); + + +cson_array_size_t csonGetArraySizeByField(void* pData, const char* field, const reflect_item_t* tbl); #endif \ No newline at end of file diff --git a/src/cson.c b/src/cson.c index 63de238..94dbb8e 100644 --- a/src/cson.c +++ b/src/cson.c @@ -35,22 +35,22 @@ extern cson_interface csomImpl; #define cson_is_bool(type) (type == CSON_TRUE || type == CSON_FALSE) const reflect_item_t integerReflectTbl[] = { - {"0Integer", 0, sizeof(int), CSON_INTEGER, NULL, 0, NULL, 1}, + {"0Integer", 0, sizeof(int), CSON_INTEGER, NULL, 0, 1}, {} }; const reflect_item_t stringReflectTbl[] = { - {"0String", 0, sizeof(char*), CSON_STRING, NULL, 0, NULL, 1}, + {"0String", 0, sizeof(char*), CSON_STRING, NULL, 0, 1}, {} }; const reflect_item_t realReflectTbl[] = { - {"0Real", 0, sizeof(double), CSON_REAL, NULL, 0, NULL, 1}, + {"0Real", 0, sizeof(double), CSON_REAL, NULL, 0, 1}, {} }; const reflect_item_t boolReflectTbl[] = { - {"0Bool", 0, sizeof(int), CSON_TRUE, NULL, 0, NULL, 1}, + {"0Bool", 0, sizeof(int), CSON_TRUE, NULL, 0, 1}, {} }; @@ -248,18 +248,13 @@ int getJsonArray(void* input, const reflect_item_t* tbl, int index, cson_t* obj) 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_array_size_t size = *((cson_array_size_t*)(pSrc - sizeof(cson_array_size_t))); cson_t joArray = cson_array(); - long long successCount = 0; + cson_array_size_t successCount = 0; - for (long long i = 0; i < size; i++) { + for (cson_array_size_t i = 0; i < size; i++) { cson_t jotmp; if (tbl[index].reflect_tbl[0].field[0] == '0') { /* field start with '0' mean basic types. */ @@ -421,30 +416,24 @@ int parseJsonArray(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int i size_t arraySize = cson_array_size(jo_tmp); if (arraySize == 0) { - csonSetProperty(output, tbl[index].arrayCountField, &arraySize, tbl); + char* pTemp = NULL; + csonSetPropertyFast(output, &pTemp, tbl + index); 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); + char* pMem = (char*)malloc(arraySize * tbl[index].arrayItemSize + sizeof(cson_array_size_t)); if (pMem == NULL) return ERR_MEMORY; - long long successCount = 0; - for (size_t j = 0; j < arraySize; j++) { + 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); + ret = jsonObjProcTbl[tbl[index].reflect_tbl[0].type](item, pMem + sizeof(cson_array_size_t) + (successCount * tbl[index].arrayItemSize), tbl[index].reflect_tbl, 0); } else { - ret = csonJsonObj2Struct(item, pMem + (successCount * tbl[index].arrayItemSize), tbl[index].reflect_tbl); + ret = csonJsonObj2Struct(item, pMem + sizeof(cson_array_size_t) + (successCount * tbl[index].arrayItemSize), tbl[index].reflect_tbl); } if (ret == ERR_NONE) { @@ -453,20 +442,15 @@ int parseJsonArray(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int i } } - 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); + *((cson_array_size_t*)pMem) = successCount; + pMem += sizeof(cson_array_size_t); + csonSetPropertyFast(output, (char*)&pMem, tbl + index); return ERR_NONE; } } @@ -708,15 +692,15 @@ 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 (ptr == NULL || countIndex == -1) { + if(*((void**)pProperty) == NULL){ + i++; continue; } - long long size = getIntegerValueFromPointer(ptr, tbl[countIndex].size); + //cson_array_size_t size = **((cson_array_size_t**)(pProperty - sizeof(cson_array_size_t))); - for (long long j = 0; j < size; j++) { + cson_array_size_t size = *((cson_array_size_t*)(*((char**)pProperty) - sizeof(cson_array_size_t))); + + for (cson_array_size_t j = 0; j < size; j++) { csonLoopProperty(*((char**)pProperty) + j * tbl[i].arrayItemSize, tbl[i].reflect_tbl, func); } } else if (tbl[i].type == CSON_OBJECT) { @@ -744,9 +728,14 @@ 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); + }else if(tbl->type == CSON_ARRAY){ + printf("free field %s.\n", tbl->field); + free((*(char**)pData) - sizeof(cson_array_size_t)); + }else{ + } return NULL; } @@ -761,4 +750,17 @@ void csonFreePointer(void* list, const reflect_item_t* tbl) { /* 调用loopProperty迭代结构体中的属性,释放字符串和数组申请的内存空间 */ csonLoopProperty(list, tbl, freePointerSub); +} + +cson_array_size_t csonGetArraySize(void* pArray){ + if(pArray == NULL){ + return 0; + } + + return *((cson_array_size_t*)((char*)pArray - sizeof(cson_array_size_t))); +} + +cson_array_size_t csonGetArraySizeByField(void* pData, const char* field, const reflect_item_t* tbl){ + void* pArray = csonGetProperty(pData, field, tbl, NULL); + return csonGetArraySize(*((void**)pArray)); } \ No newline at end of file