]> Cypherpunks repositories - gostls13.git/commitdiff
additions to array container:
authorRobert Griesemer <gri@golang.org>
Wed, 28 Jan 2009 21:32:31 +0000 (13:32 -0800)
committerRobert Griesemer <gri@golang.org>
Wed, 28 Jan 2009 21:32:31 +0000 (13:32 -0800)
- 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

src/lib/container/array/array.go
src/lib/container/array/array_test.go
src/lib/container/array/intarray.go
test/vectors.go

index 3d5c53249e4b8f05af282d0f7ef60e0110933e50..768e46d3a46cf6ec9fce4a55cd978e5d26bb55a6 100644 (file)
@@ -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);
 }
 
 
index 6deaf4a6e3fa273642000016d92fa9eeaca8341a..df9fee673c006fb5f9174e4f78126e6ebbc92800 100644 (file)
@@ -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") }
 }
-*/
index 7aefa78522af639dce657a1f6651f39af1d7686b..427ed5076c50d4cdc32ed8eb15d42b9b318ccaa4 100644 (file)
@@ -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)
 }
 
 
index e5cbde2d534e6070a1054f11bd114887634df6c0..3d745dc6aeb8162a59137130128cc3f635d83b11 100644 (file)
@@ -50,7 +50,7 @@ func test1() {
        }
 
        for v.Len() > 10 {
-               v.Remove(10);
+               v.Delete(10);
        }
 }