webmcp

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

Impressum / About Us