DCCL v4
Loading...
Searching...
No Matches
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
13PB_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
38static int lpb_relindex(int idx, int offset) {
39 return idx < 0 && idx > LUA_REGISTRYINDEX ? idx - offset : idx;
40}
41
42static 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
54static 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
59static 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
68static 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
74static 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
80static 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
97static 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 */
117static int lua53_getfield(lua_State *L, int idx, const char *field)
118{ return lua_getfield(L, idx, field), lua_type(L, -1); }
119static int lua53_rawgeti(lua_State *L, int idx, lua_Integer i)
120{ return lua_rawgeti(L, idx, i), lua_type(L, -1); }
121static 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
131static const pb_State *global_state = NULL;
132static const char state_name[] = PB_STATE;
133
134enum lpb_Int64Mode { LPB_NUMBER, LPB_STRING, LPB_HEXSTRING };
135enum lpb_EncodeMode { LPB_DEFDEF, LPB_COPYDEF, LPB_METADEF, LPB_NODEF };
136
137typedef 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
158static 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
169static void lpb_pushdeftable(lua_State *L, lpb_State *LS)
170{ LS->defs_index = lpb_reftable(L, LS->defs_index); }
171
172static void lpb_pushenchooktable(lua_State *L, lpb_State *LS)
173{ LS->enc_hooks_index = lpb_reftable(L, LS->enc_hooks_index); }
174
175static void lpb_pushdechooktable(lua_State *L, lpb_State *LS)
176{ LS->dec_hooks_index = lpb_reftable(L, LS->dec_hooks_index); }
177
178static 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
194LUALIB_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
216static 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
235static 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
240static 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
245static 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
251static 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
259static 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
270static 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
287LUALIB_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
293static 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
303static 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
316static 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
351static 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
362static 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
384typedef 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
392static 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
406static 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
484static 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
547static 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
561static 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
572static 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
589static 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
598static 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
608LUALIB_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
624static 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
629static 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
634static 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
639static 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
644static 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
649static 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
654static 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
659static 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
664static 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
669static int Lconv_decode_double(lua_State *L) {
670 return lua_pushnumber(L, pb_decode_double(lpb_checkinteger(L, 1))), 1;
671}
672
673LUALIB_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
698static 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
707static 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
757static 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
776static 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
803static 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
810static 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
820static 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
826static 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
836static 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
842static 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
851static 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
857static 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
873LUALIB_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
906typedef 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
914static 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
925static 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
936static 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
950static 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
965static 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
1002static 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
1028static 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
1045static 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
1052static 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
1062static 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
1071static 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
1080static 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
1087static 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
1094static 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
1101static 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
1121static 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
1140static 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
1158LUALIB_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
1165LUALIB_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
1199typedef enum {USE_FIELD = 1, USE_REPEAT = 2, USE_MESSAGE = 4} lpb_DefFlags;
1200
1201static void lpb_pushtypetable(lua_State *L, lpb_State *LS, const pb_Type *t);
1202static void lpb_pushdefmeta(lua_State *L, lpb_State *LS, const pb_Type *t);
1203
1204static 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
1209LUALIB_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
1225static 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
1232static 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
1242static 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
1256static 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
1283static 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
1291static 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
1310static 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
1319static 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
1326static 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
1335static 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
1342static 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
1350static 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
1356static 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
1368static 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
1422static 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
1438static 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
1454static 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
1468static 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
1475static 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
1498static 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
1515static 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
1532static 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
1555static 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
1586typedef struct lpb_Env {
1587 lua_State *L;
1588 lpb_State *LS;
1589 pb_Buffer *b;
1590 pb_Slice *s;
1591} lpb_Env;
1592
1593static void lpbE_encode (lpb_Env *e, const pb_Type *t, int idx);
1594
1595static 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
1601static 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
1614static 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
1641static 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
1669static 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
1678static 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
1697static 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
1725static 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
1734static 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
1757static 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
1777static 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
1790static 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
1814static int lpbD_message(lpb_Env *e, const pb_Type *t);
1815
1816static 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
1829static 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
1850static 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
1881static 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
1894static 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
1899static 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
1923static 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
1940static 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
1973static 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
1987static 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
1994void 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
2008static 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
2028static 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
2054static 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
2066static 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
2106LUALIB_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
2147static 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
2154static 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
2161static 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
2168static 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
2180LUALIB_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
2194PB_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
Definition pb.c:1586
Definition pb.h:310
Definition pb.h:322
Definition pb.h:128
Definition pb.h:315
Definition pb.h:335