From: yu.dongliang <18588496441@163.com> Date: Thu, 22 Feb 2024 04:01:08 +0000 (+0800) Subject: add a simple data pack module 'scf/pack' X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=a4bcb179f049e11a19fd760927ccdfb83633e594;p=scf.git add a simple data pack module 'scf/pack' --- diff --git a/pack/Makefile b/pack/Makefile new file mode 100644 index 0000000..4182bda --- /dev/null +++ b/pack/Makefile @@ -0,0 +1,11 @@ +CFILES += ../pack/scf_pack.c +CFILES += ../pack/main.c + +CFLAGS += -g +#CFLAGS += -Wall +CFLAGS += -I../util + +LDFLAGS += + +all: + gcc $(CFLAGS) $(CFILES) $(LDFLAGS) diff --git a/pack/main.c b/pack/main.c new file mode 100644 index 0000000..1e7e30b --- /dev/null +++ b/pack/main.c @@ -0,0 +1,34 @@ +#include"scf_pack.h" + +typedef struct { + SCF_PACK_DEF_VAR(int, x); // int x; + SCF_PACK_DEF_VAR(int, y); // int y; +} A; + +SCF_PACK_TYPE(A) +SCF_PACK_INFO_VAR(A, x), +SCF_PACK_INFO_VAR(A, y), +SCF_PACK_END(A) + + +int main() +{ + A a = {1, 2}; + A* p = NULL; + + uint8_t* buf = NULL; + int len = 0; + + scf_A_pack(&a, &buf, &len); + + int i; + for (i = 0; i < len; i++) + printf("i: %d, %#x\n", i, buf[i]); + + scf_A_unpack(&p, buf, len); + printf("p->x: %d, p->y: %d\n", p->x, p->y); + + scf_A_free(p); + free(buf); + return 0; +} diff --git a/pack/scf_pack.c b/pack/scf_pack.c new file mode 100644 index 0000000..db35901 --- /dev/null +++ b/pack/scf_pack.c @@ -0,0 +1,147 @@ +#include"scf_pack.h" + +int scf_pack(void* p, scf_pack_info_t* infos, int n_infos, uint8_t** pbuf, int* plen) +{ + if (!p || !infos || n_infos < 1 || !pbuf || !plen) + return -EINVAL; + + uint8_t* buf = *pbuf; + int len = *plen; + int i; + + if (!buf) + len = 0; + + for (i = 0; i < n_infos; i++) { + printf("name: %s, size: %ld, offset: %ld, noffset: %ld, members: %p, n_members: %ld\n", + infos[i].name, infos[i].size, infos[i].offset, infos[i].noffset, infos[i].members, infos[i].n_members); + + if (!infos[i].members) { + + uint8_t pack[8]; + int size = 0; + + switch (infos[i].size) { + case 1: + pack[0] = *(uint8_t*)(p + infos[i].offset); + size = 1; + break; + case 2: + *(uint16_t*)pack = *(uint16_t*)(p + infos[i].offset); + size = 2; + break; + case 4: + *(uint32_t*)pack = *(uint32_t*)(p + infos[i].offset); + size = 4; + break; + case 8: + *(uint64_t*)pack = *(uint64_t*)(p + infos[i].offset); + size = 8; + break; + default: + scf_loge("data type NOT support!\n"); + return -EINVAL; + break; + }; + + void* b = realloc(buf, len + size); + if (!b) + return -ENOMEM; + buf = b; + + memcpy(buf + len, pack, size); + len += size; + } + } + + *pbuf = buf; + *plen = len; + return 0; +} + +int scf_unpack(void** pp, scf_pack_info_t* infos, int n_infos, const uint8_t* buf, int len) +{ + if (!pp || !infos || n_infos < 1 || !buf || len < 1) + return -EINVAL; + + int size = infos[n_infos - 1].offset + infos[n_infos - 1].size; + + void* p = calloc(1, size); + if (!p) + return -ENOMEM; + + int i; + int j = 0; + + for (i = 0; i < n_infos; i++) { + + if (!infos[i].members) { + + switch (infos[i].size) { + case 1: + if (j + 1 <= len) + *(uint8_t*)(p + infos[i].offset) = buf[j++]; + else { + free(p); + return -EINVAL; + } + break; + + case 2: + if (j + 2 <= len) { + *(uint16_t*)(p + infos[i].offset) = *(uint16_t*)(buf + j); + j += 2; + } else { + free(p); + return -EINVAL; + } + break; + + case 4: + if (j + 4 <= len) { + *(uint32_t*)(p + infos[i].offset) = *(uint32_t*)(buf + j); + j += 4; + } else { + free(p); + return -EINVAL; + } + break; + + case 8: + if (j + 8 <= len) { + *(uint64_t*)(p + infos[i].offset) = *(uint64_t*)(buf + j); + j += 8; + } else { + free(p); + return -EINVAL; + } + break; + default: + scf_loge("data type NOT support!\n"); + return -EINVAL; + break; + }; + } + } + + *pp = p; + return 0; +} + +int scf_unpack_free(void* p, scf_pack_info_t* infos, int n_infos) +{ + if (!p || !infos || n_infos < 1) + return -EINVAL; + + int i; + for (i = 0; i < n_infos; i++) { + + if (infos[i].members) { + int ret = scf_unpack_free(p + infos[i].offset, infos[i].members, infos[i].n_members); + } + } + + free(p); + return 0; +} + diff --git a/pack/scf_pack.h b/pack/scf_pack.h new file mode 100644 index 0000000..0594d16 --- /dev/null +++ b/pack/scf_pack.h @@ -0,0 +1,60 @@ +#ifndef SCF_PACK_H +#define SCF_PACK_H + +#include"scf_def.h" + +typedef struct scf_pack_info_s scf_pack_info_t; + +struct scf_pack_info_s +{ + const char* name; + long size; + long offset; + long noffset; + scf_pack_info_t* members; + long n_members; +}; + +int scf_pack (void* p, scf_pack_info_t* infos, int n_infos, uint8_t** pbuf, int* plen); +int scf_unpack (void** pp, scf_pack_info_t* infos, int n_infos, const uint8_t* buf, int len); +int scf_unpack_free(void* p, scf_pack_info_t* infos, int n_infos); + +#define SCF_PACK_DEF_VAR(type, var) type var +#define SCF_PACK_DEF_VARS(type, vars) long n_##vars; type* vars + +#define SCF_PACK_DEF_OBJ(type, obj) type* obj +#define SCF_PACK_DEF_OBJS(type, objs) long n_##objs; type** objs + +#define SCF_PACK_N_INFOS(type) (sizeof(scf_pack_info_##type) / sizeof(scf_pack_info_##type[0])) + +#define SCF_PACK_INFO_VAR(type, var) {#var, sizeof(((type*)0)->var), offsetof(type, var), -1, NULL, 0} +#define SCF_PACK_INFO_OBJ(type, obj) {#obj, sizeof(((type*)0)->obj), offsetof(type, obj), -1, scf_pack_info_##type, SCF_PACK_N_INFOS(type)} + +#define SCF_PACK_INFO_VARS(type, vars) \ + {"n_"#vars, sizeof(((type* )0)->n_##vars), offsetof(type, n_##vars), -1, NULL, 0}, \ + {#vars, sizeof(((type* )0)->vars), offsetof(type, vars), offsetof(type, n_##vars), NULL, 0} + +#define SCF_PACK_INFO_OBJS(type, objs) \ + {"n_"#objs, sizeof(((type* )0)->n_##objs), offsetof(type, n_##objs), -1, NULL, 0}, \ + {#objs, sizeof(((type**)0)->objs), offsetof(type, objs), offsetof(type, n_##objs), scf_pack_info_##type, SCF_PACK_N_INFOS(type)} + +#define SCF_PACK_TYPE(type) \ +static scf_pack_info_t scf_pack_info_##type[] = { + + +#define SCF_PACK_END(type) \ +}; \ +static int scf_##type##_pack(A* p, uint8_t** pbuf, int* plen) \ +{ \ + return scf_pack(p, scf_pack_info_##type, SCF_PACK_N_INFOS(type), pbuf, plen); \ +} \ +static int scf_##type##_unpack(A** pp, uint8_t* buf, int len) \ +{ \ + return scf_unpack((void**)pp, scf_pack_info_##type, SCF_PACK_N_INFOS(type), buf, len); \ +} \ +static int scf_##type##_free(A* p) \ +{ \ + return scf_unpack_free(p, scf_pack_info_##type, SCF_PACK_N_INFOS(type)); \ +} + +#endif