SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / INTEGER_uper.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_uper(const asn_codec_ctx_t *opt_codec_ctx,
11                     const asn_TYPE_descriptor_t *td,
12                     const asn_per_constraints_t *constraints, void **sptr,
13                     asn_per_data_t *pd) {
14     const asn_INTEGER_specifics_t *specs =
15         (const asn_INTEGER_specifics_t *)td->specifics;
16     asn_dec_rval_t rval = { RC_OK, 0 };
17     INTEGER_t *st = (INTEGER_t *)*sptr;
18     const asn_per_constraint_t *ct;
19     int repeat;
20
21     (void)opt_codec_ctx;
22
23     if(!st) {
24         st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
25         if(!st) ASN__DECODE_FAILED;
26     }
27
28     if(!constraints) constraints = td->encoding_constraints.per_constraints;
29     ct = constraints ? &constraints->value : 0;
30
31     if(ct && ct->flags & APC_EXTENSIBLE) {
32         int inext = per_get_few_bits(pd, 1);
33         if(inext < 0) ASN__DECODE_STARVED;
34         if(inext) ct = 0;
35     }
36
37     FREEMEM(st->buf);
38     st->buf = 0;
39     st->size = 0;
40     if(ct) {
41         if(ct->flags & APC_SEMI_CONSTRAINED) {
42             st->buf = (uint8_t *)CALLOC(1, 2);
43             if(!st->buf) ASN__DECODE_FAILED;
44             st->size = 1;
45         } else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
46             size_t size = (ct->range_bits + 7) >> 3;
47             st->buf = (uint8_t *)MALLOC(1 + size + 1);
48             if(!st->buf) ASN__DECODE_FAILED;
49             st->size = size;
50         }
51     }
52
53     /* X.691-2008/11, #13.2.2, constrained whole number */
54     if(ct && ct->flags != APC_UNCONSTRAINED) {
55         /* #11.5.6 */
56         ASN_DEBUG("Integer with range %d bits", ct->range_bits);
57         if(ct->range_bits >= 0) {
58             if((size_t)ct->range_bits > 8 * sizeof(uintmax_t))
59                 ASN__DECODE_FAILED;
60
61             if(specs && specs->field_unsigned) {
62                 uintmax_t uvalue = 0;
63                 if(uper_get_constrained_whole_number(pd,
64                     &uvalue, ct->range_bits))
65                     ASN__DECODE_STARVED;
66                 ASN_DEBUG("Got value %lu + low %ld",
67                     uvalue, ct->lower_bound);
68                 uvalue += ct->lower_bound;
69                 if(asn_umax2INTEGER(st, uvalue))
70                     ASN__DECODE_FAILED;
71             } else {
72                 uintmax_t uvalue = 0;
73                 intmax_t svalue;
74                 if(uper_get_constrained_whole_number(pd,
75                     &uvalue, ct->range_bits))
76                     ASN__DECODE_STARVED;
77                 ASN_DEBUG("Got value %lu + low %ld",
78                 uvalue, ct->lower_bound);
79                 if(per_imax_range_unrebase(uvalue, ct->lower_bound,
80                                            ct->upper_bound, &svalue)
81                    || asn_imax2INTEGER(st, svalue)) {
82                     ASN__DECODE_FAILED;
83                 }
84             }
85             return rval;
86         }
87     } else {
88         ASN_DEBUG("Decoding unconstrained integer %s", td->name);
89     }
90
91     /* X.691, #12.2.3, #12.2.4 */
92     do {
93         ssize_t len = 0;
94         void *p = NULL;
95         int ret = 0;
96
97         /* Get the PER length */
98         len = uper_get_length(pd, -1, 0, &repeat);
99         if(len < 0) ASN__DECODE_STARVED;
100
101         p = REALLOC(st->buf, st->size + len + 1);
102         if(!p) ASN__DECODE_FAILED;
103         st->buf = (uint8_t *)p;
104
105         ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
106         if(ret < 0) ASN__DECODE_STARVED;
107         st->size += len;
108     } while(repeat);
109     st->buf[st->size] = 0;  /* JIC */
110
111     /* #12.2.3 */
112     if(ct && ct->lower_bound) {
113         /*
114          * TODO: replace by in-place arithmetic.
115          */
116         long value = 0;
117         if(asn_INTEGER2long(st, &value))
118             ASN__DECODE_FAILED;
119         if(asn_imax2INTEGER(st, value + ct->lower_bound))
120             ASN__DECODE_FAILED;
121     }
122
123     return rval;
124 }
125
126 asn_enc_rval_t
127 INTEGER_encode_uper(const asn_TYPE_descriptor_t *td,
128                     const asn_per_constraints_t *constraints, const void *sptr,
129                     asn_per_outp_t *po) {
130     const asn_INTEGER_specifics_t *specs =
131         (const asn_INTEGER_specifics_t *)td->specifics;
132     asn_enc_rval_t er = {0,0,0};
133     const INTEGER_t *st = (const INTEGER_t *)sptr;
134     const uint8_t *buf;
135     const uint8_t *end;
136     const asn_per_constraint_t *ct;
137     union {
138         intmax_t s;
139         uintmax_t u;
140     } value;
141
142     if(!st || st->size == 0) ASN__ENCODE_FAILED;
143
144     if(!constraints) constraints = td->encoding_constraints.per_constraints;
145     ct = constraints ? &constraints->value : 0;
146
147     er.encoded = 0;
148
149     if(ct) {
150         int inext = 0;
151         if(specs && specs->field_unsigned) {
152             if(asn_INTEGER2umax(st, &value.u))
153                 ASN__ENCODE_FAILED;
154             /* Check proper range */
155             if(ct->flags & APC_SEMI_CONSTRAINED) {
156                 if(value.u < (uintmax_t)ct->lower_bound)
157                     inext = 1;
158             } else if(ct->range_bits >= 0) {
159                 if(value.u < (uintmax_t)ct->lower_bound
160                 || value.u > (uintmax_t)ct->upper_bound)
161                     inext = 1;
162             }
163             ASN_DEBUG("Value %lu (%02x/%" ASN_PRI_SIZE ") lb %lu ub %lu %s",
164                       value.u, st->buf[0], st->size,
165                       ct->lower_bound, ct->upper_bound,
166                       inext ? "ext" : "fix");
167         } else {
168             if(asn_INTEGER2imax(st, &value.s))
169                 ASN__ENCODE_FAILED;
170             /* Check proper range */
171             if(ct->flags & APC_SEMI_CONSTRAINED) {
172                 if(value.s < ct->lower_bound)
173                     inext = 1;
174             } else if(ct->range_bits >= 0) {
175                 if(value.s < ct->lower_bound
176                 || value.s > ct->upper_bound)
177                     inext = 1;
178             }
179             ASN_DEBUG("Value %ld (%02x/%" ASN_PRI_SIZE ") lb %ld ub %ld %s",
180                       value.s, st->buf[0], st->size,
181                       ct->lower_bound, ct->upper_bound,
182                       inext ? "ext" : "fix");
183         }
184         if(ct->flags & APC_EXTENSIBLE) {
185             if(per_put_few_bits(po, inext, 1))
186                 ASN__ENCODE_FAILED;
187             if(inext) ct = 0;
188         } else if(inext) {
189             ASN__ENCODE_FAILED;
190         }
191     }
192
193     /* X.691-11/2008, #13.2.2, test if constrained whole number */
194     if(ct && ct->range_bits >= 0) {
195         uintmax_t v;
196         /* #11.5.6 -> #11.3 */
197         if(specs && specs->field_unsigned) {
198             if(((uintmax_t)ct->lower_bound > (uintmax_t)(ct->upper_bound)
199             || (value.u < (uintmax_t)ct->lower_bound))
200             || (value.u > (uintmax_t)ct->upper_bound)) {
201                 ASN_DEBUG("Value %lu to-be-encoded is outside the bounds [%lu, %lu]!",
202                           value.u, ct->lower_bound, ct->upper_bound);
203                 ASN__ENCODE_FAILED;
204             }
205             v = value.u - (uintmax_t)ct->lower_bound;
206         } else {
207             if(per_imax_range_rebase(value.s, ct->lower_bound, ct->upper_bound, &v)) {
208                 ASN__ENCODE_FAILED;
209             }
210         }
211         ASN_DEBUG("Encoding integer %lu with range %d bits",
212                   v, ct->range_bits);
213         if(uper_put_constrained_whole_number_u(po, v, ct->range_bits))
214             ASN__ENCODE_FAILED;
215         ASN__ENCODED_OK(er);
216     }
217
218     if(ct && ct->lower_bound) {
219         ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);
220         /* TODO: adjust lower bound */
221         ASN__ENCODE_FAILED;
222     }
223
224     for(buf = st->buf, end = st->buf + st->size; buf < end;) {
225         int need_eom = 0;
226         ssize_t mayEncode = uper_put_length(po, end - buf, &need_eom);
227         if(mayEncode < 0)
228             ASN__ENCODE_FAILED;
229         if(per_put_many_bits(po, buf, 8 * mayEncode))
230             ASN__ENCODE_FAILED;
231         buf += mayEncode;
232         if(need_eom && uper_put_length(po, 0, 0)) ASN__ENCODE_FAILED;
233     }
234
235     ASN__ENCODED_OK(er);
236 }