diff options
-rw-r--r-- | src/lib/container/vector.go | 97 | ||||
-rw-r--r-- | test/vectors.go | 61 |
2 files changed, 108 insertions, 50 deletions
diff --git a/src/lib/container/vector.go b/src/lib/container/vector.go index b4a910a9e..058992c0b 100644 --- a/src/lib/container/vector.go +++ b/src/lib/container/vector.go @@ -18,92 +18,89 @@ package vector type Element interface { } + export type Vector struct { - nalloc int; - nelem int; elem *[]Element; } -// BUG: workaround for non-constant allocation. -// i must be a power of 10. -func Alloc(i int) *[]Element { - switch i { - case 1: - return new([1]Element); - case 10: - return new([10]Element); - case 100: - return new([100]Element); - case 1000: - return new([1000]Element); - } - print("bad size ", i, "\n"); - panic("not known size\n"); -} - -func is_pow10(i int) bool { - switch i { - case 1, 10, 100, 1000: - return true; - } - return false; -} export func New() *Vector { v := new(Vector); - v.nelem = 0; - v.nalloc = 1; - v.elem = Alloc(v.nalloc); + v.elem = new([]Element, 1) [0 : 0]; // capacity must be > 0! return v; } + +func (v *Vector) RangeError(op string, i int) { + panic("Vector.", op, ": index ", i, " out of range (len = ", len(v.elem), ")\n"); +} + + func (v *Vector) Len() int { - return v.nelem; + return len(v.elem); } + func (v *Vector) At(i int) Element { - if i < 0 || i >= v.nelem { - panic("Vector.At(", i, ") out of range (size ", v.nelem, ")\n"); - return nil; + n := v.Len(); + if i < 0 || i >= n { + v.RangeError("At", i); + var e Element; + return e; // don't return nil - may not be legal in the future } return v.elem[i]; } + +// TODO(r) It would be better if this were called 'Remove' and if +// it were returning the removed element. This way it would be +// symmetric with 'Insert', provide the functionality of 'Delete' +// and allow to get the appropriate entry w/ an extra call. + func (v *Vector) Delete(i int) { - if i < 0 || i >= v.nelem { - panic("Delete out of range\n"); + n := v.Len(); + if i < 0 || i >= n { + v.RangeError("Delete", i); } - for j := i+1; j < v.nelem; j++ { - v.elem[j-1] = v.elem[j]; + for j := i + 1; j < n; j++ { + v.elem[j - 1] = v.elem[j]; } - v.nelem--; - v.elem[v.nelem] = nil; + var e Element; + v.elem[n - 1] = e; // don't set to nil - may not be legal in the future + v.elem = v.elem[0 : n - 1]; } + func (v *Vector) Insert(i int, e Element) { - if i > v.nelem { - panic("Del too large\n"); + n := v.Len(); + if i < 0 || i > n { + v.RangeError("Insert", i); } - if v.nelem == v.nalloc && is_pow10(v.nalloc) { - n := Alloc(v.nalloc * 10); - for j := 0; j < v.nalloc; j++ { - n[j] = v.elem[j]; + + // grow array by doubling its capacity + if n == cap(v.elem) { + a := new([]Element, n*2); + for j := 0; j < n; j++ { + a[j] = v.elem[j]; } - v.elem = n; - v.nalloc *= 10; + v.elem = a; } + // make a hole - for j := v.nelem; j > i; j-- { + v.elem = v.elem[0 : n + 1]; + for j := n; j > i; j-- { v.elem[j] = v.elem[j-1]; } + v.elem[i] = e; - v.nelem++; } + func (v *Vector) Append(e Element) { - v.Insert(v.nelem, e); + v.Insert(len(v.elem), e); } + /* type I struct { val int; }; // BUG: can't be local; diff --git a/test/vectors.go b/test/vectors.go new file mode 100644 index 000000000..d6a2015fe --- /dev/null +++ b/test/vectors.go @@ -0,0 +1,61 @@ +// $G $F.go && $L $F.$A && ./$A.out + +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import vector "vector" + + +type S struct { + val int +} + + +func (p *S) Init(val int) *S { + p.val = val; + return p; +} + + +func test0() { + v := vector.New(); + if v.Len() != 0 { + panic("len = ", v.Len(), "\n"); + } +} + + +func test1() { + var a [1000] *S; + for i := 0; i < len(a); i++ { + a[i] = new(S).Init(i); + } + + v := vector.New(); + for i := 0; i < len(a); i++ { + v.Insert(0, a[i]); + if v.Len() != i + 1 { + panic("len = ", v.Len(), "\n"); + } + } + + for i := 0; i < v.Len(); i++ { + x := convert(*S, v.At(i)); + if x.val != v.Len() - i - 1 { + panic("expected ", i, ", found ", x.val, "\n"); + } + } + + for v.Len() > 10 { + v.Delete(10); + } +} + + +func main() { + test0(); + test1(); +} |