scf/pack: add a simpile compression algorithm
authoryu.dongliang <18588496441@163.com>
Sat, 9 Mar 2024 05:40:21 +0000 (13:40 +0800)
committeryu.dongliang <18588496441@163.com>
Sat, 9 Mar 2024 05:40:21 +0000 (13:40 +0800)
pack/main.c
pack/scf_pack.c

index 64f1e6f2218f7044c68dfbbd6f5ae183478f929e..8d1d344f903cf61f6e7d537806a1c1694703ee5b 100644 (file)
@@ -26,7 +26,7 @@ int main()
 {
        int z0[] = {1, 2, 3, 4};
        int z1[] = {5, 6};
-       A  a0 = {7, 8, sizeof(z0) / sizeof(z0[0]), z0};
+       A  a0 = {0x90, 0xff, sizeof(z0) / sizeof(z0[0]), z0};
        A  a1 = {9, 10, sizeof(z1) / sizeof(z1[0]), z1};
        A* as[] = {&a0, &a1};
 
@@ -46,7 +46,7 @@ int main()
        int j;
        for (i = 0; i < len; i++)
                printf("i: %d, %#x\n", i, buf[i]);
-
+#if 1
        scf_B_unpack(&p, buf, len);
        printf("p: %p, p->as: %p\n", p, p->as);
        printf("p->d: %lg, p->n_as: %ld, p->as: %p\n", p->d, p->n_as, p->as);
@@ -55,7 +55,7 @@ int main()
                printf("p->as[%d]: %p\n", i, p->as[i]);
 
                A* a = p->as[i];
-               printf("a->x: %d, a->y: %d, a->n_z: %ld,a->z: %p\n", a->x,a->y, a->n_z, a->z);
+               printf("a->x: %#x, a->y: %#x, a->n_z: %ld,a->z: %p\n", a->x,a->y, a->n_z, a->z);
 
                for (j = 0; j < a->n_z; j++)
                        printf("a->z[%d]: %d\n", j, a->z[j]);
@@ -64,5 +64,6 @@ int main()
 
        scf_B_free(p);
        free(buf);
+#endif
        return 0;
 }
index 4ece50d9ca8a541721ee0948259fe53043f06a93..a4f76a8567a6aee119c27c73ad330712b3836516 100644 (file)
@@ -1,8 +1,323 @@
 #include"scf_pack.h"
 
+int __scf_pack_one_index(uint8_t* pack, uint64_t u, int shift)
+{
+       int max  = -1;
+       int bits = 1u << shift;
+       int i;
+       int j;
+       int k;
+
+       j = 0;
+       k = 3;
+       for (i = bits - 1; i >= 0; i--) {
+
+               if (!(u & (1ull << i)))
+                       continue;
+
+               if (-1 == max)
+                       max = i;
+               else
+                       max -= i;
+               scf_loge("max: %d, i: %d, j: %d, k: %d, shift: %d\n", max, i, j, k, shift);
+
+               pack[j] |= max << k;
+
+               if (8 - k < shift) {
+                       pack[++j] = max >> (8 - k);
+                       k = shift - (8 - k);
+               } else
+                       k += shift;
+
+               if (i < 2)
+                       shift  = 1;
+               else if (i < 4)
+                       shift  = 2;
+
+               else if (i < 8)
+                       shift  = 3;
+               else if (i < 16)
+                       shift  = 4;
+
+               else if (i < 32)
+                       shift  = 5;
+               else if (i < 64)
+                       shift  = 6;
+               else {
+                       scf_loge("pack error\n");
+                       return -EINVAL;
+               }
+
+               scf_logi("max: %d, i: %d, j: %d, k: %d, shift: %d\n\n", max, i, j, k, shift);
+
+               max = i;
+       }
+
+       if (8 - k < shift && 0 != max) {
+               pack[++j] = 0;
+               scf_logi("max: %d, i: %d, j: %d, k: %d, shift: %d\n\n", max, i, j, k, shift);
+       }
+
+       return j + 1;
+}
+
+int __scf_pack_byte_map(uint8_t* pack, uint64_t u, int shift)
+{
+       uint8_t* p = (uint8_t*)&u;
+       uint8_t map = 0;
+
+       int bytes = 1u << shift >> 3;
+       int i;
+       int j;
+       int k;
+
+       pack[0] |= 0x4;
+       j = 0;
+       k = 4;
+
+       for (i = 0; i < bytes; i++) {
+               if (p[i])
+                       map |= 1u << i;
+       }
+
+       if (((1u << bytes) - 1) & ~map) {
+               pack[0] |= 0x8;
+               pack[j] |= map << k;
+
+               if (bytes > k) {
+                       pack[++j] = map >> (8 - k);
+                       k = bytes - k;
+               } else
+                       k += bytes;
+       }
+
+       for (i = 0; i < bytes; i++) {
+               if (p[i]) {
+                       pack[++j] = p[i];
+                       scf_logi("bytes: %d, map: %#x, i: %d, j: %d, p[i]: %#x\n", bytes, map, i, j, p[i]);
+               }
+       }
+
+       return j + 1;
+}
+
+int __scf_pack2(uint8_t* pack, uint64_t u, int shift)
+{
+       int sum  = 0;
+       int not  = 0;
+       int bits = 1u << shift;
+       int i;
+
+       for (i = 0; i < bits; i++) {
+               if (u & (1ull << i))
+                       sum++;
+       }
+
+       if (sum > (bits >> 1)) { // bits / 2
+               not = 1;
+               sum = bits - sum;
+               u = ~u;
+       }
+
+       scf_logw("bits: %d, not: %d, u: %#lx, sum: %d\n", bits, not, u, sum);
+
+       pack[0] = not;
+
+       if (u < 64) {
+               pack[0] |= u << 2;
+               return 1;
+       }
+
+       pack[0] |= 0x2;
+
+       if (sum < 4)
+               return __scf_pack_one_index(pack, u, shift);
+       return __scf_pack_byte_map(pack, u, shift);
+}
+
+int __scf_unpack2(void* p, int shift, const uint8_t* buf, int len)
+{
+       int bits = 1u << shift;
+       int max  = -1;
+       int i;
+       int j;
+       int k;
+
+       if (len < 1)
+               return -EINVAL;
+
+       uint64_t u = 0;
+
+       if (!(buf[0] & 0x2)) {
+
+               u = buf[0] >> 2;
+               j = 1;
+
+       } else if (!(buf[0] & 0x4)) {
+               j = 0;
+               k = 3;
+
+               while (1) {
+                       if (j >= len)
+                               return -EINVAL;
+
+                       i = (buf[j] >> k) & ((1u << shift) - 1);
+
+                       if (shift > 8 - k) {
+                               if (++j >= len)
+                                       return -EINVAL;
+
+                               i |= buf[j] << (8 - k);
+                               i &= (1u << shift) - 1;
+                               k  = shift - (8 - k);
+                       } else
+                               k += shift;
+
+                       if (-1 == max)
+                               max = i;
+                       else if (0 == i)
+                               break;
+                       else
+                               max -= i;
+
+                       u |= 1u << max;
+
+                       if (i < 2)
+                               shift  = 1;
+                       else if (i < 4)
+                               shift  = 2;
+
+                       else if (i < 8)
+                               shift  = 3;
+                       else if (i < 16)
+                               shift  = 4;
+
+                       else if (i < 32)
+                               shift  = 5;
+                       else if (i < 64)
+                               shift  = 6;
+                       else {
+                               scf_loge("unpack error\n");
+                               return -EINVAL;
+                       }
+
+                       scf_logi("max: %d, i: %d, j: %d, k: %d, shift: %d\n\n", max, i, j, k, shift);
+
+                       max = i;
+               }
+
+               j++;
+               scf_logi("u: %ld, %#lx\n", u, u);
+
+       } else if (!(buf[0] & 0x8)) {
+               j = 1;
+
+               for (k = 0; k < bits / 8; k++) {
+
+                       if (j >= len)
+                               return -EINVAL;
+
+                       uint64_t u8 = buf[j];
+
+                       u |= u8 << (k << 3);
+
+                       scf_loge("buf[%d]: %#x, u: %#lx\n", j, buf[j], u);
+                       j++;
+               }
+
+       } else {
+               uint8_t map = buf[0] >> 4;
+
+               if (bits > 32) {
+                       if (1 >= len)
+                               return -EINVAL;
+
+                       map |= buf[1] & 0xf;
+                       j = 2;
+               } else
+                       j = 1;
+
+               for (k = 0; k < bits / 8; k++) {
+                       if (!(map & (1u << k)))
+                               continue;
+
+                       if (j >= len)
+                               return -EINVAL;
+
+                       uint64_t u8 = buf[j++];
+
+                       u |= u8 << (k << 3);
+               }
+       }
+
+       if (buf[0] & 0x1)
+               u = ~u;
+
+       switch (bits) {
+               case 32:
+                       *(uint32_t*)p = u;
+                       break;
+               case 64:
+                       *(uint64_t*)p = u;
+                       break;
+               default:
+                       scf_loge("bits %d Not support!\n", bits);
+                       return -EINVAL;
+                       break;
+       };
+
+       return j;
+}
+
+int __scf_unpack(void* p, int size, const uint8_t* buf, int len)
+{
+       switch (size) {
+               case 1:
+                       if (1 <= len) {
+                               *(uint8_t*)p = buf[0];
+                               return 1;
+                       }
+                       break;
+
+               case 2:
+                       if (2 <= len) {
+                               *(uint16_t*)p = *(uint16_t*)buf;
+                               return 2;
+                       }
+                       break;
+
+               case 4:
+#if 0
+                       if (4 <= len) {
+                               *(uint32_t*)p = *(uint32_t*)buf;
+                               return 4;
+                       }
+#else
+                       return __scf_unpack2(p, 5, buf, len);
+#endif
+                       break;
+
+               case 8:
+#if 0
+                       if (8 <= len) {
+                               *(uint64_t*)p = *(uint64_t*)buf;
+                               return 8;
+                       }
+#else
+                       return __scf_unpack2(p, 6, buf, len);
+#endif
+                       break;
+               default:
+                       scf_loge("data type NOT support!\n");
+                       break;
+       };
+
+       return -EINVAL;
+}
+
 int __scf_pack(void* p, int size, uint8_t** pbuf, int* plen)
 {
-       uint8_t pack[8];
+       uint8_t pack[64];
        int     len = 0;
 
        switch (size) {
@@ -15,14 +330,26 @@ int __scf_pack(void* p, int size, uint8_t** pbuf, int* plen)
                        len = 2;
                        break;
                case 4:
-                       scf_logi("p: %p, %d\n", p, *(uint32_t*)p);
+#if 1
+                       len = __scf_pack2(pack, *(uint32_t*)p, 5);
+                       if (len < 0)
+                               return len;
+#else
                        *(uint32_t*)pack = *(uint32_t*)p;
                        len = 4;
+#endif
+                       scf_logi("p: %p, %d, len: %d\n\n", p, *(uint32_t*)p, len);
                        break;
                case 8:
-                       scf_logi("p: %p, %ld, %#lx, %lg\n", p, *(uint64_t*)p, *(uint64_t*)p, *(double*)p);
+#if 1
+                       len = __scf_pack2(pack, *(uint64_t*)p, 6);
+                       if (len < 0)
+                               return len;
+#else
                        *(uint64_t*)pack = *(uint64_t*)p;
                        len = 8;
+#endif
+                       scf_logi("p: %p, %ld, %#lx, %lg, len: %d\n\n", p, *(uint64_t*)p, *(uint64_t*)p, *(double*)p, len);
                        break;
                default:
                        scf_loge("data size '%d' NOT support!\n", size);
@@ -106,44 +433,6 @@ int scf_pack(void* p, scf_pack_info_t* infos, int n_infos, uint8_t** pbuf, int*
        return 0;
 }
 
-int __scf_unpack(void* p, int size, const uint8_t* buf, int len)
-{
-       switch (size) {
-               case 1:
-                       if (1 <= len) {
-                               *(uint8_t*)p = buf[0];
-                               return 1;
-                       }
-                       break;
-
-               case 2:
-                       if (2 <= len) {
-                               *(uint16_t*)p = *(uint16_t*)buf;
-                               return 2;
-                       }
-                       break;
-
-               case 4:
-                       if (4 <= len) {
-                               *(uint32_t*)p = *(uint32_t*)buf;
-                               return 4;
-                       }
-                       break;
-
-               case 8:
-                       if (8 <= len) {
-                               *(uint64_t*)p = *(uint64_t*)buf;
-                               return 8;
-                       }
-                       break;
-               default:
-                       scf_loge("data type NOT support!\n");
-                       break;
-       };
-
-       return -EINVAL;
-}
-
 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)