SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / asn_codecs_prim_ber.c
1 /*
2  * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
3  * All rights reserved.
4  * Redistribution and modifications are permitted subject to BSD license.
5  */
6 #include <asn_internal.h>
7 #include <asn_codecs_prim.h>
8
9 /*
10  * Decode an always-primitive type.
11  */
12 asn_dec_rval_t
13 ber_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
14                      const asn_TYPE_descriptor_t *td, void **sptr,
15                      const void *buf_ptr, size_t size, int tag_mode) {
16     ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
17     asn_dec_rval_t rval;
18     ber_tlv_len_t length = 0;  /* =0 to avoid [incorrect] warning. */
19
20     /*
21      * If the structure is not there, allocate it.
22      */
23     if(st == NULL) {
24         st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
25         if(st == NULL) ASN__DECODE_FAILED;
26         *sptr = (void *)st;
27     }
28
29     ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
30               td->name, tag_mode);
31
32     /*
33      * Check tags and extract value length.
34      */
35     rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
36                           tag_mode, 0, &length, 0);
37     if(rval.code != RC_OK)
38         return rval;
39
40     ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
41
42     /*
43      * Make sure we have this length.
44      */
45     buf_ptr = ((const char *)buf_ptr) + rval.consumed;
46     size -= rval.consumed;
47     if(length > (ber_tlv_len_t)size) {
48         rval.code = RC_WMORE;
49         rval.consumed = 0;
50         return rval;
51     }
52
53     st->size = (int)length;
54     /* The following better be optimized away. */
55     if(sizeof(st->size) != sizeof(length)
56             && (ber_tlv_len_t)st->size != length) {
57         st->size = 0;
58         ASN__DECODE_FAILED;
59     }
60
61     st->buf = (uint8_t *)MALLOC(length + 1);
62     if(!st->buf) {
63         st->size = 0;
64         ASN__DECODE_FAILED;
65     }
66
67     memcpy(st->buf, buf_ptr, length);
68     st->buf[length] = '\0';  /* Just in case */
69
70     rval.code = RC_OK;
71     rval.consumed += length;
72
73     ASN_DEBUG("Took %ld/%ld bytes to encode %s",
74               (long)rval.consumed,
75               (long)length, td->name);
76
77     return rval;
78 }
79
80 /*
81  * Encode an always-primitive type using DER.
82  */
83 asn_enc_rval_t
84 der_encode_primitive(const asn_TYPE_descriptor_t *td, const void *sptr,
85                      int tag_mode, ber_tlv_tag_t tag,
86                      asn_app_consume_bytes_f *cb, void *app_key) {
87     asn_enc_rval_t erval = {0,0,0};
88     const ASN__PRIMITIVE_TYPE_t *st = (const ASN__PRIMITIVE_TYPE_t *)sptr;
89
90     ASN_DEBUG("%s %s as a primitive type (tm=%d)",
91               cb?"Encoding":"Estimating", td->name, tag_mode);
92
93     erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
94                                    cb, app_key);
95     ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
96     if(erval.encoded == -1) {
97         erval.failed_type = td;
98         erval.structure_ptr = sptr;
99         return erval;
100     }
101
102     if(cb && st->buf) {
103         if(cb(st->buf, st->size, app_key) < 0) {
104             erval.encoded = -1;
105             erval.failed_type = td;
106             erval.structure_ptr = sptr;
107             return erval;
108         }
109     } else {
110         assert(st->buf || st->size == 0);
111     }
112
113     erval.encoded += st->size;
114     ASN__ENCODED_OK(erval);
115 }