Browse Source

slice appears to be working now

pull/2/head
Sean Copenhaver 11 years ago
parent
commit
b97d5f6eaf
  1. 32
      lib/rope.ex
  2. 32
      test/rope_test.exs

32
lib/rope.ex

@ -34,6 +34,14 @@ defmodule Rope do
value: str value: str
end end
def concat(rope, nil) do
ropeify rope
end
def concat(nil, rope) do
ropeify rope
end
def concat(rope1, rope2) do def concat(rope1, rope2) do
rope1 = ropeify(rope1) rope1 = ropeify(rope1)
rope2 = ropeify(rope2) rope2 = ropeify(rope2)
@ -43,22 +51,39 @@ defmodule Rope do
length: rope1.length + rope2.length length: rope1.length + rope2.length
end end
def slice(nil, _start, _len) do
nil
end
def slice(rope = RLeaf[], start, len) do def slice(rope = RLeaf[], start, len) do
String.slice(rope.value, start, len) String.slice(rope.value, start, len)
end end
def slice(rope = RNode[length: rlen], start, len) def slice(RNode[length: rlen], start, _len)
when start > rlen do when start > rlen do
nil nil
end end
def slice(rope = RNode[length: rlen], start, len) def slice(RNode[length: rlen], start, _len)
when start == rlen do when start == rlen do
"" ""
end end
def slice(rope, start, len) do def slice(rope, start, len) do
RNode[left: left,
right: right] = rope
{startRight, lenRight} =
if start < left.length do
{0, len - (left.length - start)}
else
{start - left.length, len}
end
leftSub = slice(left, start, len)
rightSub = slice(right, startRight, lenRight)
concat(leftSub, rightSub)
end end
def to_string(rope) do def to_string(rope) do
@ -71,6 +96,7 @@ defmodule Rope do
RLeaf[] -> rope RLeaf[] -> rope
<<_ :: binary>> -> <<_ :: binary>> ->
Rope.new(rope) Rope.new(rope)
nil -> nil
end end
end end
end end

32
test/rope_test.exs

@ -3,6 +3,7 @@ Code.require_file "test_helper.exs", __DIR__
defmodule RopeTest do defmodule RopeTest do
use ExUnit.Case use ExUnit.Case
@simple "hello world"
@text "Have you any idea how much damage that bulldozer would suffer if I just let it roll straight over you?" @text "Have you any idea how much damage that bulldozer would suffer if I just let it roll straight over you?"
@longtext """ @longtext """
The Hitchhikers Guide to the Galaxy has a few things to say on the subject of towels. The Hitchhikers Guide to the Galaxy has a few things to say on the subject of towels.
@ -20,15 +21,15 @@ defmodule RopeTest do
""" """
test "can create a basic rope" do test "can create a basic rope" do
rope = Rope.new("test") rope = Rope.new(@simple)
is_equal rope, "test" is_equal rope, @simple
rope = Rope.new(@text) rope = Rope.new(@text)
is_equal rope, @text is_equal rope, @text
end end
test "can concat two single node ropes together" do test "can concat two single node ropes together" do
rope = Rope.concat(Rope.new("hello"), Rope.new(" world")) rope = build_rope @simple
is_equal rope, "hello world" is_equal rope, "hello world"
end end
@ -58,12 +59,20 @@ defmodule RopeTest do
is_equal rope, @longtext is_equal rope, @longtext
end end
test "concat handles nils" do
rope = Rope.concat(nil, "test")
is_equal rope, "test"
rope = Rope.concat("test", nil)
is_equal rope, "test"
end
test "slice with a start greater then the rope length returns the same as String.slice/3" do test "slice with a start greater then the rope length returns the same as String.slice/3" do
rope = Rope.new "test" rope = Rope.new @simple
assert Rope.slice(rope, 5, 10) == String.slice("test", 5, 10) assert Rope.slice(rope, 50, 10) == String.slice(@simple, 50, 10)
rope = Rope.concat "hello", " world" rope = build_rope @simple
assert Rope.slice(rope, 12, 10) == String.slice("hello world", 12, 10) assert Rope.slice(rope, 120, 10) == String.slice(@simple, 120, 10)
end end
test "slice with start equal to the rope returns the same as String.slice/3" do test "slice with start equal to the rope returns the same as String.slice/3" do
@ -71,7 +80,8 @@ defmodule RopeTest do
assert Rope.slice(rope, 4, 10) == String.slice("test", 4, 10) assert Rope.slice(rope, 4, 10) == String.slice("test", 4, 10)
rope = Rope.concat "hello", " world" rope = Rope.concat "hello", " world"
assert Rope.slice(rope, 11, 10) == String.slice("hello world", 11, 10) length = String.length @simple
assert Rope.slice(rope, length, 10) == String.slice(@simple, length, 10)
end end
test "slice works on single node ropes" do test "slice works on single node ropes" do
@ -80,13 +90,13 @@ defmodule RopeTest do
end end
test "slice works on multi-node ropes" do test "slice works on multi-node ropes" do
rope = Rope.concat "hello", " world" rope = build_rope @simple
assert Rope.slice(rope, 3, 5) == "lo wo" is_equal Rope.slice(rope, 3, 5), String.slice(@simple, 3, 5)
end end
test "can get slice from middle of text" do test "can get slice from middle of text" do
rope = build_rope @longtext rope = build_rope @longtext
is_equal Rope.slice(rope, 231, 15), "wrap it around" is_equal Rope.slice(rope, 231, 15), String.slice(@longtext, 231, 15)
end end
defp build_rope(text) do defp build_rope(text) do

Loading…
Cancel
Save