webmcp
view libraries/multirand/multirand.c @ 2:72860d232f32
Version 1.0.2
Fixed bug with explicit garbage collection (requests > 256kB caused an error)
Views prefixed with an underscore can't be called externally
ui.paginate now displays the last page, if the selected page number is too high.
Fixed bug with explicit garbage collection (requests > 256kB caused an error)
Views prefixed with an underscore can't be called externally
ui.paginate now displays the last page, if the selected page number is too high.
author | jbe/bsw |
---|---|
date | Thu Dec 10 12:00:00 2009 +0100 (2009-12-10) |
parents | 9fdfb27f8e67 |
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 }