diff options
Diffstat (limited to 'vendor/github.com/modern-go/reflect2/unsafe_slice.go')
-rw-r--r-- | vendor/github.com/modern-go/reflect2/unsafe_slice.go | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/vendor/github.com/modern-go/reflect2/unsafe_slice.go b/vendor/github.com/modern-go/reflect2/unsafe_slice.go new file mode 100644 index 0000000..1c6d876 --- /dev/null +++ b/vendor/github.com/modern-go/reflect2/unsafe_slice.go | |||
@@ -0,0 +1,177 @@ | |||
1 | package reflect2 | ||
2 | |||
3 | import ( | ||
4 | "reflect" | ||
5 | "unsafe" | ||
6 | ) | ||
7 | |||
8 | // sliceHeader is a safe version of SliceHeader used within this package. | ||
9 | type sliceHeader struct { | ||
10 | Data unsafe.Pointer | ||
11 | Len int | ||
12 | Cap int | ||
13 | } | ||
14 | |||
15 | type UnsafeSliceType struct { | ||
16 | unsafeType | ||
17 | elemRType unsafe.Pointer | ||
18 | pElemRType unsafe.Pointer | ||
19 | elemSize uintptr | ||
20 | } | ||
21 | |||
22 | func newUnsafeSliceType(cfg *frozenConfig, type1 reflect.Type) SliceType { | ||
23 | elemType := type1.Elem() | ||
24 | return &UnsafeSliceType{ | ||
25 | unsafeType: *newUnsafeType(cfg, type1), | ||
26 | pElemRType: unpackEFace(reflect.PtrTo(elemType)).data, | ||
27 | elemRType: unpackEFace(elemType).data, | ||
28 | elemSize: elemType.Size(), | ||
29 | } | ||
30 | } | ||
31 | |||
32 | func (type2 *UnsafeSliceType) Set(obj interface{}, val interface{}) { | ||
33 | objEFace := unpackEFace(obj) | ||
34 | assertType("Type.Set argument 1", type2.ptrRType, objEFace.rtype) | ||
35 | valEFace := unpackEFace(val) | ||
36 | assertType("Type.Set argument 2", type2.ptrRType, valEFace.rtype) | ||
37 | type2.UnsafeSet(objEFace.data, valEFace.data) | ||
38 | } | ||
39 | |||
40 | func (type2 *UnsafeSliceType) UnsafeSet(ptr unsafe.Pointer, val unsafe.Pointer) { | ||
41 | *(*sliceHeader)(ptr) = *(*sliceHeader)(val) | ||
42 | } | ||
43 | |||
44 | func (type2 *UnsafeSliceType) IsNil(obj interface{}) bool { | ||
45 | if obj == nil { | ||
46 | return true | ||
47 | } | ||
48 | objEFace := unpackEFace(obj) | ||
49 | assertType("Type.IsNil argument 1", type2.ptrRType, objEFace.rtype) | ||
50 | return type2.UnsafeIsNil(objEFace.data) | ||
51 | } | ||
52 | |||
53 | func (type2 *UnsafeSliceType) UnsafeIsNil(ptr unsafe.Pointer) bool { | ||
54 | if ptr == nil { | ||
55 | return true | ||
56 | } | ||
57 | return (*sliceHeader)(ptr).Data == nil | ||
58 | } | ||
59 | |||
60 | func (type2 *UnsafeSliceType) SetNil(obj interface{}) { | ||
61 | objEFace := unpackEFace(obj) | ||
62 | assertType("SliceType.SetNil argument 1", type2.ptrRType, objEFace.rtype) | ||
63 | type2.UnsafeSetNil(objEFace.data) | ||
64 | } | ||
65 | |||
66 | func (type2 *UnsafeSliceType) UnsafeSetNil(ptr unsafe.Pointer) { | ||
67 | header := (*sliceHeader)(ptr) | ||
68 | header.Len = 0 | ||
69 | header.Cap = 0 | ||
70 | header.Data = nil | ||
71 | } | ||
72 | |||
73 | func (type2 *UnsafeSliceType) MakeSlice(length int, cap int) interface{} { | ||
74 | return packEFace(type2.ptrRType, type2.UnsafeMakeSlice(length, cap)) | ||
75 | } | ||
76 | |||
77 | func (type2 *UnsafeSliceType) UnsafeMakeSlice(length int, cap int) unsafe.Pointer { | ||
78 | header := &sliceHeader{unsafe_NewArray(type2.elemRType, cap), length, cap} | ||
79 | return unsafe.Pointer(header) | ||
80 | } | ||
81 | |||
82 | func (type2 *UnsafeSliceType) LengthOf(obj interface{}) int { | ||
83 | objEFace := unpackEFace(obj) | ||
84 | assertType("SliceType.Len argument 1", type2.ptrRType, objEFace.rtype) | ||
85 | return type2.UnsafeLengthOf(objEFace.data) | ||
86 | } | ||
87 | |||
88 | func (type2 *UnsafeSliceType) UnsafeLengthOf(obj unsafe.Pointer) int { | ||
89 | header := (*sliceHeader)(obj) | ||
90 | return header.Len | ||
91 | } | ||
92 | |||
93 | func (type2 *UnsafeSliceType) SetIndex(obj interface{}, index int, elem interface{}) { | ||
94 | objEFace := unpackEFace(obj) | ||
95 | assertType("SliceType.SetIndex argument 1", type2.ptrRType, objEFace.rtype) | ||
96 | elemEFace := unpackEFace(elem) | ||
97 | assertType("SliceType.SetIndex argument 3", type2.pElemRType, elemEFace.rtype) | ||
98 | type2.UnsafeSetIndex(objEFace.data, index, elemEFace.data) | ||
99 | } | ||
100 | |||
101 | func (type2 *UnsafeSliceType) UnsafeSetIndex(obj unsafe.Pointer, index int, elem unsafe.Pointer) { | ||
102 | header := (*sliceHeader)(obj) | ||
103 | elemPtr := arrayAt(header.Data, index, type2.elemSize, "i < s.Len") | ||
104 | typedmemmove(type2.elemRType, elemPtr, elem) | ||
105 | } | ||
106 | |||
107 | func (type2 *UnsafeSliceType) GetIndex(obj interface{}, index int) interface{} { | ||
108 | objEFace := unpackEFace(obj) | ||
109 | assertType("SliceType.GetIndex argument 1", type2.ptrRType, objEFace.rtype) | ||
110 | elemPtr := type2.UnsafeGetIndex(objEFace.data, index) | ||
111 | return packEFace(type2.pElemRType, elemPtr) | ||
112 | } | ||
113 | |||
114 | func (type2 *UnsafeSliceType) UnsafeGetIndex(obj unsafe.Pointer, index int) unsafe.Pointer { | ||
115 | header := (*sliceHeader)(obj) | ||
116 | return arrayAt(header.Data, index, type2.elemSize, "i < s.Len") | ||
117 | } | ||
118 | |||
119 | func (type2 *UnsafeSliceType) Append(obj interface{}, elem interface{}) { | ||
120 | objEFace := unpackEFace(obj) | ||
121 | assertType("SliceType.Append argument 1", type2.ptrRType, objEFace.rtype) | ||
122 | elemEFace := unpackEFace(elem) | ||
123 | assertType("SliceType.Append argument 2", type2.pElemRType, elemEFace.rtype) | ||
124 | type2.UnsafeAppend(objEFace.data, elemEFace.data) | ||
125 | } | ||
126 | |||
127 | func (type2 *UnsafeSliceType) UnsafeAppend(obj unsafe.Pointer, elem unsafe.Pointer) { | ||
128 | header := (*sliceHeader)(obj) | ||
129 | oldLen := header.Len | ||
130 | type2.UnsafeGrow(obj, oldLen+1) | ||
131 | type2.UnsafeSetIndex(obj, oldLen, elem) | ||
132 | } | ||
133 | |||
134 | func (type2 *UnsafeSliceType) Cap(obj interface{}) int { | ||
135 | objEFace := unpackEFace(obj) | ||
136 | assertType("SliceType.Cap argument 1", type2.ptrRType, objEFace.rtype) | ||
137 | return type2.UnsafeCap(objEFace.data) | ||
138 | } | ||
139 | |||
140 | func (type2 *UnsafeSliceType) UnsafeCap(ptr unsafe.Pointer) int { | ||
141 | return (*sliceHeader)(ptr).Cap | ||
142 | } | ||
143 | |||
144 | func (type2 *UnsafeSliceType) Grow(obj interface{}, newLength int) { | ||
145 | objEFace := unpackEFace(obj) | ||
146 | assertType("SliceType.Grow argument 1", type2.ptrRType, objEFace.rtype) | ||
147 | type2.UnsafeGrow(objEFace.data, newLength) | ||
148 | } | ||
149 | |||
150 | func (type2 *UnsafeSliceType) UnsafeGrow(obj unsafe.Pointer, newLength int) { | ||
151 | header := (*sliceHeader)(obj) | ||
152 | if newLength <= header.Cap { | ||
153 | header.Len = newLength | ||
154 | return | ||
155 | } | ||
156 | newCap := calcNewCap(header.Cap, newLength) | ||
157 | newHeader := (*sliceHeader)(type2.UnsafeMakeSlice(header.Len, newCap)) | ||
158 | typedslicecopy(type2.elemRType, *newHeader, *header) | ||
159 | header.Data = newHeader.Data | ||
160 | header.Cap = newHeader.Cap | ||
161 | header.Len = newLength | ||
162 | } | ||
163 | |||
164 | func calcNewCap(cap int, expectedCap int) int { | ||
165 | if cap == 0 { | ||
166 | cap = expectedCap | ||
167 | } else { | ||
168 | for cap < expectedCap { | ||
169 | if cap < 1024 { | ||
170 | cap += cap | ||
171 | } else { | ||
172 | cap += cap / 4 | ||
173 | } | ||
174 | } | ||
175 | } | ||
176 | return cap | ||
177 | } | ||