*** empty log message ***
authorhanda <handa>
Tue, 24 Mar 2009 13:08:50 +0000 (13:08 +0000)
committerhanda <handa>
Tue, 24 Mar 2009 13:08:50 +0000 (13:08 +0000)
MText.cs

index 7e574ce..a610507 100644 (file)
--- a/MText.cs
+++ b/MText.cs
@@ -20,25 +20,47 @@ namespace M17N.Core
 
   public class MTextProperty
   {
+    private enum MTextPropertyFlagMask
+      {
+       FRONT_STICKY = 1,
+       REAR_STICKY =  2
+      };
+
     internal MProperty prop;
-    internal bool front_sticky;
-    internal bool rear_sticky;
-    internal bool merginable;
-    public MProperty Prop { get { return prop; } }
-    public bool FrontSticky { get { return front_sticky; } }
-    public bool RearSticky { get { return rear_sticky; } }
-    public bool Merginable { get { return merginable; } }
+    internal byte flags;
+    internal MText mtext;
+    internal from;
+    internal to;
 
-    public MTextProperty (bool front_sticky, bool rear_sticky)
+    public MProperty Prop
+    {
+      get { return prop; }
+    }
+    public bool FrontSticky
+    {
+      get { return (flags & MTextPropertyFlagMask.FRONT_STICKY) != 0; }
+    }
+    public bool RearSticky
+    {
+      get { return (flags & MTextPropertyFlagMask.REAR_STICKY) != 0; }
+    }
+    public MText mtext
     {
-      this.front_sticky = front_sticky;
-      this.rear_sticky = rear_sticky;
+      get { return mtext; }
     }
-    public MTextProperty (bool front_sticky, bool rear_sticky, bool merginable)
+    public int from
     {
-      this.front_sticky = front_sticky;
-      this.rear_sticky = rear_sticky;
-      this.merginable = merginable;
+      get { return from; }
+    }
+    public int to
+    {
+      get { return to; }
+    }
+
+    public MTextProperty (bool front_sticky, bool rear_sticky)
+    {
+      this.flags = ((front_sticky ? MTextPropertyFlagMask.FRONT_STICKY : 0)
+                   | (rear_sticky ? MTextPropertyFlagMask.REAR_STICKY : 0));
     }
   }
 
@@ -48,11 +70,18 @@ namespace M17N.Core
     public enum MTextFormat format;
 #endif
 
+    private struct KeyIntervalPair
+    {
+      object key;
+      MInterval interval;
+    };
+
     private StringBuilder sb;
     private int nchars;
     private int cache_pos;
     private int cache_idx;
-    private MInterval root_interval;
+    private stack<KeyIntervalPair> root_intervals;
+    private MProperty default_property;
     private bool read_only;
 
     private static UTF8Encoding utf8 = new UTF8Encoding ();
@@ -276,78 +305,62 @@ namespace M17N.Core
 
     private class MInterval
     {
-      // position:    0           1           2           3
-      // index:   -1  0  1  2  3  4  5  6  7  8  9  10 11 12 13
-      //           |     |  A  |     |  B  |     |  C  |     |
-      // interval  |<--------->|<--->|<--------------->|<----|
+      // position: 0           1           2           3
+      //           |     A     |     B     |     C     |
+      // interval  |<--------->|<--------->|<--------->|
       // 
-      //                   [-1 99 (9 89)]
-      //       [0 10 (-1 9)]            [-10 0 (89 99)]
-      // [0 4 (-1 3)] [-4 0 (5 9)] [0 4 (89 93)] [-2 0 (97 99)]
-      //
-      // Start and end positions of this interval and its children.
-      // If this is the left node, the values are relative to the
-      // parent's total_start.  Otherwise, the values are relative to
-      // the parent's total_end.  So:
-      //                       total_start    total_end
-      //   left-side interval  0              positive even
-      //   right-side interval negative even  0
-      //   top-most interval   -1             positive odd
-      private int total_start, total_end;
-      // Stack of MTextProperty
+      //                         [3 (1 2)]
+      //             [1 (0 1)]               [1 (2 3)]
+      private int total_length;
+      private int from, to;
+      private object key;
       private Stack<MTextProperty> stack;
       private MInterval left, right, parent;
-      private MText mt;
-
-      private static int adjust_position (int pos, bool front_inclusive)
-      {
-       return (pos << 2) + (front_inclusive ? -1 : 1);
-      }
+      private MText mtext;
 
-      private static bool before_point_p (int pos)
+      public MInterval (object key, int length)
       {
-       return ((pos + 1) % 4) == 0;
+       if (length <= 0)
+         throw new Exception ("Invalid interval length");
+       this.key = key;
+       total_length = length;
+       stack = new Stack<MTextProperty> ();
       }
 
-      public MInterval (int start, bool front_inclusive,
-                       int end, bool rear_inclusive)
+      private MInterval (object key, int length, Stack<MTextProperty> stack)
       {
-       if (start > end)
-         throw new Exception ("Invalid Interval Range");
-       this.total_start = (start << 2) + (front_inclusive ? -1 : 1);
-       this.total_end = (end << 2) + (rear_inclusive ? 1 : -1);
-       this.stack = new Stack<MTextProperty> ();
+       this.key = key;
+       total_length = length;
+       from = 0;
+       to = total_length;
+       stack = new Stack<MTextProperty> (stack);
       }
 
-      public MInterval (MText mt)
-      {
-       this.mt = mt;
-       this.total_start = -1;
-       this.total_end = (mt.sb.Length << 2) + 1;
-       this.stack = new Stack<MTextProperty> ();
-      }
-
-      private MInterval () { }
-
-      private MInterval (int start, int end, Stack<MTextProperty> stack)
+      public MInterval (object key, MText mt)
       {
-       this.total_start = start;
-       this.total_end = end;
-       this.stack = new Stack<MTextProperty> (stack);
+       this.key = key;
+       mtext = mt;
+       total_length = mt.sb.Length;
+       from = 0;
+       to = total_length;
+       stack = new Stack<MTextProperty> ();
       }
 
-      private MInterval find (int pos, out int offset)
+      private MInterval find (int pos)
       {
-       if (pos < total_start || total_end < pos)
+       if (parent != null)
          {
-           offset = 0;
-           return null;
+           from = parent.from - total_length;
+           if (left != null)
+             from += left.total_length;
+           to = parent.from;
+           if (right != null)
+             to -= right.total_length;
          }
-       if (pos < Start)
-         return left.find (pos, out offset);
-       if (End < pos)
-         return right.find (pos - total_end, out offset);
-       offset = pos - Start;
+       if (pos < from)
+         return left.find (pos);
+       if (pos >= to)
+         return right.find (pos);
        return this;
       }
 
@@ -357,12 +370,12 @@ namespace M17N.Core
       //          c1       c2    left     c1
       private MInterval promote_right ()
       {
-       int right_length = - right.total_start;
+       int right_length = right.total_length;
        MInterval c1;
 
        if (parent == null)
-         mt.root_interval = right;
-       else if (total_start == 0)
+         mtext.update_root_interval (key, right);
+       else if (parent.left == this)
          parent.left = right;
        else
          parent.right = right;
@@ -372,18 +385,13 @@ namespace M17N.Core
 
        parent = right;
        right = c1;
-       if (c1 != null)
-         c1.parent = this;
-
-       parent.total_start = total_start;
-       parent.total_end = total_end;
-       total_start = 0;
-       total_end -= right_length - (c1 == null ? 0 : c1.total_end);
-       
+       parent.total_length += total_length;
+       total_length -= right_length;
        if (c1 != null)
          {
-           c1.total_end = - c1.total_start;
-           c1.total_start = 0;
+           c1.parent = this;
+           parent.total_length -= c1.total_length;
+           total_length += c1.total_length;
          }
        return parent;
       }
@@ -394,33 +402,28 @@ namespace M17N.Core
       // c1      c2                        c2     right
       private MInterval promote_left ()
       {
-       int left_length = left.total_end;
-       MInterval c2;
+       int left_length = left.total_length;
+       MInterval c1;
 
        if (parent == null)
-         mt.root_interval = left;
-       else if (total_start == 0)
+         mtext.update_root_interval (key, left);
+       else if (parent.left == this)
          parent.left = left;
        else
          parent.right = left;
        left.parent = parent;
-       c2 = left.right;
+       c1 = left.left;
        left.right = this;
 
        parent = left;
-       left = c2;
-       if (c2 != null)
-         c2.parent = this;
-
-       parent.total_start = total_start;
-       parent.total_end = total_end;
-       total_start -= left_length + (c2 == null ? 0 : c2.total_end);;
-       total_end = 0;
-       
-       if (c2 != null)
+       left = c1;
+       parent.total_length += total_length;
+       total_length -= left_length;
+       if (c1 != null)
          {
-           c2.total_start = - c2.total_end;
-           c2.total_end = 0;
+           c1.parent = this;
+           parent.total_length -= c1.total_length;
+           total_length += c1.total_length;
          }
        return parent;
       }
@@ -431,12 +434,18 @@ namespace M17N.Core
 
        while (true)
          {
-           int this_start = interval.Start;
-           int this_end = interval.End;
-           int diff = ((this_start - interval.total_start)
+           //       .-this-.
+           //  .-left-.  .-right-.
+           int left_length = (left == null ? 0 : left.total_length);
+           int right_length = (right == null ? 0 : right.total_length);
+           int length = total_length - left_length - right_length;
+           int diff = ((left_length + length) - 
                        - (interval.total_end - this_end));
            int abs = Math.Abs (diff);
 
+           if (left == null)
+             diff = 
+
            if (abs < this_end - this_start)
              break;
            if (diff < 0)