Skip to content

Commit e98dfd6

Browse files
aykevldeadprogram
authored andcommitted
reflect: implement Value.Grow
This was added in Go 1.20 and becomes necessary for encoding/json in Go 1.21.
1 parent 9126b95 commit e98dfd6

File tree

2 files changed

+28
-8
lines changed

2 files changed

+28
-8
lines changed

src/reflect/all_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,8 @@ func TestFunctionValue(t *testing.T) {
790790
assert(t, v.Type().String(), "func()")
791791
}
792792
793+
*/
794+
793795
func TestGrow(t *testing.T) {
794796
v := ValueOf([]int(nil))
795797
shouldPanic("reflect.Value.Grow using unaddressable value", func() { v.Grow(0) })
@@ -857,8 +859,6 @@ func TestGrow(t *testing.T) {
857859
})
858860
}
859861

860-
*/
861-
862862
var appendTests = []struct {
863863
orig, extra []int
864864
}{

src/reflect/value.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,7 +1641,7 @@ func buflen(v Value) (unsafe.Pointer, uintptr) {
16411641
func sliceGrow(buf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr)
16421642

16431643
// extend slice to hold n new elements
1644-
func (v *Value) extendSlice(n int) {
1644+
func extendSlice(v Value, n int) sliceHeader {
16451645
if v.Kind() != Slice {
16461646
panic(&ValueError{Method: "extendSlice", Kind: v.Kind()})
16471647
}
@@ -1664,14 +1664,11 @@ func (v *Value) extendSlice(n int) {
16641664
ncap = old.cap
16651665
}
16661666

1667-
newslice := sliceHeader{
1667+
return sliceHeader{
16681668
data: nbuf,
16691669
len: nlen + uintptr(n),
16701670
cap: ncap,
16711671
}
1672-
1673-
v.flags = valueFlagExported
1674-
v.value = (unsafe.Pointer)(&newslice)
16751672
}
16761673

16771674
// Append appends the values x to a slice s and returns the resulting slice.
@@ -1681,7 +1678,9 @@ func Append(v Value, x ...Value) Value {
16811678
panic(&ValueError{Method: "Append", Kind: v.Kind()})
16821679
}
16831680
oldLen := v.Len()
1684-
v.extendSlice(len(x))
1681+
newslice := extendSlice(v, len(x))
1682+
v.flags = valueFlagExported
1683+
v.value = (unsafe.Pointer)(&newslice)
16851684
for i, xx := range x {
16861685
v.Index(oldLen + i).Set(xx)
16871686
}
@@ -1716,6 +1715,27 @@ func AppendSlice(s, t Value) Value {
17161715
}
17171716
}
17181717

1718+
// Grow increases the slice's capacity, if necessary, to guarantee space for
1719+
// another n elements. After Grow(n), at least n elements can be appended
1720+
// to the slice without another allocation.
1721+
//
1722+
// It panics if v's Kind is not a Slice or if n is negative or too large to
1723+
// allocate the memory.
1724+
func (v Value) Grow(n int) {
1725+
v.checkAddressable()
1726+
if n < 0 {
1727+
panic("reflect.Grow: negative length")
1728+
}
1729+
if v.Kind() != Slice {
1730+
panic(&ValueError{Method: "Grow", Kind: v.Kind()})
1731+
}
1732+
slice := (*sliceHeader)(v.value)
1733+
newslice := extendSlice(v, n)
1734+
// Only copy the new data and cap: the len remains unchanged.
1735+
slice.data = newslice.data
1736+
slice.cap = newslice.cap
1737+
}
1738+
17191739
//go:linkname hashmapStringSet runtime.hashmapStringSetUnsafePointer
17201740
func hashmapStringSet(m unsafe.Pointer, key string, value unsafe.Pointer)
17211741

0 commit comments

Comments
 (0)