项目简介
这是一个用C语言编写的轻量级TLV(Tag-Length-Value)编解码库,旨在提供简单、高效的TLV数据处理能力。适用于需要自定义协议或数据封装的场景,如物联网通信、配置文件解析等。
本库通过宏定义的方式简化了编解码过程,相较于使用二叉树数据结构解码的方式,降低了内存开销,提高了执行效率和代码维护性。
功能特性
-
简易使用:利用宏定义快速生成TLV解码和编码函数。
-
编解码支持:同时支持TLV数据的解码到结构化数据和结构化数据编码为TLV。
-
复合节点处理:支持嵌套TLV结构,便于处理复杂数据包。
-
优化内存:内部无全局变量和动态内存开销。
-
最大长度:单包编解码最多支持16386个字节的TLV数据buf。
编译与安装
此库为纯C语言实现,无额外依赖。将其加入到你的项目中,或通过makefile等构建系统编译即可。
快速开始
编码示例
/**
* @brief tlv编码示例
*/
#include "lw_tlv.h"
typedef struct {
uint8_t len;
uint8_t arr[130];
} arr_struct_t;
/* 待编码的结构化数据 */
static arr_struct_t data = {0};
/* 使用宏定义创建编码函数,注意结尾不需要加; */
TLV_ENCODE_CREATE(my_tlv_tl)
TLV_ENCODE_CHILD(0x03, 100, data.arr)
TLV_ENCODE_END
TLV_ENCODE_CREATE(my_tlv_encode)
TLV_ENCODE_CHILD(0x01, 1, &data.len)
TLV_ENCODE_COMPD(0x02, my_tlv_tl)
TLV_ENCODE_END
int main()
{
data.len = 100;
for (uint8_t i = 0; i < data.len; i++) {
data.arr[i] = i;
}
uint8_t buf[150] = {0};
uint16_t len = tlv_encode(buf, sizeof(buf), my_tlv_encode);
if (len > 0) {
printf("Encode len %d\n", len);
for (uint8_t i = 0; i < len; i++) {
printf("0x%.02X,", buf[i]);
}
} else {
printf("Encode failed.\n");
}
return 0;
}
解码示例
/**
* @brief tlv解码示例
*/
#include "lw_tlv.h"
typedef struct {
uint8_t len;
uint8_t arr[130];
} arr_struct_t;
/* 待解码的结构化数据 */
static arr_struct_t data = {0};
/* 使用宏定义创建解码函数 */
TLV_DECODE_CREATE(my_tlv_tl)
TLV_DECODE_CHILD(0x03, 100, data.arr)
TLV_DECODE_END
TLV_DECODE_CREATE(my_tlv_decode)
TLV_DECODE_CHILD(0x01, 1, &data.len)
TLV_DECODE_COMPD(0x02, my_tlv_tl)
TLV_DECODE_END
int main()
{
uint8_t buf[] = {0x01,0x01,0x64,0x82,0x66,0x03,0x64,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61,0x62,0x63,0x64};
if (tlv_decode(buf, sizeof(buf), my_tlv_decode) == TLV_SUCCESS) {
printf("Decode data len %d\n", data.len);
for (uint8_t i = 0; i < data.len; i++) {
printf("0x%.02X,", data.arr[i]);
}
} else {
printf("Decode failed.\n");
}
return 0;
}
程序源码
/**
* Copyright (C) 2024-2024 Puchu Co., Ltd
*
* @brief 轻量级tlv编解码
* @author zhanghongzhi
* @date 2024-03-26
*/
#ifndef LW_TLV_H
#define LW_TLV_H
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* tlv返回值 */
#define TLV_SUCCESS 0
#define TLV_FAILURE (-1)
/* 创建tlv解码函数,并命名 */
#define TLV_DECODE_CREATE(DECODE) _TLV_DECODE_CREATE(DECODE)
/* 解码tlv节点,并将值传到指针,可选 */
#define TLV_DECODE_CHILD(TAG, BYTE, POINTER) _TLV_DECODE_CHILD(TAG, BYTE, POINTER)
/* 解码复合节点,传入下一级解码函数,可选 */
#define TLV_DECODE_COMPD(TAG, DECODE) _TLV_DECODE_COMPD(TAG, DECODE)
/* 解码函数结束 */
#define TLV_DECODE_END _TLV_DECODE_END
/* 创建tlv编码函数,并命名 */
#define TLV_ENCODE_CREATE(ENCODE) _TLV_ENCODE_CREATE(ENCODE)
/* 编码tlv节点,并将值传到指针,可选 */
#define TLV_ENCODE_CHILD(TAG, BYTE, POINTER) _TLV_ENCODE_CHILD(TAG, BYTE, POINTER)
/* 解码复合节点,传入下一级编码函数,可选 */
#define TLV_ENCODE_COMPD(TAG, ENCODE) _TLV_ENCODE_COMPD(TAG, ENCODE)
/* 编码函数结束 */
#define TLV_ENCODE_END _TLV_ENCODE_END
/**
* @brief 解码tlv为结构化数据
*
* @param buf 缓存数组
* @param len 数组长度
* @param decode 解码函数
*
* @return 成功返回0,失败返回负数
*/
int32_t tlv_decode(uint8_t *buf, uint16_t len, void *decode);
/**
* @brief 将结构化数据编码为tlv
*
* @param buf 缓存数组
* @param len 数组长度
* @param encode 编码函数
*
* @return 成功返回tlv实际长度,失败返回负数
*/
int32_t tlv_encode(uint8_t *buf, uint16_t len, void *encode);
#ifdef __cplusplus
}
#endif
#endif