lsproto.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904
  1. #define LUA_LIB
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #include "msvcint.h"
  6. #include "lua.h"
  7. #include "lauxlib.h"
  8. #include "sproto.h"
  9. #define MAX_GLOBALSPROTO 16
  10. #define ENCODE_BUFFERSIZE 2050
  11. #define ENCODE_MAXSIZE 0x1000000
  12. #define ENCODE_DEEPLEVEL 64
  13. #ifndef luaL_newlib /* using LuaJIT */
  14. /*
  15. ** set functions from list 'l' into table at top - 'nup'; each
  16. ** function gets the 'nup' elements at the top as upvalues.
  17. ** Returns with only the table at the stack.
  18. */
  19. LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
  20. #ifdef luaL_checkversion
  21. luaL_checkversion(L);
  22. #endif
  23. luaL_checkstack(L, nup, "too many upvalues");
  24. for (; l->name != NULL; l++) { /* fill the table with given functions */
  25. int i;
  26. for (i = 0; i < nup; i++) /* copy upvalues to the top */
  27. lua_pushvalue(L, -nup);
  28. lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
  29. lua_setfield(L, -(nup + 2), l->name);
  30. }
  31. lua_pop(L, nup); /* remove upvalues */
  32. }
  33. #define luaL_newlibtable(L,l) \
  34. lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
  35. #define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
  36. #endif
  37. #if LUA_VERSION_NUM < 503
  38. #if LUA_VERSION_NUM < 502
  39. static int64_t lua_tointegerx(lua_State *L, int idx, int *isnum) {
  40. if (lua_isnumber(L, idx)) {
  41. if (isnum) *isnum = 1;
  42. return (int64_t)lua_tointeger(L, idx);
  43. }
  44. else {
  45. if (isnum) *isnum = 0;
  46. return 0;
  47. }
  48. }
  49. static int lua_absindex (lua_State *L, int idx) {
  50. if (idx > 0 || idx <= LUA_REGISTRYINDEX)
  51. return idx;
  52. return lua_gettop(L) + idx + 1;
  53. }
  54. #endif
  55. static void
  56. lua_geti(lua_State *L, int index, lua_Integer i) {
  57. index = lua_absindex(L, index);
  58. lua_pushinteger(L, i);
  59. lua_gettable(L, index);
  60. }
  61. static void
  62. lua_seti(lua_State *L, int index, lua_Integer n) {
  63. index = lua_absindex(L, index);
  64. lua_pushinteger(L, n);
  65. lua_insert(L, -2);
  66. lua_settable(L, index);
  67. }
  68. #endif
  69. #if defined(SPROTO_WEAK_TYPE)
  70. static int64_t
  71. tointegerx (lua_State *L, int idx, int *isnum) {
  72. int _isnum = 0;
  73. int64_t v = lua_tointegerx(L, idx, &_isnum);
  74. if (!_isnum){
  75. double num = lua_tonumberx(L, idx, &_isnum);
  76. if(_isnum) {
  77. v = (int64_t)llround(num);
  78. }
  79. }
  80. if(isnum) *isnum = _isnum;
  81. return v;
  82. }
  83. static int
  84. tobooleanx (lua_State *L, int idx, int *isbool) {
  85. if (isbool) *isbool = 1;
  86. return lua_toboolean(L, idx);
  87. }
  88. static const char *
  89. tolstringx (lua_State *L, int idx, size_t *len, int *isstring) {
  90. const char * str = luaL_tolstring(L, idx, len); // call metamethod, '__tostring' must return a string
  91. if (isstring) {
  92. *isstring = 1;
  93. }
  94. lua_pop(L, 1);
  95. return str;
  96. }
  97. #else
  98. #define tointegerx(L, idx, isnum) lua_tointegerx((L), (idx), (isnum))
  99. static int
  100. tobooleanx (lua_State *L, int idx, int *isbool) {
  101. if (isbool) *isbool = lua_isboolean(L, idx);
  102. return lua_toboolean(L, idx);
  103. }
  104. static const char *
  105. tolstringx (lua_State *L, int idx, size_t *len, int *isstring) {
  106. if (isstring) {
  107. *isstring = (lua_type(L, idx) == LUA_TSTRING);
  108. }
  109. const char * str = lua_tolstring(L, idx, len);
  110. return str;
  111. }
  112. #endif
  113. static int
  114. lnewproto(lua_State *L) {
  115. struct sproto * sp;
  116. size_t sz;
  117. void * buffer = (void *)luaL_checklstring(L,1,&sz);
  118. sp = sproto_create(buffer, sz);
  119. if (sp) {
  120. lua_pushlightuserdata(L, sp);
  121. return 1;
  122. }
  123. return 0;
  124. }
  125. static int
  126. ldeleteproto(lua_State *L) {
  127. struct sproto * sp = lua_touserdata(L,1);
  128. if (sp == NULL) {
  129. return luaL_argerror(L, 1, "Need a sproto object");
  130. }
  131. sproto_release(sp);
  132. return 0;
  133. }
  134. static int
  135. lquerytype(lua_State *L) {
  136. const char * type_name;
  137. struct sproto *sp = lua_touserdata(L,1);
  138. struct sproto_type *st;
  139. if (sp == NULL) {
  140. return luaL_argerror(L, 1, "Need a sproto object");
  141. }
  142. type_name = luaL_checkstring(L,2);
  143. st = sproto_type(sp, type_name);
  144. if (st) {
  145. lua_pushlightuserdata(L, st);
  146. return 1;
  147. }
  148. return 0;
  149. }
  150. struct encode_ud {
  151. lua_State *L;
  152. struct sproto_type *st;
  153. int tbl_index;
  154. const char * array_tag;
  155. int array_index;
  156. int deep;
  157. int map_entry;
  158. int iter_func;
  159. int iter_table;
  160. int iter_key;
  161. };
  162. static int
  163. next_list(lua_State *L, struct encode_ud * self) {
  164. // todo: check the key is equal to mainindex value
  165. if (self->iter_func) {
  166. lua_pushvalue(L, self->iter_func);
  167. lua_pushvalue(L, self->iter_table);
  168. lua_pushvalue(L, self->iter_key);
  169. lua_call(L, 2, 2);
  170. if (lua_isnil(L, -2)) {
  171. lua_pop(L, 2);
  172. return 0;
  173. }
  174. return 1;
  175. } else {
  176. lua_pushvalue(L,self->iter_key);
  177. return lua_next(L, self->array_index);
  178. }
  179. }
  180. static int
  181. get_encodefield(const struct sproto_arg *args) {
  182. struct encode_ud *self = args->ud;
  183. lua_State *L = self->L;
  184. if (args->index > 0) {
  185. int map = args->ktagname != NULL;
  186. if (args->tagname != self->array_tag) {
  187. // a new array
  188. self->array_tag = args->tagname;
  189. lua_getfield(L, self->tbl_index, args->tagname);
  190. if (lua_isnil(L, -1)) {
  191. if (self->array_index) {
  192. lua_replace(L, self->array_index);
  193. }
  194. self->array_index = 0;
  195. return SPROTO_CB_NOARRAY;
  196. }
  197. if (self->array_index) {
  198. lua_replace(L, self->array_index);
  199. } else {
  200. self->array_index = lua_gettop(L);
  201. }
  202. if (map) {
  203. if (!self->map_entry) {
  204. lua_createtable(L, 0, 2); // key/value entry
  205. self->map_entry = lua_gettop(L);
  206. }
  207. }
  208. if (luaL_getmetafield(L, self->array_index, "__pairs")) {
  209. lua_pushvalue(L, self->array_index);
  210. lua_call(L, 1, 3);
  211. int top = lua_gettop(L);
  212. self->iter_func = top - 2;
  213. self->iter_table = top - 1;
  214. self->iter_key = top;
  215. } else if (!lua_istable(L,self->array_index)) {
  216. return luaL_error(L, ".*%s(%d) should be a table or an userdata with metamethods (Is a %s)",
  217. args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
  218. } else {
  219. lua_pushnil(L);
  220. self->iter_func = 0;
  221. self->iter_table = 0;
  222. self->iter_key = lua_gettop(L);
  223. }
  224. }
  225. if (args->mainindex >= 0) { // *type(mainindex)
  226. if (!next_list(L, self)) {
  227. // iterate end
  228. lua_pushnil(L);
  229. lua_replace(L, self->iter_key);
  230. return SPROTO_CB_NIL;
  231. }
  232. if (map) {
  233. lua_pushvalue(L, -2);
  234. lua_replace(L, self->iter_key);
  235. lua_setfield(L, self->map_entry, args->vtagname);
  236. lua_setfield(L, self->map_entry, args->ktagname);
  237. lua_pushvalue(L, self->map_entry);
  238. } else {
  239. lua_insert(L, -2);
  240. lua_replace(L, self->iter_key);
  241. }
  242. } else {
  243. lua_geti(L, self->array_index, args->index);
  244. }
  245. } else {
  246. lua_getfield(L, self->tbl_index, args->tagname);
  247. }
  248. return 0;
  249. }
  250. static int encode(const struct sproto_arg *args);
  251. static int
  252. encode_one(const struct sproto_arg *args, struct encode_ud *self) {
  253. lua_State *L = self->L;
  254. int type = args->type;
  255. switch (type) {
  256. case SPROTO_TINTEGER: {
  257. int64_t v;
  258. lua_Integer vh;
  259. int isnum;
  260. if (args->extra) {
  261. // It's decimal.
  262. lua_Number vn = lua_tonumber(L, -1);
  263. // use 64bit integer for 32bit architecture.
  264. v = (int64_t)(round(vn * args->extra));
  265. } else {
  266. v = tointegerx(L, -1, &isnum);
  267. if(!isnum) {
  268. return luaL_error(L, ".%s[%d] is not an integer (Is a %s)",
  269. args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
  270. }
  271. }
  272. lua_pop(L,1);
  273. // notice: in lua 5.2, lua_Integer maybe 52bit
  274. vh = v >> 31;
  275. if (vh == 0 || vh == -1) {
  276. *(uint32_t *)args->value = (uint32_t)v;
  277. return 4;
  278. }
  279. else {
  280. *(uint64_t *)args->value = (uint64_t)v;
  281. return 8;
  282. }
  283. }
  284. case SPROTO_TDOUBLE: {
  285. lua_Number v = lua_tonumber(L, -1);
  286. *(double*)args->value = (double)v;
  287. return 8;
  288. }
  289. case SPROTO_TBOOLEAN: {
  290. int isbool;
  291. int v = tobooleanx(L, -1, &isbool);
  292. if (!isbool) {
  293. return luaL_error(L, ".%s[%d] is not a boolean (Is a %s)",
  294. args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
  295. }
  296. *(int *)args->value = v;
  297. lua_pop(L,1);
  298. return 4;
  299. }
  300. case SPROTO_TSTRING: {
  301. size_t sz = 0;
  302. int isstring;
  303. int type = lua_type(L, -1); // get the type firstly, lua_tolstring may convert value on stack to string
  304. const char * str = tolstringx(L, -1, &sz, &isstring);
  305. if (!isstring) {
  306. return luaL_error(L, ".%s[%d] is not a string (Is a %s)",
  307. args->tagname, args->index, lua_typename(L, type));
  308. }
  309. if (sz > args->length)
  310. return SPROTO_CB_ERROR;
  311. memcpy(args->value, str, sz);
  312. lua_pop(L,1);
  313. return sz;
  314. }
  315. case SPROTO_TSTRUCT: {
  316. struct encode_ud sub;
  317. int r;
  318. int top = lua_gettop(L);
  319. sub.L = L;
  320. sub.st = args->subtype;
  321. sub.tbl_index = top;
  322. sub.array_tag = NULL;
  323. sub.array_index = 0;
  324. sub.deep = self->deep + 1;
  325. sub.map_entry = 0;
  326. sub.iter_func = 0;
  327. sub.iter_table = 0;
  328. sub.iter_key = 0;
  329. r = sproto_encode(args->subtype, args->value, args->length, encode, &sub);
  330. lua_settop(L, top-1); // pop the value
  331. if (r < 0)
  332. return SPROTO_CB_ERROR;
  333. return r;
  334. }
  335. default:
  336. return luaL_error(L, "Invalid field type %d", args->type);
  337. }
  338. }
  339. static int
  340. encode(const struct sproto_arg *args) {
  341. struct encode_ud *self = args->ud;
  342. lua_State *L = self->L;
  343. int code;
  344. luaL_checkstack(L, 12, NULL);
  345. if (self->deep >= ENCODE_DEEPLEVEL)
  346. return luaL_error(L, "The table is too deep");
  347. code = get_encodefield(args);
  348. if (code < 0) {
  349. return code;
  350. }
  351. if (lua_isnil(L, -1)) {
  352. lua_pop(L,1);
  353. return SPROTO_CB_NIL;
  354. }
  355. return encode_one(args, self);
  356. }
  357. static void *
  358. expand_buffer(lua_State *L, int osz, int nsz) {
  359. void *output;
  360. do {
  361. osz *= 2;
  362. } while (osz < nsz);
  363. if (osz > ENCODE_MAXSIZE) {
  364. luaL_error(L, "object is too large (>%d)", ENCODE_MAXSIZE);
  365. return NULL;
  366. }
  367. output = lua_newuserdata(L, osz);
  368. lua_replace(L, lua_upvalueindex(1));
  369. lua_pushinteger(L, osz);
  370. lua_replace(L, lua_upvalueindex(2));
  371. return output;
  372. }
  373. /*
  374. lightuserdata sproto_type
  375. table source
  376. return string
  377. */
  378. static int
  379. lencode(lua_State *L) {
  380. struct encode_ud self;
  381. void * buffer = lua_touserdata(L, lua_upvalueindex(1));
  382. int sz = lua_tointeger(L, lua_upvalueindex(2));
  383. int tbl_index = 2;
  384. struct sproto_type * st = lua_touserdata(L, 1);
  385. if (st == NULL) {
  386. luaL_checktype(L, tbl_index, LUA_TNIL);
  387. lua_pushstring(L, "");
  388. return 1; // response nil
  389. }
  390. self.L = L;
  391. self.st = st;
  392. self.tbl_index = tbl_index;
  393. for (;;) {
  394. int r;
  395. self.array_tag = NULL;
  396. self.array_index = 0;
  397. self.deep = 0;
  398. lua_settop(L, tbl_index);
  399. self.map_entry = 0;
  400. self.iter_func = 0;
  401. self.iter_table = 0;
  402. self.iter_key = 0;
  403. r = sproto_encode(st, buffer, sz, encode, &self);
  404. if (r<0) {
  405. buffer = expand_buffer(L, sz, sz*2);
  406. sz *= 2;
  407. } else {
  408. lua_pushlstring(L, buffer, r);
  409. return 1;
  410. }
  411. }
  412. }
  413. struct decode_ud {
  414. lua_State *L;
  415. const char * array_tag;
  416. int array_index;
  417. int result_index;
  418. int deep;
  419. int mainindex_tag;
  420. int key_index;
  421. int map_entry;
  422. };
  423. static int
  424. decode(const struct sproto_arg *args) {
  425. struct decode_ud * self = args->ud;
  426. lua_State *L = self->L;
  427. if (self->deep >= ENCODE_DEEPLEVEL)
  428. return luaL_error(L, "The table is too deep");
  429. luaL_checkstack(L, 12, NULL);
  430. if (args->index != 0) {
  431. // It's array
  432. if (args->tagname != self->array_tag) {
  433. self->array_tag = args->tagname;
  434. lua_newtable(L);
  435. lua_pushvalue(L, -1);
  436. lua_setfield(L, self->result_index, args->tagname);
  437. if (self->array_index) {
  438. lua_replace(L, self->array_index);
  439. } else {
  440. self->array_index = lua_gettop(L);
  441. }
  442. if (args->index < 0) {
  443. // It's a empty array, return now.
  444. return 0;
  445. }
  446. }
  447. }
  448. switch (args->type) {
  449. case SPROTO_TINTEGER: {
  450. // notice: in lua 5.2, 52bit integer support (not 64)
  451. if (args->extra) {
  452. // lua_Integer is 32bit in small lua.
  453. int64_t v = *(int64_t*)args->value;
  454. lua_Number vn = (lua_Number)v;
  455. vn /= args->extra;
  456. lua_pushnumber(L, vn);
  457. } else {
  458. int64_t v = *(int64_t*)args->value;
  459. lua_pushinteger(L, v);
  460. }
  461. break;
  462. }
  463. case SPROTO_TDOUBLE: {
  464. double v = *(double*)args->value;
  465. lua_pushnumber(L, v);
  466. break;
  467. }
  468. case SPROTO_TBOOLEAN: {
  469. int v = *(uint64_t*)args->value;
  470. lua_pushboolean(L,v);
  471. break;
  472. }
  473. case SPROTO_TSTRING: {
  474. lua_pushlstring(L, args->value, args->length);
  475. break;
  476. }
  477. case SPROTO_TSTRUCT: {
  478. int map = args->ktagname != NULL;
  479. struct decode_ud sub;
  480. int r;
  481. sub.L = L;
  482. if (map) {
  483. if (!self->map_entry) {
  484. lua_newtable(L);
  485. self->map_entry = lua_gettop(L);
  486. }
  487. sub.result_index = self->map_entry;
  488. } else {
  489. lua_newtable(L);
  490. sub.result_index = lua_gettop(L);
  491. }
  492. sub.deep = self->deep + 1;
  493. sub.array_index = 0;
  494. sub.array_tag = NULL;
  495. sub.map_entry = 0;
  496. if (args->mainindex >= 0) {
  497. // This struct will set into a map, so mark the main index tag.
  498. sub.mainindex_tag = args->mainindex;
  499. lua_pushnil(L);
  500. sub.key_index = lua_gettop(L);
  501. r = sproto_decode(args->subtype, args->value, args->length, decode, &sub);
  502. if (r < 0)
  503. return SPROTO_CB_ERROR;
  504. if (r != args->length)
  505. return r;
  506. if (map) {
  507. lua_getfield(L, sub.result_index, args->ktagname);
  508. if (lua_isnil(L, -1)) {
  509. luaL_error(L, "Can't find key field in [%s]", args->tagname);
  510. }
  511. lua_getfield(L, sub.result_index, args->vtagname);
  512. if (lua_isnil(L, -1)) {
  513. luaL_error(L, "Can't find value field in [%s]", args->tagname);
  514. }
  515. lua_settable(L, self->array_index);
  516. lua_settop(L, sub.result_index);
  517. } else {
  518. lua_pushvalue(L, sub.key_index);
  519. if (lua_isnil(L, -1)) {
  520. luaL_error(L, "Can't find main index (tag=%d) in [%s]", args->mainindex, args->tagname);
  521. }
  522. lua_pushvalue(L, sub.result_index);
  523. lua_settable(L, self->array_index);
  524. lua_settop(L, sub.result_index-1);
  525. }
  526. return 0;
  527. } else {
  528. sub.mainindex_tag = -1;
  529. sub.key_index = 0;
  530. r = sproto_decode(args->subtype, args->value, args->length, decode, &sub);
  531. if (r < 0)
  532. return SPROTO_CB_ERROR;
  533. if (r != args->length)
  534. return r;
  535. lua_settop(L, sub.result_index);
  536. break;
  537. }
  538. }
  539. default:
  540. luaL_error(L, "Invalid type");
  541. }
  542. if (args->index > 0) {
  543. lua_seti(L, self->array_index, args->index);
  544. } else {
  545. if (self->mainindex_tag == args->tagid) {
  546. // This tag is marked, save the value to key_index
  547. // assert(self->key_index > 0);
  548. lua_pushvalue(L,-1);
  549. lua_replace(L, self->key_index);
  550. }
  551. lua_setfield(L, self->result_index, args->tagname);
  552. }
  553. return 0;
  554. }
  555. static const void *
  556. getbuffer(lua_State *L, int index, size_t *sz) {
  557. const void * buffer = NULL;
  558. int t = lua_type(L, index);
  559. if (t == LUA_TSTRING) {
  560. buffer = lua_tolstring(L, index, sz);
  561. } else {
  562. if (t != LUA_TUSERDATA && t != LUA_TLIGHTUSERDATA) {
  563. luaL_argerror(L, index, "Need a string or userdata");
  564. return NULL;
  565. }
  566. buffer = lua_touserdata(L, index);
  567. *sz = luaL_checkinteger(L, index+1);
  568. }
  569. return buffer;
  570. }
  571. /*
  572. lightuserdata sproto_type
  573. string source / (lightuserdata , integer)
  574. return table, sz(decoded bytes)
  575. */
  576. static int
  577. ldecode(lua_State *L) {
  578. struct sproto_type * st = lua_touserdata(L, 1);
  579. const void * buffer;
  580. struct decode_ud self;
  581. size_t sz;
  582. int r;
  583. if (st == NULL) {
  584. // return nil
  585. return 0;
  586. }
  587. sz = 0;
  588. buffer = getbuffer(L, 2, &sz);
  589. if (!lua_istable(L, -1)) {
  590. lua_newtable(L);
  591. }
  592. self.L = L;
  593. self.result_index = lua_gettop(L);
  594. self.array_index = 0;
  595. self.array_tag = NULL;
  596. self.deep = 0;
  597. self.mainindex_tag = -1;
  598. self.key_index = 0;
  599. self.map_entry = 0;
  600. r = sproto_decode(st, buffer, (int)sz, decode, &self);
  601. if (r < 0) {
  602. return luaL_error(L, "decode error");
  603. }
  604. lua_settop(L, self.result_index);
  605. lua_pushinteger(L, r);
  606. return 2;
  607. }
  608. static int
  609. ldumpproto(lua_State *L) {
  610. struct sproto * sp = lua_touserdata(L, 1);
  611. if (sp == NULL) {
  612. return luaL_argerror(L, 1, "Need a sproto_type object");
  613. }
  614. sproto_dump(sp);
  615. return 0;
  616. }
  617. /*
  618. string source / (lightuserdata , integer)
  619. return string
  620. */
  621. static int
  622. lpack(lua_State *L) {
  623. size_t sz=0;
  624. const void * buffer = getbuffer(L, 1, &sz);
  625. // the worst-case space overhead of packing is 2 bytes per 2 KiB of input (256 words = 2KiB).
  626. size_t maxsz = (sz + 2047) / 2048 * 2 + sz + 2;
  627. void * output = lua_touserdata(L, lua_upvalueindex(1));
  628. int bytes;
  629. int osz = lua_tointeger(L, lua_upvalueindex(2));
  630. if (osz < maxsz) {
  631. output = expand_buffer(L, osz, maxsz);
  632. }
  633. bytes = sproto_pack(buffer, sz, output, maxsz);
  634. if (bytes > maxsz) {
  635. return luaL_error(L, "packing error, return size = %d", bytes);
  636. }
  637. lua_pushlstring(L, output, bytes);
  638. return 1;
  639. }
  640. static int
  641. lunpack(lua_State *L) {
  642. size_t sz=0;
  643. const void * buffer = getbuffer(L, 1, &sz);
  644. void * output = lua_touserdata(L, lua_upvalueindex(1));
  645. int osz = lua_tointeger(L, lua_upvalueindex(2));
  646. int r = sproto_unpack(buffer, sz, output, osz);
  647. if (r < 0)
  648. return luaL_error(L, "Invalid unpack stream");
  649. if (r > osz) {
  650. output = expand_buffer(L, osz, r);
  651. r = sproto_unpack(buffer, sz, output, r);
  652. if (r < 0)
  653. return luaL_error(L, "Invalid unpack stream");
  654. }
  655. lua_pushlstring(L, output, r);
  656. return 1;
  657. }
  658. static void
  659. pushfunction_withbuffer(lua_State *L, const char * name, lua_CFunction func) {
  660. lua_newuserdata(L, ENCODE_BUFFERSIZE);
  661. lua_pushinteger(L, ENCODE_BUFFERSIZE);
  662. lua_pushcclosure(L, func, 2);
  663. lua_setfield(L, -2, name);
  664. }
  665. static int
  666. lprotocol(lua_State *L) {
  667. struct sproto * sp = lua_touserdata(L, 1);
  668. struct sproto_type * request;
  669. struct sproto_type * response;
  670. int t;
  671. int tag;
  672. if (sp == NULL) {
  673. return luaL_argerror(L, 1, "Need a sproto_type object");
  674. }
  675. t = lua_type(L,2);
  676. if (t == LUA_TNUMBER) {
  677. const char * name;
  678. tag = lua_tointeger(L, 2);
  679. name = sproto_protoname(sp, tag);
  680. if (name == NULL)
  681. return 0;
  682. lua_pushstring(L, name);
  683. } else {
  684. const char * name = lua_tostring(L, 2);
  685. if (name == NULL) {
  686. return luaL_argerror(L, 2, "Should be number or string");
  687. }
  688. tag = sproto_prototag(sp, name);
  689. if (tag < 0)
  690. return 0;
  691. lua_pushinteger(L, tag);
  692. }
  693. request = sproto_protoquery(sp, tag, SPROTO_REQUEST);
  694. if (request == NULL) {
  695. lua_pushnil(L);
  696. } else {
  697. lua_pushlightuserdata(L, request);
  698. }
  699. response = sproto_protoquery(sp, tag, SPROTO_RESPONSE);
  700. if (response == NULL) {
  701. if (sproto_protoresponse(sp, tag)) {
  702. lua_pushlightuserdata(L, NULL); // response nil
  703. } else {
  704. lua_pushnil(L);
  705. }
  706. } else {
  707. lua_pushlightuserdata(L, response);
  708. }
  709. return 3;
  710. }
  711. /* global sproto pointer for multi states
  712. NOTICE : It is not thread safe
  713. */
  714. static struct sproto * G_sproto[MAX_GLOBALSPROTO];
  715. static int
  716. lsaveproto(lua_State *L) {
  717. struct sproto * sp = lua_touserdata(L, 1);
  718. int index = luaL_optinteger(L, 2, 0);
  719. if (index < 0 || index >= MAX_GLOBALSPROTO) {
  720. return luaL_error(L, "Invalid global slot index %d", index);
  721. }
  722. /* TODO : release old object (memory leak now, but thread safe)*/
  723. G_sproto[index] = sp;
  724. return 0;
  725. }
  726. static int
  727. lloadproto(lua_State *L) {
  728. int index = luaL_optinteger(L, 1, 0);
  729. struct sproto * sp;
  730. if (index < 0 || index >= MAX_GLOBALSPROTO) {
  731. return luaL_error(L, "Invalid global slot index %d", index);
  732. }
  733. sp = G_sproto[index];
  734. if (sp == NULL) {
  735. return luaL_error(L, "nil sproto at index %d", index);
  736. }
  737. lua_pushlightuserdata(L, sp);
  738. return 1;
  739. }
  740. static void
  741. push_default(const struct sproto_arg *args, int table) {
  742. lua_State *L = args->ud;
  743. switch(args->type) {
  744. case SPROTO_TINTEGER:
  745. if (args->extra)
  746. lua_pushnumber(L, 0.0);
  747. else
  748. lua_pushinteger(L, 0);
  749. break;
  750. case SPROTO_TDOUBLE:
  751. lua_pushnumber(L, 0.0);
  752. break;
  753. case SPROTO_TBOOLEAN:
  754. lua_pushboolean(L, 0);
  755. break;
  756. case SPROTO_TSTRING:
  757. lua_pushliteral(L, "");
  758. break;
  759. case SPROTO_TSTRUCT:
  760. if (table) {
  761. lua_pushstring(L, sproto_name(args->subtype));
  762. } else {
  763. lua_createtable(L, 0, 1);
  764. lua_pushstring(L, sproto_name(args->subtype));
  765. lua_setfield(L, -2, "__type");
  766. }
  767. break;
  768. default:
  769. luaL_error(L, "Invalid type %d", args->type);
  770. break;
  771. }
  772. }
  773. static int
  774. encode_default(const struct sproto_arg *args) {
  775. lua_State *L = args->ud;
  776. lua_pushstring(L, args->tagname);
  777. if (args->index > 0) {
  778. lua_newtable(L);
  779. push_default(args, 1);
  780. lua_setfield(L, -2, "__array");
  781. lua_rawset(L, -3);
  782. return SPROTO_CB_NOARRAY;
  783. } else {
  784. push_default(args, 0);
  785. lua_rawset(L, -3);
  786. return SPROTO_CB_NIL;
  787. }
  788. }
  789. /*
  790. lightuserdata sproto_type
  791. return default table
  792. */
  793. static int
  794. ldefault(lua_State *L) {
  795. int ret;
  796. // 64 is always enough for dummy buffer, except the type has many fields ( > 27).
  797. char dummy[64];
  798. struct sproto_type * st = lua_touserdata(L, 1);
  799. if (st == NULL) {
  800. return luaL_argerror(L, 1, "Need a sproto_type object");
  801. }
  802. lua_newtable(L);
  803. ret = sproto_encode(st, dummy, sizeof(dummy), encode_default, L);
  804. if (ret<0) {
  805. // try again
  806. int sz = sizeof(dummy) * 2;
  807. void * tmp = lua_newuserdata(L, sz);
  808. lua_insert(L, -2);
  809. for (;;) {
  810. ret = sproto_encode(st, tmp, sz, encode_default, L);
  811. if (ret >= 0)
  812. break;
  813. sz *= 2;
  814. tmp = lua_newuserdata(L, sz);
  815. lua_replace(L, -3);
  816. }
  817. }
  818. return 1;
  819. }
  820. LUAMOD_API int
  821. luaopen_sproto_core(lua_State *L) {
  822. #ifdef luaL_checkversion
  823. luaL_checkversion(L);
  824. #endif
  825. luaL_Reg l[] = {
  826. { "newproto", lnewproto },
  827. { "deleteproto", ldeleteproto },
  828. { "dumpproto", ldumpproto },
  829. { "querytype", lquerytype },
  830. { "decode", ldecode },
  831. { "protocol", lprotocol },
  832. { "loadproto", lloadproto },
  833. { "saveproto", lsaveproto },
  834. { "default", ldefault },
  835. { NULL, NULL },
  836. };
  837. luaL_newlib(L,l);
  838. pushfunction_withbuffer(L, "encode", lencode);
  839. pushfunction_withbuffer(L, "pack", lpack);
  840. pushfunction_withbuffer(L, "unpack", lunpack);
  841. return 1;
  842. }