1 /*****************************************************************************
3 # Copyright 2019 AT&T Intellectual Property *
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 *
9 # http://www.apache.org/licenses/LICENSE-2.0 *
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. *
17 ******************************************************************************/
20 * Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
21 * Redistribution and modifications are permitted subject to BSD license.
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.
30 #include <asn_internal.h>
31 #include <NativeEnumerated.h>
34 * NativeEnumerated basic type description.
36 static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
37 (ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
39 asn_TYPE_operation_t asn_OP_NativeEnumerated = {
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
51 NativeEnumerated_decode_oer,
52 NativeEnumerated_encode_oer,
53 #endif /* ASN_DISABLE_OER_SUPPORT */
54 #ifdef ASN_DISABLE_PER_SUPPORT
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 */
68 asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
69 "ENUMERATED", /* The ASN.1 type is still 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 */
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;
94 if(!native) ASN__ENCODE_FAILED;
96 el = INTEGER_map_value2enum(specs, *native);
99 asn__format_to_callback(cb, app_key, "<%s/>", el->enum_name);
100 if(er.encoded < 0) ASN__ENCODE_FAILED;
104 "ASN.1 forbids dealing with "
105 "unknown value of ENUMERATED type");
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
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;
130 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
131 if(!native) ASN__DECODE_FAILED;
134 ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
136 if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
137 int inext = per_get_few_bits(pd, 1);
138 if(inext < 0) ASN__DECODE_STARVED;
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))
149 if(!specs->extension)
152 * X.691, #10.6: normally small non-negative whole number;
154 value = uper_get_nsnnwn(pd);
155 if(value < 0) ASN__DECODE_STARVED;
156 value += specs->extension - 1;
157 if(value >= specs->map_count)
161 *native = specs->value2enum[value].nat_value;
162 ASN_DEBUG("Decoded %s = %ld", td->name, *native);
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)
173 if(a->nat_value < b->nat_value)
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};
186 const asn_per_constraint_t *ct = NULL; // BMC
188 asn_INTEGER_enum_map_t key;
189 const asn_INTEGER_enum_map_t *kf;
191 if(!sptr) ASN__ENCODE_FAILED;
192 if(!specs) ASN__ENCODE_FAILED;
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! */
199 ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
203 native = *(const long *)sptr;
205 key.nat_value = native;
206 kf = bsearch(&key, specs->value2enum, specs->map_count,
207 sizeof(key), NativeEnumerated__compar_value2enum);
209 ASN_DEBUG("No element corresponds to %ld", native);
212 value = kf - specs->value2enum;
214 if(ct && ct->range_bits >= 0) { // BMC
215 int cmpWith = specs->extension
216 ? specs->extension - 1 : specs->map_count;
220 if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
221 if(per_put_few_bits(po, inext, 1))
228 if(ct && ct->range_bits >= 0) {
229 if(per_put_few_bits(po, value, ct->range_bits))
234 if(!specs->extension)
238 * X.691, #10.6: normally small non-negative whole number;
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)))
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
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;
269 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
270 if(!native) ASN__DECODE_FAILED;
273 ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
275 if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
276 int inext = per_get_few_bits(pd, 1);
277 if(inext < 0) ASN__DECODE_STARVED;
281 /* Deal with APER padding */
282 if(ct && ct->upper_bound >= 255) {
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);
288 per_get_few_bits(pd, padding);
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))
298 if(!specs->extension)
301 * X.691, #10.6: normally small non-negative whole number;
303 value = uper_get_nsnnwn(pd);
304 if(value < 0) ASN__DECODE_STARVED;
305 value += specs->extension - 1;
306 if(value >= specs->map_count)
310 *native = specs->value2enum[value].nat_value;
311 ASN_DEBUG("Decoded %s = %ld", td->name, *native);
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};
323 const asn_per_constraint_t *ct = NULL; // BMC
325 asn_INTEGER_enum_map_t key;
326 asn_INTEGER_enum_map_t *kf;
328 if(!sptr) ASN__ENCODE_FAILED;
329 if(!specs) ASN__ENCODE_FAILED;
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! */
336 ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
340 native = *(const long *)sptr;
341 if(native < 0) ASN__ENCODE_FAILED;
343 key.nat_value = native;
344 kf = bsearch(&key, specs->value2enum, specs->map_count,
345 sizeof(key), NativeEnumerated__compar_value2enum);
347 ASN_DEBUG("No element corresponds to %ld", native);
350 value = kf - specs->value2enum;
352 if(ct && ct->range_bits >= 0) { // BMC
353 int cmpWith = specs->extension
354 ? specs->extension - 1 : specs->map_count;
358 if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
359 if(per_put_few_bits(po, inext, 1))
366 if(ct && ct->range_bits >= 0) {
367 if(per_put_few_bits(po, value, ct->range_bits))
372 if(!specs->extension)
376 * X.691, #10.6: normally small non-negative whole number;
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)))