asn_random_fill.c 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  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. int
  10. asn_random_fill(const struct asn_TYPE_descriptor_s *td, void **struct_ptr,
  11. size_t length) {
  12. if(td && td->op->random_fill) {
  13. asn_random_fill_result_t res =
  14. td->op->random_fill(td, struct_ptr, 0, length);
  15. return (res.code == ARFILL_OK) ? 0 : -1;
  16. } else {
  17. return -1;
  18. }
  19. }
  20. static uintmax_t
  21. asn__intmax_range(intmax_t lb, intmax_t ub) {
  22. assert(lb <= ub);
  23. if((ub < 0) == (lb < 0)) {
  24. return ub - lb;
  25. } else if(lb < 0) {
  26. return 1 + ((uintmax_t)ub + (uintmax_t)-(lb + 1));
  27. } else {
  28. assert(!"Unreachable");
  29. return 0;
  30. }
  31. }
  32. intmax_t
  33. asn_random_between(intmax_t lb, intmax_t rb) {
  34. if(lb == rb) {
  35. return lb;
  36. } else {
  37. const uintmax_t intmax_max = ((~(uintmax_t)0) >> 1);
  38. uintmax_t range = asn__intmax_range(lb, rb);
  39. uintmax_t value = 0;
  40. uintmax_t got_entropy = 0;
  41. assert(RAND_MAX > 0xffffff); /* Seen 7ffffffd! */
  42. assert(range < intmax_max);
  43. for(; got_entropy < range;) {
  44. got_entropy = (got_entropy << 24) | 0xffffff;
  45. value = (value << 24) | (random() % 0xffffff);
  46. }
  47. return lb + (intmax_t)(value % (range + 1));
  48. }
  49. }