DCCL v4
pb.c
1 #ifdef _MSC_VER
2 # define _CRT_SECURE_NO_WARNINGS
3 # define _CRT_NONSTDC_NO_WARNINGS
4 # pragma warning(disable: 4244) /* int -> char */
5 # pragma warning(disable: 4706) /* = in if condition */
6 # pragma warning(disable: 4709) /* comma in array index */
7 # pragma warning(disable: 4127) /* const in if condition */
8 #endif
9 
10 #define PB_STATIC_API
11 #include "pb.h"
12 
13 PB_NS_BEGIN
14 
15 
16 #define LUA_LIB
17 #include <lua.h>
18 #include <lauxlib.h>
19 
20 
21 #include <stdio.h>
22 #include <errno.h>
23 
24 
25 /* Lua util routines */
26 
27 #define PB_STATE "pb.State"
28 #define PB_BUFFER "pb.Buffer"
29 #define PB_SLICE "pb.Slice"
30 
31 #define check_buffer(L,idx) ((pb_Buffer*)luaL_checkudata(L,idx,PB_BUFFER))
32 #define test_buffer(L,idx) ((pb_Buffer*)luaL_testudata(L,idx,PB_BUFFER))
33 #define check_slice(L,idx) ((pb_Slice*)luaL_checkudata(L,idx,PB_SLICE))
34 #define test_slice(L,idx) ((pb_Slice*)luaL_testudata(L,idx,PB_SLICE))
35 #define push_slice(L,s) lua_pushlstring((L), (s).p, pb_len((s)))
36 #define lpb_returnself(L) { return lua_settop(L, 1), 1; }
37 
38 static int lpb_relindex(int idx, int offset) {
39  return idx < 0 && idx > LUA_REGISTRYINDEX ? idx - offset : idx;
40 }
41 
42 static size_t lpb_checkmem(lua_State *L, size_t ret)
43 { return ret ? ret : (size_t)luaL_error(L, "out of memory"); }
44 
45 #if LUA_VERSION_NUM < 502
46 #include <assert.h>
47 
48 # define LUA_OK 0
49 # define lua_rawlen lua_objlen
50 # define luaL_setfuncs(L,l,n) (assert(n==0), luaL_register(L,NULL,l))
51 # define luaL_setmetatable(L, name) \
52  (luaL_getmetatable((L), (name)), lua_setmetatable(L, -2))
53 
54 static void lua_rawgetp(lua_State *L, int idx, const void *p) {
55  lua_pushlightuserdata(L, (void*)p);
56  lua_rawget(L, lpb_relindex(idx, 1));
57 }
58 
59 static void lua_rawsetp(lua_State *L, int idx, const void *p) {
60  lua_pushlightuserdata(L, (void*)p);
61  lua_insert(L, -2);
62  lua_rawset(L, lpb_relindex(idx, 1));
63 }
64 
65 #ifndef LUA_GCISRUNNING /* not LuaJIT 2.1 */
66 #define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l))
67 
68 static lua_Integer lua_tointegerx(lua_State *L, int idx, int *isint) {
69  lua_Integer i = lua_tointeger(L, idx);
70  if (isint) *isint = (i != 0 || lua_type(L, idx) == LUA_TNUMBER);
71  return i;
72 }
73 
74 static lua_Number lua_tonumberx(lua_State *L, int idx, int *isnum) {
75  lua_Number i = lua_tonumber(L, idx);
76  if (isnum) *isnum = (i != 0 || lua_type(L, idx) == LUA_TNUMBER);
77  return i;
78 }
79 
80 static void *luaL_testudata(lua_State *L, int idx, const char *type) {
81  void *p = lua_touserdata(L, idx);
82  if (p != NULL && lua_getmetatable(L, idx)) {
83  lua_getfield(L, LUA_REGISTRYINDEX, type);
84  if (!lua_rawequal(L, -2, -1))
85  p = NULL;
86  lua_pop(L, 2);
87  return p;
88  }
89  return NULL;
90 }
91 
92 #endif
93 
94 #ifdef LUAI_BITSINT /* not LuaJIT */
95 #include <errno.h>
96 
97 static int luaL_fileresult(lua_State *L, int stat, const char *fname) {
98  int en = errno;
99  if (stat) return lua_pushboolean(L, 1), 1;
100  lua_pushnil(L);
101  lua_pushfstring(L, "%s: %s", fname, strerror(en));
102  /*if (fname) lua_pushfstring(L, "%s: %s", fname, strerror(en));
103  else lua_pushstring(L, strerror(en));*//* NOT USED */
104  lua_pushinteger(L, en);
105  return 3;
106 }
107 
108 #endif /* not LuaJIT */
109 
110 #endif
111 
112 #if LUA_VERSION_NUM >= 503
113 # define lua53_getfield lua_getfield
114 # define lua53_rawgeti lua_rawgeti
115 # define lua53_rawgetp lua_rawgetp
116 #else /* not Lua 5.3 */
117 static int lua53_getfield(lua_State *L, int idx, const char *field)
118 { return lua_getfield(L, idx, field), lua_type(L, -1); }
119 static int lua53_rawgeti(lua_State *L, int idx, lua_Integer i)
120 { return lua_rawgeti(L, idx, i), lua_type(L, -1); }
121 static int lua53_rawgetp(lua_State *L, int idx, const void *p)
122 { return lua_rawgetp(L, idx, p), lua_type(L, -1); }
123 #endif
124 
125 
126 /* protobuf global state */
127 
128 #define lpbS_state(LS) ((LS)->state)
129 #define lpb_name(LS,s) pb_name(lpbS_state(LS), (s), &(LS)->cache)
130 
131 static const pb_State *global_state = NULL;
132 static const char state_name[] = PB_STATE;
133 
134 enum lpb_Int64Mode { LPB_NUMBER, LPB_STRING, LPB_HEXSTRING };
135 enum lpb_EncodeMode { LPB_DEFDEF, LPB_COPYDEF, LPB_METADEF, LPB_NODEF };
136 
137 typedef struct lpb_State {
138  const pb_State *state;
139  pb_State local;
140  pb_Cache cache;
141  pb_Buffer buffer;
142  pb_Type array_type;
143  pb_Type map_type;
144  int defs_index;
145  int enc_hooks_index;
146  int dec_hooks_index;
147  unsigned use_dec_hooks : 1;
148  unsigned use_enc_hooks : 1;
149  unsigned enum_as_value : 1;
150  unsigned encode_mode : 2; /* lpb_EncodeMode */
151  unsigned int64_mode : 2; /* lpb_Int64Mode */
152  unsigned encode_default_values : 1;
153  unsigned decode_default_array : 1;
154  unsigned decode_default_message : 1;
155  unsigned encode_order : 1;
156 } lpb_State;
157 
158 static int lpb_reftable(lua_State *L, int ref) {
159  if (ref != LUA_NOREF) {
160  lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
161  return ref;
162  } else {
163  lua_newtable(L);
164  lua_pushvalue(L, -1);
165  return luaL_ref(L, LUA_REGISTRYINDEX);
166  }
167 }
168 
169 static void lpb_pushdeftable(lua_State *L, lpb_State *LS)
170 { LS->defs_index = lpb_reftable(L, LS->defs_index); }
171 
172 static void lpb_pushenchooktable(lua_State *L, lpb_State *LS)
173 { LS->enc_hooks_index = lpb_reftable(L, LS->enc_hooks_index); }
174 
175 static void lpb_pushdechooktable(lua_State *L, lpb_State *LS)
176 { LS->dec_hooks_index = lpb_reftable(L, LS->dec_hooks_index); }
177 
178 static int Lpb_delete(lua_State *L) {
179  lpb_State *LS = (lpb_State*)luaL_testudata(L, 1, PB_STATE);
180  if (LS != NULL) {
181  const pb_State *GS = global_state;
182  pb_free(&LS->local);
183  if (&LS->local == GS)
184  global_state = NULL;
185  LS->state = NULL;
186  pb_resetbuffer(&LS->buffer);
187  luaL_unref(L, LUA_REGISTRYINDEX, LS->defs_index);
188  luaL_unref(L, LUA_REGISTRYINDEX, LS->enc_hooks_index);
189  luaL_unref(L, LUA_REGISTRYINDEX, LS->dec_hooks_index);
190  }
191  return 0;
192 }
193 
194 LUALIB_API lpb_State *lpb_lstate(lua_State *L) {
195  lpb_State *LS;
196  if (lua53_rawgetp(L, LUA_REGISTRYINDEX, state_name) == LUA_TUSERDATA) {
197  LS = (lpb_State*)lua_touserdata(L, -1);
198  lua_pop(L, 1);
199  } else {
200  lua_pop(L, 1);
201  LS = (lpb_State*)lua_newuserdata(L, sizeof(lpb_State));
202  memset(LS, 0, sizeof(lpb_State));
203  LS->array_type.is_dead = LS->map_type.is_dead = 1;
204  LS->defs_index = LUA_NOREF;
205  LS->enc_hooks_index = LUA_NOREF;
206  LS->dec_hooks_index = LUA_NOREF;
207  LS->state = &LS->local;
208  pb_init(&LS->local);
209  pb_initbuffer(&LS->buffer);
210  luaL_setmetatable(L, PB_STATE);
211  lua_rawsetp(L, LUA_REGISTRYINDEX, state_name);
212  }
213  return LS;
214 }
215 
216 static int Lpb_state(lua_State *L) {
217  int top = lua_gettop(L);
218  lpb_lstate(L);
219  lua_rawgetp(L, LUA_REGISTRYINDEX, state_name);
220  if (top != 0) {
221  if (lua_isnil(L, 1))
222  lua_pushnil(L);
223  else {
224  luaL_checkudata(L, 1, PB_STATE);
225  lua_pushvalue(L, 1);
226  }
227  lua_rawsetp(L, LUA_REGISTRYINDEX, state_name);
228  }
229  return 1;
230 }
231 
232 
233 /* protobuf util routines */
234 
235 static size_t lpb_addlength(lua_State *L, pb_Buffer *b, size_t len, size_t prealloc) {
236  size_t wlen = pb_addlength(b, len, prealloc);
237  return wlen ? wlen : (size_t)luaL_error(L, "encode bytes fail");
238 }
239 
240 static int lpb_typeerror(lua_State *L, int idx, const char *type) {
241  lua_pushfstring(L, "%s expected, got %s", type, luaL_typename(L, idx));
242  return luaL_argerror(L, idx, lua_tostring(L, -1));
243 }
244 
245 static lua_Integer lpb_posrelat(lua_Integer pos, size_t len) {
246  if (pos >= 0) return pos;
247  else if (0u - (size_t)pos > len) return 0;
248  else return (lua_Integer)len + pos + 1;
249 }
250 
251 static lua_Integer rangerelat(lua_State *L, int idx, lua_Integer r[2], size_t len) {
252  r[0] = lpb_posrelat(luaL_optinteger(L, idx, 1), len);
253  r[1] = lpb_posrelat(luaL_optinteger(L, idx+1, len), len);
254  if (r[0] < 1) r[0] = 1;
255  if (r[1] > (lua_Integer)len) r[1] = len;
256  return r[0] <= r[1] ? r[1] - r[0] + 1 : 0;
257 }
258 
259 static int argcheck(lua_State *L, int cond, int idx, const char *fmt, ...) {
260  if (!cond) {
261  va_list l;
262  va_start(l, fmt);
263  lua_pushvfstring(L, fmt, l);
264  va_end(l);
265  return luaL_argerror(L, idx, lua_tostring(L, -1));
266  }
267  return 1;
268 }
269 
270 static pb_Slice lpb_toslice(lua_State *L, int idx) {
271  int type = lua_type(L, idx);
272  if (type == LUA_TSTRING) {
273  size_t len;
274  const char *s = lua_tolstring(L, idx, &len);
275  return pb_lslice(s, len);
276  } else if (type == LUA_TUSERDATA) {
277  pb_Buffer *buffer;
278  pb_Slice *s;
279  if ((buffer = test_buffer(L, idx)) != NULL)
280  return pb_result(buffer);
281  else if ((s = test_slice(L, idx)) != NULL)
282  return *s;
283  }
284  return pb_slice(NULL);
285 }
286 
287 LUALIB_API pb_Slice lpb_checkslice(lua_State *L, int idx) {
288  pb_Slice ret = lpb_toslice(L, idx);
289  if (ret.p == NULL) lpb_typeerror(L, idx, "string/buffer/slice");
290  return ret;
291 }
292 
293 static void lpb_readbytes(lua_State *L, pb_Slice *s, pb_Slice *pv) {
294  uint64_t len = 0;
295  if (pb_readvarint64(s, &len) == 0 || len > PB_MAX_SIZET)
296  luaL_error(L, "invalid bytes length: %d (at offset %d)",
297  (int)len, pb_pos(*s)+1);
298  if (pb_readslice(s, (size_t)len, pv) == 0 && len != 0)
299  luaL_error(L, "unfinished bytes (len %d at offset %d)",
300  (int)len, pb_pos(*s)+1);
301 }
302 
303 static int lpb_hexchar(char ch) {
304  switch (ch) {
305  case '0': return 0;
306  case '1': return 1; case '2': return 2; case '3': return 3;
307  case '4': return 4; case '5': return 5; case '6': return 6;
308  case '7': return 7; case '8': return 8; case '9': return 9;
309  case 'a': case 'A': return 10; case 'b': case 'B': return 11;
310  case 'c': case 'C': return 12; case 'd': case 'D': return 13;
311  case 'e': case 'E': return 14; case 'f': case 'F': return 15;
312  }
313  return -1;
314 }
315 
316 static uint64_t lpb_tointegerx(lua_State *L, int idx, int *isint) {
317  int neg = 0;
318  const char *s, *os;
319 #if LUA_VERSION_NUM >= 503
320  uint64_t v = (uint64_t)lua_tointegerx(L, idx, isint);
321  if (*isint) return v;
322 #else
323  uint64_t v = 0;
324  lua_Number nv = lua_tonumberx(L, idx, isint);
325  if (*isint) {
326  if (nv < (lua_Number)INT64_MIN || nv > (lua_Number)INT64_MAX)
327  luaL_error(L, "number has no integer representation");
328  return (uint64_t)(int64_t)nv;
329  }
330 #endif
331  if ((os = s = lua_tostring(L, idx)) == NULL) return 0;
332  while (*s == '#' || *s == '+' || *s == '-')
333  neg = (*s == '-') ^ neg, ++s;
334  if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
335  for (s += 2; *s != '\0'; ++s) {
336  int n = lpb_hexchar(*s);
337  if (n < 0) break;
338  v = v << 4 | n;
339  }
340  } else {
341  for (; *s != '\0'; ++s) {
342  int n = lpb_hexchar(*s);
343  if (n < 0 || n > 10) break;
344  v = v * 10 + n;
345  }
346  }
347  if (!(*isint = *s == '\0')) return 0;
348  return neg ? ~v + 1 : v;
349 }
350 
351 static uint64_t lpb_checkinteger(lua_State *L, int idx) {
352  int isint;
353  uint64_t v = lpb_tointegerx(L, idx, &isint);
354  if (!isint) {
355  if (lua_type(L, idx) == LUA_TSTRING)
356  luaL_error(L, "integer format error: '%s'", lua_tostring(L, idx));
357  lpb_typeerror(L, idx, "number/string");
358  }
359  return v;
360 }
361 
362 static void lpb_pushinteger(lua_State *L, int64_t n, int u, int mode) {
363  if (mode != LPB_NUMBER && ((u && n < 0) || n < INT_MIN || n > UINT_MAX)) {
364  char buff[32], *p = buff + sizeof(buff) - 1;
365  int neg = !u && n < 0;
366  uint64_t un = !u && neg ? ~(uint64_t)n + 1 : (uint64_t)n;
367  if (mode == LPB_STRING) {
368  for (*p = '\0'; un > 0; un /= 10)
369  *--p = "0123456789"[un % 10];
370  } else if (mode == LPB_HEXSTRING) {
371  for (*p = '\0'; un > 0; un >>= 4)
372  *--p = "0123456789ABCDEF"[un & 0xF];
373  *--p = 'x', *--p = '0';
374  }
375  if (neg) *--p = '-';
376  *--p = '#';
377  lua_pushstring(L, p);
378  } else if (LUA_VERSION_NUM >= 503 && sizeof(lua_Integer) >= 8)
379  lua_pushinteger(L, (lua_Integer)n);
380  else
381  lua_pushnumber(L, (lua_Number)n);
382 }
383 
384 typedef union lpb_Value {
385  pb_Slice s[1];
386  uint32_t u32;
387  uint64_t u64;
388  lua_Integer lint;
389  lua_Number lnum;
390 } lpb_Value;
391 
392 static const char *lpb_expected(int type) {
393  switch (type) {
394  case PB_Tbool: case PB_Tdouble: case PB_Tfloat:
395  case PB_Tfixed32: case PB_Tsfixed32: case PB_Tint32:
396  case PB_Tuint32: case PB_Tsint32: case PB_Tfixed64:
397  case PB_Tsfixed64: case PB_Tint64: case PB_Tuint64:
398  case PB_Tsint64: case PB_Tenum:
399  return "number/'#number'";
400  case PB_Tbytes: case PB_Tstring: case PB_Tmessage:
401  return "string";
402  }
403  return "unknown";
404 }
405 
406 static size_t lpb_addtype(lua_State *L, pb_Buffer *b, int idx, int type, int *pexist) {
407  int ret = 0, has_data = 1;
408  lpb_Value v;
409  size_t len = 0;
410  switch (type) {
411  case PB_Tbool:
412  len = pb_addvarint32(b, ret = lua_toboolean(L, idx));
413  ret = 1;
414  break;
415  case PB_Tdouble:
416  v.lnum = lua_tonumberx(L, idx, &ret);
417  if (ret) len = pb_addfixed64(b, pb_encode_double((double)v.lnum));
418  if (v.lnum == 0.0) has_data = 0;
419  break;
420  case PB_Tfloat:
421  v.lnum = lua_tonumberx(L, idx, &ret);
422  if (ret) len = pb_addfixed32(b, pb_encode_float((float)v.lnum));
423  if (v.lnum == 0.0) has_data = 0;
424  break;
425  case PB_Tfixed32:
426  v.u64 = lpb_tointegerx(L, idx, &ret);
427  if (ret) len = pb_addfixed32(b, v.u32);
428  if (v.u64 == 0) has_data = 0;
429  break;
430  case PB_Tsfixed32:
431  v.u64 = lpb_tointegerx(L, idx, &ret);
432  if (ret) len = pb_addfixed32(b, v.u32);
433  if (v.u64 == 0) has_data = 0;
434  break;
435  case PB_Tint32:
436  v.u64 = lpb_tointegerx(L, idx, &ret);
437  if (ret) len = pb_addvarint64(b, pb_expandsig((uint32_t)v.u64));
438  if (v.u64 == 0) has_data = 0;
439  break;
440  case PB_Tuint32:
441  v.u64 = lpb_tointegerx(L, idx, &ret);
442  if (ret) len = pb_addvarint32(b, v.u32);
443  if (v.u64 == 0) has_data = 0;
444  break;
445  case PB_Tsint32:
446  v.u64 = lpb_tointegerx(L, idx, &ret);
447  if (ret) len = pb_addvarint32(b, pb_encode_sint32(v.u32));
448  if (v.u64 == 0) has_data = 0;
449  break;
450  case PB_Tfixed64:
451  v.u64 = lpb_tointegerx(L, idx, &ret);
452  if (ret) len = pb_addfixed64(b, v.u64);
453  if (v.u64 == 0) has_data = 0;
454  break;
455  case PB_Tsfixed64:
456  v.u64 = lpb_tointegerx(L, idx, &ret);
457  if (ret) len = pb_addfixed64(b, v.u64);
458  if (v.u64 == 0) has_data = 0;
459  break;
460  case PB_Tint64: case PB_Tuint64:
461  v.u64 = lpb_tointegerx(L, idx, &ret);
462  if (ret) len = pb_addvarint64(b, v.u64);
463  if (v.u64 == 0) has_data = 0;
464  break;
465  case PB_Tsint64:
466  v.u64 = lpb_tointegerx(L, idx, &ret);
467  if (ret) len = pb_addvarint64(b, pb_encode_sint64(v.u64));
468  if (v.u64 == 0) has_data = 0;
469  break;
470  case PB_Tbytes: case PB_Tstring:
471  *v.s = lpb_toslice(L, idx);
472  if ((ret = (v.s->p != NULL))) len = pb_addbytes(b, *v.s);
473  if (pb_len(*v.s) == 0) has_data = 0;
474  break;
475  default:
476  lua_pushfstring(L, "unknown type %s", pb_typename(type, "<unknown>"));
477  if (idx > 0) luaL_argerror(L, idx, lua_tostring(L, -1));
478  lua_error(L);
479  }
480  if (pexist) *pexist = (ret && has_data);
481  return ret ? lpb_checkmem(L, len) : 0;
482 }
483 
484 static void lpb_readtype(lua_State *L, lpb_State *LS, int type, pb_Slice *s) {
485  lpb_Value v;
486  switch (type) {
487 #define pushinteger(n,u) lpb_pushinteger((L), (n), (u), LS->int64_mode)
488  case PB_Tbool: case PB_Tenum:
489  case PB_Tint32: case PB_Tuint32: case PB_Tsint32:
490  case PB_Tint64: case PB_Tuint64: case PB_Tsint64:
491  if (pb_readvarint64(s, &v.u64) == 0)
492  luaL_error(L, "invalid varint value at offset %d", pb_pos(*s)+1);
493  switch (type) {
494  case PB_Tbool: lua_pushboolean(L, v.u64 != 0); break;
495  /*case PB_Tenum: pushinteger(v.u64); break; [> NOT REACHED <]*/
496  case PB_Tint32: pushinteger((int32_t)v.u64, 0); break;
497  case PB_Tuint32: pushinteger((uint32_t)v.u64, 1); break;
498  case PB_Tsint32: pushinteger(pb_decode_sint32((uint32_t)v.u64), 0); break;
499  case PB_Tint64: pushinteger((int64_t)v.u64, 0); break;
500  case PB_Tuint64: pushinteger((uint64_t)v.u64, 1); break;
501  case PB_Tsint64: pushinteger(pb_decode_sint64(v.u64), 0); break;
502  }
503  break;
504  case PB_Tfloat:
505  case PB_Tfixed32:
506  case PB_Tsfixed32:
507  if (pb_readfixed32(s, &v.u32) == 0)
508  luaL_error(L, "invalid fixed32 value at offset %d", pb_pos(*s)+1);
509  switch (type) {
510  case PB_Tfloat: lua_pushnumber(L, pb_decode_float(v.u32)); break;
511  case PB_Tfixed32: pushinteger(v.u32, 1); break;
512  case PB_Tsfixed32: pushinteger((int32_t)v.u32, 0); break;
513  }
514  break;
515  case PB_Tdouble:
516  case PB_Tfixed64:
517  case PB_Tsfixed64:
518  if (pb_readfixed64(s, &v.u64) == 0)
519  luaL_error(L, "invalid fixed64 value at offset %d", pb_pos(*s)+1);
520  switch (type) {
521  case PB_Tdouble: lua_pushnumber(L, pb_decode_double(v.u64)); break;
522  case PB_Tfixed64: pushinteger(v.u64, 1); break;
523  case PB_Tsfixed64: pushinteger((int64_t)v.u64, 0); break;
524  }
525  break;
526  case PB_Tbytes:
527  case PB_Tstring:
528  case PB_Tmessage:
529  lpb_readbytes(L, s, v.s);
530  push_slice(L, *v.s);
531  break;
532  default:
533  luaL_error(L, "unknown type %s (%d)", pb_typename(type, NULL), type);
534  }
535 }
536 
537 
538 /* io routines */
539 
540 #ifdef _WIN32
541 # include <io.h>
542 # include <fcntl.h>
543 #else
544 # define setmode(a,b) ((void)0)
545 #endif
546 
547 static int lpbF_read(lua_State *L) {
548  FILE *fp = (FILE*)lua_touserdata(L, 1);
549  size_t nr;
550  luaL_Buffer b;
551  luaL_buffinit(L, &b);
552  do { /* read file in chunks of LUAL_BUFFERSIZE bytes */
553  char *p = luaL_prepbuffer(&b);
554  nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, fp);
555  luaL_addsize(&b, nr);
556  } while (nr == LUAL_BUFFERSIZE);
557  luaL_pushresult(&b); /* close buffer */
558  return 1;
559 }
560 
561 static int lpbF_write(lua_State *L, FILE *f, int idx) {
562  int nargs = lua_gettop(L) - idx + 1;
563  int status = 1;
564  for (; nargs--; idx++) {
565  pb_Slice s = lpb_checkslice(L, idx);
566  size_t l = pb_len(s);
567  status = status && (fwrite(s.p, sizeof(char), l, f) == l);
568  }
569  return status ? 1 : luaL_fileresult(L, 0, NULL);
570 }
571 
572 static int Lio_read(lua_State *L) {
573  const char *fname = luaL_optstring(L, 1, NULL);
574  FILE *fp = stdin;
575  int ret;
576  if (fname == NULL)
577  (void)setmode(fileno(stdin), O_BINARY);
578  else if ((fp = fopen(fname, "rb")) == NULL)
579  return luaL_fileresult(L, 0, fname);
580  lua_pushcfunction(L, lpbF_read);
581  lua_pushlightuserdata(L, fp);
582  ret = lua_pcall(L, 1, 1, 0);
583  if (fp != stdin) fclose(fp);
584  else (void)setmode(fileno(stdin), O_TEXT);
585  if (ret != LUA_OK) { lua_pushnil(L); lua_insert(L, -2); return 2; }
586  return 1;
587 }
588 
589 static int Lio_write(lua_State *L) {
590  int res;
591  (void)setmode(fileno(stdout), O_BINARY);
592  res = lpbF_write(L, stdout, 1);
593  fflush(stdout);
594  (void)setmode(fileno(stdout), O_TEXT);
595  return res;
596 }
597 
598 static int Lio_dump(lua_State *L) {
599  int res;
600  const char *fname = luaL_checkstring(L, 1);
601  FILE *fp = fopen(fname, "wb");
602  if (fp == NULL) return luaL_fileresult(L, 0, fname);
603  res = lpbF_write(L, fp, 2);
604  fclose(fp);
605  return res;
606 }
607 
608 LUALIB_API int luaopen_pb_io(lua_State *L) {
609  luaL_Reg libs[] = {
610 #define ENTRY(name) { #name, Lio_##name }
611  ENTRY(read),
612  ENTRY(write),
613  ENTRY(dump),
614 #undef ENTRY
615  { NULL, NULL }
616  };
617  luaL_newlib(L, libs);
618  return 1;
619 }
620 
621 
622 /* protobuf integer conversion */
623 
624 static int Lconv_encode_int32(lua_State *L) {
625  uint64_t v = pb_expandsig((int32_t)lpb_checkinteger(L, 1));
626  return lpb_pushinteger(L, v, 1, lpb_lstate(L)->int64_mode), 1;
627 }
628 
629 static int Lconv_encode_uint32(lua_State *L) {
630  return lpb_pushinteger(L, (uint32_t)lpb_checkinteger(L, 1),
631  1, lpb_lstate(L)->int64_mode), 1;
632 }
633 
634 static int Lconv_encode_sint32(lua_State *L) {
635  return lpb_pushinteger(L, pb_encode_sint32((int32_t)lpb_checkinteger(L, 1)),
636  1, lpb_lstate(L)->int64_mode), 1;
637 }
638 
639 static int Lconv_decode_sint32(lua_State *L) {
640  return lpb_pushinteger(L, pb_decode_sint32((uint32_t)lpb_checkinteger(L, 1)),
641  0, lpb_lstate(L)->int64_mode), 1;
642 }
643 
644 static int Lconv_encode_sint64(lua_State *L) {
645  return lpb_pushinteger(L, pb_encode_sint64(lpb_checkinteger(L, 1)),
646  1, lpb_lstate(L)->int64_mode), 1;
647 }
648 
649 static int Lconv_decode_sint64(lua_State *L) {
650  return lpb_pushinteger(L, pb_decode_sint64(lpb_checkinteger(L, 1)),
651  0, lpb_lstate(L)->int64_mode), 1;
652 }
653 
654 static int Lconv_encode_float(lua_State *L) {
655  return lpb_pushinteger(L, pb_encode_float((float)luaL_checknumber(L, 1)),
656  1, lpb_lstate(L)->int64_mode), 1;
657 }
658 
659 static int Lconv_decode_float(lua_State *L) {
660  return lua_pushnumber(L,
661  pb_decode_float((uint32_t)lpb_checkinteger(L, 1))), 1;
662 }
663 
664 static int Lconv_encode_double(lua_State *L) {
665  return lpb_pushinteger(L, pb_encode_double(luaL_checknumber(L, 1)),
666  1, lpb_lstate(L)->int64_mode), 1;
667 }
668 
669 static int Lconv_decode_double(lua_State *L) {
670  return lua_pushnumber(L, pb_decode_double(lpb_checkinteger(L, 1))), 1;
671 }
672 
673 LUALIB_API int luaopen_pb_conv(lua_State *L) {
674  luaL_Reg libs[] = {
675  { "decode_uint32", Lconv_encode_uint32 },
676  { "decode_int32", Lconv_encode_int32 },
677 #define ENTRY(name) { #name, Lconv_##name }
678  ENTRY(encode_int32),
679  ENTRY(encode_uint32),
680  ENTRY(encode_sint32),
681  ENTRY(encode_sint64),
682  ENTRY(decode_sint32),
683  ENTRY(decode_sint64),
684  ENTRY(decode_float),
685  ENTRY(decode_double),
686  ENTRY(encode_float),
687  ENTRY(encode_double),
688 #undef ENTRY
689  { NULL, NULL }
690  };
691  luaL_newlib(L, libs);
692  return 1;
693 }
694 
695 
696 /* protobuf encode routine */
697 
698 static int lpb_typefmt(int fmt) {
699  switch (fmt) {
700 #define X(name,type,fmt) case fmt: return PB_T##name;
701  PB_TYPES(X)
702 #undef X
703  }
704  return -1;
705 }
706 
707 static int lpb_packfmt(lua_State *L, int idx, pb_Buffer *b, const char **pfmt, int level) {
708  const char *fmt = *pfmt;
709  size_t len;
710  int type;
711  luaL_argcheck(L, level <= 100, 1, "format level overflow");
712  for (; *fmt != '\0'; ++fmt) {
713  switch (*fmt) {
714  case '#':
715  len = lpb_addlength(L, b, (size_t)lpb_checkinteger(L, idx++), 0);
716  break;
717  case 'v':
718  len = pb_addvarint64(b, (uint64_t)lpb_checkinteger(L, idx++));
719  break;
720  case 'd':
721  len = pb_addfixed32(b, (uint32_t)lpb_checkinteger(L, idx++));
722  break;
723  case 'q':
724  len = pb_addfixed64(b, (uint64_t)lpb_checkinteger(L, idx++));
725  break;
726  case 'c': len = pb_addslice(b, lpb_checkslice(L, idx++)); break;
727  case 's': len = pb_addbytes(b, lpb_checkslice(L, idx++)); break;
728  case '(':
729  if ((len = pb_addvarint32(b, 0)) == 0) break;
730  len = pb_bufflen(b);
731  ++fmt;
732  idx = lpb_packfmt(L, idx, b, &fmt, level+1);
733  len = lpb_addlength(L, b, len, 1);
734  break;
735  case ')':
736  if (level == 0) luaL_argerror(L, 1, "unexpected ')' in format");
737  *pfmt = fmt;
738  return idx;
739  case '\0':
740  default:
741  argcheck(L, (type = lpb_typefmt(*fmt)) >= 0,
742  1, "invalid formater: '%c'", *fmt);
743  len = lpb_addtype(L, b, idx, type, NULL);
744  argcheck(L, len > 0, idx, "%s expected for type '%s', got %s",
745  lpb_expected(type), pb_typename(type, "<unknown>"),
746  luaL_typename(L, idx));
747  ++idx;
748  continue;
749  }
750  lpb_checkmem(L, len);
751  }
752  if (level != 0) luaL_argerror(L, 2, "unmatch '(' in format");
753  *pfmt = fmt;
754  return idx;
755 }
756 
757 static int Lpb_tohex(lua_State *L) {
758  pb_Slice s = lpb_checkslice(L, 1);
759  const char *hexa = "0123456789ABCDEF";
760  char hex[4] = "XX ";
761  lua_Integer r[2] = { 1, -1 };
762  luaL_Buffer lb;
763  rangerelat(L, 2, r, pb_len(s));
764  luaL_buffinit(L, &lb);
765  for (; r[0] <= r[1]; ++r[0]) {
766  unsigned int ch = s.p[r[0]-1];
767  hex[0] = hexa[(ch>>4)&0xF];
768  hex[1] = hexa[(ch )&0xF];
769  if (r[0] == r[1]) hex[2] = '\0';
770  luaL_addstring(&lb, hex);
771  }
772  luaL_pushresult(&lb);
773  return 1;
774 }
775 
776 static int Lpb_fromhex(lua_State *L) {
777  pb_Slice s = lpb_checkslice(L, 1);
778  lua_Integer r[2] = { 1, -1 };
779  luaL_Buffer lb;
780  int curr = 0, idx = 0, num;
781  rangerelat(L, 2, r, pb_len(s));
782  luaL_buffinit(L, &lb);
783  for (; r[0] <= r[1]; ++r[0]) {
784  switch (num = s.p[r[0]-1]) {
785  case '0': case '1': case '2': case '3':
786  case '4': case '5': case '6': case '7':
787  case '8': case '9': num -= '0'; break;
788  case 'A': case 'a': num = 10; break;
789  case 'B': case 'b': num = 11; break;
790  case 'C': case 'c': num = 12; break;
791  case 'D': case 'd': num = 13; break;
792  case 'E': case 'e': num = 14; break;
793  case 'F': case 'f': num = 15; break;
794  default: continue;
795  }
796  curr = curr<<4 | num;
797  if (++idx % 2 == 0) luaL_addchar(&lb, curr), curr = 0;
798  }
799  luaL_pushresult(&lb);
800  return 1;
801 }
802 
803 static int Lpb_result(lua_State *L) {
804  pb_Slice s = lpb_checkslice(L, 1);
805  lua_Integer r[2] = {1, -1}, range = rangerelat(L, 2, r, pb_len(s));
806  lua_pushlstring(L, s.p+r[0]-1, (size_t)range);
807  return 1;
808 }
809 
810 static int Lbuf_new(lua_State *L) {
811  int i, top = lua_gettop(L);
812  pb_Buffer *buf = (pb_Buffer*)lua_newuserdata(L, sizeof(pb_Buffer));
813  pb_initbuffer(buf);
814  luaL_setmetatable(L, PB_BUFFER);
815  for (i = 1; i <= top; ++i)
816  lpb_checkmem(L, pb_addslice(buf, lpb_checkslice(L, i)));
817  return 1;
818 }
819 
820 static int Lbuf_delete(lua_State *L) {
821  pb_Buffer *buf = test_buffer(L, 1);
822  if (buf) pb_resetbuffer(buf);
823  return 0;
824 }
825 
826 static int Lbuf_libcall(lua_State *L) {
827  int i, top = lua_gettop(L);
828  pb_Buffer *buf = (pb_Buffer*)lua_newuserdata(L, sizeof(pb_Buffer));
829  pb_initbuffer(buf);
830  luaL_setmetatable(L, PB_BUFFER);
831  for (i = 2; i <= top; ++i)
832  lpb_checkmem(L, pb_addslice(buf, lpb_checkslice(L, i)));
833  return 1;
834 }
835 
836 static int Lbuf_tostring(lua_State *L) {
837  pb_Buffer *buf = check_buffer(L, 1);
838  lua_pushfstring(L, "pb.Buffer: %p", buf);
839  return 1;
840 }
841 
842 static int Lbuf_reset(lua_State *L) {
843  pb_Buffer *buf = check_buffer(L, 1);
844  int i, top = lua_gettop(L);
845  pb_bufflen(buf) = 0;
846  for (i = 2; i <= top; ++i)
847  lpb_checkmem(L, pb_addslice(buf, lpb_checkslice(L, i)));
848  lpb_returnself(L);
849 }
850 
851 static int Lbuf_len(lua_State *L) {
852  pb_Buffer *buf = check_buffer(L, 1);
853  lua_pushinteger(L, (lua_Integer)buf->size);
854  return 1;
855 }
856 
857 static int Lbuf_pack(lua_State *L) {
858  pb_Buffer b, *pb = test_buffer(L, 1);
859  int idx = 1 + (pb != NULL);
860  const char *fmt = luaL_checkstring(L, idx++);
861  if (pb == NULL) pb_initbuffer(pb = &b);
862  lpb_packfmt(L, idx, pb, &fmt, 0);
863  if (pb != &b)
864  lua_settop(L, 1);
865  else {
866  pb_Slice ret = pb_result(pb);
867  push_slice(L, ret);
868  pb_resetbuffer(pb);
869  }
870  return 1;
871 }
872 
873 LUALIB_API int luaopen_pb_buffer(lua_State *L) {
874  luaL_Reg libs[] = {
875  { "__tostring", Lbuf_tostring },
876  { "__len", Lbuf_len },
877  { "__gc", Lbuf_delete },
878  { "delete", Lbuf_delete },
879  { "tohex", Lpb_tohex },
880  { "fromhex", Lpb_fromhex },
881  { "result", Lpb_result },
882 #define ENTRY(name) { #name, Lbuf_##name }
883  ENTRY(new),
884  ENTRY(reset),
885  ENTRY(pack),
886 #undef ENTRY
887  { NULL, NULL }
888  };
889  if (luaL_newmetatable(L, PB_BUFFER)) {
890  luaL_setfuncs(L, libs, 0);
891  lua_pushvalue(L, -1);
892  lua_setfield(L, -2, "__index");
893  lua_createtable(L, 0, 1);
894  lua_pushcfunction(L, Lbuf_libcall);
895  lua_setfield(L, -2, "__call");
896  lua_setmetatable(L, -2);
897  }
898  return 1;
899 }
900 
901 
902 /* protobuf decode routine */
903 
904 #define LPB_INITSTACKLEN 2
905 
906 typedef struct lpb_Slice {
907  pb_Slice curr;
908  pb_Slice *buff;
909  size_t used;
910  size_t size;
911  pb_Slice init_buff[LPB_INITSTACKLEN];
912 } lpb_Slice;
913 
914 static void lpb_resetslice(lua_State *L, lpb_Slice *s, size_t size) {
915  if (size == sizeof(lpb_Slice)) {
916  if (s->buff != s->init_buff) free(s->buff);
917  memset(s, 0, sizeof(lpb_Slice));
918  s->buff = s->init_buff;
919  s->size = LPB_INITSTACKLEN;
920  }
921  lua_pushnil(L);
922  lua_rawsetp(L, LUA_REGISTRYINDEX, s);
923 }
924 
925 static pb_Slice lpb_checkview(lua_State *L, int idx, pb_Slice *ps) {
926  pb_Slice src = lpb_checkslice(L, idx);
927  lua_Integer r[2] = {1, -1}, range = rangerelat(L, idx+1, r, pb_len(src));
928  pb_Slice ret;
929  if (ps) *ps = src, ps->start = src.p;
930  ret.p = src.p + r[0] - 1;
931  ret.end = ret.p + range;
932  ret.start = src.p;
933  return ret;
934 }
935 
936 static void lpb_enterview(lua_State *L, lpb_Slice *s, pb_Slice view) {
937  if (s->used >= s->size) {
938  size_t newsize = s->size * 2;
939  pb_Slice *oldp = s->buff != s->init_buff ? s->buff : NULL;
940  pb_Slice *newp = (pb_Slice*)realloc(oldp, newsize*sizeof(pb_Slice));
941  if (newp == NULL) { luaL_error(L, "out of memory"); return; }
942  if (oldp == NULL) memcpy(newp, s->buff, s->used*sizeof(pb_Slice));
943  s->buff = newp;
944  s->size = newsize;
945  }
946  s->buff[s->used++] = s->curr;
947  s->curr = view;
948 }
949 
950 static void lpb_initslice(lua_State *L, int idx, lpb_Slice *s, size_t size) {
951  if (size == sizeof(lpb_Slice)) {
952  memset(s, 0, sizeof(lpb_Slice));
953  s->buff = s->init_buff;
954  s->size = LPB_INITSTACKLEN;
955  }
956  if (!lua_isnoneornil(L, idx)) {
957  pb_Slice base, view = lpb_checkview(L, idx, &base);
958  s->curr = base;
959  if (size == sizeof(lpb_Slice)) lpb_enterview(L, s, view);
960  lua_pushvalue(L, idx);
961  lua_rawsetp(L, LUA_REGISTRYINDEX, s);
962  }
963 }
964 
965 static int lpb_unpackscalar(lua_State *L, int *pidx, int top, int fmt, pb_Slice *s) {
966  unsigned mode = lpb_lstate(L)->int64_mode;
967  lpb_Value v;
968  switch (fmt) {
969  case 'v':
970  if (pb_readvarint64(s, &v.u64) == 0) return luaL_error(L,
971  "invalid varint value at offset %d", pb_pos(*s)+1);
972  lpb_pushinteger(L, v.u64, 1, mode);
973  break;
974  case 'd':
975  if (pb_readfixed32(s, &v.u32) == 0) return luaL_error(L,
976  "invalid fixed32 value at offset %d", pb_pos(*s)+1);
977  lpb_pushinteger(L, v.u32, 1, mode);
978  break;
979  case 'q':
980  if (pb_readfixed64(s, &v.u64) == 0) return luaL_error(L,
981  "invalid fixed64 value at offset %d", pb_pos(*s)+1);
982  lpb_pushinteger(L, v.u64, 1, mode);
983  break;
984  case 's':
985  if (pb_readbytes(s, v.s) == 0) return luaL_error(L,
986  "invalid bytes value at offset %d", pb_pos(*s)+1);
987  push_slice(L, *v.s);
988  break;
989  case 'c':
990  luaL_argcheck(L, *pidx <= top, 1, "format argument exceed");
991  v.lint = luaL_checkinteger(L, (*pidx)++);
992  if (pb_readslice(s, (size_t)v.lint, v.s) == 0) return luaL_error(L,
993  "invalid sub string at offset %d", pb_pos(*s)+1);
994  push_slice(L, *v.s);
995  break;
996  default:
997  return 0;
998  }
999  return 1;
1000 }
1001 
1002 static int lpb_unpackloc(lua_State *L, int *pidx, int top, int fmt, pb_Slice *s, int *prets) {
1003  lua_Integer li;
1004  size_t len = s->end - s->start;
1005  switch (fmt) {
1006  case '@':
1007  lua_pushinteger(L, pb_pos(*s)+1);
1008  ++*prets;
1009  break;
1010 
1011  case '*': case '+':
1012  luaL_argcheck(L, *pidx <= top, 1, "format argument exceed");
1013  if (fmt == '*')
1014  li = lpb_posrelat(luaL_checkinteger(L, (*pidx)++), len);
1015  else
1016  li = pb_pos(*s) + luaL_checkinteger(L, (*pidx)++) + 1;
1017  if (li == 0) li = 1;
1018  if (li > (lua_Integer)len) li = (lua_Integer)len + 1;
1019  s->p = s->start + li - 1;
1020  break;
1021 
1022  default:
1023  return 0;
1024  }
1025  return 1;
1026 }
1027 
1028 static int lpb_unpackfmt(lua_State *L, int idx, const char *fmt, pb_Slice *s) {
1029  int rets = 0, top = lua_gettop(L), type;
1030  for (; *fmt != '\0'; ++fmt) {
1031  if (lpb_unpackloc(L, &idx, top, *fmt, s, &rets))
1032  continue;
1033  if (s->p >= s->end) return lua_pushnil(L), rets + 1;
1034  luaL_checkstack(L, 5, "too many values");
1035  if (!lpb_unpackscalar(L, &idx, top, *fmt, s)) {
1036  argcheck(L, (type = lpb_typefmt(*fmt)) >= 0,
1037  1, "invalid formater: '%c'", *fmt);
1038  lpb_readtype(L, lpb_lstate(L), type, s);
1039  }
1040  ++rets;
1041  }
1042  return rets;
1043 }
1044 
1045 static lpb_Slice *check_lslice(lua_State *L, int idx) {
1046  pb_Slice *s = check_slice(L, idx);
1047  luaL_argcheck(L, lua_rawlen(L, 1) == sizeof(lpb_Slice),
1048  idx, "unsupport operation for raw mode slice");
1049  return (lpb_Slice*)s;
1050 }
1051 
1052 static int Lslice_new(lua_State *L) {
1053  lpb_Slice *s;
1054  lua_settop(L, 3);
1055  s = (lpb_Slice*)lua_newuserdata(L, sizeof(lpb_Slice));
1056  lpb_initslice(L, 1, s, sizeof(lpb_Slice));
1057  if (s->curr.p == NULL) s->curr = pb_lslice("", 0);
1058  luaL_setmetatable(L, PB_SLICE);
1059  return 1;
1060 }
1061 
1062 static int Lslice_libcall(lua_State *L) {
1063  lpb_Slice *s;
1064  lua_settop(L, 4);
1065  s = (lpb_Slice*)lua_newuserdata(L, sizeof(lpb_Slice));
1066  lpb_initslice(L, 2, s, sizeof(lpb_Slice));
1067  luaL_setmetatable(L, PB_SLICE);
1068  return 1;
1069 }
1070 
1071 static int Lslice_reset(lua_State *L) {
1072  lpb_Slice *s = (lpb_Slice*)check_slice(L, 1);
1073  size_t size = lua_rawlen(L, 1);
1074  lpb_resetslice(L, s, size);
1075  if (!lua_isnoneornil(L, 2))
1076  lpb_initslice(L, 2, s, size);
1077  lpb_returnself(L);
1078 }
1079 
1080 static int Lslice_tostring(lua_State *L) {
1081  pb_Slice *s = check_slice(L, 1);
1082  lua_pushfstring(L, "pb.Slice: %p%s", s,
1083  lua_rawlen(L, 1) == sizeof(lpb_Slice) ? "" : " (raw)");
1084  return 1;
1085 }
1086 
1087 static int Lslice_len(lua_State *L) {
1088  pb_Slice *s = check_slice(L, 1);
1089  lua_pushinteger(L, (lua_Integer)pb_len(*s));
1090  lua_pushinteger(L, (lua_Integer)pb_pos(*s)+1);
1091  return 2;
1092 }
1093 
1094 static int Lslice_unpack(lua_State *L) {
1095  pb_Slice view, *s = test_slice(L, 1);
1096  const char *fmt = luaL_checkstring(L, 2);
1097  if (s == NULL) view = lpb_checkslice(L, 1), s = &view;
1098  return lpb_unpackfmt(L, 3, fmt, s);
1099 }
1100 
1101 static int Lslice_level(lua_State *L) {
1102  lpb_Slice *s = check_lslice(L, 1);
1103  if (!lua_isnoneornil(L, 2)) {
1104  pb_Slice *se;
1105  lua_Integer level = lpb_posrelat(luaL_checkinteger(L, 2), s->used);
1106  if (level > (lua_Integer)s->used)
1107  return 0;
1108  else if (level == (lua_Integer)s->used)
1109  se = &s->curr;
1110  else
1111  se = &s->buff[level];
1112  lua_pushinteger(L, (lua_Integer)(se->p - s->buff[0].start) + 1);
1113  lua_pushinteger(L, (lua_Integer)(se->start - s->buff[0].start) + 1);
1114  lua_pushinteger(L, (lua_Integer)(se->end - s->buff[0].start));
1115  return 3;
1116  }
1117  lua_pushinteger(L, s->used);
1118  return 1;
1119 }
1120 
1121 static int Lslice_enter(lua_State *L) {
1122  lpb_Slice *s = check_lslice(L, 1);
1123  pb_Slice view;
1124  if (lua_isnoneornil(L, 2)) {
1125  argcheck(L, pb_readbytes(&s->curr, &view) != 0,
1126  1, "bytes wireformat expected at offset %d", pb_pos(s->curr)+1);
1127  view.start = view.p;
1128  lpb_enterview(L, s, view);
1129  } else {
1130  lua_Integer r[] = {1, -1};
1131  lua_Integer range = rangerelat(L, 2, r, pb_len(s->curr));
1132  view.p = s->curr.start + r[0] - 1;
1133  view.end = view.p + range;
1134  view.start = s->curr.p;
1135  lpb_enterview(L, s, view);
1136  }
1137  lpb_returnself(L);
1138 }
1139 
1140 static int Lslice_leave(lua_State *L) {
1141  lpb_Slice *s = check_lslice(L, 1);
1142  lua_Integer count = lpb_posrelat(luaL_optinteger(L, 2, 1), s->used);
1143  if (count > (lua_Integer)s->used)
1144  argcheck(L, 0, 2, "level (%d) exceed max level %d",
1145  (int)count, (int)s->used);
1146  else if (count == (lua_Integer)s->used) {
1147  s->curr = s->buff[0];
1148  s->used = 1;
1149  } else {
1150  s->used -= (size_t)count;
1151  s->curr = s->buff[s->used];
1152  }
1153  lua_settop(L, 1);
1154  lua_pushinteger(L, s->used);
1155  return 2;
1156 }
1157 
1158 LUALIB_API int lpb_newslice(lua_State *L, const char *s, size_t len) {
1159  pb_Slice *ls = (pb_Slice*)lua_newuserdata(L, sizeof(pb_Slice));
1160  *ls = pb_lslice(s, len);
1161  luaL_setmetatable(L, PB_SLICE);
1162  return 1;
1163 }
1164 
1165 LUALIB_API int luaopen_pb_slice(lua_State *L) {
1166  luaL_Reg libs[] = {
1167  { "__tostring", Lslice_tostring },
1168  { "__len", Lslice_len },
1169  { "__gc", Lslice_reset },
1170  { "delete", Lslice_reset },
1171  { "tohex", Lpb_tohex },
1172  { "fromhex", Lpb_fromhex },
1173  { "result", Lpb_result },
1174 #define ENTRY(name) { #name, Lslice_##name }
1175  ENTRY(new),
1176  ENTRY(reset),
1177  ENTRY(level),
1178  ENTRY(enter),
1179  ENTRY(leave),
1180  ENTRY(unpack),
1181 #undef ENTRY
1182  { NULL, NULL }
1183  };
1184  if (luaL_newmetatable(L, PB_SLICE)) {
1185  luaL_setfuncs(L, libs, 0);
1186  lua_pushvalue(L, -1);
1187  lua_setfield(L, -2, "__index");
1188  lua_createtable(L, 0, 1);
1189  lua_pushcfunction(L, Lslice_libcall);
1190  lua_setfield(L, -2, "__call");
1191  lua_setmetatable(L, -2);
1192  }
1193  return 1;
1194 }
1195 
1196 
1197 /* high level typeinfo/encode/decode routines */
1198 
1199 typedef enum {USE_FIELD = 1, USE_REPEAT = 2, USE_MESSAGE = 4} lpb_DefFlags;
1200 
1201 static void lpb_pushtypetable(lua_State *L, lpb_State *LS, const pb_Type *t);
1202 static void lpb_pushdefmeta(lua_State *L, lpb_State *LS, const pb_Type *t);
1203 
1204 static void lpb_newmsgtable(lua_State *L, const pb_Type *t) {
1205  int fieldcnt = t->field_count - t->oneof_field + t->oneof_count*2;
1206  lua_createtable(L, 0, fieldcnt > 0 ? fieldcnt : 0);
1207 }
1208 
1209 LUALIB_API const pb_Type *lpb_type(lua_State *L, lpb_State *LS, pb_Slice s) {
1210  const pb_Type *t;
1211  if (s.p == NULL || *s.p == '\0' || *s.p == '.')
1212  t = pb_type(lpbS_state(LS), lpb_name(LS, s));
1213  else {
1214  pb_Buffer b;
1215  pb_initbuffer(&b);
1216  *pb_prepbuffsize(&b, 1) = '.';
1217  pb_addsize(&b, 1);
1218  lpb_checkmem(L, pb_addslice(&b, s));
1219  t = pb_type(lpbS_state(LS), pb_name(lpbS_state(LS),pb_result(&b),NULL));
1220  pb_resetbuffer(&b);
1221  }
1222  return t;
1223 }
1224 
1225 static const pb_Field *lpb_field(lua_State *L, int idx, const pb_Type *t) {
1226  lpb_State *LS = lpb_lstate(L);
1227  int isint, number = (int)lua_tointegerx(L, idx, &isint);
1228  if (isint) return pb_field(t, number);
1229  return pb_fname(t, lpb_name(LS, lpb_checkslice(L, idx)));
1230 }
1231 
1232 static int Lpb_load(lua_State *L) {
1233  lpb_State *LS = lpb_lstate(L);
1234  pb_Slice s = lpb_checkslice(L, 1);
1235  int r = pb_load(&LS->local, &s);
1236  if (r == PB_OK) global_state = &LS->local;
1237  lua_pushboolean(L, r == PB_OK);
1238  lua_pushinteger(L, pb_pos(s)+1);
1239  return 2;
1240 }
1241 
1242 static int Lpb_load_unsafe(lua_State *L) {
1243  lpb_State *LS = lpb_lstate(L);
1244  const char *data = (const char *)lua_touserdata(L, 1);
1245  size_t size = (size_t)luaL_checkinteger(L, 2);
1246  pb_Slice s = pb_lslice(data, size);
1247  int r;
1248  if (data == NULL) lpb_typeerror(L, 1, "userdata");
1249  r = pb_load(&LS->local, &s);
1250  if (r == PB_OK) global_state = &LS->local;
1251  lua_pushboolean(L, r == PB_OK);
1252  lua_pushinteger(L, pb_pos(s)+1);
1253  return 2;
1254 }
1255 
1256 static int Lpb_loadfile(lua_State *L) {
1257  lpb_State *LS = lpb_lstate(L);
1258  const char *filename = luaL_checkstring(L, 1);
1259  size_t size;
1260  pb_Buffer b;
1261  pb_Slice s;
1262  int ret;
1263  FILE *fp = fopen(filename, "rb");
1264  if (fp == NULL)
1265  return luaL_fileresult(L, 0, filename);
1266  pb_initbuffer(&b);
1267  do {
1268  char *d = pb_prepbuffsize(&b, BUFSIZ);
1269  if (d == NULL) return fclose(fp), luaL_error(L, "out of memory");
1270  size = fread(d, 1, BUFSIZ, fp);
1271  pb_addsize(&b, size);
1272  } while (size == BUFSIZ);
1273  fclose(fp);
1274  s = pb_result(&b);
1275  ret = pb_load(&LS->local, &s);
1276  if (ret == PB_OK) global_state = &LS->local;
1277  pb_resetbuffer(&b);
1278  lua_pushboolean(L, ret == PB_OK);
1279  lua_pushinteger(L, pb_pos(s)+1);
1280  return 2;
1281 }
1282 
1283 static int lpb_pushtype(lua_State *L, const pb_Type *t) {
1284  if (t == NULL) return 0;
1285  lua_pushstring(L, (const char*)t->name);
1286  lua_pushstring(L, (const char*)t->basename);
1287  lua_pushstring(L, t->is_map ? "map" : t->is_enum ? "enum" : "message");
1288  return 3;
1289 }
1290 
1291 static int lpb_pushfield(lua_State *L, const pb_Type *t, const pb_Field *f) {
1292  if (f == NULL) return 0;
1293  lua_pushstring(L, (const char*)f->name);
1294  lua_pushinteger(L, f->number);
1295  lua_pushstring(L, f->type ?
1296  (const char*)f->type->name :
1297  pb_typename(f->type_id, "<unknown>"));
1298  lua_pushstring(L, (const char*)f->default_value);
1299  lua_pushstring(L, f->repeated ?
1300  (f->packed ? "packed" : "repeated") :
1301  "optional");
1302  if (f->oneof_idx > 0) {
1303  lua_pushstring(L, (const char*)pb_oneofname(t, f->oneof_idx));
1304  lua_pushinteger(L, f->oneof_idx-1);
1305  return 7;
1306  }
1307  return 5;
1308 }
1309 
1310 static int Lpb_typesiter(lua_State *L) {
1311  lpb_State *LS = lpb_lstate(L);
1312  const pb_Type *t = lpb_type(L, LS, lpb_toslice(L, 2));
1313  if ((t == NULL && !lua_isnoneornil(L, 2)))
1314  return 0;
1315  pb_nexttype(lpbS_state(LS), &t);
1316  return lpb_pushtype(L, t);
1317 }
1318 
1319 static int Lpb_types(lua_State *L) {
1320  lua_pushcfunction(L, Lpb_typesiter);
1321  lua_pushnil(L);
1322  lua_pushnil(L);
1323  return 3;
1324 }
1325 
1326 static int Lpb_fieldsiter(lua_State *L) {
1327  lpb_State *LS = lpb_lstate(L);
1328  const pb_Type *t = lpb_type(L, LS, lpb_checkslice(L, 1));
1329  const pb_Field *f = pb_fname(t, lpb_name(LS, lpb_toslice(L, 2)));
1330  if ((f == NULL && !lua_isnoneornil(L, 2)) || !pb_nextfield(t, &f))
1331  return 0;
1332  return lpb_pushfield(L, t, f);
1333 }
1334 
1335 static int Lpb_fields(lua_State *L) {
1336  lua_pushcfunction(L, Lpb_fieldsiter);
1337  lua_pushvalue(L, 1);
1338  lua_pushnil(L);
1339  return 3;
1340 }
1341 
1342 static int Lpb_type(lua_State *L) {
1343  lpb_State *LS = lpb_lstate(L);
1344  const pb_Type *t = lpb_type(L, LS, lpb_checkslice(L, 1));
1345  if (t == NULL || t->is_dead)
1346  return 0;
1347  return lpb_pushtype(L, t);
1348 }
1349 
1350 static int Lpb_field(lua_State *L) {
1351  lpb_State *LS = lpb_lstate(L);
1352  const pb_Type *t = lpb_type(L, LS, lpb_checkslice(L, 1));
1353  return lpb_pushfield(L, t, lpb_field(L, 2, t));
1354 }
1355 
1356 static int Lpb_enum(lua_State *L) {
1357  lpb_State *LS = lpb_lstate(L);
1358  const pb_Type *t = lpb_type(L, LS, lpb_checkslice(L, 1));
1359  const pb_Field *f = lpb_field(L, 2, t);
1360  if (f == NULL) return 0;
1361  if (lua_type(L, 2) == LUA_TNUMBER)
1362  lua_pushstring(L, (const char*)f->name);
1363  else
1364  lpb_pushinteger(L, f->number, 1, LS->int64_mode);
1365  return 1;
1366 }
1367 
1368 static int lpb_pushdeffield(lua_State *L, lpb_State *LS, const pb_Field *f, int is_proto3) {
1369  int ret = 0, u = 0;
1370  const pb_Type *type;
1371  char *end;
1372  if (f == NULL) return 0;
1373  switch (f->type_id) {
1374  case PB_Tenum:
1375  if ((type = f ? f->type : NULL) == NULL) return 0;
1376  if ((f = pb_fname(type, f->default_value)) != NULL)
1377  ret = LS->enum_as_value ?
1378  (lpb_pushinteger(L, f->number, 1, LS->int64_mode), 1) :
1379  (lua_pushstring(L, (const char*)f->name), 1);
1380  else if (is_proto3)
1381  ret = (f = pb_field(type, 0)) == NULL || LS->enum_as_value ?
1382  (lua_pushinteger(L, 0), 1) :
1383  (lua_pushstring(L, (const char*)f->name), 1);
1384  break;
1385  case PB_Tmessage:
1386  ret = (lpb_pushtypetable(L, LS, f->type), 1);
1387  break;
1388  case PB_Tbytes: case PB_Tstring:
1389  if (f->default_value)
1390  ret = (lua_pushstring(L, (const char*)f->default_value), 1);
1391  else if (is_proto3) ret = (lua_pushliteral(L, ""), 1);
1392  break;
1393  case PB_Tbool:
1394  if (f->default_value) {
1395  if (f->default_value == lpb_name(LS, pb_slice("true")))
1396  ret = (lua_pushboolean(L, 1), 1);
1397  else if (f->default_value == lpb_name(LS, pb_slice("false")))
1398  ret = (lua_pushboolean(L, 0), 1);
1399  } else if (is_proto3) ret = (lua_pushboolean(L, 0), 1);
1400  break;
1401  case PB_Tdouble: case PB_Tfloat:
1402  if (f->default_value) {
1403  lua_Number ln = (lua_Number)strtod((const char*)f->default_value, &end);
1404  if ((const char*)f->default_value == end) return 0;
1405  ret = (lua_pushnumber(L, ln), 1);
1406  } else if (is_proto3) ret = (lua_pushnumber(L, 0.0), 1);
1407  break;
1408 
1409  case PB_Tuint64: case PB_Tfixed64: case PB_Tfixed32: case PB_Tuint32:
1410  u = 1;
1411  /* FALLTHROUGH */
1412  default:
1413  if (f->default_value) {
1414  lua_Integer li = (lua_Integer)strtol((const char*)f->default_value, &end, 10);
1415  if ((const char*)f->default_value == end) return 0;
1416  ret = (lpb_pushinteger(L, li, u, LS->int64_mode), 1);
1417  } else if (is_proto3) ret = (lua_pushinteger(L, 0), 1);
1418  }
1419  return ret;
1420 }
1421 
1422 static void lpb_fetchtable(lua_State *L, lpb_State *LS, const pb_Field *f, const pb_Type *t) {
1423  if (lua53_getfield(L, -1, (const char*)f->name) == LUA_TNIL) {
1424  lua_pop(L, 1);
1425  lua_newtable(L);
1426  lua_pushvalue(L, -1);
1427  lua_setfield(L, -3, (const char*)f->name);
1428  }
1429  if (t->is_dead) return;
1430  if (lua_getmetatable(L, -1))
1431  lua_pop(L, 1);
1432  else {
1433  lpb_pushdefmeta(L, LS, t);
1434  lua_setmetatable(L, -2);
1435  }
1436 }
1437 
1438 static void lpb_setdeffields(lua_State *L, lpb_State *LS, const pb_Type *t, lpb_DefFlags flags) {
1439  const pb_Field *f = NULL;
1440  while (pb_nextfield(t, &f)) {
1441  const pb_Type *fetch_type = f->type && f->type->is_map ?
1442  &LS->map_type : &LS->array_type;
1443  int has_field = f->repeated ?
1444  (flags & USE_REPEAT) && (t->is_proto3 || LS->decode_default_array)
1445  && (lpb_fetchtable(L, LS, f, fetch_type), 1) :
1446  !f->oneof_idx && (f->type_id != PB_Tmessage ?
1447  (flags & USE_FIELD) :
1448  (flags & USE_MESSAGE) && LS->decode_default_message)
1449  && lpb_pushdeffield(L, LS, f, t->is_proto3);
1450  if (has_field) lua_setfield(L, -2, (const char*)f->name);
1451  }
1452 }
1453 
1454 static void lpb_pushdefmeta(lua_State *L, lpb_State *LS, const pb_Type *t) {
1455  lpb_pushdeftable(L, LS);
1456  if (lua53_rawgetp(L, -1, t) != LUA_TTABLE) {
1457  lua_pop(L, 1);
1458  lpb_newmsgtable(L, t);
1459  lpb_setdeffields(L, LS, t, USE_FIELD);
1460  lua_pushvalue(L, -1);
1461  lua_setfield(L, -2, "__index");
1462  lua_pushvalue(L, -1);
1463  lua_rawsetp(L, -3, t);
1464  }
1465  lua_remove(L, -2);
1466 }
1467 
1468 static void lpb_cleardefmeta(lua_State *L, lpb_State *LS, const pb_Type *t) {
1469  lpb_pushdeftable(L, LS);
1470  lua_pushnil(L);
1471  lua_rawsetp(L, -2, t);
1472  lua_pop(L, 1);
1473 }
1474 
1475 static int Lpb_defaults(lua_State *L) {
1476  lpb_State *LS = lpb_lstate(L);
1477  pb_Slice tn = lpb_checkslice(L, 1);
1478  int clear = !lua_toboolean(L, 2) && !lua_isnone(L, 2);
1479  pb_Type *t = NULL;
1480  if (pb_len(tn) < 2 || tn.p[0] != '*')
1481  t = (pb_Type*)lpb_type(L, LS, tn);
1482  else if (tn.p[1] == 'a' || tn.p[1] == 'A')
1483  (t = &LS->array_type)->is_dead = clear;
1484  else if (tn.p[1] == 'm' || tn.p[1] == 'M')
1485  (t = &LS->map_type)->is_dead = clear;
1486  if (t == NULL) luaL_argerror(L, 1, "type not found");
1487  if (lua_isnone(L, 2))
1488  lpb_pushdefmeta(L, LS, t);
1489  else {
1490  lpb_pushdeftable(L, LS);
1491  lua_rawgetp(L, -1, t);
1492  lua_pushvalue(L, 2);
1493  lua_rawsetp(L, -3, t);
1494  }
1495  return 1;
1496 }
1497 
1498 static int Lpb_hook(lua_State *L) {
1499  lpb_State *LS = lpb_lstate(L);
1500  const pb_Type *t = lpb_type(L, LS, lpb_checkslice(L, 1));
1501  int type = lua_type(L, 2);
1502  if (t == NULL) luaL_argerror(L, 1, "type not found");
1503  if (type != LUA_TNONE && type != LUA_TNIL && type != LUA_TFUNCTION)
1504  lpb_typeerror(L, 2, "function");
1505  lua_settop(L, 2);
1506  lpb_pushdechooktable(L, LS);
1507  lua_rawgetp(L, 3, t);
1508  if (type != LUA_TNONE) {
1509  lua_pushvalue(L, 2);
1510  lua_rawsetp(L, 3, t);
1511  }
1512  return 1;
1513 }
1514 
1515 static int Lpb_encode_hook(lua_State *L) {
1516  lpb_State *LS = lpb_lstate(L);
1517  const pb_Type *t = lpb_type(L, LS, lpb_checkslice(L, 1));
1518  int type = lua_type(L, 2);
1519  if (t == NULL) luaL_argerror(L, 1, "type not found");
1520  if (type != LUA_TNONE && type != LUA_TNIL && type != LUA_TFUNCTION)
1521  lpb_typeerror(L, 2, "function");
1522  lua_settop(L, 2);
1523  lpb_pushenchooktable(L, LS);
1524  lua_rawgetp(L, 3, t);
1525  if (type != LUA_TNONE) {
1526  lua_pushvalue(L, 2);
1527  lua_rawsetp(L, 3, t);
1528  }
1529  return 1;
1530 }
1531 
1532 static int Lpb_clear(lua_State *L) {
1533  lpb_State *LS = lpb_lstate(L);
1534  pb_State *S = (pb_State*)LS->state;
1535  pb_Type *t;
1536  if (lua_isnoneornil(L, 1)) {
1537  pb_free(&LS->local), pb_init(&LS->local);
1538  luaL_unref(L, LUA_REGISTRYINDEX, LS->defs_index);
1539  LS->defs_index = LUA_NOREF;
1540  luaL_unref(L, LUA_REGISTRYINDEX, LS->enc_hooks_index);
1541  LS->enc_hooks_index = LUA_NOREF;
1542  luaL_unref(L, LUA_REGISTRYINDEX, LS->dec_hooks_index);
1543  LS->dec_hooks_index = LUA_NOREF;
1544  return 0;
1545  }
1546  LS->state = &LS->local;
1547  t = (pb_Type*)lpb_type(L, LS, lpb_checkslice(L, 1));
1548  if (lua_isnoneornil(L, 2)) pb_deltype(&LS->local, t);
1549  else pb_delfield(&LS->local, t, (pb_Field*)lpb_field(L, 2, t));
1550  LS->state = S;
1551  lpb_cleardefmeta(L, LS, t);
1552  return 0;
1553 }
1554 
1555 static int Lpb_typefmt(lua_State *L) {
1556  pb_Slice s = lpb_checkslice(L, 1);
1557  const char *r = NULL;
1558  char buf[2] = {0};
1559  int type;
1560  if (pb_len(s) == 1)
1561  r = pb_typename(type = lpb_typefmt(*s.p), "!");
1562  else if (lpb_type(L, lpb_lstate(L), s))
1563  r = "message", type = PB_TBYTES;
1564  else if ((type = pb_typebyname(s.p, PB_Tmessage)) != PB_Tmessage) {
1565  switch (type) {
1566 #define X(name,type,fmt) case PB_T##name: buf[0] = fmt, r = buf; break;
1567  PB_TYPES(X)
1568 #undef X
1569  }
1570  type = pb_wtypebytype(type);
1571  } else if ((type = pb_wtypebyname(s.p, PB_Tmessage)) != PB_Tmessage) {
1572  switch (type) {
1573 #define X(id,name,fmt) case PB_T##id: buf[0] = fmt, r = buf; break;
1574  PB_WIRETYPES(X)
1575 #undef X
1576  }
1577  }
1578  lua_pushstring(L, r ? r : "!");
1579  lua_pushinteger(L, type);
1580  return 2;
1581 }
1582 
1583 
1584 /* protobuf encode */
1585 
1586 typedef struct lpb_Env {
1587  lua_State *L;
1588  lpb_State *LS;
1589  pb_Buffer *b;
1590  pb_Slice *s;
1591 } lpb_Env;
1592 
1593 static void lpbE_encode (lpb_Env *e, const pb_Type *t, int idx);
1594 
1595 static void lpb_checktable(lua_State *L, const pb_Field *f, int idx) {
1596  argcheck(L, lua_istable(L, idx),
1597  2, "table expected at field '%s', got %s",
1598  (const char*)f->name, luaL_typename(L, idx));
1599 }
1600 
1601 static void lpb_useenchooks(lua_State *L, lpb_State *LS, const pb_Type *t) {
1602  lpb_pushenchooktable(L, LS);
1603  if (lua53_rawgetp(L, -1, t) != LUA_TNIL) {
1604  lua_pushvalue(L, -3);
1605  lua_call(L, 1, 1);
1606  if (!lua_isnil(L, -1)) {
1607  lua_pushvalue(L, -1);
1608  lua_replace(L, -4);
1609  }
1610  }
1611  lua_pop(L, 2);
1612 }
1613 
1614 static size_t lpbE_enum(lpb_Env *e, const pb_Field *f, int *pexist, int idx) {
1615  lua_State *L = e->L;
1616  pb_Buffer *b = e->b;
1617  const pb_Field *ev;
1618  int type = lua_type(L, idx);
1619  if (type == LUA_TNUMBER) {
1620  uint64_t v = (uint64_t)lua_tonumber(L, idx);
1621  if (pexist) *pexist = (v != 0);
1622  return lpb_checkmem(L, pb_addvarint64(b, v));
1623  } else if ((ev = pb_fname(f->type,
1624  lpb_name(e->LS, lpb_toslice(L, idx)))) != NULL) {
1625  if (pexist) *pexist = (ev->number != 0);
1626  return lpb_checkmem(L, pb_addvarint32(b, ev->number));
1627  } else if (type != LUA_TSTRING) {
1628  argcheck(L, 0, 2, "number/string expected at field '%s', got %s",
1629  (const char*)f->name, luaL_typename(L, idx));
1630  return 0;
1631  } else {
1632  uint64_t v = lpb_tointegerx(L, idx, &type);
1633  if (pexist) *pexist = (v != 0);
1634  if (!type)
1635  argcheck(L, 0, 2, "can not encode unknown enum '%s' at field '%s'",
1636  lua_tostring(L, -1), (const char*)f->name);
1637  return lpb_checkmem(L, pb_addvarint64(b, v));
1638  }
1639 }
1640 
1641 static size_t lpbE_field(lpb_Env *e, const pb_Field *f, int *pexist, int idx) {
1642  lua_State *L = e->L;
1643  pb_Buffer *b = e->b;
1644  size_t len;
1645  switch (f->type_id) {
1646  case PB_Tenum:
1647  if (e->LS->use_enc_hooks) lpb_useenchooks(L, e->LS, f->type);
1648  return lpbE_enum(e, f, pexist, idx);
1649 
1650  case PB_Tmessage:
1651  if (e->LS->use_enc_hooks) lpb_useenchooks(L, e->LS, f->type);
1652  lpb_checktable(L, f, idx);
1653  lpb_checkmem(L, pb_addvarint32(b, 0));
1654  len = pb_bufflen(b);
1655  lpbE_encode(e, f->type, idx);
1656  if (pexist) *pexist = (len < pb_bufflen(b));
1657  return lpb_addlength(L, b, len, 1);
1658 
1659  default:
1660  len = lpb_addtype(L, b, idx, f->type_id, pexist);
1661  argcheck(L, len > 0,
1662  2, "%s expected for field '%s', got %s",
1663  lpb_expected(f->type_id),
1664  (const char*)f->name, luaL_typename(L, idx));
1665  return len;
1666  }
1667 }
1668 
1669 static void lpbE_tagfield(lpb_Env *e, const pb_Field *f, int ignorezero, int idx) {
1670  size_t hlen = lpb_checkmem(e->L, pb_addvarint32(e->b,
1671  pb_pair(f->number, pb_wtypebytype(f->type_id))));
1672  int exist;
1673  size_t ignoredlen = lpbE_field(e, f, &exist, idx);
1674  if (!e->LS->encode_default_values && !exist && ignorezero)
1675  e->b->size -= (unsigned)(ignoredlen + hlen);
1676 }
1677 
1678 static void lpbE_map(lpb_Env *e, const pb_Field *f, int idx) {
1679  lua_State *L = e->L;
1680  const pb_Field *kf = pb_field(f->type, 1);
1681  const pb_Field *vf = pb_field(f->type, 2);
1682  if (kf == NULL || vf == NULL) return;
1683  lpb_checktable(L, f, idx);
1684  lua_pushnil(L);
1685  while (lua_next(L, lpb_relindex(idx, 1))) {
1686  size_t len;
1687  lpb_checkmem(L, pb_addvarint32(e->b, pb_pair(f->number, PB_TBYTES)));
1688  lpb_checkmem(L, pb_addvarint32(e->b, 0));
1689  len = pb_bufflen(e->b);
1690  lpbE_tagfield(e, kf, 1, -2);
1691  lpbE_tagfield(e, vf, 1, -1);
1692  lpb_addlength(L, e->b, len, 1);
1693  lua_pop(L, 1);
1694  }
1695 }
1696 
1697 static void lpbE_repeated(lpb_Env *e, const pb_Field *f, int idx) {
1698  lua_State *L = e->L;
1699  pb_Buffer *b = e->b;
1700  int i;
1701  lpb_checktable(L, f, idx);
1702 
1703  if (f->packed) {
1704  unsigned len, bufflen = pb_bufflen(b);
1705  lpb_checkmem(L, pb_addvarint32(b, pb_pair(f->number, PB_TBYTES)));
1706  lpb_checkmem(L, pb_addvarint32(b, 0));
1707  len = pb_bufflen(b);
1708  for (i = 1; lua53_rawgeti(L, idx, i) != LUA_TNIL; ++i) {
1709  lpbE_field(e, f, NULL, -1);
1710  lua_pop(L, 1);
1711  }
1712  if (i == 1 && !e->LS->encode_default_values)
1713  pb_bufflen(b) = bufflen;
1714  else
1715  lpb_addlength(L, b, len, 1);
1716  } else {
1717  for (i = 1; lua53_rawgeti(L, idx, i) != LUA_TNIL; ++i) {
1718  lpbE_tagfield(e, f, 0, -1);
1719  lua_pop(L, 1);
1720  }
1721  }
1722  lua_pop(L, 1);
1723 }
1724 
1725 static void lpb_encode_onefield(lpb_Env *e, const pb_Type *t, const pb_Field *f, int idx) {
1726  if (f->type && f->type->is_map)
1727  lpbE_map(e, f, idx);
1728  else if (f->repeated)
1729  lpbE_repeated(e, f, idx);
1730  else if (!f->type || !f->type->is_dead)
1731  lpbE_tagfield(e, f, t->is_proto3 && !f->oneof_idx && f->type_id != PB_Tmessage, idx);
1732 }
1733 
1734 static void lpbE_encode(lpb_Env *e, const pb_Type *t, int idx) {
1735  lua_State *L = e->L;
1736  luaL_checkstack(L, 5, "message too many levels");
1737  if (e->LS->encode_order) {
1738  const pb_Field *f = NULL;
1739  while (pb_nextfield(t, &f)) {
1740  if (lua53_getfield(L, idx, (const char*)f->name) != LUA_TNIL)
1741  lpb_encode_onefield(e, t, f, -1);
1742  lua_pop(L, 1);
1743  }
1744  } else {
1745  lua_pushnil(L);
1746  while (lua_next(L, lpb_relindex(idx, 1))) {
1747  if (lua_type(L, -2) == LUA_TSTRING) {
1748  const pb_Field *f =
1749  pb_fname(t, lpb_name(e->LS, lpb_toslice(L, -2)));
1750  if (f != NULL) lpb_encode_onefield(e, t, f, -1);
1751  }
1752  lua_pop(L, 1);
1753  }
1754  }
1755 }
1756 
1757 static int Lpb_encode(lua_State *L) {
1758  lpb_State *LS = lpb_lstate(L);
1759  const pb_Type *t = lpb_type(L, LS, lpb_checkslice(L, 1));
1760  lpb_Env e;
1761  argcheck(L, t!=NULL, 1, "type '%s' does not exists", lua_tostring(L, 1));
1762  luaL_checktype(L, 2, LUA_TTABLE);
1763  e.L = L, e.LS = LS, e.b = test_buffer(L, 3);
1764  if (e.b == NULL) pb_resetbuffer(e.b = &LS->buffer);
1765  lua_pushvalue(L, 2);
1766  if (e.LS->use_enc_hooks) lpb_useenchooks(L, e.LS, t);
1767  lpbE_encode(&e, t, -1);
1768  if (e.b != &LS->buffer)
1769  lua_settop(L, 3);
1770  else {
1771  lua_pushlstring(L, pb_buffer(e.b), pb_bufflen(e.b));
1772  pb_resetbuffer(e.b);
1773  }
1774  return 1;
1775 }
1776 
1777 static int lpbE_pack(lpb_Env* e, const pb_Type* t, int idx) {
1778  unsigned i;
1779  lua_State* L = e->L;
1780  pb_Field** f = pb_sortfield((pb_Type*)t);
1781  for (i = 0; i < t->field_count; i++) {
1782  int index = idx + i;
1783  if (!lua_isnoneornil(L, index)) {
1784  lpb_encode_onefield(e, t, f[i], index);
1785  }
1786  }
1787  return 0;
1788 }
1789 
1790 static int Lpb_pack(lua_State* L) {
1791  lpb_State* LS = lpb_lstate(L);
1792  const pb_Type* t = lpb_type(L, LS, lpb_checkslice(L, 1));
1793  lpb_Env e;
1794  int idx = 3;
1795  e.L = L, e.LS = LS, e.b = test_buffer(L, 2);
1796  if (e.b == NULL) {
1797  idx = 2;
1798  pb_resetbuffer(e.b = &LS->buffer);
1799  }
1800  lpbE_pack(&e, t, idx);
1801  if (e.b != &LS->buffer)
1802  lua_settop(L, 3);
1803  else {
1804  lua_pushlstring(L, pb_buffer(e.b), pb_bufflen(e.b));
1805  pb_resetbuffer(e.b);
1806  }
1807  return 1;
1808 }
1809 
1810 /* protobuf decode */
1811 
1812 #define lpb_withinput(e,ns,stmt) ((e)->s = (ns), (stmt), (e)->s = s)
1813 
1814 static int lpbD_message(lpb_Env *e, const pb_Type *t);
1815 
1816 static void lpb_usedechooks(lua_State *L, lpb_State *LS, const pb_Type *t) {
1817  lpb_pushdechooktable(L, LS);
1818  if (lua53_rawgetp(L, -1, t) != LUA_TNIL) {
1819  lua_pushvalue(L, -3);
1820  lua_call(L, 1, 1);
1821  if (!lua_isnil(L, -1)) {
1822  lua_pushvalue(L, -1);
1823  lua_replace(L, -4);
1824  }
1825  }
1826  lua_pop(L, 2);
1827 }
1828 
1829 static void lpb_pushtypetable(lua_State *L, lpb_State *LS, const pb_Type *t) {
1830  int mode = LS->encode_mode;
1831  luaL_checkstack(L, 5, "too many levels");
1832  lpb_newmsgtable(L, t);
1833  switch (t->is_proto3 && mode == LPB_DEFDEF ? LPB_COPYDEF : mode) {
1834  case LPB_COPYDEF:
1835  lpb_setdeffields(L, LS, t,
1836  (lpb_DefFlags)(USE_FIELD|USE_REPEAT|USE_MESSAGE));
1837  break;
1838  case LPB_METADEF:
1839  lpb_setdeffields(L, LS, t, (lpb_DefFlags)(USE_REPEAT|USE_MESSAGE));
1840  lpb_pushdefmeta(L, LS, t);
1841  lua_setmetatable(L, -2);
1842  break;
1843  default:
1844  if (LS->decode_default_array || LS->decode_default_message)
1845  lpb_setdeffields(L, LS, t, (lpb_DefFlags)(USE_REPEAT|USE_MESSAGE));
1846  break;
1847  }
1848 }
1849 
1850 static void lpbD_rawfield(lpb_Env *e, const pb_Field *f) {
1851  lua_State *L = e->L;
1852  pb_Slice sv, *s = e->s;
1853  const pb_Field *ev = NULL;
1854  uint64_t u64;
1855  switch (f->type_id) {
1856  case PB_Tenum:
1857  if (pb_readvarint64(s, &u64) == 0)
1858  luaL_error(L, "invalid varint value at offset %d", pb_pos(*s)+1);
1859  if (!lpb_lstate(L)->enum_as_value)
1860  ev = pb_field(f->type, (int32_t)u64);
1861  if (ev) lua_pushstring(L, (const char*)ev->name);
1862  else lpb_pushinteger(L, (lua_Integer)u64, 1, lpb_lstate(L)->int64_mode);
1863  if (e->LS->use_dec_hooks) lpb_usedechooks(L, e->LS, f->type);
1864  break;
1865 
1866  case PB_Tmessage:
1867  lpb_readbytes(L, s, &sv);
1868  if (f->type == NULL || f->type->is_dead)
1869  lua_pushnil(L);
1870  else {
1871  lpb_pushtypetable(L, e->LS, f->type);
1872  lpb_withinput(e, &sv, lpbD_message(e, f->type));
1873  }
1874  break;
1875 
1876  default:
1877  lpb_readtype(L, e->LS, f->type_id, s);
1878  }
1879 }
1880 
1881 static void lpbD_checktype(lpb_Env *e, const pb_Field *f, uint32_t tag) {
1882  if (pb_wtypebytype(f->type_id) == (int)pb_gettype(tag)) return;
1883  luaL_error(e->L,
1884  "type mismatch for %s%sfield '%s' at offset %d, "
1885  "%s expected for type %s, got %s",
1886  f->packed ? "packed " : "", f->repeated ? "repeated " : "",
1887  (const char*)f->name,
1888  pb_pos(*e->s)+1,
1889  pb_wtypename(pb_wtypebytype(f->type_id), NULL),
1890  pb_typename(f->type_id, NULL),
1891  pb_wtypename(pb_gettype(tag), NULL));
1892 }
1893 
1894 static void lpbD_field(lpb_Env *e, const pb_Field *f, uint32_t tag) {
1895  lpbD_checktype(e, f, tag);
1896  lpbD_rawfield(e, f);
1897 }
1898 
1899 static void lpbD_map(lpb_Env *e, const pb_Field *f) {
1900  lua_State *L = e->L;
1901  pb_Slice p, *s = e->s;
1902  int mask = 0, top = lua_gettop(L);
1903  uint32_t tag;
1904  lpb_readbytes(L, s, &p);
1905  if (f->type == NULL) return;
1906  lua_pushnil(L);
1907  lua_pushnil(L);
1908  while (pb_readvarint32(&p, &tag)) {
1909  int n = pb_gettag(tag);
1910  if (n == 1 || n == 2) {
1911  mask |= n;
1912  lpb_withinput(e, &p, lpbD_field(e, pb_field(f->type, n), tag));
1913  lua_replace(L, top+n);
1914  }
1915  }
1916  if (!(mask & 1) && lpb_pushdeffield(L, e->LS, pb_field(f->type, 1), 1))
1917  lua_replace(L, top + 1), mask |= 1;
1918  if (!(mask & 2) && lpb_pushdeffield(L, e->LS, pb_field(f->type, 2), 1))
1919  lua_replace(L, top + 2), mask |= 2;
1920  if (mask == 3) lua_rawset(L, -3); else lua_pop(L, 2);
1921 }
1922 
1923 static void lpbD_repeated(lpb_Env *e, const pb_Field *f, uint32_t tag) {
1924  lua_State *L = e->L;
1925  if (pb_gettype(tag) != PB_TBYTES
1926  || (!f->packed && pb_wtypebytype(f->type_id) == PB_TBYTES)) {
1927  lpbD_field(e, f, tag);
1928  lua_rawseti(L, -2, (int)lua_rawlen(L, -2) + 1);
1929  } else {
1930  int len = (int)lua_rawlen(L, -1);
1931  pb_Slice p, *s = e->s;
1932  lpb_readbytes(L, s, &p);
1933  while (p.p < p.end) {
1934  lpb_withinput(e, &p, lpbD_rawfield(e, f));
1935  lua_rawseti(L, -2, ++len);
1936  }
1937  }
1938 }
1939 
1940 static int lpbD_message(lpb_Env *e, const pb_Type *t) {
1941  lua_State *L = e->L;
1942  pb_Slice *s = e->s;
1943  uint32_t tag;
1944  luaL_checkstack(L, 5, "not enough stack space for fields");
1945  while (pb_readvarint32(s, &tag)) {
1946  const pb_Field *f = pb_field(t, pb_gettag(tag));
1947  if (f == NULL)
1948  pb_skipvalue(s, tag);
1949  else if (f->type && f->type->is_map) {
1950  lpb_fetchtable(L, e->LS, f, &e->LS->map_type);
1951  lpbD_checktype(e, f, tag);
1952  lpbD_map(e, f);
1953  lua_pop(L, 1);
1954  } else if (f->repeated) {
1955  lpb_fetchtable(L, e->LS, f, &e->LS->array_type);
1956  lpbD_repeated(e, f, tag);
1957  lua_pop(L, 1);
1958  } else {
1959  lua_pushstring(L, (const char*)f->name);
1960  if (f->oneof_idx) {
1961  lua_pushstring(L, (const char*)pb_oneofname(t, f->oneof_idx));
1962  lua_pushvalue(L, -2);
1963  lua_rawset(L, -4);
1964  }
1965  lpbD_field(e, f, tag);
1966  lua_rawset(L, -3);
1967  }
1968  }
1969  if (e->LS->use_dec_hooks) lpb_usedechooks(L, e->LS, t);
1970  return 1;
1971 }
1972 
1973 static int lpbD_decode(lua_State *L, pb_Slice s, int start) {
1974  lpb_State *LS = lpb_lstate(L);
1975  const pb_Type *t = lpb_type(L, LS, lpb_checkslice(L, 1));
1976  lpb_Env e;
1977  argcheck(L, t!=NULL, 1, "type '%s' does not exists", lua_tostring(L, 1));
1978  lua_settop(L, start);
1979  if (!lua_istable(L, start)) {
1980  lua_pop(L, 1);
1981  lpb_pushtypetable(L, LS, t);
1982  }
1983  e.L = L, e.LS = LS, e.s = &s;
1984  return lpbD_message(&e, t);
1985 }
1986 
1987 static int Lpb_decode(lua_State *L) {
1988  return lpbD_decode(L, lua_isnoneornil(L, 2) ?
1989  pb_lslice(NULL, 0) :
1990  lpb_checkslice(L, 2), 3);
1991 }
1992 
1993 
1994 void lpb_pushunpackdef(lua_State* L, lpb_State* LS, const pb_Type* t, pb_Field** l, int top) {
1995  unsigned int i;
1996  int mode = LS->encode_mode;
1997  mode = t->is_proto3 && mode == LPB_DEFDEF ? LPB_COPYDEF : mode;
1998  if (mode != LPB_COPYDEF && mode != LPB_METADEF) return;
1999 
2000  for (i = 0; i < t->field_count; i++) {
2001  int idx = top + i + 1;
2002  if (lua_isnoneornil(L, idx) && lpb_pushdeffield(L, LS, l[i], t->is_proto3)) {
2003  lua_replace(L, idx);
2004  }
2005  }
2006 }
2007 
2008 static int lpb_unpackfield(lpb_Env *e, const pb_Field* f, uint32_t tag, int last) {
2009  if (!f) {
2010  pb_skipvalue(e->s, tag);
2011  return 0;
2012  }
2013  if (f->type && f->type->is_map) {
2014  lpbD_checktype(e, f, tag);
2015  if (!last) lua_newtable(e->L);
2016  lpbD_map(e, f);
2017  }
2018  else if (f->repeated) {
2019  if (!last) lua_newtable(e->L);
2020  lpbD_repeated(e, f, tag);
2021  }
2022  else {
2023  lpbD_field(e, f, tag);
2024  }
2025  return f->sort_index;
2026 }
2027 
2028 static int lpbD_unpack(lpb_Env* e, const pb_Type* t) {
2029  lua_State* L = e->L;
2030  int top = lua_gettop(L);
2031  uint32_t tag;
2032  int last_index = 0;
2033  unsigned int decode_count = 0;
2034  pb_Field **list = pb_sortfield((pb_Type*)t);
2035  lua_settop(L, top + t->field_count);
2036  luaL_checkstack(L, t->field_count * 2, "not enough stack space for fields");
2037  while (pb_readvarint32(e->s, &tag)) {
2038  const pb_Field* f = pb_field(t, pb_gettag(tag));
2039  if (last_index && (!f || f->sort_index != last_index)) {
2040  decode_count++;
2041  lua_replace(L, top + last_index);
2042  last_index = 0;
2043  }
2044  last_index = lpb_unpackfield(e, f, tag, last_index);
2045  }
2046  if (last_index) {
2047  decode_count++;
2048  lua_replace(L, top + last_index);
2049  }
2050  if (decode_count != t->field_count) lpb_pushunpackdef(L, e->LS, t, list, top);
2051  return t->field_count;
2052 }
2053 
2054 static int Lpb_unpack(lua_State* L) {
2055  lpb_State* LS = lpb_lstate(L);
2056  const pb_Type* t = lpb_type(L, LS, lpb_checkslice(L, 1));
2057  pb_Slice s = lpb_checkslice(L, 2);
2058  lpb_Env e;
2059  e.L = L, e.LS = LS, e.s = &s;
2060  argcheck(L, t != NULL, 1, "type '%s' does not exists", lua_tostring(L, 1));
2061  return lpbD_unpack(&e, t);
2062 }
2063 
2064 /* pb module interface */
2065 
2066 static int Lpb_option(lua_State *L) {
2067 #define OPTS(X) \
2068  X(0, enum_as_name, LS->enum_as_value = 0) \
2069  X(1, enum_as_value, LS->enum_as_value = 1) \
2070  X(2, int64_as_number, LS->int64_mode = LPB_NUMBER) \
2071  X(3, int64_as_string, LS->int64_mode = LPB_STRING) \
2072  X(4, int64_as_hexstring, LS->int64_mode = LPB_HEXSTRING) \
2073  X(5, encode_order, LS->encode_order = 1) \
2074  X(6, no_encode_order, LS->encode_order = 0) \
2075  X(7, encode_default_values, LS->encode_default_values = 1) \
2076  X(8, no_encode_default_values, LS->encode_default_values = 0) \
2077  X(9, auto_default_values, LS->encode_mode = LPB_DEFDEF) \
2078  X(10, no_default_values, LS->encode_mode = LPB_NODEF) \
2079  X(11, use_default_values, LS->encode_mode = LPB_COPYDEF) \
2080  X(12, use_default_metatable, LS->encode_mode = LPB_METADEF) \
2081  X(13, decode_default_array, LS->decode_default_array = 1) \
2082  X(14, no_decode_default_array, LS->decode_default_array = 0) \
2083  X(15, decode_default_message, LS->decode_default_message = 1) \
2084  X(16, no_decode_default_message, LS->decode_default_message = 0) \
2085  X(17, enable_hooks, LS->use_dec_hooks = 1) \
2086  X(18, disable_hooks, LS->use_dec_hooks = 0) \
2087  X(19, enable_enchooks, LS->use_enc_hooks = 1) \
2088  X(20, disable_enchooks, LS->use_enc_hooks = 0) \
2089 
2090  static const char *opts[] = {
2091 #define X(ID,NAME,CODE) #NAME,
2092  OPTS(X)
2093 #undef X
2094  NULL
2095  };
2096  lpb_State *LS = lpb_lstate(L);
2097  switch (luaL_checkoption(L, 1, NULL, opts)) {
2098 #define X(ID,NAME,CODE) case ID: CODE; break;
2099  OPTS(X)
2100 #undef X
2101  }
2102  return 0;
2103 #undef OPTS
2104 }
2105 
2106 LUALIB_API int luaopen_pb(lua_State *L) {
2107  luaL_Reg libs[] = {
2108 #define ENTRY(name) { #name, Lpb_##name }
2109  ENTRY(clear),
2110  ENTRY(load),
2111  ENTRY(loadfile),
2112  ENTRY(encode),
2113  ENTRY(decode),
2114  ENTRY(types),
2115  ENTRY(fields),
2116  ENTRY(type),
2117  ENTRY(field),
2118  ENTRY(typefmt),
2119  ENTRY(enum),
2120  ENTRY(defaults),
2121  ENTRY(hook),
2122  ENTRY(encode_hook),
2123  ENTRY(tohex),
2124  ENTRY(fromhex),
2125  ENTRY(result),
2126  ENTRY(option),
2127  ENTRY(state),
2128  ENTRY(pack),
2129  ENTRY(unpack),
2130 #undef ENTRY
2131  { NULL, NULL }
2132  };
2133  luaL_Reg meta[] = {
2134  { "__gc", Lpb_delete },
2135  { "setdefault", Lpb_state },
2136  { NULL, NULL }
2137  };
2138  if (luaL_newmetatable(L, PB_STATE)) {
2139  luaL_setfuncs(L, meta, 0);
2140  lua_pushvalue(L, -1);
2141  lua_setfield(L, -2, "__index");
2142  }
2143  luaL_newlib(L, libs);
2144  return 1;
2145 }
2146 
2147 static int Lpb_decode_unsafe(lua_State *L) {
2148  const char *data = (const char *)lua_touserdata(L, 2);
2149  size_t size = (size_t)luaL_checkinteger(L, 3);
2150  if (data == NULL) lpb_typeerror(L, 2, "userdata");
2151  return lpbD_decode(L, pb_lslice(data, size), 4);
2152 }
2153 
2154 static int Lpb_slice_unsafe(lua_State *L) {
2155  const char *data = (const char *)lua_touserdata(L, 1);
2156  size_t size = (size_t)luaL_checkinteger(L, 2);
2157  if (data == NULL) lpb_typeerror(L, 1, "userdata");
2158  return lpb_newslice(L, data, size);
2159 }
2160 
2161 static int Lpb_touserdata(lua_State *L) {
2162  pb_Slice s = lpb_toslice(L, 1);
2163  lua_pushlightuserdata(L, (void*)s.p);
2164  lua_pushinteger(L, pb_len(s));
2165  return 2;
2166 }
2167 
2168 static int Lpb_use(lua_State *L) {
2169  const char *opts[] = { "global", "local", NULL };
2170  lpb_State *LS = lpb_lstate(L);
2171  const pb_State *GS = global_state;
2172  switch (luaL_checkoption(L, 1, NULL, opts)) {
2173  case 0: if (GS) LS->state = GS; break;
2174  case 1: LS->state = &LS->local; break;
2175  }
2176  lua_pushboolean(L, GS != NULL);
2177  return 1;
2178 }
2179 
2180 LUALIB_API int luaopen_pb_unsafe(lua_State *L) {
2181  luaL_Reg libs[] = {
2182  { "load", Lpb_load_unsafe },
2183  { "decode", Lpb_decode_unsafe },
2184  { "slice", Lpb_slice_unsafe },
2185  { "touserdata", Lpb_touserdata },
2186  { "use", Lpb_use },
2187  { NULL, NULL }
2188  };
2189  luaL_newlib(L, libs);
2190  return 1;
2191 }
2192 
2193 
2194 PB_NS_END
2195 
2196 /* cc: flags+='-O3 -ggdb -pedantic -std=c90 -Wall -Wextra'
2197  * maccc: flags+='-ggdb -shared -undefined dynamic_lookup' output='pb.so'
2198  * win32cc: flags+='-s -mdll -DLUA_BUILD_AS_DLL ' output='pb.dll' libs+='-llua54' */
2199 
pb_State
Definition: pb.h:315
pb_Cache
Definition: pb.h:310
lpb_Env
Definition: pb.c:1586
lpb_Slice
Definition: pb.c:906
pb_Slice
Definition: pb.h:128
pb_Buffer
Definition: pb.h:170
pb_Type
Definition: pb.h:335
lpb_State
Definition: pb.c:137
pb_Field
Definition: pb.h:322
lpb_Value
Definition: pb.c:384