]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: add Append and AppendSlice functions.
authorNigel Tao <nigeltao@golang.org>
Tue, 14 Dec 2010 21:50:08 +0000 (08:50 +1100)
committerNigel Tao <nigeltao@golang.org>
Tue, 14 Dec 2010 21:50:08 +0000 (08:50 +1100)
R=r, nigeltao_gnome, rog, niemeyer
CC=golang-dev
https://golang.org/cl/3529042

src/pkg/reflect/all_test.go
src/pkg/reflect/value.go

index aa831f3365c09a7e944ba71f43c871ae74f62be7..1652e173161983cb03fa0d3483194866d94508bf 100644 (file)
@@ -498,7 +498,54 @@ func TestFunctionValue(t *testing.T) {
        assert(t, v.Type().String(), "func()")
 }
 
-func TestCopyArray(t *testing.T) {
+var appendTests = []struct {
+       orig, extra []int
+}{
+       {make([]int, 2, 4), []int{22}},
+       {make([]int, 2, 4), []int{22, 33, 44}},
+}
+
+func TestAppend(t *testing.T) {
+       for i, test := range appendTests {
+               origLen, extraLen := len(test.orig), len(test.extra)
+               want := append(test.orig, test.extra...)
+               // Convert extra from []int to []Value.
+               e0 := make([]Value, len(test.extra))
+               for j, e := range test.extra {
+                       e0[j] = NewValue(e)
+               }
+               // Convert extra from []int to *SliceValue.
+               e1 := NewValue(test.extra).(*SliceValue)
+               // Test Append.
+               a0 := NewValue(test.orig).(*SliceValue)
+               have0 := Append(a0, e0...).Interface().([]int)
+               if !DeepEqual(have0, want) {
+                       t.Errorf("Append #%d: have %v, want %v", i, have0, want)
+               }
+               // Check that the orig and extra slices were not modified.
+               if len(test.orig) != origLen {
+                       t.Errorf("Append #%d origLen: have %v, want %v", i, len(test.orig), origLen)
+               }
+               if len(test.extra) != extraLen {
+                       t.Errorf("Append #%d extraLen: have %v, want %v", i, len(test.extra), extraLen)
+               }
+               // Test AppendSlice.
+               a1 := NewValue(test.orig).(*SliceValue)
+               have1 := AppendSlice(a1, e1).Interface().([]int)
+               if !DeepEqual(have1, want) {
+                       t.Errorf("AppendSlice #%d: have %v, want %v", i, have1, want)
+               }
+               // Check that the orig and extra slices were not modified.
+               if len(test.orig) != origLen {
+                       t.Errorf("AppendSlice #%d origLen: have %v, want %v", i, len(test.orig), origLen)
+               }
+               if len(test.extra) != extraLen {
+                       t.Errorf("AppendSlice #%d extraLen: have %v, want %v", i, len(test.extra), extraLen)
+               }
+       }
+}
+
+func TestCopy(t *testing.T) {
        a := []int{1, 2, 3, 4, 10, 9, 8, 7}
        b := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
        c := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
index 8b2c1a9530c74a1fed7e7d9dfe27bcfd8938161c..e0bcb1a39d46835d09d87e547f89c6d7487cc5c9 100644 (file)
@@ -400,6 +400,52 @@ type ArrayOrSliceValue interface {
        addr() addr
 }
 
+// grow grows the slice s so that it can hold extra more values, allocating
+// more capacity if needed. It also returns the old and new slice lengths.
+func grow(s *SliceValue, extra int) (*SliceValue, int, int) {
+       i0 := s.Len()
+       i1 := i0 + extra
+       if i1 < i0 {
+               panic("append: slice overflow")
+       }
+       m := s.Cap()
+       if i1 <= m {
+               return s.Slice(0, i1), i0, i1
+       }
+       if m == 0 {
+               m = extra
+       } else {
+               for m < i1 {
+                       if i0 < 1024 {
+                               m += m
+                       } else {
+                               m += m / 4
+                       }
+               }
+       }
+       t := MakeSlice(s.Type().(*SliceType), i1, m)
+       Copy(t, s)
+       return t, i0, i1
+}
+
+// Append appends the values x to a slice s and returns the resulting slice.
+// Each x must have the same type as s' element type.
+func Append(s *SliceValue, x ...Value) *SliceValue {
+       s, i0, i1 := grow(s, len(x))
+       for i, j := i0, 0; i < i1; i, j = i+1, j+1 {
+               s.Elem(i).SetValue(x[j])
+       }
+       return s
+}
+
+// AppendSlice appends a slice t to a slice s and returns the resulting slice.
+// The slices s and t must have the same element type.
+func AppendSlice(s, t *SliceValue) *SliceValue {
+       s, i0, i1 := grow(s, t.Len())
+       Copy(s.Slice(i0, i1), t)
+       return s
+}
+
 // Copy copies the contents of src into dst until either
 // dst has been filled or src has been exhausted.
 // It returns the number of elements copied.