webmcp

view libraries/multirand/multirand.c @ 567:5e3ebe9fd0ce

Added tag v2.2.1 for changeset 3b71fdb3a00d
author jbe
date Wed Apr 28 13:07:52 2021 +0200 (2 weeks ago)
parents 9d15451c340a
children
line source
1 #include <lua.h>
2 #include <lauxlib.h>
4 static FILE *multirand_dev;
6 static lua_Integer multirand_range(
7 lua_State *L, lua_Integer from, lua_Integer to
8 ) {
9 lua_Integer range;
10 int bits = 0;
11 lua_Integer bit_mask = 0;
12 if (to < from) return luaL_error(L, "Assertion failed in C.");
13 range = to - from;
14 {
15 lua_Integer tmp;
16 tmp = range;
17 while (tmp) {
18 bits++;
19 bit_mask <<= 1;
20 bit_mask |= 1;
21 tmp >>= 1;
22 }
23 }
24 while (1) {
25 int i;
26 lua_Integer rnd = 0;
27 for (i = 0; i < (bits + 7) / 8; i++) {
28 int b;
29 b = getc(multirand_dev);
30 if (b == EOF) {
31 return luaL_error(L, "I/O error while reading random.");
32 }
33 rnd = (rnd << 8) | (unsigned char)b;
34 }
35 rnd &= bit_mask;
36 if (rnd <= range) return from + rnd;
37 }
38 }
40 static int multirand_integer(lua_State *L) {
41 lua_Integer arg1, arg2;
42 lua_settop(L, 2);
43 arg1 = luaL_checkinteger(L, 1);
44 if (lua_toboolean(L, 2)) {
45 arg2 = luaL_checkinteger(L, 2);
46 if (arg1 > arg2) {
47 return luaL_error(L,
48 "Upper boundary is smaller than lower boundary."
49 );
50 } else if (arg1 == arg2) {
51 lua_pushinteger(L, arg1);
52 } else {
53 lua_pushinteger(L, multirand_range(L, arg1, arg2));
54 }
55 } else {
56 luaL_argcheck(L, arg1 >= 1, 1, "smaller than 1");
57 lua_pushinteger(L, multirand_range(L, 1, arg1));
58 }
59 return 1;
60 }
62 static int multirand_fraction(lua_State *L) {
63 int i, j;
64 lua_settop(L, 0);
65 lua_Number rnd = 0.0;
66 for (i = 0; i < 8; i++) {
67 int b;
68 unsigned char c;
69 b = getc(multirand_dev);
70 if (b == EOF) return luaL_error(L, "I/O error while reading random.");
71 c = (unsigned char) b;
72 for (j = 0; j < 8; j++) {
73 rnd /= 2.0;
74 if (c & 1) rnd += 0.5;
75 c >>= 1;
76 }
77 }
78 lua_pushnumber(L, rnd);
79 return 1;
80 }
82 static int multirand_string(lua_State *L) {
83 lua_Integer length;
84 const char *charset;
85 size_t charset_size;
86 luaL_Buffer buf;
87 lua_settop(L, 2);
88 length = luaL_checkinteger(L, 1);
89 charset = luaL_optlstring(L, 2, "abcdefghijklmnopqrstuvwxyz", &charset_size);
90 if (charset_size > 32767) {
91 return luaL_error(L, "Set of chars is too big.");
92 }
93 luaL_buffinit(L, &buf);
94 for (; length > 0; length--) {
95 luaL_addchar(&buf,
96 charset[multirand_range(L, 0, (lua_Integer)charset_size - 1)]
97 );
98 }
99 luaL_pushresult(&buf);
100 return 1;
101 }
103 static const struct luaL_Reg multirand_module_functions[] = {
104 {"integer", multirand_integer},
105 {"fraction", multirand_fraction},
106 {"string", multirand_string},
107 {NULL, NULL}
108 };
110 int luaopen_multirand(lua_State *L) {
111 multirand_dev = fopen("/dev/urandom", "r");
112 if (!multirand_dev) return luaL_error(L, "Could not open /dev/urandom.");
113 #if LUA_VERSION_NUM >= 502
114 lua_newtable(L);
115 luaL_setfuncs(L, multirand_module_functions, 0);
116 #else
117 luaL_register(L, lua_tostring(L, 1), multirand_module_functions);
118 #endif
119 return 1;
120 }

Impressum / About Us