--- /dev/null
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using M17N;
+using M17N.Core;
+
+namespace M17N.Core
+{
+ public class MCharTable : IEnumerable
+ {
+ private static readonly int[] nchars
+ = new int[] { 0x110000, 0x10000, 0x1000, 0x80 };
+ private static readonly int[] slots
+ = new int[] { 17, 16, 32, 128 };
+ private static readonly int[] mask
+ = new int[] { 0x11FFFF, 0xFFFF, 0xFFF, 0x7F };
+ private static readonly int[] shift
+ = new int[] { 16, 12, 7, 0 };
+
+ private int index (int c) { return ((c & mask[depth]) >> shift[depth]); }
+
+ private MCharTable parent;
+ private int depth;
+ private int min_char, max_char;
+ private object[] contents;
+
+ public MCharTable ()
+ {
+ parent = null;
+ depth = 0;
+ min_char = 0x110000;
+ max_char = 0;
+ contents = new object[slots[0]];
+ }
+
+ private MCharTable (MCharTable parent, int min_char, object value)
+ {
+ this.parent = parent;
+ this.min_char = min_char;
+ depth = parent.depth + 1;
+ max_char = min_char + nchars[depth] - 1;
+ contents = new object[slots[depth]];
+ for (int i = 0; i < slots[depth]; i++)
+ contents[i] = value;
+ }
+
+ private object Get (int c)
+ {
+ object slot = contents[index (c)];
+ if (slot is MCharTable)
+ return ((MCharTable) slot).Get (c);
+ return slot;
+ }
+
+ private void Set (int c, object value)
+ {
+ if (depth == 3)
+ contents[c & mask[3]] = value;
+ else
+ {
+ int i = index (c);
+ int offset = depth == 0 ? 0 : min_char;
+
+ if (! (contents[i] is MCharTable))
+ contents[i] = new MCharTable (this, offset + i << shift[depth],
+ contents[i]);
+ ((MCharTable) contents[i]).Set (c, value);
+ }
+ }
+
+ public object this[int c]
+ {
+ get {
+ if (c < 0 || c > 0x10FFFF)
+ throw new ArgumentException ("Invalid character: " + c);
+ if (min_char > c || max_char < c)
+ return null;
+ return Get (c);
+ }
+
+ set {
+ if (c < 0 || c > 0x10FFFF)
+ throw new ArgumentException ("Invalid character: " + c);
+ if (value is MCharTable)
+ throw new ArgumentException ("Invalid value type: MCharTable");
+ if (min_char > c)
+ min_char = c;
+ if (max_char < c)
+ max_char = c;
+ Set (c, value);
+ }
+ }
+
+ private class MCharTableIT
+ {
+ public int c;
+ public object value;
+ public MCharTable table;
+
+ public MCharTableIT (int c, object value, MCharTable table)
+ {
+ this.c = c;
+ this.value = value;
+ this.table = table;
+ }
+
+ public override string ToString ()
+ {
+ return (String.Format ("<{0:X},{1}>", c, value));
+ }
+ }
+
+ private bool Next (MCharTableIT it)
+ {
+ Console.WriteLine ("Depth:{0} ({1:X}-{2:X}) IT:{3}", depth, min_char, max_char, it);
+ if (it.c > max_char)
+ return (parent != null ? parent.Next (it) : false);
+
+ object value = null;
+ for (int i = index (it.c);
+ i < slots[depth] && (value = contents[i]) == null;
+ i++, it.c = min_char + i << shift[depth]);
+ Console.WriteLine ("IT:{1}", depth, it);
+ if (value == null)
+ return (parent != null ? parent.Next (it) : false);
+ if (value is MCharTable)
+ return ((MCharTable) value).Next (it);
+ it.table = this;
+ it.value = value;
+ return true;
+ }
+
+ // for IEnumerable interface
+ public IEnumerator GetEnumerator()
+ {
+ return new MCharTableEnum (this);
+ }
+
+ private class MCharTableEnum : IEnumerator
+ {
+ private MCharTable table;
+ private MCharTableIT it;
+
+ public MCharTableEnum (MCharTable table)
+ {
+ this.table = table;
+ it = new MCharTableIT (-1, null, table);
+ }
+
+ public bool MoveNext ()
+ {
+ it.c++;
+ return it.table.Next (it);
+ }
+
+ public void Reset ()
+ {
+ it.c = -1;
+ it.table = table;
+ }
+
+ public KeyValuePair<int, object> Current
+ {
+ get { return new KeyValuePair<int, object> (it.c, it.value); }
+ }
+ }
+ }
+}
public object Load ()
{
- return (loader != null ? loader (tag, ExtraInfo)
- : load (MSymbol.nil, MSymbol.nil));
+ if (loader != null)
+ return loader (tag, ExtraInfo);
+
+ if (Info.Format == Mchar_table)
+ return load_char_table ();
+ if (Info.Format == Mcharset)
+ return load_charset ();
+
+ MPlist plist = null;
+ using (FileStream stream = File.OpenRead (FileInfo.FullName))
+ plist = new MPlist (stream);
+ return plist;
}
public object Load (MSymbol key, MSymbol stop)
{
- if (loader != null)
- return null;
- return load (key, stop);
+ if (loader != null || Info.Format != MSymbol.plist)
+ throw new ArgumentException
+ ("Key can't be specified for loading this database");
+
+ MPlist plist = null;
+ using (FileStream stream = File.OpenRead (FileInfo.FullName))
+ plist = new MPlist (stream, key, stop);
+ return plist;
+ }
+
+ private object load_charset ()
+ {
+ return null;
}
- private object load (MSymbol key, MSymbol stop)
+ private object load_char_table ()
{
return null;
}