changeset 2:78eb491bd642

mergetag: partially redesigned dataset and text reader classes. Changed text format. committer: Diggory Hardy <diggory.hardy@gmail.com>
author Diggory Hardy <diggory.hardy@gmail.com>
date Sat, 03 Nov 2007 15:15:43 +0000
parents 18491334a525
children 485c98ecbd91
files mde/input/config.d mde/input/core.d mde/input/eventstream.d mde/input/input.d mde/mde.d mde/mergetag/dataset.d mde/mergetag/doc/file-format-text.txt mde/mergetag/read.d mde/test.d mde/text/util.d test.mtt
diffstat 11 files changed, 261 insertions(+), 324 deletions(-) [+]
line wrap: on
line diff
--- a/mde/input/config.d	Tue Oct 30 17:08:12 2007 +0000
+++ b/mde/input/config.d	Sat Nov 03 15:15:43 2007 +0000
@@ -1,7 +1,9 @@
 /// This module contains a class for holding configs and handles saving, loading and editing.
 module mde.input.config;
+
+// package imports
 import mde.input.core;
-/+
+
 /** Struct to hold the configuration for the input system. Thus loading and switching between
  *  multiple configurations should be easy.
  *
@@ -67,4 +69,3 @@
     outQueue[uint] axis;    /// ditto
     outQueue[uint] mouse;    /// ditto
 }
-+/
\ No newline at end of file
--- a/mde/input/core.d	Tue Oct 30 17:08:12 2007 +0000
+++ b/mde/input/core.d	Sat Nov 03 15:15:43 2007 +0000
@@ -1,6 +1,6 @@
 /// This module contains the core (i.e. common part) of the input system.
 module mde.input.core;
-/+
+
 alias Exception InputException;	// this can be expanded to a custom class if needed
 typedef uint index_t;
 struct RelPair {
@@ -20,13 +20,13 @@
     private outQueue _q;	// the queue, stored by reference to the original
     private uint p = 0;		// current read position (start at beginning)
     
-    static readOutQueue (outQueue q) {	/// Static constructor
+    static readOutQueue opCall (outQueue q) {	/// Static constructor
         readOutQueue ret;
         ret._q = q;
         return ret;
     }
     uint next () {		/// Get the next element. Throws an exception if there isn't another.
-        if (p >= _q.length())
+        if (p >= _q.length)
             throw new InputException ("Input: Invalid configuration: incomplete config stack");
         uint ret = _q[p];
         ++p;
@@ -57,4 +57,3 @@
 uint mouse_x, mouse_y;			/// Current screen coords of the mouse
 // FIXME: these need to be reset after every access:
 RelPair[index_t] axis_rel_tbl;	/// Table of relative mouse / joystick ball motions
-+/
\ No newline at end of file
--- a/mde/input/eventstream.d	Tue Oct 30 17:08:12 2007 +0000
+++ b/mde/input/eventstream.d	Sat Nov 03 15:15:43 2007 +0000
@@ -8,8 +8,10 @@
  *	To control which adjusters get called and pass parameters, a stack is used.
  */
 module mde.input.eventstream;
+
+// package imports
 import mde.input.core;
-/+
+
 /// Module constructor fills es_*_fcts tables and rehashes them.
 static this () {
 	es_b_fcts[ES_B_OUT] = &es_b_out;
@@ -21,9 +23,9 @@
 }
 
 /// These aliases are for pointers to the event functions.
-alias void function (bool, out_stack) ES_B_Func;
-alias void function (short, out_stack) ES_A_Func;			/// ditto
-alias void function (short, short, out_stack) ES_M_Func;	/// ditto
+alias void function (bool, readOutQueue) ES_B_Func;
+alias void function (short, readOutQueue) ES_A_Func;			/// ditto
+alias void function (short, short, readOutQueue) ES_M_Func;	/// ditto
 
 /// These are the tables for looking up which event function to call.
 static ES_B_Func[uint] es_b_fcts;
@@ -38,39 +40,39 @@
 }
 
 /// Functions to pass an event to the appropriate event function
-void bEventOut (bool b, out_stack s)
+void bEventOut (bool b, readOutQueue s)
 {
-	ES_B_Func* func = (s.pop in es_b_fcts);
+	ES_B_Func* func = (s.next() in es_b_fcts);
 	if (func != null) (*func)(b,s);
 	else throw new InputException ("Input: Invalid configuration: bad event function code");
 }
-void aEventOut (short x, out_stack s)	/// ditto
+void aEventOut (short x, readOutQueue s)	/// ditto
 {
-	ES_A_Func* func = (s.pop in es_a_fcts);
+	ES_A_Func* func = (s.next() in es_a_fcts);
 	if (func != null) (*func)(x,s);
 	else throw new InputException ("Input: Invalid configuration: bad event function code");
 }
-void mEventOut (short x, short y, out_stack s)	/// ditto
+void mEventOut (short x, short y, readOutQueue s)	/// ditto
 {
-	ES_M_Func* func = (s.pop in es_m_fcts);
+	ES_M_Func* func = (s.next() in es_m_fcts);
 	if (func != null) (*func)(x,y,s);
 	else throw new InputException ("Input: Invalid configuration: bad event function code");
 }
 
 /// Simple output function
-void es_b_out (bool b, out_stack s) {
-	b_tbl[cast(index_t) s.pop] = b;
+void es_b_out (bool b, readOutQueue s) {
+	b_tbl[cast(index_t) s.next()] = b;
 }
 /// Adjuster to check modifier keys
-void es_b_modifier (bool b, out_stack s);
+void es_b_modifier (bool b, readOutQueue s);
 
 /** Simple output function
 
 Adds 1-2 items on the stack.
 */
-void es_a_out (short x, out_stack s) {
+void es_a_out (short x, readOutQueue s) {
 	real y = x;
-	uint conf = s.pop;
+	uint conf = s.next();
         enum : uint {
             HALF_RANGE	= 0x8000_0000u,
             SENSITIVITY	= 0x0080_0000u,
@@ -79,15 +81,14 @@
 	if (conf & HALF_RANGE) y = (y + 32767.0) * 1.5259254737998596e-05;	// range  0.0 - 1.0
 	else y *= 3.0518509475997192e-05;					// range -1.0 - 1.0
 	real a;
-	if (conf & SENSITIVITY) a = s.pop;
+	if (conf & SENSITIVITY) a = s.next();
         /+ When a global sensitivity is available (possibly only use if it's enabled)...
         else a = axis.sensitivity;
 	y = sign(y) * pow(abs(y), a);		// sensitivity adjustment by a +/
-	axis_tbl[cast(index_t) s.pop] = y;
+	axis_tbl[cast(index_t) s.next()] = y;
 }
 
 /// Simple output function
-void es_m_out (short x, short y, out_stack s) {
-	axis_rel_tbl[cast(index_t) s.pop] = RelPair(x,y);
+void es_m_out (short x, short y, readOutQueue s) {
+	axis_rel_tbl[cast(index_t) s.next()] = RelPair(x,y);
 }
-+/
\ No newline at end of file
--- a/mde/input/input.d	Tue Oct 30 17:08:12 2007 +0000
+++ b/mde/input/input.d	Sat Nov 03 15:15:43 2007 +0000
@@ -2,11 +2,15 @@
  *	input package imported from outside this package.
  */
 module mde.input.input;
-/+import derelict.sdl.events;
+
+// package imports
 import mde.input.core;
 import mde.input.config;
 import mde.input.eventstream;
 
+// sdl imports
+import derelict.sdl.events;
+
 /// Get key status at this ID
 bool button (uint id) {
 	return b_tbl[cast(index_t) id];
@@ -55,4 +59,3 @@
  *	Other types of event functions may be added.
  */
 void SDLEvent (SDL_Event event);
-+/
\ No newline at end of file
--- a/mde/mde.d	Tue Oct 30 17:08:12 2007 +0000
+++ b/mde/mde.d	Sat Nov 03 15:15:43 2007 +0000
@@ -11,7 +11,7 @@
 import mde.init;
 import test = mde.test;
 
-//import mde.input.input;
+import mde.input.input;
 
 import mde.mergetag.read;
 
@@ -22,14 +22,14 @@
     Reader MTread;
     try {
         MTread = new Reader ("test.mtt", null, true);
-        static DataSection dataPrinter (ID) {	return new test.DataPrinter;	}
-        MTread.dataSecCreator = &dataPrinter;
+        /+static DataSection dataPrinter (ID) {	return new test.DataPrinter;	}
+        MTread.dataSecCreator = &dataPrinter;+/
         MTread.read();
     } catch (Exception e) {
         Stdout (e.msg).newline;
     }
-    //Stdout ("Data read from file:").newline;
-    //test.printDataSet (MTread.dataset);
+    Stdout ("Data read from file:").newline;
+    test.printDataSet (MTread.dataset);
     return 0;
     
     // cleanup handled by init's DTOR
--- a/mde/mergetag/dataset.d	Tue Oct 30 17:08:12 2007 +0000
+++ b/mde/mergetag/dataset.d	Sat Nov 03 15:15:43 2007 +0000
@@ -2,9 +2,13 @@
 module mde.mergetag.dataset;
 
 // package imports
-import mde.mergetag.parse;
 import mde.mergetag.exception;
 
+// other mde imports
+import mde.text.util;
+import mde.text.parse;
+import mde.text.exception : TextParseException;
+
 // tango imports
 import Util = tango.text.Util;
 import tango.util.log.Log : Log, Logger;
@@ -35,6 +39,18 @@
     logger = Log.getLogger ("mde.mergetag.dataset");
 }
 
+struct TextTag {
+    TextTag opCall (char[] _tp, ID _id, char[] _dt) {
+        TextTag ret;
+        ret.tp = _tp;
+        ret.id = _id;
+        ret.dt = _dt;
+        return ret;
+    }
+    char[] tp, dt;
+    ID id;
+}
+
 /**************************************************************************************************
  * Data class; contains a DataSection class instance for each loaded section of a file.
  *
@@ -80,8 +96,7 @@
  * Another idea for a DataSection class:
  * Use a void*[ID] variable to store all data (may also need a type var for each item).
  * addTag should call a templated function which calls parse then casts to a void* and stores the data.
- * Use a templated get(T)(ID) method which checks the type and casts to T. Small issue with this: storing
- * data in the file with an incorrect type could cause a lot of errors to be thrown in other code.
+ * Use a templated get(T)(ID) method which checks the type and casts to T.
  */
 interface DataSection
 {
@@ -89,7 +104,7 @@
      *
      * Should throw an MTUnknownTypeException for unsupported types, after logging to logger.
      */
-    void addTag (char[],ID,char[]);
+    void addTag (TypeInfo,ID,char[]);
     //void writeAll (Print!(char));	/// TBD
 }
 
@@ -99,261 +114,137 @@
  * Supports all the basic types currently supported and array versions of
  * each (except no arrays of binary or string types; these are already arrays).
  */
+/* Due to a failure to use generic programming techniques for most of this (maybe because it's not
+ * possible or maybe just because I don't know how to use templates properly) a lot of this code is
+ * really horrible and has to refer to EVERY data member.
+ * Be really careful if you add any items to this class.
+ *
+ * I really don't like having to do things like this, but it provides a lot of benefits such as no
+ * need to store types and no need to check an argument's type for every access (this could be done
+ * by throwing errors, but then an incorrect (perhaps hand-edited) data file could cause a lot of
+ * errors to be thrown).
+ */
 class DefaultData : DataSection
 {
     //BEGIN DATA
-    /** Data members for direct access. */
-    bool	[ID]	Bool;
-    byte	[ID]	Byte;	/// ditto
-    short	[ID]	Short;	/// ditto
-    int		[ID]	Int;	/// ditto
-    long	[ID]	Long;	/// ditto
-    ubyte	[ID]	UByte;	/// ditto
-    ushort	[ID]	UShort;	/// ditto
-    uint	[ID]	UInt;	/// ditto
-    ulong	[ID]	ULong;	/// ditto
+    /** Data Members
+     *
+     * These names are available for direct access.
+     *
+     * An alternative access method is to use the provided templates:
+     * --------------------
+     * template Arg(T) {
+     *     alias Name Arg;
+     * }
+     * --------------------
+     *
+     * Use with a mixin or directly:
+     * --------------------
+     * mixin Arg!(type);
+     * auto x = Arg;
+     *
+     * type y = Arg!(type).Arg;
+     * --------------------
+     * Note: trying to use Arg!(type) to implicitly refer to Arg!(type).Arg causes compiler errors due to
+     * --- alias Name Arg; ---
+     * actually being a mixin.
+     */
+     
+    bool	[ID]	_bool;
+    byte	[ID]	_byte;		/// ditto
+    short	[ID]	_short;		/// ditto
+    int		[ID]	_int;		/// ditto
+    long	[ID]	_long;		/// ditto
+    ubyte	[ID]	_ubyte;		/// ditto
+    ushort	[ID]	_ushort;	/// ditto
+    uint	[ID]	_uint;		/// ditto
+    ulong	[ID]	_ulong;		/// ditto
     
-    bool[]	[ID]	BoolA;	/// ditto
-    byte[]	[ID]	ByteA;	/// ditto
-    short[]	[ID]	ShortA;	/// ditto
-    int[]	[ID]	IntA;	/// ditto
-    long[]	[ID]	LongA;	/// ditto
-    ubyte[]	[ID]	UByteA;	/// ditto
-    ushort[]	[ID]	UShortA;/// ditto
-    uint[]	[ID]	UIntA;	/// ditto
-    ulong[]	[ID]	ULongA;	/// ditto
+    char	[ID]	_char;		/// ditto
+    
+    float	[ID]	_float;		/// ditto
+    double	[ID]	_double;	/// ditto
+    real	[ID]	_real;		/// ditto
     
-    float	[ID]	Float;	/// ditto
-    double	[ID]	Double;	/// ditto
-    real	[ID]	Real;	/// ditto
-    float[]	[ID]	FloatA;	/// ditto
-    double[]	[ID]	DoubleA;/// ditto
-    real[]	[ID]	RealA;	/// ditto
+    bool[]	[ID]	_boolA;		/// ditto
+    byte[]	[ID]	_byteA;		/// ditto
+    short[]	[ID]	_shortA;	/// ditto
+    int[]	[ID]	_intA;		/// ditto
+    long[]	[ID]	_longA;		/// ditto
+    ubyte[]	[ID]	_ubyteA;	/// ditto
+    ushort[]	[ID]	_ushortA;	/// ditto
+    uint[]	[ID]	_uintA;		/// ditto
+    ulong[]	[ID]	_ulongA;	/// ditto
     
-    char	[ID]	Char;	/// ditto
-    char[]	[ID]	CharA;	/// ditto
+    char[]	[ID]	_charA;		/// ditto
+    
+    float[]	[ID]	_floatA;	/// ditto
+    double[]	[ID]	_doubleA;	/// ditto
+    real[]	[ID]	_realA;		/// ditto
     
     /** Alias names */
-    alias	CharA	String;
-    alias	UByteA	Binary;	/// ditto
+    alias	_ubyteA	_binary;
+    alias	_charA	_string;	/// ditto
     //END DATA
     
-    /+ Could use this:
-    private template addTagTp(alias Var, T) (ID id, char[] dt) {
-        Var[id] = parse!(T) (dt);
-    }
-    or a mixin.
-    +/
-    // Unfortunately, I think each case needs to be mentioned explicitly to tie it to the correct
-    // data member.
-    void addTag (char[] tp, ID id, char[] dt) {	/// for adding tags
+    void addTag (TypeInfo ti, ID id, char[] dt) {	/// for adding tags
         try {
-            postTrim (tp);
-            // parse tp, then use if statements to replace the following switch
-            
-        switch(Util.trim(tp)) {
-            case "1":
-            case "bool":
-                Arg!(bool)[id] = parse!(bool) (dt);
-            break;
-            case "s8":
-            case "byte":
-                addTagTp!(byte) (id, dt);
-            break;
-            case "s16":
-            case "short":
-                Short[id] = parse!(short) (dt);
-            break;
-            case "s32":
-            case "int":
-                Arg!(int)[id] = parse!(int) (dt);
-            break;
-            case "s64":
-            case "long":
-                Long[id] = parse!(long) (dt);
-            break;
-            case "u8":
-            case "ubyte":
-                UByte[id] = parse!(ubyte) (dt);
-            break;
-            case "u16":
-            case "ushort":
-                UShort[id] = parse!(ushort) (dt);
-            break;
-            case "u32":
-            case "uint":
-                UInt[id] = parse!(uint) (dt);
-            break;
-            case "u64":
-            case "ulong":
-                ULong[id] = parse!(ulong) (dt);
-            break;
-            
-            case "1[]":
-            case "bool[]":
-                BoolA[id] = parse!(bool[]) (dt);
-            break;
-            case "s8[]":
-            case "byte[]":
-                ByteA[id] = parse!(byte[]) (dt);
-            break;
-            case "s16[]":
-            case "short[]":
-                ShortA[id] = parse!(short[]) (dt);
-            break;
-            case "s32[]":
-            case "int[]":
-                IntA[id] = parse!(int[]) (dt);
-            break;
-            case "s64[]":
-            case "long[]":
-                LongA[id] = parse!(long[]) (dt);
-            break;
-            case "u8[]":
-            case "ubyte[]":
-            case "binary":
-                UByteA[id] = parse!(ubyte[]) (dt);
-            break;
-            case "u16[]":
-            case "ushort[]":
-                UShortA[id] = parse!(ushort[]) (dt);
-            break;
-            case "u32[]":
-            case "uint[]":
-                UIntA[id] = parse!(uint[]) (dt);
-            break;
-            case "u64[]":
-            case "ulong[]":
-                ULongA[id] = parse!(ulong[]) (dt);
-            break;
-            
-            case "fp32":
-            case "float":
-                Float[id] = parse!(float) (dt);
-            break;
-            case "fp64":
-            case "double":
-                Double[id] = parse!(double) (dt);
-            break;
-            case "fp":
-            case "real":
-                Real[id] = parse!(real) (dt);
-            break;
-            case "fp32[]":
-            case "float[]":
-                FloatA[id] = parse!(float[]) (dt);
-            break;
-            case "fp64[]":
-            case "double[]":
-                DoubleA[id] = parse!(double[]) (dt);
-            break;
-            case "fp[]":
-            case "real[]":
-                RealA[id] = parse!(real[]) (dt);
-            break;
-            
-            case "UTF8":
-            case "char":
-                Char[id] = parse!(char) (dt);
-            break;
-            case "UTF8[]":
-            case "char[]":
-            case "string":
-                CharA[id] = parse!(char[]) (dt);
-            break;
-            
-            default:
-                logger.warn ("Type not supported: " ~ tp);
-                throw new MTUnknownTypeException ();
-        }
-        } catch (Exception e) {
-            // an error should have already been logged
+            // crazy way of only writing one parameter on each line:
+            mixin ( `if (ti == typeid(bool)) addTag_add!(bool) (id, dt);`
+            	~ addTag_elifIsType_add!(byte)
+            	~ addTag_elifIsType_add!(short)
+            	~ addTag_elifIsType_add!(int)
+            	~ addTag_elifIsType_add!(long)
+            	~ addTag_elifIsType_add!(ubyte)
+            	~ addTag_elifIsType_add!(ushort)
+            	~ addTag_elifIsType_add!(uint)
+            	~ addTag_elifIsType_add!(ulong)
+            	~ addTag_elifIsType_add!(char)
+            	~ addTag_elifIsType_add!(float)
+            	~ addTag_elifIsType_add!(double)
+            	~ addTag_elifIsType_add!(real)
+            	~ addTag_elifIsType_add!(bool[])
+            	~ addTag_elifIsType_add!(byte[])
+            	~ addTag_elifIsType_add!(short[])
+            	~ addTag_elifIsType_add!(int[])
+            	~ addTag_elifIsType_add!(long[])
+            	~ addTag_elifIsType_add!(ubyte[])
+            	~ addTag_elifIsType_add!(ushort[])
+            	~ addTag_elifIsType_add!(uint[])
+            	~ addTag_elifIsType_add!(ulong[])
+            	~ addTag_elifIsType_add!(char[])
+            	~ addTag_elifIsType_add!(float[])
+            	~ addTag_elifIsType_add!(double[])
+                ~ addTag_elifIsType_add!(real[])
+            );
+        } catch (TextParseException) {
+            // Just ignore it. A warning's already been logged.
         }
     }
-    
-private:
-    void addTagTp(T) (ID id, char[] dt) {
-        Arg!(T)[id] = parse!(T) (dt);
+    private template addTag_elifIsType_add(T) {
+        const addTag_elifIsType_add = `else if (ti == typeid(`~T.stringof~`)) addTag_add!(`~T.stringof~`) (id, dt);` ;
+    }
+    private void addTag_add(T) (ID id, char[] dt) {
+        Arg!(T).Arg[id] = parse!(T) (dt);
     }
     
-    // use as: mixin Arg!(type); or Arg!(type)
-    template Arg(T : bool) {
-        alias Bool Arg;
-    }
-    template Arg(T : byte) {
-        alias Byte Arg;
-    }
-    template Arg(T : short) {
-        alias Short Arg;
-    }
-    template Arg(T : int) {
-        alias Int Arg;
-    }
-    template Arg(T : long) {
-        alias Long Arg;
-    }
-    template Arg(T : ubyte) {
-        alias UByte Arg;
-    }
-    template Arg(T : ushort) {
-        alias UShort Arg;
-    }
-    template Arg(T : uint) {
-        alias UInt Arg;
-    }
-    template Arg(T : ulong) {
-        alias ULong Arg;
-    }
-    template Arg(T : bool[]) {
-        alias BoolA Arg;
-    }
-    template Arg(T : byte[]) {
-        alias ByteA Arg;
-    }
-    template Arg(T : short[]) {
-        alias ShortA Arg;
+    void writeTags (out TextTag[] ret) {
+        //ret.length = Arg!().length + ...;
+        
+        
     }
-    template Arg(T : int[]) {
-        alias IntA Arg;
-    }
-    template Arg(T : long[]) {
-        alias LongA Arg;
-    }
-    template Arg(T : ubyte[]) {
-        alias UByteA Arg;
-    }
-    template Arg(T : ushort[]) {
-        alias UShortA Arg;
-    }
-    template Arg(T : uint[]) {
-        alias UIntA Arg;
-    }
-    template Arg(T : ulong[]) {
-        alias ULongA Arg;
-    }
-    template Arg(T : float) {
-        alias Float Arg;
+    
+    /* These make no attempt to check Arg is valid.
+     * But if the symbol doesn't exist the complier will throw an error anyway, e.g.:
+     * Error: identifier '_boolAA' is not defined
+     */
+    template Arg(T : T[]) {
+        const ArgString = Arg!(T).ArgString ~ `A`;
+        mixin(`alias `~ArgString~` Arg;`);
     }
-    template Arg(T : double) {
-        alias Double Arg;
-    }
-    template Arg(T : real) {
-        alias Real Arg;
-    }
-    template Arg(T : float[]) {
-        alias FloatA Arg;
-    }
-    template Arg(T : double[]) {
-        alias DoubleA Arg;
-    }
-    template Arg(T : real[]) {
-        alias RealA Arg;
-    }
-    template Arg(T : char) {
-        alias Char Arg;
-    }
-    template Arg(T : char[]) {
-        alias CharA Arg;
+    template Arg(T) {
+        const ArgString = `_` ~ T.stringof;
+        mixin(`alias `~ArgString~` Arg;`);
     }
 }
 
@@ -370,4 +261,4 @@
         static T[ID][TemplateData*] Data;
     }
 }
-+/
\ No newline at end of file
++/
--- a/mde/mergetag/doc/file-format-text.txt	Tue Oct 30 17:08:12 2007 +0000
+++ b/mde/mergetag/doc/file-format-text.txt	Sat Nov 03 15:15:43 2007 +0000
@@ -45,8 +45,8 @@
 
 Data item tags: Type format:
 Note:
-	The type is not initially parsed; it is read as a token terminated by any of these
-	characters:	<>|=
+	The type is read as a single token terminated by any of these characters:	<>|=
+	There must not be spaces within the type, e.g. "char []".
 	Of course any character other than a | terminating the token is an error.
 Format:
 	tp		a basic type
@@ -57,39 +57,39 @@
 	{t1,t2,...,tn}	a tuple with sub-types t1, t2, ..., tn
 
 Basic types (only items with a + are currently supported):
-	abbrev./full name (each type has two names which can be used):
+	name
 	
-	0	void	--- less useful type
-+	1	bool	--- integer types
-+	s8	byte
-+	u8	ubyte
-+	s16	short
-+	u16	ushort
-+	s32	int
-+	u32	uint
-+	s64	long
-+	u64	ulong
-	s128	cent
-	u128	ucent
+	void	--- less useful type
++	bool	--- integer types
++	byte
++	ubyte
++	short
++	ushort
++	int
++	uint
++	long
++	ulong
+	cent
+	ucent
 	
-+		binary	--- alias for ubyte[]
++	binary	--- alias for ubyte[]
 	
-+	fp32	float	--- floating point types
-+	fp64	double
-+	fp	real
-	im32	ifloat
-	im64	idouble
-	im	ireal
-	cpx32	cfloat
-	cpx64	cdouble
-	cpx	creal
++	float	--- floating point types
++	double
++	real
+	ifloat
+	idouble
+	ireal
+	cfloat
+	cdouble
+	creal
 	
-+	UTF8	char	--- character types (actually these CANNOT support UTF8 chars with length > 1)
-	UTF16	wchar
-	UTF32	dchar
-+		string	--- alias for char[] --- (DOES support UTF8)
-		wstring	--- alias for wchar[]
-		dstring	--- alias for dchar[]
++	char	--- single character types (actually these CANNOT support UTF8 symbols with length > 1)
+	wchar
+	dchar
++	string	--- alias for char[] --- (DOES support UTF8)
+	wstring	--- alias for wchar[]
+	dstring	--- alias for dchar[]
 
 
 Data item tags: Data format:
--- a/mde/mergetag/read.d	Tue Oct 30 17:08:12 2007 +0000
+++ b/mde/mergetag/read.d	Sat Nov 03 15:15:43 2007 +0000
@@ -63,8 +63,10 @@
     
 private:
     // Static symbols:
-    typedef void delegate (char[],ID,char[]) readDelg;	// Delegate for accepting tags.
+    typedef void delegate (TypeInfo,ID,char[]) readDelg;	// Delegate for accepting tags.
     
+    static bool initialised = false;
+    static TypeInfo[char[]] typeTable;
     static Logger logger;
     
     // Error messages as const variables. Could be loaded from files to support other languages?
@@ -104,8 +106,43 @@
 //END DATA
     
 //BEGIN METHODS: CTOR / DTOR
-    static this () {
+    // Could be a static this(), but this way it's only called if the class is used.
+    private void init () {
+        init_addType!(bool);
+        init_addType!(byte);
+        init_addType!(short);
+        init_addType!(int);
+        init_addType!(long);
+        init_addType!(ubyte);
+        init_addType!(ushort);
+        init_addType!(uint);
+        init_addType!(ulong);
+        init_addType!(char);
+        init_addType!(float);
+        init_addType!(double);
+        init_addType!(real);
+        init_addType!(bool[]);
+        init_addType!(byte[]);
+        init_addType!(short[]);
+        init_addType!(int[]);
+        init_addType!(long[]);
+        init_addType!(ubyte[]);
+        init_addType!(ushort[]);
+        init_addType!(uint[]);
+        init_addType!(ulong[]);
+        init_addType!(char[]);
+        init_addType!(float[]);
+        init_addType!(double[]);
+        init_addType!(real[]);
+        // aliases:
+        typeTable["string"] = typeid(char[]);
+        typeTable["binary"] = typeid(ubyte[]);
+        
         logger = Log.getLogger ("mde.mergetag.read.Reader");
+        initialised = true;
+    }
+    private static void init_addType(T) () {
+        typeTable[T.stringof] = typeid(T);
     }
     
     /** Tries to open file path and read it into a buffer.
@@ -136,6 +173,8 @@
     }
     /** ditto */
     public this (PathView path, DataSet* dataset_ = null, bool rdHeader = false) {
+        if (!initialised) init();	// on-demand static this()
+        
         // Create a dataset or use an existing one
         if (dataset_) dataset = *dataset_;
         else dataset = new DataSet();
@@ -302,8 +341,10 @@
                 if (fbuf[pos] != '>') throwMTErr (ERR_DTAG ~ ErrInFile);
                 data = fbuf[pos_s..pos];
                 
-                if (!comment) {
-                    if (addTag != null) addTag (type, tagID, data);
+                if (!comment && addTag != null) {
+                    TypeInfo* ti_p = type in typeTable;
+                    if (ti_p) addTag (*ti_p, tagID, data);
+                    else logger.warn ("Type not supported: " ~ type);
                 } else comment = false;			// cancel comment status now
             }
             else if (fbuf[pos] == '{') {
--- a/mde/test.d	Tue Oct 30 17:08:12 2007 +0000
+++ b/mde/test.d	Sat Nov 03 15:15:43 2007 +0000
@@ -9,25 +9,25 @@
 void printDataSet (DataSet ds) {
     foreach (ID sec_id, DefaultData dd; ds.getSections!(DefaultData)()) {
         Stdout ("Section:  ")(cast(uint) sec_id).newline;
-        foreach (ID i, int x; dd.Int) {
+        foreach (ID i, int x; dd._int) {
             Stdout (cast(uint) i)('\t')(x).newline;
         }
-        foreach (ID i, int[] x; dd.IntA) {
+        foreach (ID i, int[] x; dd._intA) {
             Stdout (cast(uint) i);
             foreach (int y; x)
                 Stdout ('\t')(y);
             Stdout.newline;
         }
-        foreach (ID i, ubyte[] x; dd.Binary) {
+        foreach (ID i, ubyte[] x; dd._binary) {
             Stdout (cast(uint) i);
             foreach (ubyte y; x)
                 Stdout ('\t')(y);
             Stdout.newline;
         }
-        foreach (ID i, char x; dd.Char) {
+        foreach (ID i, char x; dd._char) {
             Stdout (cast(uint) i)('\t')(x).newline;
         }
-        foreach (ID i, char[] x; dd.String) {
+        foreach (ID i, char[] x; dd._string) {
             Stdout (cast(uint) i)('\t')(x).newline;
         }
     }
@@ -38,7 +38,7 @@
     this () {
         Stdout ("New section (can't get ID from here).").newline;
     }
-    void addTag (char[] tp, ID id, char[] dt) {
-        Stdout ("\tData item (")(id)("):\t")(tp)("\t")(dt).newline;
+    void addTag (TypeInfo ti, ID id, char[] dt) {
+        Stdout ("\tData item (")(id)("):\t")(ti)("\t")(dt).newline;
     }
 }
--- a/mde/text/util.d	Tue Oct 30 17:08:12 2007 +0000
+++ b/mde/text/util.d	Sat Nov 03 15:15:43 2007 +0000
@@ -4,8 +4,9 @@
  ******************************************************/
 module mde.text.util;
 
-T[] postTrim(T : T[]) (T[] str) {
-    for (uint i = str.length,j; i > 0; i = j) {
+T postTrim(T) (T str) {
+    uint i = str.length;
+    for (uint j; i > 0; i = j) {
         j = i - 1;
         if (str[j] != ' ' || str[j] != '\t') break;
     }
--- a/test.mtt	Tue Oct 30 17:08:12 2007 +0000
+++ b/test.mtt	Sat Nov 03 15:15:43 2007 +0000
@@ -8,13 +8,13 @@
 <ubyte|0=255>
 <byte[]|5= [ 2 , -1 , -127, 127, -127,127,0 ] >
 {1}!{Binary}
-<u8[]|1=0051B4F6 >
+<binary|1=0051B4F6 >
 <ubyte[]|2= [2,0,250,5]>
 <binary|3=00102030405060708090A0B0C0D0E0F0>
 {2}!{Chars and strings}
-<UTF8 |1= ' '>
-< char| 2 ='\a'>
-< string |0= "A	sequence of\tcharacters:\v1²€ç⋅−+↙↔↘,↕">
+<char|1= ' '>
+<char| 2 ='\a'>
+<string|0= "A	sequence of\tcharacters:\v1²€ç⋅−+↙↔↘,↕">
 <string|1= [ 's','t' ,'r'	,	'i' , 'n' , 'g', ' ' , '2' ]>
 {11}
 <int|5=6>