*** empty log message ***
authorhanda <handa>
Mon, 19 Jan 2009 00:07:06 +0000 (00:07 +0000)
committerhanda <handa>
Mon, 19 Jan 2009 00:07:06 +0000 (00:07 +0000)
MText.cs

index 1fbb3f0..cd14162 100644 (file)
--- a/MText.cs
+++ b/MText.cs
@@ -204,17 +204,14 @@ namespace M17N.Core
       int to_idx = pos_to_idx (mt2, to);
 
       sb.Insert (pos_idx, mt2.sb.ToString (from_idx, to_idx - from_idx));
-#if false
+      nchars += to - from;
       if (root_interval != null)
        {
-         MInterval interval;
-
-         if (mt2.root_interval != null)
-           interval = mt2.root_interval.Copy (from, to);
+         MInterval interval = (mt2.root_interval == null
+                               ? new MInterval (0, false, to - from, false)
+                               : mt2.root_interval.CopyTree (from, to));
          root_interval.Insert (pos, interval);
        }
-#endif
-      nchars += to - from;
     }
 
     public int this[int i]
@@ -273,12 +270,21 @@ namespace M17N.Core
     public void PushProp (int from, int to, MTextProperty prop)
     {
       if (root_interval == null)
-       root_interval = new MInterval (0, true, sb.Length, true);
+       root_interval = new MInterval (this);
       root_interval.Push (from, to, prop);
     }
 
     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  |<--------->|<--->|<--------------->|<------
+      // 
+      //                   [-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 relatie to
@@ -286,14 +292,19 @@ namespace M17N.Core
       private int total_start, total_end;
       // Stack of MTextProperty
       private Stack<MTextProperty> stack;
-      private int depth;
       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 static bool before_point_p (int pos)
+      {
+       return ((pos + 1) % 4) == 0;
+      }
+
       public MInterval (int start, bool front_inclusive,
                        int end, bool rear_inclusive)
       {
@@ -302,41 +313,167 @@ namespace M17N.Core
        this.total_start = (start << 2) + (front_inclusive ? -1 : 1);
        this.total_end = (end << 2) + (rear_inclusive ? 1 : -1);
        this.stack = new Stack<MTextProperty> ();
-       this.depth = 1;
       }
 
+      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)
       {
        this.total_start = start;
        this.total_end = end;
        this.stack = new Stack<MTextProperty> (stack);
-       this.depth = 1;
       }
 
-      private MInterval find (int pos)
+      private MInterval find (int pos, out int offset)
       {
        if (pos < total_start || total_end < pos)
-         return null;
+         {
+           offset = 0;
+           return null;
+         }
        if (pos < Start)
-         return left.find (pos);
+         return left.find (pos, out offset);
        if (End < pos)
-         return right.find (pos);
+         return right.find (pos - total_end, out offset);
+       offset = pos - Start;
        return this;
       }
 
-      public MInterval Copy (int start, int end)
+      //      p-. or .-p              p-. or .-p
+      //       .-this-.                .-right-.
+      //    left   .-right-.  ->   .-this-.    c2
+      //          c1       c2    left     c1
+      private MInterval promote_right ()
+      {
+       int right_length = - right.total_start;
+       MInterval c1;
+
+       if (parent == null)
+         mt.root_interval = right;
+       else if (total_start == 0)
+         parent.left = right;
+       else
+         parent.right = right;
+       right.parent = parent;
+       c1 = right.left;
+       right.left = this;
+
+       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);
+       
+       if (c1 != null)
+         {
+           c1.total_end = - c1.total_start;
+           c1.total_start = 0;
+         }
+       return parent;
+      }
+
+      //      p-. or .-p              p-. or .-p
+      //       .-this-.                .-left-.
+      //  .-left-.  .-right-.  ->     c1    .-this-.
+      // c1      c2                        c2     right
+      private MInterval promote_left ()
+      {
+       int left_length = left.total_end;
+       MInterval c2;
+
+       if (parent == null)
+         mt.root_interval = left;
+       else if (total_start == 0)
+         parent.left = left;
+       else
+         parent.right = left;
+       left.parent = parent;
+       c2 = left.right;
+       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)
+         {
+           c2.total_start = - c2.total_end;
+           c2.total_end = 0;
+         }
+       return parent;
+      }
+
+      private MInterval balance ()
       {
-       MInterval interval_start = find (start);
-       MInterval interval_end = find (end);
-       MInterval interval;
+       MInterval interval = this;
 
-       start = adjust_position (start, true);
-       end  = adjust_position (end, true);
-       interval = new MInterval (start, end, stack);
+       while (true)
+         {
+           int this_start = interval.Start;
+           int this_end = interval.End;
+           int diff = ((this_start - interval.total_start)
+                       - (interval.total_end - this_end));
+           int abs = Math.Abs (diff);
+
+           if (abs < this_end - this_start)
+             break;
+           if (diff < 0)
+             {
+               interval = interval.promote_right ();
+               interval.left.balance ();
+             }
+           else
+             {
+               interval = interval.promote_left ();
+               interval.right.balance ();
+             }
+         }
        return interval;
       }
 
-      private MInterval Copy ()
+      public MInterval CopyTree (int start, int end)
+      {
+       MInterval interval_start, interval_end, interval;
+       int offset_start, offset_end;
+
+       start <<= 2;
+       end  <<= 2;
+       interval_start = find (start, out offset_start);
+       interval_end = find (end, out offset_end);
+
+       interval = new MInterval ();
+       interval.total_start = 0;
+       interval.total_end = end - start;
+       interval.stack = new Stack<MTextProperty> (interval_start.stack);
+       interval = interval.divide_right (offset_start);
+       while (interval_start != interval_end)
+         {
+           interval_start = interval_start.Right;
+           interval = interval.divide_right (interval_start.End
+                                             - interval_start.Start);
+         }
+       return interval;
+      }
+
+      private MInterval CopyNode ()
       {
        return new MInterval (total_start, total_end, stack);
       }
@@ -405,17 +542,54 @@ namespace M17N.Core
        push (start, end, prop);
       }
 
-      public void Insert (int start, int end, MInterval interval)
+      public void Insert (int pos, MInterval interval)
       {
+       if (pos < Start)
+         Left.Insert (pos - total_start, interval);
+       else if (pos > End)
+         Right.Insert (pos - total_end, interval);
+       else
+         {
+           // position:    0           1           2           3
+           // index:   -1  0  1  2  3  4  5  6  7  8  9  10 11 12 13
+           // this      |<----------<-------------->->|
+           //           |<--------->|              |<>|
+           //
+           // interval                 |<->----->->|
+           //                             
+           // new       |<----------<----->----->-->------------>->|
+           //           |<--------->|     |<---->-->------------>->|
+           //                                      |<----------->->|
+           //                                                   |<>|       
+           int len = interval.total_end - interval.total_start;
+           MInterval temp;
+
+           total_end += len;
+           for (temp = this; temp.parent != null;
+                temp = temp.parent)
+             temp.parent.total_end += len;
+           if (End - pos < interval.End)
+             {
+               
+
+             }
+
+           temp = divide_right (Start + 2);
+           temp.left = interval;
+           right = interval;
+         }         
+           
+
       }
 
       private MInterval divide_right (int pos)
       {
-       MInterval interval = Copy ();
+       MInterval interval = CopyNode ();
        int this_start = Start;
        int this_end = End;
 
-       if (left == null || (right != null && left.depth < right.depth))
+       if (left == null
+           || (right != null && left.total_end < - right.total_start))
          {
            interval.left = this;
            interval.right = right;
@@ -427,9 +601,6 @@ namespace M17N.Core
                else
                  parent.right = interval;
              }
-           interval.depth = depth;
-           if (right == null)
-             interval.depth++;
            total_start = 0;
            total_end = pos - this_start;
          }
@@ -447,11 +618,12 @@ namespace M17N.Core
 
       private MInterval divide_left (int pos)
       {
-       MInterval interval = Copy ();
+       MInterval interval = CopyNode ();
        int this_start = Start;
        int this_end = End;
 
-       if (left == null || (right != null && left.depth < right.depth))
+       if (left == null
+           || (right != null && left.total_end < - right.total_start))
          {
            interval.total_start = 0;
            interval.total_end = pos - this_start;
@@ -471,9 +643,6 @@ namespace M17N.Core
                else
                  parent.right = interval;
              }
-           interval.depth = depth;
-           if (left == null)
-             interval.depth++;
            total_start = pos - this_end;
            total_end = 0;
          }