如果不使用Protobuff这类的工具,想在C++与其他语言之间共享数据似乎是一个大工程,需要写很多的的代码。Protobuff这类工具本身也具有一些问题,比如过度包装,内存,效率等等。而且引入一大堆库也增加了维护难度。C++有自身的序列化方式,最常见的就是 boost 提供的序列化方法(使用C++模板),好用,代码量少,而且简单,而且很容易就可以将这种方法迁移到其他工程里。但这个方法有个问题,几乎不可能将这种方法复制到其他语言环境内。例如C#,本身就不支持模板,而是一种泛型的思路。所以,这种序列化方法注定是c++独有。
但c++的序列化方式非常好用,让我将序列化方式换成Protobuff还真舍不得,但是为了和客户端通讯,似乎又不得不做一些什么。想了很久,找到一个办法,C#不可能像C++那样只需要定义外部Serialize函数即可定义好序列化的协议,唯一的办法就是通过C++读取序列化的协议,来生成C#对应的方法,比如一个c++结构体,通过实现序列化方法。实现了数据传输协议的约定,而我们要做的,就是读取这个协议,然后生成对应的C#的类,来序列化,反序列化这个数据。当然,这个方式就C++来看非常的笨,但没办法,Protobuff也是通过类似的方式来实现的,比如我们把下面这个类通过同样的序列化方法,转译成C#,那么C++与C#之间的通讯就无须采用额外的第三方库。
struct tagTest
{
U32 index;
vector<float> datas;
};
template<class Archive>
inline void Serialize(Archive & archive, tagTest & value, bool isSave)
{
UNREFERENCED_PARAMETER(isSave);
archive.Bind( value.index );
archive.Bind( value.datas );
}
转译成C#:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System;
namespace elapsing
{
public class tagTest : ISerializable
{
public UInt32 index;
public List<float> datas;
public tagTest()
{
index = default(UInt32);
datas = new List<float> ();
}
public bool Serialize(BytesWriter stream)
{
// Member index
stream.Write(index);
// Member datas
UInt32 length_a5778682 = (UInt32)datas.Count;
UInt16 verify_a5778682 = BytesOperator.InternetCheckSum(System.BitConverter.GetBytes(length_a5778682));
stream.Write(length_a5778682);
stream.Write(verify_a5778682);
for (UInt32 i_a5778682 = 0; i_a5778682 < length_a5778682; ++i_a5778682)
{
stream.Write(datas[(Int32)i_a5778682]);
}
//End Serialize
return true;
}
public bool Deserialize(BytesReader stream)
{
// Member index
stream.Read( out index);
// Member datas
UInt32 length_a5778682 = stream.ReadU32();
UInt16 verify_a5778682 = stream.ReadU16();
datas.Clear();
for (UInt32 i_a5778682 = 0; i_a5778682 < length_a5778682; ++i_a5778682)
{
var ds_data = default(float);
stream.Read( out ds_data);
datas.Add( ds_data );
}
//End Deserialize
return true;
}
}
}
这样也就达到了用C++序列化函数来生成C#代码,并且实现与C#之间数据交互的目的。
为了实现这个目的,主要的设计思路就是用C++的Serialize函数,通过一个额外设计的Archive类来读取Serialize函数内的要序列化的数据名称,类型等信息,然后生成一个完整的树状结构,并且通过这个树状结构为每一层生成具体的对应文件。
注意在Serialize函数中,我们用Bind方法来读或则写数据,但是Bind方法只有一个参数,为了能获取到它的名字,我们用这个办法来获取:
#define Bind(X) Bind(#X, X)
但相应的,Archive类必须实现对应的方法。
其他的,就贴代码吧,很容易读懂的,第一个是成员的定义的结构体。其中:define是解析后的定义(int float之类),keyptr:如果是map之类,那么key就是map的key的类型,def_dims: 定义的逐层的链表, arr_dims:如果是数组,则记录数组的数据。方法就看名字,很容易理解。
#ifndef TAGMEMBERDEFINE_H
#define TAGMEMBERDEFINE_H
//Begin section for file tagMemberDefine.h
//TODO: Add definitions that you want preserved
//End section for file tagMemberDefine.h
#include "../Common.h"
namespace unity
{
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
struct tagMemberDefine
{
//Begin section for unity::tagMemberDefine
//TODO: Add attributes that you want preserved
//End section for unity::tagMemberDefine
public:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
typedef CLocalObjectPtr<tagMemberDefine> Ptr ;
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
typedef vector<size_t, atom_allocator<size_t> > Arr ;
public:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string define;
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
Ptr keyptr;
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
Ptr def_dims;
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
Arr arr_dims;
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
tagMemberDefine();
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
tagMemberDefine(const tagMemberDefine & value);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
virtual ~tagMemberDefine();
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
tagMemberDefine & operator =(const tagMemberDefine & value);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool IsPrototype()const ;
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string CreateStatement(a_string var_name);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void ParseClassDefine(a_string def_str);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string RegularClassName(a_string & name);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string Splite(a_string & define, a_string & first);
}; //end struct tagMemberDefine
} //end namespace unity
#endif
第二个类,稍微复杂些,派生于tagMemberDefine,parent是上级节点地址,member是成员变量的列表,type是输入的类型(没有解析之前),name是成员变量。方法也是,看名字就知道意思。
#ifndef TAGMEMBER_H
#define TAGMEMBER_H
//Begin section for file tagFoodProperty.h
//TODO: Add definitions that you want preserved
//End section for file tagFoodProperty.h
#include "../Common.h"
#include "tagMemberDefine.h"
namespace unity
{
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
struct tagMember : public tagMemberDefine
{
//Begin section for nova::tagFoodProperty
//TODO: Add attributes that you want preserved
//End section for nova::tagFoodProperty
public:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
typedef std::list<tagMember, atom_allocator<tagMember> > Array ;
public:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
unity::tagMember * parent;
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
Array member;
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string type;
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string name;
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
tagMember();
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
tagMember(const tagMember & value);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
virtual ~tagMember();
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
tagMember & operator =(const tagMember & value);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Parse();
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool IsKeyword(a_string & name);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string CreateStatement();
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string DefineStatement();
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string RegularMemberName(a_string & name);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool Scripting(a_string path);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool ScriptingAttach(U32 indent, FILE * file);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool ScriptingDetach(U32 indent, FILE * file);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool ScriptingAttachArray(U32 indent, FILE * file, tagMember & node, U32 level);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool ScriptingDetachArray(U32 indent, FILE * file, tagMember & node, U32 level);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool ScriptingAttachClass(U32 indent, FILE * file, tagMemberDefine & node, a_string name);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool ScriptingDetachClass(U32 indent, FILE * file, tagMemberDefine & node, a_string name);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool ScriptingIndent(U32 indent, FILE * file);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void DebugOut(U32 level, a_string indent, U08 flag);
}; //end struct tagMember
} //end namespace unity;
#endif
第三个比较重要的就是这个改造的Archive,其实很简单,就是增加一些带名字的方法,然后填充数据结构。
#ifndef UNITY_CARCHIVE_H
#define UNITY_CARCHIVE_H
//Begin section for file CArchive.h
//TODO: Add definitions that you want preserved
//End section for file CArchive.h
#include "../Common.h"
#include "../bind/tagStructure.h"
#include "tagMember.h"
namespace unity
{
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
class CArchive
{
//Begin section for atom::CArchive
//TODO: Add attributes that you want preserved
//End section for atom::CArchive
private:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
tagMember root;
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
tagMember * current;
public:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
CArchive() : current( & root )
{
//TODO Auto-generated method stub
root.name = "root";
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
virtual ~CArchive()
{
//TODO Auto-generated method stub
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(bool & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "bool";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(const char * name, bool & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "bool";
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(char & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "char";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(const char * name, char & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "char";
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(I08 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "sbyte";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(const char * name, I08 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "sbyte";
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(I16 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "Int16";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(const char * name, I16 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "Int16";
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(I32 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "Int32";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(const char * name, I32 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "Int32";
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(I64 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "Int64";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(const char * name, I64 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "Int64";
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(U08 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "byte";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(const char * name, U08 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "byte";
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(U16 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "UInt16";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(const char * name, U16 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "UInt16";
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(U32 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "UInt32";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(const char * name, U32 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "UInt32";
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(U64 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "UInt64";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(const char * name, U64 & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "UInt64";
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(float & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "float";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(const char * name, float & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "float";
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(double & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "double";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(const char * name, double & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "double";
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(a_string & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "string";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(const char * name, a_string & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "string";
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(a_wstring & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "string";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(const char * name, a_wstring & value)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "string";
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Bind(void * buffer, U64 length)
{
//TODO Auto-generated method stub
tagMember member;
member.type = "byte[]";
member.parent = current;
member.Parse();
current -> member.push_back( member );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void BeginClass(const char * type, const char * name)
{
//TODO Auto-generated method stub
tagMember member;
member.type = type;
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
current = & current -> member.back();
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void BeginArray(const char * type, size_t size, const char * name)
{
//TODO Auto-generated method stub
tagMember member;
member.type = type;
member.name = name;
member.parent = current;
member.Parse();
current -> member.push_back( member );
current = & current -> member.back();
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void End()
{
//TODO Auto-generated method stub
current = current -> parent;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
template <class T>
void Bind(T & value)
{
//TODO Auto-generated method stub
tagStructure<CArchive, T, true>::Serialize( * this, "", value );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
template <class T>
void Bind(const T & value)
{
//TODO Auto-generated method stub
Bind( const_cast<T &>(value) );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
template <class T>
void Bind(const char * name, T & value)
{
//TODO Auto-generated method stub
tagStructure<CArchive, T, true>::Serialize( *this, name, value );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
template <class T>
void Bind(const char * name, const T & value)
{
//TODO Auto-generated method stub
Bind( name, const_cast<T &>(value) );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
template <class T>
inline CArchive & operator <<(T & value)
{
//TODO Auto-generated method stub
Bind( value );
return( *this );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
template <class T>
inline CArchive & operator <<(const T & value)
{
//TODO Auto-generated method stub
Bind( value );
return( *this );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
template <class T>
inline CArchive & operator >>(T & value)
{
//TODO Auto-generated method stub
Bind( value );
return( *this );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Print()
{
//TODO Auto-generated method stub
root.DebugOut( 0, "", 0 );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Assign(const CMemory & data)
{
//TODO Auto-generated method stub
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Clone(CMemory & data)
{
//TODO Auto-generated method stub
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool Scripting(const char * path)
{
//TODO Auto-generated method stub
return root.member.front().Scripting( path );
}
}; //end class CArchive
} //end namespace atom
#endif
需要对序列化Array和class的模板稍作修改:
#ifndef UNITY_TAGARRAY_H
#define UNITY_TAGARRAY_H
//Begin section for file tagArray.h
//TODO: Add definitions that you want preserved
//End section for file tagArray.h
#include "../Common.h"
namespace unity
{
//@uml.annotationsderived_abstraction="platform:/resource/SystemInterface/document/System%20Interface.emx#_GwgikKxjEdyG2OUyJIn0qA"
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
template <class A, class T, bool save>
struct tagArray
{
//Begin section for si::tagArray
//TODO: Add attributes that you want preserved
//End section for si::tagArray
public:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
inline static void Invoke(A & ar, const char * name, T & t)
{
//TODO Auto-generated method stub
// 读取或写入数组的长度;
U32 bound = static_cast<U32>( array_trait<T>::bound );
ar.BeginArray( typeid(T).name(), bound, name );
U32 limit = bound;
ar.Bind( bound );
// 确认数组的长度是否越界;
bound = atom_min( bound, limit );
// 读取或写入数组的元素;
for( size_t i = 0; i < bound; ++ i )
{
ar.Bind( t[i] );
}
ar.End();
}
}; //end struct tagArray
} // end namespace atom
#endif
#ifndef UNITY_TAGCLASS_H
#define UNITY_TAGCLASS_H
//Begin section for file tagClass.h
//TODO: Add definitions that you want preserved
//End section for file tagClass.h
namespace unity
{
//@uml.annotationsderived_abstraction="platform:/resource/SystemInterface/document/System%20Interface.emx#_gQx30KxjEdyG2OUyJIn0qA"
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
template <class A, class T, bool save>
struct tagClass
{
//Begin section for si::tagClass
//TODO: Add attributes that you want preserved
//End section for si::tagClass
public:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
inline static void Invoke(A & ar, const char * name, T & t)
{
//TODO Auto-generated method stub
ar.BeginClass( typeid(T).name(), name );
Serialize( ar, t, save );
ar.End();
}
}; //end struct tagClass
} // end namespace atom
#endif
最后就是两个结构体方法的实现:
#include "tagMemberDefine.h"
//Begin section for file tagMemberDefine.cpp
//TODO: Add definitions that you want preserved
//End section for file tagMemberDefine.cpp
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
unity::tagMemberDefine::tagMemberDefine()
{
//TODO Auto-generated method stub
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
unity::tagMemberDefine::tagMemberDefine(const tagMemberDefine & value) :
define(value.define),keyptr(value.keyptr),def_dims(value.def_dims),arr_dims(value.arr_dims)
{
//TODO Auto-generated method stub
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
unity::tagMemberDefine::~tagMemberDefine()
{
//TODO Auto-generated method stub
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
unity::tagMemberDefine & unity::tagMemberDefine::operator =(const tagMemberDefine & value)
{
//TODO Auto-generated method stub
define = value.define;
keyptr = value.keyptr;
def_dims = value.def_dims;
arr_dims = value.arr_dims;
return( * this );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool unity::tagMemberDefine::IsPrototype() const
{
//TODO Auto-generated method stub
bool result = false;
#define MAX_PROTOTYPE 20
static char * prototype[] = {
"bool",
"char",
"byte",
"sbyte",
"int",
"uint",
"short",
"ushort",
"long",
"ulong",
"Int16",
"UInt16",
"Int32",
"UInt32",
"Int64",
"UInt64",
"float",
"double",
"decimal",
"string",
};
for( size_t i = 0; i < MAX_PROTOTYPE; ++ i )
{
if( define == prototype[i] ) {
result = true; break;
}
}
return result;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string unity::tagMemberDefine::CreateStatement(a_string var_name)
{
//TODO Auto-generated method stub
a_string result;
// 如果不是原型,或则有数组,则用new;
if( !IsPrototype() || !arr_dims.empty() )
{
result += var_name;
result += " = new ";
// 遍历数组深度
size_t total = 0; Ptr value = * this;
do
{
// 增加定义
result += value -> define;
// 如果有子类,继续
if( value -> def_dims )
{
result += "<";
if( value -> keyptr )
{
result += value -> keyptr -> define;
result += ", ";
}
++ total;
}
// 遍历下一个
value = value -> def_dims;
} while( value );
// 恢复尖括号
for( size_t i = 0; i < total; ++ i )
{
result += "> ";
}
// 如果是类,并且没有维度;
// 原型不需要()
// 数组不需要()
if( !IsPrototype() && arr_dims.empty() )
{
result += "()";
}
// 如果有维度,则增加数组的定义;
if( !arr_dims.empty() )
{
result += "[";
for( size_t i = 0, j = arr_dims.size(); i < j; ++ i )
{
char msg[32];
sprintf( msg, "%llu", arr_dims[i] );
result += msg;
// 逗号个数要减一;
if( i + 1 < j ) {
result += ",";
}
}
result += "]";
}
}
// 原型,可以直接用default来处理;
else
{
result += var_name;
result += " = default(";
result += define;
result += ")";
}
return result;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void unity::tagMemberDefine::ParseClassDefine(a_string def_str)
{
//TODO Auto-generated method stub
a_string::size_type
pos_1 = a_string::npos,
pos_2 = a_string::npos;
// 判断array,必须考虑内嵌对象的数组形式 vector<a[10]> [10]
for( ; ; )
{
// 从后往前找方括号 [
pos_1 = def_str.rfind( '[' );
if( pos_1 == a_string::npos ) {
break;
}
// 从pos_1位置开始,从前往后找方括号 ]
pos_2 = def_str.find( ']', pos_1 );
if( pos_2 == a_string::npos )
{
CLog log;
log << "Invalid class declare string: " << def_str << end_error;
exit(-1);
break;
}
// 从pos_2开始,到最后除了空格不能有任何其他字符
if( def_str.find_first_not_of("] ", pos_2) != a_string::npos )
{
break;
}
// 将维度的值解析出来,并插入到数组的首部位置;
arr_dims.insert( arr_dims.begin(),
atoi( def_str.substr(pos_1 + 1, pos_2 - pos_1 - 1).c_str() ) );
// 剪切字符串,去掉最后一个数组定义
def_str = trim( def_str.substr(0, pos_1) );
}
// 再解析对象;
for( ;; )
{
// 从开始找第一个尖括号 <
pos_1 = def_str.find( '<' );
if( pos_1 == a_string::npos ) {
break;
}
// 从后开始找第一个尖括号 >
pos_2 = def_str.rfind( '>' );
if( pos_2 == a_string::npos )
{
CLog log;
log << "Invalid class declare string: " << def_str << end_error;
exit(-1);
break;
}
// 先取出类名
define = RegularClassName( def_str.substr(0, pos_1) );
// 取出子类的定义(不包括尖括号<>)
a_string sub_class = def_str.substr( pos_1 + 1, pos_2 - pos_1 - 1 );
// 如果是字符串,则不再继续解析;
if( define == "basic_string") {
define = "string";
break;
}
// 如果是map,则拆分key和value
else
if( define == "map" )
{
// 直接指定为C#内的字典
define = "Dictionary";
// 准备取出map的key类型
a_string key_class;
sub_class = Splite( sub_class, key_class );
// 递归解析key的值,并赋予keyptr
tagMemberDefine key;
key.ParseClassDefine( key_class );
keyptr = key;
// 解析value的类型,
Splite( sub_class, sub_class );
}
// 其他容器,vector list set 之类的,用C# List代替
else
if( define == "vector" || define == "list" || define == "set" )
{
define = "List";
// 解析value的类型,
Splite( sub_class, sub_class );
}
else
{
CLog log;
log << "Unknow container type: " << sub_class << end_error;
exit(-1);
break;
}
tagMemberDefine next;
next.ParseClassDefine( sub_class );
def_dims = next;
break;
}
// 如果不是容器类对象,则解析类名
if( define.empty() ) {
define = RegularClassName( def_str );
}
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string unity::tagMemberDefine::RegularClassName(a_string & clsname)
{
//TODO Auto-generated method stub
if( clsname.empty() ) {
return clsname;
}
// 去掉class关键字
size_t offset = clsname.find("class ");
if( offset != a_string::npos ) {
clsname.erase( 0, offset + strlen("class") );
}
// 去掉struct关键字
offset = clsname.find("struct ");
if( offset != a_string::npos ) {
clsname.erase( 0, offset + strlen("struct") );
}
// 去掉所有的命名空间
offset = clsname.rfind("::");
if( offset != a_string::npos ) {
clsname.erase( 0, offset + strlen("::") );
}
// 替换一些不同的定义方式
typedef map<a_string, a_string, less<a_string>, atom_allocator<pair<const a_string, a_string> > > CPrototypeMap;
CPrototypeMap replace;
replace.insert( make_pair("unsigned char", "byte") );
replace.insert( make_pair("unsigned short", "UInt16") );
replace.insert( make_pair("unsigned int", "UInt32") );
replace.insert( make_pair("unsigned __int8", "byte") );
replace.insert( make_pair("unsigned __int16", "UInt16") );
replace.insert( make_pair("unsigned __int32", "UInt32") );
replace.insert( make_pair("unsigned __int64", "UInt64") );
replace.insert( make_pair("__int8", "sbyte") );
replace.insert( make_pair("__int16", "Int16") );
replace.insert( make_pair("__int32", "Int32") );
replace.insert( make_pair("__int64", "Int64") );
CPrototypeMap::const_iterator
it = replace.find( clsname );
if( it != replace.end() ) {
clsname = it -> second;
}
return trim( clsname );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string unity::tagMemberDefine::Splite(a_string & clsstr, a_string & subcls)
{
//TODO Auto-generated method stub
a_string result;
a_string key_class; size_t offset = 0;
for( ;; )
{
size_t r(0), l(0);
// 查找key结束的逗号位置;
offset = clsstr.find( ',', offset + 1 );
if( offset != a_string::npos )
{
// 统计 <> 的个数,必须相等,才是一个完整的定义
for( size_t i = 0; i < offset; ++ i )
{
if( clsstr.at(i) == '<' ) {
l ++;
}
if( clsstr.at(i) == '>' ) {
r ++;
}
}
}
if( r == l )
{
// 如果offset有效,则在此点分割前后;
if( offset != a_string::npos )
{
result = clsstr.substr( offset + 1 );
subcls = clsstr.substr( 0, offset );
}
// 如果offset无效,则将全部复制给subcls
else
{
subcls = clsstr;
}
break;
}
}
return result;
}
#include "tagMember.h"
//Begin section for file tagMember.cpp
//TODO: Add definitions that you want preserved
//End section for file tagMember.cpp
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
unity::tagMember::tagMember() :
parent(NULL)
{
//TODO Auto-generated method stub
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
unity::tagMember::tagMember(const tagMember & value) :
tagMemberDefine(value),parent(value.parent),member(value.member),type(value.type),name(value.name)
{
//TODO Auto-generated method stub
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
unity::tagMember::~tagMember()
{
//TODO Auto-generated method stub
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
unity::tagMember & unity::tagMember::operator =(const tagMember & value)
{
//TODO Auto-generated method stub
tagMemberDefine::operator=( value );
type = value.type;
name = value.name;
member = value.member;
parent = value.parent;
return( * this );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void unity::tagMember::Parse()
{
//TODO Auto-generated method stub
// 先规整命名,再分析类型
RegularMemberName( name );
ParseClassDefine ( type );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool unity::tagMember::IsKeyword(a_string & value)
{
//TODO Auto-generated method stub
bool result = false;
#define MAX_KEYWORD 81
static char * key_word[MAX_KEYWORD] = {
"abstract",
"as",
"base",
"bool",
"break",
"byte",
"case",
"catch",
"char",
"checked",
"class",
"const",
"continue",
"decimal",
"default",
"delegate",
"do",
"double",
"else",
"enum",
"ecent",
"explicit",
"extern",
"false",
"finally",
"fixed",
"float",
"for",
"foreach",
"get",
"goto",
"if",
"implicit",
"in",
"int",
"interface",
"internal",
"is",
"lock",
"long",
"namespace",
"new",
"null",
"object",
"out",
"override",
"partial",
"private",
"protected",
"public",
"readonly",
"ref",
"return",
"sbyte",
"sealed",
"set",
"short",
"sizeof",
"stackalloc",
"static",
"struct",
"switch",
"this",
"throw",
"true",
"try",
"typeof",
"uint",
"ulong",
"unchecked",
"unsafe",
"ushort",
"using",
"value",
"virtual",
"volatile",
"volatile",
"void",
"where",
"while",
"yield"
};
for( size_t i = 0; i < MAX_KEYWORD; ++ i )
{
if( value == key_word[i] ) {
result = true; break;
}
}
return result;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string unity::tagMember::CreateStatement()
{
//TODO Auto-generated method stub
return tagMemberDefine::CreateStatement( name );
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string unity::tagMember::DefineStatement()
{
//TODO Auto-generated method stub
a_string result;
size_t total = 0; Ptr value = * this;
do
{
result += value -> define;
if( value -> def_dims )
{
result += "<";
if( value -> keyptr )
{
result += value -> keyptr -> define;
result += ", ";
}
++ total;
}
value = value -> def_dims;
} while( value );
for( size_t i = 0; i < total; ++ i )
{
result += ">";
}
if( !arr_dims.empty() )
{
result += "[";
for( size_t i = 1; i < arr_dims.size(); ++ i ) {
result += ",";
}
result += "]";
}
return result;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
a_string unity::tagMember::RegularMemberName(a_string & member_name)
{
//TODO Auto-generated method stub
if( member_name.empty() ) {
return member_name;
}
// 去掉所有的类联系
size_t offset = member_name.rfind('.');
if( offset != a_string::npos ) {
member_name.erase( 0, offset + 1 );
}
trim( member_name );
// 增加前缀避免c++与c#之间不同的关键字
if( IsKeyword(member_name) ) {
member_name = "_" + member_name;
}
return member_name;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool unity::tagMember::Scripting(a_string path)
{
//TODO Auto-generated method stub
bool result = false;
a_string filename = path + "/" + define + ".cs";
FILE * file = fopen( filename.c_str(), "w+" );
if( file )
{
result = true;
// 包含定义
fprintf( file, "using System.Collections;\n" );
fprintf( file, "using System.Collections.Generic;\n" );
fprintf( file, "using System.IO;\n" );
fprintf( file, "using System;\n\n\n" );
// 命名空间
fprintf( file, "namespace elapsing\n" );
fprintf( file, "{\n\n\n" );
// 类定义
fprintf( file, " public class %s : ISerializable\n", define.c_str() );
fprintf( file, " {\n" );
// 成员变量,只处理本级的变量;
for( tagMember::Array::iterator
it = member.begin(); it != member.end(); ++ it )
{
fprintf( file, " public %s %s;\n", it -> DefineStatement().c_str(), it -> name.c_str() );
}
// 构造函数
fprintf( file, "\n\n" );
fprintf( file, " public %s()\n", define.c_str() );
fprintf( file, " {\n" );
// 创建成员变量,只创建本级的变量;
for( tagMember::Array::iterator
it = member.begin(); it != member.end(); ++ it )
{
a_string create = it -> CreateStatement();
if( !create.empty() ) {
fprintf( file, " %s;\n", create.c_str() );
}
}
fprintf( file, " }\n" );
// 序列化函数
fprintf( file, "\n\n" );
fprintf( file, " public bool Serialize(BytesWriter stream)\n" );
fprintf( file, " {\n" );
for( tagMember::Array::iterator
it = member.begin(); it != member.end(); ++ it )
{
// 第一级都是3层缩进
fprintf( file, "\n" );
fprintf( file, " // Member %s\n", it -> name.c_str() );
fprintf( file, "\n" );
result = it -> ScriptingAttach( 3, file ) && result;
}
fprintf( file, "\n //End Serialize\n" );
fprintf( file, " return true;\n" );
fprintf( file, " }\n" );
fprintf( file, "\n\n" );
// 反序列化函数
fprintf( file, " public bool Deserialize(BytesReader stream)\n" );
fprintf( file, " {\n" );
for( tagMember::Array::iterator
it = member.begin(); it != member.end(); ++ it )
{
// 第一级都是3层缩进
fprintf( file, "\n" );
fprintf( file, " // Member %s\n", it -> name.c_str() );
fprintf( file, "\n" );
result = it -> ScriptingDetach( 3, file ) && result;
}
// 反序列化结束
fprintf( file, "\n //End Deserialize\n" );
fprintf( file, " return true;\n" );
fprintf( file, " }\n" );
// 类结束,命名空间结束
fprintf( file, " }\n" );
fprintf( file, "}\n" );
fclose( file );
}
return result;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool unity::tagMember::ScriptingAttach(U32 indent, FILE * file)
{
//TODO Auto-generated method stub
bool result = false;
if( file )
{
// 首先处理数组
if( arr_dims.empty() == false )
{
result = ScriptingAttachArray( indent, file, * this, 0 );
}
// 处理类
else
{
result = ScriptingAttachClass( indent, file, * this, name );
}
}
return result;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool unity::tagMember::ScriptingDetach(U32 indent, FILE * file)
{
//TODO Auto-generated method stub
bool result = false;
if( file )
{
// 首先处理数组
if( arr_dims.empty() == false )
{
result = ScriptingDetachArray( indent, file, * this, 0 );
}
// 处理类
else
{
result = ScriptingDetachClass( indent, file, * this, name );
}
}
return result;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool unity::tagMember::ScriptingAttachArray(U32 indent, FILE * file, tagMember & node, U32 level)
{
//TODO Auto-generated method stub
bool result = false;
if( file )
{
if( level == node.arr_dims.size() ) {
return ScriptingAttachClass( indent + level, file, node, node.name );
}
atom_hash<a_string> hasher;
U32 hash = static_cast<U32>( hasher(node.name) );
ScriptingIndent( indent + level, file );
fprintf( file, "UInt32 length_%08x_%lu = %zu;\n", hash, level + 1, node.arr_dims[level] );
ScriptingIndent( indent + level, file );
fprintf( file, "stream.Write(length_%08x_%lu);\n", hash, level + 1 );
fprintf( file, "\n" );
ScriptingIndent( indent + level, file );
fprintf( file, "for (UInt32 i_%lu = 0; i_%lu < length_%08x_%lu; ++i_%lu)\n", level + 1, level + 1, hash, level + 1, level + 1 );
ScriptingIndent( indent + level, file );
fprintf( file, "{\n" );
result = ScriptingAttachArray( indent, file, node, level + 1 );
ScriptingIndent( indent + level, file );
fprintf( file, "}\n" );
}
return result;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool unity::tagMember::ScriptingDetachArray(U32 indent, FILE * file, tagMember & node, U32 level)
{
//TODO Auto-generated method stub
bool result = false;
if( file )
{
if( level == node.arr_dims.size() ) {
return ScriptingDetachClass( indent + level, file, node, node.name );
}
atom_hash<a_string> hasher;
U32 hash = static_cast<U32>( hasher(node.name) );
ScriptingIndent( indent + level, file );
fprintf( file, "UInt32 lenmax_%08x_%lu = %zu;\n", hash, level + 1, node.arr_dims[level] );
ScriptingIndent( indent + level, file );
fprintf( file, "UInt32 length_%08x_%lu = stream.ReadU32();\n", hash, level + 1 );
ScriptingIndent( indent + level, file );
fprintf( file, "length_%08x_%lu = Math.Min(length_%08x_%lu, lenmax_%08x_%lu);\n", hash, level + 1, hash, level + 1, hash, level + 1 );
fprintf( file, "\n" );
ScriptingIndent( indent + level, file );
fprintf( file, "for (UInt32 i_%lu = 0; i_%lu < length_%08x_%lu; ++i_%lu)\n", level + 1, level + 1, hash, level + 1, level + 1 );
ScriptingIndent( indent + level, file );
fprintf( file, "{\n" );
ScriptingDetachArray( indent, file, node, level + 1);
ScriptingIndent( indent + level, file );
fprintf( file, "}\n" );
}
return result;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool unity::tagMember::ScriptingAttachClass(U32 indent, FILE * file, tagMemberDefine & node, a_string node_name)
{
//TODO Auto-generated method stub
bool result = false;
if( !file ) {
return false;
}
a_string text = node_name;
// 获取名字的哈希值
atom_hash<a_string> hasher;
U32 hash = static_cast<U32>( hasher(node_name) );
// 处理数组
if( !node.arr_dims.empty() )
{
text += "[";
for( U32 i = 0, j =
static_cast<U32>( node.arr_dims.size() ); i < j; ++ i )
{
char msg[16];
sprintf( msg, "%lu", i + 1 );
text += "i_";
text += msg;
if( i + 1 < j ) {
text += ",";
}
}
text += "]";
}
// 如果 node 是原型,或则是 byte[] 则直接写;
if( node.IsPrototype() || node.define == "byte[]" )
{
text = "stream.Write(" + text + ");";
ScriptingIndent( indent, file );
fprintf( file, "%s\n", text.c_str() );
result = true;
}
// 如果是 Dictionary 容器,key / value
else
if( node.define == "Dictionary" )
{
ScriptingIndent( indent, file );
fprintf( file, "UInt32 length_%08x = (UInt32)%s.Count;\n", hash, node_name.c_str() );
ScriptingIndent( indent, file );
fprintf( file, "UInt16 verify_%08x = BytesOperator.InternetCheckSum(System.BitConverter.GetBytes(length_%08x));\n\n", hash, hash );
ScriptingIndent( indent, file );
fprintf( file, "stream.Write(length_%08x);\n", hash );
ScriptingIndent( indent, file );
fprintf( file, "stream.Write(verify_%08x);\n", hash );
fprintf( file, "\n" );
ScriptingIndent( indent, file );
fprintf( file, "foreach(var key_%08x in %s.Keys)\n", hash, node_name.c_str() );
ScriptingIndent( indent, file );
fprintf( file, "{\n" );
// write key;
char msg[16];
sprintf( msg, "key_%08x", hash );
if( node.keyptr ) {
result = ScriptingAttachClass( indent + 1, file, * node.keyptr, msg );
}
// write value;
a_string next_name = node_name + "[" + msg + "]";
if( node.def_dims ) {
result = ScriptingAttachClass( indent + 1, file, * node.def_dims, next_name ) && result;
}
ScriptingIndent( indent, file );
fprintf( file, "}\n" );
}
// 如果是List容器
else
if( node.define == "List" )
{
ScriptingIndent( indent, file );
fprintf( file, "UInt32 length_%08x = (UInt32)%s.Count;\n", hash, node_name.c_str() );
ScriptingIndent( indent, file );
fprintf( file, "UInt16 verify_%08x = BytesOperator.InternetCheckSum(System.BitConverter.GetBytes(length_%08x));\n\n", hash, hash );
ScriptingIndent( indent, file );
fprintf( file, "stream.Write(length_%08x);\n", hash );
ScriptingIndent( indent, file );
fprintf( file, "stream.Write(verify_%08x);\n", hash );
fprintf( file, "\n" );
ScriptingIndent( indent, file );
fprintf( file, "for (UInt32 i_%08x = 0; i_%08x < length_%08x; ++i_%08x)\n", hash, hash, hash, hash );
ScriptingIndent( indent, file );
fprintf( file, "{\n" );
// write value;
char msg[16];
sprintf( msg, "i_%08x", hash );
a_string next_name = node_name + "[(Int32)" + msg + "]";
if( node.def_dims ) {
result = ScriptingAttachClass( indent + 1, file, * node.def_dims, next_name );
}
ScriptingIndent( indent, file );
fprintf( file, "}\n" );
}
// 类的类型
else
{
text = text + ".Serialize(stream);";
ScriptingIndent( indent, file );
fprintf( file, "%s\n", text.c_str() );
result = true;
}
return result;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool unity::tagMember::ScriptingDetachClass(U32 indent, FILE * file, tagMemberDefine & node, a_string node_name)
{
//TODO Auto-generated method stub
bool result = false;
if( !file ) {
return false;
}
a_string text = node_name;
// 处理哈希值
atom_hash<a_string> hasher;
U32 hash = static_cast<U32>( hasher(node_name) );
// 处理数值
if( !node.arr_dims.empty() )
{
text += "[";
for( U32 i = 0, j =
static_cast<U32>( node.arr_dims.size() ); i < j; ++ i )
{
char msg[16];
sprintf( msg, "%d", i + 1);
text += "i_";
text += msg;
if( i + 1 < j ) {
text += ",";
}
}
text += "]";
}
// 如果是原型,则用标准方法读取;
if( node.IsPrototype() )
{
text = "stream.Read( out " + text + ");";
ScriptingIndent( indent, file );
fprintf( file, "%s\n", text.c_str() );
result = true;
}
// 如果是 Dictionary ,则读取 key, value
else
if( node.define == "Dictionary" )
{
ScriptingIndent( indent, file );
fprintf( file, "UInt32 length_%08x = stream.ReadU32();\n", hash );
ScriptingIndent( indent, file );
fprintf( file, "UInt16 verify_%08x = stream.ReadU16();\n", hash );
fprintf( file, "\n" );
ScriptingIndent( indent, file );
fprintf( file, "%s.Clear();\n", node_name.c_str() );
ScriptingIndent( indent, file );
fprintf( file, "for(UInt32 i_%08x = 0; i_%08x < length_%08x; ++ i_%08x)\n", hash, hash, hash, hash );
ScriptingIndent( indent, file );
fprintf( file, "{\n" );
char msg[16];
sprintf( msg, "key_%08x", hash );
// create key;
a_string create_string;
if( node.keyptr ) {
create_string = node.keyptr -> CreateStatement( a_string(msg) );
result = true;
}
// read key;
ScriptingIndent( indent + 1, file );
fprintf( file, "var %s;\n", create_string.c_str() );
if( node.keyptr ) {
result = ScriptingDetachClass( indent + 1, file, * node.keyptr, msg ) && result;
}
// read value;
a_string next_name = node_name + "[" + msg + "]";
if( node.def_dims ) {
result = ScriptingDetachClass( indent + 1, file, *node.def_dims, next_name ) && result;
}
ScriptingIndent( indent, file );
fprintf( file, "}\n" );
}
// 如果是 List 容器
else
if( node.define == "List" )
{
ScriptingIndent( indent, file );
fprintf( file, "UInt32 length_%08x = stream.ReadU32();\n", hash );
ScriptingIndent( indent, file );
fprintf( file, "UInt16 verify_%08x = stream.ReadU16();\n", hash );
fprintf( file, "\n" );
ScriptingIndent( indent, file );
fprintf( file, "%s.Clear();\n", node_name.c_str() );
ScriptingIndent( indent, file );
fprintf( file, "for (UInt32 i_%08x = 0; i_%08x < length_%08x; ++i_%08x)\n", hash, hash, hash, hash );
ScriptingIndent( indent, file );
fprintf( file, "{\n" );
// 创建对象
a_string create_string = "var ";
if( node.def_dims ) {
create_string += node.def_dims -> CreateStatement( a_string("ds_data") );
result = true;
}
ScriptingIndent( indent + 1, file );
fprintf( file, "%s;\n", create_string.c_str() );
// 读取
if( node.def_dims ) {
result = ScriptingDetachClass( indent + 1, file, * node.def_dims, a_string("ds_data") ) && result;
}
// 添加到array
a_string add_action = node_name + ".Add( ds_data );";
ScriptingIndent( indent + 1, file );
fprintf( file, "%s\n", add_action.c_str() );
ScriptingIndent( indent, file );
fprintf( file, "}\n" );
}
// 如果是 byte[],则需要手工输入一个length。
else
if( node.define == "byte[]" )
{
// 内存块
text += " = stream.ReadBytes(<input length here>);";
ScriptingIndent( indent, file );
fprintf( file, "%s\n", text.c_str() );
result = true;
}
// 类的类型
else
{
text = text + ".Deserialize(stream);";
ScriptingIndent( indent, file );
fprintf( file, "%s\n", text.c_str() );
result = true;
}
return result;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool unity::tagMember::ScriptingIndent(U32 indent, FILE * file)
{
//TODO Auto-generated method stub
bool result = false;
if( file )
{
result = true;
for( U32 t = 0; t < indent; ++ t ) {
fprintf( file, " " );
}
}
return result;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void unity::tagMember::DebugOut(U32 level, a_string indent, U08 flag)
{
//TODO Auto-generated method stub
a_string buffer;
buffer += indent;
switch( flag )
{
case 0:
buffer += "└─┬ ";
break;
case 1:
buffer += " ├ ";
break;
case 2:
buffer += " └ ";
break;
case 3:
buffer += "└── ";
break;
case 4:
buffer += "├─┬ ";
break;
case 5:
buffer += "│ ├ ";
break;
case 6:
buffer += "│ └ ";
break;
}
size_t total = 0; Ptr value = * this;
do
{
buffer += value -> define;
if( value -> def_dims )
{
buffer += "<";
if( value -> keyptr )
{
buffer += value -> keyptr -> define;
buffer += ", ";
}
++ total;
}
value = value -> def_dims;
} while( value );
for( size_t i = 0; i < total; ++ i ) {
buffer += ">";
}
if( !arr_dims.empty() )
{
for( size_t i = 0; i < arr_dims.size(); ++ i )
{
char msg[32];
sprintf( msg, "%llu", arr_dims[i] );
buffer += "[";
buffer += msg;
buffer += "]";
}
}
buffer += " ";
buffer += name;
buffer += "\n";
printf( buffer.c_str() );
size_t parent_members = 0;
bool is_last = false;
if( parent )
{
parent_members = parent -> member.size();
if( parent_members )
{
is_last = ( this == & parent -> member.back() );
}
}
size_t grand_parent_members = 0;
if( parent && parent -> parent )
{
grand_parent_members = parent -> parent -> member.size();
}
for( tagMember::Array::iterator
it = member.begin(); it != member.end(); ++ it )
{
U32 shift = 0;
a_string sub_indent = indent;
if( grand_parent_members > 1 && parent_members > 1 )
{
sub_indent += "│ ";
}
else
{
sub_indent += " ";
}
if( parent_members > 1 && member.size() > 1 && !is_last )
{
shift = 4;
}
// 如果是第一项
if( it == member.begin() )
{
// 如果有多个子节点
if( member.size() > 1 )
{
it -> DebugOut( level + 1, sub_indent, 0 + shift );
}
// 如果只有一个子节点
else
{
// 子节点没有子节点
if( it -> member.empty() )
{
it -> DebugOut( level + 1, sub_indent, 3 + shift );
}
else
{
it -> DebugOut( level + 1, sub_indent, 0 + shift );
}
}
}
// 如果是最后一项
else
if( it == prev( member.end() ) )
{
// 有子节点
if( !it -> member.empty() )
{
it -> DebugOut( level + 1, sub_indent, 1 + shift );
}
// 如果没有子节点
else
{
it -> DebugOut( level + 1, sub_indent, 2 + shift );
}
}
// 中间项
else
{
it -> DebugOut( level + 1, sub_indent, 1 + shift );
}
}
}
到此,大功告成。