Efficient serialization in C tpl

tpl 主页
tpl 文档
tpl github

主要是对 tpl文档 中的数组表示进行说明以及代码测试
关于文档后面的 peek jot hook gather 内容 我也没有详细阅读 代码里也就没有相关测试了

数组主要分为两种 固定数组 fixed-length-array 以及 变长数组 variable-length-array

  • 固定数组表示为 i# 或者 c# 等等
  • 变长数组表示为 A(i) 或者 A© 等等 (关于字符串类型s的使用不在这里描述)

关于这两种不同表示的pack和unpack是不一样的

  • 固定数组是一次pack完毕的 tpl_pack(tn, 0) unpack也是一次解压
  • 变长数组是一次pack一个数据 tpl_pack(tn, 1) unpack也是多次解压

关于上面pack时的参数 0 和 1 的 index 说明 (是我自己看完文档之后自己的解释)

  • 当使用了类型A时 这个参数时index才有意义 没有A类型时 全部都是一次压缩和解压都使用 index 0
  • 有类型 A 存在时 index 仅仅按照顺序表示每一个 A 中的元素 与是否嵌套或者其他关系无法 只和顺序有关
    若在 A(…) 之外存在其他类型字段时那么 0 表示其他非 A(…) 的全部字段
  • A(A(i)) index 1 表示第一个A index 2 表示第二个 A 在 pack 时需要根据嵌套关系先压 index2 的数据 在压 index1 的数据
    testVariableLengthArrayPack2 函数是对 类型 A(A(i)) 的测试
  • icA(A(i))i 此时除了 index 1 和 2 以外 还需要压一次 index 为 0 的数据 将开头的 ic 和 末尾的 i 数据进行压入

使用 tpl_Alen 函数可以在 unpack 之前得到变长数组的长度 在 testVariableLengthArrayUnpackChar2 中可以看到这个函数的用法

关于以上数组的说明请自行阅读一下几个函数弄清楚区别
testFixedLengthArrayPackChar
testFixedLengthArrayUnpackChar
testVariableLengthArrayPackChar
testVariableLengthArrayUnpackChar

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include "../extra/tpl.h"

int storing(int argc, char *argv[])
{
    tpl_node *tn;
    int id = 0;
    char *name, *names[] = {"joe", "bob", "cary"};

    tn = tpl_map("A(is)", &id, &name);

    for (name = names[0]; id < 3; name = names[++id])
    {
        tpl_pack(tn, 1);
    }

    tpl_dump(tn, TPL_FILE, "users.tpl");
    tpl_free(tn);
}

int reloading(int argc, char *argv[])
{
    tpl_node *tn;
    int id;
    char *name;

    tn = tpl_map("A(is)", &id, &name);
    tpl_load(tn, TPL_FILE, "users.tpl");

    while (tpl_unpack(tn, 1) > 0)
    {
        printf("id %d, user %s\n", id, name);
        free(name);
    }
    tpl_free(tn);
}

// --------------------------------------------------------------------
// 数字数组
int testFixedLengthArrayPack(int argc, char *argv[])
{
    tpl_node *tn;
    int x[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    tn = tpl_map("i#", x, 10);
    tpl_pack(tn, 0); /* pack all 10 elements at once */
    tpl_dump(tn, TPL_FILE, "fixed.tpl");
    tpl_free(tn);
}

int testVariableLengthArrayPack(int argc, char *argv[])
{
    tpl_node *tn;
    int x;

    tn = tpl_map("A(i)", &x);
    for (x = 0; x < 10; x++)
    {
        tpl_pack(tn, 1); /* pack one element at a time */
    }
    tpl_dump(tn, TPL_FILE, "variable.tpl");
    tpl_free(tn);
}

int testFixedLengthArrayUnpack(int argc, char *argv[])
{
    tpl_node *tn;
    int x[10];

    tn = tpl_map("i#", x, 10);
    tpl_load(tn, TPL_FILE, "fixed.tpl");
    tpl_unpack(tn, 0); /* unpack all 10 elements at once */
    tpl_free(tn);
    for (int i = 0; i < 10; ++i)
    {
        printf("%d ", x[i]); /* unpack one by one */
    }
    printf("\n");
    /* now do something with x[0]...x[9].. (not shown) */
}

int testVariableLengthArrayUnpack(int argc, char *argv[])
{
    tpl_node *tn;
    int x;

    tn = tpl_map("A(i)", &x);
    tpl_load(tn, TPL_FILE, "variable.tpl");
    while (tpl_unpack(tn, 1) > 0)
    {
        printf("%d ", x); /* unpack one by one */
    }
    printf("\n");
    tpl_free(tn);
}

// --------------------------------------------------------------------
// 字符数组 字符串
int testFixedLengthArrayPackChar(int argc, char *argv[])
{
    tpl_node *tn;
    char x[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'};

    tn = tpl_map("c#", x, 10);
    tpl_pack(tn, 0); /* pack all 10 elements at once */
    tpl_dump(tn, TPL_FILE, "fixedchar.tpl");
    tpl_free(tn);
}

int testVariableLengthArrayPackChar(int argc, char *argv[])
{
    tpl_node *tn;
    int x;
    char c;

    tn = tpl_map("A(c)", &c);
    for (x = 0; x < 10; ++x)
    {
        c = 'a' + x;
        tpl_pack(tn, 1); /* pack one element at a time */
    }
    tpl_dump(tn, TPL_FILE, "variablechar.tpl");
    tpl_free(tn);
}

int testFixedLengthArrayUnpackChar(int argc, char *argv[])
{
    tpl_node *tn;
    char x[10];

    tn = tpl_map("c#", x, 10);
    tpl_load(tn, TPL_FILE, "fixedchar.tpl");
    tpl_unpack(tn, 0); /* unpack all 10 elements at once */
    tpl_free(tn);
    for (int i = 0; i < 10; ++i)
    {
        printf("%c ", x[i]); /* unpack one by one */
    }
    printf("\n");
    /* now do something with x[0]...x[9].. (not shown) */
}

int testVariableLengthArrayUnpackChar(int argc, char *argv[])
{
    tpl_node *tn;
    char c;

    tn = tpl_map("A(c)", &c);
    tpl_load(tn, TPL_FILE, "variablechar.tpl");
    while (tpl_unpack(tn, 1) > 0)
    {
        printf("%c ", c); /* unpack one by one */
    }
    printf("\n");
    tpl_free(tn);
}

// --------------------------------------------------------------------
// 二维数字数组
int testFixedLengthArrayPack2(int argc, char *argv[])
{
    tpl_node *tn;
    int x[2][3] = {{1, 2, 3}, {4, 5, 6}};

    tn = tpl_map("i##", x, 2, 3);
    tpl_pack(tn, 0); /* pack all 10 elements at once */
    tpl_dump(tn, TPL_FILE, "fixed2.tpl");
    tpl_free(tn);
}

int testVariableLengthArrayPack2(int argc, char *argv[])
{
    tpl_node *tn;
    int x;

    tn = tpl_map("A(A(i))", &x);
    for (x = 0; x < 10; x++)
    {
        if (x <= 6)
        {
            tpl_pack(tn, 2); /* pack one element at a time */
            if (x == 6)
            {
                tpl_pack(tn, 1);
            }
        }
        else
        {
            tpl_pack(tn, 2); /* pack one element at a time */
            if (x == 9)
            {
                tpl_pack(tn, 1);
            }
        }
    }
    tpl_dump(tn, TPL_FILE, "variable2.tpl");
    tpl_free(tn);
}

int testFixedLengthArrayUnpack2(int argc, char *argv[])
{
    tpl_node *tn;
    int x[2][3];

    tn = tpl_map("i##", x, 2, 3);
    tpl_load(tn, TPL_FILE, "fixed2.tpl");
    tpl_unpack(tn, 0); /* unpack all 10 elements at once */
    tpl_free(tn);
    for (int i = 0; i < 2; ++i)
    {
        for (int j = 0; j < 3; ++j)
        {
            printf("%d ", x[i][j]); /* unpack one by one */
        }
        printf("\n------\n");
    }
    printf("\n");
    /* now do something with x[0]...x[9].. (not shown) */
}

int testVariableLengthArrayUnpack2(int argc, char *argv[])
{
    tpl_node *tn;
    int x;

    tn = tpl_map("A(A(i))", &x);
    tpl_load(tn, TPL_FILE, "variable2.tpl");
    while (tpl_unpack(tn, 1) > 0)
    {
        while (tpl_unpack(tn, 2) > 0)
        {
            printf("%d ", x); /* unpack one by one */
        }
        printf("\n------\n");
    }
    printf("\n");
    tpl_free(tn);
}

// --------------------------------------------------------------------
// 二维字符数组 字符串
int testFixedLengthArrayPackChar2(int argc, char *argv[])
{
    tpl_node *tn;
    char x[2][3] = {{'a', 'b', 'c'}, {'d', 'e', 'f'}};

    tn = tpl_map("c##", x, 2, 3);
    tpl_pack(tn, 0); /* pack all 10 elements at once */
    tpl_dump(tn, TPL_FILE, "fixedchar2.tpl");
    tpl_free(tn);
}

int testVariableLengthArrayPackChar2(int argc, char *argv[])
{
    tpl_node *tn;
    char c;

    tn = tpl_map("A(A(c))", &c);
    for (int x = 0; x < 10; x++)
    {
        c = 'a' + x;
        if (x <= 6)
        {
            tpl_pack(tn, 2); /* pack one element at a time */
            if (x == 6)
            {
                tpl_pack(tn, 1);
            }
        }
        else
        {
            tpl_pack(tn, 2); /* pack one element at a time */
            if (x == 9)
            {
                tpl_pack(tn, 1);
            }
        }
    }
    tpl_dump(tn, TPL_FILE, "variablechar2.tpl");
    tpl_free(tn);
}

int testFixedLengthArrayUnpackChar2(int argc, char *argv[])
{
    tpl_node *tn;
    char x[2][3];

    tn = tpl_map("c##", x, 2, 3);
    tpl_load(tn, TPL_FILE, "fixedchar2.tpl");
    tpl_unpack(tn, 0); /* unpack all 10 elements at once */
    tpl_free(tn);
    for (int i = 0; i < 2; ++i)
    {
        for (int j = 0; j < 3; ++j)
        {
            printf("%c ", x[i][j]); /* unpack one by one */
        }
        printf("\n------\n");
    }
    printf("\n");
    /* now do something with x[0]...x[9].. (not shown) */
}

int testVariableLengthArrayUnpackChar2(int argc, char *argv[])
{
    tpl_node *tn;
    char x;

    tn = tpl_map("A(A(c))", &x);
    tpl_load(tn, TPL_FILE, "variablechar2.tpl");
    int num_elements1 = 0;
    int num_elements2 = 0;
    num_elements1 = tpl_Alen(tn, 1);
    printf("num_elements1 %d \n", num_elements1);
    while (tpl_unpack(tn, 1) > 0)
    {
        num_elements2 = tpl_Alen(tn, 2);
        printf("num_elements2 %d \n", num_elements2);
        while (tpl_unpack(tn, 2) > 0)
        {

            printf("%c ", x); /* unpack one by one */
        }
        printf("\n------\n");
    }
    printf("\n");
    tpl_free(tn);
}

// --------------------------------------------------------------------
// 使用类型s 在 type 表中表示为 string char**

int testStringPack(int argc, char *argv[])
{
    tpl_node *tn;
    char *s = "hello, world!";
    tn = tpl_map("s", &s);
    tpl_pack(tn, 0); /* copies "hello, world!" into the tpl */
    tpl_dump(tn, TPL_FILE, "string.tpl");
    tpl_free(tn);
}

int testStringUnpack(int argc, char *argv[])
{
    tpl_node *tn;
    char *s;
    tn = tpl_map("s", &s);
    tpl_load(tn, TPL_FILE, "string.tpl");
    tpl_unpack(tn, 0); /* allocates space, points s to "hello, world!" */
    printf("unpacked %s\n", s);
    free(s); /* our responsibility to free s */
    tpl_free(tn);
}

// --------------------------------------------------------------------
// 二维固定s

int testStringPack2(int argc, char *argv[])
{
    char *labels[2][3] = {{"one", "two", "three"},
                          {"eins", "zwei", "drei"}};
    tpl_node *tn;
    tn = tpl_map("s##", labels, 2, 3);
    tpl_pack(tn, 0);
    tpl_dump(tn, TPL_FILE, "string2.tpl");
    tpl_free(tn);
}

int testStringUnpack2(int argc, char *argv[])
{
    char *olabels[2][3];
    int i, j;
    tpl_node *tn;
    tn = tpl_map("s##", olabels, 2, 3);
    tpl_load(tn, TPL_FILE, "string2.tpl");
    tpl_unpack(tn, 0);
    tpl_free(tn);
    for (i = 0; i < 2; i++)
    {
        for (j = 0; j < 3; j++)
        {
            printf("%s ", olabels[i][j]);
            free(olabels[i][j]);
        }
        printf("\n------\n");
    }
    printf("\n");
}

// --------------------------------------------------------------------
// 二进制流 Binary buffers
int testBinaryPack(int argc, char *argv[])
{
    tpl_node *tn;
    tpl_bin tb;

    /* we'll use a timeval as our guinea pig */
    struct timeval tv;
    gettimeofday(&tv, NULL);

    tn = tpl_map("B", &tb);
    tb.sz = sizeof(struct timeval); /* size of buffer to pack */
    tb.addr = &tv;                  /* address of buffer to pack */
    tpl_pack(tn, 0);
    tpl_dump(tn, TPL_FILE, "bin.tpl");
    tpl_free(tn);
    printf("pack timeval %d \n", tv.tv_sec);
}

int testBinaryUnpack(int argc, char *argv[])
{
    tpl_node *tn;
    tpl_bin tb;

    tn = tpl_map("B", &tb);
    tpl_load(tn, TPL_FILE, "bin.tpl");
    tpl_unpack(tn, 0);
    tpl_free(tn);

    printf("binary buffer of length %d at address %p\n", tb.sz, tb.addr);
    struct timeval *tv = (timeval *)tb.addr;
    printf("unpack timeval %d \n", tv->tv_sec);
    free(tb.addr); /* our responsibility to free it */
}
// --------------------------------------------------------------------
// 自定义结构体
int testStructPack(int argc, char *argv[])
{
    struct ci
    {
        char c;
        int i;
    };
    struct ci s = {'a', 1};
    tpl_node *tn;
    tn = tpl_map("S(ci)", &s); /* pass structure address */
    tpl_pack(tn, 0);
    tpl_dump(tn, TPL_FILE, "struct.tpl");
    tpl_free(tn);
}

int testStructUnpack(int argc, char *argv[])
{
    struct ci
    {
        char c;
        int i;
    };
    struct ci s;

    tpl_node *tn;
    tn = tpl_map("S(ci)", &s); /* pass structure address */
    tpl_load(tn, TPL_FILE, "struct.tpl");
    tpl_unpack(tn, 0);
    tpl_free(tn);
    printf("s.c %c s.i %d\n", s.c, s.i);
}
// --------------------------------------------------------------------
// 嵌套结构体
int testNestedStructPack(int argc, char *argv[])
{
    struct inner_t
    {
        char a;
        int i;
    };
    struct outer_t
    {
        char b;
        struct inner_t i;
    };
    struct outer_t outer = {'b', {'a', 9}};
    tpl_node *tn;
    tn = tpl_map("S(c$(ci))", &outer); /* pass structure address */
    tpl_pack(tn, 0);
    tpl_dump(tn, TPL_FILE, "nestedstruct.tpl");
    tpl_free(tn);
}

int testNestedStructUnpack(int argc, char *argv[])
{
    struct inner_t
    {
        char a;
        int n;
    };
    struct outer_t
    {
        char b;
        struct inner_t i;
    };
    struct outer_t outer;
    tpl_node *tn;
    tn = tpl_map("S(c$(ci))", &outer); /* pass structure address */
    tpl_load(tn, TPL_FILE, "nestedstruct.tpl");
    tpl_free(tn);

    printf("outer.i %c %d outer.b %c\n", outer.i.a, outer.i.n, outer.b);
}

// --------------------------------------------------------------------
// 结构体list
int testStructListPack(int argc, char *argv[])
{
    struct element
    {
        char c;
        int i;
        struct element *next;
    };
    struct element *list, *i, tmp;

    tpl_node *tn;

    list = (struct element *)malloc(sizeof(struct element));
    struct element one = {'m', 8, NULL};
    list->c = 'g';
    list->i = 2;
    list->next = &one;

    tn = tpl_map("A(S(ci))", &tmp);
    for (i = list; i != NULL; i = i->next)
    {
        tmp = *i;
        tpl_pack(tn, 1);
    }
    tpl_dump(tn, TPL_FILE, "list.tpl");
    tpl_free(tn);
}

int testStructListUnpack(int argc, char *argv[])
{
    struct element
    {
        char c;
        int i;
        struct element *next;
    };
    struct element tmp;
    tpl_node *tn;
    tn = tpl_map("A(S(ci))", &tmp);
    tpl_load(tn, TPL_FILE, "list.tpl");
    while (tpl_unpack(tn, 1) > 0)
    {
        // struct element *newelt = (struct element *)malloc(sizeof(struct element));
        // *newelt = tmp;
        // add_to_list(list, newelt);
        printf("tmp.c %c tmp.i %d\n", tmp.c, tmp.i);
    }
    tpl_free(tn);
}

int main(int argc, char *argv[])
{
    storing(argc, argv);
    reloading(argc, argv);

    testFixedLengthArrayPack(argc, argv);
    testFixedLengthArrayUnpack(argc, argv);

    testVariableLengthArrayPack(argc, argv);
    testVariableLengthArrayUnpack(argc, argv);

    testFixedLengthArrayPackChar(argc, argv);
    testFixedLengthArrayUnpackChar(argc, argv);

    testVariableLengthArrayPackChar(argc, argv);
    testVariableLengthArrayUnpackChar(argc, argv);

    testFixedLengthArrayPack2(argc, argv);
    testFixedLengthArrayUnpack2(argc, argv);

    testVariableLengthArrayPack2(argc, argv);
    testVariableLengthArrayUnpack2(argc, argv);

    testFixedLengthArrayPackChar2(argc, argv);
    testFixedLengthArrayUnpackChar2(argc, argv);

    testVariableLengthArrayPackChar2(argc, argv);
    testVariableLengthArrayUnpackChar2(argc, argv);

    testStringPack(argc, argv);
    testStringUnpack(argc, argv);

    testStringPack2(argc, argv);
    testStringUnpack2(argc, argv);

    testBinaryPack(argc, argv);
    testBinaryUnpack(argc, argv);

    testStructPack(argc, argv);
    testStructUnpack(argc, argv);

    testNestedStructPack(argc, argv);
    testNestedStructUnpack(argc, argv);

    testStructListPack(argc, argv);
    testStructListUnpack(argc, argv);

    return 1;
}

发布了40 篇原创文章 · 获赞 0 · 访问量 2607

猜你喜欢

转载自blog.csdn.net/u010571102/article/details/98737409