鲲鹏社区首页
中文
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助

编解码库使用

  • 编解码库libhiasn1.so,位于“/usr/local/ksl/lib”下。用户可以在编译源码时链接此库,提供用于将用户数据编码成码流,或将码流解码成用户数据的接口。
  • 编解码接口定义头文件,位于“/usr/local/ksl/include/hiasn1/”下,KSL_ASN1相关数据结构和接口定义位于此目录下。

本章节将演示如何使用编译工具使用中解析asn1文件生成的C代码文件,通过调用KSL_ASN1的编解码库接口,实现将已有数据编码成流,及如何将流解码为数据的方法。

  1. “test_demo”目录下新建一个codec_test.c文件。
    1
    vim codec_test.c
    
  2. 按“i”进入编辑模式,填写编解码样例代码。
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    #include <stdio.h>
    #include <stdbool.h>
    #include <string.h>
    #include <assert.h>
    #include "asn_codec.h"
    #include "exports/test/codec_index.h"
    #include "exports/test/codec_interfaces.h"
    // 缓冲区大小
    #define BUF_SIZE 64
    // 缓冲区
    uint8_t g_buffer[BUF_SIZE];
    
    // 编码测试
    bool EncodeTest(const AsnDesc *desc, AsnCtx *ctx)
    {
        // 准备待编码数据
        OctStrType octStrArr[3] = {
            {
                .len = 2,
                .item = "\x12\x23"
            },
            {
                .len = 2,
                .item = "\x45\x56"
            },
            {
                .len = 2,
                .item = "\x78\x89"
            },
        };
        uint32_t oid[3] = {0, 1, 2};
        MyType userData = {
            .boolType = false,
            .intType = 10,
            .enumType = MY_TYPE_ENUM_TYPE_A,
            .bitStrType = {
                .item = "\x01\x02\x03"
            },
            .seqOfType = {
                .cnt = 3,
                .item = octStrArr
            },
            .choiceType = {
                .choice = MY_TYPE_CHOICE_TYPE_B,
                .u = {
                    .b = true,
                }
            },
            .oidType = {
                .cnt = 3,
                .item = oid
            },
        };
        // 编码
        ssize_t ret = AsnEncode(desc, &userData, ctx);
        if (ret < 0) {
            printf("failed to encode, ret: %zd\n", -ret);
            return false;
        }
        size_t encodedBytes = (size_t)(ret + 7) >> 3;
        printf("successfully encoded into %zu bytes data\n", encodedBytes);
        // 打印编码结果
        printf("encoded: ");
        for (size_t i = 0; i < encodedBytes; ++i) {
            printf("%02X ", g_buffer[i]);
        }
        printf("\n");
        // 比较编码结果
        uint8_t expected[] = "\x05\x00\x01\x02\x03\x03\x80\x12\x23\x80\x45\x56\x80\x78\x89\xC0\x02\x01\x02";
        size_t expectedBytes = sizeof(expected) - 1;
        if (encodedBytes != expectedBytes || memcmp(g_buffer, expected, expectedBytes) != 0) {
            printf("expected: ");
            for (size_t j = 0; j < expectedBytes; ++j) {
                printf("%02X ", expected[j]);
            }
            printf("\n");
            printf("encoded bytes unexpected\n");
            return false;
        }
        return true;
    }
    
    // 解码测试
    void DecodeTest(const AsnDesc *desc, AsnCtx *ctx)
    {
        // 解码
        MyType decoded = {0};
        ssize_t ret = AsnDecode(desc, &decoded, ctx);
        if (ret < 0) {
            printf("failed to decode, ret: %zd\n", -ret);
            return;
        }
        printf("successfully decoded\n");
        // 校验解码结果
        assert(decoded.boolType == false);
        assert(decoded.intType == 10);
        assert(decoded.enumType == MY_TYPE_ENUM_TYPE_A);
        assert(decoded.bitStrType.item[0] == 0x01);
        assert(decoded.bitStrType.item[1] == 0x02);
        assert(decoded.bitStrType.item[2] == 0x03);
        assert(decoded.seqOfType.cnt == 3);
        assert(decoded.seqOfType.item[0].len == 2);
        assert(decoded.seqOfType.item[0].item[0] == 0x12);
        assert(decoded.seqOfType.item[0].item[1] == 0x23);
        assert(decoded.seqOfType.item[1].len == 2);
        assert(decoded.seqOfType.item[1].item[0] == 0x45);
        assert(decoded.seqOfType.item[1].item[1] == 0x56);
        assert(decoded.seqOfType.item[2].len == 2); 
        assert(decoded.seqOfType.item[2].item[0] == 0x78);
        assert(decoded.seqOfType.item[2].item[1] == 0x89);
        assert(decoded.choiceType.choice == MY_TYPE_CHOICE_TYPE_B);
        assert(decoded.choiceType.u.b == true);
        assert(decoded.oidType.cnt == 3);
        assert(decoded.oidType.item[0] == 0);
        assert(decoded.oidType.item[1] == 1);
        assert(decoded.oidType.item[2] == 2); 
    }
    
    int main()
    {
        // 获取结构对应的描述符
        const AsnDesc *desc = CODEC_GET_TEST_DESC(CODEC_IDX_TEST_MY_TYPE);
        // 获取上下文结构体
        AsnCtx *ctx = CODEC_GET_TEST_CTX();
        AsnBuf buf; // 缓冲区结构体
        buf.buf = g_buffer; // 设置缓冲区
        buf.bufLen = BUF_SIZE; // 设置缓冲区大小
        // 初始化,传入上下文结构体、缓冲区结构体指针
        if (!AsnInit(ctx, &buf)) {
            printf("failed to init\n");
            return 1;
        }
        // 编码测试
        if (!EncodeTest(desc, ctx)) {
            return 1;
        }
        // 解码测试
        DecodeTest(desc, ctx);
        // 释放所有内部申请内存
        AsnFree(ctx);
        return 0;
    }
    
    • AsnBuf结构体的缓冲区和缓冲区大小的合法性由用户保证。
    • AsnCtx结构体需先清零,再对buf和method字段赋值。
    • 使用统一的编解码接口AsnEncode、AsnDecode,接口内部通过ctx.method判断编码模式。
    • 编解码接口返回值是ssize_t类型的:
      • 当返回值大于等于0时,表示编码成功,返回已编码字节数或比特数。
      • 当返回值小于0时,表示编码失败,错误码为返回值的绝对值,可在asn_codec_errors.h中找到对应的错误信息。
  3. 按“Esc”键,输入:wq,按“Enter”保存并退出编辑。
  4. 编译运行。
    1
    2
    gcc codec_test.c exports/test/*.c -I/usr/local/ksl/include/hiasn1/ -L/usr/local/ksl/lib/ -Wl,-rpath=/usr/local/ksl/lib/ -lhiasn1 -o codec_test
    ./codec_test