Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. /*
  2. *Tencent is pleased to support the open source community by making xLua available.
  3. *Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
  4. *Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
  5. *http://opensource.org/licenses/MIT
  6. *Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
  7. */
  8. #define LUA_LIB
  9. #include "i64lib.h"
  10. #include <string.h>
  11. #include <math.h>
  12. #include <stdlib.h>
  13. #if ( defined (_WIN32) || defined (_WIN64) ) && !defined (__MINGW32__) && !defined (__MINGW64__)
  14. #if !defined(PRId64)
  15. # if __WORDSIZE == 64
  16. # define PRId64 "ld"
  17. # else
  18. # define PRId64 "lld"
  19. # endif
  20. #endif
  21. #if !defined(PRIu64)
  22. # if __WORDSIZE == 64
  23. # define PRIu64 "lu"
  24. # else
  25. # define PRIu64 "llu"
  26. # endif
  27. #endif
  28. #else
  29. #include <inttypes.h>
  30. #endif
  31. #if LUA_VERSION_NUM == 501
  32. #define INT64_META_REF 8
  33. enum IntegerType {
  34. Int,
  35. UInt,
  36. Num
  37. };
  38. typedef struct {
  39. int fake_id;
  40. int8_t type;
  41. union {
  42. int64_t i64;
  43. uint64_t u64;
  44. } data;
  45. } Integer64;
  46. LUALIB_API void lua_pushint64(lua_State* L, int64_t n) {
  47. Integer64* p = (Integer64*)lua_newuserdata(L, sizeof(Integer64));
  48. p->fake_id = -1;
  49. p->data.i64 = n;
  50. p->type = Int;
  51. lua_rawgeti(L, LUA_REGISTRYINDEX, INT64_META_REF);
  52. lua_setmetatable(L, -2);
  53. }
  54. LUALIB_API int lua_isint64(lua_State* L, int pos) {
  55. int equal;
  56. Integer64* p = (Integer64*)lua_touserdata(L, pos);
  57. if (p != NULL) {
  58. if (lua_getmetatable(L, pos)) {
  59. lua_rawgeti(L, LUA_REGISTRYINDEX, INT64_META_REF);
  60. equal = lua_rawequal(L, -1, -2);
  61. lua_pop(L, 2);
  62. return equal && (p->type == Int);
  63. }
  64. }
  65. return 0;
  66. }
  67. LUALIB_API int lua_isint64_or_uint64(lua_State* L, int pos) {
  68. int equal;
  69. Integer64* p = (Integer64*)lua_touserdata(L, pos);
  70. if (p != NULL) {
  71. if (lua_getmetatable(L, pos)) {
  72. lua_rawgeti(L, LUA_REGISTRYINDEX, INT64_META_REF);
  73. equal = lua_rawequal(L, -1, -2);
  74. lua_pop(L, 2);
  75. return equal;
  76. }
  77. }
  78. return 0;
  79. }
  80. LUALIB_API int64_t lua_toint64(lua_State* L, int pos) {
  81. int64_t n = 0;
  82. int type = lua_type(L, pos);
  83. switch(type) {
  84. case LUA_TNUMBER:
  85. n = (int64_t)lua_tonumber(L, pos);
  86. break;
  87. case LUA_TUSERDATA:
  88. if (lua_isint64_or_uint64(L, pos)) {
  89. n = ((Integer64*)lua_touserdata(L, pos))->data.i64;
  90. }
  91. break;
  92. default:
  93. break;
  94. }
  95. return n;
  96. }
  97. #if defined(UINT_ESPECIALLY)
  98. LUALIB_API void lua_pushuint64(lua_State* L, uint64_t n) {
  99. Integer64* p = (Integer64*)lua_newuserdata(L, sizeof(Integer64));
  100. p->fake_id = -1;
  101. p->data.u64 = n;
  102. p->type = UInt;
  103. lua_rawgeti(L, LUA_REGISTRYINDEX, INT64_META_REF);
  104. lua_setmetatable(L, -2);
  105. }
  106. LUALIB_API int lua_isuint64(lua_State* L, int pos) {
  107. int equal;
  108. Integer64* p = (Integer64*)lua_touserdata(L, pos);
  109. if (p != NULL) {
  110. if (lua_getmetatable(L, pos)) {
  111. lua_rawgeti(L, LUA_REGISTRYINDEX, INT64_META_REF);
  112. equal = lua_rawequal(L, -1, -2);
  113. lua_pop(L, 2);
  114. return equal && (p->type == UInt);
  115. }
  116. }
  117. return 0;
  118. }
  119. LUALIB_API uint64_t lua_touint64(lua_State* L, int pos) {
  120. uint64_t n = 0;
  121. int type = lua_type(L, pos);
  122. switch(type) {
  123. case LUA_TNUMBER:
  124. n = (int64_t)lua_tonumber(L, pos);
  125. break;
  126. case LUA_TUSERDATA:
  127. if (lua_isint64_or_uint64(L, pos)) {
  128. n = ((Integer64*)lua_touserdata(L, pos))->data.u64;
  129. }
  130. break;
  131. default:
  132. break;
  133. }
  134. return n;
  135. }
  136. #else
  137. LUALIB_API void lua_pushuint64(lua_State* L, uint64_t n) {
  138. lua_pushint64(L, (int64_t)n);
  139. }
  140. LUALIB_API int lua_isuint64(lua_State* L, int pos) {
  141. return lua_isint64(L, pos);
  142. }
  143. LUALIB_API uint64_t lua_touint64(lua_State* L, int pos) {
  144. return (uint64_t)lua_toint64(L, pos);
  145. }
  146. #endif
  147. LUALIB_API int lua_isinteger64(lua_State* L, int pos) {
  148. int equal;
  149. Integer64* p = (Integer64*)lua_touserdata(L, pos);
  150. if (p != NULL) {
  151. if (lua_getmetatable(L, pos)) {
  152. lua_rawgeti(L, LUA_REGISTRYINDEX, INT64_META_REF);
  153. equal = lua_rawequal(L, -1, -2);
  154. lua_pop(L, 2);
  155. return equal;
  156. }
  157. }
  158. return 0;
  159. }
  160. static Integer64 lua_checkinteger64(lua_State* L, int pos) {
  161. Integer64 n = {0};
  162. int type = lua_type(L, pos);
  163. switch(type) {
  164. case LUA_TNUMBER:
  165. n.data.i64 = (int64_t)lua_tonumber(L, pos);
  166. n.type = Num;
  167. break;
  168. case LUA_TUSERDATA:
  169. if (lua_isinteger64(L, pos)) {
  170. n = *(Integer64*)lua_touserdata(L, pos);
  171. break;
  172. } else {
  173. luaL_typerror(L, pos, "Integer64");
  174. return n;
  175. }
  176. default:
  177. luaL_typerror(L, pos, "Integer64");
  178. return n;
  179. }
  180. return n;
  181. }
  182. static int int64_add(lua_State* L) {
  183. Integer64 lhs = lua_checkinteger64(L, 1);
  184. Integer64 rhs = lua_checkinteger64(L, 2);
  185. if (lhs.type != rhs.type && lhs.type != Num && rhs.type != Num) {
  186. return luaL_error(L, "type not match, lhs is %s, rhs is %s", lhs.type == Int ? "Int64" : "UInt64", rhs.type == Int ? "Int64" : "UInt64");
  187. } else if (lhs.type == UInt || rhs.type == UInt) {
  188. lua_pushuint64(L, lhs.data.u64 + rhs.data.u64);
  189. } else {
  190. lua_pushint64(L, lhs.data.i64 + rhs.data.i64);
  191. }
  192. return 1;
  193. }
  194. static int int64_sub(lua_State* L) {
  195. Integer64 lhs = lua_checkinteger64(L, 1);
  196. Integer64 rhs = lua_checkinteger64(L, 2);
  197. if (lhs.type != rhs.type && lhs.type != Num && rhs.type != Num) {
  198. return luaL_error(L, "type not match, lhs is %s, rhs is %s", lhs.type == Int ? "Int64" : "UInt64", rhs.type == Int ? "Int64" : "UInt64");
  199. } else if (lhs.type == UInt || rhs.type == UInt) {
  200. lua_pushuint64(L, lhs.data.u64 - rhs.data.u64);
  201. } else {
  202. lua_pushint64(L, lhs.data.i64 - rhs.data.i64);
  203. }
  204. return 1;
  205. }
  206. static int int64_mul(lua_State* L) {
  207. Integer64 lhs = lua_checkinteger64(L, 1);
  208. Integer64 rhs = lua_checkinteger64(L, 2);
  209. if (lhs.type != rhs.type && lhs.type != Num && rhs.type != Num) {
  210. return luaL_error(L, "type not match, lhs is %s, rhs is %s", lhs.type == Int ? "Int64" : "UInt64", rhs.type == Int ? "Int64" : "UInt64");
  211. } else if (lhs.type == UInt || rhs.type == UInt) {
  212. lua_pushuint64(L, lhs.data.u64 * rhs.data.u64);
  213. } else {
  214. lua_pushint64(L, lhs.data.i64 * rhs.data.i64);
  215. }
  216. return 1;
  217. }
  218. static int int64_div(lua_State* L) {
  219. Integer64 lhs = lua_checkinteger64(L, 1);
  220. Integer64 rhs = lua_checkinteger64(L, 2);
  221. if (rhs.data.i64 == 0) {
  222. return luaL_error(L, "div by zero");
  223. }
  224. if (lhs.type != rhs.type && lhs.type != Num && rhs.type != Num) {
  225. return luaL_error(L, "type not match, lhs is %s, rhs is %s", lhs.type == Int ? "Int64" : "UInt64", rhs.type == Int ? "Int64" : "UInt64");
  226. } else if (lhs.type == UInt || rhs.type == UInt) {
  227. lua_pushuint64(L, lhs.data.u64 / rhs.data.u64);
  228. } else {
  229. lua_pushint64(L, lhs.data.i64 / rhs.data.i64);
  230. }
  231. return 1;
  232. }
  233. static int int64_mod(lua_State* L) {
  234. Integer64 lhs = lua_checkinteger64(L, 1);
  235. Integer64 rhs = lua_checkinteger64(L, 2);
  236. if (rhs.data.i64 == 0) {
  237. return luaL_error(L, "mod by zero");
  238. }
  239. if (lhs.type != rhs.type && lhs.type != Num && rhs.type != Num) {
  240. return luaL_error(L, "type not match, lhs is %s, rhs is %s", lhs.type == Int ? "Int64" : "UInt64", rhs.type == Int ? "Int64" : "UInt64");
  241. } else if (lhs.type == UInt || rhs.type == UInt) {
  242. lua_pushuint64(L, lhs.data.u64 % rhs.data.u64);
  243. } else {
  244. lua_pushint64(L, lhs.data.i64 % rhs.data.i64);
  245. }
  246. return 1;
  247. }
  248. static int int64_unm(lua_State* L) {
  249. Integer64 lhs = lua_checkinteger64(L, 1);
  250. lua_pushint64(L, -lhs.data.i64);
  251. return 1;
  252. }
  253. static int int64_pow(lua_State* L) {
  254. Integer64 lhs = lua_checkinteger64(L, 1);
  255. Integer64 rhs = lua_checkinteger64(L, 2);
  256. if (lhs.type != rhs.type && lhs.type != Num && rhs.type != Num) {
  257. return luaL_error(L, "type not match, lhs is %s, rhs is %s", lhs.type == Int ? "Int64" : "UInt64", rhs.type == Int ? "Int64" : "UInt64");
  258. } else if (lhs.type == UInt || rhs.type == UInt) {
  259. lua_pushuint64(L, pow(lhs.data.u64, rhs.data.u64));
  260. } else {
  261. lua_pushint64(L, pow(lhs.data.i64, rhs.data.i64));
  262. }
  263. return 1;
  264. }
  265. static int int64_eq(lua_State* L) {
  266. Integer64 lhs = lua_checkinteger64(L, 1);
  267. Integer64 rhs = lua_checkinteger64(L, 2);
  268. if (lhs.type != rhs.type && lhs.type != Num && rhs.type != Num) {
  269. return luaL_error(L, "type not match, lhs is %s, rhs is %s", lhs.type == Int ? "Int64" : "UInt64", rhs.type == Int ? "Int64" : "UInt64");
  270. } else if (lhs.type == UInt || rhs.type == UInt) {
  271. lua_pushboolean(L, lhs.data.u64 == rhs.data.u64);
  272. } else {
  273. lua_pushboolean(L, lhs.data.i64 == rhs.data.i64);
  274. }
  275. return 1;
  276. }
  277. static int int64_lt(lua_State* L) {
  278. Integer64 lhs = lua_checkinteger64(L, 1);
  279. Integer64 rhs = lua_checkinteger64(L, 2);
  280. if (lhs.type != rhs.type && lhs.type != Num && rhs.type != Num) {
  281. return luaL_error(L, "type not match, lhs is %s, rhs is %s", lhs.type == Int ? "Int64" : "UInt64", rhs.type == Int ? "Int64" : "UInt64");
  282. } else if (lhs.type == UInt || rhs.type == UInt) {
  283. lua_pushboolean(L, lhs.data.u64 < rhs.data.u64);
  284. } else {
  285. lua_pushboolean(L, lhs.data.i64 < rhs.data.i64);
  286. }
  287. return 1;
  288. }
  289. static int int64_le(lua_State* L) {
  290. Integer64 lhs = lua_checkinteger64(L, 1);
  291. Integer64 rhs = lua_checkinteger64(L, 2);
  292. if (lhs.type != rhs.type && lhs.type != Num && rhs.type != Num) {
  293. return luaL_error(L, "type not match, lhs is %s, rhs is %s", lhs.type == Int ? "Int64" : "UInt64", rhs.type == Int ? "Int64" : "UInt64");
  294. } else if (lhs.type == UInt || rhs.type == UInt) {
  295. lua_pushboolean(L, lhs.data.u64 <= rhs.data.u64);
  296. } else {
  297. lua_pushboolean(L, lhs.data.i64 <= rhs.data.i64);
  298. }
  299. return 1;
  300. }
  301. static int int64_tostring(lua_State* L) {
  302. char temp[72];
  303. Integer64 lhs = lua_checkinteger64(L, 1);
  304. if (lhs.type == UInt) {
  305. sprintf(temp, "%"PRIu64"U", lhs.data.u64);
  306. } else {
  307. sprintf(temp, "%"PRId64, lhs.data.i64);
  308. }
  309. lua_pushstring(L, temp);
  310. return 1;
  311. }
  312. #endif
  313. #if LUA_VERSION_NUM == 503
  314. LUALIB_API void lua_pushint64(lua_State* L, int64_t n) {
  315. lua_pushinteger(L, n);
  316. }
  317. LUALIB_API void lua_pushuint64(lua_State* L, uint64_t n) {
  318. lua_pushinteger(L, n);
  319. }
  320. LUALIB_API int lua_isint64(lua_State* L, int pos) {
  321. return lua_isinteger(L, pos);
  322. }
  323. LUALIB_API int lua_isuint64(lua_State* L, int pos) {
  324. return lua_isinteger(L, pos);
  325. }
  326. LUALIB_API int64_t lua_toint64(lua_State* L, int pos) {
  327. return lua_tointeger(L, pos);
  328. }
  329. LUALIB_API uint64_t lua_touint64(lua_State* L, int pos) {
  330. return lua_tointeger(L, pos);
  331. }
  332. #endif
  333. static int uint64_tostring(lua_State* L) {
  334. char temp[72];
  335. uint64_t n = lua_touint64(L, 1);
  336. #if ( defined (_WIN32) || defined (_WIN64) ) && !defined (__MINGW32__) && !defined (__MINGW64__)
  337. sprintf_s(temp, sizeof(temp), "%"PRIu64, n);
  338. #else
  339. snprintf(temp, sizeof(temp), "%"PRIu64, n);
  340. #endif
  341. lua_pushstring(L, temp);
  342. return 1;
  343. }
  344. static int uint64_compare(lua_State* L) {
  345. uint64_t lhs = lua_touint64(L, 1);
  346. uint64_t rhs = lua_touint64(L, 2);
  347. lua_pushinteger(L, lhs == rhs ? 0 : (lhs < rhs ? -1 : 1));
  348. return 1;
  349. }
  350. static int uint64_divide(lua_State* L) {
  351. uint64_t lhs = lua_touint64(L, 1);
  352. uint64_t rhs = lua_touint64(L, 2);
  353. if (rhs == 0) {
  354. return luaL_error(L, "div by zero");
  355. }
  356. lua_pushuint64(L, lhs / rhs);
  357. return 1;
  358. }
  359. static int uint64_remainder(lua_State* L) {
  360. uint64_t lhs = lua_touint64(L, 1);
  361. uint64_t rhs = lua_touint64(L, 2);
  362. if (rhs == 0) {
  363. return luaL_error(L, "div by zero");
  364. }
  365. lua_pushuint64(L, lhs % rhs);
  366. return 1;
  367. }
  368. LUALIB_API int uint64_parse(lua_State* L)
  369. {
  370. const char* str = lua_tostring(L, 1);
  371. lua_pushuint64(L, strtoull(str, NULL, 0));
  372. return 1;
  373. }
  374. LUALIB_API int luaopen_i64lib(lua_State* L)
  375. {
  376. #if LUA_VERSION_NUM == 501
  377. lua_newtable(L);
  378. lua_pushcfunction(L, int64_add);
  379. lua_setfield(L, -2, "__add");
  380. lua_pushcfunction(L, int64_sub);
  381. lua_setfield(L, -2, "__sub");
  382. lua_pushcfunction(L, int64_mul);
  383. lua_setfield(L, -2, "__mul");
  384. lua_pushcfunction(L, int64_div);
  385. lua_setfield(L, -2, "__div");
  386. lua_pushcfunction(L, int64_mod);
  387. lua_setfield(L, -2, "__mod");
  388. lua_pushcfunction(L, int64_unm);
  389. lua_setfield(L, -2, "__unm");
  390. lua_pushcfunction(L, int64_pow);
  391. lua_setfield(L, -2, "__pow");
  392. lua_pushcfunction(L, int64_tostring);
  393. lua_setfield(L, -2, "__tostring");
  394. lua_pushcfunction(L, int64_eq);
  395. lua_setfield(L, -2, "__eq");
  396. lua_pushcfunction(L, int64_lt);
  397. lua_setfield(L, -2, "__lt");
  398. lua_pushcfunction(L, int64_le);
  399. lua_setfield(L, -2, "__le");
  400. lua_rawseti(L, LUA_REGISTRYINDEX, INT64_META_REF);
  401. #endif
  402. lua_newtable(L);
  403. lua_pushcfunction(L, uint64_tostring);
  404. lua_setfield(L, -2, "tostring");
  405. lua_pushcfunction(L, uint64_compare);
  406. lua_setfield(L, -2, "compare");
  407. lua_pushcfunction(L, uint64_divide);
  408. lua_setfield(L, -2, "divide");
  409. lua_pushcfunction(L, uint64_remainder);
  410. lua_setfield(L, -2, "remainder");
  411. lua_pushcfunction(L, uint64_parse);
  412. lua_setfield(L, -2, "parse");
  413. lua_setglobal(L, "uint64");
  414. return 0;
  415. }