exception Out_of_bounds of string
+exception Bad_rotation
type t =
| Leaf of string * int * int
- | Node of t * t * int
+ | Node of t * t * int * int
type rope = t
type rune = int
Leaf (s, 0, (String.length s))
let length = function
- | Leaf (_,_,l) -> l
- | Node (_,_,l) -> l
+ | Leaf (_,_,l) -> l
+ | Node (_,_,_,l) -> l
+
+let height = function
+ | Leaf (_,_,_) -> 0
+ | Node (_,_,h,_) -> h
let limit_index rope i =
if i < 0 then 0
raise (Out_of_bounds "Rope.check_index")
let join left right =
- let left_len = (length left) in
- let right_len = (length right) in
- if left_len == 0 then right
- else if right_len == 0 then left
- else Node (left, right, (length left) + (length right))
+ let llen = (length left) and rlen = (length right) in
+ if llen == 0 then right
+ else if rlen == 0 then left
+ else
+ let lh = (height left) and rh = (height right) in
+ let nh = 1 + lh + rh in
+ let n = Node (left, right, nh, llen + rlen) in
+ match (lh - rh) with
+ | 0 -> n
+ | 1 -> n
+ | -1 -> n
let rec split rope i =
if i < 0 || i > (length rope) then
match rope with
| Leaf (s,off,len) ->
(Leaf (s, off, i), Leaf (s, (off + i), len - (i)))
- | Node (l,r,len) ->
+ | Node (l,r,h,len) ->
let left_len = (length l) in
if i < left_len then
let (sl,sr) = (split l i) in
let (r_left,r_right) = split l_right (j - i) in
(join l_left r_right)
+let rec getb rope i =
+ check_index rope i;
+ match rope with
+ | Leaf (s,off,_) ->
+ s.[off + i]
+ | Node (l,r,h,len) ->
+ let left_len = (length l) in
+ if i < left_len then
+ getb l i
+ else
+ getb r (i - left_len)
+
let rec getc rope i =
check_index rope i;
match rope with
0x0A
else
c
- | Node (l,r,len) ->
+ | Node (l,r,h,len) ->
let left_len = (length l) in
if i < left_len then
getc l i
let buf = Bytes.create (j - i) in
iteri_from
(fun n c ->
- Bytes.set buf (n - i) (Char.chr (getc rope i));
+ Bytes.set buf (n - i) (getb rope i);
(n <= j))
rope i;
Bytes.unsafe_to_string buf
exception Out_of_bounds of string
+exception Bad_rotation
type t =
| Leaf of string * int * int
- | Node of t * t * int
+ | Node of t * t * int * int
type rope = t
type rune = int
val from_string : string -> rope
val length : rope -> int
+val height : rope -> int
val limit_index : rope -> int -> int
val last : rope -> int
val iter_from : (rune -> bool) -> rope -> int -> unit
val iteri_from : (int -> rune -> bool) -> rope -> int -> unit
+val getb : rope -> int -> char
val getc : rope -> int -> rune
val putc : rope -> int -> rune -> rope
val gets : rope -> int -> int -> string
let right = Leaf("a", 0, 1) in
let rope = (join left right) in
assert( match rope with
- | Node (l,r,2) -> (l == left && r == right)
+ | Node (l,r,h,2) -> (l == left && r == right)
| _ -> false)
);
test "join : join a rope with a leaf (l to r)" (fun () ->
let right = Leaf("a", 0, 1) in
let rope = (join left right) in
assert( match rope with
- | Node (l,r,3) -> (l == left && r == right)
+ | Node (l,r,h,3) -> (l == left && r == right)
| _ -> false)
);
test "join : join a rope with a leaf (r to l)" (fun () ->
let right = join (Leaf("a", 0, 1)) (Leaf("a", 0, 1)) in
let rope = (join left right) in
assert( match rope with
- | Node (l,r,3) -> (l == left && r == right)
+ | Node (l,r,h,3) -> (l == left && r == right)
| _ -> false)
);
assert( (getc rope (2)) == Char.code 'c' );
);
test "getc : return index 0 of rope" (fun () ->
- let rope = Node((Leaf("a", 0, 1)), (Leaf("b", 0, 1)), 2) in
+ let rope = Node((Leaf("a", 0, 1)), (Leaf("b", 0, 1)), 0, 2) in
assert( (getc rope (0)) == Char.code 'a' );
);
test "getc : return index 1 of rope" (fun () ->
- let rope = Node((Leaf("a", 0, 1)), (Leaf("b", 0, 1)), 2) in
+ let rope = Node((Leaf("a", 0, 1)), (Leaf("b", 0, 1)), 0, 2) in
assert( (getc rope (1)) == Char.code 'b' );
);
test "getc : return \\n for \\r\\n" (fun () ->