3 * Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
4 * Redistribution and modifications are permitted subject to BSD license.
7 * Read the NativeInteger.h for the explanation wrt. differences between
8 * INTEGER and NativeInteger.
9 * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
10 * implementation deals with the standard (machine-specific) representation
11 * of them instead of using the platform-independent buffer.
13 #include <asn_internal.h>
14 #include <NativeEnumerated.h>
17 * NativeEnumerated basic type description.
19 static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
20 (ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
22 asn_TYPE_operation_t asn_OP_NativeEnumerated = {
25 NativeInteger_compare,
26 NativeInteger_decode_ber,
27 NativeInteger_encode_der,
28 NativeInteger_decode_xer,
29 NativeEnumerated_encode_xer,
30 #ifdef ASN_DISABLE_OER_SUPPORT
34 NativeEnumerated_decode_oer,
35 NativeEnumerated_encode_oer,
36 #endif /* ASN_DISABLE_OER_SUPPORT */
37 #ifdef ASN_DISABLE_PER_SUPPORT
43 NativeEnumerated_decode_uper,
44 NativeEnumerated_encode_uper,
45 NativeEnumerated_decode_aper,
46 NativeEnumerated_encode_aper,
47 #endif /* ASN_DISABLE_PER_SUPPORT */
48 NativeEnumerated_random_fill,
49 0 /* Use generic outmost tag fetcher */
51 asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
52 "ENUMERATED", /* The ASN.1 type is still ENUMERATED */
54 &asn_OP_NativeEnumerated,
55 asn_DEF_NativeEnumerated_tags,
56 sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
57 asn_DEF_NativeEnumerated_tags, /* Same as above */
58 sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
59 { 0, 0, asn_generic_no_constraint },
60 0, 0, /* No members */
65 NativeEnumerated_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
66 int ilevel, enum xer_encoder_flags_e flags,
67 asn_app_consume_bytes_f *cb, void *app_key) {
68 const asn_INTEGER_specifics_t *specs =
69 (const asn_INTEGER_specifics_t *)td->specifics;
70 asn_enc_rval_t er = {0,0,0};
71 const long *native = (const long *)sptr;
72 const asn_INTEGER_enum_map_t *el;
77 if(!native) ASN__ENCODE_FAILED;
79 el = INTEGER_map_value2enum(specs, *native);
82 asn__format_to_callback(cb, app_key, "<%s/>", el->enum_name);
83 if(er.encoded < 0) ASN__ENCODE_FAILED;
87 "ASN.1 forbids dealing with "
88 "unknown value of ENUMERATED type");
94 NativeEnumerated_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
95 const asn_TYPE_descriptor_t *td,
96 const asn_per_constraints_t *constraints,
97 void **sptr, asn_per_data_t *pd) {
98 const asn_INTEGER_specifics_t *specs = td->specifics;
99 asn_dec_rval_t rval = { RC_OK, 0 };
100 long *native = (long *)*sptr;
101 const asn_per_constraint_t *ct = NULL; // BMC
106 if(constraints) ct = &constraints->value;
107 else if(td->encoding_constraints.per_constraints)
108 ct = &td->encoding_constraints.per_constraints->value;
109 else ASN__DECODE_FAILED; /* Mandatory! */
110 if(!specs) ASN__DECODE_FAILED;
113 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
114 if(!native) ASN__DECODE_FAILED;
117 ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
119 if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
120 int inext = per_get_few_bits(pd, 1);
121 if(inext < 0) ASN__DECODE_STARVED;
125 if(ct && ct->range_bits >= 0) {
126 value = per_get_few_bits(pd, ct->range_bits);
127 if(value < 0) ASN__DECODE_STARVED;
128 if(value >= (specs->extension
129 ? specs->extension - 1 : specs->map_count))
132 if(!specs->extension)
135 * X.691, #10.6: normally small non-negative whole number;
137 value = uper_get_nsnnwn(pd);
138 if(value < 0) ASN__DECODE_STARVED;
139 value += specs->extension - 1;
140 if(value >= specs->map_count)
144 *native = specs->value2enum[value].nat_value;
145 ASN_DEBUG("Decoded %s = %ld", td->name, *native);
151 NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
152 const asn_INTEGER_enum_map_t *a = ap;
153 const asn_INTEGER_enum_map_t *b = bp;
154 if(a->nat_value == b->nat_value)
156 if(a->nat_value < b->nat_value)
162 NativeEnumerated_encode_uper(const asn_TYPE_descriptor_t *td,
163 const asn_per_constraints_t *constraints,
164 const void *sptr, asn_per_outp_t *po) {
165 const asn_INTEGER_specifics_t *specs =
166 (const asn_INTEGER_specifics_t *)td->specifics;
167 asn_enc_rval_t er = {0,0,0};
169 const asn_per_constraint_t *ct = NULL; // BMC
171 asn_INTEGER_enum_map_t key;
172 const asn_INTEGER_enum_map_t *kf;
174 if(!sptr) ASN__ENCODE_FAILED;
175 if(!specs) ASN__ENCODE_FAILED;
177 if(constraints) ct = &constraints->value;
178 else if(td->encoding_constraints.per_constraints)
179 ct = &td->encoding_constraints.per_constraints->value;
180 else ASN__ENCODE_FAILED; /* Mandatory! */
182 ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
186 native = *(const long *)sptr;
188 key.nat_value = native;
189 kf = bsearch(&key, specs->value2enum, specs->map_count,
190 sizeof(key), NativeEnumerated__compar_value2enum);
192 ASN_DEBUG("No element corresponds to %ld", native);
195 value = kf - specs->value2enum;
197 if(ct && ct->range_bits >= 0) { // BMC
198 int cmpWith = specs->extension
199 ? specs->extension - 1 : specs->map_count;
203 if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
204 if(per_put_few_bits(po, inext, 1))
211 if(ct && ct->range_bits >= 0) {
212 if(per_put_few_bits(po, value, ct->range_bits))
217 if(!specs->extension)
221 * X.691, #10.6: normally small non-negative whole number;
223 ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
224 value, specs->extension, inext,
225 value - (inext ? (specs->extension - 1) : 0));
226 if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
233 NativeEnumerated_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
234 const asn_TYPE_descriptor_t *td,
235 const asn_per_constraints_t *constraints,
236 void **sptr, asn_per_data_t *pd) {
237 const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
238 asn_dec_rval_t rval = { RC_OK, 0 };
239 long *native = (long *)*sptr;
240 const asn_per_constraint_t *ct = NULL; // BMC
245 if(constraints) ct = &constraints->value;
246 else if(td->encoding_constraints.per_constraints)
247 ct = &td->encoding_constraints.per_constraints->value;
248 else ASN__DECODE_FAILED; /* Mandatory! */
249 if(!specs) ASN__DECODE_FAILED;
252 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
253 if(!native) ASN__DECODE_FAILED;
256 ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
258 if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
259 int inext = per_get_few_bits(pd, 1);
260 if(inext < 0) ASN__DECODE_STARVED;
264 /* Deal with APER padding */
265 if(ct && ct->upper_bound >= 255) {
267 padding = (8 - (pd->moved % 8)) % 8;
268 ASN_DEBUG("For NativeEnumerated %s,offset= %lu Padding bits = %d", td->name, pd->moved, padding);
269 ASN_DEBUG("For NativeEnumerated %s, upper bound = %lu", td->name, ct->upper_bound);
271 per_get_few_bits(pd, padding);
274 if(ct && ct->range_bits >= 0) {
275 value = per_get_few_bits(pd, ct->range_bits);
276 if(value < 0) ASN__DECODE_STARVED;
277 if(value >= (specs->extension
278 ? specs->extension - 1 : specs->map_count))
281 if(!specs->extension)
284 * X.691, #10.6: normally small non-negative whole number;
286 value = uper_get_nsnnwn(pd);
287 if(value < 0) ASN__DECODE_STARVED;
288 value += specs->extension - 1;
289 if(value >= specs->map_count)
293 *native = specs->value2enum[value].nat_value;
294 ASN_DEBUG("Decoded %s = %ld", td->name, *native);
300 NativeEnumerated_encode_aper(const asn_TYPE_descriptor_t *td,
301 const asn_per_constraints_t *constraints,
302 const void *sptr, asn_per_outp_t *po) {
303 const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
304 asn_enc_rval_t er = {0,0,0};
306 const asn_per_constraint_t *ct = NULL; // BMC
308 asn_INTEGER_enum_map_t key;
309 asn_INTEGER_enum_map_t *kf;
311 if(!sptr) ASN__ENCODE_FAILED;
312 if(!specs) ASN__ENCODE_FAILED;
314 if(constraints) ct = &constraints->value;
315 else if(td->encoding_constraints.per_constraints)
316 ct = &td->encoding_constraints.per_constraints->value;
317 else ASN__ENCODE_FAILED; /* Mandatory! */
319 ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
323 native = *(const long *)sptr;
324 if(native < 0) ASN__ENCODE_FAILED;
326 key.nat_value = native;
327 kf = bsearch(&key, specs->value2enum, specs->map_count,
328 sizeof(key), NativeEnumerated__compar_value2enum);
330 ASN_DEBUG("No element corresponds to %ld", native);
333 value = kf - specs->value2enum;
335 if(ct && ct->range_bits >= 0) { // BMC
336 int cmpWith = specs->extension
337 ? specs->extension - 1 : specs->map_count;
341 if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
342 if(per_put_few_bits(po, inext, 1))
349 if(ct && ct->range_bits >= 0) {
350 if(per_put_few_bits(po, value, ct->range_bits))
355 if(!specs->extension)
359 * X.691, #10.6: normally small non-negative whole number;
361 ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
362 value, specs->extension, inext,
363 value - (inext ? (specs->extension - 1) : 0));
364 if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))