PageRenderTime 26ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/protobuf/pb.c

https://code.google.com/p/protoc-gen-lua/
C | 469 lines | 401 code | 47 blank | 21 comment | 22 complexity | b702881f811c8143b0dd05555ae28e21 MD5 | raw file
  1. /*
  2. * =====================================================================================
  3. *
  4. * Filename: pb.c
  5. *
  6. * Description: protoc-gen-lua
  7. * Google's Protocol Buffers project, ported to lua.
  8. * https://code.google.com/p/protoc-gen-lua/
  9. *
  10. * Copyright (c) 2010 , ??? (Zhuoyi Lin) netsnail@gmail.com
  11. * All rights reserved.
  12. *
  13. * Use, modification and distribution are subject to the "New BSD License"
  14. * as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.
  15. *
  16. * Created: 2010?08?02? 18?04?21?
  17. *
  18. * Company: NetEase
  19. *
  20. * =====================================================================================
  21. */
  22. #include <stdint.h>
  23. #include <string.h>
  24. #include <lua.h>
  25. #include <lualib.h>
  26. #include <lauxlib.h>
  27. #include <endian.h>
  28. #if __BYTE_ORDER == __LITTLE_ENDIAN
  29. #define IS_LITTLE_ENDIAN
  30. #endif
  31. #define IOSTRING_META "protobuf.IOString"
  32. #define checkiostring(L) \
  33. (IOString*) luaL_checkudata(L, 1, IOSTRING_META)
  34. #define IOSTRING_BUF_LEN 65535
  35. typedef struct{
  36. size_t size;
  37. char buf[IOSTRING_BUF_LEN];
  38. } IOString;
  39. static void pack_varint(luaL_Buffer *b, uint64_t value)
  40. {
  41. if (value >= 0x80)
  42. {
  43. luaL_addchar(b, value | 0x80);
  44. value >>= 7;
  45. if (value >= 0x80)
  46. {
  47. luaL_addchar(b, value | 0x80);
  48. value >>= 7;
  49. if (value >= 0x80)
  50. {
  51. luaL_addchar(b, value | 0x80);
  52. value >>= 7;
  53. if (value >= 0x80)
  54. {
  55. luaL_addchar(b, value | 0x80);
  56. value >>= 7;
  57. if (value >= 0x80)
  58. {
  59. luaL_addchar(b, value | 0x80);
  60. value >>= 7;
  61. if (value >= 0x80)
  62. {
  63. luaL_addchar(b, value | 0x80);
  64. value >>= 7;
  65. if (value >= 0x80)
  66. {
  67. luaL_addchar(b, value | 0x80);
  68. value >>= 7;
  69. if (value >= 0x80)
  70. {
  71. luaL_addchar(b, value | 0x80);
  72. value >>= 7;
  73. if (value >= 0x80)
  74. {
  75. luaL_addchar(b, value | 0x80);
  76. value >>= 7;
  77. }
  78. }
  79. }
  80. }
  81. }
  82. }
  83. }
  84. }
  85. }
  86. luaL_addchar(b, value);
  87. }
  88. static int varint_encoder(lua_State *L)
  89. {
  90. lua_Number l_value = luaL_checknumber(L, 2);
  91. uint64_t value = (uint64_t)l_value;
  92. luaL_Buffer b;
  93. luaL_buffinit(L, &b);
  94. pack_varint(&b, value);
  95. lua_settop(L, 1);
  96. luaL_pushresult(&b);
  97. lua_call(L, 1, 0);
  98. return 0;
  99. }
  100. static int signed_varint_encoder(lua_State *L)
  101. {
  102. lua_Number l_value = luaL_checknumber(L, 2);
  103. int64_t value = (int64_t)l_value;
  104. luaL_Buffer b;
  105. luaL_buffinit(L, &b);
  106. if (value < 0)
  107. {
  108. pack_varint(&b, *(uint64_t*)&value);
  109. }else{
  110. pack_varint(&b, value);
  111. }
  112. lua_settop(L, 1);
  113. luaL_pushresult(&b);
  114. lua_call(L, 1, 0);
  115. return 0;
  116. }
  117. static int pack_fixed32(lua_State *L, uint8_t* value){
  118. #ifdef IS_LITTLE_ENDIAN
  119. lua_pushlstring(L, (char*)value, 4);
  120. #else
  121. uint32_t v = htole32(*(uint32_t*)value);
  122. lua_pushlstring(L, (char*)&v, 4);
  123. #endif
  124. return 0;
  125. }
  126. static int pack_fixed64(lua_State *L, uint8_t* value){
  127. #ifdef IS_LITTLE_ENDIAN
  128. lua_pushlstring(L, (char*)value, 8);
  129. #else
  130. uint64_t v = htole32(*(uint64_t*)value);
  131. lua_pushlstring(L, (char*)&v, 8);
  132. #endif
  133. return 0;
  134. }
  135. static int struct_pack(lua_State *L)
  136. {
  137. uint8_t format = luaL_checkinteger(L, 2);
  138. lua_Number value = luaL_checknumber(L, 3);
  139. lua_settop(L, 1);
  140. switch(format){
  141. case 'i':
  142. {
  143. int32_t v = (int32_t)value;
  144. pack_fixed32(L, (uint8_t*)&v);
  145. break;
  146. }
  147. case 'q':
  148. {
  149. int64_t v = (int64_t)value;
  150. pack_fixed64(L, (uint8_t*)&v);
  151. break;
  152. }
  153. case 'f':
  154. {
  155. float v = (float)value;
  156. pack_fixed32(L, (uint8_t*)&v);
  157. break;
  158. }
  159. case 'd':
  160. {
  161. double v = (double)value;
  162. pack_fixed64(L, (uint8_t*)&v);
  163. break;
  164. }
  165. case 'I':
  166. {
  167. uint32_t v = (uint32_t)value;
  168. pack_fixed32(L, (uint8_t*)&v);
  169. break;
  170. }
  171. case 'Q':
  172. {
  173. uint64_t v = (uint64_t) value;
  174. pack_fixed64(L, (uint8_t*)&v);
  175. break;
  176. }
  177. default:
  178. luaL_error(L, "Unknown, format");
  179. }
  180. lua_call(L, 1, 0);
  181. return 0;
  182. }
  183. static size_t size_varint(const char* buffer, size_t len)
  184. {
  185. size_t pos = 0;
  186. while(buffer[pos] & 0x80){
  187. ++pos;
  188. if(pos > len){
  189. return -1;
  190. }
  191. }
  192. return pos+1;
  193. }
  194. static uint64_t unpack_varint(const char* buffer, size_t len)
  195. {
  196. uint64_t value = buffer[0] & 0x7f;
  197. size_t shift = 7;
  198. size_t pos=0;
  199. for(pos = 1; pos < len; ++pos)
  200. {
  201. value |= ((uint64_t)(buffer[pos] & 0x7f)) << shift;
  202. shift += 7;
  203. }
  204. return value;
  205. }
  206. static int varint_decoder(lua_State *L)
  207. {
  208. size_t len;
  209. const char* buffer = luaL_checklstring(L, 1, &len);
  210. size_t pos = luaL_checkinteger(L, 2);
  211. buffer += pos;
  212. len = size_varint(buffer, len);
  213. if(len == -1){
  214. luaL_error(L, "error data %s, len:%d", buffer, len);
  215. }else{
  216. lua_pushnumber(L, (lua_Number)unpack_varint(buffer, len));
  217. lua_pushinteger(L, len + pos);
  218. }
  219. return 2;
  220. }
  221. static int signed_varint_decoder(lua_State *L)
  222. {
  223. size_t len;
  224. const char* buffer = luaL_checklstring(L, 1, &len);
  225. size_t pos = luaL_checkinteger(L, 2);
  226. buffer += pos;
  227. len = size_varint(buffer, len);
  228. if(len == -1){
  229. luaL_error(L, "error data %s, len:%d", buffer, len);
  230. }else{
  231. lua_pushnumber(L, (lua_Number)(int64_t)unpack_varint(buffer, len));
  232. lua_pushinteger(L, len + pos);
  233. }
  234. return 2;
  235. }
  236. static int zig_zag_encode32(lua_State *L)
  237. {
  238. int32_t n = luaL_checkinteger(L, 1);
  239. uint32_t value = (n << 1) ^ (n >> 31);
  240. lua_pushinteger(L, value);
  241. return 1;
  242. }
  243. static int zig_zag_decode32(lua_State *L)
  244. {
  245. uint32_t n = (uint32_t)luaL_checkinteger(L, 1);
  246. int32_t value = (n >> 1) ^ - (int32_t)(n & 1);
  247. lua_pushinteger(L, value);
  248. return 1;
  249. }
  250. static int zig_zag_encode64(lua_State *L)
  251. {
  252. int64_t n = (int64_t)luaL_checknumber(L, 1);
  253. uint64_t value = (n << 1) ^ (n >> 63);
  254. lua_pushinteger(L, value);
  255. return 1;
  256. }
  257. static int zig_zag_decode64(lua_State *L)
  258. {
  259. uint64_t n = (uint64_t)luaL_checknumber(L, 1);
  260. int64_t value = (n >> 1) ^ - (int64_t)(n & 1);
  261. lua_pushinteger(L, value);
  262. return 1;
  263. }
  264. static int read_tag(lua_State *L)
  265. {
  266. size_t len;
  267. const char* buffer = luaL_checklstring(L, 1, &len);
  268. size_t pos = luaL_checkinteger(L, 2);
  269. buffer += pos;
  270. len = size_varint(buffer, len);
  271. if(len == -1){
  272. luaL_error(L, "error data %s, len:%d", buffer, len);
  273. }else{
  274. lua_pushlstring(L, buffer, len);
  275. lua_pushinteger(L, len + pos);
  276. }
  277. return 2;
  278. }
  279. static const uint8_t* unpack_fixed32(const uint8_t* buffer, uint8_t* cache)
  280. {
  281. #ifdef IS_LITTLE_ENDIAN
  282. return buffer;
  283. #else
  284. *(uint32_t*)cache = le32toh(*(uint32_t*)buffer);
  285. return cache;
  286. #endif
  287. }
  288. static const uint8_t* unpack_fixed64(const uint8_t* buffer, uint8_t* cache)
  289. {
  290. #ifdef IS_LITTLE_ENDIAN
  291. return buffer;
  292. #else
  293. *(uint64_t*)cache = le64toh(*(uint64_t*)buffer);
  294. return cache;
  295. #endif
  296. }
  297. static int struct_unpack(lua_State *L)
  298. {
  299. uint8_t format = luaL_checkinteger(L, 1);
  300. size_t len;
  301. const uint8_t* buffer = (uint8_t*)luaL_checklstring(L, 2, &len);
  302. size_t pos = luaL_checkinteger(L, 3);
  303. buffer += pos;
  304. uint8_t out[8];
  305. switch(format){
  306. case 'i':
  307. {
  308. lua_pushinteger(L, *(int32_t*)unpack_fixed32(buffer, out));
  309. break;
  310. }
  311. case 'q':
  312. {
  313. lua_pushnumber(L, (lua_Number)*(int64_t*)unpack_fixed64(buffer, out));
  314. break;
  315. }
  316. case 'f':
  317. {
  318. lua_pushnumber(L, (lua_Number)*(float*)unpack_fixed32(buffer, out));
  319. break;
  320. }
  321. case 'd':
  322. {
  323. lua_pushnumber(L, (lua_Number)*(double*)unpack_fixed64(buffer, out));
  324. break;
  325. }
  326. case 'I':
  327. {
  328. lua_pushnumber(L, *(uint32_t*)unpack_fixed32(buffer, out));
  329. break;
  330. }
  331. case 'Q':
  332. {
  333. lua_pushnumber(L, (lua_Number)*(uint64_t*)unpack_fixed64(buffer, out));
  334. break;
  335. }
  336. default:
  337. luaL_error(L, "Unknown, format");
  338. }
  339. return 1;
  340. }
  341. static int iostring_new(lua_State* L)
  342. {
  343. IOString* io = (IOString*)lua_newuserdata(L, sizeof(IOString));
  344. io->size = 0;
  345. luaL_getmetatable(L, IOSTRING_META);
  346. lua_setmetatable(L, -2);
  347. return 1;
  348. }
  349. static int iostring_str(lua_State* L)
  350. {
  351. IOString *io = checkiostring(L);
  352. lua_pushlstring(L, io->buf, io->size);
  353. return 1;
  354. }
  355. static int iostring_len(lua_State* L)
  356. {
  357. IOString *io = checkiostring(L);
  358. lua_pushinteger(L, io->size);
  359. return 1;
  360. }
  361. static int iostring_write(lua_State* L)
  362. {
  363. IOString *io = checkiostring(L);
  364. size_t size;
  365. const char* str = luaL_checklstring(L, 2, &size);
  366. if(io->size + size > IOSTRING_BUF_LEN){
  367. luaL_error(L, "Out of range");
  368. }
  369. memcpy(io->buf + io->size, str, size);
  370. io->size += size;
  371. return 0;
  372. }
  373. static int iostring_sub(lua_State* L)
  374. {
  375. IOString *io = checkiostring(L);
  376. size_t begin = luaL_checkinteger(L, 2);
  377. size_t end = luaL_checkinteger(L, 3);
  378. if(begin > end || end > io->size)
  379. {
  380. luaL_error(L, "Out of range");
  381. }
  382. lua_pushlstring(L, io->buf + begin - 1, end - begin + 1);
  383. return 1;
  384. }
  385. static int iostring_clear(lua_State* L)
  386. {
  387. IOString *io = checkiostring(L);
  388. io->size = 0;
  389. return 0;
  390. }
  391. static const struct luaL_reg _pb [] = {
  392. {"varint_encoder", varint_encoder},
  393. {"signed_varint_encoder", signed_varint_encoder},
  394. {"read_tag", read_tag},
  395. {"struct_pack", struct_pack},
  396. {"struct_unpack", struct_unpack},
  397. {"varint_decoder", varint_decoder},
  398. {"signed_varint_decoder", signed_varint_decoder},
  399. {"zig_zag_decode32", zig_zag_decode32},
  400. {"zig_zag_encode32", zig_zag_encode32},
  401. {"zig_zag_decode64", zig_zag_decode64},
  402. {"zig_zag_encode64", zig_zag_encode64},
  403. {"new_iostring", iostring_new},
  404. {NULL, NULL}
  405. };
  406. static const struct luaL_reg _c_iostring_m [] = {
  407. {"__tostring", iostring_str},
  408. {"__len", iostring_len},
  409. {"write", iostring_write},
  410. {"sub", iostring_sub},
  411. {"clear", iostring_clear},
  412. {NULL, NULL}
  413. };
  414. int luaopen_pb (lua_State *L)
  415. {
  416. luaL_newmetatable(L, IOSTRING_META);
  417. lua_pushvalue(L, -1);
  418. lua_setfield(L, -2, "__index");
  419. luaL_register(L, NULL, _c_iostring_m);
  420. luaL_register(L, "pb", _pb);
  421. return 1;
  422. }