C语言序列化和反序列化--TPL中的API(三)

tpl_map

创建tpl的唯一方法是调用tpl_map()。第一个参数是格式字符串。后面是格式字符串中特定字符所需的参数列表。例如,

tpl_node *tn;
int i;
tn = tpl_map( "A(i)", &i );

该函数在格式字符串中的项和给定地址的C程序变量之间创建映射。稍后,C变量将在封装或解压缩tpl时被读取或写入。

这个函数成功时返回tpl_node*,失败时返回NULL。

tpl_pack

函数tpl_pack()将数据打包到一个tpl中。tpl_pack()的参数是一个tpl_node*和一个索引号。

tn = tpl_map("A(i)A(c)", &i, &c);
for(i=0; i<10; i++) tpl_pack(tn, 1);    /* pack 0-9 into index 1 */
for(c='a'; c<='z'; c++) tpl_pack(tn, 2); /* pack a-z into index 2 */
数据在打包时被复制

每次调用tpl_pack()都会立即复制正在打包的数据。因此,程序可以自由地立即覆盖或重用打包的变量。

索引号0

只有当格式字符串包含不在A(…)内的字符时,例如格式字符串iA©中的i,才有必要打包索引号0。
变长数组
向数组中添加元素

要向变长数组中添加元素,请反复调用tpl_pack()。每次调用都会向数组中添加另一个元素。
零长度数组是可以的

将任何内容都不打包到可变长度数组中是完全可以接受的,从而导致零长度数组。
填充嵌套数组

在包含嵌套可变长度数组的格式字符串中,例如a (a (s)),内部子数组应该在父数组之前打包。

当您打包父数组时,当前子数组的“快照”将被放入父元素的新元素中。打包父数组也会清空子数组。这样,您就可以将新数据打包到子数据中,然后再打包到父数据中。这将创建不同的父元素,每个父元素包含不同的子数组。
当处理像A(A(i))这样的嵌套数组时,从“内向外”(子优先)打包它们,但从“外向内”(父优先)解包它们。
下面的示例创建了一个格式字符串为a (a ©)的tpl。

#include "tpl.h"

int main() {
    char c;
    tpl_node *tn;

    tn = tpl_map("A(A(c))", &c);

    for(c='a'; c<'c'; c++) tpl_pack(tn,2);  /* pack child (twice) */
    tpl_pack(tn, 1);                        /* pack parent */

    for(c='1'; c<'4'; c++) tpl_pack(tn,2);  /* pack child (three times) */
    tpl_pack(tn, 1);                        /* pack parent */

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

这将创建一个嵌套数组,其中父元素有两个元素:第一个元素是双元素嵌套数组a, b;第二个元素是包含三个元素的嵌套数组1,2,3。嵌套解包示例展示了如何解包该tpl。

tpl_dump()

在打包tpl之后,使用tpl_dump()将tpl映像写入文件、内存缓冲区或文件描述符。相应的模式如下所示。最后一种模式用于查询输出大小,而不实际执行转储。
在这里插入图片描述第一个参数是tpl_node*,第二个参数是以下常量之一:

TPL_FILE

将tpl写入一个文件名由以下参数给出的文件。该文件的创建权限为664 (rw-rw-r——),除非被进程umask进一步限制。
TPL_FD

将tpl写入以下参数中给出的文件描述符。描述符可以是阻塞的,也可以是非阻塞的,但如果是非阻塞的,并且不能立即写入内容,则会进行忙循环。
TPL_MEM

将tpl写入内存缓冲区。下面两个参数必须是void**和size_t*。该函数将分配一个缓冲区,并将其地址和长度存储到这些位置。调用者在使用完缓冲区后负责free()。
TPL_MEM | TPL_PREALLOCD

将tpl写入调用方已经分配或声明的内存缓冲区。下面两个参数必须是void*和size_t,分别指定缓冲区地址和大小。(如果缓冲区的大小不足以接收tpl转储,该函数将返回-1)。该模式可以与TPL_EXCESS_OK模式中的tpl_load结合使用,如下所示。
TPL_GETSIZE

这种特殊模式实际上并不转储tpl。相反,它将转储所需的大小放入以下参数所指向的size_t中。

成功时返回值为0,错误时返回值为-1。

tpl_dump()函数不会释放tpl。完成后使用tpl_free()释放tpl的资源。
背靠背的tpl图像不需要分隔符
如果您希望存储一系列tpl图像,或者通过套接字传输顺序的tpl图像(可能作为消息传递给另一个程序),您可以简单地按顺序转储它们,而无需为单个tpl图像添加任何分隔符。Tpl图像是内部分隔的,因此tpl_load每次只读取一个图像,即使多个图像是连续的。

tpl_load

这个API函数从文件、内存缓冲区或文件描述符中读取先前转储的tpl映像,并为随后的解包做好准备。将交叉检查前面调用tpl_map()中指定的格式字符串是否与存储在tpl映像中的格式字符串相等。

tn = tpl_map( "A(i)", &i );
tpl_load( tn, TPL_FILE, "demo.tpl" );

tpl_load()的第一个参数是tpl_node*。第二个参数是常量之一:

TPL_FILE

从以下参数中指定的文件加载tpl。也可以使用TPL_EXCESS_OK按位或这个标志,如下所述。
TPL_MEM

从内存缓冲区加载tpl。下面两个参数必须是void*和size_t,分别指定缓冲区地址和大小。调用者必须在使用tpl_free()释放tpl之后才释放内存缓冲区。(如果调用者希望移交释放内存缓冲区的责任,以便在调用tpl_free()时自动释放内存缓冲区和tpl,则常数TPL_UFREE可以与TPL_MEM按位或来实现这一点)。此外,TPL_MEM可以与TPL_EXCESS_OK进行位或运算,如下所述。
TPL_FD

从以下参数中给出的文件描述符加载tpl。读取描述符,直到加载一个完整的tpl映像;不会读取超过TPL映像末尾的任何字节。描述符可以是阻塞的,也可以是非阻塞的,但如果非阻塞且不能立即读取内容,则将进行忙循环。

在加载过程中,将广泛检查tpl映像的内部有效性。

此函数成功时返回0,错误时返回-1。
TPL_EXCESS_OK

当从文件或内存(但不是从文件描述符)读取tpl映像时,文件或内存缓冲区的大小必须完全等于存储在其中的tpl映像的大小。换句话说,不允许有超出tpl图像的多余尾随数据。位标志TPL_EXCESS_OK可以与TPL_MEM或TPL_FILE进行或处理,以放松此要求。

这个标志在TPL_MEM| tpl_preallod模式下与tpl_dump一起使用时很有用。在本例中,只要LEN足够大,程序本身并不关心实际的tpl大小。

char buf[LEN];  /* will store and read tpl images here */
...
tpl_dump(tn, TPL_MEM|TPL_PREALLOCD, buf, LEN);
...
tpl_load(tn, TPL_MEM|TPL_EXCESS_OK, buf, LEN);

tpl_unpack()

tpl_unpack()函数的作用是:从tpl解包数据。当数据被解包时,它被复制到最初在tpl_map()中指定的C程序变量中。tpl_unpack的第一个参数是tpl的tpl_node*,第二个参数是索引号。

tn = tpl_map( "A(i)A(c)", &i, &c );
tpl_load( tn, TPL_FILE, "nested.tpl" );
while (tpl_unpack( tn, 1) > 0) printf("i is %d\n", i); /* unpack index 1 */
while (tpl_unpack( tn, 2) > 0) printf("c is %c\n", c); /* unpack index 2 */

索引号0

只有当格式字符串包含不在A(…)内的字符时,例如格式字符串iA©中的i,才有必要解包索引号0。
变长数组
从数组中拆包元素

对于变长数组,每次调用tpl_unpack()都会解包另一个元素。返回值可以用来告诉你什么时候完成了:如果它是正的,一个元素被解包;如果它是0,没有解包,因为没有更多的元素。负返回值表示错误(例如无效的索引号)。在本文档中,我们通常使用while循环来解包可变长度数组:

while( tpl_unpack( tn, 1 ) > 0 ) {
    /* got another element */
}

数组长度

在解包可变长度数组时,提前知道需要解包多少元素可能会很方便。您可以使用tpl_allen()来获取这个数字。
拆包嵌套数组

在包含嵌套可变长度数组(如a (a (s)))的格式字符串中,在解压缩子数组之前解压缩外部父数组。

当您解压缩父数组时,它会为解压缩准备子数组。在解包子数组的元素之后,程序可以通过解包另一个父元素来重复这个过程,然后解包子元素,依此类推。下面的示例解包一个格式字符串为a (a ©)的tpl。

拆包嵌套数组
#include "tpl.h"
#include <stdio.h>

int main() {
    char c;
    tpl_node *tn;

    tn = tpl_map("A(A(c))", &c);

    tpl_load(tn, TPL_FILE, "test40.tpl");
    while (tpl_unpack(tn,1) > 0) {
        while (tpl_unpack(tn,2) > 0) printf("%c ",c);
        printf("\n");
    }
    tpl_free(tn);
}

文件test40。TPL来自嵌套打包示例。当运行时,这个程序输出:

a b
1 2 3

tpl_free

任何tpl的最后一步是使用tpl_free()释放它。它唯一的参数是要释放的tpl_node*。

tpl_free( tn );

这个函数不返回值(它是void)。

tpl_Alen

该函数接受一个tpl_node*和一个索引号,并返回一个int值,该值指定变长数组中的元素个数。

num_elements = tpl_Alen(tn, index);

这对于解包数据并需要提前知道需要解包的元素数量的程序非常有用。(它返回当前元素的数目;它将随着元素被解包而减小)。

tpl_peek

这个函数窥视包含tpl图像的文件或内存缓冲区,并返回其格式字符串的副本。它还可以查看格式字符串中任何固定长度数组的长度,或者也可以查看存储在tpl中的数据。
格式偷看

格式字符串可以像这样获得:

fmt = tpl_peek(TPL_FILE, "file.tpl");
fmt = tpl_peek(TPL_MEM, addr, sz);

如果成功,则返回格式字符串的副本。调用者最终必须释放它。如果出现错误,例如不存在的文件或无效的tpl映像,则返回NULL。
数组长度峰值

格式字符串中所有定长数组的长度都可以通过TPL_FXLENS模式查询。它提供了这种固定长度数组的数量及其长度。如果前者不为零,则调用方必须在完成后释放后者数组。格式字符串本身也必须被释放。

uint32_t num_fxlens, *fxlens, j;
fmt = tpl_peek(TPL_FILE|TPL_FXLENS, filename, &num_fxlens, &fxlens);
if (fmt) {
  printf("format %s, num_fxlens %u\n", fmt, num_fxlens);
  for(j=0; j<num_fxlens; j++) printf("fxlens[%u] %u\n", j, fxlens[j]);
  if (num_fxlens > 0) free(fxlens);
  free(fmt);
}

TPL_FXLENS模式与TPL_DATAPEEK模式互斥。
数据窥视

为了窥探数据,使用了额外的参数。这是映射、加载和解包tpl的一种快速替代方法,但是窥视仅限于索引0中的数据。换句话说,不要窥探A(…)类型。假设文件中的tpl映像。tpl的格式字符串为siA(i)。那么索引0的格式字符就是si。下面是窥视其内容的方法:

char *s;
int i;
fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "file.tpl", "si", &s, &i);

现在已经用数据填充了s、i和fmt。调用者最终必须释放fmt和s,因为它们是分配的字符串。当然,它可以与TPL_MEM和TPL_FILE一起工作。请注意,TPL_DATAPEEK是与该模式相关联的。你也可以指定索引0格式的任何前导部分,如果你不想偷看整个东西:

fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "file.tpl", "s", &s);

TPL_DATAPEEK模式与TPL_FXLENS模式互斥。
结构查看

最后,您可以查看索引0中的S(…)结构,但在格式中省略周围的S(…),并指定一个参数来单独接收每个结构成员。可以指定结构格式的任何前导部分。例如if struct。tpl具有格式字符串S(si),您可以通过以下方式查看其数据:

fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "struct.tpl", "s", &s);
fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "struct.tpl", "si", &s, &i);

tpl_jot

这是生成tpl的快捷方式。它可以用来代替通常的“映射、打包、转储和释放”的生命周期。使用tpl_jot,所有这些步骤都可以为您处理。它只适用于简单的格式——即那些格式字符串中没有A(…)的格式。下面是它的用法:

char *hello = "hello", *world = "world";
tpl_jot( TPL_FILE, "file.tpl", "ss", &hello, &world);

支持TPL_FILE、TPL_FD和TPL_MEM三种标准模式。失败时返回-1(例如格式字符串错误或写入文件错误),成功时返回0。

tpl_hook

大多数用户会让这些钩子保持默认值。如果希望修改tpl的内部内存管理和错误报告行为,可以更改这些钩子值。

一个名为tpl_hook的全局结构封装了钩子。程序可以通过指定一个原型与默认值匹配的替代函数来重新配置任何钩子。例如:



#include "tpl.h"
extern tpl_hook_t tpl_hook;

int main() {
    tpl_hook.oops = printf;
    ...
}

tpl_gather

这个函数的原型是:

int tpl_gather( int mode, ...);

mode参数是下面列出的三个常量之一,它必须后跟特定于模式的必需参数:

TPL_GATHER_BLOCKING,    int fd, void **img, size_t *sz
TPL_GATHER_NONBLOCKING, int fd, tpl_gather_t **gs, tpl_gather_cb *cb, void *data
TPL_GATHER_MEM,         void *addr, size_t sz, tpl_gather_t **gs, tpl_gather_cb *cb, void *data

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/666801.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java-集合基础

集合 一、含义 集合是Java API所提供的一系列类&#xff0c;可以用于动态存放多个对象 (集合只能存对象)集合与数组的不同在于&#xff0c;集合是大小可变的序列&#xff0c;而且元素类型可以不受限定&#xff0c;只要是引用类型。(集合中不能放基本数据类型&#xff0c;但可以…

element-plus关于表单数据自定义参数校验

element-plus关于表单数据自定义参数校验 核心点&#xff1a; 代码&#xff1a; <el-form-item :prop"tableData[ scope.$index ].score":rules"[{ required: true, message: 得分不能为空, trigger: blur },{ validator: (rule: any, value: any, ca…

服务器主板电池

一、什么是服务器纽扣电池&#xff1f; 服务器纽扣电池&#xff0c;也叫CMOS电池&#xff0c;是一种非常小型的电池&#xff0c;通常与服务器主板上的CMOS芯片相结合&#xff0c;用于储存BIOS设置、时钟和其他关键系统信息。这种电池的体积通常比一枚硬币还小&#xff0c;而且…

JeecgBoot-Vue3:基于Vue3的低代码开发平台的新篇章

摘要 随着前端技术的不断发展&#xff0c;Vue3.0、TypeScript、Vite以及Ant Design Vue等新技术方案的涌现&#xff0c;为低代码开发平台带来了全新的可能性。JeecgBoot-Vue3作为JeecgBoot低代码平台的全新UI版本&#xff0c;采用Vue3技术栈&#xff0c;结合上述先进技术&#…

海外动态IP代理可以用来批量注册邮箱吗?

无论是个人还是企业&#xff0c;都需要使用邮箱进行沟通、注册账号、接收通知等多种用途。然而&#xff0c;由于互联网服务商为了防止滥用和垃圾邮件的传播&#xff0c;通常对注册邮箱设置了一定的限制&#xff0c;如IP限制、验证码验证等。为了解决这些问题&#xff0c;海外动…

【EFK日志系统】docker一键部署filebeat、metricbeat

docker一键部署filebeat、metricbeat filebeat部署创建配置文件一键启动修改配置文件查验信息 metricbeat部署创建配置文件一键启动修改配置文件查验信息 上两篇文章写了搭建部署es集群和部署kibana 这篇写一键部署filebeat和metricbeat收集工具 规划服务器是 es01:172.23.16…

段码屏|液晶显示模块|超低功耗LCD驱动芯片

1 简介 PC164S32 是一款支持 128 点 (32 4)显示 的多功能 LCD 控制器芯片&#xff0c;内部存储器RAM数据直接映射到 LCD 显示。可软件配置特性使其适用于包括 LCD 模块和显示子系统在内的多种 LCD 应用。主控制器与 PC164S32接口仅需3 或 4 条线。内置的省电模式极大的降低了功…

MYSQL四大操作——查!查!查!

目录 简洁版&#xff1a; 详解版&#xff1a; SQL通用语法&#xff1a; 分类&#xff1a; 1. DDL —库 1.1 查询&#xff1a; 1.2 创建&#xff1a; 1.3 删除 1.4 使用库 2. DDL—表 2.1 查询 2.1.1 查询当前库的所有表&#xff1a; 2.1.2 查询表结构 &#xff1a; 2.1.…

【云原生】Kubernetes----POD控制器

目录 引言 一、Pod控制器概述 二、Pod控制器的种类 &#xff08;一&#xff09;ReplicaSet &#xff08;二&#xff09;Deployment &#xff08;三&#xff09;StatefulSet &#xff08;四&#xff09;DaemonSet &#xff08;五&#xff09;Job 三、使用POD控制器 &a…

江苏大信环境科技有限公司:环保领域的开拓者与引领者

2009 年&#xff0c;江苏大信环境科技有限公司在宜兴环保科技工业园成立。自创立之始&#xff0c;该公司便笃定坚守“诚信为本、以质量求生存、以创新谋发展”这一经营理念&#xff0c;全力以赴为客户构建专业的工业有机废气治理整体解决方案&#xff0c;进而成为国家高新技术企…

Vxe UI vxe-upload 上传组件,显示进度条的方法

vxe-upload 上传组件 查看官网 https://vxeui.com 显示进度条很简单&#xff0c;需要后台支持进度就可以了&#xff0c;后台实现逻辑具体可以百度&#xff0c;这里只介绍前端逻辑。 上传附件 相关参数说明&#xff0c;具体可以看文档&#xff1a; multiple 是否允许多选 li…

6.5 Go 指针

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

微信小程序上架,AI类目审核(AI问答、AI绘画、AI换脸)

小程序对于生成式AI类目的产品上架审核较为严格&#xff0c;这也是近两年新增了几个类目&#xff0c;一旦小程序中涉及生成式AI相关的内容&#xff0c;如果你选择相应类目&#xff0c;但审核被划归为这一类&#xff0c;都需要准备此类目的审核&#xff0c;才能正常上架。 如果…

Open3D(C++) Ransac拟合多项式曲线

目录 一、算法原理一、代码实现三、结果展示本文由CSDN点云侠原创,Open3D(C++) Ransac拟合多项式曲线,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT生成的文章。 一、算法原理 RANSAC(Random Sample Consensus)是一种用于拟合模型的迭…

dockers安装mysql

1.dockerhub上搜索自己需要安装得镜像版本 dockerhub网址&#xff1a;https://hub-stage.docker.com docker pull mysql:5.7 #下载自己需要得版本2.启动容器实例&#xff0c;并且挂载容器数据卷 docker run -d -p 3306:3306 --privilegedtrue \ -v /home/mysql/log:/var/log/…

WireShark抓包软件的使用 上海商学院 计算机网络 实验作业3

实验目的 &#xff08;1&#xff09;熟悉wireShark软件操作界面和操作步骤&#xff1b; &#xff08;2&#xff09;学会捕获过滤器的设置方法&#xff1b; &#xff08;3&#xff09;学会显示过滤器的设置方法&#xff1b; &#xff08;4&#xff09;学会使用捕获报文的统计…

全栈工程师需要具备哪些技能?

概论&#xff1a; 全栈工程师是一位能够从头到尾构建 Web 应用程序的工程师&#xff0c;能独立完成产品。技术包括前端部分、后端部分和应用程序所在的基础架构。他们在整个技术栈中工作&#xff0c;并了解其中的每个部分。从需求分析开始&#xff0c;到概要设计&#xff0c;详…

【计算机网络】——物理层(图文并茂)

物理层 一.物理层概述1.物理层要实现的功能2.物理层接口特征1.机械特性2.电气特性3.功能特性4.过程特性 二.物理层下面的传输媒体1.传输媒体的分类2.导向型传输媒体1.同轴电缆2.双绞线3.光纤 3.非导向型传输媒体1.无线电波2.微波3.红外线4.激光5.可见光 三.传输方式1.串行传输与…

小学数学出题器-Word插件-大珩助手

Word大珩助手是一款功能丰富的Office Word插件&#xff0c;旨在提高用户在处理文档时的效率。它具有多种实用的功能&#xff0c;能够帮助用户轻松修改、优化和管理Word文件&#xff0c;从而打造出专业而精美的文档。 【新功能】小学数学出题器 1、实现了难度设定&#xff1b;…

生成ssh密钥,使用ssh连接linux系统

这里写目录标题 ssh密钥大概介绍1、密钥在哪里生成&#xff08;客户端/服务器&#xff09;&#xff1f;2、密钥生成是什么样子的&#xff1f; ssh &#xff08;生成密钥、密钥传输、配置连接、连接服务&#xff09;过程1、生成密钥提示一&#xff1a;输入保存密钥的文件&#x…