pbc-lua53.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  1. #ifdef __cplusplus
  2. extern "C" {
  3. #endif
  4. #include "lua.h"
  5. #include "lualib.h"
  6. #include "lauxlib.h"
  7. #ifdef __cplusplus
  8. }
  9. #endif
  10. #if defined(__APPLE__)
  11. #include <malloc/malloc.h>
  12. #else
  13. #include <malloc.h>
  14. #endif
  15. #ifndef _MSC_VER
  16. #include <stdbool.h>
  17. #else
  18. #define alloca _alloca
  19. #endif
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #include <stdint.h>
  23. #include "pbc.h"
  24. static inline void *
  25. checkuserdata(lua_State *L, int index) {
  26. void * ud = lua_touserdata(L,index);
  27. if (ud == NULL) {
  28. luaL_error(L, "userdata %d is nil",index);
  29. }
  30. return ud;
  31. }
  32. static int
  33. _env_new(lua_State *L) {
  34. struct pbc_env * env = pbc_new();
  35. lua_pushlightuserdata(L, env);
  36. return 1;
  37. }
  38. static int
  39. _env_register(lua_State *L) {
  40. struct pbc_env * env = (struct pbc_env *)checkuserdata(L,1);
  41. size_t sz = 0;
  42. const char * buffer = luaL_checklstring(L, 2 , &sz);
  43. struct pbc_slice slice;
  44. slice.buffer = (void *)buffer;
  45. slice.len = (int)sz;
  46. int ret = pbc_register(env, &slice);
  47. if (ret) {
  48. return luaL_error(L, "register fail");
  49. }
  50. return 0;
  51. }
  52. static int
  53. _env_enum_id(lua_State *L) {
  54. struct pbc_env * env = (struct pbc_env *)checkuserdata(L,1);
  55. size_t sz = 0;
  56. const char* enum_type = luaL_checklstring(L, 2, &sz);
  57. const char* enum_name = luaL_checklstring(L, 3, &sz);
  58. int32_t enum_id = pbc_enum_id(env, enum_type, enum_name);
  59. if (enum_id < 0)
  60. return 0;
  61. lua_pushinteger(L, enum_id);
  62. return 1;
  63. }
  64. static int
  65. _rmessage_new(lua_State *L) {
  66. struct pbc_env * env = (struct pbc_env *)checkuserdata(L,1);
  67. const char * type_name = luaL_checkstring(L,2);
  68. struct pbc_slice slice;
  69. if (lua_isstring(L,3)) {
  70. size_t sz = 0;
  71. slice.buffer = (void *)lua_tolstring(L,3,&sz);
  72. slice.len = (int)sz;
  73. } else {
  74. slice.buffer = lua_touserdata(L,3);
  75. slice.len = luaL_checkinteger(L,4);
  76. }
  77. struct pbc_rmessage * m = pbc_rmessage_new(env, type_name, &slice);
  78. if (m==NULL)
  79. return 0;
  80. lua_pushlightuserdata(L,m);
  81. return 1;
  82. }
  83. static int
  84. _rmessage_delete(lua_State *L) {
  85. struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);
  86. pbc_rmessage_delete(m);
  87. return 0;
  88. }
  89. static int
  90. _rmessage_int(lua_State *L) {
  91. struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);
  92. const char * key = luaL_checkstring(L,2);
  93. int index = luaL_checkinteger(L,3);
  94. uint32_t hi,low;
  95. low = pbc_rmessage_integer(m, key, index, &hi);
  96. int64_t v = (int64_t)((uint64_t)hi << 32 | (uint64_t)low);
  97. lua_pushinteger(L,v);
  98. return 1;
  99. }
  100. static int
  101. _rmessage_real(lua_State *L) {
  102. struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);
  103. const char * key = luaL_checkstring(L,2);
  104. int index = luaL_checkinteger(L,3);
  105. double v = pbc_rmessage_real(m, key, index);
  106. lua_pushnumber(L,v);
  107. return 1;
  108. }
  109. static int
  110. _rmessage_string(lua_State *L) {
  111. struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);
  112. const char * key = luaL_checkstring(L,2);
  113. int index = lua_tointeger(L,3);
  114. int sz = 0;
  115. const char * v = pbc_rmessage_string(m,key,index,&sz);
  116. lua_pushlstring(L,v,sz);
  117. return 1;
  118. }
  119. static int
  120. _rmessage_message(lua_State *L) {
  121. struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);
  122. const char * key = luaL_checkstring(L,2);
  123. int index = lua_tointeger(L,3);
  124. struct pbc_rmessage * v = pbc_rmessage_message(m,key,index);
  125. lua_pushlightuserdata(L,v);
  126. return 1;
  127. }
  128. static int
  129. _rmessage_size(lua_State *L) {
  130. struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);
  131. const char * key = luaL_checkstring(L,2);
  132. int sz = pbc_rmessage_size(m, key);
  133. lua_pushinteger(L, sz);
  134. return 1;
  135. }
  136. static int
  137. _env_type(lua_State *L) {
  138. lua_settop(L,3);
  139. struct pbc_env * env = (struct pbc_env *)checkuserdata(L,1);
  140. const char * type_name = luaL_checkstring(L,2);
  141. if (lua_isnil(L,3)) {
  142. int ret = pbc_type(env, type_name, NULL, NULL);
  143. lua_pushboolean(L,ret);
  144. return 1;
  145. }
  146. const char * key = luaL_checkstring(L,3);
  147. const char * type = NULL;
  148. int ret = pbc_type(env, type_name, key, &type);
  149. lua_pushinteger(L,ret);
  150. if (type == NULL) {
  151. return 1;
  152. } {
  153. lua_pushstring(L, type);
  154. return 2;
  155. }
  156. }
  157. static int
  158. _wmessage_new(lua_State *L) {
  159. struct pbc_env * env = (struct pbc_env *)checkuserdata(L,1);
  160. const char * type_name = luaL_checkstring(L,2);
  161. struct pbc_wmessage * ret = pbc_wmessage_new(env, type_name);
  162. lua_pushlightuserdata(L,ret);
  163. return 1;
  164. }
  165. static int
  166. _wmessage_delete(lua_State *L) {
  167. struct pbc_wmessage * m = (struct pbc_wmessage *)lua_touserdata(L,1);
  168. pbc_wmessage_delete(m);
  169. return 0;
  170. }
  171. static int
  172. _wmessage_real(lua_State *L) {
  173. struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);
  174. const char * key = luaL_checkstring(L,2);
  175. double number = luaL_checknumber(L,3);
  176. pbc_wmessage_real(m, key, number);
  177. return 0;
  178. }
  179. static int
  180. _wmessage_string(lua_State *L) {
  181. struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);
  182. const char * key = luaL_checkstring(L,2);
  183. size_t len = 0;
  184. const char * v = luaL_checklstring(L,3,&len);
  185. int err = pbc_wmessage_string(m, key, v, (int)len);
  186. if (err) {
  187. return luaL_error(L, "Write string error : %s", v);
  188. }
  189. return 0;
  190. }
  191. static int
  192. _wmessage_message(lua_State *L) {
  193. struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);
  194. const char * key = luaL_checkstring(L,2);
  195. struct pbc_wmessage * ret = pbc_wmessage_message(m, key);
  196. lua_pushlightuserdata(L, ret);
  197. return 1;
  198. }
  199. static int
  200. _wmessage_int(lua_State *L) {
  201. struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);
  202. const char * key = luaL_checkstring(L,2);
  203. int64_t number;
  204. // compat float for some historical reasons.
  205. if (lua_isinteger(L, 3)) {
  206. number = lua_tointeger(L,3);
  207. } else {
  208. number = (int64_t)lua_tonumber(L,3);
  209. }
  210. uint32_t hi = (uint32_t)(number >> 32);
  211. pbc_wmessage_integer(m, key, (uint32_t)number, hi);
  212. return 0;
  213. }
  214. static int
  215. _wmessage_buffer(lua_State *L) {
  216. struct pbc_slice slice;
  217. struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);
  218. pbc_wmessage_buffer(m , &slice);
  219. lua_pushlightuserdata(L, slice.buffer);
  220. lua_pushinteger(L, slice.len);
  221. return 2;
  222. }
  223. static int
  224. _wmessage_buffer_string(lua_State *L) {
  225. struct pbc_slice slice;
  226. struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);
  227. pbc_wmessage_buffer(m , &slice);
  228. lua_pushlstring(L, (const char *)slice.buffer, slice.len);
  229. return 1;
  230. }
  231. /*
  232. lightuserdata env
  233. */
  234. static int
  235. _last_error(lua_State *L) {
  236. struct pbc_env * env = (struct pbc_env *)checkuserdata(L, 1);
  237. const char * err = pbc_error(env);
  238. lua_pushstring(L,err);
  239. return 1;
  240. }
  241. /*
  242. lightuserdata env
  243. string message
  244. string format
  245. */
  246. static int
  247. _pattern_new(lua_State *L) {
  248. struct pbc_env * env = (struct pbc_env *)checkuserdata(L, 1);
  249. const char * message = luaL_checkstring(L,2);
  250. const char * format = luaL_checkstring(L,3);
  251. struct pbc_pattern * pat = pbc_pattern_new(env, message, format);
  252. if (pat == NULL) {
  253. return luaL_error(L, "create patten %s (%s) failed", message , format);
  254. }
  255. lua_pushlightuserdata(L,pat);
  256. return 1;
  257. }
  258. static int
  259. _pattern_delete(lua_State *L) {
  260. struct pbc_pattern * pat = (struct pbc_pattern *)lua_touserdata(L,1);
  261. pbc_pattern_delete(pat);
  262. return 0;
  263. }
  264. static void *
  265. _push_value(lua_State *L, char * ptr, char type) {
  266. switch(type) {
  267. case 'd': {
  268. uint64_t v = *(uint64_t*)ptr;
  269. ptr += 8;
  270. lua_pushinteger(L, v);
  271. break;
  272. }
  273. case 'i': {
  274. int32_t v = *(int32_t*)ptr;
  275. ptr += 4;
  276. lua_pushinteger(L,v);
  277. break;
  278. }
  279. case 'b': {
  280. int32_t v = *(int32_t*)ptr;
  281. ptr += 4;
  282. lua_pushboolean(L,v);
  283. break;
  284. }
  285. case 'r': {
  286. double v = *(double *)ptr;
  287. ptr += 8;
  288. lua_pushnumber(L,v);
  289. break;
  290. }
  291. case 's': {
  292. struct pbc_slice * slice = (struct pbc_slice *)ptr;
  293. lua_pushlstring(L,(const char *)slice->buffer, slice->len);
  294. ptr += sizeof(struct pbc_slice);
  295. break;
  296. }
  297. case 'm': {
  298. struct pbc_slice * slice = (struct pbc_slice *)ptr;
  299. lua_createtable(L,2,0);
  300. lua_pushlightuserdata(L, slice->buffer);
  301. lua_rawseti(L,-2,1);
  302. lua_pushinteger(L,slice->len);
  303. lua_rawseti(L,-2,2);
  304. ptr += sizeof(struct pbc_slice);
  305. break;
  306. }
  307. }
  308. return ptr;
  309. }
  310. static void
  311. _push_array(lua_State *L, pbc_array array, char type, int index) {
  312. switch (type) {
  313. case 'I': {
  314. int v = pbc_array_integer(array, index, NULL);
  315. lua_pushinteger(L, v);
  316. break;
  317. }
  318. case 'D': {
  319. uint32_t hi = 0;
  320. uint32_t low = pbc_array_integer(array, index, &hi);
  321. uint64_t v = (uint64_t)hi << 32 | (uint64_t)low;
  322. lua_pushinteger(L, v);
  323. break;
  324. }
  325. case 'B': {
  326. int v = pbc_array_integer(array, index, NULL);
  327. lua_pushboolean(L, v);
  328. break;
  329. }
  330. case 'X': {
  331. uint32_t hi = 0;
  332. uint32_t low = pbc_array_integer(array, index, &hi);
  333. uint64_t v = (uint64_t)low | (uint64_t)hi << 32;
  334. lua_pushlstring(L, (char *)&v, 8);
  335. break;
  336. }
  337. case 'R': {
  338. double v = pbc_array_real(array, index);
  339. lua_pushnumber(L, v);
  340. break;
  341. }
  342. case 'S': {
  343. struct pbc_slice * slice = pbc_array_slice(array, index);
  344. lua_pushlstring(L, (const char *)slice->buffer,slice->len);
  345. break;
  346. }
  347. case 'M': {
  348. struct pbc_slice * slice = pbc_array_slice(array, index);
  349. lua_createtable(L,2,0);
  350. lua_pushlightuserdata(L,slice->buffer);
  351. lua_rawseti(L,-2,1);
  352. lua_pushinteger(L,slice->len);
  353. lua_rawseti(L,-2,2);
  354. break;
  355. }
  356. }
  357. lua_rawseti(L,-2,index+1);
  358. }
  359. /*
  360. lightuserdata pattern
  361. string format "ixrsmb"
  362. integer size
  363. lightuserdata buffer
  364. integer buffer_len
  365. */
  366. static int
  367. _pattern_unpack(lua_State *L) {
  368. struct pbc_pattern * pat = (struct pbc_pattern *)checkuserdata(L, 1);
  369. if (pat == NULL) {
  370. return luaL_error(L, "unpack pattern is NULL");
  371. }
  372. size_t format_sz = 0;
  373. const char * format = lua_tolstring(L,2,&format_sz);
  374. int size = lua_tointeger(L,3);
  375. struct pbc_slice slice;
  376. if (lua_isstring(L,4)) {
  377. size_t buffer_len = 0;
  378. const char *buffer = luaL_checklstring(L,4,&buffer_len);
  379. slice.buffer = (void *)buffer;
  380. slice.len = buffer_len;
  381. } else {
  382. if (!lua_isuserdata(L,4)) {
  383. return luaL_error(L, "Need a userdata");
  384. }
  385. slice.buffer = lua_touserdata(L,4);
  386. slice.len = luaL_checkinteger(L,5);
  387. }
  388. char * temp = (char *)alloca(size);
  389. int ret = pbc_pattern_unpack(pat, &slice, temp);
  390. if (ret < 0) {
  391. return 0;
  392. }
  393. lua_checkstack(L, format_sz + 3);
  394. int i;
  395. char * ptr = temp;
  396. bool array = false;
  397. for (i=0;i<format_sz;i++) {
  398. char type = format[i];
  399. if (type >= 'a' && type <='z') {
  400. ptr = (char *)_push_value(L,ptr,type);
  401. } else {
  402. array = true;
  403. int n = pbc_array_size((struct _pbc_array *)ptr);
  404. lua_createtable(L,n,0);
  405. int j;
  406. for (j=0;j<n;j++) {
  407. _push_array(L,(struct _pbc_array *)ptr, type, j);
  408. }
  409. ptr += sizeof(pbc_array);
  410. }
  411. }
  412. if (array) {
  413. pbc_pattern_close_arrays(pat, temp);
  414. }
  415. return format_sz;
  416. }
  417. static char *
  418. _get_value(lua_State *L, int index, char * ptr, char type) {
  419. switch(type) {
  420. case 'i': {
  421. int32_t v = luaL_checkinteger(L, index);
  422. memcpy(ptr, &v, 4);
  423. return ptr + 4;
  424. }
  425. case 'd': {
  426. int64_t v = (int64_t)luaL_checkinteger(L, index);
  427. memcpy(ptr, &v, 8);
  428. return ptr + 8;
  429. }
  430. case 'b': {
  431. int32_t v = lua_toboolean(L, index);
  432. memcpy(ptr, &v, 4);
  433. return ptr + 4;
  434. }
  435. case 'r': {
  436. double v = luaL_checknumber(L, index);
  437. memcpy(ptr, &v, 8);
  438. return ptr + 8;
  439. }
  440. case 's': {
  441. size_t sz = 0;
  442. const char * str = luaL_checklstring(L, index, &sz);
  443. struct pbc_slice * slice = (struct pbc_slice *)ptr;
  444. slice->buffer = (void*)str;
  445. slice->len = sz;
  446. return ptr + sizeof(struct pbc_slice);
  447. }
  448. case 'm': {
  449. struct pbc_slice * slice = (struct pbc_slice *)ptr;
  450. if (lua_istable(L,index)) {
  451. lua_rawgeti(L,index,1);
  452. slice->buffer = lua_touserdata(L,-1);
  453. lua_rawgeti(L,index,2);
  454. slice->len = lua_tointeger(L,-1);
  455. lua_pop(L,2);
  456. } else {
  457. size_t sz = 0;
  458. const char * buffer = luaL_checklstring(L, index, &sz);
  459. slice->buffer = (void *)buffer;
  460. slice->len = sz;
  461. }
  462. return ptr + sizeof(struct pbc_slice);
  463. }
  464. default:
  465. luaL_error(L,"unknown format %c", type);
  466. return ptr;
  467. }
  468. }
  469. static void
  470. _get_array_value(lua_State *L, pbc_array array, char type) {
  471. switch(type) {
  472. case 'I': {
  473. int32_t v = luaL_checkinteger(L, -1);
  474. uint32_t hi = 0;
  475. if (v<0) {
  476. hi = ~0;
  477. }
  478. pbc_array_push_integer(array, v, hi);
  479. break;
  480. }
  481. case 'D' : {
  482. uint64_t v = (uint64_t)luaL_checknumber(L, -1);
  483. pbc_array_push_integer(array, (uint32_t)v, (uint32_t)(v >> 32));
  484. break;
  485. }
  486. case 'B': {
  487. int32_t v = lua_toboolean(L, -1);
  488. pbc_array_push_integer(array, v ? 1: 0, 0);
  489. break;
  490. }
  491. case 'R': {
  492. double v = luaL_checknumber(L, -1);
  493. pbc_array_push_real(array, v);
  494. break;
  495. }
  496. case 'S': {
  497. size_t sz = 0;
  498. const char * str = luaL_checklstring(L, -1, &sz);
  499. struct pbc_slice slice;
  500. slice.buffer = (void*)str;
  501. slice.len = sz;
  502. pbc_array_push_slice(array, &slice);
  503. break;
  504. }
  505. case 'M': {
  506. struct pbc_slice slice;
  507. if (lua_istable(L,-1)) {
  508. lua_rawgeti(L,-1,1);
  509. slice.buffer = lua_touserdata(L,-1);
  510. lua_rawgeti(L,-2,2);
  511. slice.len = lua_tointeger(L,-1);
  512. lua_pop(L,2);
  513. } else {
  514. size_t sz = 0;
  515. const char * buffer = luaL_checklstring(L, -1, &sz);
  516. slice.buffer = (void *)buffer;
  517. slice.len = sz;
  518. }
  519. pbc_array_push_slice(array, &slice);
  520. break;
  521. }
  522. }
  523. }
  524. /*
  525. lightuserdata pattern
  526. string format "ixrsmbp"
  527. integer size
  528. */
  529. static int
  530. _pattern_pack(lua_State *L) {
  531. struct pbc_pattern * pat = (struct pbc_pattern *)checkuserdata(L,1);
  532. if (pat == NULL) {
  533. return luaL_error(L, "pack pattern is NULL");
  534. }
  535. size_t format_sz = 0;
  536. const char * format = lua_tolstring(L,2,&format_sz);
  537. int size = lua_tointeger(L,3);
  538. char * data = (char *)alloca(size);
  539. // A trick , we don't need default value. zero buffer for array and message field.
  540. // pbc_pattern_set_default(pat, data);
  541. memset(data, 0 , size);
  542. char * ptr = data;
  543. int i;
  544. for (i=0;i<format_sz;i++) {
  545. if (format[i] >= 'a' && format[i] <='z') {
  546. ptr = _get_value(L, 4+i, ptr, format[i]);
  547. } else {
  548. if (!lua_istable(L,4+i)) {
  549. luaL_error(L,"need table for array type");
  550. }
  551. int j;
  552. int n = lua_rawlen(L,4+i);
  553. for (j=0;j<n;j++) {
  554. lua_rawgeti(L,4+i,j+1);
  555. _get_array_value(L,(struct _pbc_array *)ptr,format[i]);
  556. lua_pop(L,1);
  557. }
  558. ptr += sizeof(pbc_array);
  559. }
  560. }
  561. luaL_Buffer b;
  562. luaL_buffinit(L, &b);
  563. int cap = 128;
  564. for (;;) {
  565. char * temp = (char *)luaL_prepbuffsize(&b , cap);
  566. struct pbc_slice slice;
  567. slice.buffer = temp;
  568. slice.len = cap;
  569. int ret = pbc_pattern_pack(pat, data, &slice);
  570. if (ret < 0) {
  571. cap = cap * 2;
  572. continue;
  573. }
  574. luaL_addsize(&b , slice.len);
  575. break;
  576. }
  577. luaL_pushresult(&b);
  578. pbc_pattern_close_arrays(pat, data);
  579. return 1;
  580. }
  581. static int
  582. _pattern_size(lua_State *L) {
  583. size_t sz =0;
  584. const char *format = luaL_checklstring(L,1,&sz);
  585. int i;
  586. int size = 0;
  587. for (i=0;i<sz;i++) {
  588. switch(format[i]) {
  589. case 'b':
  590. case 'i':
  591. size += 4;
  592. break;
  593. case 'r':
  594. case 'd':
  595. size += 8;
  596. break;
  597. case 's':
  598. case 'm':
  599. size += sizeof(struct pbc_slice);
  600. break;
  601. default:
  602. size += sizeof(pbc_array);
  603. break;
  604. }
  605. }
  606. lua_pushinteger(L,size);
  607. return 1;
  608. }
  609. /*
  610. -3 table key
  611. -2 table id
  612. -1 value
  613. */
  614. static void
  615. new_array(lua_State *L, int id, const char *key) {
  616. lua_rawgeti(L, -2 , id);
  617. if (lua_isnil(L, -1)) {
  618. lua_pop(L,1);
  619. lua_newtable(L); // table.key table.id value array
  620. lua_pushvalue(L,-1);
  621. lua_pushvalue(L,-1); // table.key table.id value array array array
  622. lua_setfield(L, -6 , key);
  623. lua_rawseti(L, -4, id);
  624. }
  625. }
  626. static void
  627. push_value(lua_State *L, int type, const char * type_name, union pbc_value *v) {
  628. switch(type) {
  629. case PBC_FIXED32:
  630. case PBC_INT:
  631. lua_pushinteger(L, (int)v->i.low);
  632. break;
  633. case PBC_REAL:
  634. lua_pushnumber(L, v->f);
  635. break;
  636. case PBC_BOOL:
  637. lua_pushboolean(L, v->i.low);
  638. break;
  639. case PBC_ENUM:
  640. lua_pushstring(L, v->e.name);
  641. break;
  642. case PBC_BYTES:
  643. case PBC_STRING:
  644. lua_pushlstring(L, (const char *)v->s.buffer , v->s.len);
  645. break;
  646. case PBC_MESSAGE:
  647. lua_pushvalue(L, -3);
  648. lua_pushstring(L, type_name);
  649. lua_pushlstring(L, (const char *)v->s.buffer , v->s.len);
  650. lua_call(L, 2 , 1);
  651. break;
  652. case PBC_FIXED64:
  653. case PBC_UINT:
  654. case PBC_INT64: {
  655. uint64_t v64 = (uint64_t)(v->i.hi) << 32 | (uint64_t)(v->i.low);
  656. lua_pushinteger(L,v64);
  657. break;
  658. }
  659. default:
  660. luaL_error(L, "Unknown type %s", type_name);
  661. break;
  662. }
  663. }
  664. /*
  665. -3: function decode
  666. -2: table key
  667. -1: table id
  668. */
  669. static void
  670. decode_cb(void *ud, int type, const char * type_name, union pbc_value *v, int id, const char *key) {
  671. lua_State *L = (lua_State *)ud;
  672. if (key == NULL) {
  673. // undefined field
  674. return;
  675. }
  676. if (type & PBC_REPEATED) {
  677. push_value(L, type & ~PBC_REPEATED, type_name, v);
  678. new_array(L, id , key); // func.decode table.key table.id value array
  679. int n = lua_rawlen(L,-1);
  680. lua_insert(L, -2); // func.decode table.key table.id array value
  681. lua_rawseti(L, -2 , n+1); // func.decode table.key table.id array
  682. lua_pop(L,1);
  683. } else {
  684. push_value(L, type, type_name, v);
  685. lua_setfield(L, -3 , key);
  686. }
  687. }
  688. /*
  689. :1 lightuserdata env
  690. :2 function decode_message
  691. :3 table target
  692. :4 string type
  693. :5 string data
  694. :5 lightuserdata pointer
  695. :6 integer len
  696. table
  697. */
  698. static int
  699. _decode(lua_State *L) {
  700. struct pbc_env * env = (struct pbc_env *)checkuserdata(L,1);
  701. luaL_checktype(L, 2 , LUA_TFUNCTION);
  702. luaL_checktype(L, 3 , LUA_TTABLE);
  703. const char * type = luaL_checkstring(L,4);
  704. struct pbc_slice slice;
  705. if (lua_type(L,5) == LUA_TSTRING) {
  706. size_t len;
  707. slice.buffer = (void *)luaL_checklstring(L,5,&len);
  708. slice.len = (int)len;
  709. } else {
  710. slice.buffer = checkuserdata(L,5);
  711. slice.len = luaL_checkinteger(L,6);
  712. }
  713. lua_pushvalue(L, 2);
  714. lua_pushvalue(L, 3);
  715. lua_newtable(L);
  716. int n = pbc_decode(env, type, &slice, decode_cb, L);
  717. if (n<0) {
  718. lua_pushboolean(L,0);
  719. } else {
  720. lua_pushboolean(L,1);
  721. }
  722. return 1;
  723. }
  724. struct gcobj {
  725. struct pbc_env * env;
  726. int size_pat;
  727. int cap_pat;
  728. struct pbc_pattern ** pat;
  729. int size_msg;
  730. int cap_msg;
  731. struct pbc_rmessage ** msg;
  732. };
  733. static int
  734. _clear_gcobj(lua_State *L) {
  735. struct gcobj * obj = (struct gcobj *)lua_touserdata(L,1);
  736. int i;
  737. for (i=0;i<obj->size_pat;i++) {
  738. pbc_pattern_delete(obj->pat[i]);
  739. }
  740. for (i=0;i<obj->size_msg;i++) {
  741. pbc_rmessage_delete(obj->msg[i]);
  742. }
  743. free(obj->pat);
  744. free(obj->msg);
  745. obj->pat = NULL;
  746. obj->msg = NULL;
  747. if (obj->env) {
  748. pbc_delete(obj->env);
  749. obj->env = NULL;
  750. }
  751. return 0;
  752. }
  753. static int
  754. _gc(lua_State *L) {
  755. struct gcobj * obj;
  756. lua_settop(L,1);
  757. obj = (struct gcobj *)lua_newuserdata(L,sizeof(*obj));
  758. obj->env = (struct pbc_env *)lua_touserdata(L,1);
  759. obj->size_pat = 0;
  760. obj->cap_pat = 4;
  761. obj->size_msg = 0;
  762. obj->cap_msg = 4;
  763. obj->pat = (struct pbc_pattern **)malloc(obj->cap_pat * sizeof(struct pbc_pattern *));
  764. obj->msg = (struct pbc_rmessage **)malloc(obj->cap_msg * sizeof(struct pbc_rmessage *));
  765. lua_createtable(L,0,1);
  766. lua_pushcfunction(L, _clear_gcobj);
  767. lua_setfield(L,-2,"__gc");
  768. lua_setmetatable(L,-2);
  769. return 1;
  770. }
  771. static int
  772. _add_pattern(lua_State *L) {
  773. struct gcobj * obj = (struct gcobj *)lua_touserdata(L,1);
  774. if (obj->size_pat >= obj->cap_pat) {
  775. obj->cap_pat *= 2;
  776. obj->pat = (struct pbc_pattern **)realloc(obj->pat, obj->cap_pat * sizeof(struct pbc_pattern *));
  777. }
  778. struct pbc_pattern * pat = (struct pbc_pattern *)lua_touserdata(L,2);
  779. obj->pat[obj->size_pat++] = pat;
  780. return 0;
  781. }
  782. static int
  783. _add_rmessage(lua_State *L) {
  784. struct gcobj * obj = (struct gcobj *)lua_touserdata(L,1);
  785. if (obj->size_msg >= obj->cap_msg) {
  786. obj->cap_msg *= 2;
  787. obj->msg = (struct pbc_rmessage **)realloc(obj->msg, obj->cap_msg * sizeof(struct pbc_rmessage *));
  788. }
  789. struct pbc_rmessage * msg = (struct pbc_rmessage *)lua_touserdata(L,2);
  790. obj->msg[obj->size_msg++] = msg;
  791. return 0;
  792. }
  793. int
  794. luaopen_protobuf_c(lua_State *L) {
  795. luaL_Reg reg[] = {
  796. {"_env_new" , _env_new },
  797. {"_env_register" , _env_register },
  798. {"_env_type", _env_type },
  799. {"_rmessage_new" , _rmessage_new },
  800. {"_rmessage_delete" , _rmessage_delete },
  801. {"_rmessage_int", _rmessage_int },
  802. {"_rmessage_real" , _rmessage_real },
  803. {"_rmessage_string" , _rmessage_string },
  804. {"_rmessage_message" , _rmessage_message },
  805. {"_rmessage_size" , _rmessage_size },
  806. {"_wmessage_new", _wmessage_new },
  807. {"_wmessage_delete", _wmessage_delete },
  808. {"_wmessage_real", _wmessage_real },
  809. {"_wmessage_string", _wmessage_string },
  810. {"_wmessage_message", _wmessage_message },
  811. {"_wmessage_int", _wmessage_int },
  812. {"_wmessage_buffer", _wmessage_buffer },
  813. {"_wmessage_buffer_string", _wmessage_buffer_string },
  814. {"_pattern_new", _pattern_new },
  815. {"_pattern_delete", _pattern_delete },
  816. {"_pattern_size", _pattern_size },
  817. {"_pattern_unpack", _pattern_unpack },
  818. {"_pattern_pack", _pattern_pack },
  819. {"_last_error", _last_error },
  820. {"_decode", _decode },
  821. {"_gc", _gc },
  822. {"_add_pattern", _add_pattern },
  823. {"_add_rmessage", _add_rmessage },
  824. {"_env_enum_id", _env_enum_id},
  825. {NULL,NULL},
  826. };
  827. luaL_checkversion(L);
  828. luaL_newlib(L, reg);
  829. return 1;
  830. }