function is similar to Protobuf
首先这不能算作严格意义上的帮助文档,本来规划中的还有很多东西要写,譬如,我虽然已经为每个字段都增加了repeated标识,来标识该字段是否是可重复的,但该标识始终为真,解析配置还没有增加相关逻辑,既然是向Protobuf看齐,又怎么能少的了optional标识,如果是只考虑实现的话,像repeated那样增加字段标识,序列化时如果是optional字段且值为初始值则置2byte内存为0,其实这个值也是标识重复字段重复次数的(关于序列化及反序列化实现方法后面会提到),自然,反序列化的时候,先读出2byte发现为0就知道没有写内容,跳过该字段的反序列化操作就好,一个完备程序应该是经得大量测试的,现在我已经没有足够的时间来做这些工作啦,其实原本设想的写完之后还想和Protobuf比较一下效率的,看看到底会差多大,但是,一切的一切都暂时没有时间啦,再过几天就要开始找新的工作啦,换好新工作的初期也未必有时间完善这些,所以这里备注下。
关于主要的使用说明,相信main.cpp里面的内容已经足以说明所有简单的接口
没有cpp文件,使程序尽量简单,方便调用,使用的时候仅需要包含Director.h文件即可
涉及的设计模式有:单例,组合,原型,迭代器,可能还有我不知道的,呵呵
uml类图已经提供,并置于uml目录下,并提供了可供PowerDesigner16编辑的文件
程序中大量使用类模板及模板特例化,请阅读源代码的时候发散思维
依然尽量使用C++0x提供的新语法,显示指定命名空间来保证不污染调用它们的程序
程序提供的测试代码经valgrind测试无内存泄漏,当然我在测试的时候失败等等也都考虑进去了
程序并没有统一大小端,所以在实际应用中请提前考虑这一点,当然实际应用并不是我写这的目的
Director存在的意义就是总要有一个类来加载配置,创建原型,并管理原型(用户来克隆)
Component算是一个非严格意义上的接口类,提供的仅是对成员的获取设置等基本操作,Component实现了单向链表,所以该类还额外提供了获取链表长度,只是我起的名字是times,意为重复次数,Component类提供递归析构,空的add实现(组合中叶节点调用不至于出错)
Proto模板类,组合中的叶子节点,正是协议中所支持的那些类型的集合,譬如,Proto,Proto<int32_t>,Proto等等,它所持有的那个唯一的成员变量就是它所持有的数据,实现了克隆自身用于辅佐用户从Director克隆原型
ProtoIterator模板类,专用于Proto的迭代器,重载operator来向标准库致敬,直接取到Proto持有的数据
Prototype原型,组合中的组合节点,实现add操作,实现克隆自身,增加扩展函数(用于增加新的重复字段),提供getValue方法,在是Proto时直接调用迭代返回持有数据,而在是Prototype的时候返回Prototype指针(这种区别对待采用模板特例化实现),提供addValue方法,当是Proto将第二个行参设进新增的Proto,返回值无用,而在是Prototype的时候,第二个行参形同虚设,返回值则是新创建的原型,你可以放心的向里面设置数据
PrototypeIterator专用于Prototype的迭代器,重载operator来向标准库致敬,返回Prototype指针
Iterator迭代器基类,实现迭代
Utils提供一些静态方法
上面都没有提到序列化及反序列化相关,这个我在这里提一下,关于相关的函数我就不一一说明了,其实也是向Protobuf致敬,因为名称一样,当克隆一个原型,设置内容,甚至重复,甚至该原型中存在原型(自定义消息),序列化步骤如下,首先我会遍历原型中所有Component,如果是repeated或optional字段,总要写入2byte用以标识重复次数,接下来就是序列化内容,因为Component自成链表,依次序列化,特殊的string我会额外在序列话之前增加4byte字符串长度,主要是怕65535不够用啊,再一个特殊就是Prototype啦,这自然就是递归啦,你可以单步调试测试代码逻辑,这样会对这有更深的理解,自然反序列化一样道理,所以这里依赖了一个东西,就是相同map的相同机器与不同机器里面元素顺序都相同