namespace M17N.Core
{
- public class MCharTable : IEnumerable
+ public class MCharRange
+ {
+ internal int from;
+ internal int to;
+ internal object value;
+ internal MCharTable from_table;
+ internal MCharTable to_table;
+
+ public int From { get { return from; } }
+ public int To { get { return to; } }
+ public object Value { get { return value; } }
+
+ internal static void CheckChar (int c)
+ {
+ if (c < 0 || c > 0x10FFFF)
+ throw new ArgumentException ("Invalid Unicode character: " + c);
+ }
+
+ public MCharRange (int c, MCharTable table)
+ {
+ CheckChar (c);
+ value = table.Get (c, out table);
+ if (c == 0)
+ {
+ from = c;
+ from_table = table;
+ }
+ else
+ from = table.PrevBoundary (c - 1, value, out from_table) + 1;
+ if (c == 0x10FFFF)
+ {
+ to = c;
+ to_table = table;
+ }
+ else
+ to = table.NextBoundary (c + 1, value, out to_table) - 1;
+ }
+
+ public bool Prev ()
+ {
+ if (from == 0)
+ return false;
+ to = from - 1;
+ value = from_table.Get (to, out to_table);
+ if (to == 0)
+ {
+ from = to;
+ from_table = to_table;
+ }
+ else
+ from = to_table.PrevBoundary (to - 1, value, out from_table) + 1;
+ return true;
+ }
+
+ public bool Next ()
+ {
+ if (to == 0x10FFFF)
+ return false;
+ from = to + 1;
+ value = to_table.Get (from, out from_table);
+ if (from == 0x10FFFF)
+ {
+ to = from;
+ to_table = from_table;
+ }
+ else
+ to = from_table.NextBoundary (from + 1, value, out to_table) - 1;
+ return true;
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("[U+{0:X}..U+{1:X} {2}]", from, to,
+ value == null ? "null" : value);
+ }
+ }
+
+ public class MCharTable : IEnumerable<MCharRange>
{
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 static bool IsSubCharTable (object obj)
+ {
+ return (obj is MCharTable
+ && ((MCharTable) obj).depth > 0);
+ }
+
+ private int index (int c) { return ((c - min_char) >> shift[depth]); }
private MCharTable parent;
private int depth;
{
parent = null;
depth = 0;
- min_char = 0x110000;
- max_char = 0;
+ min_char = 0;
+ max_char = 0x10FFFF;
contents = new object[slots[0]];
}
private object Get (int c)
{
object slot = contents[index (c)];
- if (slot is MCharTable)
+ if (IsSubCharTable (slot))
return ((MCharTable) slot).Get (c);
return slot;
}
+ internal object Get (int c, out MCharTable table)
+ {
+ if (c < min_char || c > max_char)
+ return parent.Get (c, out table);
+ object slot = contents[index (c)];
+ if (IsSubCharTable (slot))
+ return ((MCharTable) slot).Get (c, out table);
+ table = this;
+ return slot;
+ }
+
private void Set (int c, object value)
{
+ int i = index (c);
+
if (depth == 3)
- contents[c & mask[3]] = value;
+ contents[i] = 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],
+ if (! IsSubCharTable (contents[i]))
+ contents[i] = new MCharTable (this, min_char + (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;
+ MCharRange.CheckChar (c);
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;
+ MCharRange.CheckChar (c);
Set (c, value);
}
}
- private class MCharTableIT
+ public object this[int from, int to]
{
- public int c;
- public object value;
- public MCharTable table;
+ set { set_range (from, to, value); }
+ }
- public MCharTableIT (int c, object value, MCharTable table)
- {
- this.c = c;
- this.value = value;
- this.table = table;
- }
+ private void set_range (int from, int to, object value)
+ {
+ if (to > max_char)
+ to = max_char;
+ int i0 = index (from), i1 = index (to);
- public override string ToString ()
- {
- return (String.Format ("<{0:X},{1}>", c, value));
- }
+ if (depth == 3)
+ {
+ for (; i0 <= i1; i0++)
+ contents[i0] = value;
+ }
+ else
+ {
+ int min0 = min_char + (i0 << shift[depth]);
+ int min1 = min_char + (i1 << shift[depth]);
+
+ if (min0 < from)
+ {
+ if (contents[i0] != value)
+ {
+ if (! IsSubCharTable (contents[i0]))
+ contents[i0] = new MCharTable (this, min0, contents[i0]);
+ ((MCharTable) contents[i0]).set_range (from, to, value);
+ }
+ from = min0 + nchars[depth + 1];
+ if (from >= to)
+ return;
+ i0++;
+ }
+ for (; i0 < i1; i0++)
+ contents[i0] = value;
+ if (to == min1 + nchars[depth + 1] - 1)
+ contents[i1] = value;
+ else if (contents[i1] != value)
+ {
+ if (! IsSubCharTable (contents[i1]))
+ contents[i1] = new MCharTable (this, min1, contents[i1]);
+ ((MCharTable) contents[i1]).set_range (min1, to, value);
+ }
+ }
}
- private bool Next (MCharTableIT it)
+ internal int NextBoundary (int c, object value, out MCharTable table)
{
- 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);
+ table = this;
+ for (int i = index (c); i < slots[depth];
+ i++, c = min_char + (i << shift[depth]))
+ if (contents[i] != value)
+ return (IsSubCharTable (contents[i])
+ ? ((MCharTable) contents[i]).NextBoundary (c, value,
+ out table)
+ : c);
+ return (depth == 0
+ ? c : parent.NextBoundary (c, value, out table));
+ }
- 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;
+ internal int PrevBoundary (int c, object value, out MCharTable table)
+ {
+ table = this;
+ for (int i = index (c); i >= 0;
+ c = min_char + (i << shift[depth]) - 1, i--)
+ if (contents[i] != value)
+ return (IsSubCharTable (contents[i])
+ ? ((MCharTable) contents[i]).PrevBoundary (c, value,
+ out table)
+ : c);
+ return (depth == 0
+ ? c : parent.PrevBoundary (c, value, out table));
}
// for IEnumerable interface
- public IEnumerator GetEnumerator()
+ public IEnumerator<MCharRange> GetEnumerator()
{
return new MCharTableEnum (this);
}
- private class MCharTableEnum : IEnumerator
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator ();
+ }
+
+ private class MCharTableEnum : IEnumerator<MCharRange>
{
- private MCharTable table;
- private MCharTableIT it;
+ MCharTable table;
+ private MCharRange range;
public MCharTableEnum (MCharTable table)
{
this.table = table;
- it = new MCharTableIT (-1, null, table);
}
+ public void Dispose () {}
+
public bool MoveNext ()
{
- it.c++;
- return it.table.Next (it);
+ if (range == null)
+ {
+ range = new MCharRange (0, table);
+ return true;
+ }
+ return range.Next ();
}
public void Reset ()
{
- it.c = -1;
- it.table = table;
+ range = null;
+ }
+
+ public MCharRange Current
+ {
+ get { return range; }
}
- public KeyValuePair<int, object> Current
+ object IEnumerator.Current
{
- get { return new KeyValuePair<int, object> (it.c, it.value); }
+ get { return Current; }
}
}
}