EndGame/random.lua

87 lines
2.1 KiB
Lua

local require = require
local ffi = require "ffi"
local ffi_cdef = ffi.cdef
local ffi_new = ffi.new
local ffi_str = ffi.string
local ffi_typeof = ffi.typeof
local C = ffi.C
local type = type
local random = math.random
local randomseed = math.randomseed
local concat = table.concat
local tostring = tostring
local pcall = pcall
ffi_cdef[[
typedef unsigned char u_char;
u_char * ngx_hex_dump(u_char *dst, const u_char *src, size_t len);
int RAND_bytes(u_char *buf, int num);
]]
local ok, new_tab = pcall(require, "table.new")
if not ok then
new_tab = function () return {} end
end
local alnum = {
'A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'
}
local t = ffi_typeof "uint8_t[?]"
local function bytes(len, format)
local s = ffi_new(t, len)
C.RAND_bytes(s, len)
if not s then return nil end
if format == "hex" then
local b = ffi_new(t, len * 2)
C.ngx_hex_dump(b, s, len)
return ffi_str(b, len * 2), true
else
return ffi_str(s, len), true
end
end
local function seed()
local a,b,c,d = bytes(4):byte(1, 4)
return randomseed(a * 0x1000000 + b * 0x10000 + c * 0x100 + d)
end
local function number(min, max, reseed)
if reseed then seed() end
if min and max then return random(min, max)
elseif min then return random(min)
else return random() end
end
local function token(len, chars, sep)
chars = chars or alnum
local count
local token = new_tab(len, 0)
if type(chars) ~= "table" then
chars = tostring(chars)
count = #chars
local n
for i=1,len do
n = number(1, count)
token[i] = chars:sub(n, n)
end
else
count = #chars
for i=1,len do token[i] = chars[number(1, count)] end
end
return concat(token, sep)
end
seed()
return {
bytes = bytes,
number = number,
token = token
}