Skip to content

Commit 2dedcc8

Browse files
author
David Rajchenbach-Teller
committed
[stdlib optim] rope::node improved balancing strategy
1 parent 81a93ef commit 2dedcc8

File tree

1 file changed

+59
-8
lines changed

1 file changed

+59
-8
lines changed

src/lib/rope.rs

+59-8
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ Safety notes:
9595
*/
9696
fn of_substr(str: @str, byte_offset: uint, byte_len: uint) -> rope {
9797
if byte_len == 0u { ret node::empty; }
98+
if byte_offset + byte_len > str::byte_len(*str) { fail; }
9899
ret node::content(node::of_substr(str, byte_offset, byte_len));
99100
}
100101

@@ -702,18 +703,50 @@ mod node {
702703
}
703704

704705
/*
706+
Function: of_substr
707+
705708
Adopt a slice of a string as a node.
706709
707710
If the slice is longer than `max_leaf_char_len`, it is logically split
708711
between as many leaves as necessary. Regardless, the string itself
709712
is not copied.
710713
711-
@param byte_start The byte offset where the slice of `str` starts.
712-
@param byte_len The number of bytes from `str` to use.
714+
Parameters:
715+
byte_start - The byte offset where the slice of `str` starts.
716+
byte_len - The number of bytes from `str` to use.
717+
718+
Safety note:
719+
- Behavior is undefined if `byte_start` or `byte_len` do not represent
720+
valid positions in `str`
713721
*/
714722
fn of_substr(str: @str, byte_start: uint, byte_len: uint) -> @node {
715-
assert (byte_len > 0u);
716-
let char_len = str::char_len_range(*str, byte_start, byte_len);
723+
ret of_substr_unsafer(str, byte_start, byte_len,
724+
str::char_len_range(*str, byte_start, byte_len));
725+
}
726+
727+
/*
728+
Function: of_substr_unsafer
729+
730+
Adopt a slice of a string as a node.
731+
732+
If the slice is longer than `max_leaf_char_len`, it is logically split
733+
between as many leaves as necessary. Regardless, the string itself
734+
is not copied.
735+
736+
byte_start - The byte offset where the slice of `str` starts.
737+
byte_len - The number of bytes from `str` to use.
738+
char_len - The number of chars in `str` in the interval
739+
[byte_start, byte_start+byte_len(
740+
741+
Safety note:
742+
- Behavior is undefined if `byte_start` or `byte_len` do not represent
743+
valid positions in `str`
744+
- Behavior is undefined if `char_len` does not accurately represent the
745+
number of chars between byte_start and byte_start+byte_len
746+
*/
747+
fn of_substr_unsafer(str: @str, byte_start: uint, byte_len: uint,
748+
char_len: uint) -> @node {
749+
assert(byte_start + byte_len <= str::byte_len(*str));
717750
let candidate = @leaf({
718751
byte_offset: byte_start,
719752
byte_len: byte_len,
@@ -784,6 +817,15 @@ mod node {
784817
}
785818

786819

820+
/*
821+
Function: tree_from_forest_destructive
822+
823+
Concatenate a forest of nodes into one tree.
824+
825+
Parameters:
826+
forest - The forest. This vector is progressively rewritten during
827+
execution and should be discarded as meaningless afterwards.
828+
*/
787829
fn tree_from_forest_destructive(forest: [mutable @node]) -> @node {
788830
let i = 0u;
789831
let len = vec::len(forest);
@@ -796,17 +838,26 @@ mod node {
796838
let right_len= char_len(right);
797839
let left_height= height(left);
798840
let right_height=height(right);
799-
if left_len + right_len > hint_max_leaf_char_len
800-
//TODO: Improve strategy
801-
|| left_height >= hint_max_node_height
802-
|| right_height >= hint_max_node_height {
841+
if left_len + right_len > hint_max_leaf_char_len {
803842
if left_len <= hint_max_leaf_char_len {
804843
left = flatten(left);
844+
left_height = height(left);
805845
}
806846
if right_len <= hint_max_leaf_char_len {
807847
right = flatten(right);
848+
right_height = height(right);
808849
}
809850
}
851+
if left_height >= hint_max_node_height {
852+
left = of_substr_unsafer(@serialize_node(left),
853+
0u,byte_len(left),
854+
left_len);
855+
}
856+
if right_height >= hint_max_node_height {
857+
right = of_substr_unsafer(@serialize_node(right),
858+
0u,byte_len(right),
859+
right_len);
860+
}
810861
forest[i/2u] = concat2(left, right);
811862
i += 2u;
812863
}

0 commit comments

Comments
 (0)