//#include //#include #include #include #include "spinlock.h" #include #if !defined(_MSC_VER) #include #include #else #define gmtime_r( _clock, _result ) \ ( *(_result) = *gmtime( (_clock) ), \ (_result) ) #define localtime_r( _clock, _result ) \ ( *(_result) = *localtime( (_clock) ), \ (_result) ) #endif #define L_RANDMAX 0x7fff #if defined(__APPLE__) #include #include #endif #include #define NANOSEC 1000000000 #define MICROSEC 1000000 static struct spinlock lock; static struct random { unsigned int seed; } holdrand; static double get_time() { #if !defined(__APPLE__) struct timespec ti; clock_gettime(CLOCK_MONOTONIC, &ti); int sec = ti.tv_sec & 0xffff; int nsec = ti.tv_nsec; return (double)sec + (double)nsec / NANOSEC; #else struct task_thread_times_info aTaskInfo; mach_msg_type_number_t aTaskInfoCount = TASK_THREAD_TIMES_INFO_COUNT; if (KERN_SUCCESS != task_info(mach_task_self(), TASK_THREAD_TIMES_INFO, (task_info_t)&aTaskInfo, &aTaskInfoCount)) { return 0; } int sec = aTaskInfo.user_time.seconds & 0xffff; int msec = aTaskInfo.user_time.microseconds; return (double)sec + (double)msec / MICROSEC; #endif } static int _rand(unsigned int* seed) { return (((*seed = (*seed) * 214013L + 2531011L) >> 16) & L_RANDMAX); /* Linear Congruence */ } static int lnewrandom(lua_State* L) { struct random * c = NULL; lua_Integer seed = 1L; if (lua_gettop(L) == 1) { seed = luaL_checkinteger(L, 1); } c = (struct random *)lua_newuserdata(L, sizeof(struct random)); c->seed = (unsigned int)seed; return 1; } static int lrand(lua_State* L) { lua_Integer low, up; double r; struct random * c = (struct random *)lua_touserdata(L, 1); if (c == NULL) { return luaL_argerror(L, 1, "Need an util object"); } /* between 0 and 1 */ r = (double)_rand(&c->seed) * (1.0 / ((double)L_RANDMAX + 1.0)); switch (lua_gettop(L) - 1) { /* check number of arguments */ case 0: { /* no arguments */ lua_pushnumber(L, (lua_Number)r); /* Number between 0 and 1 */ return 1; } case 1: { /* only upper limit */ low = 1; up = luaL_checkinteger(L, 2); break; } case 2: { /* lower and upper limits */ low = luaL_checkinteger(L, 2); up = luaL_checkinteger(L, 3); break; } default: return luaL_error(L, "wrong number of arguments"); } /* random integer in the interval [low, up] */ luaL_argcheck(L, low <= up, 1, "interval is empty"); luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1, "interval too large"); r *= (double)(up - low) + 1.0; lua_pushinteger(L, (lua_Integer)r + low); return 1; } static int lsrand(lua_State* L) { struct random * c = (struct random *)lua_touserdata(L, 1); if (c == NULL) { return luaL_argerror(L, 1, "Need an util object"); } c->seed = (unsigned int)luaL_checkinteger(L, 2); return 0; } static int lpeekseed(lua_State* L) { struct random * c = (struct random *)lua_touserdata(L, 1); if (c == NULL) { return luaL_argerror(L, 1, "Need an util object"); } lua_pushinteger(L, c->seed); return 1; } static int lrandom(lua_State* L) { lua_Integer low, up; double r = 0; spinlock_lock(&lock); r = (double)_rand(&holdrand.seed) * (1.0 / ((double)L_RANDMAX + 1.0)); spinlock_unlock(&lock); switch (lua_gettop(L)) { /* check number of arguments */ case 0: { /* no arguments */ lua_pushnumber(L, (lua_Number)r); /* Number between 0 and 1 */ lua_pushinteger(L, holdrand.seed); return 2; } case 1: { /* only upper limit */ low = 1; up = luaL_checkinteger(L, 1); break; } case 2: { /* lower and upper limits */ low = luaL_checkinteger(L, 1); up = luaL_checkinteger(L, 2); break; } default: return luaL_error(L, "wrong number of arguments"); } /* random integer in the interval [low, up] */ luaL_argcheck(L, low <= up, 1, "interval is empty"); luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1, "interval too large"); r *= (double)(up - low) + 1.0; lua_pushinteger(L, (lua_Integer)r + low); lua_pushinteger(L, holdrand.seed); return 2; } static int lsrandom(lua_State* L) { holdrand.seed = (unsigned int)luaL_checkinteger(L, 1); return 0; } static int ltimezone(lua_State* L) { // Get the UTC time time_t time_utc; time(&time_utc); // Get the local time // Use localtime_r for threads safe struct tm tm_local; localtime_r(&time_utc, &tm_local); // Change tm to time_t //time_t time_local = mktime(&tm_local); // Get the GMT time // Use gmtime_r for threads safe struct tm tm_gmt; gmtime_r(&time_utc, &tm_gmt); // Change tm to time_t //time_t time_gmt = mktime(&tm_gmt); int time_zone = tm_local.tm_hour - tm_gmt.tm_hour; if (time_zone < -12) { time_zone += 24; } else if (time_zone > 12) { time_zone -= 24; } lua_pushinteger(L, time_zone); return 1; } static int lgettime(lua_State* L) { double ti = get_time(); lua_pushnumber(L, ti); return 1; } static int luuid(lua_State *L) { uuid_t __uuid; char uuid_str[37]; uuid_generate(__uuid); uuid_unparse_lower(__uuid, uuid_str); lua_pushstring(L, uuid_str); return 1; } static int Hash(const char * str, int sz) { uint32_t hash = 0; int i; for (i=0;i