Moving in e2sim originally from it/test/simulators
[sim/e2-interface.git] / e2sim / ASN1c / BOOLEAN.c
1 /*****************************************************************************
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) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
21  * Redistribution and modifications are permitted subject to BSD license.
22  */
23 #include <asn_internal.h>
24 #include <asn_codecs_prim.h>
25 #include <BOOLEAN.h>
26
27 /*
28  * BOOLEAN basic type description.
29  */
30 static const ber_tlv_tag_t asn_DEF_BOOLEAN_tags[] = {
31         (ASN_TAG_CLASS_UNIVERSAL | (1 << 2))
32 };
33 asn_TYPE_operation_t asn_OP_BOOLEAN = {
34         BOOLEAN_free,
35         BOOLEAN_print,
36         BOOLEAN_compare,
37         BOOLEAN_decode_ber,
38         BOOLEAN_encode_der,
39         BOOLEAN_decode_xer,
40         BOOLEAN_encode_xer,
41 #ifdef  ASN_DISABLE_OER_SUPPORT
42         0,
43         0,
44 #else
45         BOOLEAN_decode_oer,
46         BOOLEAN_encode_oer,
47 #endif  /* ASN_DISABLE_OER_SUPPORT */
48 #ifdef  ASN_DISABLE_PER_SUPPORT
49         0,
50         0,
51         0,
52         0,
53 #else
54         BOOLEAN_decode_uper,    /* Unaligned PER decoder */
55         BOOLEAN_encode_uper,    /* Unaligned PER encoder */
56         BOOLEAN_decode_aper,    /* Aligned PER decoder */
57         BOOLEAN_encode_aper,    /* Aligned PER encoder */
58 #endif  /* ASN_DISABLE_PER_SUPPORT */
59         BOOLEAN_random_fill,
60         0       /* Use generic outmost tag fetcher */
61 };
62 asn_TYPE_descriptor_t asn_DEF_BOOLEAN = {
63         "BOOLEAN",
64         "BOOLEAN",
65         &asn_OP_BOOLEAN,
66         asn_DEF_BOOLEAN_tags,
67         sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
68         asn_DEF_BOOLEAN_tags,   /* Same as above */
69         sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
70         { 0, 0, asn_generic_no_constraint },
71         0, 0,   /* No members */
72         0       /* No specifics */
73 };
74
75 /*
76  * Decode BOOLEAN type.
77  */
78 asn_dec_rval_t
79 BOOLEAN_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
80                    const asn_TYPE_descriptor_t *td, void **bool_value,
81                    const void *buf_ptr, size_t size, int tag_mode) {
82     BOOLEAN_t *st = (BOOLEAN_t *)*bool_value;
83         asn_dec_rval_t rval;
84         ber_tlv_len_t length;
85         ber_tlv_len_t lidx;
86
87         if(st == NULL) {
88                 st = (BOOLEAN_t *)(*bool_value = CALLOC(1, sizeof(*st)));
89                 if(st == NULL) {
90                         rval.code = RC_FAIL;
91                         rval.consumed = 0;
92                         return rval;
93                 }
94         }
95
96         ASN_DEBUG("Decoding %s as BOOLEAN (tm=%d)",
97                 td->name, tag_mode);
98
99         /*
100          * Check tags.
101          */
102         rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
103                 tag_mode, 0, &length, 0);
104         if(rval.code != RC_OK)
105                 return rval;
106
107         ASN_DEBUG("Boolean length is %d bytes", (int)length);
108
109         buf_ptr = ((const char *)buf_ptr) + rval.consumed;
110         size -= rval.consumed;
111         if(length > (ber_tlv_len_t)size) {
112                 rval.code = RC_WMORE;
113                 rval.consumed = 0;
114                 return rval;
115         }
116
117         /*
118          * Compute boolean value.
119          */
120         for(*st = 0, lidx = 0;
121                 (lidx < length) && *st == 0; lidx++) {
122                 /*
123                  * Very simple approach: read bytes until the end or
124                  * value is already TRUE.
125                  * BOOLEAN is not supposed to contain meaningful data anyway.
126                  */
127                 *st |= ((const uint8_t *)buf_ptr)[lidx];
128         }
129
130         rval.code = RC_OK;
131         rval.consumed += length;
132
133         ASN_DEBUG("Took %ld/%ld bytes to encode %s, value=%d",
134                 (long)rval.consumed, (long)length,
135                 td->name, *st);
136         
137         return rval;
138 }
139
140 asn_enc_rval_t
141 BOOLEAN_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
142                    int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb,
143                    void *app_key) {
144         asn_enc_rval_t erval = {0,0,0};
145         const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
146
147         erval.encoded = der_write_tags(td, 1, tag_mode, 0, tag, cb, app_key);
148         if(erval.encoded == -1) {
149                 erval.failed_type = td;
150                 erval.structure_ptr = sptr;
151                 return erval;
152         }
153
154         if(cb) {
155                 uint8_t bool_value;
156
157                 bool_value = *st ? 0xff : 0; /* 0xff mandated by DER */
158
159                 if(cb(&bool_value, 1, app_key) < 0) {
160                         erval.encoded = -1;
161                         erval.failed_type = td;
162                         erval.structure_ptr = sptr;
163                         return erval;
164                 }
165         }
166
167         erval.encoded += 1;
168
169         ASN__ENCODED_OK(erval);
170 }
171
172
173 /*
174  * Decode the chunk of XML text encoding INTEGER.
175  */
176 static enum xer_pbd_rval
177 BOOLEAN__xer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
178                          const void *chunk_buf, size_t chunk_size) {
179     BOOLEAN_t *st = (BOOLEAN_t *)sptr;
180         const char *p = (const char *)chunk_buf;
181
182         (void)td;
183
184         if(chunk_size && p[0] == 0x3c /* '<' */) {
185                 switch(xer_check_tag(chunk_buf, chunk_size, "false")) {
186                 case XCT_BOTH:
187                         /* "<false/>" */
188                         *st = 0;
189                         break;
190                 case XCT_UNKNOWN_BO:
191                         if(xer_check_tag(chunk_buf, chunk_size, "true")
192                                         != XCT_BOTH)
193                                 return XPBD_BROKEN_ENCODING;
194                         /* "<true/>" */
195                         *st = 1;        /* Or 0xff as in DER?.. */
196                         break;
197                 default:
198                         return XPBD_BROKEN_ENCODING;
199                 }
200                 return XPBD_BODY_CONSUMED;
201         } else {
202                 return XPBD_BROKEN_ENCODING;
203         }
204 }
205
206
207 asn_dec_rval_t
208 BOOLEAN_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
209                    const asn_TYPE_descriptor_t *td, void **sptr,
210                    const char *opt_mname, const void *buf_ptr, size_t size) {
211     return xer_decode_primitive(opt_codec_ctx, td,
212                 sptr, sizeof(BOOLEAN_t), opt_mname, buf_ptr, size,
213                 BOOLEAN__xer_body_decode);
214 }
215
216 asn_enc_rval_t
217 BOOLEAN_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
218         int ilevel, enum xer_encoder_flags_e flags,
219                 asn_app_consume_bytes_f *cb, void *app_key) {
220         const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
221         asn_enc_rval_t er = {0, 0, 0};
222
223         (void)ilevel;
224         (void)flags;
225
226         if(!st) ASN__ENCODE_FAILED;
227
228         if(*st) {
229                 ASN__CALLBACK("<true/>", 7);
230         } else {
231                 ASN__CALLBACK("<false/>", 8);
232         }
233
234         ASN__ENCODED_OK(er);
235 cb_failed:
236         ASN__ENCODE_FAILED;
237 }
238
239 int
240 BOOLEAN_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
241               asn_app_consume_bytes_f *cb, void *app_key) {
242     const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
243         const char *buf;
244         size_t buflen;
245
246         (void)td;       /* Unused argument */
247         (void)ilevel;   /* Unused argument */
248
249         if(st) {
250                 if(*st) {
251                         buf = "TRUE";
252                         buflen = 4;
253                 } else {
254                         buf = "FALSE";
255                         buflen = 5;
256                 }
257         } else {
258                 buf = "<absent>";
259                 buflen = 8;
260         }
261
262         return (cb(buf, buflen, app_key) < 0) ? -1 : 0;
263 }
264
265 void
266 BOOLEAN_free(const asn_TYPE_descriptor_t *td, void *ptr,
267              enum asn_struct_free_method method) {
268     if(td && ptr) {
269         switch(method) {
270         case ASFM_FREE_EVERYTHING:
271             FREEMEM(ptr);
272             break;
273         case ASFM_FREE_UNDERLYING:
274             break;
275         case ASFM_FREE_UNDERLYING_AND_RESET:
276             memset(ptr, 0, sizeof(BOOLEAN_t));
277             break;
278         }
279     }
280 }
281
282 #ifndef ASN_DISABLE_PER_SUPPORT
283
284 asn_dec_rval_t
285 BOOLEAN_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
286                     const asn_TYPE_descriptor_t *td,
287                     const asn_per_constraints_t *constraints, void **sptr,
288                     asn_per_data_t *pd) {
289     asn_dec_rval_t rv;
290         BOOLEAN_t *st = (BOOLEAN_t *)*sptr;
291
292         (void)opt_codec_ctx;
293     (void)td;
294         (void)constraints;
295
296         if(!st) {
297                 st = (BOOLEAN_t *)(*sptr = MALLOC(sizeof(*st)));
298                 if(!st) ASN__DECODE_FAILED;
299         }
300
301         /*
302          * Extract a single bit
303          */
304         switch(per_get_few_bits(pd, 1)) {
305         case 1: *st = 1; break;
306         case 0: *st = 0; break;
307         case -1: default: ASN__DECODE_STARVED;
308         }
309
310         ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE");
311
312         rv.code = RC_OK;
313         rv.consumed = 1;
314         return rv;
315 }
316
317
318 asn_enc_rval_t
319 BOOLEAN_encode_uper(const asn_TYPE_descriptor_t *td,
320                     const asn_per_constraints_t *constraints, const void *sptr,
321                     asn_per_outp_t *po) {
322     const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
323         asn_enc_rval_t er = { 0, 0, 0 };
324
325         (void)constraints;
326
327         if(!st) ASN__ENCODE_FAILED;
328
329         if(per_put_few_bits(po, *st ? 1 : 0, 1))
330                 ASN__ENCODE_FAILED;
331
332         ASN__ENCODED_OK(er);
333 }
334
335 asn_dec_rval_t
336 BOOLEAN_decode_aper(const asn_codec_ctx_t *opt_codec_ctx, const asn_TYPE_descriptor_t *td,
337                     const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
338         asn_dec_rval_t rv;
339         BOOLEAN_t *st = (BOOLEAN_t *)*sptr;
340
341         (void)opt_codec_ctx;
342         (void)constraints;
343         (void)td;
344
345         if(!st) {
346                 st = (BOOLEAN_t *)(*sptr = MALLOC(sizeof(*st)));
347                 if(!st) ASN__DECODE_FAILED;
348         }
349
350         /*
351          * Extract a single bit
352          */
353         switch(per_get_few_bits(pd, 1)) {
354         case 1:
355                 *st = 1;
356                 break;
357         case 0:
358                 *st = 0;
359                 break;
360         case -1:
361         default:
362                 ASN__DECODE_STARVED;
363         }
364
365         ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE");
366
367         rv.code = RC_OK;
368         rv.consumed = 1;
369         return rv;
370 }
371
372 asn_enc_rval_t
373 BOOLEAN_encode_aper(const asn_TYPE_descriptor_t *td,
374                     const asn_per_constraints_t *constraints,
375                     const void *sptr, asn_per_outp_t *po) {
376         const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
377         asn_enc_rval_t er = { 0, 0, 0 };
378
379         (void)constraints;
380
381         if(!st) ASN__ENCODE_FAILED;
382
383         if(per_put_few_bits(po, *st ? 1 : 0, 1))
384                 ASN__ENCODE_FAILED;
385
386         ASN__ENCODED_OK(er);
387 }
388
389 #endif /* ASN_DISABLE_PER_SUPPORT */
390
391 #ifndef  ASN_DISABLE_OER_SUPPORT
392
393 /*
394  * Encode as Canonical OER.
395  */
396 asn_enc_rval_t
397 BOOLEAN_encode_oer(const asn_TYPE_descriptor_t *td,
398                    const asn_oer_constraints_t *constraints, const void *sptr,
399                    asn_app_consume_bytes_f *cb, void *app_key) {
400     asn_enc_rval_t er = { 1, 0, 0 };
401     const BOOLEAN_t *st = sptr;
402     uint8_t bool_value = *st ? 0xff : 0; /* 0xff mandated by OER */
403
404     (void)td;
405     (void)constraints;  /* Constraints are unused in OER */
406
407     if(cb(&bool_value, 1, app_key) < 0) {
408         ASN__ENCODE_FAILED;
409     } else {
410         ASN__ENCODED_OK(er);
411     }
412 }
413
414 asn_dec_rval_t
415 BOOLEAN_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
416                    const asn_TYPE_descriptor_t *td,
417                    const asn_oer_constraints_t *constraints, void **sptr,
418                    const void *ptr, size_t size) {
419     asn_dec_rval_t ok = {RC_OK, 1};
420     BOOLEAN_t *st;
421
422     (void)opt_codec_ctx;
423     (void)td;
424     (void)constraints; /* Constraints are unused in OER */
425
426     if(size < 1) {
427         ASN__DECODE_STARVED;
428     }
429
430     if(!(st = *sptr)) {
431         st = (BOOLEAN_t *)(*sptr = CALLOC(1, sizeof(*st)));
432         if(!st) ASN__DECODE_FAILED;
433     }
434
435     *st = *(const uint8_t *)ptr;
436
437     return ok;
438 }
439
440
441
442 #endif
443
444 int
445 BOOLEAN_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
446                 const void *bptr) {
447     const BOOLEAN_t *a = aptr;
448     const BOOLEAN_t *b = bptr;
449
450     (void)td;
451
452     if(a && b) {
453         if(!*a == !*b) {    /* TRUE can be encoded by any non-zero byte. */
454             return 0;
455         } else if(!*a) {
456             return -1;
457         } else {
458             return 1;
459         }
460     } else if(!a) {
461         return -1;
462     } else {
463         return 1;
464     }
465 }
466
467 asn_random_fill_result_t
468 BOOLEAN_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
469                     const asn_encoding_constraints_t *constraints,
470                     size_t max_length) {
471     asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
472     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
473     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
474     BOOLEAN_t *st = *sptr;
475
476     if(max_length == 0) return result_skipped;
477
478     if(st == NULL) {
479         st = (BOOLEAN_t *)(*sptr = CALLOC(1, sizeof(*st)));
480         if(st == NULL) {
481             return result_failed;
482         }
483     }
484
485     if(!constraints || !constraints->per_constraints)
486         constraints = &td->encoding_constraints;
487     if(constraints->per_constraints) {
488         const asn_per_constraint_t *pc = &constraints->per_constraints->value;
489         if(pc->flags & APC_CONSTRAINED) {
490             *st = asn_random_between(pc->lower_bound, pc->upper_bound);
491             return result_ok;
492         }
493     }
494
495     /* Simulate booleans that are sloppily set and biased. */
496     switch(asn_random_between(0, 7)) {
497     case 0:
498     case 1:
499     case 2:
500         *st = 0; break;
501     case 3: *st = -1; break;
502     case 4: *st = 1; break;
503     case 5: *st = INT_MIN; break;
504     case 6: *st = INT_MAX; break;
505     default:
506         *st = asn_random_between(INT_MIN, INT_MAX);
507         break;
508     }
509     return result_ok;
510 }