@@ -711,6 +711,8 @@ mod node {
711
711
const hint_max_node_height: uint = 16 u;
712
712
713
713
/*
714
+ Function: of_str
715
+
714
716
Adopt a string as a node.
715
717
716
718
If the string is longer than `max_leaf_char_len`, it is
@@ -918,7 +920,11 @@ mod node {
918
920
}
919
921
920
922
/*
923
+ Function: flatten
924
+
921
925
Replace a subtree by a single leaf with the same contents.
926
+
927
+ Performance note: This function executes in linear time.
922
928
*/
923
929
fn flatten ( node : @node ) -> @node unsafe {
924
930
alt ( * node) {
@@ -934,49 +940,77 @@ mod node {
934
940
}
935
941
}
936
942
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
+ */
937
958
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) ] ; }
948
967
}
949
- //2. Rebuild tree from forest
950
- let root = @* tree_from_forest_destructive ( forest) ;
951
- ret option:: some ( root) ;
952
968
}
969
+ //2. Rebuild tree from forest
970
+ let root = @* tree_from_forest_destructive ( forest) ;
971
+ ret option:: some ( root) ;
972
+
953
973
}
954
974
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
+ */
955
993
fn sub_bytes ( node : @node , byte_offset : uint , byte_len : uint ) -> @node {
956
994
let node = node;
957
- let result = node; //Arbitrary value
958
995
let byte_offset = byte_offset;
959
- let byte_len = byte_len;
960
996
while true {
961
997
if byte_offset == 0 u && byte_len == node:: byte_len ( node) {
962
- result = node;
963
- break ;
998
+ ret node;
964
999
}
965
1000
alt ( * node) {
966
1001
node:: leaf ( x) {
967
1002
let char_len =
968
1003
str:: char_len_range ( * x. content , byte_offset, byte_len) ;
969
- result = @leaf ( { byte_offset: byte_offset,
1004
+ ret @leaf ( { byte_offset: byte_offset,
970
1005
byte_len: byte_len,
971
1006
char_len: char_len,
972
1007
content: x. content } ) ;
973
- break ;
974
1008
}
975
1009
node:: concat ( x) {
976
1010
let left_len: uint = node:: byte_len ( x. left ) ;
977
1011
if byte_offset <= left_len {
978
1012
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
980
1014
node = x. left ;
981
1015
} else {
982
1016
//Case 2: A (non-empty, possibly full) suffix
@@ -986,8 +1020,7 @@ mod node {
986
1020
sub_bytes ( x. left , byte_offset, left_len) ;
987
1021
let right_result =
988
1022
sub_bytes ( x. right , 0 u, left_len - byte_offset) ;
989
- result = concat2 ( left_result, right_result) ;
990
- break ;
1023
+ ret concat2( left_result, right_result) ;
991
1024
}
992
1025
} else {
993
1026
//Case 3: Everything fits in x.right
@@ -997,49 +1030,71 @@ mod node {
997
1030
}
998
1031
}
999
1032
}
1000
- ret result ;
1033
+ fail ; //Note: unreachable
1001
1034
}
1002
1035
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
+ */
1003
1054
fn sub_chars ( node : @node , char_offset : uint , char_len : uint ) -> @node {
1004
- alt ( * node) {
1005
- node:: leaf ( x) {
1006
- if char_offset == 0 u && char_len == x. char_len {
1007
- ret node;
1008
- }
1009
- let byte_offset =
1010
- str:: byte_len_range ( * x. content , 0 u, 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 == 0 u && 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 == 0 u && char_len == x. char_len {
1061
+ ret node;
1062
+ }
1063
+ let byte_offset =
1064
+ str:: byte_len_range ( * x. content , 0 u, 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 == 0 u && 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 , 0 u, left_len - char_offset) ;
1087
+ ret concat2( left_result, right_result) ;
1088
+ }
1026
1089
} 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 , 0 u, 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;
1035
1093
}
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
+ }
1040
1095
}
1041
- }
1042
1096
}
1097
+ fail;
1043
1098
}
1044
1099
1045
1100
fn concat2 ( left : @node , right : @node ) -> @node {
@@ -1091,54 +1146,80 @@ mod node {
1091
1146
} )
1092
1147
}
1093
1148
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
+ */
1094
1165
fn loop_leaves( node: @node, it : block( leaf) -> bool) -> bool {
1095
- let result = true ;
1096
1166
let current = node;
1097
1167
while true {
1098
1168
alt ( * current) {
1099
1169
leaf ( x) {
1100
- result = it ( x) ;
1101
- break ;
1170
+ ret it( x) ;
1102
1171
}
1103
1172
concat ( x) {
1104
1173
if loop_leaves ( x. left , it) { //non tail call
1105
1174
current = x. right ; //tail call
1106
1175
} else {
1107
- result = false ;
1108
- break ;
1176
+ ret false ;
1109
1177
}
1110
1178
}
1111
1179
}
1112
1180
}
1113
- ret result ;
1181
+ fail ; //unreachable
1114
1182
}
1115
1183
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
+ */
1116
1199
fn char_at ( node : @node , pos : uint ) -> char {
1117
1200
let node = node;
1118
1201
let pos = pos;
1119
- let result = '0' ;
1120
1202
while true {
1121
1203
alt ( * node) {
1122
1204
leaf ( x) {
1123
- result = str:: char_at ( * x. content , pos) ;
1124
- break ;
1205
+ ret str:: char_at ( * x. content , pos) ;
1125
1206
}
1126
1207
concat ( { left: left,
1127
1208
right: right,
1128
1209
char_len: _,
1129
1210
byte_len: _,
1130
1211
height: _} ) {
1131
1212
let left_len = char_len ( left) ;
1132
- if left_len > pos {
1213
+ if left_len > pos {
1133
1214
node = left;
1134
- } else {
1215
+ } else {
1135
1216
node = right;
1136
1217
pos = pos - left_len;
1137
- }
1218
+ }
1138
1219
}
1139
1220
}
1140
1221
} ;
1141
- ret result ;
1222
+ fail ; //unreachable
1142
1223
}
1143
1224
1144
1225
mod leaf_iterator {
@@ -1162,7 +1243,6 @@ mod node {
1162
1243
1163
1244
fn next ( it : t ) -> option:: t < leaf > {
1164
1245
if it. stackpos < 0 { ret option:: none; }
1165
- let result = option:: none;
1166
1246
while true {
1167
1247
let current = it. stack [ it. stackpos ] ;
1168
1248
it. stackpos -= 1 ;
@@ -1174,12 +1254,11 @@ mod node {
1174
1254
it. stack [ it. stackpos ] = x. left ;
1175
1255
}
1176
1256
leaf ( x) {
1177
- result = option:: some ( x) ;
1178
- break ;
1257
+ ret option:: some ( x) ;
1179
1258
}
1180
1259
}
1181
1260
}
1182
- ret result ;
1261
+ fail ; //unreachable
1183
1262
}
1184
1263
}
1185
1264
@@ -1207,27 +1286,23 @@ mod node {
1207
1286
}
1208
1287
1209
1288
fn next ( it : t ) -> option:: t < char > {
1210
- let result = option:: none;
1211
1289
while true {
1212
1290
alt ( get_current_or_next_leaf ( it) ) {
1213
- option:: none. {
1214
- break ;
1215
- }
1291
+ option:: none. { ret option :: none; }
1216
1292
option:: some ( leaf) {
1217
1293
let next_char = get_next_char_in_leaf ( it) ;
1218
1294
alt ( next_char) {
1219
1295
option:: none. {
1220
1296
cont ;
1221
1297
}
1222
1298
option:: some ( _) {
1223
- result = next_char;
1224
- break ;
1299
+ ret next_char;
1225
1300
}
1226
1301
}
1227
1302
}
1228
1303
}
1229
1304
}
1230
- ret result ;
1305
+ fail ; //unreachable
1231
1306
}
1232
1307
1233
1308
fn get_current_or_next_leaf ( it : t ) -> option:: t < leaf > {
0 commit comments