SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / OCTET_STRING_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 <OCTET_STRING.h>
8 #include <BIT_STRING.h>  /* for .bits_unused member */
9
10 #undef RETURN
11 #define RETURN(_code) 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_constraints_t asn_DEF_OCTET_STRING_constraints = {
19     { APC_CONSTRAINED, 8, 8, 0, 255 },
20     { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
21     0, 0
22 };
23
24 asn_dec_rval_t
25 OCTET_STRING_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
26                          const asn_TYPE_descriptor_t *td,
27                          const asn_per_constraints_t *constraints,
28                          void **sptr, asn_per_data_t *pd) {
29
30     const asn_OCTET_STRING_specifics_t *specs = td->specifics
31         ? (const asn_OCTET_STRING_specifics_t *)td->specifics
32         : &asn_SPC_OCTET_STRING_specs;
33     const asn_per_constraints_t *pc = constraints
34         ? constraints
35         : td->encoding_constraints.per_constraints;
36     const asn_per_constraint_t *cval;
37     const asn_per_constraint_t *csiz;
38     asn_dec_rval_t rval = { RC_OK, 0 };
39     BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
40     ssize_t consumed_myself = 0;
41     int repeat;
42     enum {
43         OS__BPC_BIT = 0,
44         OS__BPC_CHAR = 1,
45         OS__BPC_U16 = 2,
46         OS__BPC_U32 = 4
47     } bpc;  /* Bytes per character */
48     unsigned int unit_bits;
49     unsigned int canonical_unit_bits;
50
51     (void)opt_codec_ctx;
52
53     if(pc) {
54         cval = &pc->value;
55         csiz = &pc->size;
56     } else {
57         cval = &asn_DEF_OCTET_STRING_constraints.value;
58         csiz = &asn_DEF_OCTET_STRING_constraints.size;
59     }
60
61     switch(specs->subvariant) {
62     default:
63 /*
64     case ASN_OSUBV_ANY:
65         ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant);
66         RETURN(RC_FAIL);
67 */
68     case ASN_OSUBV_BIT:
69         canonical_unit_bits = unit_bits = 1;
70         bpc = OS__BPC_BIT;
71         break;
72     case ASN_OSUBV_ANY:
73     case ASN_OSUBV_STR:
74         canonical_unit_bits = unit_bits = 8;
75 /*
76         if(cval->flags & APC_CONSTRAINED)
77             unit_bits = cval->range_bits;
78 */
79         bpc = OS__BPC_CHAR;
80         break;
81     case ASN_OSUBV_U16:
82         canonical_unit_bits = unit_bits = 16;
83         if(cval->flags & APC_CONSTRAINED)
84             unit_bits = cval->range_bits;
85         bpc = OS__BPC_U16;
86         break;
87     case ASN_OSUBV_U32:
88         canonical_unit_bits = unit_bits = 32;
89         if(cval->flags & APC_CONSTRAINED)
90             unit_bits = cval->range_bits;
91         bpc = OS__BPC_U32;
92         break;
93     }
94
95     /*
96      * Allocate the string.
97      */
98     if(!st) {
99         st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
100         if(!st) RETURN(RC_FAIL);
101     }
102
103     ASN_DEBUG("PER Decoding %s size %lld .. %lld bits %d",
104               csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
105               (long long int)csiz->lower_bound, (long long int)csiz->upper_bound,
106               csiz->effective_bits);
107
108     if(csiz->flags & APC_EXTENSIBLE) {
109         int inext = per_get_few_bits(pd, 1);
110         if(inext < 0) RETURN(RC_WMORE);
111         if(inext) {
112             csiz = &asn_DEF_OCTET_STRING_constraints.size;
113             cval = &asn_DEF_OCTET_STRING_constraints.value;
114             unit_bits = canonical_unit_bits;
115         }
116     }
117
118     if(csiz->effective_bits >= 0) {
119         FREEMEM(st->buf);
120         if(bpc) {
121             st->size = csiz->upper_bound * bpc;
122         } else {
123             st->size = (csiz->upper_bound + 7) >> 3;
124         }
125         st->buf = (uint8_t *)MALLOC(st->size + 1);
126         if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
127     }
128
129     /* X.691, #16.5: zero-length encoding */
130     /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
131     /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
132     if(csiz->effective_bits == 0) {
133         int ret;
134         /* X.691 #16 NOTE 1 for fixed length (<= 16 bits) strings */
135         if (st->size > 2 || csiz->range_bits != 0) {
136             if (aper_get_align(pd) < 0)
137                 RETURN(RC_FAIL);
138         }
139         if(bpc) {
140             ASN_DEBUG("Decoding OCTET STRING size %lld",
141                       (long long int)csiz->upper_bound);
142             ret = OCTET_STRING_per_get_characters(pd, st->buf,
143                                                   csiz->upper_bound,
144                                                   bpc, unit_bits,
145                                                   cval->lower_bound,
146                                                   cval->upper_bound,
147                                                   pc);
148             if(ret > 0) RETURN(RC_FAIL);
149         } else {
150             ASN_DEBUG("Decoding BIT STRING size %lld",
151                       (long long int)csiz->upper_bound);
152             ret = per_get_many_bits(pd, st->buf, 0,
153                                     unit_bits * csiz->upper_bound);
154         }
155         if(ret < 0) RETURN(RC_WMORE);
156         consumed_myself += unit_bits * csiz->upper_bound;
157         st->buf[st->size] = 0;
158         if(bpc == 0) {
159             int ubs = (csiz->upper_bound & 0x7);
160             st->bits_unused = ubs ? 8 - ubs : 0;
161         }
162         RETURN(RC_OK);
163     }
164
165     st->size = 0;
166     do {
167         ssize_t raw_len;
168         ssize_t len_bytes;
169         ssize_t len_bits;
170         void *p;
171         int ret;
172
173         repeat = 0;
174         /* Get the PER length */
175         if (csiz->upper_bound - csiz->lower_bound == 0)
176             /* Indefinite length case */
177             raw_len = aper_get_length(pd, -1, -1, csiz->effective_bits, &repeat);
178         else
179             raw_len = aper_get_length(pd, csiz->lower_bound, csiz->upper_bound,
180                                       csiz->effective_bits, &repeat);
181         if(raw_len < 0) RETURN(RC_WMORE);
182         raw_len += csiz->lower_bound;
183
184         ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
185                   (long)csiz->effective_bits, (long)raw_len,
186                   repeat ? "repeat" : "once", td->name);
187
188         /* X.691 #16 NOTE 1  for fixed length (<=16 bits) strings */
189         if ((raw_len > 2) || (csiz->upper_bound > 2) || (csiz->range_bits != 0))
190         {
191             if (aper_get_align(pd) < 0)
192                 RETURN(RC_FAIL);
193         }
194
195         if(bpc) {
196             len_bytes = raw_len * bpc;
197             len_bits = len_bytes * unit_bits;
198         } else {
199             len_bits = raw_len;
200             len_bytes = (len_bits + 7) >> 3;
201             if(len_bits & 0x7)
202                 st->bits_unused = 8 - (len_bits & 0x7);
203             /* len_bits be multiple of 16K if repeat is set */
204         }
205         p = REALLOC(st->buf, st->size + len_bytes + 1);
206         if(!p) RETURN(RC_FAIL);
207         st->buf = (uint8_t *)p;
208
209         if(bpc) {
210             ret = OCTET_STRING_per_get_characters(pd,
211                                                   &st->buf[st->size],
212                                                   raw_len, bpc,
213                                                   unit_bits,
214                                                   cval->lower_bound,
215                                                   cval->upper_bound,
216                                                   pc);
217             if(ret > 0) RETURN(RC_FAIL);
218         } else {
219             ret = per_get_many_bits(pd, &st->buf[st->size],
220                                     0, len_bits);
221         }
222         if(ret < 0) RETURN(RC_WMORE);
223         st->size += len_bytes;
224     } while(repeat);
225     st->buf[st->size] = 0;  /* nul-terminate */
226
227     return rval;
228 }
229
230 asn_enc_rval_t
231 OCTET_STRING_encode_aper(const asn_TYPE_descriptor_t *td,
232                          const asn_per_constraints_t *constraints,
233                          const void *sptr, asn_per_outp_t *po) {
234
235     const asn_OCTET_STRING_specifics_t *specs = td->specifics
236         ? (const asn_OCTET_STRING_specifics_t *)td->specifics
237         : &asn_SPC_OCTET_STRING_specs;
238     const asn_per_constraints_t *pc = constraints
239         ? constraints
240         : td->encoding_constraints.per_constraints;
241     const asn_per_constraint_t *cval;
242     const asn_per_constraint_t *csiz;
243     const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
244     asn_enc_rval_t er = { 0, 0, 0 };
245     int inext = 0;  /* Lies not within extension root */
246     unsigned int unit_bits;
247     unsigned int canonical_unit_bits;
248     unsigned int sizeinunits;
249     const uint8_t *buf;
250     int ret;
251     enum {
252         OS__BPC_BIT  = 0,
253         OS__BPC_CHAR = 1,
254         OS__BPC_U16  = 2,
255         OS__BPC_U32  = 4
256     } bpc;  /* Bytes per character */
257     int ct_extensible;
258
259     if(!st || (!st->buf && st->size))
260         ASN__ENCODE_FAILED;
261
262     if(pc) {
263         cval = &pc->value;
264         csiz = &pc->size;
265     } else {
266         cval = &asn_DEF_OCTET_STRING_constraints.value;
267         csiz = &asn_DEF_OCTET_STRING_constraints.size;
268     }
269     ct_extensible = csiz->flags & APC_EXTENSIBLE;
270
271     switch(specs->subvariant) {
272         default:
273 /*
274         case ASN_OSUBV_ANY:
275             ASN__ENCODE_FAILED;
276 */
277         case ASN_OSUBV_BIT:
278             canonical_unit_bits = unit_bits = 1;
279             bpc = OS__BPC_BIT;
280             sizeinunits = st->size * 8 - (st->bits_unused & 0x07);
281             ASN_DEBUG("BIT STRING of %d bytes",
282                       sizeinunits);
283         break;
284         case ASN_OSUBV_ANY:
285     case ASN_OSUBV_STR:
286         canonical_unit_bits = unit_bits = 8;
287 /*
288         if(cval->flags & APC_CONSTRAINED)
289             unit_bits = 8;
290 */
291         bpc = OS__BPC_CHAR;
292         sizeinunits = st->size;
293         break;
294     case ASN_OSUBV_U16:
295         canonical_unit_bits = unit_bits = 16;
296         if(cval->flags & APC_CONSTRAINED)
297             unit_bits = cval->range_bits;
298         bpc = OS__BPC_U16;
299         sizeinunits = st->size / 2;
300         break;
301     case ASN_OSUBV_U32:
302         canonical_unit_bits = unit_bits = 32;
303         if(cval->flags & APC_CONSTRAINED)
304             unit_bits = cval->range_bits;
305         bpc = OS__BPC_U32;
306         sizeinunits = st->size / 4;
307         break;
308     }
309
310     ASN_DEBUG("Encoding %s into %d units of %d bits"
311               " (%lld..%lld, effective %d)%s",
312               td->name, sizeinunits, unit_bits,
313               (long long int)csiz->lower_bound,
314               (long long int)csiz->upper_bound,
315               csiz->effective_bits, ct_extensible ? " EXT" : "");
316
317     /* Figure out wheter size lies within PER visible constraint */
318
319     if(csiz->effective_bits >= 0) {
320         if((int)sizeinunits < csiz->lower_bound
321         || (int)sizeinunits > csiz->upper_bound) {
322             if(ct_extensible) {
323                 cval = &asn_DEF_OCTET_STRING_constraints.value;
324                 csiz = &asn_DEF_OCTET_STRING_constraints.size;
325                 unit_bits = canonical_unit_bits;
326                 inext = 1;
327             } else
328                 ASN__ENCODE_FAILED;
329         }
330     } else {
331         inext = 0;
332     }
333
334     if(ct_extensible) {
335         /* Declare whether length is [not] within extension root */
336         if(per_put_few_bits(po, inext, 1))
337             ASN__ENCODE_FAILED;
338     }
339
340     /* X.691, #16.5: zero-length encoding */
341     /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
342     /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
343     if(csiz->effective_bits >= 0) {
344         ASN_DEBUG("Encoding %zu bytes (%lld), length in %d bits",
345                   st->size, (long long int)(sizeinunits - csiz->lower_bound),
346                   csiz->effective_bits);
347         if (csiz->effective_bits > 0) {
348                 ret = aper_put_length(po, csiz->lower_bound, csiz->upper_bound,
349                                       sizeinunits - csiz->lower_bound, NULL);
350                 if(ret < 0) ASN__ENCODE_FAILED;
351         }
352         if (csiz->effective_bits > 0 || (st->size > 2)
353             || (csiz->upper_bound > (2 * 8 / unit_bits))
354             || (csiz->range_bits != 0))
355         { /* X.691 #16 NOTE 1 for fixed length (<=16 bits) strings*/
356             if (aper_put_align(po) < 0)
357                 ASN__ENCODE_FAILED;
358         }
359         if(bpc) {
360             ret = OCTET_STRING_per_put_characters(po, st->buf,
361                                                   sizeinunits,
362                                                   bpc, unit_bits,
363                                                   cval->lower_bound,
364                                                   cval->upper_bound,
365                                                   pc);
366         } else {
367             ret = per_put_many_bits(po, st->buf,
368                                     sizeinunits * unit_bits);
369         }
370         if(ret) ASN__ENCODE_FAILED;
371         ASN__ENCODED_OK(er);
372     }
373
374     ASN_DEBUG("Encoding %zu bytes", st->size);
375
376     if(sizeinunits == 0) {
377         if(aper_put_length(po, -1, -1, 0, NULL) < 0)
378             ASN__ENCODE_FAILED;
379         ASN__ENCODED_OK(er);
380     }
381
382     buf = st->buf;
383     while(sizeinunits) {
384         int need_eom = 0;
385         ssize_t maySave = aper_put_length(po, -1, -1, sizeinunits, &need_eom);
386
387         if(maySave < 0) ASN__ENCODE_FAILED;
388
389         ASN_DEBUG("Encoding %ld of %ld",
390                   (long)maySave, (long)sizeinunits);
391
392         if(bpc) {
393             ret = OCTET_STRING_per_put_characters(po, buf, maySave,
394                                                   bpc, unit_bits,
395                                                   cval->lower_bound,
396                                                   cval->upper_bound,
397                                                   pc);
398         } else {
399             ret = per_put_many_bits(po, buf, maySave * unit_bits);
400         }
401         if(ret) ASN__ENCODE_FAILED;
402
403         if(bpc)
404             buf += maySave * bpc;
405         else
406             buf += maySave >> 3;
407         sizeinunits -= maySave;
408         assert(!(maySave & 0x07) || !sizeinunits);
409         if(need_eom && (aper_put_length(po, -1, -1, 0, NULL) < 0))
410             ASN__ENCODE_FAILED; /* End of Message length */
411     }
412
413     ASN__ENCODED_OK(er);
414 }