读xml生成相应的 lua解析协议代码:
#include <iostream>
#include "tinyxml2.h"
#include <fstream>
#include <string>
using namespace tinyxml2;
using namespace std;
std::ofstream file("readProto.lua",std::ios::ate|std::ios::binary);
void read_S_ElementChild(XMLElement *surface)
{
while (surface)
{
const XMLAttribute *attr = surface->FirstAttribute();//获取第一个属性值
string strType;
bool isArray = false;
while(attr)
{
if (strcmp(attr->Name(), "name")==0)
{
string name = attr->Value();
string dataStr = "data.";
string temp1 = "\t" + dataStr + name + " = ";
string temp;
if(strcmp(strType.c_str(), "String")==0){
temp = "is:readUTF8()";
}else if(strcmp(strType.c_str(), "long")==0){
temp = "is:readLong()";
}else if(strcmp(strType.c_str(), "int")==0){
temp = "is:readInt()";
}else if(strcmp(strType.c_str(), "short")==0){
temp = "is:readShort()";
}else if(strcmp(strType.c_str(), "byte")==0){
temp = "is:readByte()";
}else if(strcmp(strType.c_str(), "boolean")==0){
temp = "is:readBool()";
}else if(strcmp(strType.c_str(), "float")==0){
temp = "is:readJavaFloat()";
}else{
size_t len = strType.size();
string lastStr = strType.substr(len-2, 2);
if(strcmp(lastStr.c_str(), "[]")==0){ //代表是数组
isArray = true;
file << "\tlocal cnt = is:readShort()" << endl;
file << "\tlocal temps = {}" << endl;
file << "\tfor i=1, cnt do" << endl;
string preStr = strType.substr(0, len-2);
string preStrTemp;
if(strcmp(preStr.c_str(), "String")==0){
preStrTemp = "is:readUTF8()";
}else if(strcmp(preStr.c_str(), "long")==0){
preStrTemp = "is:readLong()";
}else if(strcmp(preStr.c_str(), "int")==0){
preStrTemp = "is:readInt()";
}else if(strcmp(preStr.c_str(), "short")==0){
preStrTemp = "is:readShort()";
}else if(strcmp(preStr.c_str(), "byte")==0){
preStrTemp = "is:readByte()";
}else if(strcmp(preStr.c_str(), "boolean")==0){
preStrTemp = "is:readBool()";
}else if(strcmp(preStr.c_str(), "float")==0){
preStrTemp = "is:readJavaFloat()";
}else
{
preStrTemp = "read_" + preStr + "(is)";
}
file << "\t\ttemps[i] = " << preStrTemp << endl;
file << "\tend" << endl;
}else{
temp = "read_" + strType + "(is)";
}
}
if(!isArray){
file << temp1 + temp;
}else{ //是数组
file << temp1 + "temps" ;
}
}else if(strcmp(attr->Name(), "type")==0)
{
strType = attr->Value();
}else if(strcmp(attr->Name(), "description")==0)
{
string desc = attr->Value();
string temp = " --" + desc;
file << temp << endl;
if(isArray)
{
file << endl;
}
}
attr = attr->Next(); //获取下一个属性值
}
surface = surface->NextSiblingElement();//当前对象的下一个节点
}
}
void read_C_ElementChild(XMLElement *surface)
{
int i = 0;
while (surface)
{
string strType;
const XMLAttribute *attr = surface->FirstAttribute();//获取第一个属性值
while(attr)
{
if (strcmp(attr->Name(), "name")==0)
{
string temp;
bool isNum = false;
string param = "param";
char num[4]="";
sprintf_s(num, "%d", i);
if(strcmp(strType.c_str(), "String")==0){
temp = "sendData:writeUTF8(";
}else if(strcmp(strType.c_str(), "long")==0){
isNum = true;
temp = "sendData:writeLong(";
}else if(strcmp(strType.c_str(), "int")==0){
isNum = true;
temp = "sendData:writeInt(";
}else if(strcmp(strType.c_str(), "short")==0){
isNum = true;
temp = "sendData:writeShort(";
}else if(strcmp(strType.c_str(), "byte")==0){
isNum = true;
temp = "sendData:writeByte(";
}else if(strcmp(strType.c_str(), "boolean")==0){
temp = "sendData:writeBool(";
}else if(strcmp(strType.c_str(), "float")==0){
isNum = true;
temp = "sendData:writeJavaFloat(";
}else{
temp = "error ############ ";
}
if (isNum)
{
file << "\tlocal " + param + num + " = tonumber(" + "self:getExtraValue(" + num + "))" << endl;
}else{
file << "\tlocal " + param + num + " = " + "self:getExtraValue(" + num + ")" << endl;
}
file << "\t" + temp + param + num + ")" ;
}else if(strcmp(attr->Name(), "type")==0){
strType = attr->Value();
}else if(strcmp(attr->Name(), "description")==0){
file << " --" << attr->Value() << endl;
}
attr = attr->Next(); //获取下一个属性值
}
i = i + 1;
surface = surface->NextSiblingElement();//当前对象的下一个节点
}
}
void read_xml(XMLElement *surface)
{
while (surface)
{
string id;
string name;
bool isRead = true;
const XMLAttribute *attr = surface->FirstAttribute();//获取第一个属性值
while(attr)
{
if(strcmp(attr->Name(), "id")==0)
{
id = attr->Value();
}else if(strcmp(attr->Name(), "name")==0)
{
name = attr->Value();
string fristStr = name.substr(0,1);
string wirteStr = "function read_" + name + "(is)";
if(strcmp(fristStr.c_str(), "C")== 0 )
{
isRead = false;
wirteStr = "function send_" + name + "(self)";
}
file << wirteStr ;
}else if(strcmp(attr->Name(), "description")==0)
{
file << " --" << attr->Value() << endl;
if (!isRead)
{
file << "\tlocal " + name + " = " + id + " --" + attr->Value() << endl;
file << "\tlocal sendData = ByteArrayOutputStream()" << endl;
file << "\tsendData:writeInt(" + id + ")" << endl;
}
}
attr = attr->Next(); //获取下一个属性值
}
XMLElement *surface1 = surface->FirstChildElement(); //查看当前对象是否有子节点
if(surface1)
{
if(isRead)
{
file << "\tlocal data = {}" << endl;
read_S_ElementChild(surface1);//递归调用
}else
{
read_C_ElementChild(surface1);
}
}
if (isRead)
{
file << "\treturn data" << endl;
}else
{
file << "\tsendDataStream(sendData)" << endl;
}
file << "end" << endl;
file << endl;
surface = surface->NextSiblingElement();//当前对象的下一个节点
}
}
int main()
{
if(!file)
{
std::cout<<"文件打开失败!";
abort();//等同于exit
}
tinyxml2::XMLDocument mydocument; //声明xml对象
mydocument.LoadFile("protocol.xml"); //载入xml文件
XMLElement *rootElement = mydocument.RootElement(); //获取跟节点
XMLElement *surface = rootElement->FirstChildElement("message");//获取第一个值为value的子节点 默认为空则返回第一个节点
read_xml(surface);
file.close();
cin.get();
}
xml
<message id="0x09001017" name="S_ITEM_ADD_TASK" description="向背包添加一种任务道具">
<field type="int" name="task_max" description="任务道具包裹的当前长度(可能有空格)"/>
<field type="S_ITEM_TASKPROPS[]" name="items" description="数据"/>
</message>
<message id="0x02000006" name="C_MAP_NODE_ARRIVE" description="角色到达结点">
<field type="int" name="id" description="关卡结点id"/>
<field type="boolean" name="isEnd" description="是否到达终点"/>
</message>
生成效果:
function read_S_ITEM_ADD_TASK(is) --向背包添加一种任务道具
local data = {}
data.task_max = is:readInt() --任务道具包裹的当前长度(可能有空格)
local cnt = is:readShort()
local temps = {}
for i=1, cnt do
temps[i] = read_S_ITEM_TASKPROPS(is)
end
data.items = temps --数据
return data
end
function send_C_MAP_NODE_ARRIVE(self) --角色到达结点
local C_MAP_NODE_ARRIVE = 0x02000006 --角色到达结点
local sendData = ByteArrayOutputStream()
sendData:writeInt(0x02000006)
local param0 = tonumber(self:getExtraValue(0))
sendData:writeInt(param0) --关卡结点id
local param1 = self:getExtraValue(1)
sendData:writeBool(param1) --是否到达终点
sendDataStream(sendData)
end