www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - New to D: parse a binary file

reply scottrick <scottrick49 hotmail.com> writes:
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,
Feb 05 2011
parent reply spir <denis.spir gmail.com> writes:
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
Feb 05 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
spir:

 Out[] map (In, Out) (In[] source, Out delegate (In) f) {
      // (0)

      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);

 (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.

See also: void foo(In, Out)(Out function(In) f) {} void main() { static int bar(int i) { return 0; } foo(&bar); } Bye, bearophile
Feb 05 2011
prev sibling parent reply scottrick <scottrick49 hotmail.com> writes:
Thanks, your post was very helpful.  Two more questions (probably
related):

Where is the function 'format' defined?  Also, what is that 'unittest'
block?  It compiles fine as is, but if I refer to format outside of
unittest, it will not compile.  Also, if I compile and run your
example, it doesn't do anything, since main() is empty?

Thanks again,
Feb 06 2011
parent bearophile <bearophileHUGS lycos.com> writes:
scottrick:

 Where is the function 'format' defined?

You need to add at the top of the module: import std.conv: format; Or: import std.conv;
 Also, what is that 'unittest' block?  It compiles fine as is, but if I refer
to format outside of
 unittest, it will not compile.  Also, if I compile and run your
 example, it doesn't do anything, since main() is empty?

It's an block of unit tests :-) Currently in your program they are not even compiled, so the format is not used. To run the unit tests you need to compile with -unittest compiler switch (with DMD). See also: http://www.digitalmars.com/d/2.0/unittest.html Bye, bearophile
Feb 06 2011