#include
#include
#include
#include
#include
#include
#define ENCODE_LUA_API 1
#ifndef LUA
#endif
#if defined(LUA) && (ENCODE_LUA_API > 0)
#endif
extern "C" {
}
int CIO2_Lua_Open(lua_State *state);
using namespace std;
using namespace cocos2d;
//========================================= optimize =========================================
char* nil = new char(0x00); //memory leaks.
#define CIO_TYPE_NIL 0x7f //
#define CIO_TYPE_FALSE 0x00
#define CIO_TYPE_TRUE 0x01
#define CIO_TYPE_INT 0x04
#define CIO_TYPE_STRING 0x05
#define CIO_TYPE_CSTR 0x06
#define CIO_TYPE_WSTR 0x07
#define CIO_TYPE_TABLE 0x08
#define CIO_TYPE_BYTES 0x09
#define CIO_TYPE_LONG 0x0a
#define CIO_TYPE_TIME 0x0b //long (2000-01-01 00:00:00)
#define CIO_TYPE_LIST 0x0c
#define CIO_TYPE_INTEGER_ARRAY 0x0d
#define CIO_TYPE_STRING_ARRAY 0x0e
#define CIO_TYPE_DOUBLE 0x0f
typedef std::map
#define STRING_MAP_PAIR(k,v) pair
STRING_MAP TYPE_SHORT_STRING_MAP = {
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
};
STRING_MAP TYPE_SHORT_STRING_MAP2 = {
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
STRING_MAP_PAIR(, ),
};
//=======================================end optimize =========================================
class StreamBuf4Encodeing;
namespace LuaArray {
enum Type {
STRING,
// NUMBER,
INT,
BOOLEAN,
};
class LuaArrayItem {
friend class StreamBuf4Encodeing;
public:
virtual ~LuaArrayItem(){
};
virtual Type getType() const = ;
};
// class LuaArrayItemNumber : virtual public LuaArrayItem{
// private:
// lua_Number val;
// public:
// LuaArrayItemNumber(lua_Number val):val(val) { };
// virtual Type getType() const override { return Type::NUMBER; };
// inline lua_Number getValue() const{ return this->val; };
// };
class LuaArrayItemINT : virtual public LuaArrayItem{
private:
int val;
public:
LuaArrayItemINT(int val):val(val) { };
virtual Type getType() const override { return Type::INT; };
inline int getValue() const{ return this->val; };
};
class LuaArrayItemString : virtual public LuaArrayItem{
private:
std::string val;
public:
LuaArrayItemString(std::string \_val):val(\_val) { };
virtual Type getType() const override { return Type::STRING; };
inline std::string getValue() const{ return this->val; };
};
class LuaArrayItemBoolean : virtual public LuaArrayItem{
private:
bool val;
public:
LuaArrayItemBoolean(bool val):val(val) { };
virtual Type getType() const override { return Type::BOOLEAN; };
inline bool getValue(){ return this->val; };
};
class LuaArray{
private:
std::list<LuaArrayItem\*> \_list;
public:
~LuaArray(){
for(auto &itr:\_list){
delete itr;
}
\_list.clear();
};
inline std::list<LuaArrayItem\*>& getList(){
return this->\_list;
};
};
}
class StreamBuf4Encodeing {
private:
char *buffer;
size_t capacity;
size_t pos ;
size_t size;
public:
StreamBuf4Encodeing():buffer(nullptr),
capacity(),
pos(),
size()
{
capacity = DEFAULT_BUFFER_CAPACITY;
buffer = (char*)malloc(capacity);
};
StreamBuf4Encodeing(char \* c,int n){
new (this)StreamBuf4Encodeing();
if(DEFAULT\_BUFFER\_CAPACITY < n ){
if (buffer) free(buffer);
capacity = DEFAULT\_BUFFER\_CAPACITY;
buffer = (char\*)malloc(capacity);
}
memcpy(buffer, c, n);
size = n;
};
virtual ~StreamBuf4Encodeing(void) {
free(buffer);
size = ;
capacity = ;
}
virtual std::string toString(){
return std::string(buffer,size);
}
private:
StreamBuf4Encodeing& operator << (LuaArray::LuaArrayItem * luaArrayItem){
auto type = luaArrayItem->getType();
switch (type) {
case LuaArray::Type::INT : {
LuaArray::LuaArrayItemINT *numItr =
dynamic_cast
int num = numItr->getValue();
this->_write_int((int)(num));
break;
}
case LuaArray::Type::STRING : {
LuaArray::LuaArrayItemString *strItr =
dynamic_cast
std::string str = strItr->getValue();
this->Write_str(str);
break;
}
case LuaArray::Type::BOOLEAN :{
LuaArray::LuaArrayItemBoolean *boolItr =
dynamic_cast
bool b = boolItr->getValue();
if(b) this->Write_true();
else this->Write_false();
break;
}
default:
break;
}
return *this;
};
inline StreamBuf4Encodeing& \_write\_type\_head(unsigned char val) {
return this->\_write\_char(val);
};
inline void remalloc(size\_t cap){
if(cap > this->size){
char \* rawBuf = this->buffer;
char \* newbuf = (char\*)malloc(cap);
this->buffer = newbuf;
memcpy(this->buffer,rawBuf,this->size);
free(rawBuf);
}else if(cap < this->size / ){
char \* rawBuf = this->buffer;
char \* newbuf = (char\*)malloc(cap);
this->buffer = newbuf;
memcpy(this->buffer,rawBuf,cap); //会导致数据丢失
this->size = cap;
this->pos = cap - ;
free(rawBuf);
}
}
inline StreamBuf4Encodeing& \_write\_chars(char\* c,size\_t len) {
while(this->capacity < this->pos + len ){
this->remalloc(this->capacity \* );
}
memcpy((this->buffer + pos),c, len);
pos+= len;
size += len;
return \*this;
}
inline StreamBuf4Encodeing& \_write\_char(unsigned char val){
char c;
c = val;
this->\_write\_chars(&c,);
return \*this;
};
inline StreamBuf4Encodeing& \_write\_str(char \*c,size\_t len){
this->\_write\_chars(c,len);
return \*this;
};
inline StreamBuf4Encodeing& \_write\_int(int i){
char \*c = (char\*)(&i);
this->\_write\_chars(c, sizeof(int));
return \*this;
};
inline StreamBuf4Encodeing& \_write\_str(const char \*c,size\_t len){
char \* vc = (char\*)c;
return this->\_write\_str(vc,len);
};
public:
inline StreamBuf4Encodeing& Write\_str(std::string val){
int len =(int) val.length();
if( TYPE\_SHORT\_STRING\_MAP2.find(len) != TYPE\_SHORT\_STRING\_MAP2.end()) {
char tlen = TYPE\_SHORT\_STRING\_MAP2\[len\];
this->\_write\_char(tlen);
}else {
this->\_write\_type\_head(CIO\_TYPE\_STRING);
this->\_write\_int(len);
}
return this->\_write\_str(val.c\_str(),val.length());
};
inline StreamBuf4Encodeing& Write\_number(lua\_Number val){
if(floor(val) == val) {
int v = (int)val;
char \* c = (char\*) (&v);
this->\_write\_type\_head(CIO\_TYPE\_INT);
this->\_write\_chars(c,sizeof(int));
}else {
this->\_write\_type\_head(CIO\_TYPE\_DOUBLE);
char \* c = (char\*) (&val);
this->\_write\_chars(c, sizeof(lua\_Number));
}
return \*this;
};
inline StreamBuf4Encodeing& Write\_false(){ return this ->\_write\_char(CIO\_TYPE\_FALSE); };
inline StreamBuf4Encodeing& Write\_true(){ return this ->\_write\_char(CIO\_TYPE\_TRUE); };
inline StreamBuf4Encodeing& Write\_nil(){ return this ->\_write\_char(CIO\_TYPE\_NIL); };
inline StreamBuf4Encodeing& Write\_int(int val){
this->\_write\_type\_head(CIO\_TYPE\_INT);
return this->\_write\_int(val);
};
inline StreamBuf4Encodeing& Write\_table(StreamBuf4Encodeing & encode,size\_t len){
this->\_write\_type\_head(CIO\_TYPE\_TABLE);
this->\_write\_int((int)len);
std::string str = encode.toString();
this ->\_write\_str(str.c\_str(),str.length());
return (\*this) ;
};
inline StreamBuf4Encodeing& Write\_int\_array(StreamBuf4Encodeing & encode,size\_t len){
this->\_write\_type\_head(CIO\_TYPE\_INTEGER\_ARRAY);
this->\_write\_int((int)len);
std::string str = encode.toString();
this ->\_write\_str(str.c\_str(),str.length());
return (\*this);
};
inline StreamBuf4Encodeing& Write\_string\_array(StreamBuf4Encodeing & encode,size\_t len){
this->\_write\_type\_head(CIO\_TYPE\_STRING\_ARRAY);
this->\_write\_int((int)len);
std::string str = encode.toString();
this ->\_write\_str(str.c\_str(),str.length());
return (\*this);
};
};
class StreamBuf4Dencodeing{
private:
char * buffer;
int pos;
int size;
public:
StreamBuf4Dencodeing(char* c,int n):size(n),pos(){
buffer = (char*)malloc(n);
memcpy(buffer, c, n);
};
~StreamBuf4Dencodeing(void){
free(buffer);
};
unsigned char readChar() {
char\* ptr = buffer + pos;
// if(pos >40){
// char *temptr = buffer + pos - 40;
// int i = 0;
// }
pos++;
return ptr[];
};
void readStr(char\* \_buf,int len) {
memcpy(\_buf,buffer+pos,len);
pos+= len;
}
public:
int getPos() const {
return this->pos;
};
bool eof(){
return pos >= size;
}
unsigned char readType(){
return this->readChar();
}
lua\_Number readNum() {
lua\_Number num;
char \* c = (char\*)(&num);
this->readStr(c,sizeof(lua\_Number));
return num;
};
int readInt() {
int num;
char \* c = (char\*)(&num);
this->readStr(c,sizeof(int));
return num;
};
void moveCursor(int n){
this->pos += n;
}
bool readBoolean() {
return this->readChar();
};
//有bug.还会导致逻辑混乱。
// std::string readString() {
//
// char tlen = this->readChar();
// this->moveCursor(-1);//不能影响游标,只是用来做检测,确定是进入什么逻辑
//
// int len = 0;
// if(TYPE_SHORT_STRING_MAP.find(tlen) != TYPE_SHORT_STRING_MAP.end()) {
// char tlen = this->readChar();
// len = TYPE_SHORT_STRING_MAP[tlen];
// }else {
// len = this->readInt();
// }
// return this->readString(len);
// };
std::string readString(int len) {
char \*c = (char\*)malloc(len);
this->readStr(c,len);
std::string str(c,len);
free(c);
return str;
};
};
extern "C" {
static int cio2\_encode\_table(lua\_State \*L, StreamBuf4Encodeing &encode) ;
static void cio2\_encode\_val(lua\_State \*L,int stackIdx, StreamBuf4Encodeing &encode);
static int cio\_decode\_array(lua\_State \*L,StreamBuf4Dencodeing& decoder,unsigned char type);
static int cio\_decode\_list(lua\_State \*L,StreamBuf4Dencodeing& decoder);
static int cio\_decode\_table(lua\_State \*L ,StreamBuf4Dencodeing& decoder,size\_t len);
static int \_\_gcReleaseLuaArray(lua\_State \*L);
static int \_\_gcReleaseLuaArray(lua\_State\* L) {
int top = lua\_gettop(L);
int t = lua\_type(L,top);
if(t == LUA\_TUSERDATA ) {
void \* ud = lua\_touserdata(L, top);
LuaArray::LuaArray \*\*array = (LuaArray::LuaArray\*\*)(ud);
if(\*array == nullptr) return ;
delete \*array;
\*array = nullptr;
}
return ;
};
static void cio2\_encode\_val(lua\_State \*L,int stackIdx, StreamBuf4Encodeing &encode){
int nodeType = lua\_type(L, stackIdx);
switch (nodeType) {
case LUA\_TNUMBER:
{
encode.Write\_number(lua\_tonumber(L, stackIdx));
break;
}
case LUA\_TSTRING:
{
encode.Write\_str(lua\_tostring(L, stackIdx));
break;
}
case LUA\_TTABLE:
{
cio2\_encode\_table(L,encode);
break;
}
case LUA\_TBOOLEAN:{
int \_bool = lua\_toboolean(L, stackIdx);
if(\_bool) encode.Write\_true();
else encode.Write\_false();
break;
}
case LUA\_TUSERDATA:
{
StreamBuf4Encodeing tencode;
LuaArray::LuaArray \*\*array = (LuaArray::LuaArray\*\*)lua\_touserdata(L, stackIdx);
char type = 0x00;
for(auto &itr: (\*array)->getList()) {
switch(itr->getType()){
case LuaArray::Type::BOOLEAN: {
//
// LuaArray::LuaArrayItem *arrayItr = &(*itr);
// LuaArray::LuaArrayItemBoolean *_bool = dynamic_cast
// if(_bool->getValue()==true) tencode.Write_true();
// else tencode.Write_false();
printf("%s","不支持boolean 数组的解码!");
break;
}
case LuaArray::Type::INT : {
LuaArray::LuaArrayItem *arrayItr = &(*itr);
LuaArray::LuaArrayItemINT *num = dynamic_cast
tencode.Write_int(num->getValue());
type = CIO_TYPE_INTEGER_ARRAY;
break;
}
case LuaArray::Type::STRING :{
LuaArray::LuaArrayItem *arrayItr = &(*itr);
LuaArray::LuaArrayItemString *str = dynamic_cast
tencode.Write_str(str->getValue());
type = CIO_TYPE_STRING_ARRAY;
break;
}
}
}
//write to buffer;
switch(type){
case CIO\_TYPE\_INTEGER\_ARRAY:{
encode.Write\_int\_array(tencode, (\*array)->getList().size());
break;
}
case CIO\_TYPE\_STRING\_ARRAY:{
encode.Write\_string\_array(tencode, (\*array)->getList().size());
break;
}
}
}
default:
break;
}
}
static int cio2\_encode\_table(lua\_State \*L, StreamBuf4Encodeing &encode) {
int top = lua\_gettop(L);
int type = lua\_type(L, top);
if(type != LUA\_TTABLE) {
luaL\_error(L,"%s","arg must a table.");
return -;
}
lua\_pushnil(L);
StreamBuf4Encodeing tencode;
int len = ;
while (lua\_next(L, top) != ) {
cio2\_encode\_val(L, -, tencode); //key
cio2\_encode\_val(L, -, tencode); //value
len++;
lua\_pop(L, ); //clean processed.
}
encode.Write\_table(tencode, len);
return ;
};
static int cio\_encode(lua\_State \*L) {
int RET\_ARG\_LEN = ;
int top = lua\_gettop(L);
int t = lua\_type(L, top);
if(t != LUA\_TTABLE){
luaL\_error(L, "%s","argment must a table when call \\"by cio\_encode\\"");
return RET\_ARG\_LEN;
}
StreamBuf4Encodeing ecode;
int ret = cio2\_encode\_table(L, ecode);
if(ret !=){
luaL\_error(L, "%s","decode table fail by cio\_encode.");
return -;
}else {
std::string str = ecode.toString();
lua\_pushlstring(L, str.c\_str(), str.length());
return RET\_ARG\_LEN;
}
return ;
}
static int cio\_table\_toarray(lua\_State \*L) {
int top = lua\_gettop(L);
int type =lua\_type(L, top);
if(type != LUA\_TTABLE ) {
luaL\_error(L, "%s","arguments must a table");
return ;
}
lua\_pushnil(L);
LuaArray::LuaArray \*array = new LuaArray::LuaArray();
while (lua\_next(L, top) != ) {
int valtype = lua\_type(L,-);
switch(valtype){
case LUA\_TNUMBER:
{
lua\_Number num = lua\_tonumber(L, -);
LuaArray::LuaArrayItemINT \*udNum = new LuaArray::LuaArrayItemINT(num);
array->getList(). push\_back(udNum);
break;
}
case LUA\_TSTRING:
{
const char\* str = lua\_tostring(L, -);
LuaArray::LuaArrayItemString \*udStr = new LuaArray::LuaArrayItemString(str);
array->getList().push\_back(udStr);
break;
}
case LUA\_TBOOLEAN:
{
int num = lua\_toboolean(L, -);
LuaArray::LuaArrayItemBoolean \*udBool = new LuaArray::LuaArrayItemBoolean(num);
array->getList().push\_back(udBool);
break;
}
}
lua\_pop(L, ); //clean processed.
}
lua\_pushnumber(L, );
//new userdata.
LuaArray::LuaArray \*\* array\_userdata = (LuaArray::LuaArray \*\*)lua\_newuserdata(L, sizeof(LuaArray::LuaArray\*));
\*array\_userdata = array;
//bing metatable
luaL\_getmetatable(L, "LuaArray");
lua\_setmetatable(L, -);
return ;
}
static int cio\_decode\_val(lua\_State\* L,StreamBuf4Dencodeing& decoder){
unsigned char type = decoder.readType();
//优化操作
if(TYPE\_SHORT\_STRING\_MAP.find(type)!= TYPE\_SHORT\_STRING\_MAP.end()){
int len = TYPE\_SHORT\_STRING\_MAP\[type\];
std::string str = decoder.readString(len);
lua\_pushlstring(L, str.c\_str(), len);
}else{
// printf("--------%c",type);
switch (type) {
case CIO_TYPE_NIL : lua_pushnil(L); break;
case CIO_TYPE_FALSE : lua_pushboolean(L, );break;
case CIO_TYPE_TRUE : lua_pushboolean(L, );break;
case CIO_TYPE_INT : lua_pushinteger(L, decoder.readInt()); break;
case CIO_TYPE_STRING :
{
//std::string str = decoder.readString();
int len = decoder.readInt();
std::string str = decoder.readString(len);
lua_pushlstring(L, str.c_str(), str.length());
break;
}
case CIO_TYPE_CSTR :break;
case CIO_TYPE_WSTR :break;
case CIO_TYPE_TABLE :{
//cio_decode_val(L,decoder);
int len = decoder.readInt();
// decoder.moveCursor(-sizeof(int));
cio_decode_table(L,decoder,len);
break;
}
case CIO_TYPE_BYTES :break;
case CIO_TYPE_LONG :break;
case CIO_TYPE_TIME :break;
case CIO\_TYPE\_LIST :
{
cio\_decode\_list(L,decoder);
break;
}
case CIO\_TYPE\_INTEGER\_ARRAY :
case CIO\_TYPE\_STRING\_ARRAY :
{
cio\_decode\_array(L,decoder,type);
break;
}
case CIO\_TYPE\_DOUBLE : lua\_pushnumber(L, decoder.readNum());break;
default:
break;
}
}
return ;
};
static int cio\_decode\_array(lua\_State \*L,StreamBuf4Dencodeing& decoder,unsigned char type){
int len = decoder.readInt();
lua\_newtable(L);
for( int i = ;i <= len; i++) {
lua\_pushnumber(L, i); //key
cio\_decode\_val(L,decoder); //value
lua\_settable(L, -);
}
return ;
};
static int cio\_decode\_list(lua\_State \*L,StreamBuf4Dencodeing& decoder){
int len = decoder.readInt();
lua\_newtable(L);
for( int i = ;i <= len; i++) {
lua\_pushnumber(L, i); //key
cio\_decode\_val(L,decoder); //value
lua\_settable(L, -);
}
return ;
};
static int i = ;
static int cio\_decode\_table(lua\_State \*L ,StreamBuf4Dencodeing& decoder,size\_t len) {
lua\_newtable(L);
while (!decoder.eof() && len) {
cio\_decode\_val(L,decoder); //key
cio\_decode\_val(L,decoder); //value
lua\_settable(L, -);
len --;
}
return ;
};
static int cio\_decode(lua\_State \*L) {
int top = lua\_gettop(L);
int t = lua\_type(L,top);
if(t != LUA\_TSTRING) {
luaL\_error(L,"%s","arg must string.");
return -;
}
size\_t size;
const char \* c = lua\_tolstring(L,top,&size);
StreamBuf4Dencodeing decoder((char\*)c,(int)size); //bug.长度丢失
if(decoder.readType() != CIO\_TYPE\_TABLE ) {
luaL\_error(L, "%s","the encode is not encode from a lua table.");
return -;
}
int len = decoder.readInt();
int ret = cio\_decode\_table(L, decoder,len);
if(ret == ){
int processBuferLen = decoder.getPos();
lua\_pushnumber(L, processBuferLen); //已处理的长度
return ;
}
else luaL\_error(L,"%s", "decode error!");
return ;
}
}
#ifdef NEED_DEFINE_ENCODE_LUA_API
int CIO2_Lua_Open(lua_State *L) {
//register coi2 api
const struct luaL\_Reg cio2\_libs \[\] = {
{"Encode",cio\_encode},
{"Decode",cio\_decode},
{"ToArray",cio\_table\_toarray },
{NULL,NULL}
};
luaL\_register(L, "CIO2", cio2\_libs);
//register lua array metatable.
const struct luaL\_Reg cio2\_lua\_array \[\] = {
{NULL,NULL}
};
//luaarray 元表
luaL\_newmetatable(L, "LuaArray");
lua\_pushvalue(L, -);
lua\_setfield(L, -, "\_\_index");
lua\_pushcfunction(L, \_\_gcReleaseLuaArray);
lua\_setfield(L,-,"\_\_gc");
luaL\_register(L, "LuaArray", cio2\_lua\_array);
return ;
};
#endif
手机扫一扫
移动阅读更方便
你可能感兴趣的文章