我想将某些信息从已解析的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;
SHORT glygh_data_format;
// some member functions...
};
现在,我想编写一个名为dump_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");
}
我的问题是:
是否有更好的解决方案来实现此目标?我已经写了几N
行代码来定义结构,现在我必须再写N
一行代码到dump_info
。这不酷。我想要的东西是这样的:
foreach field in fields
dump(indent);
dumpLn("<$1 value=\"$2\">", field.name, field.value);
// Fields of different type are dumped in different format!
end
如何明智地完成缩进?我定义了以下宏
#define INDENT(fp, indent) for(size_t i = 0; i < (indent); ++i) fprintf((fp), "\t")
并将此宏附加到每一行...我想知道是否有一种优雅的方式来完成此任务。
以下代码是我的尝试。我将类的字段信息存储到一个Notation
数组中。我假设ULL
(即unsigned long long
)是消耗最大内存(8B)的类型,并且始终从每个字段的指针中获得8B。应该特别注意的一件事是,我应始终确保正确分配了format
in Notation
。例如,如果我想打印一个short
值(我只需要2B),但是却分配format
了一个值("%d"
为我获取4B),我将得到一个错误的答案。
仍然有两个问题困扰着我:
ULL
不同的内存大小。好吧,更新...我添加mask
到Notation
以获得正确的值,即使format
没有正确分配。
请参阅ttf中的OS / 2表。它由近40个字段组成。现在,我写了40行来定义该表,写40行来读取该表,并写40行来转储该表的信息!天啊。也许将来我还要添加其他40行,40行和40行...如果我无法自动执行此任务,请杀死我。
#include <stdio.h>
class X{
public:
char a;
short b;
int c;
double d;
X(char a, short b, int c, double d) : a(a), b(b), c(c), d(d) {}
};
typedef unsigned long long ULL;
#define FIELD(c, x) (((c*)0)->x)
#define OFFSET(c, x) ((size_t)&FIELD(c, x))
#define SIZE(c, x) (sizeof(FIELD(c, x)))
#define MASK(c, x) (((ULL)~0) >> ((sizeof(ULL) - SIZE(c, x)) << 3))
#define NOTATION(c, x, s) { SIZE(c, x), OFFSET(c, x), #x, s, MASK(c, x) }
#define PTR(c, f) ((void*)((size_t)&c + f->offset))
#define VALUE(c, f) (f->mask & *(ULL*)PTR(x, f))
struct Notation{
size_t size;
size_t offset;
const char *name;
const char *format;
ULL mask;
};
Notation X_field[] = {
NOTATION(X, a, "%c"),
NOTATION(X, b, "%d"), // The right 'format' of short should be %hd. I intentionally set it wrong.
NOTATION(X, c, "%d"),
NOTATION(X, d, "%lf")
};
#define PRINT(x, f, s) \
printf("name: %s, size: %u, ptr: %p, value: " s "\n", #f, sizeof(x.f), &x.f, x.f)
int main(){
X x('z', 3, 2, 1.5);
printf("--------------------MANUAL--------------------\n");
PRINT(x, a, "%c");
PRINT(x, b, "%hd");
PRINT(x, c, "%d");
PRINT(x, d, "%lf");
printf("--------------------MASK--------------------\n");
printf("0x%016hhx, %hhu\n", (char)~0, (char)~0);
printf("0x%016hx, %hu\n", (short)~0, (short)~0);
printf("0x%016x, %u\n", (int)~0, (int)~0);
printf("0x%016llx, %llu\n", (ULL)~0, (ULL)~0);
printf("--------------------FIELD--------------------\n");
Notation *field = NULL;
int i = 0;
for(i = 0, field = X_field; i < 4; ++i, ++field){
printf("size: %u, offset: %u, name: %s, format: %s, mask: 0x%016llx\n",
field->size, field->offset, field->name, field->format, field->mask);
}
printf("--------------------AUTO--------------------\n");
for(i = 0, field = X_field; i < 4; ++i, ++field){
printf("name: %s, size: %u, ptr: %p, value: ", field->name, field->size, PTR(x, field));
printf(field->format, VALUE(x, field));
printf("\n");
}
return 0;
}
输出:
--------------------MANUAL--------------------
name: a, size: 1, ptr: 0x22ac18, value: z
name: b, size: 2, ptr: 0x22ac1a, value: 3
name: c, size: 4, ptr: 0x22ac1c, value: 2
name: d, size: 8, ptr: 0x22ac20, value: 1.500000
--------------------MASK--------------------
0x00000000000000ff, 255
0x000000000000ffff, 65535
0x00000000ffffffff, 4294967295
0xffffffffffffffff, 18446744073709551615
--------------------FIELD--------------------
size: 1, offset: 0, name: a, format: %c, mask: 0x00000000000000ff
size: 2, offset: 2, name: b, format: %d, mask: 0x000000000000ffff
size: 4, offset: 4, name: c, format: %d, mask: 0x00000000ffffffff
size: 8, offset: 8, name: d, format: %lf, mask: 0xffffffffffffffff
--------------------AUTO--------------------
name: a, size: 1, ptr: 0x22ac18, value: z
name: b, size: 2, ptr: 0x22ac1a, value: 3
name: c, size: 4, ptr: 0x22ac1c, value: 2
name: d, size: 8, ptr: 0x22ac20, value: 1.500000
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句