C++ 如何以优雅的方式转储XML?
我想将解析的ttf文件中的一些信息转储到XML文件中。ttf中有几个表格,例如cmap、head、hhea。我已经定义了这些表的结构,例如:C++ 如何以优雅的方式转储XML?,c++,c,xml,indentation,C++,C,Xml,Indentation,我想将解析的ttf文件中的一些信息转储到XML文件中。ttf中有几个表格,例如cmap、head、hhea。我已经定义了这些表的结构,例如: class Font_Header{ public: FIXED table_version_number; FIXED font_revision; ULONG checksum_adjustment; // some other field... SHORT index_to_loc_format;
class Font_Header{
public:
FIXED table_version_number;
FIXED font_revision;
ULONG checksum_adjustment;
// some other field...
SHORT index_to_loc_format;
SHORT glygh_data_format;
// some member functions...
};
现在我想写一个名为dump\u info
的函数来转储这个结构的内存布局
void Font_Header::dump_info(FILE *fp, size_t indent){
INDENT(fp, indent); fprintf(fp, "<head>\n");
++indent;
INDENT(fp, indent); fprintf(fp, "<tableVersion value=\"0x%08x\"/>\n", table_version_number);
// some other lines...
INDENT(fp, indent); fprintf(fp, "<glyphDataFormat value=\"%d\"/>\n", glygh_data_format);
--indent;
INDENT(fp, indent); fprintf(fp, "</head>\n");
}
#define INDENT(fp, indent) for(size_t i = 0; i < (indent); ++i) fprintf((fp), "\t")
#为(尺寸i=0;i<(缩进);+i)fprintf((fp),“\t”)定义缩进(fp,缩进)
并将此宏附加到每一行。。。我想知道是否有一种优雅的方式来完成这项任务 以下代码是我的尝试。我将类的字段信息存储到
表示法数组中。我假设ULL
,即unsigned long long
,是消耗最大内存(8B)的类型,并且总是从每个字段的指针获取8B。需要特别注意的一点是,我应该始终确保在符号中正确分配了格式
。例如,如果我想打印一个short
值(我只需要2B),但我用%d”
分配了format
(为我取4B),我会得到一个错误的答案
两个问题仍然困扰着我:
该方法不可移植。不同的平台可能会为ULL
分配不同大小的内存
由于我总是从内存中获得8B,所以撇开效率不谈,这可能会导致读取内存冲突
嗯,更新。。。我将掩码
添加到符号
中,以获得正确的值,即使格式
分配不正确
见ttf中的表格。它由近40个字段组成。现在我已经写了40行定义表,40行读取表,40行转储表的信息!哦,天哪。也许将来我还要再加上40行,40行,40行。。。如果我不能自动完成这项任务,就杀了我
若你们只是在做一些案例,那个么就用手去做,并在重复中生活
如果您只是为简单结构中的<强>大量/强>这样做,我会考虑一个简单的解析器,将给定的头文件中的结构转换为倾倒结构的源。
void Font_Header::dump_info(FILE *fp, size_t indent){
INDENT(fp, indent); fprintf(fp, "<head>\n");
++indent;
INDENT(fp, indent); fprintf(fp, "<tableVersion value=\"0x%08x\"/>\n", table_version_number);
// some other lines...
INDENT(fp, indent); fprintf(fp, "<glyphDataFormat value=\"%d\"/>\n", glygh_data_format);
--indent;
INDENT(fp, indent); fprintf(fp, "</head>\n");
}
如果我希望能够更多地定制XML输出(这似乎是可能的),我会从一些元数据文件生成struct和struct printing函数
如果您不只是针对简单结构执行此操作,那么我会将我的数据部分包装在一个简单结构中,并按照上面的方法执行
例如,您可以使用如下内容:(我可能会使用XML或JSON元数据,因为它们更容易解析——这取决于您希望用什么语言编写生成器)
FontHeaderData.crazymeta
struct_name : Font_Header_data
dumper_name : Font_Header_data_to_xml
xml_root_node : head
FIXED table_version_number tableVersionNumber 0x%08x
...
那么您的主文件将如下所示:
Font\u Header.h
#include "Font_Header_data.h"
#include "Font_Header_data_to_xml.h"
class Font_Header {
Font_Header_data data;
void dump_info(FILE *fp, size_t indent){
Font_Header_data_to_xml(fp,indent);
}
};
其中,Font\u Header\u data.h
,Font\u Header\u data\u to\u xml.h
和Font\u Header\u data\u to\u xml.c
由解析器生成
请记住,要将生成的文件与正确的依赖项挂钩到构建过程中,以便在正确的时间重建它们
“乐趣”部分是将元数据写入.c
和.h
转换器
过去我做过类似的事情,是为了保持大量的MySQL表与它们的C++对应的同步,并且生成了正确的C API <代码> INSERT//COM>/<代码> UPDATE < /Cord>命令,以在两者之间进行桥接。虽然从一开始就做好这件事需要做很多工作,但它确实为我节省了很多小时以后的痛苦
您考虑过boost::property_树吗?看看这个问题,看看。
struct_name : Font_Header_data
dumper_name : Font_Header_data_to_xml
xml_root_node : head
FIXED table_version_number tableVersionNumber 0x%08x
...
#include "Font_Header_data.h"
#include "Font_Header_data_to_xml.h"
class Font_Header {
Font_Header_data data;
void dump_info(FILE *fp, size_t indent){
Font_Header_data_to_xml(fp,indent);
}
};