blob: 800da97caf8110fa158351057ce64e873da45968 [file] [log] [blame]
Juha Hyttinenff8dccd2019-12-10 14:34:07 +02001/*-
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 */
18static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
19 (ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
20};
21asn_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};
50asn_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
63asn_enc_rval_t
64NativeEnumerated_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
92asn_dec_rval_t
93NativeEnumerated_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;
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->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
149static int
150NativeEnumerated__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
160asn_enc_rval_t
161NativeEnumerated_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;
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->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->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
231asn_dec_rval_t
232NativeEnumerated_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;
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->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
298asn_enc_rval_t
299NativeEnumerated_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;
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->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->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}