I'm trying to develop an emulator, and I'm struggling with finding a performant way to read the file and make an array with its data. The way I'm doing it now feels inefficient; it consists of me using the readToEndAlloc function to convert the data to an array of u8's, then combining the u8's into u16's in a BoundedArray by bitshifting each array[i] value left by 8 and logical OR'ing it with array[i + 1].
#How to read a binary file by `u16`'s instead of `u8`'s?
1 messages · Page 1 of 1 (latest)
std.mem.bytesAsSlice(u16, buffer)
read the file then run it through this
Thank you! This helps, but it seems to change the endianness from big-endian to little-endian. Is there a way of making it stay big-endian?
if you have an io.Reader, you can call readInt(u16, .little) on it.
with .big for big endian
Thank you both! I think I landed on a possible solution. Does this seem efficient?
const array = try rom.readToEndAlloc(allocator, rom_size);
const slice = std.mem.bytesAsSlice(u16, array);
for (0..slice.len) |i| {
slice[i] = std.mem.toNative(u16, slice[i], .big);
}
that seems fine. not sure about mem.toNative just cause i haven't used it before. i might write it like this
const slice = try allocator.alloc(u16, rom_size/2);
for (0..slice.len) |i| {
// if you're on a little platform
slice[i] = @byteSwap(try rom.readInt(u16, .little));
// if you're not sure whether you're on big or little
// slice[i] = std.mem.nativeToBig(u16, try rom.readInt(u16, .little));
}
Thats what toNative would do
Fwiw since you control how its allocated, youd be able to ensure that its 2 byte aligned
That way the cpu wont need to load/store one byte at a time
Although ofc idk what the opimized code gen would actually be like
And idk if itd make a real difference
Woah, thanks! I didn't realize that the readInt function would work with iteration! I was struggling with using it, but now I kinda understand how it works.
After doing more research and finding out just how rare big-endianness is, I decided to settle on this approach, which just assumes the host's architecture is little-endian:
const slice = try allocator.alloc(u16, rom_size / 2);
for (0..slice.len) |i| {
slice[i] = try rom.reader().readInt(u16, .big);
}