lua-datasheet.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. #include <lua.h>
  2. #include <lauxlib.h>
  3. #include <stdint.h>
  4. #define NODECACHE "_ctable"
  5. #define PROXYCACHE "_proxy"
  6. #define TABLES "_ctables"
  7. #define VALUE_NIL 0
  8. #define VALUE_INTEGER 1
  9. #define VALUE_REAL 2
  10. #define VALUE_BOOLEAN 3
  11. #define VALUE_TABLE 4
  12. #define VALUE_STRING 5
  13. #define VALUE_INVALID 6
  14. #define INVALID_OFFSET 0xffffffff
  15. struct proxy {
  16. const char * data;
  17. int index;
  18. };
  19. struct document {
  20. uint32_t strtbl;
  21. uint32_t n;
  22. uint32_t index[1];
  23. // table[n]
  24. // strings
  25. };
  26. struct table {
  27. uint32_t array;
  28. uint32_t dict;
  29. uint8_t type[1];
  30. // value[array]
  31. // kvpair[dict]
  32. };
  33. static inline const struct table *
  34. gettable(const struct document *doc, int index) {
  35. if (doc->index[index] == INVALID_OFFSET) {
  36. return NULL;
  37. }
  38. return (const struct table *)((const char *)doc + sizeof(uint32_t) + sizeof(uint32_t) + doc->n * sizeof(uint32_t) + doc->index[index]);
  39. }
  40. static void
  41. create_proxy(lua_State *L, const void *data, int index) {
  42. const struct table * t = gettable(data, index);
  43. if (t == NULL) {
  44. luaL_error(L, "Invalid index %d", index);
  45. }
  46. lua_getfield(L, LUA_REGISTRYINDEX, NODECACHE);
  47. if (lua_rawgetp(L, -1, t) == LUA_TTABLE) {
  48. lua_replace(L, -2);
  49. return;
  50. }
  51. lua_pop(L, 1);
  52. lua_newtable(L);
  53. lua_pushvalue(L, lua_upvalueindex(1));
  54. lua_setmetatable(L, -2);
  55. lua_pushvalue(L, -1);
  56. // NODECACHE, table, table
  57. lua_rawsetp(L, -3, t);
  58. // NODECACHE, table
  59. lua_getfield(L, LUA_REGISTRYINDEX, PROXYCACHE);
  60. // NODECACHE, table, PROXYCACHE
  61. lua_pushvalue(L, -2);
  62. // NODECACHE, table, PROXYCACHE, table
  63. struct proxy * p = lua_newuserdatauv(L, sizeof(struct proxy), 0);
  64. // NODECACHE, table, PROXYCACHE, table, proxy
  65. p->data = data;
  66. p->index = index;
  67. lua_rawset(L, -3);
  68. // NODECACHE, table, PROXYCACHE
  69. lua_pop(L, 1);
  70. // NODECACHE, table
  71. lua_replace(L, -2);
  72. // table
  73. }
  74. static void
  75. clear_table(lua_State *L) {
  76. int t = lua_gettop(L); // clear top table
  77. if (lua_type(L, t) != LUA_TTABLE) {
  78. luaL_error(L, "Invalid cache");
  79. }
  80. lua_pushnil(L);
  81. while (lua_next(L, t) != 0) {
  82. // key value
  83. lua_pop(L, 1);
  84. lua_pushvalue(L, -1);
  85. lua_pushnil(L);
  86. // key key nil
  87. lua_rawset(L, t);
  88. // key
  89. }
  90. }
  91. static void
  92. update_cache(lua_State *L, const void *data, const void * newdata) {
  93. lua_getfield(L, LUA_REGISTRYINDEX, NODECACHE);
  94. int t = lua_gettop(L);
  95. lua_getfield(L, LUA_REGISTRYINDEX, PROXYCACHE);
  96. int pt = t + 1;
  97. lua_newtable(L); // temp table
  98. int nt = pt + 1;
  99. lua_pushnil(L);
  100. while (lua_next(L, t) != 0) {
  101. // pointer (-2) -> table (-1)
  102. lua_pushvalue(L, -1);
  103. if (lua_rawget(L, pt) == LUA_TUSERDATA) {
  104. // pointer, table, proxy
  105. struct proxy * p = lua_touserdata(L, -1);
  106. if (p->data == data) {
  107. // update to newdata
  108. p->data = newdata;
  109. const struct table * newt = gettable(newdata, p->index);
  110. lua_pop(L, 1);
  111. // pointer, table
  112. clear_table(L);
  113. lua_pushvalue(L, lua_upvalueindex(1));
  114. // pointer, table, meta
  115. lua_setmetatable(L, -2);
  116. // pointer, table
  117. if (newt) {
  118. lua_rawsetp(L, nt, newt);
  119. } else {
  120. lua_pop(L, 1);
  121. }
  122. // pointer
  123. lua_pushvalue(L, -1);
  124. lua_pushnil(L);
  125. lua_rawset(L, t);
  126. } else {
  127. lua_pop(L, 2);
  128. }
  129. } else {
  130. lua_pop(L, 2);
  131. // pointer
  132. }
  133. }
  134. // copy nt to t
  135. lua_pushnil(L);
  136. while (lua_next(L, nt) != 0) {
  137. lua_pushvalue(L, -2);
  138. lua_insert(L, -2);
  139. // key key value
  140. lua_rawset(L, t);
  141. }
  142. // NODECACHE PROXYCACHE TEMP
  143. lua_pop(L, 3);
  144. }
  145. static int
  146. lupdate(lua_State *L) {
  147. lua_getfield(L, LUA_REGISTRYINDEX, PROXYCACHE);
  148. lua_pushvalue(L, 1);
  149. // PROXYCACHE, table
  150. if (lua_rawget(L, -2) != LUA_TUSERDATA) {
  151. luaL_error(L, "Invalid proxy table %p", lua_topointer(L, 1));
  152. }
  153. struct proxy * p = lua_touserdata(L, -1);
  154. luaL_checktype(L, 2, LUA_TLIGHTUSERDATA);
  155. const char * newdata = lua_touserdata(L, 2);
  156. update_cache(L, p->data, newdata);
  157. return 1;
  158. }
  159. static inline uint32_t
  160. getuint32(const void *v) {
  161. union {
  162. uint32_t d;
  163. uint8_t t[4];
  164. } test = { 1 };
  165. if (test.t[0] == 0) {
  166. // big endian
  167. test.d = *(const uint32_t *)v;
  168. return test.t[0] | test.t[1] << 4 | test.t[2] << 8 | test.t[3] << 12;
  169. } else {
  170. return *(const uint32_t *)v;
  171. }
  172. }
  173. static inline float
  174. getfloat(const void *v) {
  175. union {
  176. uint32_t d;
  177. float f;
  178. uint8_t t[4];
  179. } test = { 1 };
  180. if (test.t[0] == 0) {
  181. // big endian
  182. test.d = *(const uint32_t *)v;
  183. test.d = test.t[0] | test.t[1] << 4 | test.t[2] << 8 | test.t[3] << 12;
  184. return test.f;
  185. } else {
  186. return *(const float *)v;
  187. }
  188. }
  189. static void
  190. pushvalue(lua_State *L, const void *v, int type, const struct document * doc) {
  191. switch (type) {
  192. case VALUE_NIL:
  193. lua_pushnil(L);
  194. break;
  195. case VALUE_INTEGER:
  196. lua_pushinteger(L, (int32_t)getuint32(v));
  197. break;
  198. case VALUE_REAL:
  199. lua_pushnumber(L, getfloat(v));
  200. break;
  201. case VALUE_BOOLEAN:
  202. lua_pushboolean(L, getuint32(v));
  203. break;
  204. case VALUE_TABLE:
  205. create_proxy(L, doc, getuint32(v));
  206. break;
  207. case VALUE_STRING:
  208. lua_pushstring(L, (const char *)doc + doc->strtbl + getuint32(v));
  209. break;
  210. default:
  211. luaL_error(L, "Invalid type %d at %p", type, v);
  212. }
  213. }
  214. static void
  215. copytable(lua_State *L, int tbl, struct proxy *p) {
  216. const struct document * doc = (const struct document *)p->data;
  217. if (p->index < 0 || p->index >= doc->n) {
  218. luaL_error(L, "Invalid proxy (index = %d, total = %d)", p->index, (int)doc->n);
  219. }
  220. const struct table * t = gettable(doc, p->index);
  221. if (t == NULL) {
  222. luaL_error(L, "Invalid proxy (index = %d)", p->index);
  223. }
  224. const uint32_t * v = (const uint32_t *)((const char *)t + sizeof(uint32_t) + sizeof(uint32_t) + ((t->array + t->dict + 3) & ~3));
  225. int i;
  226. for (i=0;i<t->array;i++) {
  227. pushvalue(L, v++, t->type[i], doc);
  228. lua_rawseti(L, tbl, i+1);
  229. }
  230. for (i=0;i<t->dict;i++) {
  231. pushvalue(L, v++, VALUE_STRING, doc);
  232. pushvalue(L, v++, t->type[t->array+i], doc);
  233. lua_rawset(L, tbl);
  234. }
  235. }
  236. static int
  237. lnew(lua_State *L) {
  238. luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
  239. const char * data = lua_touserdata(L, 1);
  240. // hold ref to data
  241. lua_getfield(L, LUA_REGISTRYINDEX, TABLES);
  242. lua_pushvalue(L, 1);
  243. lua_rawsetp(L, -2, data);
  244. create_proxy(L, data, 0);
  245. return 1;
  246. }
  247. static void
  248. copyfromdata(lua_State *L) {
  249. lua_getfield(L, LUA_REGISTRYINDEX, PROXYCACHE);
  250. lua_pushvalue(L, 1);
  251. // PROXYCACHE, table
  252. if (lua_rawget(L, -2) != LUA_TUSERDATA) {
  253. luaL_error(L, "Invalid proxy table %p", lua_topointer(L, 1));
  254. }
  255. struct proxy * p = lua_touserdata(L, -1);
  256. lua_pop(L, 2);
  257. copytable(L, 1, p);
  258. lua_pushnil(L);
  259. lua_setmetatable(L, 1); // remove metatable
  260. }
  261. static int
  262. lindex(lua_State *L) {
  263. copyfromdata(L);
  264. lua_rawget(L, 1);
  265. return 1;
  266. }
  267. static int
  268. lnext(lua_State *L) {
  269. luaL_checktype(L, 1, LUA_TTABLE);
  270. lua_settop(L, 2); /* create a 2nd argument if there isn't one */
  271. if (lua_next(L, 1))
  272. return 2;
  273. else {
  274. lua_pushnil(L);
  275. return 1;
  276. }
  277. }
  278. static int
  279. lpairs(lua_State *L) {
  280. copyfromdata(L);
  281. lua_pushcfunction(L, lnext);
  282. lua_pushvalue(L, 1);
  283. lua_pushnil(L);
  284. return 3;
  285. }
  286. static int
  287. llen(lua_State *L) {
  288. copyfromdata(L);
  289. lua_pushinteger(L, lua_rawlen(L, 1));
  290. return 1;
  291. }
  292. static void
  293. new_weak_table(lua_State *L, const char *mode) {
  294. lua_newtable(L); // NODECACHE { pointer:table }
  295. lua_createtable(L, 0, 1); // weak meta table
  296. lua_pushstring(L, mode);
  297. lua_setfield(L, -2, "__mode");
  298. lua_setmetatable(L, -2); // make NODECACHE weak
  299. }
  300. static void
  301. gen_metatable(lua_State *L) {
  302. new_weak_table(L, "kv"); // NODECACHE { pointer:table }
  303. lua_setfield(L, LUA_REGISTRYINDEX, NODECACHE);
  304. new_weak_table(L, "k"); // PROXYCACHE { table:userdata }
  305. lua_setfield(L, LUA_REGISTRYINDEX, PROXYCACHE);
  306. lua_newtable(L);
  307. lua_setfield(L, LUA_REGISTRYINDEX, TABLES);
  308. lua_createtable(L, 0, 1); // mod table
  309. lua_createtable(L, 0, 2); // metatable
  310. luaL_Reg l[] = {
  311. { "__index", lindex },
  312. { "__pairs", lpairs },
  313. { "__len", llen },
  314. { NULL, NULL },
  315. };
  316. lua_pushvalue(L, -1);
  317. luaL_setfuncs(L, l, 1);
  318. }
  319. static int
  320. lstringpointer(lua_State *L) {
  321. const char * str = luaL_checkstring(L, 1);
  322. lua_pushlightuserdata(L, (void *)str);
  323. return 1;
  324. }
  325. LUAMOD_API int
  326. luaopen_skynet_datasheet_core(lua_State *L) {
  327. luaL_checkversion(L);
  328. luaL_Reg l[] = {
  329. { "new", lnew },
  330. { "update", lupdate },
  331. { NULL, NULL },
  332. };
  333. luaL_newlibtable(L,l);
  334. gen_metatable(L);
  335. luaL_setfuncs(L, l, 1);
  336. lua_pushcfunction(L, lstringpointer);
  337. lua_setfield(L, -2, "stringpointer");
  338. return 1;
  339. }