轻量级tlv编解码

项目简介

这是一个用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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值