update sproto lib

This commit is contained in:
Cloud Wu
2014-10-31 16:49:54 +08:00
parent 6c9ad16077
commit 803a79059a
2 changed files with 155 additions and 104 deletions

View File

@@ -62,18 +62,20 @@ ldeleteproto(lua_State *L) {
static int static int
lquerytype(lua_State *L) { lquerytype(lua_State *L) {
const char * type_name;
struct sproto *sp = lua_touserdata(L,1); struct sproto *sp = lua_touserdata(L,1);
struct sproto_type *st;
if (sp == NULL) { if (sp == NULL) {
return luaL_argerror(L, 1, "Need a sproto object"); return luaL_argerror(L, 1, "Need a sproto object");
} }
const char * typename = luaL_checkstring(L,2); type_name = luaL_checkstring(L,2);
struct sproto_type *st = sproto_type(sp, typename); st = sproto_type(sp, type_name);
if (st) { if (st) {
lua_pushlightuserdata(L, st); lua_pushlightuserdata(L, st);
return 1; return 1;
} }
return luaL_error(L, "type %s not found", typename); return luaL_error(L, "type %s not found", type_name);
} }
struct encode_ud { struct encode_ud {
@@ -119,9 +121,10 @@ encode(void *ud, const char *tagname, int type, int index, struct sproto_type *s
switch (type) { switch (type) {
case SPROTO_TINTEGER: { case SPROTO_TINTEGER: {
lua_Integer v = luaL_checkinteger(L, -1); lua_Integer v = luaL_checkinteger(L, -1);
lua_Integer vh;
lua_pop(L,1); lua_pop(L,1);
// notice: in lua 5.2, lua_Integer maybe 52bit // notice: in lua 5.2, lua_Integer maybe 52bit
lua_Integer vh = v >> 31; vh = v >> 31;
if (vh == 0 || vh == -1) { if (vh == 0 || vh == -1) {
*(uint32_t *)value = (uint32_t)v; *(uint32_t *)value = (uint32_t)v;
return 4; return 4;
@@ -148,13 +151,14 @@ encode(void *ud, const char *tagname, int type, int index, struct sproto_type *s
} }
case SPROTO_TSTRUCT: { case SPROTO_TSTRUCT: {
struct encode_ud sub; struct encode_ud sub;
int r;
sub.L = L; sub.L = L;
sub.st = st; sub.st = st;
sub.tbl_index = lua_gettop(L); sub.tbl_index = lua_gettop(L);
sub.array_tag = NULL; sub.array_tag = NULL;
sub.array_index = 0; sub.array_index = 0;
sub.deep = self->deep + 1; sub.deep = self->deep + 1;
int r = sproto_encode(st, value, length, encode, &sub); r = sproto_encode(st, value, length, encode, &sub);
lua_pop(L,1); lua_pop(L,1);
return r; return r;
} }
@@ -165,6 +169,7 @@ encode(void *ud, const char *tagname, int type, int index, struct sproto_type *s
static void * static void *
expand_buffer(lua_State *L, int osz, int nsz) { expand_buffer(lua_State *L, int osz, int nsz) {
void *output;
do { do {
osz *= 2; osz *= 2;
} while (osz < nsz); } while (osz < nsz);
@@ -172,7 +177,7 @@ expand_buffer(lua_State *L, int osz, int nsz) {
luaL_error(L, "object is too large (>%d)", ENCODE_MAXSIZE); luaL_error(L, "object is too large (>%d)", ENCODE_MAXSIZE);
return NULL; return NULL;
} }
void *output = lua_newuserdata(L, osz); output = lua_newuserdata(L, osz);
lua_replace(L, lua_upvalueindex(1)); lua_replace(L, lua_upvalueindex(1));
lua_pushinteger(L, osz); lua_pushinteger(L, osz);
lua_replace(L, lua_upvalueindex(2)); lua_replace(L, lua_upvalueindex(2));
@@ -188,6 +193,7 @@ expand_buffer(lua_State *L, int osz, int nsz) {
*/ */
static int static int
lencode(lua_State *L) { lencode(lua_State *L) {
struct encode_ud self;
void * buffer = lua_touserdata(L, lua_upvalueindex(1)); void * buffer = lua_touserdata(L, lua_upvalueindex(1));
int sz = lua_tointeger(L, lua_upvalueindex(2)); int sz = lua_tointeger(L, lua_upvalueindex(2));
@@ -197,7 +203,6 @@ lencode(lua_State *L) {
} }
luaL_checktype(L, 2, LUA_TTABLE); luaL_checktype(L, 2, LUA_TTABLE);
luaL_checkstack(L, ENCODE_DEEPLEVEL + 8, NULL); luaL_checkstack(L, ENCODE_DEEPLEVEL + 8, NULL);
struct encode_ud self;
self.L = L; self.L = L;
self.st = st; self.st = st;
self.tbl_index = 2; self.tbl_index = 2;
@@ -261,15 +266,16 @@ decode(void *ud, const char *tagname, int type, int index, struct sproto_type *s
break; break;
} }
case SPROTO_TSTRUCT: { case SPROTO_TSTRUCT: {
lua_newtable(L);
struct decode_ud sub; struct decode_ud sub;
int r;
lua_newtable(L);
sub.L = L; sub.L = L;
sub.result_index = lua_gettop(L); sub.result_index = lua_gettop(L);
sub.deep = self->deep + 1; sub.deep = self->deep + 1;
sub.array_index = 0; sub.array_index = 0;
sub.array_tag = NULL; sub.array_tag = NULL;
int r = sproto_decode(st, value, length, decode, &sub); r = sproto_decode(st, value, length, decode, &sub);
if (r < 0 || r != length) if (r < 0 || r != length)
return r; return r;
lua_settop(L, sub.result_index); lua_settop(L, sub.result_index);
@@ -312,22 +318,25 @@ getbuffer(lua_State *L, int index, size_t *sz) {
static int static int
ldecode(lua_State *L) { ldecode(lua_State *L) {
struct sproto_type * st = lua_touserdata(L, 1); struct sproto_type * st = lua_touserdata(L, 1);
const void * buffer;
struct decode_ud self;
size_t sz;
int r;
if (st == NULL) { if (st == NULL) {
return luaL_argerror(L, 1, "Need a sproto_type object"); return luaL_argerror(L, 1, "Need a sproto_type object");
} }
size_t sz=0; sz = 0;
const void * buffer = getbuffer(L, 2, &sz); buffer = getbuffer(L, 2, &sz);
if (!lua_istable(L, -1)) { if (!lua_istable(L, -1)) {
lua_newtable(L); lua_newtable(L);
} }
luaL_checkstack(L, ENCODE_DEEPLEVEL*2 + 8, NULL); luaL_checkstack(L, ENCODE_DEEPLEVEL*2 + 8, NULL);
struct decode_ud self;
self.L = L; self.L = L;
self.result_index = lua_gettop(L); self.result_index = lua_gettop(L);
self.array_index = 0; self.array_index = 0;
self.array_tag = NULL; self.array_tag = NULL;
self.deep = 0; self.deep = 0;
int r = sproto_decode(st, buffer, (int)sz, decode, &self); r = sproto_decode(st, buffer, (int)sz, decode, &self);
if (r < 0) { if (r < 0) {
return luaL_error(L, "decode error"); return luaL_error(L, "decode error");
} }
@@ -359,11 +368,12 @@ lpack(lua_State *L) {
// the worst-case space overhead of packing is 2 bytes per 2 KiB of input (256 words = 2KiB). // the worst-case space overhead of packing is 2 bytes per 2 KiB of input (256 words = 2KiB).
size_t maxsz = (sz + 2047) / 2048 * 2 + sz; size_t maxsz = (sz + 2047) / 2048 * 2 + sz;
void * output = lua_touserdata(L, lua_upvalueindex(1)); void * output = lua_touserdata(L, lua_upvalueindex(1));
int bytes;
int osz = lua_tointeger(L, lua_upvalueindex(2)); int osz = lua_tointeger(L, lua_upvalueindex(2));
if (osz < maxsz) { if (osz < maxsz) {
output = expand_buffer(L, osz, maxsz); output = expand_buffer(L, osz, maxsz);
} }
int bytes = sproto_pack(buffer, sz, output, maxsz); bytes = sproto_pack(buffer, sz, output, maxsz);
if (bytes > maxsz) { if (bytes > maxsz) {
return luaL_error(L, "packing error, return size = %d", bytes); return luaL_error(L, "packing error, return size = %d", bytes);
} }
@@ -402,14 +412,18 @@ pushfunction_withbuffer(lua_State *L, const char * name, lua_CFunction func) {
static int static int
lprotocol(lua_State *L) { lprotocol(lua_State *L) {
struct sproto * sp = lua_touserdata(L, 1); struct sproto * sp = lua_touserdata(L, 1);
struct sproto_type * request;
struct sproto_type * response;
int t;
int tag;
if (sp == NULL) { if (sp == NULL) {
return luaL_argerror(L, 1, "Need a sproto_type object"); return luaL_argerror(L, 1, "Need a sproto_type object");
} }
int t = lua_type(L,2); t = lua_type(L,2);
int tag;
if (t == LUA_TNUMBER) { if (t == LUA_TNUMBER) {
const char * name;
tag = lua_tointeger(L, 2); tag = lua_tointeger(L, 2);
const char * name = sproto_protoname(sp, tag); name = sproto_protoname(sp, tag);
if (name == NULL) if (name == NULL)
return 0; return 0;
lua_pushstring(L, name); lua_pushstring(L, name);
@@ -420,13 +434,13 @@ lprotocol(lua_State *L) {
return 0; return 0;
lua_pushinteger(L, tag); lua_pushinteger(L, tag);
} }
struct sproto_type * request = sproto_protoquery(sp, tag, SPROTO_REQUEST); request = sproto_protoquery(sp, tag, SPROTO_REQUEST);
if (request == NULL) { if (request == NULL) {
lua_pushnil(L); lua_pushnil(L);
} else { } else {
lua_pushlightuserdata(L, request); lua_pushlightuserdata(L, request);
} }
struct sproto_type * response = sproto_protoquery(sp, tag, SPROTO_RESPONSE); response = sproto_protoquery(sp, tag, SPROTO_RESPONSE);
if (response == NULL) { if (response == NULL) {
lua_pushnil(L); lua_pushnil(L);
} else { } else {

View File

@@ -119,8 +119,8 @@ todword(const uint8_t *p) {
static int static int
count_array(const uint8_t * stream) { count_array(const uint8_t * stream) {
uint32_t length = todword(stream); uint32_t length = todword(stream);
stream += SIZEOF_LENGTH;
int n = 0; int n = 0;
stream += SIZEOF_LENGTH;
while (length > 0) { while (length > 0) {
uint32_t nsz; uint32_t nsz;
if (length < SIZEOF_LENGTH) if (length < SIZEOF_LENGTH)
@@ -180,6 +180,10 @@ static const uint8_t *
import_field(struct sproto *s, struct field *f, const uint8_t * stream) { import_field(struct sproto *s, struct field *f, const uint8_t * stream) {
uint32_t sz; uint32_t sz;
const uint8_t * result; const uint8_t * result;
int fn;
int i;
int array = 0;
int tag = -1;
f->tag = -1; f->tag = -1;
f->type = -1; f->type = -1;
f->name = NULL; f->name = NULL;
@@ -188,13 +192,10 @@ import_field(struct sproto *s, struct field *f, const uint8_t * stream) {
sz = todword(stream); sz = todword(stream);
stream += SIZEOF_LENGTH; stream += SIZEOF_LENGTH;
result = stream + sz; result = stream + sz;
int fn = struct_field(stream, sz); fn = struct_field(stream, sz);
if (fn < 0) if (fn < 0)
return NULL; return NULL;
stream += SIZEOF_HEADER; stream += SIZEOF_HEADER;
int i;
int array = 0;
int tag = -1;
for (i=0;i<fn;i++) { for (i=0;i<fn;i++) {
int value; int value;
++tag; ++tag;
@@ -259,11 +260,16 @@ import_field(struct sproto *s, struct field *f, const uint8_t * stream) {
*/ */
static const uint8_t * static const uint8_t *
import_type(struct sproto *s, struct sproto_type *t, const uint8_t * stream) { import_type(struct sproto *s, struct sproto_type *t, const uint8_t * stream) {
const uint8_t * result;
uint32_t sz = todword(stream); uint32_t sz = todword(stream);
int i; int i;
int fn;
int n;
int maxn;
int last;
stream += SIZEOF_LENGTH; stream += SIZEOF_LENGTH;
const uint8_t * result = stream + sz; result = stream + sz;
int fn = struct_field(stream, sz); fn = struct_field(stream, sz);
if (fn <= 0 || fn > 2) if (fn <= 0 || fn > 2)
return NULL; return NULL;
for (i=0;i<fn*SIZEOF_FIELD;i+=SIZEOF_FIELD) { for (i=0;i<fn*SIZEOF_FIELD;i+=SIZEOF_FIELD) {
@@ -279,20 +285,21 @@ import_type(struct sproto *s, struct sproto_type *t, const uint8_t * stream) {
return result; return result;
} }
stream += todword(stream)+SIZEOF_LENGTH; // second data stream += todword(stream)+SIZEOF_LENGTH; // second data
int n = count_array(stream); n = count_array(stream);
if (n<0) if (n<0)
return NULL; return NULL;
stream += SIZEOF_LENGTH; stream += SIZEOF_LENGTH;
int maxn = n; maxn = n;
int last = -1; last = -1;
t->n = n; t->n = n;
t->f = pool_alloc(&s->memory, sizeof(struct field) * n); t->f = pool_alloc(&s->memory, sizeof(struct field) * n);
for (i=0;i<n;i++) { for (i=0;i<n;i++) {
int tag;
struct field *f = &t->f[i]; struct field *f = &t->f[i];
stream = import_field(s, f, stream); stream = import_field(s, f, stream);
if (stream == NULL) if (stream == NULL)
return NULL; return NULL;
int tag = f->tag; tag = f->tag;
if (tag < last) if (tag < last)
return NULL; // tag must in ascending order return NULL; // tag must in ascending order
if (tag > last+1) { if (tag > last+1) {
@@ -319,17 +326,20 @@ import_type(struct sproto *s, struct sproto_type *t, const uint8_t * stream) {
*/ */
static const uint8_t * static const uint8_t *
import_protocol(struct sproto *s, struct protocol *p, const uint8_t * stream) { import_protocol(struct sproto *s, struct protocol *p, const uint8_t * stream) {
const uint8_t * result;
uint32_t sz = todword(stream); uint32_t sz = todword(stream);
int fn;
int i;
int tag;
stream += SIZEOF_LENGTH; stream += SIZEOF_LENGTH;
const uint8_t * result = stream + sz; result = stream + sz;
int fn = struct_field(stream, sz); fn = struct_field(stream, sz);
stream += SIZEOF_HEADER; stream += SIZEOF_HEADER;
p->name = NULL; p->name = NULL;
p->tag = -1; p->tag = -1;
p->p[SPROTO_REQUEST] = NULL; p->p[SPROTO_REQUEST] = NULL;
p->p[SPROTO_RESPONSE] = NULL; p->p[SPROTO_RESPONSE] = NULL;
int i; tag = 0;
int tag = 0;
for (i=0;i<fn;i++,tag++) { for (i=0;i<fn;i++,tag++) {
int value = toword(stream + SIZEOF_FIELD * i); int value = toword(stream + SIZEOF_FIELD * i);
if (value & 1) { if (value & 1) {
@@ -374,22 +384,23 @@ import_protocol(struct sproto *s, struct protocol *p, const uint8_t * stream) {
static struct sproto * static struct sproto *
create_from_bundle(struct sproto *s, const uint8_t * stream, size_t sz) { create_from_bundle(struct sproto *s, const uint8_t * stream, size_t sz) {
const uint8_t * content;
const uint8_t * typedata = NULL;
const uint8_t * protocoldata = NULL;
int fn = struct_field(stream, sz); int fn = struct_field(stream, sz);
int i;
if (fn < 0) if (fn < 0)
return NULL; return NULL;
stream += SIZEOF_HEADER; stream += SIZEOF_HEADER;
content = stream + fn*SIZEOF_FIELD;
const uint8_t * content = stream + fn*SIZEOF_FIELD;
const uint8_t * typedata = NULL;
const uint8_t * protocoldata = NULL;
int i;
for (i=0;i<fn;i++) { for (i=0;i<fn;i++) {
int value = toword(stream + i*SIZEOF_FIELD); int value = toword(stream + i*SIZEOF_FIELD);
int n;
if (value != 0) if (value != 0)
return NULL; return NULL;
int n = count_array(content); n = count_array(content);
if (n<0) if (n<0)
return NULL; return NULL;
if (i == 0) { if (i == 0) {
@@ -423,8 +434,9 @@ create_from_bundle(struct sproto *s, const uint8_t * stream, size_t sz) {
struct sproto * struct sproto *
sproto_create(const void * proto, size_t sz) { sproto_create(const void * proto, size_t sz) {
struct pool mem; struct pool mem;
struct sproto * s;
pool_init(&mem); pool_init(&mem);
struct sproto * s = pool_alloc(&mem, sizeof(*s)); s = pool_alloc(&mem, sizeof(*s));
if (s == NULL) if (s == NULL)
return NULL; return NULL;
memset(s, 0, sizeof(*s)); memset(s, 0, sizeof(*s));
@@ -445,34 +457,35 @@ sproto_release(struct sproto * s) {
void void
sproto_dump(struct sproto *s) { sproto_dump(struct sproto *s) {
int i,j;
static const char * buildin[] = { static const char * buildin[] = {
"integer", "integer",
"boolean", "boolean",
"string", "string",
}; };
printf("=== %d types ===\n", s->type_n); printf("=== %d types ===\n", s->type_n);
int i,j;
for (i=0;i<s->type_n;i++) { for (i=0;i<s->type_n;i++) {
struct sproto_type *t = &s->type[i]; struct sproto_type *t = &s->type[i];
printf("%s\n", t->name); printf("%s\n", t->name);
for (j=0;j<t->n;j++) { for (j=0;j<t->n;j++) {
char array[2] = { 0, 0 }; char array[2] = { 0, 0 };
const char * typename = NULL; const char * type_name = NULL;
struct field *f = &t->f[j]; struct field *f = &t->f[j];
if (f->type & SPROTO_TARRAY) { if (f->type & SPROTO_TARRAY) {
array[0] = '*'; array[0] = '*';
} else { } else {
array[0] = 0; array[0] = 0;
} }
{
int t = f->type & ~SPROTO_TARRAY; int t = f->type & ~SPROTO_TARRAY;
if (t == SPROTO_TSTRUCT) { if (t == SPROTO_TSTRUCT) {
typename = f->st->name; type_name = f->st->name;
} else { } else {
assert(t<SPROTO_TSTRUCT); assert(t<SPROTO_TSTRUCT);
typename = buildin[t]; type_name = buildin[t];
} }
}
printf("\t%s (%d) %s%s\n", f->name, f->tag, array, typename); printf("\t%s (%d) %s%s\n", f->name, f->tag, array, type_name);
} }
} }
printf("=== %d protocol ===\n", s->protocol_n); printf("=== %d protocol ===\n", s->protocol_n);
@@ -518,10 +531,11 @@ query_proto(struct sproto *sp, int tag) {
struct sproto_type * struct sproto_type *
sproto_protoquery(struct sproto *sp, int proto, int what) { sproto_protoquery(struct sproto *sp, int proto, int what) {
struct protocol * p;
if (what <0 || what >1) { if (what <0 || what >1) {
return NULL; return NULL;
} }
struct protocol * p = query_proto(sp, proto); p = query_proto(sp, proto);
if (p) { if (p) {
return p->p[what]; return p->p[what];
} }
@@ -555,13 +569,15 @@ sproto_name(struct sproto_type * st) {
static struct field * static struct field *
findtag(struct sproto_type *st, int tag) { findtag(struct sproto_type *st, int tag) {
int begin, end;
if (st->base >=0 ) { if (st->base >=0 ) {
tag -= st->base; tag -= st->base;
if (tag < 0 || tag >= st->n) if (tag < 0 || tag >= st->n)
return NULL; return NULL;
return &st->f[tag]; return &st->f[tag];
} }
int begin = 0, end = st->n; begin = 0;
end = st->n;
while (begin < end) { while (begin < end) {
int mid = (begin+end)/2; int mid = (begin+end)/2;
struct field *f = &st->f[mid]; struct field *f = &st->f[mid];
@@ -623,18 +639,20 @@ encode_uint64(uint64_t v, uint8_t * data, int size) {
static int static int
encode_string(sproto_callback cb, void *ud, struct field *f, uint8_t *data, int size) { encode_string(sproto_callback cb, void *ud, struct field *f, uint8_t *data, int size) {
int sz;
if (size < SIZEOF_LENGTH) if (size < SIZEOF_LENGTH)
return -1; return -1;
int sz = cb(ud, f->name, SPROTO_TSTRING, 0, NULL, data+SIZEOF_LENGTH, size-SIZEOF_LENGTH); sz = cb(ud, f->name, SPROTO_TSTRING, 0, NULL, data+SIZEOF_LENGTH, size-SIZEOF_LENGTH);
return fill_size(data, sz); return fill_size(data, sz);
} }
static int static int
encode_struct(sproto_callback cb, void *ud, struct field *f, uint8_t *data, int size) { encode_struct(sproto_callback cb, void *ud, struct field *f, uint8_t *data, int size) {
int sz;
if (size < SIZEOF_LENGTH) { if (size < SIZEOF_LENGTH) {
return -1; return -1;
} }
int sz = cb(ud, f->name, SPROTO_TSTRUCT, 0, f->st, data+SIZEOF_LENGTH, size-SIZEOF_LENGTH); sz = cb(ud, f->name, SPROTO_TSTRUCT, 0, f->st, data+SIZEOF_LENGTH, size-SIZEOF_LENGTH);
return fill_size(data, sz); return fill_size(data, sz);
} }
@@ -656,18 +674,21 @@ uint32_to_uint64(int negative, uint8_t *buffer) {
static uint8_t * static uint8_t *
encode_integer_array(sproto_callback cb, void *ud, struct field *f, uint8_t *buffer, int size) { encode_integer_array(sproto_callback cb, void *ud, struct field *f, uint8_t *buffer, int size) {
uint8_t * header = buffer; uint8_t * header = buffer;
int intlen;
int index;
if (size < 1) if (size < 1)
return NULL; return NULL;
buffer++; buffer++;
size--; size--;
int intlen = sizeof(uint32_t); intlen = sizeof(uint32_t);
int index = 1; index = 1;
for (;;) { for (;;) {
int sz;
union { union {
uint64_t u64; uint64_t u64;
uint32_t u32; uint32_t u32;
} u; } u;
int sz = cb(ud, f->name, SPROTO_TINTEGER, index, f->st, &u, sizeof(u)); sz = cb(ud, f->name, SPROTO_TINTEGER, index, f->st, &u, sizeof(u));
if (sz < 0) if (sz < 0)
return NULL; return NULL;
if (sz == 0) if (sz == 0)
@@ -685,24 +706,26 @@ encode_integer_array(sproto_callback cb, void *ud, struct field *f, uint8_t *buf
uint32_to_uint64(v & 0x80000000, buffer); uint32_to_uint64(v & 0x80000000, buffer);
} }
} else { } else {
uint64_t v;
if (sz != sizeof(uint64_t)) if (sz != sizeof(uint64_t))
return NULL; return NULL;
if (intlen == sizeof(uint32_t)) { if (intlen == sizeof(uint32_t)) {
int i;
// rearrange // rearrange
size -= (index-1) * sizeof(uint32_t); size -= (index-1) * sizeof(uint32_t);
if (size < sizeof(uint64_t)) if (size < sizeof(uint64_t))
return NULL; return NULL;
buffer += (index-1) * sizeof(uint32_t); buffer += (index-1) * sizeof(uint32_t);
int i;
for (i=index-2;i>=0;i--) { for (i=index-2;i>=0;i--) {
int negative;
memcpy(header+1+i*sizeof(uint64_t), header+1+i*sizeof(uint32_t), sizeof(uint32_t)); memcpy(header+1+i*sizeof(uint64_t), header+1+i*sizeof(uint32_t), sizeof(uint32_t));
int negative = header[1+i*sizeof(uint64_t)+3] & 0x80; negative = header[1+i*sizeof(uint64_t)+3] & 0x80;
uint32_to_uint64(negative, header+1+i*sizeof(uint64_t)); uint32_to_uint64(negative, header+1+i*sizeof(uint64_t));
} }
intlen = sizeof(uint64_t); intlen = sizeof(uint64_t);
} }
uint64_t v = u.u64; v = u.u64;
buffer[0] = v & 0xff; buffer[0] = v & 0xff;
buffer[1] = (v >> 8) & 0xff; buffer[1] = (v >> 8) & 0xff;
buffer[2] = (v >> 16) & 0xff; buffer[2] = (v >> 16) & 0xff;
@@ -727,12 +750,16 @@ encode_integer_array(sproto_callback cb, void *ud, struct field *f, uint8_t *buf
static int static int
encode_array(sproto_callback cb, void *ud, struct field *f, uint8_t *data, int size) { encode_array(sproto_callback cb, void *ud, struct field *f, uint8_t *data, int size) {
uint8_t * buffer;
int index;
int type;
int sz;
if (size < SIZEOF_LENGTH) if (size < SIZEOF_LENGTH)
return -1; return -1;
size -= SIZEOF_LENGTH; size -= SIZEOF_LENGTH;
int index = 1; index = 1;
uint8_t * buffer = data + SIZEOF_LENGTH; buffer = data + SIZEOF_LENGTH;
int type = f->type & ~SPROTO_TARRAY; type = f->type & ~SPROTO_TARRAY;
switch (type) { switch (type) {
case SPROTO_TINTEGER: case SPROTO_TINTEGER:
buffer = encode_integer_array(cb,ud,f,buffer,size); buffer = encode_integer_array(cb,ud,f,buffer,size);
@@ -757,10 +784,11 @@ encode_array(sproto_callback cb, void *ud, struct field *f, uint8_t *data, int s
break; break;
default: default:
for (;;) { for (;;) {
int sz;
if (size < SIZEOF_LENGTH) if (size < SIZEOF_LENGTH)
return -1; return -1;
size -= SIZEOF_LENGTH; size -= SIZEOF_LENGTH;
int sz = cb(ud, f->name, type, index, f->st, buffer+SIZEOF_LENGTH, size); sz = cb(ud, f->name, type, index, f->st, buffer+SIZEOF_LENGTH, size);
if (sz < 0) if (sz < 0)
return -1; return -1;
if (sz == 0) if (sz == 0)
@@ -772,7 +800,7 @@ encode_array(sproto_callback cb, void *ud, struct field *f, uint8_t *data, int s
} }
break; break;
} }
int sz = buffer - (data + SIZEOF_LENGTH); sz = buffer - (data + SIZEOF_LENGTH);
if (sz == 0) if (sz == 0)
return 0; return 0;
return fill_size(data, sz); return fill_size(data, sz);
@@ -783,13 +811,16 @@ sproto_encode(struct sproto_type *st, void * buffer, int size, sproto_callback c
uint8_t * header = buffer; uint8_t * header = buffer;
uint8_t * data; uint8_t * data;
int header_sz = SIZEOF_HEADER + st->maxn * SIZEOF_FIELD; int header_sz = SIZEOF_HEADER + st->maxn * SIZEOF_FIELD;
int i;
int index;
int lasttag;
int datasz;
if (size < header_sz) if (size < header_sz)
return -1; return -1;
data = header + header_sz; data = header + header_sz;
size -= header_sz; size -= header_sz;
int i; index = 0;
int index = 0; lasttag = -1;
int lasttag = -1;
for (i=0;i<st->n;i++) { for (i=0;i<st->n;i++) {
struct field *f = &st->f[i]; struct field *f = &st->f[i];
int type = f->type; int type = f->type;
@@ -837,12 +868,14 @@ sproto_encode(struct sproto_type *st, void * buffer, int size, sproto_callback c
if (sz < 0) if (sz < 0)
return -1; return -1;
if (sz > 0) { if (sz > 0) {
uint8_t * record;
int tag;
if (value == 0) { if (value == 0) {
data += sz; data += sz;
size -= sz; size -= sz;
} }
uint8_t * record = header+SIZEOF_HEADER+SIZEOF_FIELD*index; record = header+SIZEOF_HEADER+SIZEOF_FIELD*index;
int tag = f->tag - lasttag - 1; tag = f->tag - lasttag - 1;
if (tag > 0) { if (tag > 0) {
// skip tag // skip tag
tag = (tag - 1) * 2 + 1; tag = (tag - 1) * 2 + 1;
@@ -862,7 +895,7 @@ sproto_encode(struct sproto_type *st, void * buffer, int size, sproto_callback c
header[0] = index & 0xff; header[0] = index & 0xff;
header[1] = (index >> 8) & 0xff; header[1] = (index >> 8) & 0xff;
int datasz = data - (header + header_sz); datasz = data - (header + header_sz);
data = header + header_sz; data = header + header_sz;
if (index != st->maxn) { if (index != st->maxn) {
memmove(header + SIZEOF_HEADER + index * SIZEOF_FIELD, data, datasz); memmove(header + SIZEOF_HEADER + index * SIZEOF_FIELD, data, datasz);
@@ -909,9 +942,10 @@ decode_array(sproto_callback cb, void *ud, struct field *f, uint8_t * stream) {
stream += SIZEOF_LENGTH; stream += SIZEOF_LENGTH;
switch (type) { switch (type) {
case SPROTO_TINTEGER: { case SPROTO_TINTEGER: {
int len;
if (sz < 1) if (sz < 1)
return -1; return -1;
int len = *stream; len = *stream;
++stream; ++stream;
--sz; --sz;
if (len == sizeof(uint32_t)) { if (len == sizeof(uint32_t)) {
@@ -956,6 +990,8 @@ sproto_decode(struct sproto_type *st, const void * data, int size, sproto_callba
uint8_t * stream; uint8_t * stream;
uint8_t * datastream; uint8_t * datastream;
int fn; int fn;
int i;
int tag;
if (size < SIZEOF_HEADER) if (size < SIZEOF_HEADER)
return -1; return -1;
stream = (void *)data; stream = (void *)data;
@@ -967,17 +1003,18 @@ sproto_decode(struct sproto_type *st, const void * data, int size, sproto_callba
datastream = stream + fn * SIZEOF_FIELD; datastream = stream + fn * SIZEOF_FIELD;
size -= fn * SIZEOF_FIELD ; size -= fn * SIZEOF_FIELD ;
int i; tag = -1;
int tag = -1;
for (i=0;i<fn;i++) { for (i=0;i<fn;i++) {
++ tag; uint8_t * currentdata;
struct field * f;
int value = toword(stream + i * SIZEOF_FIELD); int value = toword(stream + i * SIZEOF_FIELD);
++ tag;
if (value & 1) { if (value & 1) {
tag += value/2; tag += value/2;
continue; continue;
} }
value = value/2 - 1; value = value/2 - 1;
uint8_t * currentdata = datastream; currentdata = datastream;
if (value < 0) { if (value < 0) {
uint32_t sz; uint32_t sz;
if (size < SIZEOF_LENGTH) if (size < SIZEOF_LENGTH)
@@ -988,7 +1025,7 @@ sproto_decode(struct sproto_type *st, const void * data, int size, sproto_callba
datastream += sz+SIZEOF_LENGTH; datastream += sz+SIZEOF_LENGTH;
size -= sz+SIZEOF_LENGTH; size -= sz+SIZEOF_LENGTH;
} }
struct field * f= findtag(st, tag); f = findtag(st, tag);
if (f == NULL) if (f == NULL)
continue; continue;
if (value < 0) { if (value < 0) {