digitalmars.D.learn - New to D: parse a binary file
- scottrick (16/16) Feb 05 2011 Hi,
- spir (68/84) Feb 05 2011 Below a pair of examples that should make all this clearer: a templated
- bearophile (11/19) Feb 05 2011 ...
- scottrick (7/7) Feb 06 2011 Thanks, your post was very helpful. Two more questions (probably
- bearophile (10/14) Feb 06 2011 You need to add at the top of the module:
- Jesse Phillips (5/9) Feb 06 2011 That T is defining the symbol to represent the generic type. It can have...
- Mafi (17/26) Feb 06 2011 I think you meant
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
scottrick Wrote: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.That T is defining the symbol to represent the generic type. It can have more than one and D provides other things like aliases... Another way to write that function (I may get something wrong here but give it a shot) is: template(T) { T[] rawRead(T[] buffer); }
Feb 06 2011
Am 06.02.2011 19:38, schrieb Jesse Phillips:scottrick Wrote:I think you meant template(T) rawRead{ T[] rawRead(T[] buffer); } 'template' defines a namespace which is normally accessed like templ!(parameters).member; templ!(parameters).memberfunc(parameters); Because the template and it's member are called identically this member is accessed autoatically (the eponymous-trick). If it's a function you call it like that: templfunc!(compiletimeparam)(param); The compile time parameters can left out, if these can be derived from the normal parameters' type. templfun(param); Voilla! You have a completely transparent templated func. MafiT[] 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.That T is defining the symbol to represent the generic type. It can have more than one and D provides other things like aliases... Another way to write that function (I may get something wrong here but give it a shot) is: template(T) { T[] rawRead(T[] buffer); }
Feb 06 2011