Moving in e2sim originally from it/test/simulators
[sim/e2-interface.git] / e2sim / ASN1c / asn_random_fill.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) 2017 Lev Walkin <vlm@lionet.info>.
21  * All rights reserved.
22  * Redistribution and modifications are permitted subject to BSD license.
23  */
24 #include <asn_internal.h>
25 #include <asn_random_fill.h>
26 #include <constr_TYPE.h>
27
28 int
29 asn_random_fill(const struct asn_TYPE_descriptor_s *td, void **struct_ptr,
30                 size_t length) {
31
32     if(td && td->op->random_fill) {
33         asn_random_fill_result_t res =
34             td->op->random_fill(td, struct_ptr, 0, length);
35         return (res.code == ARFILL_OK) ? 0 : -1;
36     } else {
37         return -1;
38     }
39 }
40
41 static uintmax_t
42 asn__intmax_range(intmax_t lb, intmax_t ub) {
43     assert(lb <= ub);
44     if((ub < 0) == (lb < 0)) {
45         return ub - lb;
46     } else if(lb < 0) {
47         return 1 + ((uintmax_t)ub + (uintmax_t)-(lb + 1));
48     } else {
49         assert(!"Unreachable");
50         return 0;
51     }
52 }
53
54 intmax_t
55 asn_random_between(intmax_t lb, intmax_t rb) {
56     if(lb == rb) {
57         return lb;
58     } else {
59         const uintmax_t intmax_max = ((~(uintmax_t)0) >> 1);
60         uintmax_t range = asn__intmax_range(lb, rb);
61         uintmax_t value = 0;
62         uintmax_t got_entropy = 0;
63
64         assert(RAND_MAX > 0xffffff);    /* Seen 7ffffffd! */
65         assert(range < intmax_max);
66
67         for(; got_entropy < range;) {
68             got_entropy = (got_entropy << 24) | 0xffffff;
69             value = (value << 24) | (random() % 0xffffff);
70         }
71
72         return lb + (intmax_t)(value % (range + 1));
73     }
74 }