SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / BIT_STRING_rfill.c
1 /*
2  * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
3  * All rights reserved.
4  * Redistribution and modifications are permitted subject to BSD license.
5  */
6 #include <asn_internal.h>
7 #include <BIT_STRING.h>
8
9 asn_random_fill_result_t
10 BIT_STRING_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
11                        const asn_encoding_constraints_t *constraints,
12                        size_t max_length) {
13     const asn_OCTET_STRING_specifics_t *specs =
14         td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
15                       : &asn_SPC_BIT_STRING_specs;
16     asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
17     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
18     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
19     static unsigned lengths[] = {0,     1,     2,     3,     4,     8,
20                                  126,   127,   128,   16383, 16384, 16385,
21                                  65534, 65535, 65536, 65537};
22     uint8_t *buf;
23     uint8_t *bend;
24     uint8_t *b;
25     size_t rnd_bits, rnd_len;
26     BIT_STRING_t *st;
27
28     if(max_length == 0) return result_skipped;
29
30     switch(specs->subvariant) {
31     case ASN_OSUBV_ANY:
32         return result_failed;
33     case ASN_OSUBV_BIT:
34         break;
35     default:
36         break;
37     }
38
39     /* Figure out how far we should go */
40     rnd_bits = lengths[asn_random_between(
41         0, sizeof(lengths) / sizeof(lengths[0]) - 1)];
42 #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
43     if(!constraints || !constraints->per_constraints)
44         constraints = &td->encoding_constraints;
45     if(constraints->per_constraints) {
46         const asn_per_constraint_t *pc = &constraints->per_constraints->size;
47         if(pc->flags & APC_CONSTRAINED) {
48             long suggested_upper_bound = pc->upper_bound < (ssize_t)max_length
49                                              ? pc->upper_bound
50                                              : (ssize_t)max_length;
51             if(max_length < (size_t)pc->lower_bound) {
52                 return result_skipped;
53             }
54             if(pc->flags & APC_EXTENSIBLE) {
55                 switch(asn_random_between(0, 5)) {
56                 case 0:
57                     if(pc->lower_bound > 0) {
58                         rnd_bits = pc->lower_bound - 1;
59                         break;
60                     }
61                     /* Fall through */
62                 case 1:
63                     rnd_bits = pc->upper_bound + 1;
64                     break;
65                 case 2:
66                     /* Keep rnd_bits from the table */
67                     if(rnd_bits < max_length) {
68                         break;
69                     }
70                     /* Fall through */
71                 default:
72                     rnd_bits = asn_random_between(pc->lower_bound,
73                                                   suggested_upper_bound);
74                 }
75             } else {
76                 rnd_bits =
77                     asn_random_between(pc->lower_bound, suggested_upper_bound);
78             }
79         } else {
80             rnd_bits = asn_random_between(0, max_length - 1);
81         }
82     } else {
83 #else
84     if(!constraints) constraints = &td->encoding_constraints;
85     {
86 #endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
87         if(rnd_bits >= max_length) {
88             rnd_bits = asn_random_between(0, max_length - 1);
89         }
90     }
91
92     rnd_len = (rnd_bits + 7) / 8;
93     buf = CALLOC(1, rnd_len + 1);
94     if(!buf) return result_failed;
95
96     bend = &buf[rnd_len];
97
98     for(b = buf; b < bend; b++) {
99         *(uint8_t *)b = asn_random_between(0, 255);
100     }
101     *b = 0; /* Zero-terminate just in case. */
102
103     if(*sptr) {
104         st = *sptr;
105         FREEMEM(st->buf);
106     } else {
107         st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
108         if(!st) {
109             FREEMEM(buf);
110             return result_failed;
111         }
112     }
113
114     st->buf = buf;
115     st->size = rnd_len;
116     st->bits_unused = (8 - (rnd_bits & 0x7)) & 0x7;
117     if(st->bits_unused) {
118         assert(st->size > 0);
119         st->buf[st->size-1] &= 0xff << st->bits_unused;
120     }
121
122     result_ok.length = st->size;
123     return result_ok;
124 }