我要评分
获取效率
正确性
完整性
易理解

Using the Encoding and Decoding Library

  • The encoding and decoding library libhiasn1.so is stored in /usr/local/ksl/lib. You can link this library during source code compilation. It provides interfaces for encoding user data into streams and decoding streams into user data.
  • The header file that defines encoding and decoding interfaces is stored in /usr/local/ksl/include/hiasn1/. The data structure and interface definitions related to KSL_ASN1 are stored in this directory.

This section describes how to use the C code file generated by parsing ASN.1 files in Using the Compilation Tool to encode data into streams and decode the streams into data by calling the encoding and decoding interfaces of KSL_ASN1.

  1. Create a codec_test.c file in test_demo.
    1
    vim codec_test.c
    
  2. Press i to enter the insert mode and fill in the codec code.
      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"
    // Buffer size
    #define BUF_SIZE 64
    // Buffer
    uint8_t g_buffer[BUF_SIZE];
    
    // Encoding test
    bool EncodeTest(const AsnDesc *desc, AsnCtx *ctx)
    {
        // Prepare data to be encoded.
        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
            },
        };
        // Encoding
        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);
        // Print the encoding result.
        printf("encoded: ");
        for (size_t i = 0; i < encodedBytes; ++i) {
            printf("%02X ", g_buffer[i]);
        }
        printf("\n");
        // Verify the encoding result.
        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;
    }
    
    // Decoding test
    void DecodeTest(const AsnDesc *desc, AsnCtx *ctx)
    {
        // Decoding
        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");
        // Verify the decoding result.
        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()
    {
        // Obtain the descriptor corresponding to the structure.
        const AsnDesc *desc = CODEC_GET_TEST_DESC(CODEC_IDX_TEST_MY_TYPE);
        // Obtain the context structure.
        AsnCtx *ctx = CODEC_GET_TEST_CTX();
        AsnBuf buf; // Buffer structure
        buf.buf = g_buffer; // Set the buffer.
        buf.bufLen = BUF_SIZE; // Set the buffer size.
        // Pass the context structure and the buffer structure pointer for initialization.
        if (!AsnInit(ctx, &buf)) {
            printf("failed to init\n");
            return 1;
        }
        // Encoding test
        if (!EncodeTest(desc, ctx)) {
            return 1;
        }
        // Decoding test
        DecodeTest(desc, ctx);
        // Release all internally allocated memory.
        AsnFree(ctx);
        return 0;
    }
    
    • You need to ensure the validity of the buffer and buffer size of the AsnBuf structure.
    • Before assigning values to the buf and method fields, you must clear the AsnCtx structure.
    • Use the unified encoding and decoding interfaces AsnEncode and AsnDecode. The interfaces use ctx.method to determine the encoding method.
    • The return values of the encoding and decoding interfaces are of the ssize_t type.
      • If the return value is greater than or equal to 0, the encoding is successful, and the return value indicates the number of encoded bytes or bits.
      • If the return value is less than 0, the encoding fails. The error code is the absolute value of the return value, and you can find the corresponding error information in asn_codec_errors.h.
  3. Press Esc, type :wq!, and press Enter to save the file and exit.
  4. Compile and run the project.
    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
    

    If the execution is successful, information similar to the following will be displayed:

    1
    2
    3
    successfully encoded into 19 bytes data
    encoded: 05 00 01 02 03 03 80 12 23 80 45 56 80 78 89 C0 02 01 02
    successfully decoded