add a simple data pack module 'scf/pack'
authoryu.dongliang <18588496441@163.com>
Thu, 22 Feb 2024 04:01:08 +0000 (12:01 +0800)
committeryu.dongliang <18588496441@163.com>
Thu, 22 Feb 2024 04:01:08 +0000 (12:01 +0800)
pack/Makefile [new file with mode: 0644]
pack/main.c [new file with mode: 0644]
pack/scf_pack.c [new file with mode: 0644]
pack/scf_pack.h [new file with mode: 0644]

diff --git a/pack/Makefile b/pack/Makefile
new file mode 100644 (file)
index 0000000..4182bda
--- /dev/null
@@ -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 (file)
index 0000000..1e7e30b
--- /dev/null
@@ -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 (file)
index 0000000..db35901
--- /dev/null
@@ -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 (file)
index 0000000..0594d16
--- /dev/null
@@ -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