mp.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  1. #define LUA_LIB
  2. #include <lua.h>
  3. #include <lauxlib.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #if LUA_VERSION_NUM == 501
  7. # define LUA_OK 0
  8. # define luaL_setfuncs(L,l,u) luaL_register(L,NULL,l)
  9. # define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l))
  10. # define luaL_len(L,i) lua_objlen(L,i)
  11. static const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
  12. if (luaL_callmeta(L, idx, "__tostring")) {
  13. if (!lua_isstring(L, -1))
  14. luaL_error(L, "'__tostring' must return a string");
  15. } else {
  16. int tt;
  17. const char *kind;
  18. switch (lua_type(L, idx)) {
  19. case LUA_TNUMBER:
  20. lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx));
  21. break;
  22. case LUA_TSTRING:
  23. lua_pushvalue(L, idx); break;
  24. case LUA_TBOOLEAN:
  25. lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false"));
  26. break;
  27. case LUA_TNIL:
  28. lua_pushliteral(L, "nil");
  29. break;
  30. default:
  31. tt = luaL_getmetafield(L, idx, "__name");
  32. kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) :
  33. luaL_typename(L, idx);
  34. lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx));
  35. if (tt != LUA_TNIL) lua_remove(L, -2);
  36. }
  37. }
  38. return lua_tolstring(L, -1, len);
  39. }
  40. #endif
  41. #if LUA_VERSION_NUM >= 503
  42. # define lua53_getfield lua_getfield
  43. # define lua53_geti lua_geti
  44. # define lua53_tointegerx lua_tointegerx
  45. #else
  46. static int lua53_getfield(lua_State *L, int idx, const char *f)
  47. { lua_getfield(L, idx, f); return lua_type(L, -1); }
  48. static int lua53_geti(lua_State *L, int idx, int i)
  49. { lua_rawgeti(L, idx, i); return lua_type(L, -1); }
  50. static void lua_rotate(lua_State *L, int start, int n)
  51. { int i; for (i = 0; i < n; ++i) lua_insert(L, start+i); }
  52. static lua_Integer lua53_tointegerx(lua_State *L, int idx, int *isint) {
  53. lua_Integer i = lua_tointeger(L, idx);
  54. *isint = i == 0 ? lua_type(L, idx)==LUA_TNUMBER : lua_tonumber(L, idx)==i;
  55. return i;
  56. }
  57. #endif
  58. typedef signed long long lmp_I64;
  59. typedef unsigned long long lmp_U64;
  60. /* type info */
  61. #define LMP_TYPE_BOX "msgpack.Types"
  62. #define LMP_TYPE_FIELD "msgpack.type"
  63. static int Lnull_tostring(lua_State *L)
  64. { lua_pushliteral(L, "null"); return 1; }
  65. static int Lnull_index(lua_State *L)
  66. { return luaL_error(L, "attempt to index a msgpack.null value"); }
  67. static int lmp_fetchtable(lua_State *L, const char *name) {
  68. if (!luaL_newmetatable(L, LMP_TYPE_BOX)) {
  69. if (lua53_getfield(L, -1, name) != LUA_TNIL) {
  70. lua_remove(L, -2);
  71. return 0;
  72. }
  73. lua_pop(L, 1);
  74. }
  75. lua_createtable(L, 0, 2); /* 1 */
  76. lua_pushstring(L, name); /* 2 */
  77. lua_pushvalue(L, -2); /* 1->3 */
  78. lua_pushvalue(L, -2); /* 2->4 */
  79. lua_pushvalue(L, -3); /* 2->5 */
  80. lua_setfield(L, -3, LMP_TYPE_FIELD); /* 5->2 */
  81. lua_setfield(L, -2, "__name"); /* 4->2 */
  82. lua_rawset(L, -4); /* 2,3 -> mt */
  83. lua_remove(L, -2); /* (mt) */
  84. return 1;
  85. }
  86. static void lmp_pushnull(lua_State *L) {
  87. lua_newtable(L);
  88. if (lmp_fetchtable(L, "null")) {
  89. luaL_Reg libs[] = {
  90. { "__index", Lnull_index },
  91. { "__newindex", Lnull_index },
  92. { "__tostring", Lnull_tostring },
  93. { NULL, NULL }
  94. };
  95. luaL_setfuncs(L, libs, 0);
  96. }
  97. lua_setmetatable(L, -2);
  98. }
  99. static const char *lmp_type(lua_State *L, int idx) {
  100. const char *r = "";
  101. if (lua_getmetatable(L, idx)) {
  102. if (lua53_getfield(L, -1, LMP_TYPE_FIELD) == LUA_TSTRING)
  103. r = lua_tostring(L, -1);
  104. lua_pop(L, 2);
  105. }
  106. return r;
  107. }
  108. static int lmp_object(lua_State *L, int i, const char *name) {
  109. int start = i, top = lua_gettop(L);
  110. for (; i <= top; ++i) {
  111. if (lua_type(L, i) != LUA_TTABLE) {
  112. lua_createtable(L, 0, 1);
  113. lua_pushvalue(L, i);
  114. lua_setfield(L, -2, "value");
  115. lua_replace(L, i);
  116. lmp_fetchtable(L, name);
  117. lua_setmetatable(L, i);
  118. } else if (lua_getmetatable(L, i)) {
  119. lua_pushstring(L, name);
  120. lua_setfield(L, -2, LMP_TYPE_FIELD);
  121. lua_pop(L, 1);
  122. } else {
  123. lmp_fetchtable(L, name);
  124. lua_setmetatable(L, i);
  125. }
  126. }
  127. return top - start + 1;
  128. }
  129. static int Lmeta(lua_State *L) {
  130. const char *types[] = { "null", "False", "True", "int", "uint",
  131. "float", "double", "string", "binary", "value", "handler",
  132. "array", "map", "extension", NULL };
  133. return lmp_object(L, 2, types[luaL_checkoption(L, 1, NULL, types)]);
  134. }
  135. static int Larray(lua_State *L) { return lmp_object(L, 1, "array"); }
  136. static int Lmap(lua_State *L) { return lmp_object(L, 1, "map"); }
  137. /* encode */
  138. #define LMP_SSO_SIZE (sizeof(lmp_HeapBuffer))
  139. #define LMP_MAX_SIZE (~(unsigned)0>>1)
  140. #define LMP_MAX_STACK 100
  141. typedef struct lmp_HeapBuffer {
  142. unsigned cap;
  143. unsigned char *data;
  144. } lmp_HeapBuffer;
  145. typedef struct lmp_Buffer {
  146. lua_State *L;
  147. unsigned len : sizeof(unsigned) * CHAR_BIT - 1;
  148. unsigned sso : 1;
  149. union {
  150. lmp_HeapBuffer heap;
  151. unsigned char buff[LMP_SSO_SIZE];
  152. } u;
  153. } lmp_Buffer;
  154. #define lmp_data(B) ((B)->sso ? (B)->u.heap.data : (B)->u.buff)
  155. #define lmp_addchar(B,ch) (*lmp_prepare(B,1)=(ch),++(B)->len)
  156. #define lmp_addchars(B,s,l) (memcpy(lmp_prepare(B,l),s,l),(B)->len+=(unsigned)(l))
  157. #define lmp_nomem(B) luaL_error((B)->L, "out of memory")
  158. #define lmp_toobig(B,i,n,l) lmp_error(B,i,0,"%s too large (count=%d)",(n),(int)(l))
  159. static int lmp_encode (lmp_Buffer *B, int idx, int type, int hidx);
  160. static int lmp_pack (lmp_Buffer *B, int idx, const char *type, int fetch);
  161. static void lmp_resetbuffer(lmp_Buffer *B)
  162. { if (B->sso) { free(lmp_data(B)); memset(B, 0, sizeof(lmp_Buffer)); } }
  163. static unsigned char *lmp_prepare(lmp_Buffer *B, size_t len) {
  164. unsigned expected = B->len + (unsigned)len;
  165. unsigned cap = B->sso ? B->u.heap.cap : LMP_SSO_SIZE;
  166. if (expected > cap) {
  167. unsigned newsize = LMP_SSO_SIZE;
  168. void *newptr, *oldptr = B->sso ? lmp_data(B) : NULL;
  169. while (newsize < expected && newsize < LMP_MAX_SIZE)
  170. newsize += newsize >> 1;
  171. if (newsize < expected) lmp_nomem(B);
  172. if (!(newptr = realloc(oldptr, newsize))) lmp_nomem(B);
  173. if (!B->sso) memcpy(newptr, lmp_data(B), B->len);
  174. B->sso = 1;
  175. B->u.heap.data = (unsigned char*)newptr;
  176. B->u.heap.cap = newsize;
  177. }
  178. return lmp_data(B) + B->len;
  179. }
  180. static void lmp_writeuint(lmp_Buffer *B, lmp_U64 v, int len) {
  181. unsigned char buff[8];
  182. switch (len) {
  183. case 8: buff[0] = (v >> 56) & 0xFF;
  184. buff[1] = (v >> 48) & 0xFF;
  185. buff[2] = (v >> 40) & 0xFF;
  186. buff[3] = (v >> 32) & 0xFF; /* FALLTHROUGH */
  187. case 4: buff[4] = (v >> 24) & 0xFF;
  188. buff[5] = (v >> 16) & 0xFF; /* FALLTHROUGH */
  189. case 2: buff[6] = (v >> 8) & 0xFF; /* FALLTHROUGH */
  190. case 1: buff[7] = (v ) & 0xFF; /* FALLTHROUGH */
  191. }
  192. lmp_addchars(B, buff+8-len, len);
  193. }
  194. static int lmp_calcbytes(lmp_U64 v)
  195. { return v < 0x100 ? 0 : v < 0x10000 ? 1 : v < 0x100000000 ? 2 : 3; }
  196. static void lmp_prefix(lmp_Buffer *B, lmp_U64 v, int base, int o)
  197. { lmp_addchar(B, base + o); lmp_writeuint(B, v, 1<<o); }
  198. static void lmp_writeint(lmp_Buffer *B, lmp_U64 v, int uint) {
  199. if (v < 128) lmp_addchar(B, v & 0xFF);
  200. else if (uint) lmp_prefix(B, v, 0xCC, lmp_calcbytes(v));
  201. else if (~v < 32) lmp_addchar(B, v & 0xFF);
  202. else lmp_prefix(B, v, 0xD0, lmp_calcbytes(v >> 63 ? ~v + 1 : v<<1));
  203. }
  204. static void lmp_writefloat(lmp_Buffer *B, lua_Number n, int len) {
  205. union {
  206. float f32;
  207. double f64;
  208. unsigned u32;
  209. lmp_U64 u64;
  210. } u;
  211. if (len == 4) {
  212. u.f32 = (float)n;
  213. lmp_addchar(B, 0xCA);
  214. lmp_writeuint(B, u.u32, 4);
  215. } else {
  216. u.f64 = (double)n;
  217. lmp_addchar(B, 0xCB);
  218. lmp_writeuint(B, u.u64, 8);
  219. }
  220. }
  221. static void lmp_writestring(lmp_Buffer *B, int base, const char *s, size_t len) {
  222. if (len < 32 && base == 0xD9) { /* str */
  223. lmp_addchar(B, (char)(0xA0 + len));
  224. lmp_addchars(B, s, len);
  225. } else {
  226. lmp_prefix(B, len, base, lmp_calcbytes(len));
  227. lmp_addchars(B, s, len);
  228. }
  229. }
  230. static void lmp_writeext(lmp_Buffer *B, int type, const char *s, size_t len) {
  231. unsigned char *buff = lmp_prepare(B, 2);
  232. int o;
  233. switch (len) {
  234. case 1: buff[0] = 0xD4; break;
  235. case 2: buff[0] = 0xD5; break;
  236. case 4: buff[0] = 0xD6; break;
  237. case 8: buff[0] = 0xD7; break;
  238. case 16: buff[0] = 0xD8; break;
  239. default:
  240. o = lmp_calcbytes(len);
  241. lmp_prefix(B, len, 0xC7, o);
  242. lmp_addchar(B, type);
  243. lmp_addchars(B, s, len);
  244. return;
  245. }
  246. buff[1] = type, B->len += 2;
  247. lmp_addchars(B, s, len);
  248. }
  249. static int lmp_addfloat(lmp_Buffer *B, int idx, int len)
  250. { lmp_writefloat(B, lua_tonumber(B->L, idx), len); return 1; }
  251. static int lmp_relindex(int idx, int onstack)
  252. { return idx > 0 || idx <= LUA_REGISTRYINDEX ? idx : idx - onstack; }
  253. static int lmp_error(lmp_Buffer *B, int idx, const char *fmt, ...) {
  254. va_list l;
  255. va_start(l, fmt);
  256. lua_pushvfstring(B->L, fmt, l);
  257. va_end(l);
  258. lua_replace(B->L, lmp_relindex(idx, 1));
  259. lua_settop(B->L, idx);
  260. return 0;
  261. }
  262. static int lmp_chain(lmp_Buffer *B, int idx, int prev, const char *fmt, ...) {
  263. va_list l;
  264. va_start(l, fmt);
  265. lua_pushvfstring(B->L, fmt, l);
  266. va_end(l);
  267. lua_pushliteral(B->L, ";\n\t");
  268. lua_pushvalue(B->L, lmp_relindex(prev, 2));
  269. lua_concat(B->L, 3);
  270. lua_replace(B->L, lmp_relindex(idx, 1));
  271. lua_settop(B->L, idx);
  272. return 0;
  273. }
  274. static int lmp_addinteger(lmp_Buffer *B, int idx, int uint) {
  275. int isint;
  276. lua_Integer i = lua53_tointegerx(B->L, idx, &isint);
  277. if (!isint)
  278. return lmp_error(B, idx, "integer expected, got %s",
  279. luaL_typename(B->L, idx));
  280. if (uint) lmp_writeint(B, (lmp_U64)i, 1);
  281. else lmp_writeint(B, (lmp_U64)i, 0);
  282. return 1;
  283. }
  284. static int lmp_addstring(lmp_Buffer *B, int idx, int type) {
  285. size_t len;
  286. const char *s = lua_tolstring(B->L, idx, &len);
  287. if (len > LMP_MAX_SIZE) return lmp_toobig(B,idx,"string",(int)len);
  288. lmp_writestring(B, type, s, len);
  289. return 1;
  290. }
  291. static int lmp_addext(lmp_Buffer *B, int idx, int fetch) {
  292. int type, tt, vt;
  293. size_t len;
  294. const char *s;
  295. tt = fetch ? lua53_getfield(B->L, idx, "type") : lua_type(B->L, idx);
  296. if (tt != LUA_TNUMBER)
  297. return lmp_error(B, idx,
  298. "integer expected for extension type, got %s",
  299. lua_typename(B->L, tt));
  300. type = (int)lua_tointeger(B->L, fetch ? -1 : idx);
  301. if (type < -128 || type > 127)
  302. return lmp_error(B, idx, "invalid extension type: %d", type);
  303. vt = fetch ? lua53_getfield(B->L, idx, "value") : lua_type(B->L, idx+1);
  304. if (vt != LUA_TSTRING)
  305. return lmp_error(B, idx,
  306. "string expected for extension value, got %s",
  307. lua_typename(B->L, vt));
  308. s = lua_tolstring(B->L, fetch ? -1 : idx+1, &len);
  309. if (len > LMP_MAX_SIZE) return lmp_toobig(B,idx,"extension",(int)len);
  310. lmp_writeext(B, type, s, len);
  311. if (fetch) lua_pop(B->L, 2);
  312. return 1;
  313. }
  314. static int lmp_handlerresult(lmp_Buffer *B, int idx, int top) {
  315. int r;
  316. const char *type;
  317. if ((type = lua_tostring(B->L, top)) == NULL)
  318. return lmp_error(B, idx, "type expected from handler, got %s",
  319. luaL_typename(B->L, top));
  320. r = *type == 'e' ? lmp_addext(B, top+1, 0) : lmp_pack(B, top+1, type, 0);
  321. if (r == 0) return lmp_chain(B, idx,top+1, "error from handler");
  322. if (r == -1) return lmp_error(B, idx, "invalid msgpack.type '%s'", type);
  323. return (lua_pop(B->L, 3), 1);
  324. }
  325. static int lmp_encoderesult(lmp_Buffer *B, int idx, int r, int hidx) {
  326. if (r < 0 && hidx == 0)
  327. return lmp_error(B, idx, "invalid type '%s'", lua_typename(B->L, -r));
  328. return r;
  329. }
  330. static int lmp_addarray(lmp_Buffer *B, int idx, int hidx) {
  331. int i, len = (int)luaL_len(B->L, idx);
  332. int top = lua_gettop(B->L);
  333. if (top > LMP_MAX_STACK || !lua_checkstack(B->L, 5))
  334. return lmp_error(B, idx, "array level too deep");
  335. if (len < 16)
  336. lmp_addchar(B, 0x90 + len);
  337. else if (len < 0x10000) {
  338. lmp_addchar(B, 0xDC);
  339. lmp_writeuint(B, len, 2);
  340. } else {
  341. lmp_addchar(B, 0xDD);
  342. lmp_writeuint(B, len, 4);
  343. }
  344. for (i = 1; i <= len; ++i) {
  345. int r = lmp_encode(B, top+1, lua53_geti(B->L, idx, i), hidx);
  346. if ((r = lmp_encoderesult(B, top+1, r, hidx)) < 0) {
  347. lua_pushvalue(B->L, hidx);
  348. lua_insert(B->L, -2);
  349. lua_pushinteger(B->L, i);
  350. lua_pushvalue(B->L, idx);
  351. lua_call(B->L, 3, 3);
  352. r = lmp_handlerresult(B, top+1, top+1);
  353. }
  354. if (!r) return lmp_chain(B, idx,top+1, "invalid element '%d' in array", i);
  355. lua_settop(B->L, top);
  356. }
  357. return 1;
  358. }
  359. static void lmp_fixmapszie(lmp_Buffer *B, unsigned off, unsigned count) {
  360. unsigned len = B->len - off;
  361. unsigned char *buff;
  362. lmp_prepare(B, 5);
  363. buff = lmp_data(B) + off;
  364. if (count < 16)
  365. buff[-1] = (char)(0x80 + count);
  366. else if (count < 0x10000) {
  367. buff[-1] = 0xDE;
  368. memmove(buff+2, buff, len);
  369. B->len = off, lmp_writeuint(B, count, 2); B->len += len;
  370. } else {
  371. buff[-1] = 0xDF;
  372. memmove(buff+4, buff, len);
  373. B->len = off, lmp_writeuint(B, count, 4); B->len += len;
  374. }
  375. }
  376. static int lmp_addmap(lmp_Buffer *B, int idx, int hidx) {
  377. unsigned off = B->len + 1, count = 0;
  378. int top = lua_gettop(B->L);
  379. if (top > LMP_MAX_STACK || !lua_checkstack(B->L, 10))
  380. return lmp_error(B, idx, "map level too deep");
  381. lmp_addchar(B, 0x80);
  382. lua_pushnil(B->L);
  383. for (; lua_next(B->L, idx); ++count) {
  384. int r = lmp_encode(B, top+1, 0, hidx);
  385. if ((r = lmp_encoderesult(B, top+1, r, hidx)) < 0) {
  386. lua_pushvalue(B->L, hidx);
  387. lua_pushvalue(B->L, top+1);
  388. lua_pushnil(B->L); /* for key, the key is nil */
  389. lua_pushvalue(B->L, idx);
  390. lua_call(B->L, 3, 3);
  391. r = lmp_handlerresult(B, top+1, top+3);
  392. }
  393. if (!r) return lmp_chain(B, idx, top+1, "invalid key in map");
  394. r = lmp_encode(B, top+2, 0, hidx);
  395. if ((r = lmp_encoderesult(B, top+2, r, hidx)) < 0) {
  396. lua_pushvalue(B->L, hidx);
  397. lua_insert(B->L, -2);
  398. lua_pushvalue(B->L, top+1);
  399. lua_pushvalue(B->L, idx);
  400. lua_call(B->L, 3, 3);
  401. r = lmp_handlerresult(B, top+2, top+2);
  402. }
  403. if (!r)
  404. return lmp_chain(B, idx,top+2, "invalid value for key '%s' in map",
  405. luaL_tolstring(B->L, top+1, NULL));
  406. lua_settop(B->L, top+1);
  407. }
  408. lmp_fixmapszie(B, off, count);
  409. return 1;
  410. }
  411. static int lmp_addhandler(lmp_Buffer *B, int idx, int fetch) {
  412. int top = lua_gettop(B->L)+1;
  413. if (!fetch)
  414. lua_pushvalue(B->L, idx);
  415. else if (lua53_getfield(B->L, idx, "pack") == LUA_TNIL)
  416. return lmp_error(B, idx, "'pack' field expected in handler object");
  417. if (fetch) lua_pushvalue(B->L, idx);
  418. lua_call(B->L, fetch, 3);
  419. return lmp_handlerresult(B, idx, top);
  420. }
  421. static int lmp_check(lmp_Buffer *B, int idx, int fetch, int type) {
  422. int rt;
  423. if (!fetch)
  424. rt = lua_type(B->L, idx);
  425. else {
  426. if ((rt = lua53_getfield(B->L, idx, "value")) == LUA_TNIL)
  427. return lmp_error(B, idx, "'value' field expected in wrapper object");
  428. lua_replace(B->L, idx);
  429. }
  430. return !type || rt == type ? 1 :
  431. lmp_error(B, idx, "%s expected, got %s",
  432. lua_typename(B->L, type), luaL_typename(B->L, idx));
  433. }
  434. static int lmp_pack(lmp_Buffer *B, int idx, const char *type, int fetch) {
  435. #define check(t,c) (lmp_check(B,idx,fetch,t) && (c))
  436. switch (*type) {
  437. case 'n': lmp_addchar(B,0xC0); return 1;
  438. case 'F': lmp_addchar(B,0xC2); return 1;
  439. case 'T': lmp_addchar(B,0xC3); return 1;
  440. case 'i': return check(LUA_TNUMBER, lmp_addinteger(B,idx,0));
  441. case 'u': return check(LUA_TNUMBER, lmp_addinteger(B,idx,1));
  442. case 'f': return check(LUA_TNUMBER, lmp_addfloat(B,idx,4));
  443. case 'd': return check(LUA_TNUMBER, lmp_addfloat(B,idx,8));
  444. case 's': return check(LUA_TSTRING, lmp_addstring(B,idx,0xD9));
  445. case 'b': return check(LUA_TSTRING, lmp_addstring(B,idx,0xC4));
  446. case 'v': return check(0, lmp_encode(B, idx, 0, 0));
  447. case 'h': return lmp_addhandler(B, idx, 1);
  448. case 'a': return lmp_addarray(B, idx, 0);
  449. case 'm': return lmp_addmap(B, idx, 0);
  450. case 'e': return lmp_addext(B, idx, 1);
  451. }
  452. #undef check
  453. return -1;
  454. }
  455. static int lmp_addnumber(lmp_Buffer *B, int idx) {
  456. int isint;
  457. lua_Integer i = lua53_tointegerx(B->L, idx, &isint);
  458. if (isint)
  459. lmp_writeint(B, (lmp_U64)i, 0);
  460. else {
  461. lua_Number n = lua_tonumber(B->L, idx);
  462. int float_ok = (lua_Number)(float)n == n;
  463. if (float_ok) lmp_writefloat(B, n, 4);
  464. else lmp_writefloat(B, n, 8);
  465. }
  466. return 1;
  467. }
  468. static int lmp_addtable(lmp_Buffer *B, int idx, int hidx) {
  469. const char *type = lmp_type(B->L, idx);
  470. int r = lmp_pack(B, idx, type, 1);
  471. if (r == 0 || r == 1) return r;
  472. return luaL_len(B->L, idx) > 0 ? lmp_addarray(B, idx, hidx) : lmp_addmap(B, idx, hidx);
  473. }
  474. static int lmp_encode(lmp_Buffer *B, int idx, int type, int hidx) {
  475. switch (type ? type : (type = lua_type(B->L, idx))) {
  476. case LUA_TNONE:
  477. case LUA_TNIL: lmp_addchar(B, 0xC0); return 1;
  478. case LUA_TBOOLEAN: lmp_addchar(B, 0xC2+lua_toboolean(B->L,idx)); return 1;
  479. case LUA_TNUMBER: return lmp_addnumber(B, idx);
  480. case LUA_TSTRING: return lmp_addstring(B, idx, 0xD9);
  481. case LUA_TFUNCTION: return lmp_addhandler(B, idx, 0);
  482. case LUA_TTABLE: return lmp_addtable(B, idx, hidx);
  483. }
  484. return -type;
  485. }
  486. static int Lencode_aux(lua_State *L) {
  487. lmp_Buffer *B = (lmp_Buffer*)lua_touserdata(L, 1);
  488. int i, top = lua_gettop(L);
  489. B->L = L;
  490. for (i = 2; i <= top; ++i) {
  491. int r = lmp_encode(B, i, 0, 0);
  492. if (!(r = lmp_encoderesult(B, i, r, 0)))
  493. return luaL_error(L, "bad argument to #%d: %s",
  494. i-1, lua_tostring(L, i));
  495. }
  496. lua_pushlstring(L, (const char*)lmp_data(B), B->len);
  497. return 1;
  498. }
  499. static int Lencode(lua_State *L) {
  500. lmp_Buffer B;
  501. int r;
  502. memset(&B, 0, sizeof(B));
  503. lua_pushcfunction(L, Lencode_aux);
  504. lua_insert(L, 1);
  505. lua_pushlightuserdata(L, &B);
  506. lua_insert(L, 2);
  507. r = lua_pcall(L, lua_gettop(L)-1, 1, 0) == LUA_OK;
  508. lmp_resetbuffer(&B);
  509. return r ? 1 : luaL_error(L, "%s", lua_tostring(L, -1));
  510. }
  511. static int Lencoder_aux(lua_State *L) {
  512. lmp_Buffer *B = (lmp_Buffer*)lua_touserdata(L, 1);
  513. int i, top = lua_gettop(L);
  514. B->L = L;
  515. for (i = 3; i <= top; ++i) {
  516. int r = lmp_encode(B, i, 0, 2);
  517. if ((r = lmp_encoderesult(B, i, r, 2)) < 0) {
  518. lua_pushvalue(B->L, 2);
  519. lua_pushvalue(B->L, i);
  520. lua_call(B->L, 1, 3);
  521. r = lmp_handlerresult(B, i, top+1);
  522. }
  523. if (r == 0) return luaL_error(L, "bad argument to #%d: %s",
  524. i-2, lua_tostring(L, i));
  525. }
  526. lua_pushlstring(L, (const char*)lmp_data(B), B->len);
  527. return 1;
  528. }
  529. static int Lencoder(lua_State *L) {
  530. lmp_Buffer B;
  531. int r;
  532. memset(&B, 0, sizeof(B));
  533. lua_pushcfunction(L, Lencoder_aux);
  534. lua_insert(L, 1);
  535. lua_pushlightuserdata(L, &B);
  536. lua_insert(L, 2);
  537. lua_pushvalue(L, lua_upvalueindex(1));
  538. lua_insert(L, 3);
  539. r = lua_pcall(L, lua_gettop(L)-1, 1, 0) == LUA_OK;
  540. lmp_resetbuffer(&B);
  541. return r ? 1 : luaL_error(L, "%s", lua_tostring(L, -1));
  542. }
  543. static int Lnewencoder(lua_State *L) {
  544. if (lua_isnoneornil(L, 1))
  545. lua_pushcfunction(L, Lencode);
  546. else {
  547. lua_pushvalue(L, 1);
  548. lua_pushcclosure(L, Lencoder, 1);
  549. }
  550. return 1;
  551. }
  552. /* decode */
  553. typedef struct lmp_Slice {
  554. const char *p, *e, *s;
  555. lua_State *L;
  556. int ext;
  557. } lmp_Slice;
  558. #define lmp_readsize(S,l) ((int)lmp_readuint(S,(int)l,"size"))
  559. #define lmp_readluint(S,l) ((lua_Integer)lmp_readuint(S,l,"uint"))
  560. #define lmp_readlint(S,l) ((lua_Integer)lmp_u2s(lmp_readuint(S,l,"int"),l))
  561. static void lmp_decode(lmp_Slice *S);
  562. static size_t lmp_off(lmp_Slice *S) { return S->p - S->s + 1; }
  563. static size_t lmp_len(lmp_Slice *S) { return S->e - S->p; }
  564. static void lmp_ensure(lmp_Slice *S, size_t len, const char *tname) {
  565. size_t rem = lmp_len(S);
  566. if (rem >= len) return;
  567. luaL_error(S->L, "invalid %s at offset %d: "
  568. "%d bytes expected, got %d bytes",
  569. tname, (int)lmp_off(S), (int)len, (int)rem);
  570. }
  571. static void lmp_pushstring(lmp_Slice *S, size_t len)
  572. { lmp_ensure(S, len, "string"); lua_pushlstring(S->L,S->p,len); S->p += len; }
  573. static void lmp_checkend(lmp_Slice *S, const char *tname) {
  574. if (S->p < S->e) return;
  575. luaL_error(S->L, "unexpected end of message at offset %d: %s expected",
  576. (int)lmp_off(S), tname);
  577. }
  578. static lmp_U64 lmp_readuint(lmp_Slice *S, int len, const char *tname) {
  579. lmp_U64 r = 0;
  580. lmp_ensure(S, len, tname);
  581. #define ch(i) ((lmp_U64)(unsigned char)S->p[i])
  582. switch (len) {
  583. case 8: r |= ch(0) << 56 | ch(1) << 48
  584. | ch(2) << 40 | ch(3) << 32; S->p += 4; /* FALLTHROUGH */
  585. case 4: r |= ch(0) << 24 | ch(1) << 16; S->p += 2; /* FALLTHROUGH */
  586. case 2: r |= ch(0) << 8; S->p += 1; /* FALLTHROUGH */
  587. case 1: r |= ch(0); S->p += 1;
  588. }
  589. #undef ch
  590. return r;
  591. }
  592. static lmp_I64 lmp_u2s(lmp_U64 v, int len) {
  593. const lmp_I64 m = 1LL << (len*8 - 1);
  594. if (len == 8 || !(v & (lmp_U64)m)) return (lmp_I64)v;
  595. v = v & ((1ULL << len*8) - 1);
  596. return (lmp_I64)(v^m) - m;
  597. }
  598. static lua_Number lmp_readfloat(lmp_Slice *S, int len) {
  599. union {
  600. float f32;
  601. double f64;
  602. lmp_U64 u64;
  603. unsigned u32;
  604. } u;
  605. if (len == 4) {
  606. u.u32 = (unsigned)lmp_readuint(S, len, "float");
  607. return (lua_Number)u.f32;
  608. } else {
  609. u.u64 = lmp_readuint(S, len, "float");
  610. return (lua_Number)u.f64;
  611. }
  612. }
  613. static void lmp_pushext(lmp_Slice *S, int fix, size_t len) {
  614. int type;
  615. lmp_ensure(S, len+1, "extension");
  616. if (!fix) len = lmp_readsize(S, len), lmp_ensure(S, len, "extension");
  617. type = (int)(signed char)*S->p++;
  618. lua_pushinteger(S->L, type);
  619. lua_pushlstring(S->L, S->p, len);
  620. S->p += len;
  621. if (S->ext) {
  622. lua_pushvalue(S->L, S->ext);
  623. lua_pushvalue(S->L, -3);
  624. lua_pushvalue(S->L, -3);
  625. lua_call(S->L, 2, 1);
  626. if (!lua_isnil(S->L, -1)) {
  627. lua_insert(S->L, -3), lua_pop(S->L, 2);
  628. return;
  629. }
  630. lua_pop(S->L, 1);
  631. }
  632. lua_createtable(S->L, 0, 2);
  633. lua_rotate(S->L, -3, 1);
  634. lua_setfield(S->L, -3, "value");
  635. lua_setfield(S->L, -2, "type");
  636. }
  637. static void lmp_pusharray(lmp_Slice *S, int count) {
  638. int i;
  639. lua_createtable(S->L, count, 0);
  640. for (i = 0; i < count; ++i) {
  641. lmp_checkend(S, "array element"); lmp_decode(S);
  642. lua_rawseti(S->L, -2, (lua_Integer)i+1);
  643. }
  644. }
  645. static void lmp_pushmap(lmp_Slice *S, int count) {
  646. int i;
  647. lua_createtable(S->L, 0, count);
  648. for (i = 0; i < count; ++i) {
  649. lmp_checkend(S, "map key"); lmp_decode(S);
  650. lmp_checkend(S, "map value"); lmp_decode(S);
  651. lua_rawset(S->L, -3);
  652. }
  653. }
  654. static void lmp_decode(lmp_Slice *S) {
  655. int ch = *S->p++ & 0xFF;
  656. switch (ch) {
  657. case 0x80: case 0x81: case 0x82: case 0x83:
  658. case 0x84: case 0x85: case 0x86: case 0x87:
  659. case 0x88: case 0x89: case 0x8A: case 0x8B:
  660. case 0x8C: case 0x8D: case 0x8E: case 0x8F:
  661. lmp_pushmap(S, ch - 0x80); break;
  662. case 0x90: case 0x91: case 0x92: case 0x93:
  663. case 0x94: case 0x95: case 0x96: case 0x97:
  664. case 0x98: case 0x99: case 0x9A: case 0x9B:
  665. case 0x9C: case 0x9D: case 0x9E: case 0x9F:
  666. lmp_pusharray(S, ch - 0x90); break;
  667. case 0xA0: case 0xA1: case 0xA2: case 0xA3:
  668. case 0xA4: case 0xA5: case 0xA6: case 0xA7:
  669. case 0xA8: case 0xA9: case 0xAA: case 0xAB:
  670. case 0xAC: case 0xAD: case 0xAE: case 0xAF:
  671. case 0xB0: case 0xB1: case 0xB2: case 0xB3:
  672. case 0xB4: case 0xB5: case 0xB6: case 0xB7:
  673. case 0xB8: case 0xB9: case 0xBA: case 0xBB:
  674. case 0xBC: case 0xBD: case 0xBE: case 0xBF:
  675. lmp_pushstring(S, (size_t)ch - 0xA0); break;
  676. case 0xC0: lua_pushnil(S->L); break;
  677. case 0xC2: lua_pushboolean(S->L, 0); break;
  678. case 0xC3: lua_pushboolean(S->L, 1); break;
  679. case 0xC4: case 0xD9: lmp_pushstring(S, lmp_readsize(S,1)); break;
  680. case 0xC5: case 0xDA: lmp_pushstring(S, lmp_readsize(S,2)); break;
  681. case 0xC6: case 0xDB: lmp_pushstring(S, lmp_readsize(S,4)); break;
  682. case 0xC7: lmp_pushext(S, 0, 1); break;
  683. case 0xC8: lmp_pushext(S, 0, 2); break;
  684. case 0xC9: lmp_pushext(S, 0, 4); break;
  685. case 0xCA: lua_pushnumber(S->L, lmp_readfloat(S, 4)); break;
  686. case 0xCB: lua_pushnumber(S->L, lmp_readfloat(S, 8)); break;
  687. case 0xCC: lua_pushinteger(S->L, lmp_readluint(S, 1)); break;
  688. case 0xCD: lua_pushinteger(S->L, lmp_readluint(S, 2)); break;
  689. case 0xCE: lua_pushinteger(S->L, lmp_readluint(S, 4)); break;
  690. case 0xCF: lua_pushinteger(S->L, lmp_readluint(S, 8)); break;
  691. case 0xD0: lua_pushinteger(S->L, lmp_readlint(S, 1)); break;
  692. case 0xD1: lua_pushinteger(S->L, lmp_readlint(S, 2)); break;
  693. case 0xD2: lua_pushinteger(S->L, lmp_readlint(S, 4)); break;
  694. case 0xD3: lua_pushinteger(S->L, lmp_readlint(S, 8)); break;
  695. case 0xD4: lmp_pushext(S, 1, 1); break;
  696. case 0xD5: lmp_pushext(S, 1, 2); break;
  697. case 0xD6: lmp_pushext(S, 1, 4); break;
  698. case 0xD7: lmp_pushext(S, 1, 8); break;
  699. case 0xD8: lmp_pushext(S, 1, 16); break;
  700. case 0xDC: lmp_pusharray(S, lmp_readsize(S, 2)); break;
  701. case 0xDD: lmp_pusharray(S, lmp_readsize(S, 4)); break;
  702. case 0xDE: lmp_pushmap(S, lmp_readsize(S, 2)); break;
  703. case 0xDF: lmp_pushmap(S, lmp_readsize(S, 4)); break;
  704. default:
  705. if (ch < 0x80) lua_pushinteger(S->L, ch);
  706. else if (ch > 0xDF) lua_pushinteger(S->L, (lua_Integer)ch - 256);
  707. else luaL_error(S->L, "invalid char '%d' at offset %d", ch, lmp_off(S));
  708. }
  709. }
  710. static size_t lmp_posrelat(lua_Integer pos, size_t len) {
  711. if (pos > 0) return (size_t)pos;
  712. else if (pos == 0) return 1;
  713. else if (pos < -(lua_Integer)len) return 1;
  714. else return len + (size_t)pos + 1;
  715. }
  716. static int Ldecode(lua_State *L) {
  717. lmp_Slice S;
  718. size_t len;
  719. const char *s = luaL_checklstring(L, 1, &len);
  720. size_t i = lmp_posrelat(luaL_optinteger(L, 2, 1), len);
  721. size_t j = lmp_posrelat(luaL_optinteger(L, 3, -1), len);
  722. if (i > j || i > len) return 0;
  723. lua_settop(L, 4);
  724. S.s = s;
  725. S.e = s + j;
  726. S.p = s + (i ? i : 1) - 1;
  727. S.L = L;
  728. S.ext = lua_isnoneornil(L, 4) ? 0 : 4;
  729. lmp_decode(&S);
  730. if (S.p >= S.e) return 1;
  731. lua_pushinteger(L, lmp_off(&S));
  732. return 2;
  733. }
  734. /* entry point */
  735. static int Ltohex(lua_State *L) {
  736. size_t i, len;
  737. const char *s = luaL_checklstring(L, 1, &len);
  738. const char *hexa = "0123456789ABCDEF";
  739. char hex[4] = "XX ";
  740. luaL_Buffer lb;
  741. luaL_buffinit(L, &lb);
  742. for (i = 0; i < len; ++i) {
  743. unsigned int ch = s[i] & 0xFF;
  744. hex[0] = hexa[(ch>>4)&0xF];
  745. hex[1] = hexa[(ch )&0xF];
  746. if (i == len-1) hex[2] = '\0';
  747. luaL_addstring(&lb, hex);
  748. }
  749. luaL_pushresult(&lb);
  750. return 1;
  751. }
  752. static int Lfromhex(lua_State *L) {
  753. size_t i, len;
  754. const char *s = luaL_checklstring(L, 1, &len);
  755. luaL_Buffer lb;
  756. int curr = 0, idx = 0, num;
  757. luaL_buffinit(L, &lb);
  758. for (i = 0; i < len; ++i) {
  759. switch (num = s[i]) {
  760. case '0': case '1': case '2': case '3':
  761. case '4': case '5': case '6': case '7':
  762. case '8': case '9': num -= '0'; break;
  763. case 'A': case 'a': num = 10; break;
  764. case 'B': case 'b': num = 11; break;
  765. case 'C': case 'c': num = 12; break;
  766. case 'D': case 'd': num = 13; break;
  767. case 'E': case 'e': num = 14; break;
  768. case 'F': case 'f': num = 15; break;
  769. default: continue;
  770. }
  771. curr = curr<<4 | num;
  772. if (++idx % 2 == 0) luaL_addchar(&lb, curr), curr = 0;
  773. }
  774. luaL_pushresult(&lb);
  775. return 1;
  776. }
  777. LUALIB_API int luaopen_mp(lua_State *L) {
  778. luaL_Reg libs[] = {
  779. { "null", NULL },
  780. #define ENTRY(name) { #name, L##name }
  781. ENTRY(array),
  782. ENTRY(map),
  783. ENTRY(meta),
  784. ENTRY(encode),
  785. ENTRY(newencoder),
  786. ENTRY(decode),
  787. ENTRY(fromhex),
  788. ENTRY(tohex),
  789. #undef ENTRY
  790. { NULL, NULL }
  791. };
  792. luaL_newlib(L, libs);
  793. lmp_pushnull(L), lua_setfield(L, -2, "null");
  794. return 1;
  795. }
  796. /* cc: flags+='-march=native -O3 -Wextra -pedantic --coverage'
  797. * unixcc: flags+='-shared -fPIC ' output='mp.so'
  798. * maccc: flags+='-undefined dynamic_lookup'
  799. * win32cc: flags+='-mdll -DLUA_BUILD_AS_DLL ' libs+='-llua54' output='mp.dll' */