You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

762 lines
18 KiB

  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "config.h"
  17. #include "lua_api/l_noise.h"
  18. #include "lua_api/l_internal.h"
  19. #include "common/c_converter.h"
  20. #include "common/c_content.h"
  21. #include "log.h"
  22. #include "porting.h"
  23. #include "util/numeric.h"
  24. ///////////////////////////////////////
  25. /*
  26. LuaPerlinNoise
  27. */
  28. LuaPerlinNoise::LuaPerlinNoise(NoiseParams *params) :
  29. np(*params)
  30. {
  31. }
  32. LuaPerlinNoise::~LuaPerlinNoise()
  33. {
  34. }
  35. int LuaPerlinNoise::l_get_2d(lua_State *L)
  36. {
  37. NO_MAP_LOCK_REQUIRED;
  38. LuaPerlinNoise *o = checkobject(L, 1);
  39. v2f p = check_v2f(L, 2);
  40. lua_Number val = NoisePerlin2D(&o->np, p.X, p.Y, 0);
  41. lua_pushnumber(L, val);
  42. return 1;
  43. }
  44. int LuaPerlinNoise::l_get_3d(lua_State *L)
  45. {
  46. NO_MAP_LOCK_REQUIRED;
  47. LuaPerlinNoise *o = checkobject(L, 1);
  48. v3f p = check_v3f(L, 2);
  49. lua_Number val = NoisePerlin3D(&o->np, p.X, p.Y, p.Z, 0);
  50. lua_pushnumber(L, val);
  51. return 1;
  52. }
  53. int LuaPerlinNoise::create_object(lua_State *L)
  54. {
  55. NO_MAP_LOCK_REQUIRED;
  56. NoiseParams params;
  57. if (lua_istable(L, 1)) {
  58. read_noiseparams(L, 1, &params);
  59. } else {
  60. params.seed = luaL_checkint(L, 1);
  61. params.octaves = luaL_checkint(L, 2);
  62. params.persist = readParam<float>(L, 3);
  63. params.spread = v3f(1, 1, 1) * readParam<float>(L, 4);
  64. }
  65. LuaPerlinNoise *o = new LuaPerlinNoise(&params);
  66. *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
  67. luaL_getmetatable(L, className);
  68. lua_setmetatable(L, -2);
  69. return 1;
  70. }
  71. int LuaPerlinNoise::gc_object(lua_State *L)
  72. {
  73. LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1));
  74. delete o;
  75. return 0;
  76. }
  77. LuaPerlinNoise *LuaPerlinNoise::checkobject(lua_State *L, int narg)
  78. {
  79. NO_MAP_LOCK_REQUIRED;
  80. luaL_checktype(L, narg, LUA_TUSERDATA);
  81. void *ud = luaL_checkudata(L, narg, className);
  82. if (!ud)
  83. luaL_typerror(L, narg, className);
  84. return *(LuaPerlinNoise **)ud;
  85. }
  86. void LuaPerlinNoise::Register(lua_State *L)
  87. {
  88. lua_newtable(L);
  89. int methodtable = lua_gettop(L);
  90. luaL_newmetatable(L, className);
  91. int metatable = lua_gettop(L);
  92. lua_pushliteral(L, "__metatable");
  93. lua_pushvalue(L, methodtable);
  94. lua_settable(L, metatable);
  95. lua_pushliteral(L, "__index");
  96. lua_pushvalue(L, methodtable);
  97. lua_settable(L, metatable);
  98. lua_pushliteral(L, "__gc");
  99. lua_pushcfunction(L, gc_object);
  100. lua_settable(L, metatable);
  101. lua_pop(L, 1);
  102. luaL_openlib(L, 0, methods, 0);
  103. lua_pop(L, 1);
  104. lua_register(L, className, create_object);
  105. }
  106. const char LuaPerlinNoise::className[] = "PerlinNoise";
  107. const luaL_Reg LuaPerlinNoise::methods[] = {
  108. luamethod_aliased(LuaPerlinNoise, get_2d, get2d),
  109. luamethod_aliased(LuaPerlinNoise, get_3d, get3d),
  110. {0,0}
  111. };
  112. ///////////////////////////////////////
  113. /*
  114. LuaPerlinNoiseMap
  115. */
  116. LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *params, s32 seed, v3s16 size)
  117. {
  118. m_is3d = size.Z > 1;
  119. np = *params;
  120. try {
  121. noise = new Noise(&np, seed, size.X, size.Y, size.Z);
  122. } catch (InvalidNoiseParamsException &e) {
  123. throw LuaError(e.what());
  124. }
  125. }
  126. LuaPerlinNoiseMap::~LuaPerlinNoiseMap()
  127. {
  128. delete noise;
  129. }
  130. int LuaPerlinNoiseMap::l_get_2d_map(lua_State *L)
  131. {
  132. NO_MAP_LOCK_REQUIRED;
  133. size_t i = 0;
  134. LuaPerlinNoiseMap *o = checkobject(L, 1);
  135. v2f p = check_v2f(L, 2);
  136. Noise *n = o->noise;
  137. n->perlinMap2D(p.X, p.Y);
  138. lua_newtable(L);
  139. for (u32 y = 0; y != n->sy; y++) {
  140. lua_newtable(L);
  141. for (u32 x = 0; x != n->sx; x++) {
  142. lua_pushnumber(L, n->result[i++]);
  143. lua_rawseti(L, -2, x + 1);
  144. }
  145. lua_rawseti(L, -2, y + 1);
  146. }
  147. return 1;
  148. }
  149. int LuaPerlinNoiseMap::l_get_2d_map_flat(lua_State *L)
  150. {
  151. NO_MAP_LOCK_REQUIRED;
  152. LuaPerlinNoiseMap *o = checkobject(L, 1);
  153. v2f p = check_v2f(L, 2);
  154. bool use_buffer = lua_istable(L, 3);
  155. Noise *n = o->noise;
  156. n->perlinMap2D(p.X, p.Y);
  157. size_t maplen = n->sx * n->sy;
  158. if (use_buffer)
  159. lua_pushvalue(L, 3);
  160. else
  161. lua_newtable(L);
  162. for (size_t i = 0; i != maplen; i++) {
  163. lua_pushnumber(L, n->result[i]);
  164. lua_rawseti(L, -2, i + 1);
  165. }
  166. return 1;
  167. }
  168. int LuaPerlinNoiseMap::l_get_3d_map(lua_State *L)
  169. {
  170. NO_MAP_LOCK_REQUIRED;
  171. size_t i = 0;
  172. LuaPerlinNoiseMap *o = checkobject(L, 1);
  173. v3f p = check_v3f(L, 2);
  174. if (!o->m_is3d)
  175. return 0;
  176. Noise *n = o->noise;
  177. n->perlinMap3D(p.X, p.Y, p.Z);
  178. lua_newtable(L);
  179. for (u32 z = 0; z != n->sz; z++) {
  180. lua_newtable(L);
  181. for (u32 y = 0; y != n->sy; y++) {
  182. lua_newtable(L);
  183. for (u32 x = 0; x != n->sx; x++) {
  184. lua_pushnumber(L, n->result[i++]);
  185. lua_rawseti(L, -2, x + 1);
  186. }
  187. lua_rawseti(L, -2, y + 1);
  188. }
  189. lua_rawseti(L, -2, z + 1);
  190. }
  191. return 1;
  192. }
  193. int LuaPerlinNoiseMap::l_get_3d_map_flat(lua_State *L)
  194. {
  195. NO_MAP_LOCK_REQUIRED;
  196. LuaPerlinNoiseMap *o = checkobject(L, 1);
  197. v3f p = check_v3f(L, 2);
  198. bool use_buffer = lua_istable(L, 3);
  199. if (!o->m_is3d)
  200. return 0;
  201. Noise *n = o->noise;
  202. n->perlinMap3D(p.X, p.Y, p.Z);
  203. size_t maplen = n->sx * n->sy * n->sz;
  204. if (use_buffer)
  205. lua_pushvalue(L, 3);
  206. else
  207. lua_newtable(L);
  208. for (size_t i = 0; i != maplen; i++) {
  209. lua_pushnumber(L, n->result[i]);
  210. lua_rawseti(L, -2, i + 1);
  211. }
  212. return 1;
  213. }
  214. int LuaPerlinNoiseMap::l_calc_2d_map(lua_State *L)
  215. {
  216. NO_MAP_LOCK_REQUIRED;
  217. LuaPerlinNoiseMap *o = checkobject(L, 1);
  218. v2f p = check_v2f(L, 2);
  219. Noise *n = o->noise;
  220. n->perlinMap2D(p.X, p.Y);
  221. return 0;
  222. }
  223. int LuaPerlinNoiseMap::l_calc_3d_map(lua_State *L)
  224. {
  225. NO_MAP_LOCK_REQUIRED;
  226. LuaPerlinNoiseMap *o = checkobject(L, 1);
  227. v3f p = check_v3f(L, 2);
  228. if (!o->m_is3d)
  229. return 0;
  230. Noise *n = o->noise;
  231. n->perlinMap3D(p.X, p.Y, p.Z);
  232. return 0;
  233. }
  234. int LuaPerlinNoiseMap::l_get_map_slice(lua_State *L)
  235. {
  236. NO_MAP_LOCK_REQUIRED;
  237. LuaPerlinNoiseMap *o = checkobject(L, 1);
  238. v3s16 slice_offset = read_v3s16(L, 2);
  239. v3s16 slice_size = read_v3s16(L, 3);
  240. bool use_buffer = lua_istable(L, 4);
  241. Noise *n = o->noise;
  242. if (use_buffer)
  243. lua_pushvalue(L, 4);
  244. else
  245. lua_newtable(L);
  246. write_array_slice_float(L, lua_gettop(L), n->result,
  247. v3u16(n->sx, n->sy, n->sz),
  248. v3u16(slice_offset.X, slice_offset.Y, slice_offset.Z),
  249. v3u16(slice_size.X, slice_size.Y, slice_size.Z));
  250. return 1;
  251. }
  252. int LuaPerlinNoiseMap::create_object(lua_State *L)
  253. {
  254. NoiseParams np;
  255. if (!read_noiseparams(L, 1, &np))
  256. return 0;
  257. v3s16 size = read_v3s16(L, 2);
  258. LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(&np, 0, size);
  259. *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
  260. luaL_getmetatable(L, className);
  261. lua_setmetatable(L, -2);
  262. return 1;
  263. }
  264. int LuaPerlinNoiseMap::gc_object(lua_State *L)
  265. {
  266. LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1));
  267. delete o;
  268. return 0;
  269. }
  270. LuaPerlinNoiseMap *LuaPerlinNoiseMap::checkobject(lua_State *L, int narg)
  271. {
  272. luaL_checktype(L, narg, LUA_TUSERDATA);
  273. void *ud = luaL_checkudata(L, narg, className);
  274. if (!ud)
  275. luaL_typerror(L, narg, className);
  276. return *(LuaPerlinNoiseMap **)ud;
  277. }
  278. void LuaPerlinNoiseMap::Register(lua_State *L)
  279. {
  280. lua_newtable(L);
  281. int methodtable = lua_gettop(L);
  282. luaL_newmetatable(L, className);
  283. int metatable = lua_gettop(L);
  284. lua_pushliteral(L, "__metatable");
  285. lua_pushvalue(L, methodtable);
  286. lua_settable(L, metatable);
  287. lua_pushliteral(L, "__index");
  288. lua_pushvalue(L, methodtable);
  289. lua_settable(L, metatable);
  290. lua_pushliteral(L, "__gc");
  291. lua_pushcfunction(L, gc_object);
  292. lua_settable(L, metatable);
  293. lua_pop(L, 1);
  294. luaL_openlib(L, 0, methods, 0);
  295. lua_pop(L, 1);
  296. lua_register(L, className, create_object);
  297. }
  298. const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap";
  299. const luaL_Reg LuaPerlinNoiseMap::methods[] = {
  300. luamethod_aliased(LuaPerlinNoiseMap, get_2d_map, get2dMap),
  301. luamethod_aliased(LuaPerlinNoiseMap, get_2d_map_flat, get2dMap_flat),
  302. luamethod_aliased(LuaPerlinNoiseMap, calc_2d_map, calc2dMap),
  303. luamethod_aliased(LuaPerlinNoiseMap, get_3d_map, get3dMap),
  304. luamethod_aliased(LuaPerlinNoiseMap, get_3d_map_flat, get3dMap_flat),
  305. luamethod_aliased(LuaPerlinNoiseMap, calc_3d_map, calc3dMap),
  306. luamethod_aliased(LuaPerlinNoiseMap, get_map_slice, getMapSlice),
  307. {0,0}
  308. };
  309. extern "C" {
  310. EXPORT size_t PerlinNoiseMap_get_area(void **pnmp)
  311. {
  312. NO_MAP_LOCK_REQUIRED;
  313. if (pnmp == nullptr)
  314. throw ModError("Nil pointer in C call");
  315. LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)pnmp;
  316. Noise *n = o->getNoise();
  317. return n->sx * n->sy;
  318. }
  319. EXPORT size_t PerlinNoiseMap_get_volume(void **pnmp)
  320. {
  321. NO_MAP_LOCK_REQUIRED;
  322. if (pnmp == nullptr)
  323. throw ModError("Nil pointer in C call");
  324. LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)pnmp;
  325. Noise *n = o->getNoise();
  326. return n->sx * n->sy * n->sz;
  327. }
  328. EXPORT void PerlinNoiseMap_get_pointer(void **pnmp, void **ptr)
  329. {
  330. NO_MAP_LOCK_REQUIRED;
  331. if (pnmp == nullptr || ptr == nullptr)
  332. throw ModError("Nil pointer in C call");
  333. LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)pnmp;
  334. *ptr = o->getNoise();
  335. }
  336. } // extern "C"
  337. ///////////////////////////////////////
  338. /*
  339. LuaPseudoRandom
  340. */
  341. int LuaPseudoRandom::l_next(lua_State *L)
  342. {
  343. NO_MAP_LOCK_REQUIRED;
  344. LuaPseudoRandom *o = checkobject(L, 1);
  345. int min = 0;
  346. int max = 32767;
  347. lua_settop(L, 3);
  348. if (lua_isnumber(L, 2))
  349. min = luaL_checkinteger(L, 2);
  350. if (lua_isnumber(L, 3))
  351. max = luaL_checkinteger(L, 3);
  352. if (max < min) {
  353. errorstream<<"PseudoRandom.next(): max="<<max<<" min="<<min<<std::endl;
  354. throw LuaError("PseudoRandom.next(): max < min");
  355. }
  356. if(max - min != 32767 && max - min > 32767/5)
  357. throw LuaError("PseudoRandom.next() max-min is not 32767"
  358. " and is > 32768/5. This is disallowed due to"
  359. " the bad random distribution the"
  360. " implementation would otherwise make.");
  361. PseudoRandom &pseudo = o->m_pseudo;
  362. int val = pseudo.next();
  363. val = (val % (max-min+1)) + min;
  364. lua_pushinteger(L, val);
  365. return 1;
  366. }
  367. int LuaPseudoRandom::create_object(lua_State *L)
  368. {
  369. NO_MAP_LOCK_REQUIRED;
  370. u64 seed = luaL_checknumber(L, 1);
  371. LuaPseudoRandom *o = new LuaPseudoRandom(seed);
  372. *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
  373. luaL_getmetatable(L, className);
  374. lua_setmetatable(L, -2);
  375. return 1;
  376. }
  377. int LuaPseudoRandom::gc_object(lua_State *L)
  378. {
  379. LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1));
  380. delete o;
  381. return 0;
  382. }
  383. LuaPseudoRandom *LuaPseudoRandom::checkobject(lua_State *L, int narg)
  384. {
  385. luaL_checktype(L, narg, LUA_TUSERDATA);
  386. void *ud = luaL_checkudata(L, narg, className);
  387. if (!ud)
  388. luaL_typerror(L, narg, className);
  389. return *(LuaPseudoRandom **)ud;
  390. }
  391. void LuaPseudoRandom::Register(lua_State *L)
  392. {
  393. lua_newtable(L);
  394. int methodtable = lua_gettop(L);
  395. luaL_newmetatable(L, className);
  396. int metatable = lua_gettop(L);
  397. lua_pushliteral(L, "__metatable");
  398. lua_pushvalue(L, methodtable);
  399. lua_settable(L, metatable);
  400. lua_pushliteral(L, "__index");
  401. lua_pushvalue(L, methodtable);
  402. lua_settable(L, metatable);
  403. lua_pushliteral(L, "__gc");
  404. lua_pushcfunction(L, gc_object);
  405. lua_settable(L, metatable);
  406. lua_pop(L, 1);
  407. luaL_openlib(L, 0, methods, 0);
  408. lua_pop(L, 1);
  409. lua_register(L, className, create_object);
  410. }
  411. const char LuaPseudoRandom::className[] = "PseudoRandom";
  412. const luaL_Reg LuaPseudoRandom::methods[] = {
  413. luamethod(LuaPseudoRandom, next),
  414. {0,0}
  415. };
  416. ///////////////////////////////////////
  417. /*
  418. LuaPcgRandom
  419. */
  420. int LuaPcgRandom::l_next(lua_State *L)
  421. {
  422. NO_MAP_LOCK_REQUIRED;
  423. LuaPcgRandom *o = checkobject(L, 1);
  424. u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
  425. u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
  426. lua_pushinteger(L, o->m_rnd.range(min, max));
  427. return 1;
  428. }
  429. int LuaPcgRandom::l_rand_normal_dist(lua_State *L)
  430. {
  431. NO_MAP_LOCK_REQUIRED;
  432. LuaPcgRandom *o = checkobject(L, 1);
  433. u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
  434. u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
  435. int num_trials = lua_isnumber(L, 4) ? lua_tointeger(L, 4) : 6;
  436. lua_pushinteger(L, o->m_rnd.randNormalDist(min, max, num_trials));
  437. return 1;
  438. }
  439. int LuaPcgRandom::create_object(lua_State *L)
  440. {
  441. NO_MAP_LOCK_REQUIRED;
  442. u64 seed = luaL_checknumber(L, 1);
  443. LuaPcgRandom *o = lua_isnumber(L, 2) ?
  444. new LuaPcgRandom(seed, lua_tointeger(L, 2)) :
  445. new LuaPcgRandom(seed);
  446. *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
  447. luaL_getmetatable(L, className);
  448. lua_setmetatable(L, -2);
  449. return 1;
  450. }
  451. int LuaPcgRandom::gc_object(lua_State *L)
  452. {
  453. LuaPcgRandom *o = *(LuaPcgRandom **)(lua_touserdata(L, 1));
  454. delete o;
  455. return 0;
  456. }
  457. LuaPcgRandom *LuaPcgRandom::checkobject(lua_State *L, int narg)
  458. {
  459. luaL_checktype(L, narg, LUA_TUSERDATA);
  460. void *ud = luaL_checkudata(L, narg, className);
  461. if (!ud)
  462. luaL_typerror(L, narg, className);
  463. return *(LuaPcgRandom **)ud;
  464. }
  465. void LuaPcgRandom::Register(lua_State *L)
  466. {
  467. lua_newtable(L);
  468. int methodtable = lua_gettop(L);
  469. luaL_newmetatable(L, className);
  470. int metatable = lua_gettop(L);
  471. lua_pushliteral(L, "__metatable");
  472. lua_pushvalue(L, methodtable);
  473. lua_settable(L, metatable);
  474. lua_pushliteral(L, "__index");
  475. lua_pushvalue(L, methodtable);
  476. lua_settable(L, metatable);
  477. lua_pushliteral(L, "__gc");
  478. lua_pushcfunction(L, gc_object);
  479. lua_settable(L, metatable);
  480. lua_pop(L, 1);
  481. luaL_openlib(L, 0, methods, 0);
  482. lua_pop(L, 1);
  483. lua_register(L, className, create_object);
  484. }
  485. const char LuaPcgRandom::className[] = "PcgRandom";
  486. const luaL_Reg LuaPcgRandom::methods[] = {
  487. luamethod(LuaPcgRandom, next),
  488. luamethod(LuaPcgRandom, rand_normal_dist),
  489. {0,0}
  490. };
  491. ///////////////////////////////////////
  492. /*
  493. LuaSecureRandom
  494. */
  495. bool LuaSecureRandom::fillRandBuf()
  496. {
  497. return porting::secure_rand_fill_buf(m_rand_buf, RAND_BUF_SIZE);
  498. }
  499. int LuaSecureRandom::l_next_bytes(lua_State *L)
  500. {
  501. NO_MAP_LOCK_REQUIRED;
  502. LuaSecureRandom *o = checkobject(L, 1);
  503. u32 count = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : 1;
  504. // Limit count
  505. count = MYMIN(RAND_BUF_SIZE, count);
  506. // Find out whether we can pass directly from our array, or have to do some gluing
  507. size_t count_remaining = RAND_BUF_SIZE - o->m_rand_idx;
  508. if (count_remaining >= count) {
  509. lua_pushlstring(L, o->m_rand_buf + o->m_rand_idx, count);
  510. o->m_rand_idx += count;
  511. } else {
  512. char output_buf[RAND_BUF_SIZE];
  513. // Copy over with what we have left from our current buffer
  514. memcpy(output_buf, o->m_rand_buf + o->m_rand_idx, count_remaining);
  515. // Refill buffer and copy over the remainder of what was requested
  516. o->fillRandBuf();
  517. memcpy(output_buf + count_remaining, o->m_rand_buf, count - count_remaining);
  518. // Update index
  519. o->m_rand_idx = count - count_remaining;
  520. lua_pushlstring(L, output_buf, count);
  521. }
  522. return 1;
  523. }
  524. int LuaSecureRandom::create_object(lua_State *L)
  525. {
  526. LuaSecureRandom *o = new LuaSecureRandom();
  527. // Fail and return nil if we can't securely fill the buffer
  528. if (!o->fillRandBuf()) {
  529. delete o;
  530. return 0;
  531. }
  532. *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
  533. luaL_getmetatable(L, className);
  534. lua_setmetatable(L, -2);
  535. return 1;
  536. }
  537. int LuaSecureRandom::gc_object(lua_State *L)
  538. {
  539. LuaSecureRandom *o = *(LuaSecureRandom **)(lua_touserdata(L, 1));
  540. delete o;
  541. return 0;
  542. }
  543. LuaSecureRandom *LuaSecureRandom::checkobject(lua_State *L, int narg)
  544. {
  545. luaL_checktype(L, narg, LUA_TUSERDATA);
  546. void *ud = luaL_checkudata(L, narg, className);
  547. if (!ud)
  548. luaL_typerror(L, narg, className);
  549. return *(LuaSecureRandom **)ud;
  550. }
  551. void LuaSecureRandom::Register(lua_State *L)
  552. {
  553. lua_newtable(L);
  554. int methodtable = lua_gettop(L);
  555. luaL_newmetatable(L, className);
  556. int metatable = lua_gettop(L);
  557. lua_pushliteral(L, "__metatable");
  558. lua_pushvalue(L, methodtable);
  559. lua_settable(L, metatable);
  560. lua_pushliteral(L, "__index");
  561. lua_pushvalue(L, methodtable);
  562. lua_settable(L, metatable);
  563. lua_pushliteral(L, "__gc");
  564. lua_pushcfunction(L, gc_object);
  565. lua_settable(L, metatable);
  566. lua_pop(L, 1);
  567. luaL_openlib(L, 0, methods, 0);
  568. lua_pop(L, 1);
  569. lua_register(L, className, create_object);
  570. }
  571. const char LuaSecureRandom::className[] = "SecureRandom";
  572. const luaL_Reg LuaSecureRandom::methods[] = {
  573. luamethod(LuaSecureRandom, next_bytes),
  574. {0,0}
  575. };