blob: 819cf700ecc63254d2063af92e5a071d860899f8 [file] [log] [blame]
Lev Walkina5972be2017-09-29 23:15:58 -07001/*
2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
3 * All rights reserved.
4 * Redistribution and modifications are permitted subject to BSD license.
5 */
Lev Walkina5972be2017-09-29 23:15:58 -07006#include <asn_internal.h>
7#include <asn_random_fill.h>
8#include <constr_TYPE.h>
9
10int
11asn_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
Lev Walkin121ad662017-10-09 01:03:54 -070023static uintmax_t
24asn__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
Lev Walkina5972be2017-09-29 23:15:58 -070036intmax_t
Lev Walkin121ad662017-10-09 01:03:54 -070037asn_random_between(intmax_t lb, intmax_t rb) {
38 if(lb == rb) {
Lev Walkin8f501762017-10-10 00:28:57 -070039 return lb;
Lev Walkin121ad662017-10-09 01:03:54 -070040 } 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 }
Lev Walkina5972be2017-09-29 23:15:58 -070056}