SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / ANY_aper.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 <ANY.h>
8 #include <errno.h>
9
10 #undef RETURN
11 #define RETURN(_code)                       \
12     do {                                    \
13         asn_dec_rval_t tmprval;             \
14         tmprval.code = _code;               \
15         tmprval.consumed = consumed_myself; \
16         return tmprval;                     \
17     } while(0)
18
19 int
20 ANY_fromType_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
21     uint8_t *buffer = NULL;
22     ssize_t erval;
23
24     if(!st || !td) {
25         errno = EINVAL;
26         return -1;
27     }
28
29     if(!sptr) {
30         if(st->buf) FREEMEM(st->buf);
31         st->size = 0;
32         return 0;
33     }
34
35     erval = aper_encode_to_new_buffer(td, td->encoding_constraints.per_constraints, sptr, (void**)&buffer);
36
37     if(erval == -1) {
38         if(buffer) FREEMEM(buffer);
39         return -1;
40     }
41     assert((size_t)erval > 0);
42
43     if(st->buf) FREEMEM(st->buf);
44     st->buf = buffer;
45     st->size = erval;
46
47     return 0;
48 }
49
50 ANY_t *
51 ANY_new_fromType_aper(asn_TYPE_descriptor_t *td, void *sptr) {
52     ANY_t tmp;
53     ANY_t *st;
54
55     if(!td || !sptr) {
56         errno = EINVAL;
57         return 0;
58     }
59
60     memset(&tmp, 0, sizeof(tmp));
61
62     if(ANY_fromType_aper(&tmp, td, sptr)) return 0;
63
64     st = (ANY_t *)CALLOC(1, sizeof(ANY_t));
65     if(st) {
66         *st = tmp;
67         return st;
68     } else {
69         FREEMEM(tmp.buf);
70         return 0;
71     }
72 }
73
74 int
75 ANY_to_type_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
76     asn_dec_rval_t rval;
77     void *newst = 0;
78
79     if(!st || !td || !struct_ptr) {
80         errno = EINVAL;
81         return -1;
82     }
83
84     if(st->buf == 0) {
85         /* Nothing to convert, make it empty. */
86         *struct_ptr = (void *)0;
87         return 0;
88     }
89
90     rval = aper_decode(0, td, (void **)&newst, st->buf, st->size, 0, 0);
91     if(rval.code == RC_OK) {
92         *struct_ptr = newst;
93         return 0;
94     } else {
95         /* Remove possibly partially decoded data. */
96         ASN_STRUCT_FREE(*td, newst);
97         return -1;
98     }
99 }
100
101 asn_dec_rval_t
102 ANY_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
103                 const asn_TYPE_descriptor_t *td,
104                 const asn_per_constraints_t *constraints, void **sptr,
105                 asn_per_data_t *pd) {
106     const asn_OCTET_STRING_specifics_t *specs =
107         td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
108                       : &asn_SPC_ANY_specs;
109     size_t consumed_myself = 0;
110     int repeat;
111     ANY_t *st = (ANY_t *)*sptr;
112
113     (void)opt_codec_ctx;
114     (void)constraints;
115
116     /*
117      * Allocate the structure.
118      */
119     if(!st) {
120         st = (ANY_t *)(*sptr = CALLOC(1, specs->struct_size));
121         if(!st) RETURN(RC_FAIL);
122     }
123
124     ASN_DEBUG("APER Decoding ANY type");
125
126     st->size = 0;
127     do {
128         ssize_t raw_len;
129         ssize_t len_bytes;
130         ssize_t len_bits;
131         void *p;
132         int ret;
133
134         /* Get the PER length */
135         raw_len = aper_get_length(pd, -1, -1, 0, &repeat);
136         if(raw_len < 0) RETURN(RC_WMORE);
137         if(raw_len == 0 && st->buf) break;
138
139         ASN_DEBUG("Got PER length len %" ASN_PRI_SIZE ", %s (%s)", raw_len,
140                   repeat ? "repeat" : "once", td->name);
141         len_bytes = raw_len;
142         len_bits = len_bytes * 8;
143
144         p = REALLOC(st->buf, st->size + len_bytes + 1);
145         if(!p) RETURN(RC_FAIL);
146         st->buf = (uint8_t *)p;
147
148         ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits);
149         if(ret < 0) RETURN(RC_WMORE);
150         consumed_myself += len_bits;
151         st->size += len_bytes;
152     } while(repeat);
153     st->buf[st->size] = 0; /* nul-terminate */
154
155     RETURN(RC_OK);
156 }
157
158 asn_enc_rval_t
159 ANY_encode_aper(const asn_TYPE_descriptor_t *td,
160                 const asn_per_constraints_t *constraints, const void *sptr,
161                 asn_per_outp_t *po) {
162     const ANY_t *st = (const ANY_t *)sptr;
163     asn_enc_rval_t er = {0, 0, 0};
164     const uint8_t *buf;
165     size_t size;
166     int ret;
167
168     (void)constraints;
169
170     if(!st || (!st->buf && st->size)) ASN__ENCODE_FAILED;
171
172     buf = st->buf;
173     size = st->size;
174     do {
175         int need_eom = 0;
176         ssize_t may_save = aper_put_length(po, -1, -1, size, &need_eom);
177         if(may_save < 0) ASN__ENCODE_FAILED;
178
179         ret = per_put_many_bits(po, buf, may_save * 8);
180         if(ret) ASN__ENCODE_FAILED;
181
182         buf += may_save;
183         size -= may_save;
184         assert(!(may_save & 0x07) || !size);
185         if(need_eom && aper_put_length(po, -1, -1, 0, NULL))
186             ASN__ENCODE_FAILED; /* End of Message length */
187     } while(size);
188
189     ASN__ENCODED_OK(er);
190 }