2 using System.Collections;
3 using System.Collections.Generic;
9 public class MCharRange
13 internal object value;
14 internal MCharTable from_table;
15 internal MCharTable to_table;
17 public int From { get { return from; } }
18 public int To { get { return to; } }
19 public object Value { get { return value; } }
21 internal static void CheckChar (int c)
23 if (c < 0 || c > 0x10FFFF)
24 throw new ArgumentException ("Invalid Unicode character: " + c);
27 public MCharRange (int c, MCharTable table)
30 value = table.Get (c, out table);
37 from = table.PrevBoundary (c - 1, value, out from_table) + 1;
44 to = table.NextBoundary (c + 1, value, out to_table) - 1;
52 value = from_table.Get (to, out to_table);
56 from_table = to_table;
59 from = to_table.PrevBoundary (to - 1, value, out from_table) + 1;
68 value = to_table.Get (from, out from_table);
72 to_table = from_table;
75 to = from_table.NextBoundary (from + 1, value, out to_table) - 1;
79 public override string ToString ()
81 return String.Format ("[U+{0:X}..U+{1:X} {2}]", from, to,
82 value == null ? "null" : value);
86 public class MCharTable : IEnumerable<MCharRange>
88 private static readonly int[] nchars
89 = new int[] { 0x110000, 0x10000, 0x1000, 0x80 };
90 private static readonly int[] slots
91 = new int[] { 17, 16, 32, 128 };
92 private static readonly int[] shift
93 = new int[] { 16, 12, 7, 0 };
95 private static bool IsSubCharTable (object obj)
97 return (obj is MCharTable
98 && ((MCharTable) obj).depth > 0);
101 private int index (int c) { return ((c - min_char) >> shift[depth]); }
103 private MCharTable parent;
105 private int min_char, max_char;
106 private object[] contents;
114 contents = new object[slots[0]];
117 private MCharTable (MCharTable parent, int min_char, object value)
119 this.parent = parent;
120 this.min_char = min_char;
121 depth = parent.depth + 1;
122 max_char = min_char + nchars[depth] - 1;
123 contents = new object[slots[depth]];
124 for (int i = 0; i < slots[depth]; i++)
128 private object Get (int c)
130 object slot = contents[index (c)];
131 if (IsSubCharTable (slot))
132 return ((MCharTable) slot).Get (c);
136 internal object Get (int c, out MCharTable table)
138 if (c < min_char || c > max_char)
139 return parent.Get (c, out table);
140 object slot = contents[index (c)];
141 if (IsSubCharTable (slot))
142 return ((MCharTable) slot).Get (c, out table);
147 private void Set (int c, object value)
155 if (! IsSubCharTable (contents[i]))
156 contents[i] = new MCharTable (this, min_char + (i << shift[depth]),
158 ((MCharTable) contents[i]).Set (c, value);
162 public object this[int c]
165 MCharRange.CheckChar (c);
170 MCharRange.CheckChar (c);
175 public object this[int from, int to]
178 MCharRange.CheckChar (from);
179 MCharRange.CheckChar (to);
180 set_range (from, to, value);
184 private void set_range (int from, int to, object value)
188 int i0 = index (from), i1 = index (to);
192 for (; i0 <= i1; i0++)
193 contents[i0] = value;
197 int min0 = min_char + (i0 << shift[depth]);
198 int min1 = min_char + (i1 << shift[depth]);
202 if (contents[i0] != value)
204 if (! IsSubCharTable (contents[i0]))
205 contents[i0] = new MCharTable (this, min0, contents[i0]);
206 ((MCharTable) contents[i0]).set_range (from, to, value);
208 from = min0 + nchars[depth + 1];
213 for (; i0 < i1; i0++)
214 contents[i0] = value;
215 if (to == min1 + nchars[depth + 1] - 1)
216 contents[i1] = value;
217 else if (contents[i1] != value)
219 if (! IsSubCharTable (contents[i1]))
220 contents[i1] = new MCharTable (this, min1, contents[i1]);
221 ((MCharTable) contents[i1]).set_range (min1, to, value);
226 internal int NextBoundary (int c, object value, out MCharTable table)
229 for (int i = index (c); i < slots[depth];
230 i++, c = min_char + (i << shift[depth]))
231 if (contents[i] != value)
232 return (IsSubCharTable (contents[i])
233 ? ((MCharTable) contents[i]).NextBoundary (c, value,
237 ? c : parent.NextBoundary (c, value, out table));
240 internal int PrevBoundary (int c, object value, out MCharTable table)
243 for (int i = index (c); i >= 0;
244 c = min_char + (i << shift[depth]) - 1, i--)
245 if (contents[i] != value)
246 return (IsSubCharTable (contents[i])
247 ? ((MCharTable) contents[i]).PrevBoundary (c, value,
251 ? c : parent.PrevBoundary (c, value, out table));
254 // for IEnumerable interface
255 public IEnumerator<MCharRange> GetEnumerator()
257 return new MCharTableEnum (this);
260 IEnumerator IEnumerable.GetEnumerator()
262 return GetEnumerator ();
265 private class MCharTableEnum : IEnumerator<MCharRange>
268 private MCharRange range;
270 public MCharTableEnum (MCharTable table) {
274 public bool MoveNext ()
278 range = new MCharRange (0, table);
281 return range.Next ();
284 public void Reset () { range = null; }
286 public MCharRange Current { get { return range; } }
288 object IEnumerator.Current { get { return Current; } }
290 public void Dispose () {}