Moving in e2sim originally from it/test/simulators
[sim/e2-interface.git] / e2sim / ASN1c / NativeEnumerated.c
1 /*****************************************************************************
2 #                                                                            *
3 # Copyright 2019 AT&T Intellectual Property                                  *
4 #                                                                            *
5 # Licensed under the Apache License, Version 2.0 (the "License");            *
6 # you may not use this file except in compliance with the License.           *
7 # You may obtain a copy of the License at                                    *
8 #                                                                            *
9 #      http://www.apache.org/licenses/LICENSE-2.0                            *
10 #                                                                            *
11 # Unless required by applicable law or agreed to in writing, software        *
12 # distributed under the License is distributed on an "AS IS" BASIS,          *
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
14 # See the License for the specific language governing permissions and        *
15 # limitations under the License.                                             *
16 #                                                                            *
17 ******************************************************************************/
18
19 /*-
20  * Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
21  * Redistribution and modifications are permitted subject to BSD license.
22  */
23 /*
24  * Read the NativeInteger.h for the explanation wrt. differences between
25  * INTEGER and NativeInteger.
26  * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
27  * implementation deals with the standard (machine-specific) representation
28  * of them instead of using the platform-independent buffer.
29  */
30 #include <asn_internal.h>
31 #include <NativeEnumerated.h>
32
33 /*
34  * NativeEnumerated basic type description.
35  */
36 static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
37         (ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
38 };
39 asn_TYPE_operation_t asn_OP_NativeEnumerated = {
40         NativeInteger_free,
41         NativeInteger_print,
42         NativeInteger_compare,
43         NativeInteger_decode_ber,
44         NativeInteger_encode_der,
45         NativeInteger_decode_xer,
46         NativeEnumerated_encode_xer,
47 #ifdef  ASN_DISABLE_OER_SUPPORT
48         0,
49         0,
50 #else
51         NativeEnumerated_decode_oer,
52         NativeEnumerated_encode_oer,
53 #endif  /* ASN_DISABLE_OER_SUPPORT */
54 #ifdef  ASN_DISABLE_PER_SUPPORT
55         0,
56         0,
57         0,
58         0,
59 #else
60         NativeEnumerated_decode_uper,
61         NativeEnumerated_encode_uper,
62         NativeEnumerated_decode_aper,
63         NativeEnumerated_encode_aper,
64 #endif  /* ASN_DISABLE_PER_SUPPORT */
65         NativeEnumerated_random_fill,
66         0       /* Use generic outmost tag fetcher */
67 };
68 asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
69         "ENUMERATED",                   /* The ASN.1 type is still ENUMERATED */
70         "ENUMERATED",
71         &asn_OP_NativeEnumerated,
72         asn_DEF_NativeEnumerated_tags,
73         sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
74         asn_DEF_NativeEnumerated_tags,  /* Same as above */
75         sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
76         { 0, 0, asn_generic_no_constraint },
77         0, 0,   /* No members */
78         0       /* No specifics */
79 };
80
81 asn_enc_rval_t
82 NativeEnumerated_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
83                             int ilevel, enum xer_encoder_flags_e flags,
84                             asn_app_consume_bytes_f *cb, void *app_key) {
85     const asn_INTEGER_specifics_t *specs =
86         (const asn_INTEGER_specifics_t *)td->specifics;
87     asn_enc_rval_t er = {0,0,0};
88     const long *native = (const long *)sptr;
89     const asn_INTEGER_enum_map_t *el;
90
91     (void)ilevel;
92     (void)flags;
93
94     if(!native) ASN__ENCODE_FAILED;
95
96     el = INTEGER_map_value2enum(specs, *native);
97     if(el) {
98         er.encoded =
99             asn__format_to_callback(cb, app_key, "<%s/>", el->enum_name);
100         if(er.encoded < 0) ASN__ENCODE_FAILED;
101         ASN__ENCODED_OK(er);
102     } else {
103         ASN_DEBUG(
104             "ASN.1 forbids dealing with "
105             "unknown value of ENUMERATED type");
106         ASN__ENCODE_FAILED;
107     }
108 }
109
110 asn_dec_rval_t
111 NativeEnumerated_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
112                              const asn_TYPE_descriptor_t *td,
113                              const asn_per_constraints_t *constraints,
114                              void **sptr, asn_per_data_t *pd) {
115     const asn_INTEGER_specifics_t *specs = td->specifics;
116     asn_dec_rval_t rval = { RC_OK, 0 };
117         long *native = (long *)*sptr;
118         const asn_per_constraint_t *ct = NULL; // BMC
119         long value;
120
121         (void)opt_codec_ctx;
122
123         if(constraints) ct = &constraints->value;
124         else if(td->encoding_constraints.per_constraints)
125                 ct = &td->encoding_constraints.per_constraints->value;
126         else ASN__DECODE_FAILED;        /* Mandatory! */
127         if(!specs) ASN__DECODE_FAILED;
128
129         if(!native) {
130                 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
131                 if(!native) ASN__DECODE_FAILED;
132         }
133
134         ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
135
136         if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
137                 int inext = per_get_few_bits(pd, 1);
138                 if(inext < 0) ASN__DECODE_STARVED;
139                 if(inext) ct = 0;
140         }
141
142         if(ct && ct->range_bits >= 0) {
143                 value = per_get_few_bits(pd, ct->range_bits);
144                 if(value < 0) ASN__DECODE_STARVED;
145                 if(value >= (specs->extension
146                         ? specs->extension - 1 : specs->map_count))
147                         ASN__DECODE_FAILED;
148         } else {
149                 if(!specs->extension)
150                         ASN__DECODE_FAILED;
151                 /*
152                  * X.691, #10.6: normally small non-negative whole number;
153                  */
154                 value = uper_get_nsnnwn(pd);
155                 if(value < 0) ASN__DECODE_STARVED;
156                 value += specs->extension - 1;
157                 if(value >= specs->map_count)
158                         ASN__DECODE_FAILED;
159         }
160
161         *native = specs->value2enum[value].nat_value;
162         ASN_DEBUG("Decoded %s = %ld", td->name, *native);
163
164         return rval;
165 }
166
167 static int
168 NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
169         const asn_INTEGER_enum_map_t *a = ap;
170         const asn_INTEGER_enum_map_t *b = bp;
171         if(a->nat_value == b->nat_value)
172                 return 0;
173         if(a->nat_value < b->nat_value)
174                 return -1;
175         return 1;
176 }
177
178 asn_enc_rval_t
179 NativeEnumerated_encode_uper(const asn_TYPE_descriptor_t *td,
180                              const asn_per_constraints_t *constraints,
181                              const void *sptr, asn_per_outp_t *po) {
182         const asn_INTEGER_specifics_t *specs =
183         (const asn_INTEGER_specifics_t *)td->specifics;
184         asn_enc_rval_t er = {0,0,0};
185         long native, value;
186         const asn_per_constraint_t *ct = NULL; // BMC
187         int inext = 0;
188         asn_INTEGER_enum_map_t key;
189         const asn_INTEGER_enum_map_t *kf;
190
191         if(!sptr) ASN__ENCODE_FAILED;
192         if(!specs) ASN__ENCODE_FAILED;
193
194         if(constraints) ct = &constraints->value;
195         else if(td->encoding_constraints.per_constraints)
196                 ct = &td->encoding_constraints.per_constraints->value;
197         else ASN__ENCODE_FAILED;        /* Mandatory! */
198
199         ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
200
201         er.encoded = 0;
202
203         native = *(const long *)sptr;
204
205         key.nat_value = native;
206         kf = bsearch(&key, specs->value2enum, specs->map_count,
207                 sizeof(key), NativeEnumerated__compar_value2enum);
208         if(!kf) {
209                 ASN_DEBUG("No element corresponds to %ld", native);
210                 ASN__ENCODE_FAILED;
211         }
212         value = kf - specs->value2enum;
213
214         if(ct && ct->range_bits >= 0) { // BMC
215                 int cmpWith = specs->extension
216                                 ? specs->extension - 1 : specs->map_count;
217                 if(value >= cmpWith)
218                         inext = 1;
219         }
220         if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
221                 if(per_put_few_bits(po, inext, 1))
222                         ASN__ENCODE_FAILED;
223                 if(inext) ct = 0;
224         } else if(inext) {
225                 ASN__ENCODE_FAILED;
226         }
227
228         if(ct && ct->range_bits >= 0) {
229                 if(per_put_few_bits(po, value, ct->range_bits))
230                         ASN__ENCODE_FAILED;
231                 ASN__ENCODED_OK(er);
232         }
233
234         if(!specs->extension)
235                 ASN__ENCODE_FAILED;
236
237         /*
238          * X.691, #10.6: normally small non-negative whole number;
239          */
240         ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
241                 value, specs->extension, inext,
242                 value - (inext ? (specs->extension - 1) : 0));
243         if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
244                 ASN__ENCODE_FAILED;
245
246         ASN__ENCODED_OK(er);
247 }
248
249 asn_dec_rval_t
250 NativeEnumerated_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
251                              const asn_TYPE_descriptor_t *td,
252                              const asn_per_constraints_t *constraints,
253                              void **sptr, asn_per_data_t *pd) {
254         const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
255         asn_dec_rval_t rval = { RC_OK, 0 };
256         long *native = (long *)*sptr;
257         const asn_per_constraint_t *ct = NULL; // BMC
258         long value;
259
260         (void)opt_codec_ctx;
261
262         if(constraints) ct = &constraints->value;
263         else if(td->encoding_constraints.per_constraints)
264                 ct = &td->encoding_constraints.per_constraints->value;
265         else ASN__DECODE_FAILED;        /* Mandatory! */
266         if(!specs) ASN__DECODE_FAILED;
267
268         if(!native) {
269                 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
270                 if(!native) ASN__DECODE_FAILED;
271         }
272
273         ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
274
275         if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
276                 int inext = per_get_few_bits(pd, 1);
277                 if(inext < 0) ASN__DECODE_STARVED;
278                 if(inext) ct = 0;
279         }
280
281         /* Deal with APER padding */
282         if(ct && ct->upper_bound >= 255) {
283                 int padding = 0;
284                 padding = (8 - (pd->moved % 8)) % 8;
285                 ASN_DEBUG("For NativeEnumerated %s,offset= %lu Padding bits = %d", td->name, pd->moved, padding);
286                 ASN_DEBUG("For NativeEnumerated %s, upper bound = %lu", td->name, ct->upper_bound);
287                 if(padding > 0)
288                         per_get_few_bits(pd, padding);
289         }
290
291         if(ct && ct->range_bits >= 0) {
292                 value = per_get_few_bits(pd, ct->range_bits);
293                 if(value < 0) ASN__DECODE_STARVED;
294                 if(value >= (specs->extension
295                              ? specs->extension - 1 : specs->map_count))
296                         ASN__DECODE_FAILED;
297         } else {
298                 if(!specs->extension)
299                         ASN__DECODE_FAILED;
300                 /*
301                  * X.691, #10.6: normally small non-negative whole number;
302                  */
303                 value = uper_get_nsnnwn(pd);
304                 if(value < 0) ASN__DECODE_STARVED;
305                 value += specs->extension - 1;
306                 if(value >= specs->map_count)
307                         ASN__DECODE_FAILED;
308         }
309
310         *native = specs->value2enum[value].nat_value;
311         ASN_DEBUG("Decoded %s = %ld", td->name, *native);
312
313         return rval;
314 }
315
316 asn_enc_rval_t
317 NativeEnumerated_encode_aper(const asn_TYPE_descriptor_t *td,
318                              const asn_per_constraints_t *constraints,
319                              const void *sptr, asn_per_outp_t *po) {
320         const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
321         asn_enc_rval_t er = {0,0,0};
322         long native, value;
323         const asn_per_constraint_t *ct = NULL; // BMC
324         int inext = 0;
325         asn_INTEGER_enum_map_t key;
326         asn_INTEGER_enum_map_t *kf;
327
328         if(!sptr) ASN__ENCODE_FAILED;
329         if(!specs) ASN__ENCODE_FAILED;
330
331         if(constraints) ct = &constraints->value;
332         else if(td->encoding_constraints.per_constraints)
333                 ct = &td->encoding_constraints.per_constraints->value;
334         else ASN__ENCODE_FAILED;        /* Mandatory! */
335
336         ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
337
338         er.encoded = 0;
339
340         native = *(const long *)sptr;
341         if(native < 0) ASN__ENCODE_FAILED;
342
343         key.nat_value = native;
344         kf = bsearch(&key, specs->value2enum, specs->map_count,
345                      sizeof(key), NativeEnumerated__compar_value2enum);
346         if(!kf) {
347                 ASN_DEBUG("No element corresponds to %ld", native);
348                 ASN__ENCODE_FAILED;
349         }
350         value = kf - specs->value2enum;
351
352         if(ct && ct->range_bits >= 0) { // BMC
353                 int cmpWith = specs->extension
354                               ? specs->extension - 1 : specs->map_count;
355                 if(value >= cmpWith)
356                         inext = 1;
357         }
358         if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
359                 if(per_put_few_bits(po, inext, 1))
360                         ASN__ENCODE_FAILED;
361                 if(inext) ct = 0;
362         } else if(inext) {
363                 ASN__ENCODE_FAILED;
364         }
365
366         if(ct && ct->range_bits >= 0) {
367                 if(per_put_few_bits(po, value, ct->range_bits))
368                         ASN__ENCODE_FAILED;
369                 ASN__ENCODED_OK(er);
370         }
371
372         if(!specs->extension)
373                 ASN__ENCODE_FAILED;
374
375         /*
376          * X.691, #10.6: normally small non-negative whole number;
377          */
378         ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
379                   value, specs->extension, inext,
380                   value - (inext ? (specs->extension - 1) : 0));
381         if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
382                 ASN__ENCODE_FAILED;
383
384         ASN__ENCODED_OK(er);
385 }