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