SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / constr_SET_OF_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 <constr_SET_OF.h>
8
9 asn_random_fill_result_t
10 SET_OF_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_SET_OF_specifics_t *specs =
14         (const asn_SET_OF_specifics_t *)td->specifics;
15     asn_random_fill_result_t res_ok = {ARFILL_OK, 0};
16     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
17     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
18     const asn_TYPE_member_t *elm = td->elements;
19     void *st = *sptr;
20     long max_elements = 5;
21     long slb = 0;  /* Lower size bound */
22     long sub = 0;  /* Upper size bound */
23     size_t rnd_len;
24
25     if(max_length == 0) return result_skipped;
26
27     if(st == NULL) {
28         st = (*sptr = CALLOC(1, specs->struct_size));
29         if(st == NULL) {
30             return result_failed;
31         }
32     }
33
34     switch(asn_random_between(0, 6)) {
35     case 0: max_elements = 0; break;
36     case 1: max_elements = 1; break;
37     case 2: max_elements = 5; break;
38     case 3: max_elements = max_length; break;
39     case 4: max_elements = max_length / 2; break;
40     case 5: max_elements = max_length / 4; break;
41     default: break;
42     }
43     sub = slb + max_elements;
44
45 #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
46     if(!constraints || !constraints->per_constraints)
47         constraints = &td->encoding_constraints;
48     if(constraints->per_constraints) {
49         const asn_per_constraint_t *pc = &constraints->per_constraints->size;
50         if(pc->flags & APC_SEMI_CONSTRAINED) {
51             slb = pc->lower_bound;
52             sub = pc->lower_bound + max_elements;
53         } else if(pc->flags & APC_CONSTRAINED) {
54             slb = pc->lower_bound;
55             sub = pc->upper_bound;
56             if(sub - slb > max_elements) sub = slb + max_elements;
57         }
58     }
59 #else
60     if(!constraints) constraints = &td->encoding_constraints;
61 #endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
62
63     /* Bias towards edges of allowed space */
64     switch(asn_random_between(-1, 4)) {
65     default:
66     case -1:
67 #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
68         /* Prepare lengths somewhat outside of constrained range. */
69         if(constraints->per_constraints
70            && (constraints->per_constraints->size.flags & APC_EXTENSIBLE)) {
71             switch(asn_random_between(0, 5)) {
72             default:
73             case 0:
74                 rnd_len = 0;
75                 break;
76             case 1:
77                 if(slb > 0) {
78                     rnd_len = slb - 1;
79                 } else {
80                     rnd_len = 0;
81                 }
82                 break;
83             case 2:
84                 rnd_len = asn_random_between(0, slb);
85                 break;
86             case 3:
87                 if(sub < (ssize_t)max_length) {
88                     rnd_len = sub + 1;
89                 } else {
90                     rnd_len = max_length;
91                 }
92                 break;
93             case 4:
94                 if(sub < (ssize_t)max_length) {
95                     rnd_len = asn_random_between(sub + 1, max_length);
96                 } else {
97                     rnd_len = max_length;
98                 }
99                 break;
100             case 5:
101                 rnd_len = max_length;
102                 break;
103             }
104             break;
105         }
106 #endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
107         /* Fall through */
108     case 0:
109         rnd_len = asn_random_between(slb, sub);
110         break;
111     case 1:
112         if(slb < sub) {
113             rnd_len = asn_random_between(slb + 1, sub);
114             break;
115         }
116         /* Fall through */
117     case 2:
118         rnd_len = asn_random_between(slb, slb);
119         break;
120     case 3:
121         if(slb < sub) {
122             rnd_len = asn_random_between(slb, sub - 1);
123             break;
124         }
125         /* Fall through */
126     case 4:
127         rnd_len = asn_random_between(sub, sub);
128         break;
129     }
130
131     for(; rnd_len > 0; rnd_len--) {
132         asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
133         void *ptr = 0;
134         asn_random_fill_result_t tmpres = elm->type->op->random_fill(
135             elm->type, &ptr, &elm->encoding_constraints,
136             (max_length > res_ok.length ? max_length - res_ok.length : 0)
137                 / rnd_len);
138         switch(tmpres.code) {
139         case ARFILL_OK:
140             ASN_SET_ADD(list, ptr);
141             res_ok.length += tmpres.length;
142             break;
143         case ARFILL_SKIPPED:
144             break;
145         case ARFILL_FAILED:
146             assert(ptr == 0);
147             return tmpres;
148         }
149     }
150
151     return res_ok;
152 }