August 31, 2015
On Saturday, 29 August 2015 at 12:56:08 UTC, cym13 wrote:
> Hi,
>
> Let's say I have a simple binary file whose structure is well-known. Here is
> an example which stores points:
>
> struct Point {
>     long x;
>     long y;
>     long z;
> }
>
> struct BinFile {
>     uint    magicNumber;  // Some identifier
>     ulong   pointsNumber;
>     Point[] points;       // Array of pointsNumber points.
> }
>
> What is the best way to read some file and fill a structure with it? Would
> reading the file into a void[] and then casting it to the struct work with
> things like internal struct padding?

struct Point {
     long x;
     long y;
     long z;
}

struct BinFile {
    uint    magicNumber;  // Some identifier
    ulong   pointsNumber;
    Point[] points;       // Array of pointsNumber points.

    this(ubyte [] buf)
    {
        auto f = cast(BinFile *)buf.ptr;
        this = cast(BinFile)*f;
        this.points = (cast(Point*)&f.points)[0..cast(uint)this.pointsNumber];
    }
}


August 31, 2015
On Monday, 31 August 2015 at 01:01:32 UTC, mzfhhhh wrote:
> On Saturday, 29 August 2015 at 12:56:08 UTC, cym13 wrote:
>> Hi,
>>
>> Let's say I have a simple binary file whose structure is well-known. Here is
>> an example which stores points:
>>
>> struct Point {
>>     long x;
>>     long y;
>>     long z;
>> }
>>
>> struct BinFile {
>>     uint    magicNumber;  // Some identifier
>>     ulong   pointsNumber;
>>     Point[] points;       // Array of pointsNumber points.
>> }
>>
>> What is the best way to read some file and fill a structure with it? Would
>> reading the file into a void[] and then casting it to the struct work with
>> things like internal struct padding?
>
> struct Point {
>      long x;
>      long y;
>      long z;
> }
>
> struct BinFile {
>     uint    magicNumber;  // Some identifier
>     ulong   pointsNumber;
>     Point[] points;       // Array of pointsNumber points.
>
>     this(ubyte [] buf)
>     {
>         auto f = cast(BinFile *)buf.ptr;
>         this = cast(BinFile)*f;
>         this.points = (cast(Point*)&f.points)[0..cast(uint)this.pointsNumber];
>     }
> }

Thank you, this is what I was looking for :) I had to combine it with align(1) though. Complete working example:

import std.conv;
import std.stdio;

align(1)
struct Point {
     long x;
     long y;
     long z;
}

struct BinFile {
    align(1):
        uint    magicNumber;  // Some identifier
        ulong   pointsNumber;
        Point[] points;       // Array of pointsNumber points.

    this(ubyte [] buf)
    {
        auto f = cast(BinFile *)buf.ptr;
        this = cast(BinFile)*f;
        this.points = (cast(Point*)&f.points)[0..pointsNumber];
    }
}

void main(string[] args) {
    /*
    auto f = File(args[1], "rb");
    ubyte[] buffer = [];
    foreach (chunk ; f.byChunk(4096))
        buffer ~= chunk;
    */

    ubyte[] buffer = [
        0xef, 0xbe, 0xad, 0xde,                          // magicNumber
        0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // pointsNumber
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // points[0].x
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // points[0].y
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // points[0].z
        0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // points[1].x
        0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // points[1].y
        0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // points[1].z
    ];

    auto bf = BinFile(buffer);
    writefln("Magic number: %x", bf.magicNumber);
    writeln("Number of points: ", bf.pointsNumber);
    writeln("Points:");
    foreach (p ; bf.points)
        writeln("  ", p);
}

Thanks all!
1 2
Next ›   Last »