From: handa Date: Mon, 19 Jan 2009 00:07:06 +0000 (+0000) Subject: *** empty log message *** X-Git-Url: http://git.chise.org/gitweb/?a=commitdiff_plain;ds=sidebyside;h=0f8cabbaa51863e72a0f5c8e1d6904163e9e7bc6;p=m17n%2Fm17n-lib-cs.git *** empty log message *** --- diff --git a/MText.cs b/MText.cs index 1fbb3f0..cd14162 100644 --- 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 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 (); - 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 (); + } + + private MInterval () { } + private MInterval (int start, int end, Stack stack) { this.total_start = start; this.total_end = end; this.stack = new Stack (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 (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; }