]> git.stg.codes - stg.git/blob - libs/smux/asn_random_fill.c
More std::jthread stuff.
[stg.git] / libs / smux / asn_random_fill.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 <asn_random_fill.h>
8 #include <constr_TYPE.h>
9
10 int
11 asn_random_fill(const struct asn_TYPE_descriptor_s *td, void **struct_ptr,
12                 size_t length) {
13
14     if(td && td->op->random_fill) {
15         asn_random_fill_result_t res =
16             td->op->random_fill(td, struct_ptr, 0, length);
17         return (res.code == ARFILL_OK) ? 0 : -1;
18     } else {
19         return -1;
20     }
21 }
22
23 static uintmax_t
24 asn__intmax_range(intmax_t lb, intmax_t ub) {
25     assert(lb <= ub);
26     if((ub < 0) == (lb < 0)) {
27         return ub - lb;
28     } else if(lb < 0) {
29         return 1 + ((uintmax_t)ub + (uintmax_t)-(lb + 1));
30     } else {
31         assert(!"Unreachable");
32         return 0;
33     }
34 }
35
36 intmax_t
37 asn_random_between(intmax_t lb, intmax_t rb) {
38     if(lb == rb) {
39         return lb;
40     } else {
41         const uintmax_t intmax_max = ((~(uintmax_t)0) >> 1);
42         uintmax_t range = asn__intmax_range(lb, rb);
43         uintmax_t value = 0;
44         uintmax_t got_entropy = 0;
45
46         assert(RAND_MAX > 0xffffff);    /* Seen 7ffffffd! */
47         assert(range < intmax_max);
48
49         for(; got_entropy < range;) {
50             got_entropy = (got_entropy << 24) | 0xffffff;
51             value = (value << 24) | (random() % 0xffffff);
52         }
53
54         return lb + (intmax_t)(value % (range + 1));
55     }
56 }