-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathvar_store.go
91 lines (75 loc) · 2.58 KB
/
var_store.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
package sophia
import (
"reflect"
"unsafe"
)
// varStore manages memory allocation and free for C variables
// Interface for C sophia object
// Only for internal usage
type varStore struct {
// ptr Pointer to C sophia object
ptr unsafe.Pointer
// pointers slice of pointers to allocated C variables,
// that must be freed after store usage
pointers []unsafe.Pointer
}
func newVarStore(ptr unsafe.Pointer, size int) varStore {
ret := varStore{ptr: ptr}
if size > 0 {
ret.pointers = make([]unsafe.Pointer, 0, size)
}
return ret
}
func (s *varStore) IsEmpty() bool {
return s.ptr == nil
}
// TODO :: implement custom types
func (s *varStore) Set(path string, val interface{}) bool {
v := reflect.ValueOf(val)
switch v.Kind() {
case reflect.String:
return s.SetString(path, v.String())
case reflect.Int, reflect.Int64, reflect.Int8, reflect.Int16, reflect.Int32:
return s.SetInt(path, v.Int())
case reflect.Uint, reflect.Uint64, reflect.Uint8, reflect.Uint16, reflect.Uint32:
return s.SetInt(path, int64(v.Uint()))
}
cPath := getCStringFromCache(path)
size := int(reflect.TypeOf(val).Size())
return spSetString(s.ptr, cPath, (unsafe.Pointer)(reflect.ValueOf(val).Pointer()), size)
}
func (s *varStore) SetString(path, val string) bool {
cPath := getCStringFromCache(path)
cVal := cString(val)
s.pointers = append(s.pointers, unsafe.Pointer(cVal))
return spSetString(s.ptr, cPath, unsafe.Pointer(cVal), len(val))
}
func (s *varStore) SetInt(path string, val int64) bool {
return spSetInt(s.ptr, getCStringFromCache(path), val)
}
func (s *varStore) Get(path string, size *int) unsafe.Pointer {
return spGetString(s.ptr, getCStringFromCache(path), size)
}
// GetString returns string without extra allocations.
// We can use C pointer to string to make Go string without allocation.
// C memory will be freed on Document Destroy() call.
// So for long-term usage you should to make copy of string to avoid data corruption.
func (s *varStore) GetString(path string, size *int) string {
ptr := spGetString(s.ptr, getCStringFromCache(path), size)
sh := reflect.StringHeader{Data: uintptr(ptr), Len: *size}
return *(*string)(unsafe.Pointer(&sh))
}
func (s *varStore) GetObject(path string) unsafe.Pointer {
return spGetObject(s.ptr, getCStringFromCache(path))
}
func (s *varStore) GetInt(path string) int64 {
return spGetInt(s.ptr, getCStringFromCache(path))
}
// Free frees allocated memory for all C variables, that were in this store
// This always should be called to prevent memory leaks
func (s *varStore) Free() {
for _, f := range s.pointers {
free(f)
}
s.pointers = s.pointers[:0]
}