From 9db8c225f7679dc803ac309aa6d8f24bbb626972 Mon Sep 17 00:00:00 2001 From: handa Date: Tue, 14 Jul 2009 11:17:53 +0000 Subject: [PATCH] *** empty log message *** --- MCharTable.cs | 263 ++++++++++++++++++++++++++++++++++++++++++--------------- chartab.cs | 35 ++++++++ 2 files changed, 232 insertions(+), 66 deletions(-) create mode 100644 chartab.cs diff --git a/MCharTable.cs b/MCharTable.cs index 6845767..35685d7 100644 --- a/MCharTable.cs +++ b/MCharTable.cs @@ -6,18 +6,99 @@ using M17N.Core; 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 { 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; @@ -28,8 +109,8 @@ namespace M17N.Core { parent = null; depth = 0; - min_char = 0x110000; - max_char = 0; + min_char = 0; + max_char = 0x10FFFF; contents = new object[slots[0]]; } @@ -47,22 +128,32 @@ namespace M17N.Core 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); } @@ -71,97 +162,137 @@ namespace M17N.Core 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 GetEnumerator() { return new MCharTableEnum (this); } - private class MCharTableEnum : IEnumerator + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator (); + } + + private class MCharTableEnum : IEnumerator { - 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 Current + object IEnumerator.Current { - get { return new KeyValuePair (it.c, it.value); } + get { return Current; } } } } diff --git a/chartab.cs b/chartab.cs new file mode 100644 index 0000000..78e2a29 --- /dev/null +++ b/chartab.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.IO; +using M17N; +using M17N.Core; + +public class Test +{ + public static void Main() + { + MCharTable tbl = new MCharTable (); + + tbl[0x100] = MSymbol.Of ("test-100"); + tbl[0x101] = MSymbol.Of ("test-101"); + tbl[0xFFF] = MSymbol.Of ("test-FFF"); + tbl[0x1000] = MSymbol.Of ("test-1000"); + + tbl[0x2070, 0x4001] = MSymbol.t; + + Console.WriteLine ("# Direct access by tbl[CHAR]"); + Console.WriteLine ("0x100:{0}, 0x1000:{1}", tbl[0x100], tbl[0x1000]); + Console.WriteLine ("0x206F:{0}, 0x2070:{1}, 0x4001:{2}, 0x4002:{3}", + tbl[0x206F], tbl[0x2070], tbl[0x4001], tbl[0x4002]); + + Console.WriteLine ("# Enumerate on tbl"); + foreach (MCharRange range in tbl) + Console.WriteLine (range); + + Console.WriteLine ("# Using CharRange from U+3000 to U+0"); + MCharRange r = new MCharRange (0x3000, tbl); + do { + Console.WriteLine (r); + } while (r.Prev ()); + } +} -- 1.7.10.4