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