2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
4 * Redistribution and modifications are permitted subject to BSD license.
6 #include <asn_internal.h>
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;
22 st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
23 if(!st) ASN__DECODE_FAILED;
26 if(!constraints) constraints = td->encoding_constraints.per_constraints;
27 ct = constraints ? &constraints->value : 0;
29 if(ct && ct->flags & APC_EXTENSIBLE) {
30 int inext = per_get_few_bits(pd, 1);
31 if(inext < 0) ASN__DECODE_STARVED;
39 if(ct->flags & APC_SEMI_CONSTRAINED) {
40 st->buf = (uint8_t *)CALLOC(1, 2);
41 if(!st->buf) ASN__DECODE_FAILED;
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;
52 if(ct && ct->flags != APC_UNCONSTRAINED) {
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);
64 if (upper >= max_range_bytes)
67 ASN_DEBUG("Can encode %d (%d bytes) in %d bits", ct->range_bits,
70 if ((length = per_get_few_bits(pd, i)) < 0)
73 /* X.691 #12.2.6 length determinant + lb (1) */
75 ASN_DEBUG("Got length %d", length);
76 if (aper_get_align(pd) != 0)
79 int buf = per_get_few_bits(pd, 8);
82 value += (((long)buf) << (8 * length));
85 value += ct->lower_bound;
86 if((specs && specs->field_unsigned)
87 ? asn_uint642INTEGER(st, (unsigned long)value)
88 : asn_int642INTEGER(st, value))
90 ASN_DEBUG("Got value %ld + low %lld",
91 value, (long long int)ct->lower_bound);
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)
100 value = per_get_few_bits(pd, ct->range_bits);
101 if(value < 0) ASN__DECODE_STARVED;
104 if (aper_get_align(pd) < 0)
106 value = per_get_few_bits(pd, 16);
107 if(value < 0) ASN__DECODE_STARVED;
109 value += ct->lower_bound;
110 if((specs && specs->field_unsigned)
111 ? asn_ulong2INTEGER(st, value)
112 : asn_long2INTEGER(st, value))
114 ASN_DEBUG("Got value %ld + low %lld",
115 value, (long long int)ct->lower_bound);
122 ASN_DEBUG("Decoding unconstrained integer %s", td->name);
125 /* X.691, #12.2.3, #12.2.4 */
131 /* Get the PER length */
132 len = aper_get_length(pd, -1, -1, -1, &repeat);
133 if(len < 0) ASN__DECODE_STARVED;
135 p = REALLOC(st->buf, st->size + len + 1);
136 if(!p) ASN__DECODE_FAILED;
137 st->buf = (uint8_t *)p;
139 ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
140 if(ret < 0) ASN__DECODE_STARVED;
143 st->buf[st->size] = 0; /* JIC */
146 if(ct && ct->lower_bound) {
148 * TODO: replace by in-place arithmetics.
151 if(asn_INTEGER2long(st, &value))
153 if(asn_long2INTEGER(st, value + ct->lower_bound))
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;
169 const asn_per_constraint_t *ct;
172 if(!st || st->size == 0) ASN__ENCODE_FAILED;
174 if(!constraints) constraints = td->encoding_constraints.per_constraints;
175 ct = constraints ? &constraints->value : 0;
181 if(specs && specs->field_unsigned) {
183 if(asn_INTEGER2ulong(st, &uval))
185 /* Check proper range */
186 if(ct->flags & APC_SEMI_CONSTRAINED) {
187 if(uval < (unsigned long)ct->lower_bound)
189 } else if(ct->range_bits >= 0) {
190 if(uval < (unsigned long)ct->lower_bound
191 || uval > (unsigned long)ct->upper_bound)
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");
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)
206 } else if(ct->range_bits >= 0) {
207 if(value < ct->lower_bound
208 || value > ct->upper_bound)
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");
217 if(ct->flags & APC_EXTENSIBLE) {
218 if(per_put_few_bits(po, inext, 1))
227 if(ct && ct->range_bits >= 0) {
231 ASN_DEBUG("Encoding integer %ld (%lld) with range %d bits",
232 value, (long long int)(value - ct->lower_bound),
235 v = value - ct->lower_bound;
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))
242 } else if (ct->range_bits == 8) {
243 if(aper_put_align(po) < 0)
245 if(per_put_few_bits(po, 0x00 | v, ct->range_bits))
247 } else if (ct->range_bits <= 16) {
248 /* Consume the bytes to align on octet */
249 if(aper_put_align(po) < 0)
251 if(per_put_few_bits(po, 0x0000 | v, 16))
254 /* TODO: extend to >64 bits */
257 int max_range_bytes = (ct->range_bits >> 3) +
258 (((ct->range_bits % 8) > 0) ? 1 : 0);
262 if (upper >= max_range_bytes)
266 for (j = sizeof(int64_t) -1; j != 0; j--) {
268 val = v64 >> (j * 8);
273 /* Putting length in the minimum number of bits ex: 5 = 3bits */
274 if (per_put_few_bits(po, j, i))
277 /* Consume the bits to align on octet */
278 if (aper_put_align(po) < 0)
281 for (i = 0; i <= j; i++) {
282 if(per_put_few_bits(po, (v64 >> (8 * (j - i))) & 0xff, 8))
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 */
295 for(buf = st->buf, end = st->buf + st->size; buf < end;) {
297 ssize_t mayEncode = aper_put_length(po, -1, -1, end - buf, &need_eom);
300 if(per_put_many_bits(po, buf, 8 * mayEncode))
303 if(need_eom && (aper_put_length(po, -1, -1, 0, NULL) < 0))