SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / OCTET_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 <OCTET_STRING.h>
8
9 /*
10  * Biased function for randomizing character values around their limits.
11  */
12 static uint32_t
13 OCTET_STRING__random_char(unsigned long lb, unsigned long ub) {
14     assert(lb <= ub);
15     switch(asn_random_between(0, 16)) {
16     case 0:
17         if(lb < ub) return lb + 1;
18         /* Fall through */
19     case 1:
20         return lb;
21     case 2:
22         if(lb < ub) return ub - 1;
23         /* Fall through */
24     case 3:
25         return ub;
26     default:
27         return asn_random_between(lb, ub);
28     }
29 }
30
31 asn_random_fill_result_t
32 OCTET_STRING_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
33                          const asn_encoding_constraints_t *constraints,
34                          size_t max_length) {
35     const asn_OCTET_STRING_specifics_t *specs = td->specifics
36         ? (const asn_OCTET_STRING_specifics_t *)td->specifics
37         : &asn_SPC_OCTET_STRING_specs;
38     asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
39     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
40     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
41     unsigned int unit_bytes = 1;
42     unsigned long clb = 0;  /* Lower bound on char */
43     unsigned long cub = 255;  /* Higher bound on char value */
44     uint8_t *buf;
45     uint8_t *bend;
46     uint8_t *b;
47     size_t rnd_len;
48     OCTET_STRING_t *st;
49
50     if(max_length == 0 && !*sptr) return result_skipped;
51
52     switch(specs->subvariant) {
53     default:
54     case ASN_OSUBV_ANY:
55         return result_failed;
56     case ASN_OSUBV_BIT:
57         /* Handled by BIT_STRING itself. */
58         return result_failed;
59     case ASN_OSUBV_STR:
60         unit_bytes = 1;
61         clb = 0;
62         cub = 255;
63         break;
64     case ASN_OSUBV_U16:
65         unit_bytes = 2;
66         clb = 0;
67         cub = 65535;
68         break;
69     case ASN_OSUBV_U32:
70         unit_bytes = 4;
71         clb = 0;
72         cub = 0x10FFFF;
73         break;
74     }
75
76 #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
77     if(!constraints || !constraints->per_constraints)
78         constraints = &td->encoding_constraints;
79     if(constraints->per_constraints) {
80         const asn_per_constraint_t *pc = &constraints->per_constraints->value;
81         if(pc->flags & APC_SEMI_CONSTRAINED) {
82             clb = pc->lower_bound;
83         } else if(pc->flags & APC_CONSTRAINED) {
84             clb = pc->lower_bound;
85             cub = pc->upper_bound;
86         }
87     }
88 #else
89     if(!constraints) constraints = &td->encoding_constraints;
90 #endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
91
92     rnd_len =
93         OCTET_STRING_random_length_constrained(td, constraints, max_length);
94
95     buf = CALLOC(unit_bytes, rnd_len + 1);
96     if(!buf) return result_failed;
97
98     bend = &buf[unit_bytes * rnd_len];
99
100     switch(unit_bytes) {
101     case 1:
102         for(b = buf; b < bend; b += unit_bytes) {
103             *(uint8_t *)b = OCTET_STRING__random_char(clb, cub);
104         }
105         *(uint8_t *)b = 0;
106         break;
107     case 2:
108         for(b = buf; b < bend; b += unit_bytes) {
109             uint32_t code = OCTET_STRING__random_char(clb, cub);
110             b[0] = code >> 8;
111             b[1] = code;
112         }
113         *(uint16_t *)b = 0;
114         break;
115     case 4:
116         for(b = buf; b < bend; b += unit_bytes) {
117             uint32_t code = OCTET_STRING__random_char(clb, cub);
118             b[0] = code >> 24;
119             b[1] = code >> 16;
120             b[2] = code >> 8;
121             b[3] = code;
122         }
123         *(uint32_t *)b = 0;
124         break;
125     }
126
127     if(*sptr) {
128         st = *sptr;
129         FREEMEM(st->buf);
130     } else {
131         st = (OCTET_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
132         if(!st) {
133             FREEMEM(buf);
134             return result_failed;
135         }
136     }
137
138     st->buf = buf;
139     st->size = unit_bytes * rnd_len;
140
141     result_ok.length = st->size;
142     return result_ok;
143 }
144
145 size_t
146 OCTET_STRING_random_length_constrained(
147     const asn_TYPE_descriptor_t *td,
148     const asn_encoding_constraints_t *constraints, size_t max_length) {
149     const unsigned lengths[] = {0,     1,     2,     3,     4,     8,
150                                 126,   127,   128,   16383, 16384, 16385,
151                                 65534, 65535, 65536, 65537};
152     size_t rnd_len;
153
154     /* Figure out how far we should go */
155     rnd_len = lengths[asn_random_between(
156         0, sizeof(lengths) / sizeof(lengths[0]) - 1)];
157
158 #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
159     if(!constraints || !constraints->per_constraints)
160         constraints = &td->encoding_constraints;
161     if(constraints->per_constraints) {
162         const asn_per_constraint_t *pc = &constraints->per_constraints->size;
163         if(pc->flags & APC_CONSTRAINED) {
164             long suggested_upper_bound = pc->upper_bound < (ssize_t)max_length
165                                              ? pc->upper_bound
166                                              : (ssize_t)max_length;
167             if(max_length <= (size_t)pc->lower_bound) {
168                 return pc->lower_bound;
169             }
170             if(pc->flags & APC_EXTENSIBLE) {
171                 switch(asn_random_between(0, 5)) {
172                 case 0:
173                     if(pc->lower_bound > 0) {
174                         rnd_len = pc->lower_bound - 1;
175                         break;
176                     }
177                     /* Fall through */
178                 case 1:
179                     rnd_len = pc->upper_bound + 1;
180                     break;
181                 case 2:
182                     /* Keep rnd_len from the table */
183                     if(rnd_len <= max_length) {
184                         break;
185                     }
186                     /* Fall through */
187                 default:
188                     rnd_len = asn_random_between(pc->lower_bound,
189                                                  suggested_upper_bound);
190                 }
191             } else {
192                 rnd_len =
193                     asn_random_between(pc->lower_bound, suggested_upper_bound);
194             }
195         } else {
196             rnd_len = asn_random_between(0, max_length);
197         }
198     } else {
199 #else
200     if(!constraints) constraints = &td->encoding_constraints;
201     {
202 #endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
203         if(rnd_len > max_length) {
204             rnd_len = asn_random_between(0, max_length);
205         }
206     }
207
208     return rnd_len;
209 }