blob: 16ffd6820c38de9e3274a0be7932b8c59716e943 [file] [log] [blame]
Harry Trana1b2b292019-10-28 11:07:23 -04001/*****************************************************************************
2# *
3# Copyright 2019 AT&T Intellectual Property *
4# *
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 *
8# *
9# http://www.apache.org/licenses/LICENSE-2.0 *
10# *
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. *
16# *
17******************************************************************************/
18
19/*-
20 * Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
21 * Redistribution and modifications are permitted subject to BSD license.
22 */
23/*
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.
29 */
30#include <asn_internal.h>
31#include <NativeEnumerated.h>
32
33/*
34 * NativeEnumerated basic type description.
35 */
36static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
37 (ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
38};
39asn_TYPE_operation_t asn_OP_NativeEnumerated = {
40 NativeInteger_free,
41 NativeInteger_print,
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
48 0,
49 0,
50#else
51 NativeEnumerated_decode_oer,
52 NativeEnumerated_encode_oer,
53#endif /* ASN_DISABLE_OER_SUPPORT */
54#ifdef ASN_DISABLE_PER_SUPPORT
55 0,
56 0,
57 0,
58 0,
59#else
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 */
67};
68asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
69 "ENUMERATED", /* The ASN.1 type is still ENUMERATED */
70 "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 */
78 0 /* No specifics */
79};
80
81asn_enc_rval_t
82NativeEnumerated_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;
90
91 (void)ilevel;
92 (void)flags;
93
94 if(!native) ASN__ENCODE_FAILED;
95
96 el = INTEGER_map_value2enum(specs, *native);
97 if(el) {
98 er.encoded =
99 asn__format_to_callback(cb, app_key, "<%s/>", el->enum_name);
100 if(er.encoded < 0) ASN__ENCODE_FAILED;
101 ASN__ENCODED_OK(er);
102 } else {
103 ASN_DEBUG(
104 "ASN.1 forbids dealing with "
105 "unknown value of ENUMERATED type");
106 ASN__ENCODE_FAILED;
107 }
108}
109
110asn_dec_rval_t
111NativeEnumerated_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
119 long value;
120
121 (void)opt_codec_ctx;
122
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;
128
129 if(!native) {
130 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
131 if(!native) ASN__DECODE_FAILED;
132 }
133
134 ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
135
136 if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
137 int inext = per_get_few_bits(pd, 1);
138 if(inext < 0) ASN__DECODE_STARVED;
139 if(inext) ct = 0;
140 }
141
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))
147 ASN__DECODE_FAILED;
148 } else {
149 if(!specs->extension)
150 ASN__DECODE_FAILED;
151 /*
152 * X.691, #10.6: normally small non-negative whole number;
153 */
154 value = uper_get_nsnnwn(pd);
155 if(value < 0) ASN__DECODE_STARVED;
156 value += specs->extension - 1;
157 if(value >= specs->map_count)
158 ASN__DECODE_FAILED;
159 }
160
161 *native = specs->value2enum[value].nat_value;
162 ASN_DEBUG("Decoded %s = %ld", td->name, *native);
163
164 return rval;
165}
166
167static int
168NativeEnumerated__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)
172 return 0;
173 if(a->nat_value < b->nat_value)
174 return -1;
175 return 1;
176}
177
178asn_enc_rval_t
179NativeEnumerated_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};
185 long native, value;
186 const asn_per_constraint_t *ct = NULL; // BMC
187 int inext = 0;
188 asn_INTEGER_enum_map_t key;
189 const asn_INTEGER_enum_map_t *kf;
190
191 if(!sptr) ASN__ENCODE_FAILED;
192 if(!specs) ASN__ENCODE_FAILED;
193
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! */
198
199 ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
200
201 er.encoded = 0;
202
203 native = *(const long *)sptr;
204
205 key.nat_value = native;
206 kf = bsearch(&key, specs->value2enum, specs->map_count,
207 sizeof(key), NativeEnumerated__compar_value2enum);
208 if(!kf) {
209 ASN_DEBUG("No element corresponds to %ld", native);
210 ASN__ENCODE_FAILED;
211 }
212 value = kf - specs->value2enum;
213
214 if(ct && ct->range_bits >= 0) { // BMC
215 int cmpWith = specs->extension
216 ? specs->extension - 1 : specs->map_count;
217 if(value >= cmpWith)
218 inext = 1;
219 }
220 if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
221 if(per_put_few_bits(po, inext, 1))
222 ASN__ENCODE_FAILED;
223 if(inext) ct = 0;
224 } else if(inext) {
225 ASN__ENCODE_FAILED;
226 }
227
228 if(ct && ct->range_bits >= 0) {
229 if(per_put_few_bits(po, value, ct->range_bits))
230 ASN__ENCODE_FAILED;
231 ASN__ENCODED_OK(er);
232 }
233
234 if(!specs->extension)
235 ASN__ENCODE_FAILED;
236
237 /*
238 * X.691, #10.6: normally small non-negative whole number;
239 */
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)))
244 ASN__ENCODE_FAILED;
245
246 ASN__ENCODED_OK(er);
247}
248
249asn_dec_rval_t
250NativeEnumerated_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
258 long value;
259
260 (void)opt_codec_ctx;
261
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;
267
268 if(!native) {
269 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
270 if(!native) ASN__DECODE_FAILED;
271 }
272
273 ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
274
275 if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
276 int inext = per_get_few_bits(pd, 1);
277 if(inext < 0) ASN__DECODE_STARVED;
278 if(inext) ct = 0;
279 }
280
281 /* Deal with APER padding */
282 if(ct && ct->upper_bound >= 255) {
283 int padding = 0;
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);
287 if(padding > 0)
288 per_get_few_bits(pd, padding);
289 }
290
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))
296 ASN__DECODE_FAILED;
297 } else {
298 if(!specs->extension)
299 ASN__DECODE_FAILED;
300 /*
301 * X.691, #10.6: normally small non-negative whole number;
302 */
303 value = uper_get_nsnnwn(pd);
304 if(value < 0) ASN__DECODE_STARVED;
305 value += specs->extension - 1;
306 if(value >= specs->map_count)
307 ASN__DECODE_FAILED;
308 }
309
310 *native = specs->value2enum[value].nat_value;
311 ASN_DEBUG("Decoded %s = %ld", td->name, *native);
312
313 return rval;
314}
315
316asn_enc_rval_t
317NativeEnumerated_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};
322 long native, value;
323 const asn_per_constraint_t *ct = NULL; // BMC
324 int inext = 0;
325 asn_INTEGER_enum_map_t key;
326 asn_INTEGER_enum_map_t *kf;
327
328 if(!sptr) ASN__ENCODE_FAILED;
329 if(!specs) ASN__ENCODE_FAILED;
330
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! */
335
336 ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
337
338 er.encoded = 0;
339
340 native = *(const long *)sptr;
341 if(native < 0) ASN__ENCODE_FAILED;
342
343 key.nat_value = native;
344 kf = bsearch(&key, specs->value2enum, specs->map_count,
345 sizeof(key), NativeEnumerated__compar_value2enum);
346 if(!kf) {
347 ASN_DEBUG("No element corresponds to %ld", native);
348 ASN__ENCODE_FAILED;
349 }
350 value = kf - specs->value2enum;
351
352 if(ct && ct->range_bits >= 0) { // BMC
353 int cmpWith = specs->extension
354 ? specs->extension - 1 : specs->map_count;
355 if(value >= cmpWith)
356 inext = 1;
357 }
358 if(ct && ct->flags & APC_EXTENSIBLE) { // BMC
359 if(per_put_few_bits(po, inext, 1))
360 ASN__ENCODE_FAILED;
361 if(inext) ct = 0;
362 } else if(inext) {
363 ASN__ENCODE_FAILED;
364 }
365
366 if(ct && ct->range_bits >= 0) {
367 if(per_put_few_bits(po, value, ct->range_bits))
368 ASN__ENCODE_FAILED;
369 ASN__ENCODED_OK(er);
370 }
371
372 if(!specs->extension)
373 ASN__ENCODE_FAILED;
374
375 /*
376 * X.691, #10.6: normally small non-negative whole number;
377 */
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)))
382 ASN__ENCODE_FAILED;
383
384 ASN__ENCODED_OK(er);
385}