2 * Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
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.
12 #include <asn_internal.h>
13 #include <NativeEnumerated.h>
16 * NativeEnumerated basic type description.
18 static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
19 (ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
21 asn_TYPE_operation_t asn_OP_NativeEnumerated = {
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
33 NativeEnumerated_decode_oer,
34 NativeEnumerated_encode_oer,
35 #endif /* ASN_DISABLE_OER_SUPPORT */
36 #ifdef ASN_DISABLE_PER_SUPPORT
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 */
50 asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
51 "ENUMERATED", /* The ASN.1 type is still 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 */
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;
76 if(!native) ASN__ENCODE_FAILED;
78 el = INTEGER_map_value2enum(specs, *native);
81 asn__format_to_callback(cb, app_key, "<%s/>", el->enum_name);
82 if(er.encoded < 0) ASN__ENCODE_FAILED;
86 "ASN.1 forbids dealing with "
87 "unknown value of ENUMERATED type");
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;
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;
112 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
113 if(!native) ASN__DECODE_FAILED;
116 ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
118 if(ct->flags & APC_EXTENSIBLE) {
119 int inext = per_get_few_bits(pd, 1);
120 if(inext < 0) ASN__DECODE_STARVED;
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))
131 if(!specs->extension)
134 * X.691, #10.6: normally small non-negative whole number;
136 value = uper_get_nsnnwn(pd);
137 if(value < 0) ASN__DECODE_STARVED;
138 value += specs->extension - 1;
139 if(value >= specs->map_count)
143 *native = specs->value2enum[value].nat_value;
144 ASN_DEBUG("Decoded %s = %ld", td->name, *native);
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)
155 if(a->nat_value < b->nat_value)
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};
168 const asn_per_constraint_t *ct;
170 asn_INTEGER_enum_map_t key;
171 const asn_INTEGER_enum_map_t *kf;
173 if(!sptr) ASN__ENCODE_FAILED;
174 if(!specs) ASN__ENCODE_FAILED;
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! */
181 ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
185 native = *(const long *)sptr;
187 key.nat_value = native;
188 kf = bsearch(&key, specs->value2enum, specs->map_count,
189 sizeof(key), NativeEnumerated__compar_value2enum);
191 ASN_DEBUG("No element corresponds to %ld", native);
194 value = kf - specs->value2enum;
196 if(ct->range_bits >= 0) {
197 int cmpWith = specs->extension
198 ? specs->extension - 1 : specs->map_count;
202 if(ct->flags & APC_EXTENSIBLE) {
203 if(per_put_few_bits(po, inext, 1))
210 if(ct && ct->range_bits >= 0) {
211 if(per_put_few_bits(po, value, ct->range_bits))
216 if(!specs->extension)
220 * X.691, #10.6: normally small non-negative whole number;
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)))
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;
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;
251 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
252 if(!native) ASN__DECODE_FAILED;
255 ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
257 if(ct->flags & APC_EXTENSIBLE) {
258 int inext = per_get_few_bits(pd, 1);
259 if(inext < 0) ASN__DECODE_STARVED;
263 /* Deal with APER padding */
264 if(ct && ct->upper_bound >= 255) {
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);
270 per_get_few_bits(pd, padding);
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))
280 if(!specs->extension)
283 * X.691, #10.6: normally small non-negative whole number;
285 value = uper_get_nsnnwn(pd);
286 if(value < 0) ASN__DECODE_STARVED;
287 value += specs->extension - 1;
288 if(value >= specs->map_count)
292 *native = specs->value2enum[value].nat_value;
293 ASN_DEBUG("Decoded %s = %ld", td->name, *native);
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};
305 const asn_per_constraint_t *ct;
307 asn_INTEGER_enum_map_t key;
308 asn_INTEGER_enum_map_t *kf;
310 if(!sptr) ASN__ENCODE_FAILED;
311 if(!specs) ASN__ENCODE_FAILED;
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! */
318 ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
322 native = *(const long *)sptr;
323 if(native < 0) ASN__ENCODE_FAILED;
325 key.nat_value = native;
326 kf = bsearch(&key, specs->value2enum, specs->map_count,
327 sizeof(key), NativeEnumerated__compar_value2enum);
329 ASN_DEBUG("No element corresponds to %ld", native);
332 value = kf - specs->value2enum;
334 if(ct->range_bits >= 0) {
335 int cmpWith = specs->extension
336 ? specs->extension - 1 : specs->map_count;
340 if(ct->flags & APC_EXTENSIBLE) {
341 if(per_put_few_bits(po, inext, 1))
348 if(ct && ct->range_bits >= 0) {
349 if(per_put_few_bits(po, value, ct->range_bits))
354 if(!specs->extension)
358 * X.691, #10.6: normally small non-negative whole number;
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)))