先上代碼:
#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
#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轉換爲字節。
經過測試,代碼穩定。