Skip to content

Commit

Permalink
[stdlib optim] rope::node improved balancing strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
Yoric committed Nov 6, 2011
1 parent 81a93ef commit 2dedcc8
Showing 1 changed file with 59 additions and 8 deletions.
67 changes: 59 additions & 8 deletions src/lib/rope.rs
Expand Up @@ -95,6 +95,7 @@ Safety notes:
*/
fn of_substr(str: @str, byte_offset: uint, byte_len: uint) -> rope {
if byte_len == 0u { ret node::empty; }
if byte_offset + byte_len > str::byte_len(*str) { fail; }
ret node::content(node::of_substr(str, byte_offset, byte_len));
}

Expand Down Expand Up @@ -702,18 +703,50 @@ mod node {
}

/*
Function: of_substr
Adopt a slice of a string as a node.
If the slice is longer than `max_leaf_char_len`, it is logically split
between as many leaves as necessary. Regardless, the string itself
is not copied.
@param byte_start The byte offset where the slice of `str` starts.
@param byte_len The number of bytes from `str` to use.
Parameters:
byte_start - The byte offset where the slice of `str` starts.
byte_len - The number of bytes from `str` to use.
Safety note:
- Behavior is undefined if `byte_start` or `byte_len` do not represent
valid positions in `str`
*/
fn of_substr(str: @str, byte_start: uint, byte_len: uint) -> @node {
assert (byte_len > 0u);
let char_len = str::char_len_range(*str, byte_start, byte_len);
ret of_substr_unsafer(str, byte_start, byte_len,
str::char_len_range(*str, byte_start, byte_len));
}

/*
Function: of_substr_unsafer
Adopt a slice of a string as a node.
If the slice is longer than `max_leaf_char_len`, it is logically split
between as many leaves as necessary. Regardless, the string itself
is not copied.
byte_start - The byte offset where the slice of `str` starts.
byte_len - The number of bytes from `str` to use.
char_len - The number of chars in `str` in the interval
[byte_start, byte_start+byte_len(
Safety note:
- Behavior is undefined if `byte_start` or `byte_len` do not represent
valid positions in `str`
- Behavior is undefined if `char_len` does not accurately represent the
number of chars between byte_start and byte_start+byte_len
*/
fn of_substr_unsafer(str: @str, byte_start: uint, byte_len: uint,
char_len: uint) -> @node {
assert(byte_start + byte_len <= str::byte_len(*str));
let candidate = @leaf({
byte_offset: byte_start,
byte_len: byte_len,
Expand Down Expand Up @@ -784,6 +817,15 @@ mod node {
}


/*
Function: tree_from_forest_destructive
Concatenate a forest of nodes into one tree.
Parameters:
forest - The forest. This vector is progressively rewritten during
execution and should be discarded as meaningless afterwards.
*/
fn tree_from_forest_destructive(forest: [mutable @node]) -> @node {
let i = 0u;
let len = vec::len(forest);
Expand All @@ -796,17 +838,26 @@ mod node {
let right_len= char_len(right);
let left_height= height(left);
let right_height=height(right);
if left_len + right_len > hint_max_leaf_char_len
//TODO: Improve strategy
|| left_height >= hint_max_node_height
|| right_height >= hint_max_node_height {
if left_len + right_len > hint_max_leaf_char_len {
if left_len <= hint_max_leaf_char_len {
left = flatten(left);
left_height = height(left);
}
if right_len <= hint_max_leaf_char_len {
right = flatten(right);
right_height = height(right);
}
}
if left_height >= hint_max_node_height {
left = of_substr_unsafer(@serialize_node(left),
0u,byte_len(left),
left_len);
}
if right_height >= hint_max_node_height {
right = of_substr_unsafer(@serialize_node(right),
0u,byte_len(right),
right_len);
}
forest[i/2u] = concat2(left, right);
i += 2u;
}
Expand Down

0 comments on commit 2dedcc8

Please sign in to comment.