SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / OCTET_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 <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_uper(const asn_codec_ctx_t *opt_codec_ctx,
26                          const asn_TYPE_descriptor_t *td,
27                          const asn_per_constraints_t *constraints, void **sptr,
28                          asn_per_data_t *pd) {
29     const asn_OCTET_STRING_specifics_t *specs = td->specifics
30         ? (const asn_OCTET_STRING_specifics_t *)td->specifics
31         : &asn_SPC_OCTET_STRING_specs;
32     const asn_per_constraints_t *pc =
33         constraints ? constraints : td->encoding_constraints.per_constraints;
34     const asn_per_constraint_t *cval;
35     const asn_per_constraint_t *csiz;
36     asn_dec_rval_t rval = { RC_OK, 0 };
37     OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr;
38     ssize_t consumed_myself = 0;
39     int repeat;
40     enum {
41         OS__BPC_CHAR = 1,
42         OS__BPC_U16 = 2,
43         OS__BPC_U32 = 4
44     } bpc;  /* Bytes per character */
45     unsigned int unit_bits;
46     unsigned int canonical_unit_bits;
47
48     (void)opt_codec_ctx;
49
50     if(pc) {
51         cval = &pc->value;
52         csiz = &pc->size;
53     } else {
54         cval = &asn_DEF_OCTET_STRING_constraints.value;
55         csiz = &asn_DEF_OCTET_STRING_constraints.size;
56     }
57
58     switch(specs->subvariant) {
59     default:
60     case ASN_OSUBV_ANY:
61     case ASN_OSUBV_BIT:
62         ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant);
63         RETURN(RC_FAIL);
64         break;
65     case ASN_OSUBV_STR:
66         canonical_unit_bits = unit_bits = 8;
67         if(cval->flags & APC_CONSTRAINED)
68             unit_bits = cval->range_bits;
69         bpc = OS__BPC_CHAR;
70         break;
71     case ASN_OSUBV_U16:
72         canonical_unit_bits = unit_bits = 16;
73         if(cval->flags & APC_CONSTRAINED)
74             unit_bits = cval->range_bits;
75         bpc = OS__BPC_U16;
76         break;
77     case ASN_OSUBV_U32:
78         canonical_unit_bits = unit_bits = 32;
79         if(cval->flags & APC_CONSTRAINED)
80             unit_bits = cval->range_bits;
81         bpc = OS__BPC_U32;
82         break;
83     }
84
85     /*
86      * Allocate the string.
87      */
88     if(!st) {
89         st = (OCTET_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
90         if(!st) RETURN(RC_FAIL);
91     }
92
93     ASN_DEBUG("PER Decoding %s size %ld .. %ld bits %d",
94               csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
95               csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
96
97     if(csiz->flags & APC_EXTENSIBLE) {
98         int inext = per_get_few_bits(pd, 1);
99         if(inext < 0) RETURN(RC_WMORE);
100         if(inext) {
101             csiz = &asn_DEF_OCTET_STRING_constraints.size;
102             unit_bits = canonical_unit_bits;
103         }
104     }
105
106     if(csiz->effective_bits >= 0) {
107         FREEMEM(st->buf);
108         if(bpc) {
109             st->size = csiz->upper_bound * bpc;
110         } else {
111             st->size = (csiz->upper_bound + 7) >> 3;
112         }
113         st->buf = (uint8_t *)MALLOC(st->size + 1);
114         if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
115     }
116
117     /* X.691, #16.5: zero-length encoding */
118     /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
119     /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
120     if(csiz->effective_bits == 0) {
121         int ret;
122         if(bpc) {
123             ASN_DEBUG("Encoding OCTET STRING size %ld",
124                       csiz->upper_bound);
125             ret = OCTET_STRING_per_get_characters(pd, st->buf,
126                                                   csiz->upper_bound,
127                                                   bpc, unit_bits,
128                                                   cval->lower_bound,
129                                                   cval->upper_bound,
130                                                   pc);
131             if(ret > 0) RETURN(RC_FAIL);
132         } else {
133             ASN_DEBUG("Encoding BIT STRING size %ld",
134                       csiz->upper_bound);
135             ret = per_get_many_bits(pd, st->buf, 0,
136                                     unit_bits * csiz->upper_bound);
137         }
138         if(ret < 0) RETURN(RC_WMORE);
139         consumed_myself += unit_bits * csiz->upper_bound;
140         st->buf[st->size] = 0;
141         RETURN(RC_OK);
142     }
143
144     st->size = 0;
145     do {
146         ssize_t raw_len;
147         ssize_t len_bytes;
148         void *p;
149         int ret;
150
151         /* Get the PER length */
152         raw_len = uper_get_length(pd, csiz->effective_bits, csiz->lower_bound,
153                                   &repeat);
154         if(raw_len < 0) RETURN(RC_WMORE);
155         if(raw_len == 0 && st->buf) break;
156
157         ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
158                   (long)csiz->effective_bits, (long)raw_len,
159                   repeat ? "repeat" : "once", td->name);
160         len_bytes = raw_len * bpc;
161         p = REALLOC(st->buf, st->size + len_bytes + 1);
162         if(!p) RETURN(RC_FAIL);
163         st->buf = (uint8_t *)p;
164
165         ret = OCTET_STRING_per_get_characters(pd, &st->buf[st->size], raw_len,
166                                               bpc, unit_bits, cval->lower_bound,
167                                               cval->upper_bound, pc);
168         if(ret > 0) RETURN(RC_FAIL);
169         if(ret < 0) RETURN(RC_WMORE);
170         st->size += len_bytes;
171     } while(repeat);
172     st->buf[st->size] = 0;  /* nul-terminate */
173
174     return rval;
175 }
176
177 asn_enc_rval_t
178 OCTET_STRING_encode_uper(const asn_TYPE_descriptor_t *td,
179                          const asn_per_constraints_t *constraints,
180                          const void *sptr, asn_per_outp_t *po) {
181     const asn_OCTET_STRING_specifics_t *specs = td->specifics
182         ? (const asn_OCTET_STRING_specifics_t *)td->specifics
183         : &asn_SPC_OCTET_STRING_specs;
184     const asn_per_constraints_t *pc = constraints
185         ? constraints
186         : td->encoding_constraints.per_constraints;
187     const asn_per_constraint_t *cval;
188     const asn_per_constraint_t *csiz;
189     const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
190     asn_enc_rval_t er = { 0, 0, 0 };
191     int inext = 0;  /* Lies not within extension root */
192     unsigned int unit_bits;
193     unsigned int canonical_unit_bits;
194     size_t size_in_units;
195     const uint8_t *buf;
196     int ret;
197     enum {
198         OS__BPC_CHAR = 1,
199         OS__BPC_U16 = 2,
200         OS__BPC_U32 = 4
201     } bpc;  /* Bytes per character */
202     int ct_extensible;
203
204     if(!st || (!st->buf && st->size))
205         ASN__ENCODE_FAILED;
206
207     if(pc) {
208         cval = &pc->value;
209         csiz = &pc->size;
210     } else {
211         cval = &asn_DEF_OCTET_STRING_constraints.value;
212         csiz = &asn_DEF_OCTET_STRING_constraints.size;
213     }
214     ct_extensible = csiz->flags & APC_EXTENSIBLE;
215
216     switch(specs->subvariant) {
217     default:
218     case ASN_OSUBV_ANY:
219     case ASN_OSUBV_BIT:
220         ASN__ENCODE_FAILED;
221     case ASN_OSUBV_STR:
222         canonical_unit_bits = unit_bits = 8;
223         if(cval->flags & APC_CONSTRAINED)
224             unit_bits = cval->range_bits;
225         bpc = OS__BPC_CHAR;
226         size_in_units = st->size;
227         break;
228     case ASN_OSUBV_U16:
229         canonical_unit_bits = unit_bits = 16;
230         if(cval->flags & APC_CONSTRAINED)
231             unit_bits = cval->range_bits;
232         bpc = OS__BPC_U16;
233         size_in_units = st->size >> 1;
234         if(st->size & 1) {
235             ASN_DEBUG("%s string size is not modulo 2", td->name);
236             ASN__ENCODE_FAILED;
237         }
238         break;
239     case ASN_OSUBV_U32:
240         canonical_unit_bits = unit_bits = 32;
241         if(cval->flags & APC_CONSTRAINED)
242             unit_bits = cval->range_bits;
243         bpc = OS__BPC_U32;
244         size_in_units = st->size >> 2;
245         if(st->size & 3) {
246             ASN_DEBUG("%s string size is not modulo 4", td->name);
247             ASN__ENCODE_FAILED;
248         }
249         break;
250     }
251
252     ASN_DEBUG("Encoding %s into %" ASN_PRI_SIZE " units of %d bits"
253               " (%ld..%ld, effective %d)%s",
254               td->name, size_in_units, unit_bits,
255               csiz->lower_bound, csiz->upper_bound,
256               csiz->effective_bits, ct_extensible ? " EXT" : "");
257
258     /* Figure out whether size lies within PER visible constraint */
259
260     if(csiz->effective_bits >= 0) {
261         if((ssize_t)size_in_units < csiz->lower_bound
262            || (ssize_t)size_in_units > csiz->upper_bound) {
263             if(ct_extensible) {
264                 csiz = &asn_DEF_OCTET_STRING_constraints.size;
265                 unit_bits = canonical_unit_bits;
266                 inext = 1;
267             } else {
268                 ASN__ENCODE_FAILED;
269             }
270         }
271     } else {
272         inext = 0;
273     }
274
275     if(ct_extensible) {
276         /* Declare whether length is [not] within extension root */
277         if(per_put_few_bits(po, inext, 1))
278             ASN__ENCODE_FAILED;
279     }
280
281     if(csiz->effective_bits >= 0 && !inext) {
282         ASN_DEBUG("Encoding %" ASN_PRI_SIZE " bytes (%ld), length in %d bits", st->size,
283                   size_in_units - csiz->lower_bound, csiz->effective_bits);
284         ret = per_put_few_bits(po, size_in_units - csiz->lower_bound,
285                                csiz->effective_bits);
286         if(ret) ASN__ENCODE_FAILED;
287         ret = OCTET_STRING_per_put_characters(po, st->buf, size_in_units, bpc,
288                                               unit_bits, cval->lower_bound,
289                                               cval->upper_bound, pc);
290         if(ret) ASN__ENCODE_FAILED;
291         ASN__ENCODED_OK(er);
292     }
293
294     ASN_DEBUG("Encoding %" ASN_PRI_SIZE " bytes", st->size);
295
296     buf = st->buf;
297     ASN_DEBUG("Encoding %" ASN_PRI_SIZE " in units", size_in_units);
298     do {
299         int need_eom = 0;
300         ssize_t may_save = uper_put_length(po, size_in_units, &need_eom);
301         if(may_save < 0) ASN__ENCODE_FAILED;
302
303         ASN_DEBUG("Encoding %" ASN_PRI_SSIZE " of %" ASN_PRI_SIZE "%s", may_save, size_in_units,
304                   need_eom ? ",+EOM" : "");
305
306         ret = OCTET_STRING_per_put_characters(po, buf, may_save, bpc, unit_bits,
307                                               cval->lower_bound,
308                                               cval->upper_bound, pc);
309         if(ret) ASN__ENCODE_FAILED;
310
311         buf += may_save * bpc;
312         size_in_units -= may_save;
313         assert(!(may_save & 0x07) || !size_in_units);
314         if(need_eom && uper_put_length(po, 0, 0))
315             ASN__ENCODE_FAILED; /* End of Message length */
316     } while(size_in_units);
317
318     ASN__ENCODED_OK(er);
319 }