-
Notifications
You must be signed in to change notification settings - Fork 0
/
value.go
135 lines (120 loc) · 2.84 KB
/
value.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package reflect
import (
"reflect"
"unsafe"
)
const (
FlagKindWidth = 5 // there are 27 kinds
FlagKindMask Flag = 1<<FlagKindWidth - 1
FlagStickyRO Flag = 1 << 5
FlagEmbedRO Flag = 1 << 6
FlagIndir Flag = 1 << 7
FlagAddr Flag = 1 << 8
FlagMethod Flag = 1 << 9
FlagMethodShift = 10
FlagRO Flag = FlagStickyRO | FlagEmbedRO
)
var (
e = Eface{Type: new(Type)}
PtrOffset = func() uintptr {
return unsafe.Offsetof(e.Value)
}()
KindOffset = func() uintptr { return unsafe.Offsetof(e.Type.KindFlags) }()
ElemOffset = func() uintptr {
return unsafe.Offsetof(new(PtrType).Elem)
}()
SliceDataOffset = func() uintptr {
return unsafe.Offsetof(new(reflect.SliceHeader).Data)
}()
)
// DereferenceValue dereference and unpack interface,
// get the underlying non-pointer and non-interface value.
func DerefValue(v reflect.Value) reflect.Value {
for {
kind := v.Kind()
if kind == reflect.Ptr || kind == reflect.Interface {
if ev := v.Elem(); ev.IsValid() {
v = ev
} else {
return v
}
} else {
return v
}
}
}
// DerefPtrValue returns the underlying non-pointer type value.
func DerefPtrValue(v reflect.Value) reflect.Value {
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
return v
}
// DerefInterfaceValue returns the value of the underlying type that implements the interface v.
func DerefInterfaceValue(v reflect.Value) reflect.Value {
for v.Kind() == reflect.Interface {
if ev := v.Elem(); ev.IsValid() {
v = ev
} else {
return v
}
}
return v
}
func InitPtr(v reflect.Value) reflect.Value {
for v.Kind() == reflect.Pointer {
if !v.IsValid() || v.IsNil() {
v.Set(reflect.New(v.Type().Elem()))
}
v = v.Elem()
}
return v
}
//go:nocheckptr
func ValueOf(v interface{}) Value {
stdValue := reflect.ValueOf(v)
return *(*Value)(unsafe.Pointer(&stdValue))
}
//go:nocheckptr
func ConvertValue(v reflect.Value) Value {
return *(*Value)(unsafe.Pointer(&v))
}
//go:nocheckptr
func getFlag(typPtr uintptr) Flag {
if unsafe.Pointer(typPtr) == nil {
return 0
}
return *(*Flag)(unsafe.Pointer(typPtr + KindOffset))
}
//go:nocheckptr
func pointerElem(p unsafe.Pointer) unsafe.Pointer {
return *(*unsafe.Pointer)(p)
}
// Pointer gets the pointer of i.
// NOTE:
//
// *T and T, gets diffrent pointer
//
//go:nocheckptr
func (v Value) Pointer() uintptr {
switch v.Kind() {
case reflect.Invalid:
return 0
case reflect.Slice:
return uintptrElem(uintptr(v.Ptr)) + SliceDataOffset
default:
return uintptr(v.Ptr)
}
}
// Kind gets the reflect.Kind fastly.
func (v Value) Kind() reflect.Kind {
return reflect.Kind(v.Flag & FlagKindMask)
}
//go:nocheckptr
func uintptrElem(ptr uintptr) uintptr {
return *(*uintptr)(unsafe.Pointer(ptr))
}
// todo
func rangeValue(v reflect.Value, callbacks [reflect.UnsafePointer]func(reflect.Value) reflect.Value) {
callbacks[v.Kind()](v)
}