protobuf for lua

#ifndef _UNIL_H_
#define _UNIL_H_
 
#include <sstream>
#include <string>
#include<cstring>
#include <iostream>
#include "error.h"
 
using namespace std;
 
#define BYTE_LEN 8
#define SHORT_LEN 2
#define PROTO_BIG_ENDIAN
//#define PROTO_LITTLE_ENDIAN
 
namespace unil{
 
    typedef signed char         int8;
    typedef short               int16;
    typedef int                 int32;
    typedef long long           int64;
 
    typedef unsigned char       uint8;
    typedef unsigned short      uint16;
    typedef unsigned int        uint32;
    typedef unsigned long long  uint64;
 
    union Data
    {
    	int16 shortData;
    	uint8 charData[2];
    };
 
    inline void Short2Bit(int16 data, uint8 *buf)
    {
    #ifdef LITTLE_ENDIAN
        #ifdef PROTO_LITTLE_ENDIAN
            memcpy(buf, &data, SHORT_LEN);
        #else
            buf[0] = data >> BYTE_LEN;
            buf[1] = data;
        #endif
    #else
        #ifdef PROTO_LITTLE_ENDIAN
            buf[0] = data >> BYTE_LEN;
            buf[1] = data;
        #else
            memcpy(buf, &data, SHORT_LEN);
        #endif
    #endif
    }
 
	inline int Bit2Short(const uint8* buff, uint32 beg, uint32 len, int16& outLen)
	{
		if(NULL == buff || len < SHORT_LEN)
			return ERROR::ERROR_BIT2SHORT;
		Data d;
    #ifdef LITTLE_ENDIAN
	    #ifdef PROTO_LITTLE_ENDIAN
		    d.charData[0] = buff[beg];
		    d.charData[1] = buff[beg+1];
	    #else
		    d.charData[1] = buff[beg];
		    d.charData[0] = buff[beg+1];
	    #endif
    #else
        #ifdef PROTO_LITTLE_ENDIAN
            d.charData[1] = buff[beg];
            d.charData[0] = buff[beg+1];
        #else
            d.charData[0] = buff[beg];
            d.charData[1] = buff[beg+1];
        #endif
    #endif
		outLen = d.shortData;
		return ERROR::SUCCESS_UNIL;
	}
 
	inline int String2Int(const string& str)
	{
		int number;
		std::stringstream stream;
		stream << str;
		stream >> number;
		return number; 
	}
 
    inline string Int2String(uint32 data)
	{
		stringstream ss;
		ss << data; 
		string result = ss.str();
		return result; 
	}
};
 
#endif 



#ifndef _PROTO_CPP_H_
#define _PROTO_CPP_H_
 
extern "C"
{
    #include "lua.h"
    #include "lualib.h"
    #include "lauxlib.h"
}
 
#include <iostream>
#include <string>
#include "error.h"
#include "unil.h"
 
using namespace unil;
using namespace std;
using namespace google;
using namespace google::protobuf;
 
typedef unsigned int uint;
typedef short int sint;
 
class Proto{
 
    public:
 
        static Proto* getInstance();
 
        ERROR pack(lua_State* L);
        ERROR unpack(lua_State* L);
 
        bool hasRes(const string& typeName);
        ERROR setProto(const string& packFile,const string& unpackFile);
 
        ~Proto();
 
    private:
 
        ERROR packHeader(int &outType, lua_State* L,uint8 *&packBuf,uint &packBufLen);
        ERROR packContent(int type, lua_State* L, uint8 *&packBuf,uint &packBufLen);
        void pack(Message* message, const FieldDescriptor* pFieldDescriptor, lua_State* L);
 
        ERROR unpackHeader(const uint8* buff, uint32 length, lua_State* L, int& outType, int& session,int& timestamp);
        ERROR unpackContent(int type, int session, int timestamp,const uint8* buff, uint32 length, lua_State* L);
        void unpack(const Message& message, lua_State* L);
 
        void getValue(
            const Reflection* reflection,
            const FieldDescriptor* pFieldDescriptor,
            const Message& message,
            lua_State* L,
            int index = 0
            );
        
        void setValue(
            const Reflection* reflection,
            const FieldDescriptor* pFieldDescriptor,
            Message *message,
            lua_State* L
            );
 
        void merage(uint8* des, uint8* src, uint beg, uint len);
        const void* getBuffer(lua_State *L, int index, size_t *sz);
 
        static Proto* instance;
 
        string unpackProtoFileName;
        string packProtoFileName;
        const string headerProtoFileName;
 
    private:
        explicit Proto();
        Proto(const Proto&){}
};
 
 
#endif


#ifndef _UNIL_H_
#define _UNIL_H_
 
#include <sstream>
#include <string>
#include<cstring>
#include <iostream>
#include "error.h"
 
using namespace std;
 
#define BYTE_LEN 8
#define SHORT_LEN 2
#define PROTO_BIG_ENDIAN
//#define PROTO_LITTLE_ENDIAN
 
namespace unil{
 
    typedef signed char         int8;
    typedef short               int16;
    typedef int                 int32;
    typedef long long           int64;
 
    typedef unsigned char       uint8;
    typedef unsigned short      uint16;
    typedef unsigned int        uint32;
    typedef unsigned long long  uint64;
 
    union Data
    {
      int16 shortData;
      uint8 charData[2];
    };
 
    inline void Short2Bit(int16 data, uint8 *buf)
    {
    #ifdef LITTLE_ENDIAN
        #ifdef PROTO_LITTLE_ENDIAN
            memcpy(buf, &data, SHORT_LEN);
        #else
            buf[0] = data >> BYTE_LEN;
            buf[1] = data;
        #endif
    #else
        #ifdef PROTO_LITTLE_ENDIAN
            buf[0] = data >> BYTE_LEN;
            buf[1] = data;
        #else
            memcpy(buf, &data, SHORT_LEN);
        #endif
    #endif
    }
 
  inline int Bit2Short(const uint8* buff, uint32 beg, uint32 len, int16& outLen)
  {
    if(NULL == buff || len < SHORT_LEN)
      return ERROR::ERROR_BIT2SHORT;
    Data d;
    #ifdef LITTLE_ENDIAN
      #ifdef PROTO_LITTLE_ENDIAN
        d.charData[0] = buff[beg];
        d.charData[1] = buff[beg+1];
      #else
        d.charData[1] = buff[beg];
        d.charData[0] = buff[beg+1];
      #endif
    #else
        #ifdef PROTO_LITTLE_ENDIAN
            d.charData[1] = buff[beg];
            d.charData[0] = buff[beg+1];
        #else
            d.charData[0] = buff[beg];
            d.charData[1] = buff[beg+1];
        #endif
    #endif
    outLen = d.shortData;
    return ERROR::SUCCESS_UNIL;
  }
 
  inline int String2Int(const string& str)
  {
    int number;
    std::stringstream stream;
    stream << str;
    stream >> number;
    return number; 
  }
 
    inline string Int2String(uint32 data)
  {
    stringstream ss;
    ss << data; 
    string result = ss.str();
    return result; 
  }
};
 
#endif 


#include "pb.h"
#include "error.h"
#include <google/protobuf/dynamic_message.h>
 
#include <iostream>
#include <iomanip>
 
Proto* Proto::instance = nullptr;
 
Proto::Proto():
    headerProtoFileName("protohead.proto")
{
}
 
Proto* Proto::getInstance()
{
    if(nullptr == instance)
    {
        instance = new Proto();
    }
    return instance;
}
 
Proto::~Proto()
{
}
 
void Proto::merage(uint8* des, uint8* src, uint beg, uint len)
{
    if(nullptr == des || nullptr == src)
        return;
    for(uint i = 0;i < len; ++i)
        des[beg+i] = src[i];
}
 
ERROR Proto::setProto(const string& packFile,const string& unpackFile)
{
    packProtoFileName = packFile;
    unpackProtoFileName = unpackFile;
 
    const FileDescriptor *packfileDescriptor = DescriptorPool::generated_pool()->FindFileByName(packProtoFileName);
    if(nullptr == packfileDescriptor)
    {
        return ERROR::ERROR_PACK_FILE;
    }
    const FileDescriptor *unpackfileDescriptor = DescriptorPool::generated_pool()->FindFileByName(unpackProtoFileName);
    if(nullptr == unpackfileDescriptor)
    {
        return ERROR::ERROR_UNPACK_FILE;
    }
    return ERROR_NONE;
}
 
ERROR Proto::pack(lua_State* L)
{
    ERROR error = ERROR::SUCCESS_PACK;
    
    int type = -1;
    uint8* headerBuf = nullptr;
    uint headerBufLen = 0;
    error = packHeader(type, L, headerBuf, headerBufLen);
 
    if(ERROR::SUCCESS_PACK != error)
    {
        return error;
    }
    
    uint8* contentBuf = nullptr;
    uint contentBufLen = 0;
 
    error = packContent(type, L, contentBuf, contentBufLen);
 
 
    if(ERROR::SUCCESS_PACK != error)
    {    
        return error;
    }
 
    uint8 headerLenBuf[HEADER_LEN] = {0};
    uint8 contentLenBuf[CONTENT_LEN] = {0};
    Short2Bit(headerBufLen, headerLenBuf);
    Short2Bit(contentBufLen, contentLenBuf);
 
    uint totalBufLen = headerBufLen + contentBufLen + HEADER_LEN + CONTENT_LEN;
    uint8 *packBuf = new uint8 [totalBufLen];
 
    merage(packBuf,headerLenBuf,0,HEADER_LEN);
    merage(packBuf,headerBuf, HEADER_LEN, headerBufLen);
    merage(packBuf,contentLenBuf, HEADER_LEN + headerBufLen, CONTENT_LEN);
    merage(packBuf,contentBuf, HEADER_LEN + CONTENT_LEN + headerBufLen, contentBufLen);
 
    lua_settop(L,0);
    lua_pushlstring(L, (const char *)packBuf, totalBufLen);
 
    delete []headerBuf;
    delete []contentBuf;
    delete []packBuf;
    return error;
}   
 
ERROR Proto::packHeader(int &outType, lua_State* L ,uint8* &packBuf,uint &packBufLen)
{
    packBuf = nullptr;
    packBufLen = 0;
    int session = 0;
    int timestamp = 0;
    string typeName = "";
    int depth = lua_gettop(L);
 
 
    if(4 == depth)
    {
        if(lua_type(L, -1) == LUA_TNUMBER)
        {
            session = luaL_checkinteger(L, -1);
        }
        else if(lua_type(L, -1) == LUA_TSTRING)
        {
            string s = luaL_checkstring(L, -1);
            session = String2Int(s); 
        }
 
        lua_pop(L, 1);
 
        if(lua_type(L, -1) == LUA_TNUMBER)
        {
            timestamp = luaL_checkinteger(L, -1);
        }
        else if(lua_type(L, -1) == LUA_TSTRING)
        {
            string s = luaL_checkstring(L, -1);
            timestamp = String2Int(s); 
        }
        lua_pop(L,1);
    }
    else if(3 == depth)
    {
        if(lua_type(L, -1) == LUA_TNUMBER)
        {
            timestamp = luaL_checkinteger(L, -1);
        }
        else if(lua_type(L, -1) == LUA_TSTRING)
        {
            string s = luaL_checkstring(L, -1);
            timestamp = String2Int(s); 
        }
        lua_pop(L,1);
    }
    else if(2 == depth)
    {
        ;
    }
    else
    {
        return ERROR::ERROR_ARGS; 
    }
 
    if(lua_type(L, 1) == LUA_TSTRING)
        typeName = luaL_checkstring(L, 1);
 
    if(typeName.compare("") == 0)
        return ERROR::ERROR_PACK_TYPE_NAME;
 
    const FileDescriptor *fileDescriptor = DescriptorPool::generated_pool()->FindFileByName(packProtoFileName);
    if(nullptr == fileDescriptor)
    {
        return ERROR::ERROR_PACK_FILE;
    }
 
    const Descriptor *descriptor = fileDescriptor->FindMessageTypeByName(typeName);
    if(nullptr == descriptor)
    {
        return ERROR::ERROR_PACK_TYPE_NAME;
    }
 
    outType = descriptor->index();
    //静态设置了协议头,代码略
 
    packBufLen  = header.ByteSize();
    packBuf = new uint8[packBufLen];
 
    if(!header.SerializeToArray(packBuf, packBufLen))
    {
        delete []packBuf;
        packBufLen = 0;                
        return ERROR_PACK_ERROR;
    }
    return ERROR::SUCCESS_PACK;
}
 
ERROR Proto::packContent(int type, lua_State* L, uint8* &packBuf, uint &packBufLen)
{
    packBuf = nullptr;
    packBufLen = 0;
 
    const FileDescriptor *fileDescriptor = DescriptorPool::generated_pool()->FindFileByName(packProtoFileName);
    if(nullptr == fileDescriptor)
    {
        return ERROR::ERROR_PACK_FILE;
    }
    if(type >= fileDescriptor->message_type_count() || type < 0)
    {
        return ERROR::ERROR_PACK_TYPE_INDEX;
    }
    const Descriptor *descriptor = fileDescriptor->message_type(type);
    if(nullptr == descriptor)
    {
        return ERROR::ERROR_PACK_TYPE_INDEX;
    }
    
    DynamicMessageFactory factory;
    const Message *msg = factory.GetPrototype(descriptor);
    Message *message = msg->New();
 
    pack(message, nullptr, L);
 
    packBufLen = message->ByteSize();
    packBuf = new uint8[packBufLen];
    
    if(!message->SerializeToArray(packBuf, packBufLen))
    {
        packBufLen = 0;
        delete []packBuf;
        return ERROR::ERROR_PACK_ERROR;
    }
 
    delete message;
    return ERROR::SUCCESS_PACK;
}
 
void Proto::setValue(
    const Reflection* reflection,
    const FieldDescriptor* pFieldDescriptor,
    Message *message,
    lua_State* L)
{  
    switch (pFieldDescriptor->cpp_type())
    {
        case FieldDescriptor::CPPTYPE_STRING:
        {
            if(lua_type(L, -1) == LUA_TSTRING)
            {
                size_t len = 0;
                const char* c = luaL_checklstring(L,-1,&len);
                std::string str(c,len); 
                reflection->SetString(message, pFieldDescriptor, str);
            }
            break;
        }
        case FieldDescriptor::CPPTYPE_INT32:
        {
            if(lua_type(L, -1) == LUA_TNUMBER)
            {
                reflection->SetInt32(message, pFieldDescriptor, luaL_checkinteger(L, -1));
            }
            else if(lua_type(L, -1) == LUA_TSTRING)
            { 
                string s = luaL_checkstring(L, -1);
                int value = String2Int(s);
                reflection->SetInt32(message, pFieldDescriptor, value);
            }
            break;
        }
        case FieldDescriptor::CPPTYPE_UINT32:
        {
            if(lua_type(L, -1) == LUA_TNUMBER || lua_type(L, -1) == LUA_TSTRING)
            {
                reflection->SetUInt32(message, pFieldDescriptor, luaL_checkinteger(L, -1));
            }
            break;
        }
        case FieldDescriptor::CPPTYPE_BOOL:
        {
            if(lua_type(L, -1) == LUA_TBOOLEAN )
            {
                reflection->SetBool(message, pFieldDescriptor, luaL_checkinteger(L, -1));
            }
            break;
        }
        case FieldDescriptor::CPPTYPE_INT64:
        {
            if(lua_type(L, -1) == LUA_TNUMBER)
            {
                reflection->SetInt64(message, pFieldDescriptor, luaL_checkinteger(L, -1));
            }
            break;
        }
        case FieldDescriptor::CPPTYPE_UINT64:
        {
            if(lua_type(L, -1) == LUA_TNUMBER)
            {
                reflection->SetUInt64(message, pFieldDescriptor, luaL_checkinteger(L, -1));
            }
            break;
        }
        case FieldDescriptor::CPPTYPE_ENUM:
        {
            //if(lua_type(L, -1) == LUA_TNUMBER)
            //{
            //    reflection->SetEnum(message, pFieldDescriptor, luaL_checkinteger(L, -1));
            //}
            break;
        }
        case FieldDescriptor::CPPTYPE_DOUBLE:
        {
            if(lua_type(L, -1) == LUA_TNUMBER)
            {
                reflection->SetDouble(message, pFieldDescriptor, luaL_checknumber(L, -1));
            }
            break;
        }
        case FieldDescriptor::CPPTYPE_FLOAT:
        {
            if(lua_type(L, -1) == LUA_TNUMBER){
                reflection->SetFloat(message, pFieldDescriptor, luaL_checknumber(L, -1));
            }
            break;
        }
        case FieldDescriptor::CPPTYPE_MESSAGE:
        {
            if(lua_type(L, -1) == LUA_TTABLE){
                Message* subMessage = reflection->MutableMessage(message, pFieldDescriptor);
                pack(subMessage, nullptr, L);
            }
            break;
        }
        default:
        {
            //log
            break;
        }
    }
}
 
void Proto::pack(Message* message, const FieldDescriptor* pFieldDescriptor, lua_State* L)
{
    int it = lua_gettop(L);
    if(1 == lua_isnil(L,it))
    {
        lua_pop(L, 1);
        return;
    }
    lua_pushnil(L);
 
    const Reflection* reflection = message->GetReflection();
    const Descriptor* descriptor = message->GetDescriptor();
 
    while(0 != lua_next(L, it))
    {
        if(LUA_TNUMBER == lua_type(L, -2))
        {
            if(nullptr != pFieldDescriptor && pFieldDescriptor->is_repeated())
            {
                if(lua_type(L, -1) == LUA_TTABLE)
                {
                    Message* subMessage = reflection->AddMessage(message, pFieldDescriptor);
                    pack(subMessage, nullptr, L);
                }
                else if(lua_type(L ,-1) == LUA_TSTRING)
                {
                    size_t len = 0;
                    const char* c = luaL_checklstring(L,-1,&len);
                    std::string str(c,len); 
                    reflection->AddString(message, pFieldDescriptor, str);
                }
                else if(lua_type(L, -1) == LUA_TNUMBER)
                {
                    if(pFieldDescriptor->cpp_type() ==  FieldDescriptor::CPPTYPE_INT32)
                    {
                        int value = luaL_checkinteger(L,-1);
                        reflection->AddInt32(message,  pFieldDescriptor, value);
                    }
                    else if(pFieldDescriptor->cpp_type() ==  FieldDescriptor::CPPTYPE_INT64)
                    {   
                        int64 value = luaL_checkinteger(L,-1);
                        reflection->AddInt64(message,  pFieldDescriptor, value);
                    }
                    else if(pFieldDescriptor->cpp_type() ==  FieldDescriptor::CPPTYPE_UINT32)
                    {   
                        uint32 value = luaL_checkinteger(L,-1);
                        reflection->AddInt32(message,  pFieldDescriptor, value);
                    }
                    else if(pFieldDescriptor->cpp_type() ==  FieldDescriptor::CPPTYPE_UINT64)
                    {   
                        uint64 value = luaL_checkinteger(L,-1);
                        reflection->AddUInt64(message,  pFieldDescriptor, value);
                    }
                    else if(pFieldDescriptor->cpp_type() ==  FieldDescriptor::CPPTYPE_BOOL)
                    {   
                        bool value = luaL_checkinteger(L,-1);
                        reflection->AddBool(message,  pFieldDescriptor, value);
                    }
                    else if(pFieldDescriptor->cpp_type() ==  FieldDescriptor::CPPTYPE_FLOAT)
                    {   
                        float value = luaL_checknumber(L,-1);
                        reflection->AddFloat(message,  pFieldDescriptor, value);
                    }
                    else if(pFieldDescriptor->cpp_type() ==  FieldDescriptor::CPPTYPE_DOUBLE)
                    {   
                        double value = luaL_checknumber(L,-1);
                        reflection->AddDouble(message,  pFieldDescriptor, value);
                    }
                    else
                    {
                        //log
                    }
                }
           }        
        }    
        else
        {
            string fieldName = luaL_checkstring(L, -2);
            const FieldDescriptor* fieldDescriptor = descriptor->FindFieldByName(fieldName);
            if(fieldDescriptor)
            {
                if(fieldDescriptor->is_repeated())
                {
                    pack(message, fieldDescriptor, L);
                }
                else
                {
                    setValue(reflection, fieldDescriptor, message, L);
                }
            }
        }
        lua_pop(L, 1);
    }
}
 
const void *Proto::getBuffer(lua_State *L, int index, size_t *sz) {
    const void * buffer = nullptr;
    int t = lua_type(L, index);
    if (t == LUA_TSTRING) 
    {
        buffer = lua_tolstring(L, index, sz);
    } else 
    {
        if (t != LUA_TUSERDATA && t != LUA_TLIGHTUSERDATA) 
        {
            luaL_argerror(L, index, "Need a string or userdata");
            return nullptr;
        }
        buffer = lua_touserdata(L, index);
        *sz = luaL_checkinteger(L, index+1);
    }
    return buffer;
}
 
ERROR Proto::unpack(lua_State* L)
{
    size_t len = 0;
    const uint8 * buff = (const uint8*)getBuffer(L, 1, &len);
 
    ERROR error = ERROR::SUCCESS_UNPACK;
    if(len < HEADER_LEN)
        return ERROR::ERROR_UNPACK_LEN1;
 
    sint headerLen = 0;
    Bit2Short(buff, 0, HEADER_LEN, headerLen);
    int type = -1;
    int session = -1;
    int timestamp = 0;
 
    if(len < headerLen + HEADER_LEN)
        return ERROR::ERROR_UNPACK_LEN2;
 
    error = unpackHeader(
        buff + HEADER_LEN, 
        headerLen, 
        L, 
        type, 
        session,    
        timestamp
        );
    
    if(ERROR::SUCCESS_UNPACK != error) 
    {
        std::cout<<"HEX DATA ALL :"<<std::endl;
        for(int i = 0; i<len; i++) {
            std::cout.fill('0');//设置填充字符
            std::cout.width(2);//设置域宽
            std::cout<<std::hex<<(int)buff[i];
        }
        std::cout<<std::endl;
        
        return error; 
    }
 
    if(len < HEADER_LEN + headerLen + CONTENT_LEN)
        return ERROR::ERROR_UNPACK_LEN3;
 
    sint contentLen = 0;
    Bit2Short(
        buff,
        HEADER_LEN + headerLen,
        CONTENT_LEN,
        contentLen
    );
 
    if(len < headerLen + contentLen + HEADER_LEN + CONTENT_LEN)
    {
        return ERROR::ERROR_UNPACK_LEN4;
    }    
    error = unpackContent(
        type,
        session,
        timestamp,
        buff + HEADER_LEN + headerLen + CONTENT_LEN,
        contentLen,
        L
        );
 
    return error;
}
 
 
void Proto::unpack(const Message& message,lua_State* L)
{  
    const Reflection* reflection = message.GetReflection();
    const Descriptor* descriptor = message.GetDescriptor();
 
    for (int i = 0; i < descriptor->field_count(); ++i)
    {
        const FieldDescriptor* pFieldDescriptor = descriptor->field(i);
        if(pFieldDescriptor->is_repeated())
        {
            if(pFieldDescriptor->cpp_type() ==  FieldDescriptor::CPPTYPE_MESSAGE)
            {
                const RepeatedPtrField<Message>& pRepeatedField = reflection->GetRepeatedPtrField<Message>(message,pFieldDescriptor);
                string fieldName = pFieldDescriptor->name();
                lua_pushstring(L,fieldName.c_str());
                lua_newtable(L);
                for(int i = 0;i < pRepeatedField.size();++i)
                {
                    lua_pushnumber(L, i+1);
                    lua_newtable(L);
                    const Message& subMessage = reflection->GetRepeatedMessage(message, pFieldDescriptor, i);
                    unpack(subMessage,L);
                    lua_settable(L,-3);
                }
 
                lua_settable(L, -3);
            }
            else
            {
                if(pFieldDescriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING)
                {
                    const RepeatedPtrField<string>& pRepeatedField = reflection->GetRepeatedPtrField<string>(message,pFieldDescriptor);
                    string fieldName = pFieldDescriptor->name();
                    lua_pushstring(L,fieldName.c_str());
                    lua_newtable(L);
                    for(int i = 0;i < pRepeatedField.size();++i)
                    {
                        lua_pushnumber(L, i);
                        const string& str = reflection->GetRepeatedString(message, pFieldDescriptor, i);
                        lua_pushlstring(L, str.c_str(),str.size());
                        lua_settable(L, -3);
                    }
                    lua_settable(L, -3);
                }
                if(pFieldDescriptor->cpp_type() == FieldDescriptor::CPPTYPE_INT32)
                {
                    int psize = reflection->FieldSize(message, pFieldDescriptor);   
                    string fieldName = pFieldDescriptor->name();
                    lua_pushstring(L,fieldName.c_str());
                    lua_newtable(L);
                    for(int i = 0;i < psize;++i)
                    {
                        lua_pushnumber(L, i);
                        int value = reflection->GetRepeatedInt32(message, pFieldDescriptor, i);
                        lua_pushinteger(L, value);
                        lua_settable(L, -3);
                    }
                    lua_settable(L, -3);
                }
 
                if(pFieldDescriptor->cpp_type() == FieldDescriptor::CPPTYPE_INT64)
                {
                    int psize = reflection->FieldSize(message, pFieldDescriptor);   
                    string fieldName = pFieldDescriptor->name();
                    lua_pushstring(L,fieldName.c_str());
                    lua_newtable(L);
                    for(int i = 0;i < psize;++i)
                    {
                        lua_pushnumber(L, i);
                        int64 value = reflection->GetRepeatedInt64(message, pFieldDescriptor, i);
                        lua_pushinteger(L, value);
                        lua_settable(L, -3);
                    }
                    lua_settable(L, -3);
                }
 
 
                if(pFieldDescriptor->cpp_type() == FieldDescriptor::CPPTYPE_BOOL)
                {
                    int psize = reflection->FieldSize(message, pFieldDescriptor);   
                    string fieldName = pFieldDescriptor->name();
                    lua_pushstring(L,fieldName.c_str());
                    lua_newtable(L);
                    for(int i = 0;i < psize;++i)
                    {
                        lua_pushnumber(L, i);
                        int value = reflection->GetRepeatedBool(message, pFieldDescriptor, i);
                        lua_pushinteger(L, value);
                        lua_settable(L, -3);
                    }
                    lua_settable(L, -3);
                }
 
 
                if(pFieldDescriptor->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT)
                {
                    int psize = reflection->FieldSize(message, pFieldDescriptor);   
                    string fieldName = pFieldDescriptor->name();
                    lua_pushstring(L,fieldName.c_str());
                    lua_newtable(L);
                    for(int i = 0;i < psize;++i)
                    {
                        lua_pushnumber(L, i);
                        float value = reflection->GetRepeatedFloat(message, pFieldDescriptor, i);
                        lua_pushnumber(L, value);
                        lua_settable(L, -3);
                    }
                    lua_settable(L, -3);
                }
 
 
                if(pFieldDescriptor->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE)
                {
                    int psize = reflection->FieldSize(message, pFieldDescriptor);   
                    string fieldName = pFieldDescriptor->name();
                    lua_pushstring(L,fieldName.c_str());
                    lua_newtable(L);
                    for(int i = 0;i < psize;++i)
                    {
                        lua_pushnumber(L, i);
                        double value = reflection->GetRepeatedDouble(message, pFieldDescriptor, i);
                        lua_pushnumber(L, value);
                        lua_settable(L, -3);
                    }
                    lua_settable(L, -3);
                }
 
                if(pFieldDescriptor->cpp_type() == FieldDescriptor::CPPTYPE_UINT32)
                {
                    int psize = reflection->FieldSize(message, pFieldDescriptor);   
                    string fieldName = pFieldDescriptor->name();
                    lua_pushstring(L,fieldName.c_str());
                    lua_newtable(L);
                    for(int i = 0;i < psize;++i)
                    {
                        lua_pushnumber(L, i);
                        uint32 value = reflection->GetRepeatedUInt32(message, pFieldDescriptor, i);
                        lua_pushinteger(L, value);
                        lua_settable(L, -3);
                    }
                    lua_settable(L, -3);
                }
 
                if(pFieldDescriptor->cpp_type() == FieldDescriptor::CPPTYPE_UINT64)
                {
                    int psize = reflection->FieldSize(message, pFieldDescriptor);   
                    string fieldName = pFieldDescriptor->name();
                    lua_pushstring(L,fieldName.c_str());
                    lua_newtable(L);
                    for(int i = 0;i < psize;++i)
                    {
                        lua_pushnumber(L, i);
                        uint64 value = reflection->GetRepeatedUInt64(message, pFieldDescriptor, i);
                        lua_pushinteger(L, value);
                        lua_settable(L, -3);
                    }
                    lua_settable(L, -3);
                }
            }
        }
        else
        {
            //
            //if(!reflection->HasField(message, pFieldDescriptor))
            //{
            //    continue;
            //}
 
            getValue(reflection,pFieldDescriptor,message,L);
        }
    }
}
 
ERROR Proto::unpackHeader(const uint8* buff,uint32 length,lua_State* L,int &outType,int &session,int ×tamp)
{//静态解析协议头,代码略
 
    return ERROR::SUCCESS_UNPACK;
}
 
ERROR Proto::unpackContent(int type, int session, int timestamp, const uint8* buff, uint32 length, lua_State* L)
{ 
    const FileDescriptor *fileDescriptor = DescriptorPool::generated_pool()->FindFileByName(unpackProtoFileName);
    if(nullptr == fileDescriptor)
    {
        return ERROR::ERROR_UNPACK_FILE;
    }
    
    if(type >= fileDescriptor->message_type_count() || type < 0)
    {
        return ERROR::ERROR_UNPACK_TYPE_INDEX;
    }
    
    const Descriptor *descriptor = fileDescriptor->message_type(type);
    if(nullptr == descriptor)
    {
        return ERROR::ERROR_UNPACK_TYPE_INDEX;
    }
 
    DynamicMessageFactory factory;
    const Message *msg = factory.GetPrototype(descriptor); 
    Message *message = msg->New(); 
 
    if (!message->ParseFromArray(buff,length))
    {
        std::cout<<"HEX DATA CONTENT:"<<std::endl;
        for(int i = 0; i<length; i++) {
            std::cout.fill('0');//设置填充字符
            std::cout.width(2);//设置域宽
            std::cout<<std::setbase(16);
            std::cout<<std::hex<<(int)buff[i];
        }
        std::cout<<std::endl;
        return ERROR::ERROR_UNPACK_ERROR;
    }
    lua_settop(L,0);
    lua_pushstring(L,descriptor->name().c_str());
    lua_newtable(L);
    
    unpack(*message,L);
 
    lua_pushinteger(L,timestamp);
    lua_pushinteger(L,session);
 
    delete message;
    return ERROR::SUCCESS_UNPACK;
}
 
void Proto::getValue(
    const Reflection* reflection,
    const FieldDescriptor* pFieldDescriptor,
    const Message &message,
    lua_State* L,
    int index)
{
    if(!pFieldDescriptor->is_repeated())
    {
        string fieldName = pFieldDescriptor->name();
        lua_pushstring(L,fieldName.c_str());
    }
    else
    {
        lua_pushnumber(L,index);
    }
 
    switch (pFieldDescriptor->cpp_type())
    {
        case FieldDescriptor::CPPTYPE_STRING:
        {
            string value = reflection->GetString(message,pFieldDescriptor);
            lua_pushlstring(L,value.c_str(),value.size());
            break;
        }        
        case FieldDescriptor::CPPTYPE_INT32:
        {
            int32 value = reflection->GetInt32(message,pFieldDescriptor);
            lua_pushinteger(L,value);
            break;
        }
        case FieldDescriptor::CPPTYPE_BOOL:
        {
            int value = reflection->GetBool(message,pFieldDescriptor);
            lua_pushinteger(L,value); 
            break;
        }
        case FieldDescriptor::CPPTYPE_ENUM:
        {
            //int value = reflection->GetEnum(message,pFieldDescriptor);
            //lua_pushinteger(L,value); 
            break;
        }
        case FieldDescriptor::CPPTYPE_FLOAT:
        {
            float value = reflection->GetFloat(message,pFieldDescriptor);
            lua_pushnumber(L,value); 
            break;
        }
        case FieldDescriptor::CPPTYPE_DOUBLE:
        {
            double value = reflection->GetDouble(message,pFieldDescriptor);
            lua_pushnumber(L,value); 
            break;
        }
        case FieldDescriptor::CPPTYPE_UINT64:
        {
            uint64 value = reflection->GetUInt64(message,pFieldDescriptor);
            lua_pushinteger(L,value); 
            break;
        }
        case FieldDescriptor::CPPTYPE_INT64:
        {
            int64 value = reflection->GetInt64(message,pFieldDescriptor);
            lua_pushinteger(L,value); 
            break;
        }
        case FieldDescriptor::CPPTYPE_UINT32:
        {
            uint32 value = reflection->GetUInt32(message,pFieldDescriptor);
            lua_pushinteger(L,value); 
            break;
        }
        case FieldDescriptor::CPPTYPE_MESSAGE:
        {
            lua_newtable(L);
            const Message &subMessage = reflection->GetMessage(message,pFieldDescriptor);
            unpack(subMessage,L);
            break;
        }
        default:
        {
            //log
            break;
        }
    }
    lua_settable(L,-3);
}
 
bool Proto::hasRes(const string& typeName)
{
    const FileDescriptor *fileDescriptor = DescriptorPool::generated_pool()->FindFileByName(packProtoFileName);
    if(nullptr == fileDescriptor)
    {
           return false;
    }
    const Descriptor *descriptor = fileDescriptor->FindMessageTypeByName(typeName);
    if(nullptr == descriptor)
    {
        return false;
    }
    return true;
}

#include "pb.h"
#include "error.h"
 
extern "C"{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
 
extern"C"
int lpack(lua_State *L)
{
  Proto *proto = Proto::getInstance();
    ERROR error = proto->pack(L);
    if(ERROR::SUCCESS_PACK != error)
    {
        return luaL_error(L,"error: %d",error);
    }
    return 1;
}  
 
extern"C"
int lunpack(lua_State *L)
{
    Proto *proto = Proto::getInstance();
    ERROR error = proto->unpack(L);
    if(ERROR::SUCCESS_UNPACK != error){
        return luaL_error(L, "unpack error: %d",error);
    }
    return lua_gettop(L);
}
 
extern "C"
int lclear(lua_State *L)
{
    lua_settop(L,0);
    return 0;
}
 
extern "C"
int lhasres(lua_State *L)
{
    Proto *proto = Proto::getInstance();
    bool hasRes = false;
    if(LUA_TSTRING == lua_type(L, -1))
    {    
        string typeName = lua_tostring(L, -1);
        hasRes = proto->hasRes(typeName);
        lua_settop(L,0);
    }
    lua_pushboolean(L,hasRes);
    return 1;
}
 
extern "C"
int lsetproto(lua_State *L)
{
    string packFile,unpackFile = "";
    if(LUA_TSTRING == lua_type(L, -1))
    {
        unpackFile = lua_tostring(L,-1);
    }
    if(LUA_TSTRING == lua_type(L, -2))
    {
        packFile =lua_tostring(L,-2);
    }
 
    Proto *proto = Proto::getInstance();
    ERROR error = proto->setProto(packFile,unpackFile);
 
    if(ERROR::ERROR_NONE != error)
    {
        return luaL_error(L,"setproto error :%d",error);
    }
    lua_settop(L, 0);
    return 0;
}
 
extern "C"
int luaopen_protobufclua(lua_State* L) 
{
    luaL_Reg protobufclua[] = {
        {"pack", lpack},
        {"unpack", lunpack},
        {"clear", lclear},
        {"hasRes",lhasres},
        {"setproto",lsetproto},
        {NULL, NULL}
    };
 
  luaL_newlib(L, protobufclua);
 
  return 1;
}
 


protobuf for lua
代码里面包含了C++反射处理protobuf,C++构造Lua表,C++读取Lua表,C++静态处理protobuf。

大端,小端的short转换为字节。

经过测试,代码稳定。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值