lua-util.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. //#include <stdio.h>
  2. //#include <stdlib.h>
  3. #include <lua.h>
  4. #include <lauxlib.h>
  5. #include "spinlock.h"
  6. #include <time.h>
  7. #if !defined(_MSC_VER)
  8. #include <sys/time.h>
  9. #include <uuid/uuid.h>
  10. #else
  11. #define gmtime_r( _clock, _result ) \
  12. ( *(_result) = *gmtime( (_clock) ), \
  13. (_result) )
  14. #define localtime_r( _clock, _result ) \
  15. ( *(_result) = *localtime( (_clock) ), \
  16. (_result) )
  17. #endif
  18. #define L_RANDMAX 0x7fff
  19. #if defined(__APPLE__)
  20. #include <mach/task.h>
  21. #include <mach/mach.h>
  22. #endif
  23. #include <unistd.h>
  24. #define NANOSEC 1000000000
  25. #define MICROSEC 1000000
  26. static struct spinlock lock;
  27. static struct random {
  28. unsigned int seed;
  29. } holdrand;
  30. static double
  31. get_time() {
  32. #if !defined(__APPLE__)
  33. struct timespec ti;
  34. clock_gettime(CLOCK_MONOTONIC, &ti);
  35. int sec = ti.tv_sec & 0xffff;
  36. int nsec = ti.tv_nsec;
  37. return (double)sec + (double)nsec / NANOSEC;
  38. #else
  39. struct task_thread_times_info aTaskInfo;
  40. mach_msg_type_number_t aTaskInfoCount = TASK_THREAD_TIMES_INFO_COUNT;
  41. if (KERN_SUCCESS != task_info(mach_task_self(), TASK_THREAD_TIMES_INFO, (task_info_t)&aTaskInfo, &aTaskInfoCount)) {
  42. return 0;
  43. }
  44. int sec = aTaskInfo.user_time.seconds & 0xffff;
  45. int msec = aTaskInfo.user_time.microseconds;
  46. return (double)sec + (double)msec / MICROSEC;
  47. #endif
  48. }
  49. static int
  50. _rand(unsigned int* seed) {
  51. return (((*seed = (*seed) * 214013L + 2531011L) >> 16) & L_RANDMAX); /* Linear Congruence */
  52. }
  53. static int
  54. lnewrandom(lua_State* L) {
  55. struct random * c = NULL;
  56. lua_Integer seed = 1L;
  57. if (lua_gettop(L) == 1) {
  58. seed = luaL_checkinteger(L, 1);
  59. }
  60. c = (struct random *)lua_newuserdata(L, sizeof(struct random));
  61. c->seed = (unsigned int)seed;
  62. return 1;
  63. }
  64. static int
  65. lrand(lua_State* L) {
  66. lua_Integer low, up;
  67. double r;
  68. struct random * c = (struct random *)lua_touserdata(L, 1);
  69. if (c == NULL) {
  70. return luaL_argerror(L, 1, "Need an util object");
  71. }
  72. /* between 0 and 1 */
  73. r = (double)_rand(&c->seed) * (1.0 / ((double)L_RANDMAX + 1.0));
  74. switch (lua_gettop(L) - 1) { /* check number of arguments */
  75. case 0: { /* no arguments */
  76. lua_pushnumber(L, (lua_Number)r); /* Number between 0 and 1 */
  77. return 1;
  78. }
  79. case 1: { /* only upper limit */
  80. low = 1;
  81. up = luaL_checkinteger(L, 2);
  82. break;
  83. }
  84. case 2: { /* lower and upper limits */
  85. low = luaL_checkinteger(L, 2);
  86. up = luaL_checkinteger(L, 3);
  87. break;
  88. }
  89. default: return luaL_error(L, "wrong number of arguments");
  90. }
  91. /* random integer in the interval [low, up] */
  92. luaL_argcheck(L, low <= up, 1, "interval is empty");
  93. luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1,
  94. "interval too large");
  95. r *= (double)(up - low) + 1.0;
  96. lua_pushinteger(L, (lua_Integer)r + low);
  97. return 1;
  98. }
  99. static int
  100. lsrand(lua_State* L) {
  101. struct random * c = (struct random *)lua_touserdata(L, 1);
  102. if (c == NULL) {
  103. return luaL_argerror(L, 1, "Need an util object");
  104. }
  105. c->seed = (unsigned int)luaL_checkinteger(L, 2);
  106. return 0;
  107. }
  108. static int
  109. lpeekseed(lua_State* L) {
  110. struct random * c = (struct random *)lua_touserdata(L, 1);
  111. if (c == NULL) {
  112. return luaL_argerror(L, 1, "Need an util object");
  113. }
  114. lua_pushinteger(L, c->seed);
  115. return 1;
  116. }
  117. static int
  118. lrandom(lua_State* L) {
  119. lua_Integer low, up;
  120. double r = 0;
  121. spinlock_lock(&lock);
  122. r = (double)_rand(&holdrand.seed) * (1.0 / ((double)L_RANDMAX + 1.0));
  123. spinlock_unlock(&lock);
  124. switch (lua_gettop(L)) { /* check number of arguments */
  125. case 0: { /* no arguments */
  126. lua_pushnumber(L, (lua_Number)r); /* Number between 0 and 1 */
  127. lua_pushinteger(L, holdrand.seed);
  128. return 2;
  129. }
  130. case 1: { /* only upper limit */
  131. low = 1;
  132. up = luaL_checkinteger(L, 1);
  133. break;
  134. }
  135. case 2: { /* lower and upper limits */
  136. low = luaL_checkinteger(L, 1);
  137. up = luaL_checkinteger(L, 2);
  138. break;
  139. }
  140. default: return luaL_error(L, "wrong number of arguments");
  141. }
  142. /* random integer in the interval [low, up] */
  143. luaL_argcheck(L, low <= up, 1, "interval is empty");
  144. luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1,
  145. "interval too large");
  146. r *= (double)(up - low) + 1.0;
  147. lua_pushinteger(L, (lua_Integer)r + low);
  148. lua_pushinteger(L, holdrand.seed);
  149. return 2;
  150. }
  151. static int
  152. lsrandom(lua_State* L) {
  153. holdrand.seed = (unsigned int)luaL_checkinteger(L, 1);
  154. return 0;
  155. }
  156. static int
  157. ltimezone(lua_State* L) {
  158. // Get the UTC time
  159. time_t time_utc;
  160. time(&time_utc);
  161. // Get the local time
  162. // Use localtime_r for threads safe
  163. struct tm tm_local;
  164. localtime_r(&time_utc, &tm_local);
  165. // Change tm to time_t
  166. //time_t time_local = mktime(&tm_local);
  167. // Get the GMT time
  168. // Use gmtime_r for threads safe
  169. struct tm tm_gmt;
  170. gmtime_r(&time_utc, &tm_gmt);
  171. // Change tm to time_t
  172. //time_t time_gmt = mktime(&tm_gmt);
  173. int time_zone = tm_local.tm_hour - tm_gmt.tm_hour;
  174. if (time_zone < -12) {
  175. time_zone += 24;
  176. }
  177. else if (time_zone > 12) {
  178. time_zone -= 24;
  179. }
  180. lua_pushinteger(L, time_zone);
  181. return 1;
  182. }
  183. static int
  184. lgettime(lua_State* L) {
  185. double ti = get_time();
  186. lua_pushnumber(L, ti);
  187. return 1;
  188. }
  189. static int
  190. luuid(lua_State *L) {
  191. uuid_t __uuid;
  192. char uuid_str[37];
  193. uuid_generate(__uuid);
  194. uuid_unparse_lower(__uuid, uuid_str);
  195. lua_pushstring(L, uuid_str);
  196. return 1;
  197. }
  198. static int
  199. Hash(const char * str, int sz) {
  200. uint32_t hash = 0;
  201. int i;
  202. for (i=0;i<sz;i++) {
  203. hash = hash * 0x83 + (uint8_t)str[i];
  204. }
  205. return (hash & 0x7FFFFFFF);
  206. }
  207. static int
  208. lhashcode(lua_State *L) {
  209. size_t sz = 0;
  210. const char * str = luaL_checklstring(L, 1, &sz);
  211. int code = Hash(str,(int)sz);
  212. lua_pushinteger(L, code);
  213. return 1;
  214. }
  215. static int
  216. lgettimeofday(lua_State *L) {
  217. struct timeval tv;
  218. gettimeofday(&tv, 0);
  219. int64_t id = tv.tv_sec * 1000 + tv.tv_usec / 1000;
  220. lua_pushinteger(L, (lua_Integer)id);
  221. return 1;
  222. }
  223. int
  224. luaopen_util_core(lua_State *L) {
  225. spinlock_init(&lock);
  226. luaL_checkversion (L);
  227. luaL_Reg l[] = {
  228. { "newrandom", lnewrandom },
  229. { "rand", lrand },
  230. { "srand", lsrand },
  231. { "peekseed", lpeekseed },
  232. { "random", lrandom },
  233. { "srandom", lsrandom },
  234. { "timezone", ltimezone },
  235. { "gettime", lgettime },
  236. { "gettimeofday", lgettimeofday },
  237. { "uuid", luuid },
  238. { "hashcode", lhashcode },
  239. { NULL, NULL },
  240. };
  241. luaL_newlib (L,l);
  242. return 1;
  243. }