确保 D rawRead()s 是来自文件的大端结构
Making sure D rawRead()s a big endian struct from a file
我正在尝试构建一个简单的 PNG reader,但是由于 macOS 是一个小端系统而 PNG 是一个大端格式,我 运行 变成了一个大的(对我来说,至少,我是 D) 问题的新手。
先来一堆代码:
static enum IHDR_BitDepth: ubyte {
BitDepth1 = 1,
BitDepth2 = 2,
BitDepth4 = 4,
BitDepth8 = 8,
BitDepth16 = 16
}
static enum IHDR_ColorType: ubyte {
Greyscale = 0,
TrueColor = 2,
Indexed = 3,
GreyscaleAlpha = 4,
TrueColorAlpha = 6
}
static enum IHDR_CompressionMethod: ubyte {
Deflate = 0
}
static enum IHDR_FilterMethod: ubyte {
Adaptive = 0
}
static enum IHDR_InterlaceMethod: ubyte {
NoInterlace = 0,
Adam7Interlace = 1
}
struct IHDR {
align(1): // don't pad this struct so .sizeof works properly
uint Width;
uint Height;
IHDR_BitDepth BitDepth;
IHDR_ColorType ColorType;
IHDR_CompressionMethod CompressionMethod;
IHDR_FilterMethod FilterMethod;
IHDR_InterlaceMethod InterlaceMethod;
}
// further down the file
File file = File(fname, "r");
// stuff
PngHeaders.IHDR ihdr;
file.rawRead((&ihdr)[0..1]);
writeln(ihdr);
最后一个 writeln
输出:
IHDR(1380206665, 570490880, cast(IHDR_BitDepth)0, Greyscale, cast(IHDR_CompressionMethod)1, cast(IHDR_FilterMethod)34, cast(IHDR_InterlaceMethod)8)
这显然是错误的。
我发现 a thread from 2003 正在讨论字节序属性,但它尚不存在。
是否有另一种简单的方法让 D 将文件(或至少结构)视为大端?我喜欢从文件中读取整个结构而不是必须自己读取每个值的能力,所以如果有一种方法可以让我继续这样做,我会更喜欢它。
所以我实际上更喜欢逐字节读取文件,因为它们中的许多文件具有可变长度和字节顺序,逐字节读取可以解决这两个问题。 (您还可以使用辅助函数、混入、属性等来简化此过程。)
但另一种选择是保持结构不变,但编写 属性 函数来进行转换。
struct Header {
align(1):
ubyte[4] Width_; // the bytes in the file
@property int Width() { return bigEndianToNative(Width_); }
// ditto for the others
/* snip */
}
如果您愿意,也可以 setter。因此,您仍然可以使用 rawRead 来解决它,但访问属性会为您转换。
这有利有弊,但我想作为替代方案来回答。
我正在尝试构建一个简单的 PNG reader,但是由于 macOS 是一个小端系统而 PNG 是一个大端格式,我 运行 变成了一个大的(对我来说,至少,我是 D) 问题的新手。
先来一堆代码:
static enum IHDR_BitDepth: ubyte {
BitDepth1 = 1,
BitDepth2 = 2,
BitDepth4 = 4,
BitDepth8 = 8,
BitDepth16 = 16
}
static enum IHDR_ColorType: ubyte {
Greyscale = 0,
TrueColor = 2,
Indexed = 3,
GreyscaleAlpha = 4,
TrueColorAlpha = 6
}
static enum IHDR_CompressionMethod: ubyte {
Deflate = 0
}
static enum IHDR_FilterMethod: ubyte {
Adaptive = 0
}
static enum IHDR_InterlaceMethod: ubyte {
NoInterlace = 0,
Adam7Interlace = 1
}
struct IHDR {
align(1): // don't pad this struct so .sizeof works properly
uint Width;
uint Height;
IHDR_BitDepth BitDepth;
IHDR_ColorType ColorType;
IHDR_CompressionMethod CompressionMethod;
IHDR_FilterMethod FilterMethod;
IHDR_InterlaceMethod InterlaceMethod;
}
// further down the file
File file = File(fname, "r");
// stuff
PngHeaders.IHDR ihdr;
file.rawRead((&ihdr)[0..1]);
writeln(ihdr);
最后一个 writeln
输出:
IHDR(1380206665, 570490880, cast(IHDR_BitDepth)0, Greyscale, cast(IHDR_CompressionMethod)1, cast(IHDR_FilterMethod)34, cast(IHDR_InterlaceMethod)8)
这显然是错误的。
我发现 a thread from 2003 正在讨论字节序属性,但它尚不存在。
是否有另一种简单的方法让 D 将文件(或至少结构)视为大端?我喜欢从文件中读取整个结构而不是必须自己读取每个值的能力,所以如果有一种方法可以让我继续这样做,我会更喜欢它。
所以我实际上更喜欢逐字节读取文件,因为它们中的许多文件具有可变长度和字节顺序,逐字节读取可以解决这两个问题。 (您还可以使用辅助函数、混入、属性等来简化此过程。)
但另一种选择是保持结构不变,但编写 属性 函数来进行转换。
struct Header {
align(1):
ubyte[4] Width_; // the bytes in the file
@property int Width() { return bigEndianToNative(Width_); }
// ditto for the others
/* snip */
}
如果您愿意,也可以 setter。因此,您仍然可以使用 rawRead 来解决它,但访问属性会为您转换。
这有利有弊,但我想作为替代方案来回答。