Skip to content

Commit 05c9c73

Browse files
author
David Rajchenbach-Teller
committed
[Stdlib] rope.rs: improved doc, code readability
1 parent 7bfe4db commit 05c9c73

File tree

1 file changed

+157
-82
lines changed

1 file changed

+157
-82
lines changed

src/lib/rope.rs

+157-82
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,8 @@ mod node {
711711
const hint_max_node_height: uint = 16u;
712712

713713
/*
714+
Function: of_str
715+
714716
Adopt a string as a node.
715717
716718
If the string is longer than `max_leaf_char_len`, it is
@@ -918,7 +920,11 @@ mod node {
918920
}
919921

920922
/*
923+
Function: flatten
924+
921925
Replace a subtree by a single leaf with the same contents.
926+
927+
Performance note: This function executes in linear time.
922928
*/
923929
fn flatten(node: @node) -> @node unsafe {
924930
alt(*node) {
@@ -934,49 +940,77 @@ mod node {
934940
}
935941
}
936942

943+
/*
944+
Function: bal
945+
946+
Balance a node.
947+
948+
Algorithm:
949+
- if the node height is smaller than `hint_max_node_height`, do nothing
950+
- otherwise, gather all leaves as a forest, rebuild a balanced node,
951+
concatenating small leaves along the way
952+
953+
Returns:
954+
- `option::none` if no transformation happened
955+
- `option::some(x)` otherwise, in which case `x` has the same contents
956+
as `node` bot lower height and/or fragmentation.
957+
*/
937958
fn bal(node: @node) -> option::t<@node> {
938-
if height(node) < hint_max_node_height { ret option::none }
939-
else {
940-
//1. Gather all leaves as a forest
941-
let forest = [mutable];
942-
let it = leaf_iterator::start(node);
943-
while true {
944-
alt (leaf_iterator::next(it)) {
945-
option::none. { break; }
946-
option::some(x) { forest += [mutable @leaf(x)]; }
947-
}
959+
if height(node) < hint_max_node_height { ret option::none; }
960+
//1. Gather all leaves as a forest
961+
let forest = [mutable];
962+
let it = leaf_iterator::start(node);
963+
while true {
964+
alt (leaf_iterator::next(it)) {
965+
option::none. { break; }
966+
option::some(x) { forest += [mutable @leaf(x)]; }
948967
}
949-
//2. Rebuild tree from forest
950-
let root = @*tree_from_forest_destructive(forest);
951-
ret option::some(root);
952968
}
969+
//2. Rebuild tree from forest
970+
let root = @*tree_from_forest_destructive(forest);
971+
ret option::some(root);
972+
953973
}
954974

975+
/*
976+
Function: sub_bytes
977+
978+
Compute the subnode of a node.
979+
980+
Parameters:
981+
node - A node
982+
byte_offset - A byte offset in `node`
983+
byte_len - The number of bytes to return
984+
985+
Performance notes:
986+
- this function performs no copying;
987+
- this function executes in a time proportional to the height of `node`.
988+
989+
Safety notes:
990+
- this function fails if `byte_offset` or `byte_len` do not represent
991+
valid positions in `node`.
992+
*/
955993
fn sub_bytes(node: @node, byte_offset: uint, byte_len: uint) -> @node {
956994
let node = node;
957-
let result = node;//Arbitrary value
958995
let byte_offset = byte_offset;
959-
let byte_len = byte_len;
960996
while true {
961997
if byte_offset == 0u && byte_len == node::byte_len(node) {
962-
result = node;
963-
break;
998+
ret node;
964999
}
9651000
alt(*node) {
9661001
node::leaf(x) {
9671002
let char_len =
9681003
str::char_len_range(*x.content, byte_offset, byte_len);
969-
result = @leaf({byte_offset: byte_offset,
1004+
ret @leaf({byte_offset: byte_offset,
9701005
byte_len: byte_len,
9711006
char_len: char_len,
9721007
content: x.content});
973-
break;
9741008
}
9751009
node::concat(x) {
9761010
let left_len: uint = node::byte_len(x.left);
9771011
if byte_offset <= left_len {
9781012
if byte_offset + byte_len <= left_len {
979-
//Case 1: Everything fits in x.left, tail-call
1013+
//Case 1: Everything fits in x.left, tail-call
9801014
node = x.left;
9811015
} else {
9821016
//Case 2: A (non-empty, possibly full) suffix
@@ -986,8 +1020,7 @@ mod node {
9861020
sub_bytes(x.left, byte_offset, left_len);
9871021
let right_result =
9881022
sub_bytes(x.right, 0u, left_len - byte_offset);
989-
result = concat2(left_result, right_result);
990-
break;
1023+
ret concat2(left_result, right_result);
9911024
}
9921025
} else {
9931026
//Case 3: Everything fits in x.right
@@ -997,49 +1030,71 @@ mod node {
9971030
}
9981031
}
9991032
}
1000-
ret result;
1033+
fail;//Note: unreachable
10011034
}
10021035

1036+
/*
1037+
Function: sub_chars
1038+
1039+
Compute the subnode of a node.
1040+
1041+
Parameters:
1042+
node - A node
1043+
char_offset - A char offset in `node`
1044+
char_len - The number of chars to return
1045+
1046+
Performance notes:
1047+
- this function performs no copying;
1048+
- this function executes in a time proportional to the height of `node`.
1049+
1050+
Safety notes:
1051+
- this function fails if `char_offset` or `char_len` do not represent
1052+
valid positions in `node`.
1053+
*/
10031054
fn sub_chars(node: @node, char_offset: uint, char_len: uint) -> @node {
1004-
alt(*node) {
1005-
node::leaf(x) {
1006-
if char_offset == 0u && char_len == x.char_len {
1007-
ret node;
1008-
}
1009-
let byte_offset =
1010-
str::byte_len_range(*x.content, 0u, char_offset);
1011-
let byte_len =
1012-
str::byte_len_range(*x.content, byte_offset, char_len);
1013-
ret @leaf({byte_offset: byte_offset,
1014-
byte_len: byte_len,
1015-
char_len: char_len,
1016-
content: x.content});
1017-
}
1018-
node::concat(x) {
1019-
if char_offset == 0u && char_len == x.char_len {ret node;}
1020-
let left_len : uint = node::char_len(x.left);
1021-
if char_offset <= left_len {
1022-
if char_offset + char_len <= left_len {
1023-
//Case 1: Everything fits in x.left
1024-
ret sub_chars(x.left, char_offset, char_len);
1025-
//TODO: Optimize manually this tail call?
1055+
let node = node;
1056+
let char_offset = char_offset;
1057+
while true {
1058+
alt(*node) {
1059+
node::leaf(x) {
1060+
if char_offset == 0u && char_len == x.char_len {
1061+
ret node;
1062+
}
1063+
let byte_offset =
1064+
str::byte_len_range(*x.content, 0u, char_offset);
1065+
let byte_len =
1066+
str::byte_len_range(*x.content, byte_offset, char_len);
1067+
ret @leaf({byte_offset: byte_offset,
1068+
byte_len: byte_len,
1069+
char_len: char_len,
1070+
content: x.content});
1071+
}
1072+
node::concat(x) {
1073+
if char_offset == 0u && char_len == x.char_len {ret node;}
1074+
let left_len : uint = node::char_len(x.left);
1075+
if char_offset <= left_len {
1076+
if char_offset + char_len <= left_len {
1077+
//Case 1: Everything fits in x.left, tail call
1078+
node = x.left;
1079+
} else {
1080+
//Case 2: A (non-empty, possibly full) suffix
1081+
//of x.left and a (non-empty, possibly full) prefix
1082+
//of x.right
1083+
let left_result =
1084+
sub_chars(x.left, char_offset, left_len);
1085+
let right_result =
1086+
sub_chars(x.right, 0u, left_len - char_offset);
1087+
ret concat2(left_result, right_result);
1088+
}
10261089
} else {
1027-
//Case 2: A (non-empty, possibly full) suffix
1028-
//of x.left and a (non-empty, possibly full) prefix
1029-
//of x.right
1030-
let left_result =
1031-
sub_chars(x.left, char_offset, left_len);
1032-
let right_result =
1033-
sub_chars(x.right, 0u, left_len - char_offset);
1034-
ret concat2(left_result, right_result)
1090+
//Case 3: Everything fits in x.right, tail call
1091+
node = x.right;
1092+
char_offset -= left_len;
10351093
}
1036-
} else {
1037-
//Case 3: Everything fits in x.right
1038-
ret sub_chars(x.right, char_offset - left_len, char_len);
1039-
//TODO: Optimize manually this tail call?
1094+
}
10401095
}
1041-
}
10421096
}
1097+
fail;
10431098
}
10441099

10451100
fn concat2(left: @node, right: @node) -> @node {
@@ -1091,54 +1146,80 @@ mod node {
10911146
})
10921147
}
10931148

1149+
/*
1150+
Function: loop_leaves
1151+
1152+
Loop through a node, leaf by leaf
1153+
1154+
Parameters:
1155+
1156+
rope - A node to traverse.
1157+
it - A block to execute with each consecutive leaf of the node.
1158+
Return `true` to continue, `false` to stop.
1159+
1160+
Returns:
1161+
1162+
`true` If execution proceeded correctly, `false` if it was interrupted,
1163+
that is if `it` returned `false` at any point.
1164+
*/
10941165
fn loop_leaves(node: @node, it: block(leaf) -> bool) -> bool{
1095-
let result = true;
10961166
let current = node;
10971167
while true {
10981168
alt(*current) {
10991169
leaf(x) {
1100-
result = it(x);
1101-
break;
1170+
ret it(x);
11021171
}
11031172
concat(x) {
11041173
if loop_leaves(x.left, it) { //non tail call
11051174
current = x.right; //tail call
11061175
} else {
1107-
result = false;
1108-
break;
1176+
ret false;
11091177
}
11101178
}
11111179
}
11121180
}
1113-
ret result;
1181+
fail;//unreachable
11141182
}
11151183

1184+
/*
1185+
Function: char_at
1186+
1187+
Parameters:
1188+
pos - A position in the rope
1189+
1190+
Returns: The character at position `pos`
1191+
1192+
Safety notes: The function will fail if `pos`
1193+
is not a valid position in the rope.
1194+
1195+
Performance note: This function executes in a time
1196+
proportional to the height of the rope + the (bounded)
1197+
length of the largest leaf.
1198+
*/
11161199
fn char_at(node: @node, pos: uint) -> char {
11171200
let node = node;
11181201
let pos = pos;
1119-
let result = '0';
11201202
while true {
11211203
alt(*node) {
11221204
leaf(x) {
1123-
result = str::char_at(*x.content, pos);
1124-
break;
1205+
ret str::char_at(*x.content, pos);
11251206
}
11261207
concat({left: left,
11271208
right: right,
11281209
char_len: _,
11291210
byte_len: _,
11301211
height: _}) {
11311212
let left_len = char_len(left);
1132-
if left_len > pos {
1213+
if left_len > pos {
11331214
node = left;
1134-
} else {
1215+
} else {
11351216
node = right;
11361217
pos = pos - left_len;
1137-
}
1218+
}
11381219
}
11391220
}
11401221
};
1141-
ret result;
1222+
fail;//unreachable
11421223
}
11431224

11441225
mod leaf_iterator {
@@ -1162,7 +1243,6 @@ mod node {
11621243

11631244
fn next(it: t) -> option::t<leaf> {
11641245
if it.stackpos < 0 { ret option::none; }
1165-
let result = option::none;
11661246
while true {
11671247
let current = it.stack[it.stackpos];
11681248
it.stackpos -= 1;
@@ -1174,12 +1254,11 @@ mod node {
11741254
it.stack[it.stackpos] = x.left;
11751255
}
11761256
leaf(x) {
1177-
result = option::some(x);
1178-
break;
1257+
ret option::some(x);
11791258
}
11801259
}
11811260
}
1182-
ret result;
1261+
fail;//unreachable
11831262
}
11841263
}
11851264

@@ -1207,27 +1286,23 @@ mod node {
12071286
}
12081287

12091288
fn next(it: t) -> option::t<char> {
1210-
let result = option::none;
12111289
while true {
12121290
alt(get_current_or_next_leaf(it)) {
1213-
option::none. {
1214-
break;
1215-
}
1291+
option::none. { ret option::none; }
12161292
option::some(leaf) {
12171293
let next_char = get_next_char_in_leaf(it);
12181294
alt(next_char) {
12191295
option::none. {
12201296
cont;
12211297
}
12221298
option::some(_) {
1223-
result = next_char;
1224-
break;
1299+
ret next_char;
12251300
}
12261301
}
12271302
}
12281303
}
12291304
}
1230-
ret result;
1305+
fail;//unreachable
12311306
}
12321307

12331308
fn get_current_or_next_leaf(it: t) -> option::t<leaf> {

0 commit comments

Comments
 (0)