*** empty log message ***
[m17n/m17n-lib-cs.git] / MText.cs
index dc31f78..185ec08 100644 (file)
--- a/MText.cs
+++ b/MText.cs
@@ -8,14 +8,14 @@ namespace M17N.Core
 {
 #if false
   public enum MTextFormat
-  {
-    MTEXT_FORMAT_US_ASCII,
-    MTEXT_FORMAT_UTF_8,
-    MTEXT_FORMAT_UTF_16BE,
-    MTEXT_FORMAT_UTF_16LE,
-    MTEXT_FORMAT_UTF_32BE,
-    MTEXT_FORMAT_UTF_32LE,
-  }
+    {
+      MTEXT_FORMAT_US_ASCII,
+      MTEXT_FORMAT_UTF_8,
+      MTEXT_FORMAT_UTF_16BE,
+      MTEXT_FORMAT_UTF_16LE,
+      MTEXT_FORMAT_UTF_32BE,
+      MTEXT_FORMAT_UTF_32LE,
+    }
 #endif
 
   public class MTextProperty
@@ -42,7 +42,7 @@ namespace M17N.Core
     }
   }
 
-  public class MText
+  public class MText : IEnumerable, IComparable<MText>, IEquatable<MText>
   {
 #if false
     public enum MTextFormat format;
@@ -53,7 +53,7 @@ namespace M17N.Core
     private int cache_pos;
     private int cache_idx;
     private MInterval root_interval;
-    private bool unmodifiable;
+    private bool read_only;
 
     private static UTF8Encoding utf8 = new UTF8Encoding ();
 
@@ -61,8 +61,9 @@ namespace M17N.Core
     {
       int len = str.Length, n = 0;
 
-      for (int i = 0; i < len; i++) 
-       n += surrogate_high_p (str[i]) ? 2 : 1;
+      for (int i = 0; i < len; i++, n++) 
+       if (surrogate_high_p (str[i]))
+         i++;
       return n;
     }
 
@@ -70,44 +71,59 @@ namespace M17N.Core
     {
       int len = str.Length, n = 0;
 
-      for (int i = 0; i < len; i++) 
-       n += surrogate_high_p (str[i]) ? 2 : 1;
+      for (int i = 0; i < len; i++, n++) 
+       if (surrogate_high_p (str[i]))
+         i++;
       return n;
     }
 
     public MText ()
-    {
-      sb = new StringBuilder ();
-    }
+      {
+       sb = new StringBuilder ();
+      }
 
     public MText (byte[] str)
-    {
-      sb = new StringBuilder (utf8.GetString (str));
-      nchars = count_chars (sb);
-    }
+      {
+       sb = new StringBuilder (utf8.GetString (str));
+       nchars = count_chars (sb);
+      }
 
     public MText (String str)
-    {
-      sb = new StringBuilder (str);
-      nchars = count_chars (str);
-    }
+      {
+       sb = new StringBuilder (str);
+       nchars = count_chars (str);
+      }
 
     public MText (StringBuilder str)
-    {
-      sb = str;
-      nchars = count_chars (str);
-    }
+      {
+       sb = str;
+       nchars = count_chars (str);
+      }
 
     public static MText operator+ (MText mt1, MText mt2)
     {
-      MText mt = new MText (mt1.sb);
+      MText mt = new MText ();
 
+      mt.sb.Append (mt1.sb);
       mt.sb.Append (mt2.sb);
       mt.nchars = mt1.nchars + mt2.nchars;
       return mt;
     }
 
-    public override string ToString ()
+    public bool ReadOnly { get { return read_only; } }
+    public int Length { get { return nchars; } }
+
+    public int CompareTo (MText other)
+    {
+      return this.sb.ToString ().CompareTo (other.sb.ToString ());
+    }
+
+    public bool Equals (MText other)
+    {
+      return this.sb.Equals (other.sb);
+    }
+
+    public override String ToString ()
     {
       return sb.ToString ();
     }
@@ -242,6 +258,18 @@ namespace M17N.Core
       return this;
     }
 
+    public void PushProp (int from, int to, MTextProperty prop)
+    {
+      if (root_interval == null)
+       root_interval = new MInterval (0, true, sb.Length, true);
+      root_interval.Push (from, to, prop);
+    }
+
+    public IEnumerator GetEnumerator()
+    {
+      return new MTextEnum (this);
+    }
+
     private class MInterval
     {
       // Start and end positions of this interval and its children.
@@ -324,7 +352,7 @@ namespace M17N.Core
        }
       }
 
-      public void Push (MTextProperty prop, int start, int end)
+      public void Push (int start, int end, MTextProperty prop)
       {
        start <<= 2;
        if (prop.FrontSticky)
@@ -339,7 +367,7 @@ namespace M17N.Core
        if (start >= end)
          throw new Exception ("Invalid Text Property Range");
 
-       push (prop, start, end);
+       push (start, end, prop);
       }
 
       private MInterval divide_right (int pos)
@@ -414,7 +442,7 @@ namespace M17N.Core
        return interval;
       }
 
-      private void push (MTextProperty prop, int start, int end)
+      private void push (int start, int end, MTextProperty prop)
       {
        int this_start = Start;
        int this_end = End;
@@ -422,29 +450,59 @@ namespace M17N.Core
        if (start < this_start)
          {
            if (end <= this_start)
-             Left.push (prop, start, end);
-           else
              {
-               Left.push (prop, start, this_start);
-               if (end < this_end)
-                 {
-                   divide_right (end);
-                   stack.Push (prop);
-                 }
-               else
-                 {
-                   stack.Push (prop);
-                   if (this_end < end)
-                     Right.Push (prop, this_end, end);
-                 }
+               Left.push (start, end, prop);
+               return;
              }
+           Left.push (start, this_start, prop);
+           start = this_start;
          }
-       else if (start < this_end)
+       if (this_end < end)
          {
-           divide_right (start).Push (prop, start, end);
+           if (this_end < start)
+             {
+               Right.push (start, end, prop);
+               return;
+             }
+           Right.push (this_end, end, prop);
+           end = this_end;
          }
-       else
-         Right.Push (prop, start, end);
+       if (this_start < start)
+         divide_left (start);
+       if (end < this_end)
+         divide_right (end);
+       stack.Push (prop);
+      }
+    }
+
+    private class MTextEnum : IEnumerator
+    {
+      private MText mt;
+      private int pos = -1;
+
+      public MTextEnum (MText mt)
+       {
+         this.mt = mt;
+       }
+
+      public bool MoveNext ()
+      {
+        pos++;
+        return (pos < mt.nchars);
+      }
+
+      public void Reset ()
+      {
+        pos = -1;
+      }
+
+      public object Current
+      {
+        get {
+         //if (pos < 0 || pos >= mt.nchars)
+         //throw new InvalidOperationException ();
+         return mt[pos];
+       }
       }
     }
   }