SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / BIT_STRING_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 <BIT_STRING.h>
8
9 #undef  RETURN
10 #define RETURN(_code)                       \
11     do {                                    \
12         asn_dec_rval_t tmprval;             \
13         tmprval.code = _code;               \
14         tmprval.consumed = consumed_myself; \
15         return tmprval;                     \
16     } while(0)
17
18 static asn_per_constraint_t asn_DEF_BIT_STRING_constraint_size = {
19     APC_SEMI_CONSTRAINED, -1, -1, 0, 0};
20
21 asn_dec_rval_t
22 BIT_STRING_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
23                        const asn_TYPE_descriptor_t *td,
24                        const asn_per_constraints_t *constraints, void **sptr,
25                        asn_per_data_t *pd) {
26     const asn_OCTET_STRING_specifics_t *specs = td->specifics
27         ? (const asn_OCTET_STRING_specifics_t *)td->specifics
28         : &asn_SPC_BIT_STRING_specs;
29     const asn_per_constraints_t *pc =
30         constraints ? constraints : td->encoding_constraints.per_constraints;
31     const asn_per_constraint_t *csiz;
32     asn_dec_rval_t rval = { RC_OK, 0 };
33     BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
34     ssize_t consumed_myself = 0;
35     int repeat;
36
37     (void)opt_codec_ctx;
38
39     if(pc) {
40         csiz = &pc->size;
41     } else {
42         csiz = &asn_DEF_BIT_STRING_constraint_size;
43     }
44
45     if(specs->subvariant != ASN_OSUBV_BIT) {
46         ASN_DEBUG("Subvariant %d is not BIT OSUBV_BIT", specs->subvariant);
47         RETURN(RC_FAIL);
48     }
49
50     /*
51      * Allocate the string.
52      */
53     if(!st) {
54         st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
55         if(!st) RETURN(RC_FAIL);
56     }
57
58     ASN_DEBUG("PER Decoding %s size %ld .. %ld bits %d",
59         csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
60         csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
61
62     if(csiz->flags & APC_EXTENSIBLE) {
63         int inext = per_get_few_bits(pd, 1);
64         if(inext < 0) RETURN(RC_WMORE);
65         if(inext) {
66             csiz = &asn_DEF_BIT_STRING_constraint_size;
67         }
68     }
69
70     if(csiz->effective_bits >= 0) {
71         FREEMEM(st->buf);
72         st->size = (csiz->upper_bound + 7) >> 3;
73         st->buf = (uint8_t *)MALLOC(st->size + 1);
74         if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
75     }
76
77     /* X.691, #16.5: zero-length encoding */
78     /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
79     /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
80     if(csiz->effective_bits == 0) {
81         int ret;
82         ASN_DEBUG("Encoding BIT STRING size %ld", csiz->upper_bound);
83         ret = per_get_many_bits(pd, st->buf, 0, csiz->upper_bound);
84         if(ret < 0) RETURN(RC_WMORE);
85         consumed_myself += csiz->upper_bound;
86         st->buf[st->size] = 0;
87         st->bits_unused = (8 - (csiz->upper_bound & 0x7)) & 0x7;
88         RETURN(RC_OK);
89     }
90
91     st->size = 0;
92     do {
93         ssize_t raw_len;
94         ssize_t len_bytes;
95         ssize_t len_bits;
96         void *p;
97         int ret;
98
99         /* Get the PER length */
100         raw_len = uper_get_length(pd, csiz->effective_bits, csiz->lower_bound,
101                                   &repeat);
102         if(raw_len < 0) RETURN(RC_WMORE);
103         if(raw_len == 0 && st->buf) break;
104
105         ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
106             (long)csiz->effective_bits, (long)raw_len,
107             repeat ? "repeat" : "once", td->name);
108         len_bits = raw_len;
109         len_bytes = (len_bits + 7) >> 3;
110         if(len_bits & 0x7) st->bits_unused = 8 - (len_bits & 0x7);
111         /* len_bits be multiple of 16K if repeat is set */
112         p = REALLOC(st->buf, st->size + len_bytes + 1);
113         if(!p) RETURN(RC_FAIL);
114         st->buf = (uint8_t *)p;
115
116         ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits);
117         if(ret < 0) RETURN(RC_WMORE);
118         st->size += len_bytes;
119     } while(repeat);
120     st->buf[st->size] = 0;  /* nul-terminate */
121
122     return rval;
123 }
124
125 asn_enc_rval_t
126 BIT_STRING_encode_uper(const asn_TYPE_descriptor_t *td,
127                        const asn_per_constraints_t *constraints,
128                        const void *sptr, asn_per_outp_t *po) {
129     const asn_OCTET_STRING_specifics_t *specs =
130         td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
131                       : &asn_SPC_BIT_STRING_specs;
132     const asn_per_constraints_t *pc =
133         constraints ? constraints : td->encoding_constraints.per_constraints;
134     const asn_per_constraint_t *csiz;
135     const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
136     BIT_STRING_t compact_bstr;  /* Do not modify this directly! */
137     asn_enc_rval_t er = { 0, 0, 0 };
138     int inext = 0;  /* Lies not within extension root */
139     size_t size_in_bits;
140     const uint8_t *buf;
141     int ret;
142     int ct_extensible;
143
144     if(!st || (!st->buf && st->size))
145         ASN__ENCODE_FAILED;
146
147     if(specs->subvariant == ASN_OSUBV_BIT) {
148         if((st->size == 0 && st->bits_unused) || (st->bits_unused & ~7))
149             ASN__ENCODE_FAILED;
150     } else {
151         ASN__ENCODE_FAILED;
152     }
153
154     if(pc) {
155         csiz = &pc->size;
156     } else {
157         csiz = &asn_DEF_BIT_STRING_constraint_size;
158     }
159     ct_extensible = csiz->flags & APC_EXTENSIBLE;
160
161     /* Figure out the size without the trailing bits */
162     st = BIT_STRING__compactify(st, &compact_bstr);
163     size_in_bits = 8 * st->size - st->bits_unused;
164
165     ASN_DEBUG(
166         "Encoding %s into %" ASN_PRI_SIZE " bits"
167         " (%ld..%ld, effective %d)%s",
168         td->name, size_in_bits, csiz->lower_bound, csiz->upper_bound,
169         csiz->effective_bits, ct_extensible ? " EXT" : "");
170
171     /* Figure out whether size lies within PER visible constraint */
172
173     if(csiz->effective_bits >= 0) {
174         if((ssize_t)size_in_bits > csiz->upper_bound) {
175             if(ct_extensible) {
176                 csiz = &asn_DEF_BIT_STRING_constraint_size;
177                 inext = 1;
178             } else {
179                 ASN__ENCODE_FAILED;
180             }
181         }
182     } else {
183         inext = 0;
184     }
185
186     if(ct_extensible) {
187         /* Declare whether length is [not] within extension root */
188         if(per_put_few_bits(po, inext, 1))
189             ASN__ENCODE_FAILED;
190     }
191
192     if(csiz->effective_bits >= 0 && !inext) {
193         int add_trailer = (ssize_t)size_in_bits < csiz->lower_bound;
194         ASN_DEBUG(
195             "Encoding %" ASN_PRI_SIZE " bytes (%ld), length (in %d bits) trailer %d; actual "
196             "value %" ASN_PRI_SSIZE "",
197             st->size, size_in_bits - csiz->lower_bound, csiz->effective_bits,
198             add_trailer,
199             add_trailer ? 0 : (ssize_t)size_in_bits - csiz->lower_bound);
200         ret = per_put_few_bits(
201             po, add_trailer ? 0 : (ssize_t)size_in_bits - csiz->lower_bound,
202             csiz->effective_bits);
203         if(ret) ASN__ENCODE_FAILED;
204         ret = per_put_many_bits(po, st->buf, size_in_bits);
205         if(ret) ASN__ENCODE_FAILED;
206         if(add_trailer) {
207             static const uint8_t zeros[16];
208             size_t trailing_zero_bits = csiz->lower_bound - size_in_bits;
209             while(trailing_zero_bits > 0) {
210                 if(trailing_zero_bits > 8 * sizeof(zeros)) {
211                     ret = per_put_many_bits(po, zeros, 8 * sizeof(zeros));
212                     trailing_zero_bits -= 8 * sizeof(zeros);
213                 } else {
214                     ret = per_put_many_bits(po, zeros, trailing_zero_bits);
215                     trailing_zero_bits = 0;
216                 }
217                 if(ret) ASN__ENCODE_FAILED;
218             }
219         }
220         ASN__ENCODED_OK(er);
221     }
222
223     ASN_DEBUG("Encoding %" ASN_PRI_SIZE " bytes", st->size);
224
225     buf = st->buf;
226     do {
227         int need_eom = 0;
228         ssize_t maySave = uper_put_length(po, size_in_bits, &need_eom);
229         if(maySave < 0) ASN__ENCODE_FAILED;
230
231         ASN_DEBUG("Encoding %" ASN_PRI_SSIZE " of %" ASN_PRI_SIZE "", maySave, size_in_bits);
232
233         ret = per_put_many_bits(po, buf, maySave);
234         if(ret) ASN__ENCODE_FAILED;
235
236         buf += maySave >> 3;
237         size_in_bits -= maySave;
238         assert(!(maySave & 0x07) || !size_in_bits);
239         if(need_eom && uper_put_length(po, 0, 0))
240             ASN__ENCODE_FAILED; /* End of Message length */
241     } while(size_in_bits);
242
243     ASN__ENCODED_OK(er);
244 }