New to D: parse a binary file

spir denis.spir at gmail.com
Sat Feb 5 12:10:42 PST 2011


On 02/05/2011 06:26 PM, scottrick wrote:
> Hi,
>
> I am new to D.  I am trying to write a binary file parser for a
> project of mine and I thought it would be fun to try and learn a new
> language at the same time.  So I chose D!  :D  I have been
> struggling however and have not been able to find very many good
> examples, so I am posting this message.
>
> I think I'm supposed to be using std.stdio, but I'm not 100% sure.
> Could somebody post a short example of how to parse a couple of
> characters and ints or whatever from a file?  Or how to read, say,
> the next however many bytes into a struct?
>
> Also, looking at the documentation, I am confused by this method
> signature:
>
> T[] rawRead(T)(T[] buffer);
>
> I understand that T is generic type, but I am not sure of the
> meaning of the (T) after the method name.
>
> Thanks,

Below a pair of examples that should make all this clearer: a templated 
hand-written naive map func, and a template struct type (would be nearly the 
same for a class). Just run it. Additional explanations on demand.

import File=std.file;
import std.array;

Out[] map (In, Out) (In[] source, Out delegate (In) f) {
     // (0)
     Out[] target;
     foreach (element; source)
         target ~= f(element);
     return target;
}

struct StoreStack (T) {
     T[] items;
     string logFileName;
     this (string logFileName, T[] items=[]) {
         this.items = items;
         this.logFileName = logFileName;
         // create/reset log file
         File.write(logFileName, "");
     }
     string toString () {
         static form = "StoreStack(\"%s\", %s)";
         return format(form, this.logFileName, this.items);
     }

     void put (T item) {
         this.items ~= item;
         string message = format("put item: %s\n", item);
         File.append(logFileName, message);
     }
     T take () {
         T item = this.items[$-1];
         this.items = this.items[0..$-1];
         string message = format("took item: %s\n", item);
         File.append(logFileName, message);
         return item;
     }
}

unittest {
     // map
     string hex (uint i) { return format("0x%03X", i); }
     uint[] decs = [1, 3, 9, 27, 81, 243, 729];
     auto hexes = map!(uint,string)(decs, &hex);
     // auto hexes = map(decs, &hex);  // (1)
     writefln ("decs: %s\n-->\nhexes: %s", decs, hexes);
     writeln();

     // StoreStack
     auto store = StoreStack!(int)("test_log");
     // auto store = StoreStack!int("test_log");  // (2)
     store.put(3); store.put(2); store.put(3);
     auto i = store.take();
     writefln("store: %s", store);
     writefln("log:\n%s", File.readText("test_log"));
}
void main() {}

(0) The func must be declared as delegate (instead of simple func pointer) 
because: the actual func hex beeing defined in a block, the compiler turns it 
into a delegate. Detail.
(1) Here, the compiler is able to infer the template parameters (types): no 
need to specify them.
(2) When there is a single template parameter, the syntax allows omitting () 
around it.

Denis
-- 
_________________
vita es estrany
spir.wikidot.com



More information about the Digitalmars-d-learn mailing list