digitalmars.D.learn - New to D: parse a binary file
- scottrick <scottrick49 hotmail.com> Feb 05 2011
- spir <denis.spir gmail.com> Feb 05 2011
- bearophile <bearophileHUGS lycos.com> Feb 05 2011
- scottrick <scottrick49 hotmail.com> Feb 06 2011
- bearophile <bearophileHUGS lycos.com> Feb 06 2011
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
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
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
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
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









bearophile <bearophileHUGS lycos.com> 