Commit cb659ece authored by Robert Griesemer's avatar Robert Griesemer

additions to array container:

- added Slice, Cut, InsertArray, AppendArray
- renamed Remove -> Delete (so we have: Insert, Delete, Cut)
- more factoring of code
- extra tests (could use some more)

R=r,rsc
DELTA=179  (127 added, 22 deleted, 30 changed)
OCL=23648
CL=23685
parent 712522a6
......@@ -4,13 +4,47 @@
package array
type Element interface {
type (
Element interface {};
Array struct {
a []Element
}
)
func copy(dst, src []Element) {
for i := 0; i < len(src); i++ {
dst[i] = src[i]
}
}
type Array struct {
// TODO do not export field
a []Element
// Insert n elements at position i.
func expand(a []Element, i, n int) []Element {
// make sure we have enough space
len0 := len(a);
len1 := len0 + n;
if len1 < cap(a) {
// enough space - just expand
a = a[0 : len1]
} else {
// not enough space - double capacity
capb := cap(a)*2;
if capb < len1 {
// still not enough - use required length
capb = len1
}
// capb >= len1
b := make([]Element, len1, capb);
copy(b, a);
a = b
}
// make a hole
for j := len0-1; j >= i ; j-- {
a[j+n] = a[j]
}
return a
}
......@@ -61,52 +95,65 @@ func (p *Array) Last() Element {
func (p *Array) Insert(i int, x Element) {
p.a = expand(p.a, i, 1);
p.a[i] = x;
}
func (p *Array) Delete(i int) Element {
a := p.a;
n := len(a);
// grow array by doubling its capacity
if n == cap(a) {
b := make([]Element, 2*n);
for j := n-1; j >= 0; j-- {
b[j] = a[j];
}
a = b
}
x := a[i];
copy(a[i : n-1], a[i+1 : n]);
a[n-1] = nil; // support GC, nil out entry
p.a = a[0 : n-1];
return x
}
// make a hole
a = a[0 : n+1];
for j := n; j > i; j-- {
a[j] = a[j-1]
}
a[i] = x;
p.a = a
func (p *Array) InsertArray(i int, x *Array) {
p.a = expand(p.a, i, len(x.a));
copy(p.a[i : i + len(x.a)], x.a);
}
func (p *Array) Remove(i int) Element {
func (p *Array) Cut(i, j int) {
a := p.a;
n := len(a);
m := n - (j - i);
x := a[i];
for j := i+1; j < n; j++ {
a[j-1] = a[j]
copy(a[i : m], a[j : n]);
for k := m; k < n; k++ {
a[k] = nil // support GC, nil out entries
}
a[n-1] = nil; // support GC, nil out entry
p.a = a[0 : n-1];
p.a = a[0 : m];
}
return x
func (p *Array) Slice(i, j int) *Array {
s := New(j - i); // will fail in Init() if j < j
copy(s.a, p.a[i : j]);
return s;
}
// Convenience wrappers
func (p *Array) Push(x Element) {
p.Insert(len(p.a), x)
}
func (p *Array) Pop() Element {
return p.Remove(len(p.a) - 1)
return p.Delete(len(p.a) - 1)
}
func (p *Array) AppendArray(x *Array) {
p.InsertArray(len(p.a), x);
}
......
......@@ -24,7 +24,7 @@ func TestNew(t *testing.T) {
}
func Val(i int) int {
func val(i int) int {
return i*991 - 1234
}
......@@ -34,34 +34,34 @@ func TestAccess(t *testing.T) {
var a array.Array;
a.Init(n);
for i := 0; i < n; i++ {
a.Set(i, Val(i));
a.Set(i, val(i));
}
for i := 0; i < n; i++ {
if a.At(i).(int) != Val(i) { t.Error(i) }
if a.At(i).(int) != val(i) { t.Error(i) }
}
}
func TestInsertRemoveClear(t *testing.T) {
func TestInsertDeleteClear(t *testing.T) {
const n = 100;
a := array.New(0);
for i := 0; i < n; i++ {
if a.Len() != i { t.Errorf("A wrong len %d (expected %d)", a.Len(), i) }
a.Insert(0, Val(i));
if a.Last().(int) != Val(0) { t.Error("B") }
if a.Len() != i { t.Errorf("A) wrong len %d (expected %d)", a.Len(), i) }
a.Insert(0, val(i));
if a.Last().(int) != val(0) { t.Error("B") }
}
for i := n-1; i >= 0; i-- {
if a.Last().(int) != Val(0) { t.Error("C") }
if a.Remove(0).(int) != Val(i) { t.Error("D") }
if a.Len() != i { t.Errorf("E wrong len %d (expected %d)", a.Len(), i) }
if a.Last().(int) != val(0) { t.Error("C") }
if a.Delete(0).(int) != val(i) { t.Error("D") }
if a.Len() != i { t.Errorf("E) wrong len %d (expected %d)", a.Len(), i) }
}
if a.Len() != 0 { t.Errorf("F wrong len %d (expected 0)", a.Len()) }
if a.Len() != 0 { t.Errorf("F) wrong len %d (expected 0)", a.Len()) }
for i := 0; i < n; i++ {
a.Push(Val(i));
if a.Len() != i+1 { t.Errorf("G wrong len %d (expected %d)", a.Len(), i+1) }
if a.Last().(int) != Val(i) { t.Error("H") }
a.Push(val(i));
if a.Len() != i+1 { t.Errorf("G) wrong len %d (expected %d)", a.Len(), i+1) }
if a.Last().(int) != val(i) { t.Error("H") }
}
a.Init(0);
if a.Len() != 0 { t.Errorf("I wrong len %d (expected 0)", a.Len()) }
......@@ -70,17 +70,76 @@ func TestInsertRemoveClear(t *testing.T) {
for j := 0; j < m; j++ {
a.Push(j);
for i := 0; i < n; i++ {
x := Val(i);
x := val(i);
a.Push(x);
if a.Pop().(int) != x { t.Error("J") }
if a.Len() != j+1 { t.Errorf("K wrong len %d (expected %d)", a.Len(), j+1) }
if a.Len() != j+1 { t.Errorf("K) wrong len %d (expected %d)", a.Len(), j+1) }
}
}
if a.Len() != m { t.Errorf("L wrong len %d (expected %d)", a.Len(), m) }
if a.Len() != m { t.Errorf("L) wrong len %d (expected %d)", a.Len(), m) }
}
func verify_slice(t *testing.T, x *array.Array, elt, i, j int) {
for k := i; k < j; k++ {
if x.At(k).(int) != elt {
t.Errorf("M) wrong [%d] element %d (expected %d)", k, x.At(k).(int), elt)
}
}
s := x.Slice(i, j);
for k, n := 0, j-i; k < n; k++ {
if s.At(k).(int) != elt {
t.Errorf("N) wrong [%d] element %d (expected %d)", k, x.At(k).(int), elt)
}
}
}
func verify_pattern(t *testing.T, x *array.Array, a, b, c int) {
n := a + b + c;
if x.Len() != n {
t.Errorf("O) wrong len %d (expected %d)", x.Len(), n)
}
verify_slice(t, x, 0, 0, a);
verify_slice(t, x, 1, a, a + b);
verify_slice(t, x, 0, a + b, n);
}
func make_array(elt, len int) *array.Array {
x := array.New(len);
for i := 0; i < len; i++ {
x.Set(i, elt);
}
return x;
}
func TestInsertArray(t *testing.T) {
// 1
a := make_array(0, 0);
b := make_array(1, 10);
a.InsertArray(0, b);
verify_pattern(t, a, 0, 10, 0);
// 2
a = make_array(0, 10);
b = make_array(1, 0);
a.InsertArray(5, b);
verify_pattern(t, a, 5, 0, 5);
// 3
a = make_array(0, 10);
b = make_array(1, 3);
a.InsertArray(3, b);
verify_pattern(t, a, 3, 3, 7);
// 4
a = make_array(0, 10);
b = make_array(1, 1000);
a.InsertArray(8, b);
verify_pattern(t, a, 8, 1000, 2);
}
/* currently doesn't compile due to linker bug
func TestSorting(t *testing.T) {
const n = 100;
a := array.NewIntArray(n);
......@@ -89,4 +148,3 @@ func TestSorting(t *testing.T) {
}
if sort.IsSorted(a) { t.Error("not sorted") }
}
*/
......@@ -43,8 +43,8 @@ func (p *IntArray) Insert(i int, x int) {
}
func (p *IntArray) Remove(i int) int {
return p.Array.Remove(i).(int)
func (p *IntArray) Delete(i int) int {
return p.Array.Delete(i).(int)
}
......
......@@ -50,7 +50,7 @@ func test1() {
}
for v.Len() > 10 {
v.Remove(10);
v.Delete(10);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment