merge sproto

This commit is contained in:
Cloud Wu
2017-03-14 20:56:49 +08:00
parent 1cdc0d7558
commit 48034ae22e
4 changed files with 103 additions and 33 deletions

View File

@@ -166,10 +166,16 @@ encode(const struct sproto_arg *args) {
lua_Integer v; lua_Integer v;
lua_Integer vh; lua_Integer vh;
int isnum; int isnum;
v = lua_tointegerx(L, -1, &isnum); if (args->extra) {
if(!isnum) { // It's decimal.
return luaL_error(L, ".%s[%d] is not an integer (Is a %s)", lua_Number vn = lua_tonumber(L, -1);
args->tagname, args->index, lua_typename(L, lua_type(L, -1))); v = (lua_Integer)(vn * args->extra + 0.5);
} else {
v = lua_tointegerx(L, -1, &isnum);
if(!isnum) {
return luaL_error(L, ".%s[%d] is not an integer (Is a %s)",
args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
}
} }
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
@@ -332,8 +338,15 @@ decode(const struct sproto_arg *args) {
switch (args->type) { switch (args->type) {
case SPROTO_TINTEGER: { case SPROTO_TINTEGER: {
// notice: in lua 5.2, 52bit integer support (not 64) // notice: in lua 5.2, 52bit integer support (not 64)
lua_Integer v = *(uint64_t*)args->value; if (args->extra) {
lua_pushinteger(L, v); lua_Integer v = *(uint64_t*)args->value;
lua_Number vn = (lua_Number)v;
vn /= args->extra;
lua_pushnumber(L, vn);
} else {
lua_Integer v = *(uint64_t*)args->value;
lua_pushinteger(L, v);
}
break; break;
} }
case SPROTO_TBOOLEAN: { case SPROTO_TBOOLEAN: {
@@ -660,7 +673,7 @@ ldefault(lua_State *L) {
return 1; return 1;
} }
int LUAMOD_API int
luaopen_sproto_core(lua_State *L) { luaopen_sproto_core(lua_State *L) {
#ifdef luaL_checkversion #ifdef luaL_checkversion
luaL_checkversion(L); luaL_checkversion(L);

View File

@@ -18,6 +18,7 @@ struct field {
const char * name; const char * name;
struct sproto_type * st; struct sproto_type * st;
int key; int key;
int extra;
}; };
struct sproto_type { struct sproto_type {
@@ -177,6 +178,18 @@ import_string(struct sproto *s, const uint8_t * stream) {
return buffer; return buffer;
} }
static int
calc_pow(int base, int n) {
int r;
if (n == 0)
return 1;
r = calc_pow(base * base , n / 2);
if (n&1) {
r *= base;
}
return r;
}
static const uint8_t * 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;
@@ -190,6 +203,7 @@ import_field(struct sproto *s, struct field *f, const uint8_t * stream) {
f->name = NULL; f->name = NULL;
f->st = NULL; f->st = NULL;
f->key = -1; f->key = -1;
f->extra = 0;
sz = todword(stream); sz = todword(stream);
stream += SIZEOF_LENGTH; stream += SIZEOF_LENGTH;
@@ -222,12 +236,18 @@ import_field(struct sproto *s, struct field *f, const uint8_t * stream) {
f->type = value; f->type = value;
break; break;
case 2: // type index case 2: // type index
if (value >= s->type_n) if (f->type == SPROTO_TINTEGER) {
return NULL; // invalid type index f->extra = calc_pow(10, value);
if (f->type >= 0) } else if (f->type == SPROTO_TSTRING) {
return NULL; f->extra = value; // string if 0 ; binary is 1
f->type = SPROTO_TSTRUCT; } else {
f->st = &s->type[value]; if (value >= s->type_n)
return NULL; // invalid type index
if (f->type >= 0)
return NULL;
f->type = SPROTO_TSTRUCT;
f->st = &s->type[value];
}
break; break;
case 3: // tag case 3: // tag
f->tag = value; f->tag = value;
@@ -463,11 +483,6 @@ sproto_release(struct sproto * s) {
void void
sproto_dump(struct sproto *s) { sproto_dump(struct sproto *s) {
int i,j; int i,j;
static const char * buildin[] = {
"integer",
"boolean",
"string",
};
printf("=== %d types ===\n", s->type_n); printf("=== %d types ===\n", s->type_n);
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];
@@ -476,25 +491,45 @@ sproto_dump(struct sproto *s) {
char array[2] = { 0, 0 }; char array[2] = { 0, 0 };
const char * type_name = NULL; const char * type_name = NULL;
struct field *f = &t->f[j]; struct field *f = &t->f[j];
int type = f->type & ~SPROTO_TARRAY;
if (f->type & SPROTO_TARRAY) { if (f->type & SPROTO_TARRAY) {
array[0] = '*'; array[0] = '*';
} else { } else {
array[0] = 0; array[0] = 0;
} }
{ if (type == SPROTO_TSTRUCT) {
int t = f->type & ~SPROTO_TARRAY; type_name = f->st->name;
if (t == SPROTO_TSTRUCT) { } else {
type_name = f->st->name; switch(type) {
} else { case SPROTO_TINTEGER:
assert(t<SPROTO_TSTRUCT); if (f->extra) {
type_name = buildin[t]; type_name = "decimal";
} else {
type_name = "integer";
}
break;
case SPROTO_TBOOLEAN:
type_name = "boolean";
break;
case SPROTO_TSTRING:
if (f->extra == SPROTO_TSTRING_BINARY)
type_name = "binary";
else
type_name = "string";
break;
default:
type_name = "invalid";
break;
} }
} }
if (f->key >= 0) { printf("\t%s (%d) %s%s", f->name, f->tag, array, type_name);
printf("\t%s (%d) %s%s(%d)\n", f->name, f->tag, array, type_name, f->key); if (type == SPROTO_TINTEGER && f->extra > 0) {
} else { printf("(%d)", f->extra);
printf("\t%s (%d) %s%s\n", f->name, f->tag, array, type_name);
} }
if (f->key >= 0) {
printf("[%d]", f->key);
}
printf("\n");
} }
} }
printf("=== %d protocol ===\n", s->protocol_n); printf("=== %d protocol ===\n", s->protocol_n);
@@ -884,6 +919,7 @@ sproto_encode(const struct sproto_type *st, void * buffer, int size, sproto_call
args.tagid = f->tag; args.tagid = f->tag;
args.subtype = f->st; args.subtype = f->st;
args.mainindex = f->key; args.mainindex = f->key;
args.extra = f->extra;
if (type & SPROTO_TARRAY) { if (type & SPROTO_TARRAY) {
args.type = type & ~SPROTO_TARRAY; args.type = type & ~SPROTO_TARRAY;
sz = encode_array(cb, &args, data, size); sz = encode_array(cb, &args, data, size);
@@ -1116,6 +1152,7 @@ sproto_decode(const struct sproto_type *st, const void * data, int size, sproto_
args.subtype = f->st; args.subtype = f->st;
args.index = 0; args.index = 0;
args.mainindex = f->key; args.mainindex = f->key;
args.extra = f->extra;
if (value < 0) { if (value < 0) {
if (f->type & SPROTO_TARRAY) { if (f->type & SPROTO_TARRAY) {
if (decode_array(cb, &args, currentdata)) { if (decode_array(cb, &args, currentdata)) {

View File

@@ -9,11 +9,16 @@ struct sproto_type;
#define SPROTO_REQUEST 0 #define SPROTO_REQUEST 0
#define SPROTO_RESPONSE 1 #define SPROTO_RESPONSE 1
// type (sproto_arg.type)
#define SPROTO_TINTEGER 0 #define SPROTO_TINTEGER 0
#define SPROTO_TBOOLEAN 1 #define SPROTO_TBOOLEAN 1
#define SPROTO_TSTRING 2 #define SPROTO_TSTRING 2
#define SPROTO_TSTRUCT 3 #define SPROTO_TSTRUCT 3
// sub type of string (sproto_arg.extra)
#define SPROTO_TSTRING_STRING 0
#define SPROTO_TSTRING_BINARY 1
#define SPROTO_CB_ERROR -1 #define SPROTO_CB_ERROR -1
#define SPROTO_CB_NIL -2 #define SPROTO_CB_NIL -2
#define SPROTO_CB_NOARRAY -3 #define SPROTO_CB_NOARRAY -3
@@ -41,6 +46,7 @@ struct sproto_arg {
int length; int length;
int index; // array base 1 int index; // array base 1
int mainindex; // for map int mainindex; // for map
int extra; // SPROTO_TINTEGER: decimal ; SPROTO_TSTRING 0:utf8 string 1:binary
}; };
typedef int (*sproto_callback)(const struct sproto_arg *args); typedef int (*sproto_callback)(const struct sproto_arg *args);

View File

@@ -70,6 +70,7 @@ local name = C(word)
local typename = C(word * ("." * word) ^ 0) local typename = C(word * ("." * word) ^ 0)
local tag = R"09" ^ 1 / tonumber local tag = R"09" ^ 1 / tonumber
local mainkey = "(" * blank0 * name * blank0 * ")" local mainkey = "(" * blank0 * name * blank0 * ")"
local decimal = "(" * blank0 * C(tag) * blank0 * ")"
local function multipat(pat) local function multipat(pat)
return Ct(blank0 * (pat * blanks) ^ 0 * pat^0 * blank0) return Ct(blank0 * (pat * blanks) ^ 0 * pat^0 * blank0)
@@ -81,7 +82,7 @@ end
local typedef = P { local typedef = P {
"ALL", "ALL",
FIELD = namedpat("field", (name * blanks * tag * blank0 * ":" * blank0 * (C"*")^-1 * typename * mainkey^0)), FIELD = namedpat("field", (name * blanks * tag * blank0 * ":" * blank0 * (C"*")^-1 * typename * (mainkey + decimal)^0)),
STRUCT = P"{" * multipat(V"FIELD" + V"TYPE") * P"}", STRUCT = P"{" * multipat(V"FIELD" + V"TYPE") * P"}",
TYPE = namedpat("type", P"." * name * blank0 * V"STRUCT" ), TYPE = namedpat("type", P"." * name * blank0 * V"STRUCT" ),
SUBPROTO = Ct((C"request" + C"response") * blanks * (typename + V"STRUCT")), SUBPROTO = Ct((C"request" + C"response") * blanks * (typename + V"STRUCT")),
@@ -134,8 +135,12 @@ function convert.type(all, obj)
end end
local mainkey = f[5] local mainkey = f[5]
if mainkey then if mainkey then
assert(field.array) if fieldtype == "integer" then
field.key = mainkey field.decimal = mainkey
else
assert(field.array)
field.key = mainkey
end
end end
field.typename = fieldtype field.typename = fieldtype
else else
@@ -167,6 +172,7 @@ local buildin_types = {
integer = 0, integer = 0,
boolean = 1, boolean = 1,
string = 2, string = 2,
binary = 2, -- binary is a sub type of string
} }
local function checktype(types, ptype, t) local function checktype(types, ptype, t)
@@ -275,7 +281,11 @@ local function packfield(f)
table.insert(strtbl, "\0\0") -- name (tag = 0, ref an object) table.insert(strtbl, "\0\0") -- name (tag = 0, ref an object)
if f.buildin then if f.buildin then
table.insert(strtbl, packvalue(f.buildin)) -- buildin (tag = 1) table.insert(strtbl, packvalue(f.buildin)) -- buildin (tag = 1)
table.insert(strtbl, "\1\0") -- skip (tag = 2) if f.extra then
table.insert(strtbl, packvalue(f.extra)) -- f.buildin can be integer or string
else
table.insert(strtbl, "\1\0") -- skip (tag = 2)
end
table.insert(strtbl, packvalue(f.tag)) -- tag (tag = 3) table.insert(strtbl, packvalue(f.tag)) -- tag (tag = 3)
else else
table.insert(strtbl, "\1\0") -- skip (tag = 1) table.insert(strtbl, "\1\0") -- skip (tag = 1)
@@ -299,8 +309,12 @@ local function packtype(name, t, alltypes)
tmp.array = f.array tmp.array = f.array
tmp.name = f.name tmp.name = f.name
tmp.tag = f.tag tmp.tag = f.tag
tmp.extra = f.decimal
tmp.buildin = buildin_types[f.typename] tmp.buildin = buildin_types[f.typename]
if f.typename == "binary" then
tmp.extra = 1 -- binary is sub type of string
end
local subtype local subtype
if not tmp.buildin then if not tmp.buildin then
subtype = assert(alltypes[f.typename]) subtype = assert(alltypes[f.typename])