Skip to content

Commit c85b85e

Browse files
committed
now we can decode a stream of protobuf.
1 parent d6bcea4 commit c85b85e

File tree

4 files changed

+102
-27
lines changed

4 files changed

+102
-27
lines changed

pb.c

+47-27
Original file line numberDiff line numberDiff line change
@@ -354,10 +354,18 @@ static int Lbuf_tostring(lua_State *L) {
354354
}
355355

356356
static int Lbuf_new(lua_State *L) {
357+
int i, top = lua_gettop(L);
357358
pb_Buffer *buf = (pb_Buffer*)lua_newuserdata(L, sizeof(pb_Buffer));
358359
pb_initbuffer(buf, L);
359360
lua_rawgetp(L, LUA_REGISTRYINDEX, pb_buftype);
360361
lua_setmetatable(L, -2);
362+
for (i = 1; i <= top; ++i) {
363+
size_t len;
364+
const char *s = pb_tolbuffer(L, i, &len);
365+
pb_prepbuffer(buf, len);
366+
memcpy(&buf->buf[buf->used], s, len);
367+
buf->used += len;
368+
}
361369
return 1;
362370
}
363371

@@ -524,7 +532,7 @@ static int Lbuf_clear(lua_State *L) {
524532
static int Lbuf_concat(lua_State *L) {
525533
pb_Buffer *buf = check_buffer(L, 1);
526534
int i, top = lua_gettop(L);
527-
for (i = 2; i < top; ++i) {
535+
for (i = 2; i <= top; ++i) {
528536
size_t len;
529537
const char *s = pb_tolbuffer(L, i, &len);
530538
pb_prepbuffer(buf, len);
@@ -597,7 +605,7 @@ LUALIB_API int luaopen_pb_buffer(lua_State *L) {
597605
typedef struct pb_Decoder {
598606
size_t len;
599607
const char *s;
600-
const char *p, *start, *end;
608+
const char *p, *end;
601609
} pb_Decoder;
602610

603611
static int pb_readvarint(pb_Decoder *dec, uint64_t *pv) {
@@ -800,14 +808,13 @@ static int pb_pushscalar(pb_FBDecoder *dec, int wiretype, int type) {
800808

801809
static void init_decoder(pb_Decoder *dec, lua_State *L, int idx) {
802810
size_t len;
803-
const char *s = luaL_checklstring(L, idx, &len);
811+
const char *s = pb_tolbuffer(L, idx, &len);
804812
lua_Integer i = luaL_optinteger(L, idx+1, 1);
805813
lua_Integer j = luaL_optinteger(L, idx+2, len);
806814
rangerelat(&i, &j, len);
807815
dec->s = s;
808816
dec->len = len;
809817
dec->p = s + i - 1;
810-
dec->start = s;
811818
dec->end = dec->p + j;
812819
lua_pushvalue(L, idx);
813820
lua_rawsetp(L, LUA_REGISTRYINDEX, dec);
@@ -827,7 +834,7 @@ static int Ldec_new(lua_State *L) {
827834
if (lua_gettop(L) == 0) {
828835
dec = (pb_Decoder*)lua_newuserdata(L, sizeof(pb_Decoder));
829836
dec->len = 0;
830-
dec->s = dec->p = dec->start = dec->end = NULL;
837+
dec->s = dec->p = dec->end = NULL;
831838
}
832839
else {
833840
lua_settop(L, 3);
@@ -844,14 +851,14 @@ static int Ldec_reset(lua_State *L) {
844851
lua_pushnil(L);
845852
lua_rawsetp(L, LUA_REGISTRYINDEX, dec);
846853
dec->len = 0;
847-
dec->s = dec->p = dec->start = dec->end = NULL;
854+
dec->s = dec->p = dec->end = NULL;
848855
return 0;
849856
}
850857

851858
static int Ldec_source(lua_State *L) {
852859
pb_Decoder *dec = check_decoder(L, 1);
853-
size_t oi = dec->p - dec->start + 1;
854-
size_t oj = dec->end - dec->start;
860+
size_t oi = dec->p - dec->s + 1;
861+
size_t oj = dec->end - dec->s;
855862
int top = lua_gettop(L);
856863
if (top != 1) lua_settop(L, 3);
857864
lua_rawgetp(L, LUA_REGISTRYINDEX, dec);
@@ -863,34 +870,30 @@ static int Ldec_source(lua_State *L) {
863870

864871
static int Ldec_pos(lua_State *L) {
865872
pb_Decoder *dec = check_decoder(L, 1);
866-
size_t pos = dec->p - dec->start + 1;
873+
size_t pos = dec->p - dec->s + 1;
867874
lua_pushinteger(L, (lua_Integer)pos);
868875
if (lua_gettop(L) != 1) {
869876
lua_Integer npos = posrelat(luaL_optinteger(L, 2, pos),
870-
dec->end - dec->start);
877+
dec->end - dec->s);
871878
if (npos < 1) npos = 1;
872-
dec->p = dec->start + npos - 1;
879+
dec->p = dec->s + npos - 1;
873880
}
874881
return 1;
875882
}
876883

877884
static int Ldec_len(lua_State *L) {
878885
pb_Decoder *dec = check_decoder(L, 1);
879-
size_t len = dec->end - dec->start;
880-
lua_pushinteger(L, (lua_Integer)len);
881-
if (lua_gettop(L) != 1) {
882-
lua_Integer len;
883-
len = luaL_optinteger(L, 2, dec->len);
886+
int type = lua_type(L, 2);
887+
lua_pushinteger(L, (lua_Integer)(dec->end - dec->p));
888+
lua_pushinteger(L, (lua_Integer)dec->len);
889+
if (type <= 0)
890+
dec->end = dec->s + dec->len;
891+
else if (type == LUA_TNUMBER) {
892+
size_t len = (size_t)lua_tointeger(L, 2);
884893
if (len > dec->len) len = dec->len;
885-
dec->end = dec->start + len;
894+
dec->end = dec->s + len;
886895
}
887-
return 1;
888-
}
889-
890-
static int Ldec_rawlen(lua_State *L) {
891-
pb_Decoder *dec = check_decoder(L, 1);
892-
lua_pushinteger(L, (lua_Integer)dec->len);
893-
return 1;
896+
return 2;
894897
}
895898

896899
static int Ldec_finished(lua_State *L) {
@@ -1037,12 +1040,29 @@ static int values_iter(lua_State *L) {
10371040
}
10381041

10391042
static int Ldec_values(lua_State *L) {
1040-
check_buffer(L, 1);
1043+
check_decoder(L, 1);
10411044
lua_pushcfunction(L, values_iter);
10421045
lua_pushvalue(L, 1);
10431046
return 2;
10441047
}
10451048

1049+
static int Ldec_update(lua_State *L) {
1050+
pb_Decoder *dec = check_decoder(L, 1);
1051+
pb_Buffer *buf;
1052+
lua_rawgetp(L, LUA_REGISTRYINDEX, dec);
1053+
if ((buf = testudata(L, -1, pb_buftype)) == NULL)
1054+
return 0;
1055+
if (buf->used == dec->p - dec->s) {
1056+
dec->p = dec->s;
1057+
buf->used = 0;
1058+
}
1059+
dec->p = buf->buf + (dec->p - dec->s);
1060+
dec->s = buf->buf;
1061+
dec->len = buf->used;
1062+
dec->end = buf->buf + buf->used;
1063+
return_self(L);
1064+
}
1065+
10461066
LUALIB_API int luaopen_pb_decoder(lua_State *L) {
10471067
luaL_Reg libs[] = {
10481068
{ "__gc", Ldec_reset },
@@ -1054,16 +1074,16 @@ LUALIB_API int luaopen_pb_decoder(lua_State *L) {
10541074
ENTRY(source),
10551075
ENTRY(pos),
10561076
ENTRY(len),
1057-
ENTRY(rawlen),
10581077
ENTRY(tag),
1059-
ENTRY(varint),
10601078
ENTRY(bytes),
10611079
ENTRY(fixed32),
10621080
ENTRY(fixed64),
1081+
ENTRY(varint),
10631082
ENTRY(fetch),
10641083
ENTRY(skip),
10651084
ENTRY(values),
10661085
ENTRY(finished),
1086+
ENTRY(update),
10671087
#undef ENTRY
10681088
{ NULL, NULL }
10691089
};

test/test.lua

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
package.path = "../?.lua;"..package.path
2+
package.cpath = "../?.dll;../?.so;"..package.cpath
13
local decoder = require "pb.decoder"
24
local serpent = require "serpent"
35

test/test_protobuf.lua

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
package.path = "../?.lua;"..package.path
2+
package.cpath = "../?.dll;../?.so;"..package.cpath
13
local protobuf = require "pb"
24
t = protobuf.loadfile "addressbook.pb"
35

test/test_stream.lua

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package.path = "../?.lua;"..package.path
2+
package.cpath = "../?.dll;../?.so;"..package.cpath
3+
local decoder = require "pb.decoder"
4+
local buffer = require "pb.buffer"
5+
6+
local buf = buffer.new()
7+
local dec = decoder.new(buf)
8+
9+
print(dec:pos(), #dec, #buf) -- 1, 0, 0
10+
assert(dec:varint() == nil)
11+
12+
-- add a varint
13+
buf:varint(150)
14+
print(dec:pos(), #dec, #buf) -- 1, 0, 2
15+
16+
-- update decoder
17+
dec:update()
18+
print(dec:pos(), #dec, #buf) -- 1, 2, 2
19+
assert(dec:varint() == 150)
20+
21+
-- clear readed buffer
22+
dec:update()
23+
print(dec:pos(), #dec, #buf) -- 1, 0, 0
24+
25+
-- add imcomplete bytes message
26+
buf:varint(10)
27+
buf:concat("abcde")
28+
print(dec:pos(), #dec, #buf) -- 1, 0, 6
29+
30+
-- update decoder
31+
dec:update()
32+
print(dec:pos(), #dec, #buf) -- 1, 6, 6
33+
34+
-- can not read anything now (bytes imcomplete)
35+
assert(dec:bytes() == nil)
36+
dec:update() -- does nothing
37+
print(dec:pos(), #dec, #buf) -- 1, 6, 6
38+
39+
-- now complete bytes
40+
buf:concat("fghij")
41+
print(dec:pos(), #dec, #buf) -- 1, 6, 11
42+
43+
-- update decoder
44+
dec:update()
45+
print(dec:pos(), #dec, #buf) -- 1, 11, 11
46+
47+
48+
-- now we read whole message
49+
assert(dec:bytes() == "abcdefghij")
50+
51+
print "ok"

0 commit comments

Comments
 (0)