确保 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 将文件(或至少结构)视为大端?我喜欢从文件中读取整个结构而不是必须自己读取每个值的能力,所以如果有一种方法可以让我继续这样做,我会更喜欢它。

使用bigEndianToNative i.e. my png file format module.

所以我实际上更喜欢逐字节读取文件,因为它们中的许多文件具有可变长度和字节顺序,逐字节读取可以解决这两个问题。 (您还可以使用辅助函数、混入、属性等来简化此过程。)

但另一种选择是保持结构不变,但编写 属性 函数来进行转换。

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 来解决它,但访问属性会为您转换。

这有利有弊,但我想作为替代方案来回答。