通信编码解码 c11 实现 [ lua 专用版]

#include <istream>
#include <ostream>
#include <iostream>
#include <strstream>
#include <list>
#include <map>
#include "cocos2d.h"
#include <math.h>

#define ENCODE_LUA_API 1

#ifndef LUA
#   define LUA
#endif

#if defined(LUA) && (ENCODE_LUA_API > 0)
#   define NEED_DEFINE_ENCODE_LUA_API 1
#endif

extern "C" {
#   include "lua.h"
#   include "lauxlib.h"
}

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 //127
#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<char,char> STRING_MAP;
#define STRING_MAP_PAIR(k,v) pair<char, char>(k,v)
STRING_MAP TYPE_SHORT_STRING_MAP = {
    STRING_MAP_PAIR(50, 0),
    STRING_MAP_PAIR(51, 1),
    STRING_MAP_PAIR(52, 2),
    STRING_MAP_PAIR(53, 3),
    STRING_MAP_PAIR(54, 4),
    STRING_MAP_PAIR(55, 5),
    STRING_MAP_PAIR(56, 6),
    STRING_MAP_PAIR(57, 7),
    STRING_MAP_PAIR(58, 8),
    STRING_MAP_PAIR(59, 9),
    STRING_MAP_PAIR(60, 10),
    STRING_MAP_PAIR(61, 11),
    STRING_MAP_PAIR(62, 12),
    STRING_MAP_PAIR(63, 13),
    STRING_MAP_PAIR(64, 14),
    STRING_MAP_PAIR(65, 15),
    STRING_MAP_PAIR(66, 16),
    STRING_MAP_PAIR(67, 17),
    STRING_MAP_PAIR(68, 18),
    STRING_MAP_PAIR(69, 19),
    STRING_MAP_PAIR(70, 20),
    STRING_MAP_PAIR(71, 21),
    STRING_MAP_PAIR(72, 22),
    STRING_MAP_PAIR(73, 23),
    STRING_MAP_PAIR(74, 24),
    STRING_MAP_PAIR(75, 25),
    STRING_MAP_PAIR(76, 32),
};

STRING_MAP TYPE_SHORT_STRING_MAP2 = {
    STRING_MAP_PAIR(0, 50),
    STRING_MAP_PAIR(1, 51),
    STRING_MAP_PAIR(2, 52),
    STRING_MAP_PAIR(3, 53),
    STRING_MAP_PAIR(4, 54),
    STRING_MAP_PAIR(5, 55),
    STRING_MAP_PAIR(6, 56),
    STRING_MAP_PAIR(7, 57),
    STRING_MAP_PAIR(8, 58),
    STRING_MAP_PAIR(9, 59),
    STRING_MAP_PAIR(10, 60),
    STRING_MAP_PAIR(11, 61),
    STRING_MAP_PAIR(12, 62),
    STRING_MAP_PAIR(13, 63),
    STRING_MAP_PAIR(14, 64),
    STRING_MAP_PAIR(15, 65),
    STRING_MAP_PAIR(16, 66),
    STRING_MAP_PAIR(17, 67),
    STRING_MAP_PAIR(18, 68),
    STRING_MAP_PAIR(19, 69),
    STRING_MAP_PAIR(20, 70),
    STRING_MAP_PAIR(21, 71),
    STRING_MAP_PAIR(22, 72),
    STRING_MAP_PAIR(23, 73),
    STRING_MAP_PAIR(24, 74),
    STRING_MAP_PAIR(25, 75),
    STRING_MAP_PAIR(32, 76),
};

//=======================================end optimize =========================================

class StreamBuf4Encodeing;
namespace LuaArray {
    
    enum Type {
        STRING,
//        NUMBER,
        INT,
        BOOLEAN,
    };
    
    class LuaArrayItem {
        friend class StreamBuf4Encodeing;
        
    public:
        virtual ~LuaArrayItem(){
            
        };
        
        virtual Type getType() const = 0;
        
    };
    
//    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 {
#   define DEFAULT_BUFFER_CAPACITY 2048
private:
    char *buffer;
    size_t capacity;
    size_t pos ;
    size_t size;
public:
    StreamBuf4Encodeing():buffer(nullptr),
    capacity(0),
    pos(0),
    size(0)
    {
        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 = 0;
        capacity = 0;
    }
    
    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<LuaArray::LuaArrayItemINT*>(luaArrayItem);
                int num = numItr->getValue();
                this->_write_int((int)(num));
                break;
            }
            case LuaArray::Type::STRING : {
                LuaArray::LuaArrayItemString *strItr =
                dynamic_cast<LuaArray::LuaArrayItemString*>(luaArrayItem);
                std::string str = strItr->getValue();
                this->Write_str(str);
                break;
            }
            case LuaArray::Type::BOOLEAN :{
                LuaArray::LuaArrayItemBoolean *boolItr =
                dynamic_cast<LuaArray::LuaArrayItemBoolean*>(luaArrayItem);
                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 / 2){
            char * rawBuf = this->buffer;
            char * newbuf = (char*)malloc(cap);
            this->buffer = newbuf;
            memcpy(this->buffer,rawBuf,cap); //会导致数据丢失
            this->size = cap;
            this->pos = cap - 1;
            free(rawBuf);
        }
    }
    
    inline StreamBuf4Encodeing& _write_chars(char* c,size_t len) {
        while(this->capacity < this->pos + len ){
            this->remalloc(this->capacity * 2);
        }
        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,1);
        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(0){
        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[0];
    };
    
    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 0;
            delete *array;
            *array = nullptr;
        }
        return 0;
    };
    
    
    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<LuaArray::LuaArrayItemBoolean*>(arrayItr) ;
//                            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<LuaArray::LuaArrayItemINT*>(arrayItr) ;
                            tencode.Write_int(num->getValue());
                            type = CIO_TYPE_INTEGER_ARRAY;
                            break;
                        }
                        case LuaArray::Type::STRING :{
                            LuaArray::LuaArrayItem *arrayItr = &(*itr);
                            LuaArray::LuaArrayItemString *str = dynamic_cast<LuaArray::LuaArrayItemString*>(arrayItr) ;
                            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 -1;
        }
        
        lua_pushnil(L);
        
        StreamBuf4Encodeing tencode;
        int len = 0 ;
        while (lua_next(L, top) != 0) {
            cio2_encode_val(L, -2, tencode); //key
            cio2_encode_val(L, -1, tencode); //value
            len++;
            lua_pop(L, 1); //clean processed.
        }
        encode.Write_table(tencode, len);
        return 0;
    };
    
    static int cio_encode(lua_State *L) {
        int RET_ARG_LEN = 1;
        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 !=0){
            luaL_error(L, "%s","decode table fail by cio_encode.");
            return -1;
        }else {
            std::string str = ecode.toString();
            lua_pushlstring(L, str.c_str(), str.length());
            return RET_ARG_LEN;
        }
        return 0;
    }

    
    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 0;
        }
        
        lua_pushnil(L);
        
        LuaArray::LuaArray *array = new LuaArray::LuaArray();
        
        while (lua_next(L, top) != 0) {
            int valtype = lua_type(L,-1);
            switch(valtype){
                case LUA_TNUMBER:
                {
                    lua_Number num = lua_tonumber(L, -1);
                    LuaArray::LuaArrayItemINT *udNum = new LuaArray::LuaArrayItemINT(num);
                    array->getList(). push_back(udNum);
                    break;
                }
                    
                case LUA_TSTRING:
                {
                    const char* str = lua_tostring(L, -1);
                    LuaArray::LuaArrayItemString *udStr = new LuaArray::LuaArrayItemString(str);
                    array->getList().push_back(udStr);
                    break;
                }
                    
                case LUA_TBOOLEAN:
                {
                    int num = lua_toboolean(L, -1);
                    LuaArray::LuaArrayItemBoolean *udBool = new LuaArray::LuaArrayItemBoolean(num);
                    array->getList().push_back(udBool);
                    break;
                }
            }

            lua_pop(L, 1); //clean processed.
        }

        lua_pushnumber(L, 0);
        
        //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, -2);
        
        return 1;
    }
    
    
    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, 0);break;
                case CIO_TYPE_TRUE              : lua_pushboolean(L, 1);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 0;
    };
    
    static int cio_decode_array(lua_State *L,StreamBuf4Dencodeing& decoder,unsigned char type){
        int len = decoder.readInt();
        lua_newtable(L);
        
        for( int i = 1 ;i <= len; i++) {
            lua_pushnumber(L, i);       //key
            cio_decode_val(L,decoder);  //value
            lua_settable(L, -3);
        }
        return 0;
        
    };
    
    static int cio_decode_list(lua_State *L,StreamBuf4Dencodeing& decoder){
        int len = decoder.readInt();
        lua_newtable(L);
        for( int i = 1 ;i <= len; i++) {
            lua_pushnumber(L, i);       //key
            cio_decode_val(L,decoder);  //value
            lua_settable(L, -3);
        }
        return 0;
        
    };
    
    static int i = 0;
    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, -3);
            len --;
        }
        return 0;
    };
    
    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 -1;
        }
        
        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 -1;
        }
        int len = decoder.readInt();
        int ret = cio_decode_table(L, decoder,len);
        if(ret == 0){
            int processBuferLen = decoder.getPos();
            lua_pushnumber(L, processBuferLen); //已处理的长度
            return 2;
        }
        else luaL_error(L,"%s", "decode error!");
        return 1;
    }
}

#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, -1);
    lua_setfield(L, -2, "__index");
    lua_pushcfunction(L, __gcReleaseLuaArray);
    lua_setfield(L,-2,"__gc");
    luaL_register(L, "LuaArray", cio2_lua_array);
    
    return 0;
};

#endif