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_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,
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;
24 st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
25 if(!st) ASN__DECODE_FAILED;
28 if(!constraints) constraints = td->encoding_constraints.per_constraints;
29 ct = constraints ? &constraints->value : 0;
31 if(ct && ct->flags & APC_EXTENSIBLE) {
32 int inext = per_get_few_bits(pd, 1);
33 if(inext < 0) ASN__DECODE_STARVED;
41 if(ct->flags & APC_SEMI_CONSTRAINED) {
42 st->buf = (uint8_t *)CALLOC(1, 2);
43 if(!st->buf) ASN__DECODE_FAILED;
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;
53 /* X.691-2008/11, #13.2.2, constrained whole number */
54 if(ct && ct->flags != APC_UNCONSTRAINED) {
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))
61 if(specs && specs->field_unsigned) {
63 if(uper_get_constrained_whole_number(pd,
64 &uvalue, ct->range_bits))
66 ASN_DEBUG("Got value %lu + low %ld",
67 uvalue, ct->lower_bound);
68 uvalue += ct->lower_bound;
69 if(asn_umax2INTEGER(st, uvalue))
74 if(uper_get_constrained_whole_number(pd,
75 &uvalue, ct->range_bits))
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)) {
88 ASN_DEBUG("Decoding unconstrained integer %s", td->name);
91 /* X.691, #12.2.3, #12.2.4 */
97 /* Get the PER length */
98 len = uper_get_length(pd, -1, 0, &repeat);
99 if(len < 0) ASN__DECODE_STARVED;
101 p = REALLOC(st->buf, st->size + len + 1);
102 if(!p) ASN__DECODE_FAILED;
103 st->buf = (uint8_t *)p;
105 ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
106 if(ret < 0) ASN__DECODE_STARVED;
109 st->buf[st->size] = 0; /* JIC */
112 if(ct && ct->lower_bound) {
114 * TODO: replace by in-place arithmetic.
117 if(asn_INTEGER2long(st, &value))
119 if(asn_imax2INTEGER(st, value + ct->lower_bound))
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;
136 const asn_per_constraint_t *ct;
142 if(!st || st->size == 0) ASN__ENCODE_FAILED;
144 if(!constraints) constraints = td->encoding_constraints.per_constraints;
145 ct = constraints ? &constraints->value : 0;
151 if(specs && specs->field_unsigned) {
152 if(asn_INTEGER2umax(st, &value.u))
154 /* Check proper range */
155 if(ct->flags & APC_SEMI_CONSTRAINED) {
156 if(value.u < (uintmax_t)ct->lower_bound)
158 } else if(ct->range_bits >= 0) {
159 if(value.u < (uintmax_t)ct->lower_bound
160 || value.u > (uintmax_t)ct->upper_bound)
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");
168 if(asn_INTEGER2imax(st, &value.s))
170 /* Check proper range */
171 if(ct->flags & APC_SEMI_CONSTRAINED) {
172 if(value.s < ct->lower_bound)
174 } else if(ct->range_bits >= 0) {
175 if(value.s < ct->lower_bound
176 || value.s > ct->upper_bound)
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");
184 if(ct->flags & APC_EXTENSIBLE) {
185 if(per_put_few_bits(po, inext, 1))
193 /* X.691-11/2008, #13.2.2, test if constrained whole number */
194 if(ct && ct->range_bits >= 0) {
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);
205 v = value.u - (uintmax_t)ct->lower_bound;
207 if(per_imax_range_rebase(value.s, ct->lower_bound, ct->upper_bound, &v)) {
211 ASN_DEBUG("Encoding integer %lu with range %d bits",
213 if(uper_put_constrained_whole_number_u(po, v, ct->range_bits))
218 if(ct && ct->lower_bound) {
219 ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);
220 /* TODO: adjust lower bound */
224 for(buf = st->buf, end = st->buf + st->size; buf < end;) {
226 ssize_t mayEncode = uper_put_length(po, end - buf, &need_eom);
229 if(per_put_many_bits(po, buf, 8 * mayEncode))
232 if(need_eom && uper_put_length(po, 0, 0)) ASN__ENCODE_FAILED;