SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / INTEGER_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 <INTEGER.h>
8
9 asn_dec_rval_t
10 INTEGER_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
11                     const asn_TYPE_descriptor_t *td,
12                     const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
13     const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
14     asn_dec_rval_t rval = { RC_OK, 0 };
15     INTEGER_t *st = (INTEGER_t *)*sptr;
16     const asn_per_constraint_t *ct;
17     int repeat;
18
19     (void)opt_codec_ctx;
20
21     if(!st) {
22         st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
23         if(!st) ASN__DECODE_FAILED;
24     }
25
26     if(!constraints) constraints = td->encoding_constraints.per_constraints;
27     ct = constraints ? &constraints->value : 0;
28
29     if(ct && ct->flags & APC_EXTENSIBLE) {
30         int inext = per_get_few_bits(pd, 1);
31         if(inext < 0) ASN__DECODE_STARVED;
32         if(inext) ct = 0;
33     }
34
35     FREEMEM(st->buf);
36     st->buf = 0;
37     st->size = 0;
38     if(ct) {
39         if(ct->flags & APC_SEMI_CONSTRAINED) {
40             st->buf = (uint8_t *)CALLOC(1, 2);
41             if(!st->buf) ASN__DECODE_FAILED;
42             st->size = 1;
43         } else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
44             size_t size = (ct->range_bits + 7) >> 3;
45             st->buf = (uint8_t *)MALLOC(1 + size + 1);
46             if(!st->buf) ASN__DECODE_FAILED;
47             st->size = size;
48         }
49     }
50
51     /* X.691, #12.2.2 */
52     if(ct && ct->flags != APC_UNCONSTRAINED) {
53         /* #10.5.6 */
54         ASN_DEBUG("Integer with range %d bits", ct->range_bits);
55         if(ct->range_bits >= 0) {
56             if (ct->range_bits > 16) {
57                 int max_range_bytes = (ct->range_bits >> 3) +
58                                       (((ct->range_bits % 8) > 0) ? 1 : 0);
59                 int length = 0, i;
60                 long value = 0;
61
62                 for (i = 1; ; i++) {
63                     int upper = 1 << i;
64                     if (upper >= max_range_bytes)
65                         break;
66                 }
67                 ASN_DEBUG("Can encode %d (%d bytes) in %d bits", ct->range_bits,
68                           max_range_bytes, i);
69
70                 if ((length = per_get_few_bits(pd, i)) < 0)
71                     ASN__DECODE_FAILED;
72
73                 /* X.691 #12.2.6 length determinant + lb (1) */
74                 length += 1;
75                 ASN_DEBUG("Got length %d", length);
76                 if (aper_get_align(pd) != 0)
77                     ASN__DECODE_FAILED;
78                 while (length--) {
79                     int buf = per_get_few_bits(pd, 8);
80                     if (buf < 0)
81                         ASN__DECODE_FAILED;
82                     value += (((long)buf) << (8 * length));
83                 }
84
85                 value += ct->lower_bound;
86                 if((specs && specs->field_unsigned)
87                         ? asn_uint642INTEGER(st, (unsigned long)value)
88                         : asn_int642INTEGER(st, value))
89                     ASN__DECODE_FAILED;
90                 ASN_DEBUG("Got value %ld + low %lld",
91                           value, (long long int)ct->lower_bound);
92             } else {
93                 long value = 0;
94                 if (ct->range_bits < 8) {
95                     value = per_get_few_bits(pd, ct->range_bits);
96                     if(value < 0) ASN__DECODE_STARVED;
97                 } else if (ct->range_bits == 8) {
98                     if (aper_get_align(pd) < 0)
99                         ASN__DECODE_FAILED;
100                     value = per_get_few_bits(pd, ct->range_bits);
101                     if(value < 0) ASN__DECODE_STARVED;
102                 } else {
103                     /* Align */
104                     if (aper_get_align(pd) < 0)
105                         ASN__DECODE_FAILED;
106                     value = per_get_few_bits(pd, 16);
107                     if(value < 0) ASN__DECODE_STARVED;
108                 }
109                 value += ct->lower_bound;
110                 if((specs && specs->field_unsigned)
111                         ? asn_ulong2INTEGER(st, value)
112                         : asn_long2INTEGER(st, value))
113                     ASN__DECODE_FAILED;
114                 ASN_DEBUG("Got value %ld + low %lld",
115                           value, (long long int)ct->lower_bound);
116             }
117             return rval;
118         } else {
119             ASN__DECODE_FAILED;
120         }
121     } else {
122         ASN_DEBUG("Decoding unconstrained integer %s", td->name);
123     }
124
125     /* X.691, #12.2.3, #12.2.4 */
126     do {
127         ssize_t len;
128         void *p;
129         int ret;
130
131         /* Get the PER length */
132         len = aper_get_length(pd, -1, -1, -1, &repeat);
133         if(len < 0) ASN__DECODE_STARVED;
134
135         p = REALLOC(st->buf, st->size + len + 1);
136         if(!p) ASN__DECODE_FAILED;
137         st->buf = (uint8_t *)p;
138
139         ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
140         if(ret < 0) ASN__DECODE_STARVED;
141         st->size += len;
142     } while(repeat);
143     st->buf[st->size] = 0;  /* JIC */
144
145     /* #12.2.3 */
146     if(ct && ct->lower_bound) {
147         /*
148          * TODO: replace by in-place arithmetics.
149          */
150         long value;
151         if(asn_INTEGER2long(st, &value))
152             ASN__DECODE_FAILED;
153         if(asn_long2INTEGER(st, value + ct->lower_bound))
154             ASN__DECODE_FAILED;
155     }
156
157     return rval;
158 }
159
160 asn_enc_rval_t
161 INTEGER_encode_aper(const asn_TYPE_descriptor_t *td,
162                     const asn_per_constraints_t *constraints,
163                     const void *sptr, asn_per_outp_t *po) {
164     const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
165     asn_enc_rval_t er = {0,0,0};
166     const INTEGER_t *st = (const INTEGER_t *)sptr;
167     const uint8_t *buf;
168     const uint8_t *end;
169     const asn_per_constraint_t *ct;
170     long value = 0;
171
172     if(!st || st->size == 0) ASN__ENCODE_FAILED;
173
174     if(!constraints) constraints = td->encoding_constraints.per_constraints;
175     ct = constraints ? &constraints->value : 0;
176
177     er.encoded = 0;
178
179     if(ct) {
180         int inext = 0;
181         if(specs && specs->field_unsigned) {
182             unsigned long uval;
183             if(asn_INTEGER2ulong(st, &uval))
184                 ASN__ENCODE_FAILED;
185             /* Check proper range */
186             if(ct->flags & APC_SEMI_CONSTRAINED) {
187                 if(uval < (unsigned long)ct->lower_bound)
188                     inext = 1;
189             } else if(ct->range_bits >= 0) {
190                 if(uval < (unsigned long)ct->lower_bound
191                         || uval > (unsigned long)ct->upper_bound)
192                     inext = 1;
193             }
194             ASN_DEBUG("Value %lu (%02x/%zu) lb %lld ub %lld %s",
195                       uval, st->buf[0], st->size,
196                       (long long int)ct->lower_bound,
197                       (long long int)ct->upper_bound,
198                       inext ? "ext" : "fix");
199             value = uval;
200         } else {
201             if(asn_INTEGER2long(st, &value)) ASN__ENCODE_FAILED;
202             /* Check proper range */
203             if(ct->flags & APC_SEMI_CONSTRAINED) {
204                 if(value < ct->lower_bound)
205                     inext = 1;
206             } else if(ct->range_bits >= 0) {
207                 if(value < ct->lower_bound
208                         || value > ct->upper_bound)
209                     inext = 1;
210             }
211             ASN_DEBUG("Value %lu (%02x/%zu) lb %lld ub %lld %s",
212                       value, st->buf[0], st->size,
213                       (long long int)ct->lower_bound,
214                       (long long int)ct->upper_bound,
215                       inext ? "ext" : "fix");
216         }
217         if(ct->flags & APC_EXTENSIBLE) {
218             if(per_put_few_bits(po, inext, 1))
219                 ASN__ENCODE_FAILED;
220             if(inext) ct = 0;
221         } else if(inext) {
222             ASN__ENCODE_FAILED;
223         }
224     }
225
226     /* X.691, #12.2.2 */
227     if(ct && ct->range_bits >= 0) {
228         unsigned long v;
229
230         /* #10.5.6 */
231         ASN_DEBUG("Encoding integer %ld (%lld) with range %d bits",
232                   value, (long long int)(value - ct->lower_bound),
233                   ct->range_bits);
234
235         v = value - ct->lower_bound;
236
237         /* #12 <= 8 -> alignment ? */
238         int range = ct->upper_bound - ct->lower_bound + 1;
239         if (ct->range_bits < 8 || (ct->range_bits == 8 && range < 256)) {
240             if(per_put_few_bits(po, 0x00 | v, ct->range_bits))
241                 ASN__ENCODE_FAILED;
242         } else if (ct->range_bits == 8) {
243             if(aper_put_align(po) < 0)
244                 ASN__ENCODE_FAILED;
245             if(per_put_few_bits(po, 0x00 | v, ct->range_bits))
246                 ASN__ENCODE_FAILED;
247         } else if (ct->range_bits <= 16) {
248             /* Consume the bytes to align on octet */
249             if(aper_put_align(po) < 0)
250                 ASN__ENCODE_FAILED;
251             if(per_put_few_bits(po, 0x0000 | v, 16))
252                 ASN__ENCODE_FAILED;
253         } else {
254             /* TODO: extend to >64 bits */
255             int64_t v64 = v;
256             int i, j;
257             int max_range_bytes = (ct->range_bits >> 3) +
258                                   (((ct->range_bits % 8) > 0) ? 1 : 0);
259
260             for (i = 1; ; i++) {
261                 int upper = 1 << i;
262                 if (upper >= max_range_bytes)
263                     break;
264             }
265
266             for (j = sizeof(int64_t) -1; j != 0; j--) {
267                 int64_t val;
268                 val = v64 >> (j * 8);
269                 if (val != 0)
270                     break;
271             }
272
273             /* Putting length in the minimum number of bits ex: 5 = 3bits */
274             if (per_put_few_bits(po, j, i))
275                 ASN__ENCODE_FAILED;
276
277             /* Consume the bits to align on octet */
278             if (aper_put_align(po) < 0)
279                 ASN__ENCODE_FAILED;
280             /* Put the value */
281             for (i = 0; i <= j; i++) {
282                 if(per_put_few_bits(po, (v64 >> (8 * (j - i))) & 0xff, 8))
283                     ASN__ENCODE_FAILED;
284             }
285         }
286         ASN__ENCODED_OK(er);
287     }
288
289     if(ct && ct->lower_bound) {
290         ASN_DEBUG("Adjust lower bound to %lld", (long long int)ct->lower_bound);
291         /* TODO: adjust lower bound */
292         ASN__ENCODE_FAILED;
293     }
294
295     for(buf = st->buf, end = st->buf + st->size; buf < end;) {
296         int need_eom = 0;
297         ssize_t mayEncode = aper_put_length(po, -1, -1, end - buf, &need_eom);
298         if(mayEncode < 0)
299             ASN__ENCODE_FAILED;
300         if(per_put_many_bits(po, buf, 8 * mayEncode))
301             ASN__ENCODE_FAILED;
302         buf += mayEncode;
303         if(need_eom && (aper_put_length(po, -1, -1, 0, NULL) < 0))
304             ASN__ENCODE_FAILED;
305     }
306
307     ASN__ENCODED_OK(er);
308 }