mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-24 20:23:06 +00:00
update sproto. support encode empty table
This commit is contained in:
@@ -210,13 +210,13 @@ Each integer number must be serialized in little-endian format.
|
|||||||
The sproto message must be a user defined type struct, and a struct is encoded in three parts. The header, the field part, and the data part.
|
The sproto message must be a user defined type struct, and a struct is encoded in three parts. The header, the field part, and the data part.
|
||||||
The tag and small integer or boolean will be encoded in field part, and others are in data part.
|
The tag and small integer or boolean will be encoded in field part, and others are in data part.
|
||||||
|
|
||||||
All the fields must be encoded in ascending order (by tag). The tags of fields can be discontinuous, if a field is nil. (default value in lua), don't encode it in message.
|
All the fields must be encoded in ascending order (by tag, base 0). The tags of fields can be discontinuous, if a field is nil. (default value in lua), don't encode it in message.
|
||||||
|
|
||||||
The header is a 16bit integer. It is the number of fields.
|
The header is a 16bit integer. It is the number of fields.
|
||||||
|
|
||||||
Each field in field part is a 16bit integer (n). If n is zero, that means the field data is encoded in data part ;
|
Each field in field part is a 16bit integer (n). If n is zero, that means the field data is encoded in data part ;
|
||||||
|
|
||||||
If n is even (and not zero), the value of this field is n/2-1 ;
|
If n is even (and not zero), the value of this field is n/2-1 , and the tag increases 1;
|
||||||
|
|
||||||
If n is odd, that means the tags is not continuous, and we should add current tag by (n+1)/2 .
|
If n is odd, that means the tags is not continuous, and we should add current tag by (n+1)/2 .
|
||||||
|
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ encode(const struct sproto_arg *args) {
|
|||||||
lua_replace(L, self->array_index);
|
lua_replace(L, self->array_index);
|
||||||
}
|
}
|
||||||
self->array_index = 0;
|
self->array_index = 0;
|
||||||
return 0;
|
return SPROTO_CB_NOARRAY;
|
||||||
}
|
}
|
||||||
if (!lua_istable(L, -1)) {
|
if (!lua_istable(L, -1)) {
|
||||||
return luaL_error(L, ".*%s(%d) should be a table (Is a %s)",
|
return luaL_error(L, ".*%s(%d) should be a table (Is a %s)",
|
||||||
@@ -147,7 +147,7 @@ encode(const struct sproto_arg *args) {
|
|||||||
// iterate end
|
// iterate end
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
lua_replace(L, self->iter_index);
|
lua_replace(L, self->iter_index);
|
||||||
return 0;
|
return SPROTO_CB_NIL;
|
||||||
}
|
}
|
||||||
lua_insert(L, -2);
|
lua_insert(L, -2);
|
||||||
lua_replace(L, self->iter_index);
|
lua_replace(L, self->iter_index);
|
||||||
@@ -159,7 +159,7 @@ encode(const struct sproto_arg *args) {
|
|||||||
}
|
}
|
||||||
if (lua_isnil(L, -1)) {
|
if (lua_isnil(L, -1)) {
|
||||||
lua_pop(L,1);
|
lua_pop(L,1);
|
||||||
return 0;
|
return SPROTO_CB_NIL;
|
||||||
}
|
}
|
||||||
switch (args->type) {
|
switch (args->type) {
|
||||||
case SPROTO_TINTEGER: {
|
case SPROTO_TINTEGER: {
|
||||||
@@ -203,10 +203,10 @@ encode(const struct sproto_arg *args) {
|
|||||||
str = lua_tolstring(L, -1, &sz);
|
str = lua_tolstring(L, -1, &sz);
|
||||||
}
|
}
|
||||||
if (sz > args->length)
|
if (sz > args->length)
|
||||||
return -1;
|
return SPROTO_CB_ERROR;
|
||||||
memcpy(args->value, str, sz);
|
memcpy(args->value, str, sz);
|
||||||
lua_pop(L,1);
|
lua_pop(L,1);
|
||||||
return sz + 1; // The length of empty string is 1.
|
return sz;
|
||||||
}
|
}
|
||||||
case SPROTO_TSTRUCT: {
|
case SPROTO_TSTRUCT: {
|
||||||
struct encode_ud sub;
|
struct encode_ud sub;
|
||||||
@@ -226,6 +226,8 @@ encode(const struct sproto_arg *args) {
|
|||||||
sub.iter_index = sub.tbl_index + 1;
|
sub.iter_index = sub.tbl_index + 1;
|
||||||
r = sproto_encode(args->subtype, args->value, args->length, encode, &sub);
|
r = sproto_encode(args->subtype, args->value, args->length, encode, &sub);
|
||||||
lua_settop(L, top-1); // pop the value
|
lua_settop(L, top-1); // pop the value
|
||||||
|
if (r < 0)
|
||||||
|
return SPROTO_CB_ERROR;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -309,7 +311,7 @@ decode(const struct sproto_arg *args) {
|
|||||||
lua_State *L = self->L;
|
lua_State *L = self->L;
|
||||||
if (self->deep >= ENCODE_DEEPLEVEL)
|
if (self->deep >= ENCODE_DEEPLEVEL)
|
||||||
return luaL_error(L, "The table is too deep");
|
return luaL_error(L, "The table is too deep");
|
||||||
if (args->index > 0) {
|
if (args->index != 0) {
|
||||||
// It's array
|
// It's array
|
||||||
if (args->tagname != self->array_tag) {
|
if (args->tagname != self->array_tag) {
|
||||||
self->array_tag = args->tagname;
|
self->array_tag = args->tagname;
|
||||||
@@ -321,6 +323,10 @@ decode(const struct sproto_arg *args) {
|
|||||||
} else {
|
} else {
|
||||||
self->array_index = lua_gettop(L);
|
self->array_index = lua_gettop(L);
|
||||||
}
|
}
|
||||||
|
if (args->index < 0) {
|
||||||
|
// It's a empty array, return now.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (args->type) {
|
switch (args->type) {
|
||||||
@@ -355,9 +361,10 @@ decode(const struct sproto_arg *args) {
|
|||||||
sub.key_index = lua_gettop(L);
|
sub.key_index = lua_gettop(L);
|
||||||
|
|
||||||
r = sproto_decode(args->subtype, args->value, args->length, decode, &sub);
|
r = sproto_decode(args->subtype, args->value, args->length, decode, &sub);
|
||||||
if (r < 0 || r != args->length)
|
if (r < 0)
|
||||||
|
return SPROTO_CB_ERROR;
|
||||||
|
if (r != args->length)
|
||||||
return r;
|
return r;
|
||||||
// assert(args->index > 0);
|
|
||||||
lua_pushvalue(L, sub.key_index);
|
lua_pushvalue(L, sub.key_index);
|
||||||
if (lua_isnil(L, -1)) {
|
if (lua_isnil(L, -1)) {
|
||||||
luaL_error(L, "Can't find main index (tag=%d) in [%s]", args->mainindex, args->tagname);
|
luaL_error(L, "Can't find main index (tag=%d) in [%s]", args->mainindex, args->tagname);
|
||||||
@@ -370,7 +377,9 @@ decode(const struct sproto_arg *args) {
|
|||||||
sub.mainindex_tag = -1;
|
sub.mainindex_tag = -1;
|
||||||
sub.key_index = 0;
|
sub.key_index = 0;
|
||||||
r = sproto_decode(args->subtype, args->value, args->length, decode, &sub);
|
r = sproto_decode(args->subtype, args->value, args->length, decode, &sub);
|
||||||
if (r < 0 || r != args->length)
|
if (r < 0)
|
||||||
|
return SPROTO_CB_ERROR;
|
||||||
|
if (r != args->length)
|
||||||
return r;
|
return r;
|
||||||
lua_settop(L, sub.result_index);
|
lua_settop(L, sub.result_index);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -677,10 +677,10 @@ encode_object(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int si
|
|||||||
args->value = data+SIZEOF_LENGTH;
|
args->value = data+SIZEOF_LENGTH;
|
||||||
args->length = size-SIZEOF_LENGTH;
|
args->length = size-SIZEOF_LENGTH;
|
||||||
sz = cb(args);
|
sz = cb(args);
|
||||||
if (sz <= 0)
|
if (sz < 0) {
|
||||||
return sz;
|
if (sz == SPROTO_CB_NIL)
|
||||||
if (args->type == SPROTO_TSTRING) {
|
return 0;
|
||||||
--sz; // the length of null string is 1
|
return -1; // sz == SPROTO_CB_ERROR
|
||||||
}
|
}
|
||||||
assert(sz <= size-SIZEOF_LENGTH); // verify buffer overflow
|
assert(sz <= size-SIZEOF_LENGTH); // verify buffer overflow
|
||||||
return fill_size(data, sz);
|
return fill_size(data, sz);
|
||||||
@@ -702,7 +702,7 @@ uint32_to_uint64(int negative, uint8_t *buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t *
|
static uint8_t *
|
||||||
encode_integer_array(sproto_callback cb, struct sproto_arg *args, uint8_t *buffer, int size) {
|
encode_integer_array(sproto_callback cb, struct sproto_arg *args, uint8_t *buffer, int size, int *noarray) {
|
||||||
uint8_t * header = buffer;
|
uint8_t * header = buffer;
|
||||||
int intlen;
|
int intlen;
|
||||||
int index;
|
int index;
|
||||||
@@ -712,6 +712,8 @@ encode_integer_array(sproto_callback cb, struct sproto_arg *args, uint8_t *buffe
|
|||||||
size--;
|
size--;
|
||||||
intlen = sizeof(uint32_t);
|
intlen = sizeof(uint32_t);
|
||||||
index = 1;
|
index = 1;
|
||||||
|
*noarray = 0;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int sz;
|
int sz;
|
||||||
union {
|
union {
|
||||||
@@ -722,10 +724,15 @@ encode_integer_array(sproto_callback cb, struct sproto_arg *args, uint8_t *buffe
|
|||||||
args->length = sizeof(u);
|
args->length = sizeof(u);
|
||||||
args->index = index;
|
args->index = index;
|
||||||
sz = cb(args);
|
sz = cb(args);
|
||||||
if (sz < 0)
|
if (sz <= 0) {
|
||||||
return NULL;
|
if (sz == SPROTO_CB_NIL) // nil object, end of array
|
||||||
if (sz == 0) // nil object, end of array
|
break;
|
||||||
break;
|
if (sz == SPROTO_CB_NOARRAY) { // no array, don't encode it
|
||||||
|
*noarray = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return NULL; // sz == SPROTO_CB_ERROR
|
||||||
|
}
|
||||||
if (size < sizeof(uint64_t))
|
if (size < sizeof(uint64_t))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (sz == sizeof(uint32_t)) {
|
if (sz == sizeof(uint32_t)) {
|
||||||
@@ -790,11 +797,17 @@ encode_array(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int siz
|
|||||||
size -= SIZEOF_LENGTH;
|
size -= SIZEOF_LENGTH;
|
||||||
buffer = data + SIZEOF_LENGTH;
|
buffer = data + SIZEOF_LENGTH;
|
||||||
switch (args->type) {
|
switch (args->type) {
|
||||||
case SPROTO_TINTEGER:
|
case SPROTO_TINTEGER: {
|
||||||
buffer = encode_integer_array(cb,args,buffer,size);
|
int noarray;
|
||||||
|
buffer = encode_integer_array(cb,args,buffer,size, &noarray);
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (noarray) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SPROTO_TBOOLEAN:
|
case SPROTO_TBOOLEAN:
|
||||||
args->index = 1;
|
args->index = 1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -802,10 +815,13 @@ encode_array(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int siz
|
|||||||
args->value = &v;
|
args->value = &v;
|
||||||
args->length = sizeof(v);
|
args->length = sizeof(v);
|
||||||
sz = cb(args);
|
sz = cb(args);
|
||||||
if (sz < 0)
|
if (sz < 0) {
|
||||||
return -1;
|
if (sz == SPROTO_CB_NIL) // nil object , end of array
|
||||||
if (sz == 0) // nil object , end of array
|
break;
|
||||||
break;
|
if (sz == SPROTO_CB_NOARRAY) // no array, don't encode it
|
||||||
|
return 0;
|
||||||
|
return -1; // sz == SPROTO_CB_ERROR
|
||||||
|
}
|
||||||
if (size < 1)
|
if (size < 1)
|
||||||
return -1;
|
return -1;
|
||||||
buffer[0] = v ? 1: 0;
|
buffer[0] = v ? 1: 0;
|
||||||
@@ -823,12 +839,13 @@ encode_array(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int siz
|
|||||||
args->value = buffer+SIZEOF_LENGTH;
|
args->value = buffer+SIZEOF_LENGTH;
|
||||||
args->length = size;
|
args->length = size;
|
||||||
sz = cb(args);
|
sz = cb(args);
|
||||||
if (sz == 0)
|
if (sz < 0) {
|
||||||
break;
|
if (sz == SPROTO_CB_NIL) {
|
||||||
if (sz < 0)
|
break;
|
||||||
return -1;
|
}
|
||||||
if (args->type == SPROTO_TSTRING) {
|
if (sz == SPROTO_CB_NOARRAY) // no array, don't encode it
|
||||||
--sz;
|
return 0;
|
||||||
|
return -1; // sz == SPROTO_CB_ERROR
|
||||||
}
|
}
|
||||||
fill_size(buffer, sz);
|
fill_size(buffer, sz);
|
||||||
buffer += SIZEOF_LENGTH+sz;
|
buffer += SIZEOF_LENGTH+sz;
|
||||||
@@ -838,8 +855,6 @@ encode_array(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int siz
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sz = buffer - (data + SIZEOF_LENGTH);
|
sz = buffer - (data + SIZEOF_LENGTH);
|
||||||
if (sz == 0) // empty array
|
|
||||||
return 0;
|
|
||||||
return fill_size(data, sz);
|
return fill_size(data, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -885,10 +900,13 @@ sproto_encode(const struct sproto_type *st, void * buffer, int size, sproto_call
|
|||||||
args.value = &u;
|
args.value = &u;
|
||||||
args.length = sizeof(u);
|
args.length = sizeof(u);
|
||||||
sz = cb(&args);
|
sz = cb(&args);
|
||||||
if (sz < 0)
|
if (sz < 0) {
|
||||||
return -1;
|
if (sz == SPROTO_CB_NIL)
|
||||||
if (sz == 0) // nil object
|
continue;
|
||||||
continue;
|
if (sz == SPROTO_CB_NOARRAY) // no array, don't encode it
|
||||||
|
return 0;
|
||||||
|
return -1; // sz == SPROTO_CB_ERROR
|
||||||
|
}
|
||||||
if (sz == sizeof(uint32_t)) {
|
if (sz == sizeof(uint32_t)) {
|
||||||
if (u.u32 < 0x7fff) {
|
if (u.u32 < 0x7fff) {
|
||||||
value = (u.u32+1) * 2;
|
value = (u.u32+1) * 2;
|
||||||
@@ -985,13 +1003,18 @@ decode_array(sproto_callback cb, struct sproto_arg *args, uint8_t * stream) {
|
|||||||
uint32_t sz = todword(stream);
|
uint32_t sz = todword(stream);
|
||||||
int type = args->type;
|
int type = args->type;
|
||||||
int i;
|
int i;
|
||||||
|
if (sz == 0) {
|
||||||
|
// It's empty array, call cb with index == -1 to create the empty array.
|
||||||
|
args->index = -1;
|
||||||
|
args->value = NULL;
|
||||||
|
args->length = 0;
|
||||||
|
cb(args);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
stream += SIZEOF_LENGTH;
|
stream += SIZEOF_LENGTH;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SPROTO_TINTEGER: {
|
case SPROTO_TINTEGER: {
|
||||||
int len;
|
int len = *stream;
|
||||||
if (sz < 1)
|
|
||||||
return -1;
|
|
||||||
len = *stream;
|
|
||||||
++stream;
|
++stream;
|
||||||
--sz;
|
--sz;
|
||||||
if (len == sizeof(uint32_t)) {
|
if (len == sizeof(uint32_t)) {
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ struct sproto_type;
|
|||||||
#define SPROTO_TSTRING 2
|
#define SPROTO_TSTRING 2
|
||||||
#define SPROTO_TSTRUCT 3
|
#define SPROTO_TSTRUCT 3
|
||||||
|
|
||||||
|
#define SPROTO_CB_ERROR -1
|
||||||
|
#define SPROTO_CB_NIL -2
|
||||||
|
#define SPROTO_CB_NOARRAY -3
|
||||||
|
|
||||||
struct sproto * sproto_create(const void * proto, size_t sz);
|
struct sproto * sproto_create(const void * proto, size_t sz);
|
||||||
void sproto_release(struct sproto *);
|
void sproto_release(struct sproto *);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user