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 vh;
int isnum;
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)));
if (args->extra) {
// It's decimal.
lua_Number vn = lua_tonumber(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);
// notice: in lua 5.2, lua_Integer maybe 52bit
@@ -332,8 +338,15 @@ decode(const struct sproto_arg *args) {
switch (args->type) {
case SPROTO_TINTEGER: {
// notice: in lua 5.2, 52bit integer support (not 64)
lua_Integer v = *(uint64_t*)args->value;
lua_pushinteger(L, v);
if (args->extra) {
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;
}
case SPROTO_TBOOLEAN: {
@@ -660,7 +673,7 @@ ldefault(lua_State *L) {
return 1;
}
int
LUAMOD_API int
luaopen_sproto_core(lua_State *L) {
#ifdef luaL_checkversion
luaL_checkversion(L);

View File

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

View File

@@ -9,11 +9,16 @@ struct sproto_type;
#define SPROTO_REQUEST 0
#define SPROTO_RESPONSE 1
// type (sproto_arg.type)
#define SPROTO_TINTEGER 0
#define SPROTO_TBOOLEAN 1
#define SPROTO_TSTRING 2
#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_NIL -2
#define SPROTO_CB_NOARRAY -3
@@ -41,6 +46,7 @@ struct sproto_arg {
int length;
int index; // array base 1
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);

View File

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