1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
9 // Swapper returns a function that swaps the elements in the provided
12 // Swapper panics if the provided interface is not a slice.
13 func Swapper(slice
interface{}) func(i
, j
int) {
15 if v
.Kind() != Slice
{
16 panic(&ValueError
{Method
: "Swapper", Kind
: v
.Kind()})
18 // Fast path for slices of size 0 and 1. Nothing to swap.
21 return func(i
, j
int) { panic("reflect: slice index out of range") }
23 return func(i
, j
int) {
25 panic("reflect: slice index out of range")
30 typ
:= v
.Type().Elem().(*rtype
)
32 hasPtr
:= typ
.kind
&kindNoPointers
== 0
34 // Some common & small cases, without using memmove:
37 ps
:= *(*[]unsafe
.Pointer
)(v
.ptr
)
38 return func(i
, j
int) { ps
[i
], ps
[j
] = ps
[j
], ps
[i
] }
40 if typ
.Kind() == String
{
41 ss
:= *(*[]string)(v
.ptr
)
42 return func(i
, j
int) { ss
[i
], ss
[j
] = ss
[j
], ss
[i
] }
47 is
:= *(*[]int64)(v
.ptr
)
48 return func(i
, j
int) { is
[i
], is
[j
] = is
[j
], is
[i
] }
50 is
:= *(*[]int32)(v
.ptr
)
51 return func(i
, j
int) { is
[i
], is
[j
] = is
[j
], is
[i
] }
53 is
:= *(*[]int16)(v
.ptr
)
54 return func(i
, j
int) { is
[i
], is
[j
] = is
[j
], is
[i
] }
56 is
:= *(*[]int8)(v
.ptr
)
57 return func(i
, j
int) { is
[i
], is
[j
] = is
[j
], is
[i
] }
61 s
:= (*sliceHeader
)(v
.ptr
)
62 tmp
:= unsafe_New(typ
) // swap scratch space
64 return func(i
, j
int) {
65 if uint(i
) >= uint(s
.Len
) ||
uint(j
) >= uint(s
.Len
) {
66 panic("reflect: slice index out of range")
68 val1
:= arrayAt(s
.Data
, i
, size
)
69 val2
:= arrayAt(s
.Data
, j
, size
)
70 typedmemmove(typ
, tmp
, val1
)
71 typedmemmove(typ
, val1
, val2
)
72 typedmemmove(typ
, val2
, tmp
)