2 * Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
\r
3 * Redistribution and modifications are permitted subject to BSD license.
\r
6 * Read the NativeInteger.h for the explanation wrt. differences between
\r
7 * INTEGER and NativeInteger.
\r
8 * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
\r
9 * implementation deals with the standard (machine-specific) representation
\r
10 * of them instead of using the platform-independent buffer.
\r
12 #include <asn_internal.h>
\r
13 #include <NativeEnumerated.h>
\r
16 * NativeEnumerated basic type description.
\r
18 static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
\r
19 (ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
\r
21 asn_TYPE_operation_t asn_OP_NativeEnumerated = {
\r
23 NativeInteger_print,
\r
24 NativeInteger_compare,
\r
25 NativeInteger_decode_ber,
\r
26 NativeInteger_encode_der,
\r
27 NativeInteger_decode_xer,
\r
28 NativeEnumerated_encode_xer,
\r
29 #ifdef ASN_DISABLE_OER_SUPPORT
\r
33 NativeEnumerated_decode_oer,
\r
34 NativeEnumerated_encode_oer,
\r
35 #endif /* ASN_DISABLE_OER_SUPPORT */
\r
36 #ifdef ASN_DISABLE_PER_SUPPORT
\r
42 NativeEnumerated_decode_uper,
\r
43 NativeEnumerated_encode_uper,
\r
44 NativeEnumerated_decode_aper,
\r
45 NativeEnumerated_encode_aper,
\r
46 #endif /* ASN_DISABLE_PER_SUPPORT */
\r
47 NativeEnumerated_random_fill,
\r
48 0 /* Use generic outmost tag fetcher */
\r
50 asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
\r
51 "ENUMERATED", /* The ASN.1 type is still ENUMERATED */
\r
53 &asn_OP_NativeEnumerated,
\r
54 asn_DEF_NativeEnumerated_tags,
\r
55 sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
\r
56 asn_DEF_NativeEnumerated_tags, /* Same as above */
\r
57 sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
\r
58 { 0, 0, asn_generic_no_constraint },
\r
59 0, 0, /* No members */
\r
60 0 /* No specifics */
\r
64 NativeEnumerated_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
\r
65 int ilevel, enum xer_encoder_flags_e flags,
\r
66 asn_app_consume_bytes_f *cb, void *app_key) {
\r
67 const asn_INTEGER_specifics_t *specs =
\r
68 (const asn_INTEGER_specifics_t *)td->specifics;
\r
69 asn_enc_rval_t er = {0,0,0};
\r
70 const long *native = (const long *)sptr;
\r
71 const asn_INTEGER_enum_map_t *el;
\r
76 if(!native) ASN__ENCODE_FAILED;
\r
78 el = INTEGER_map_value2enum(specs, *native);
\r
81 asn__format_to_callback(cb, app_key, "<%s/>", el->enum_name);
\r
82 if(er.encoded < 0) ASN__ENCODE_FAILED;
\r
83 ASN__ENCODED_OK(er);
\r
86 "ASN.1 forbids dealing with "
\r
87 "unknown value of ENUMERATED type");
\r
93 NativeEnumerated_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
\r
94 const asn_TYPE_descriptor_t *td,
\r
95 const asn_per_constraints_t *constraints,
\r
96 void **sptr, asn_per_data_t *pd) {
\r
97 const asn_INTEGER_specifics_t *specs = td->specifics;
\r
98 asn_dec_rval_t rval = { RC_OK, 0 };
\r
99 long *native = (long *)*sptr;
\r
100 const asn_per_constraint_t *ct;
\r
103 (void)opt_codec_ctx;
\r
105 if(constraints) ct = &constraints->value;
\r
106 else if(td->encoding_constraints.per_constraints)
\r
107 ct = &td->encoding_constraints.per_constraints->value;
\r
108 else ASN__DECODE_FAILED; /* Mandatory! */
\r
109 if(!specs) ASN__DECODE_FAILED;
\r
112 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
\r
113 if(!native) ASN__DECODE_FAILED;
\r
116 ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
\r
118 if(ct->flags & APC_EXTENSIBLE) {
\r
119 int inext = per_get_few_bits(pd, 1);
\r
120 if(inext < 0) ASN__DECODE_STARVED;
\r
124 if(ct && ct->range_bits >= 0) {
\r
125 value = per_get_few_bits(pd, ct->range_bits);
\r
126 if(value < 0) ASN__DECODE_STARVED;
\r
127 if(value >= (specs->extension
\r
128 ? specs->extension - 1 : specs->map_count))
\r
129 ASN__DECODE_FAILED;
\r
131 if(!specs->extension)
\r
132 ASN__DECODE_FAILED;
\r
134 * X.691, #10.6: normally small non-negative whole number;
\r
136 value = uper_get_nsnnwn(pd);
\r
137 if(value < 0) ASN__DECODE_STARVED;
\r
138 value += specs->extension - 1;
\r
139 if(value >= specs->map_count)
\r
140 ASN__DECODE_FAILED;
\r
143 *native = specs->value2enum[value].nat_value;
\r
144 ASN_DEBUG("Decoded %s = %ld", td->name, *native);
\r
150 NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
\r
151 const asn_INTEGER_enum_map_t *a = ap;
\r
152 const asn_INTEGER_enum_map_t *b = bp;
\r
153 if(a->nat_value == b->nat_value)
\r
155 if(a->nat_value < b->nat_value)
\r
161 NativeEnumerated_encode_uper(const asn_TYPE_descriptor_t *td,
\r
162 const asn_per_constraints_t *constraints,
\r
163 const void *sptr, asn_per_outp_t *po) {
\r
164 const asn_INTEGER_specifics_t *specs =
\r
165 (const asn_INTEGER_specifics_t *)td->specifics;
\r
166 asn_enc_rval_t er = {0,0,0};
\r
167 long native, value;
\r
168 const asn_per_constraint_t *ct;
\r
170 asn_INTEGER_enum_map_t key;
\r
171 const asn_INTEGER_enum_map_t *kf;
\r
173 if(!sptr) ASN__ENCODE_FAILED;
\r
174 if(!specs) ASN__ENCODE_FAILED;
\r
176 if(constraints) ct = &constraints->value;
\r
177 else if(td->encoding_constraints.per_constraints)
\r
178 ct = &td->encoding_constraints.per_constraints->value;
\r
179 else ASN__ENCODE_FAILED; /* Mandatory! */
\r
181 ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
\r
185 native = *(const long *)sptr;
\r
187 key.nat_value = native;
\r
188 kf = bsearch(&key, specs->value2enum, specs->map_count,
\r
189 sizeof(key), NativeEnumerated__compar_value2enum);
\r
191 ASN_DEBUG("No element corresponds to %ld", native);
\r
192 ASN__ENCODE_FAILED;
\r
194 value = kf - specs->value2enum;
\r
196 if(ct->range_bits >= 0) {
\r
197 int cmpWith = specs->extension
\r
198 ? specs->extension - 1 : specs->map_count;
\r
199 if(value >= cmpWith)
\r
202 if(ct->flags & APC_EXTENSIBLE) {
\r
203 if(per_put_few_bits(po, inext, 1))
\r
204 ASN__ENCODE_FAILED;
\r
207 ASN__ENCODE_FAILED;
\r
210 if(ct && ct->range_bits >= 0) {
\r
211 if(per_put_few_bits(po, value, ct->range_bits))
\r
212 ASN__ENCODE_FAILED;
\r
213 ASN__ENCODED_OK(er);
\r
216 if(!specs->extension)
\r
217 ASN__ENCODE_FAILED;
\r
220 * X.691, #10.6: normally small non-negative whole number;
\r
222 ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
\r
223 value, specs->extension, inext,
\r
224 value - (inext ? (specs->extension - 1) : 0));
\r
225 if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
\r
226 ASN__ENCODE_FAILED;
\r
228 ASN__ENCODED_OK(er);
\r
232 NativeEnumerated_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
\r
233 const asn_TYPE_descriptor_t *td,
\r
234 const asn_per_constraints_t *constraints,
\r
235 void **sptr, asn_per_data_t *pd) {
\r
236 const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
\r
237 asn_dec_rval_t rval = { RC_OK, 0 };
\r
238 long *native = (long *)*sptr;
\r
239 const asn_per_constraint_t *ct;
\r
242 (void)opt_codec_ctx;
\r
244 if(constraints) ct = &constraints->value;
\r
245 else if(td->encoding_constraints.per_constraints)
\r
246 ct = &td->encoding_constraints.per_constraints->value;
\r
247 else ASN__DECODE_FAILED; /* Mandatory! */
\r
248 if(!specs) ASN__DECODE_FAILED;
\r
251 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
\r
252 if(!native) ASN__DECODE_FAILED;
\r
255 ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
\r
257 if(ct->flags & APC_EXTENSIBLE) {
\r
258 int inext = per_get_few_bits(pd, 1);
\r
259 if(inext < 0) ASN__DECODE_STARVED;
\r
263 /* Deal with APER padding */
\r
264 if(ct && ct->upper_bound >= 255) {
\r
266 padding = (8 - (pd->moved % 8)) % 8;
\r
267 ASN_DEBUG("For NativeEnumerated %s,offset= %lu Padding bits = %d", td->name, pd->moved, padding);
\r
268 ASN_DEBUG("For NativeEnumerated %s, upper bound = %lu", td->name, ct->upper_bound);
\r
270 per_get_few_bits(pd, padding);
\r
273 if(ct && ct->range_bits >= 0) {
\r
274 value = per_get_few_bits(pd, ct->range_bits);
\r
275 if(value < 0) ASN__DECODE_STARVED;
\r
276 if(value >= (specs->extension
\r
277 ? specs->extension - 1 : specs->map_count))
\r
278 ASN__DECODE_FAILED;
\r
280 if(!specs->extension)
\r
281 ASN__DECODE_FAILED;
\r
283 * X.691, #10.6: normally small non-negative whole number;
\r
285 value = uper_get_nsnnwn(pd);
\r
286 if(value < 0) ASN__DECODE_STARVED;
\r
287 value += specs->extension - 1;
\r
288 if(value >= specs->map_count)
\r
289 ASN__DECODE_FAILED;
\r
292 *native = specs->value2enum[value].nat_value;
\r
293 ASN_DEBUG("Decoded %s = %ld", td->name, *native);
\r
299 NativeEnumerated_encode_aper(const asn_TYPE_descriptor_t *td,
\r
300 const asn_per_constraints_t *constraints,
\r
301 const void *sptr, asn_per_outp_t *po) {
\r
302 const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
\r
303 asn_enc_rval_t er = {0,0,0};
\r
304 long native, value;
\r
305 const asn_per_constraint_t *ct;
\r
307 asn_INTEGER_enum_map_t key;
\r
308 asn_INTEGER_enum_map_t *kf;
\r
310 if(!sptr) ASN__ENCODE_FAILED;
\r
311 if(!specs) ASN__ENCODE_FAILED;
\r
313 if(constraints) ct = &constraints->value;
\r
314 else if(td->encoding_constraints.per_constraints)
\r
315 ct = &td->encoding_constraints.per_constraints->value;
\r
316 else ASN__ENCODE_FAILED; /* Mandatory! */
\r
318 ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
\r
322 native = *(const long *)sptr;
\r
323 if(native < 0) ASN__ENCODE_FAILED;
\r
325 key.nat_value = native;
\r
326 kf = bsearch(&key, specs->value2enum, specs->map_count,
\r
327 sizeof(key), NativeEnumerated__compar_value2enum);
\r
329 ASN_DEBUG("No element corresponds to %ld", native);
\r
330 ASN__ENCODE_FAILED;
\r
332 value = kf - specs->value2enum;
\r
334 if(ct->range_bits >= 0) {
\r
335 int cmpWith = specs->extension
\r
336 ? specs->extension - 1 : specs->map_count;
\r
337 if(value >= cmpWith)
\r
340 if(ct->flags & APC_EXTENSIBLE) {
\r
341 if(per_put_few_bits(po, inext, 1))
\r
342 ASN__ENCODE_FAILED;
\r
345 ASN__ENCODE_FAILED;
\r
348 if(ct && ct->range_bits >= 0) {
\r
349 if(per_put_few_bits(po, value, ct->range_bits))
\r
350 ASN__ENCODE_FAILED;
\r
351 ASN__ENCODED_OK(er);
\r
354 if(!specs->extension)
\r
355 ASN__ENCODE_FAILED;
\r
358 * X.691, #10.6: normally small non-negative whole number;
\r
360 ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
\r
361 value, specs->extension, inext,
\r
362 value - (inext ? (specs->extension - 1) : 0));
\r
363 if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
\r
364 ASN__ENCODE_FAILED;
\r
366 ASN__ENCODED_OK(er);
\r