mirror of
https://github.com/golang/go
synced 2024-11-21 18:24:46 -07:00
reflect: add Append and AppendSlice functions.
R=r, nigeltao_gnome, rog, niemeyer CC=golang-dev https://golang.org/cl/3529042
This commit is contained in:
parent
da1cbe5d11
commit
8b64cd9c5e
@ -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}
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user