主要是对 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;
}