webmcp

view libraries/multirand/multirand.c @ 0:9fdfb27f8e67

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

Impressum / About Us