What is the D way to map a binary file to a structure?

cym13 via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Aug 31 05:35:47 PDT 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!


More information about the Digitalmars-d-learn mailing list