这两天在看CEGUI,其中有个String类是32字节栈加速字符串实现,很多引擎里也都是这么实现的,应该算比较统一了。起初我对这份实现还是很敬重的,并没有要换掉的意思。后来再细看的时候发现问题还是比较大的。
该类的功能并没有比std的string实现有明显的扩充,甚至还想做到与std::string的兼容,当然这个并不算缺点。
String本身是兼容UTF32(当然作者的实现是非标准的UTF32)和UTF8的,其中UTF8是在UTF32格式存贮的String中再建了一个临时缓冲区。如果加一个脏标记就可以避免每次build_utf8_buff的麻烦了。通过建立冗余的缓冲区来保持和标准string::c_str()的兼容显得稍微有点不值。
String内部每个codepoint是用一个utf32(unsigned int)存的,其实两个字节已经足够了,win系统内部就是采用两个字节的,虽然这无法显示地球上所有的语言。有点浪费。
最致命的一点是代码中将ASCII的char*和UTF8编码的utf8*(unsigned char*)混用,甚至我无法正确的通过cout打印出String的值,要保证代码中没有ASCII和UTF8编码的混淆是很难的,我对此持有怀疑。
再三考虑后,决定换掉CEGUI:: String。自定义字符串无疑会加重和系统其他部分交互时的代价,再者性能也不一定会比std的string好到哪去。采用ASCII的std::string是没有任何问题的,而且在做字体文件的编码映射时会比较集中,但要在游戏中显示火星文貌似有点难度。
最终,采用std::wstring,内部是以wchar_t存贮的Unicode 16bit格式,和Windows一致。值得庆幸的是Win系统对很多API都提供了普通字符和宽字符两个版本,但并非所有,所以在使用的时候还是需要适当的转一下的。
结论:CEGUI自带的String不好用,换成std:wstring标准字符串是个不错的选择。
用了两年多的CEGUI,觉得将CEGUI自带的String换成std::wstring确实是非常明智的选择。避免编码混淆,避免乱码,方便外部使用交互。暂不理解作者为什么要采用DIY String?
评论