*** empty log message ***
[m17n/m17n-lib-cs.git] / MCharTable.cs
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using M17N;
5 using M17N.Core;
6
7 namespace M17N.Core
8 {
9   public class MCharTable : IEnumerable
10   {
11     private static readonly int[] nchars
12       = new int[] { 0x110000, 0x10000, 0x1000, 0x80 };
13     private static readonly int[] slots
14       = new int[] { 17, 16, 32, 128 };
15     private static readonly int[] mask
16       = new int[] { 0x11FFFF, 0xFFFF, 0xFFF, 0x7F };
17     private static readonly int[] shift
18       = new int[] { 16, 12, 7, 0 };
19
20     private int index (int c) { return ((c & mask[depth]) >> shift[depth]); }
21
22     private MCharTable parent;
23     private int depth;
24     private int min_char, max_char;
25     private object[] contents;
26
27     public MCharTable ()
28       {
29         parent = null;
30         depth = 0;
31         min_char = 0x110000;
32         max_char = 0;
33         contents = new object[slots[0]];
34       }
35
36     private MCharTable (MCharTable parent, int min_char, object value)
37       {
38         this.parent = parent;
39         this.min_char = min_char;
40         depth = parent.depth + 1;
41         max_char = min_char + nchars[depth] - 1;
42         contents = new object[slots[depth]];
43         for (int i = 0; i < slots[depth]; i++)
44           contents[i] = value;
45       }
46
47     private object Get (int c)
48     {
49       object slot = contents[index (c)];
50       if (slot is MCharTable)
51         return ((MCharTable) slot).Get (c);
52       return slot;
53     }
54
55     private void Set (int c, object value)
56     {
57       if (depth == 3)
58         contents[c & mask[3]] = value;
59       else
60         {
61           int i = index (c);
62           int offset = depth == 0 ? 0 : min_char;
63
64           if (! (contents[i] is MCharTable))
65             contents[i] = new MCharTable (this, offset + i << shift[depth],
66                                           contents[i]);
67           ((MCharTable) contents[i]).Set (c, value);
68         }
69     }
70
71     public object this[int c]
72     {
73       get {
74         if (c < 0 || c > 0x10FFFF)
75           throw new ArgumentException ("Invalid character: " + c);
76         if (min_char > c || max_char < c)
77           return null;
78         return Get (c);
79       }
80
81       set {
82         if (c < 0 || c > 0x10FFFF)
83           throw new ArgumentException ("Invalid character: " + c);
84         if (value is MCharTable)
85           throw new ArgumentException ("Invalid value type: MCharTable");
86         if (min_char > c)
87           min_char = c;
88         if (max_char < c)
89           max_char = c;
90         Set (c, value);
91       }
92     }
93
94     private class MCharTableIT
95     {
96       public int c;
97       public object value;
98       public MCharTable table;
99
100       public MCharTableIT (int c, object value, MCharTable table)
101       {
102         this.c = c;
103         this.value = value;
104         this.table = table;
105       }
106
107       public override string ToString ()
108       {
109         return (String.Format ("<{0:X},{1}>", c, value));
110       }
111     }
112
113     private bool Next (MCharTableIT it)
114     {
115       Console.WriteLine ("Depth:{0} ({1:X}-{2:X}) IT:{3}", depth, min_char, max_char, it);
116       if (it.c > max_char)
117         return (parent != null ? parent.Next (it) : false);
118
119       object value = null;
120       for (int i = index (it.c);
121            i < slots[depth] && (value = contents[i]) == null;
122            i++, it.c = min_char + i << shift[depth]);
123       Console.WriteLine ("IT:{1}", depth, it);
124       if (value == null)
125         return (parent != null ? parent.Next (it) : false);
126       if (value is MCharTable)
127         return ((MCharTable) value).Next (it);
128       it.table = this;
129       it.value = value;
130       return true;
131     }
132
133     // for IEnumerable interface
134     public IEnumerator GetEnumerator()
135     {
136       return new MCharTableEnum (this);
137     }
138
139     private class MCharTableEnum : IEnumerator
140     {
141       private MCharTable table;
142       private MCharTableIT it;
143
144       public MCharTableEnum (MCharTable table)
145         {
146           this.table = table;
147           it = new MCharTableIT (-1, null, table);
148         }
149
150       public bool MoveNext ()
151       {
152         it.c++;
153         return it.table.Next (it);
154       }
155
156       public void Reset ()
157       {
158         it.c = -1;
159         it.table = table;
160       }
161
162       public KeyValuePair<int, object> Current
163       {
164         get { return new KeyValuePair<int, object> (it.c, it.value); }
165       }
166     }
167   }
168 }