-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdict.go
112 lines (99 loc) · 2.48 KB
/
dict.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
package gp
/*
#include <Python.h>
typedef struct pyCriticalSection {
uintptr_t _cs_prev;
void *_cs_mutex;
} pyCriticalSection;
static inline void pyCriticalSection_Begin(pyCriticalSection *pcs, PyObject *op) {
#if PY_VERSION_HEX >= 0x030D0000
PyCriticalSection_Begin((PyCriticalSection*)pcs, op);
#else
PyGILState_STATE gstate = PyGILState_Ensure();
pcs->_cs_prev = (uintptr_t)gstate;
#endif
}
static inline void pyCriticalSection_End(pyCriticalSection *pcs) {
#if PY_VERSION_HEX >= 0x030D0000
PyCriticalSection_End((PyCriticalSection*)pcs);
#else
PyGILState_Release((PyGILState_STATE)pcs->_cs_prev);
#endif
}
*/
import "C"
import (
"fmt"
"unsafe"
)
type Dict struct {
Object
}
func newDict(obj *cPyObject) Dict {
return Dict{newObject(obj)}
}
func DictFromPairs(pairs ...any) Dict {
check(len(pairs)%2 == 0, "DictFromPairs requires an even number of arguments")
dict := newDict(C.PyDict_New())
for i := 0; i < len(pairs); i += 2 {
key := From(pairs[i])
value := From(pairs[i+1])
dict.Set(key, value)
}
return dict
}
func MakeDict(m map[any]any) Dict {
dict := newDict(C.PyDict_New())
for key, value := range m {
keyObj := From(key)
valueObj := From(value)
dict.Set(keyObj, valueObj)
}
return dict
}
func (d Dict) HasKey(key any) bool {
keyObj := From(key)
return C.PyDict_Contains(d.obj, keyObj.obj) != 0
}
func (d Dict) Get(key Objecter) Object {
v := C.PyDict_GetItem(d.obj, key.cpyObj())
C.Py_IncRef(v)
return newObject(v)
}
func (d Dict) Set(key, value Objecter) {
keyObj := key.cpyObj()
valueObj := value.cpyObj()
C.PyDict_SetItem(d.obj, keyObj, valueObj)
}
func (d Dict) SetString(key string, value Objecter) {
valueObj := value.cpyObj()
ckey := AllocCStr(key)
r := C.PyDict_SetItemString(d.obj, ckey, valueObj)
C.free(unsafe.Pointer(ckey))
check(r == 0, fmt.Sprintf("failed to set item string: %v", r))
}
func (d Dict) GetString(key string) Object {
ckey := AllocCStr(key)
v := C.PyDict_GetItemString(d.obj, ckey)
C.Py_IncRef(v)
C.free(unsafe.Pointer(ckey))
return newObject(v)
}
func (d Dict) Del(key Objecter) {
C.PyDict_DelItem(d.obj, key.cpyObj())
}
func (d Dict) Items() func(func(Object, Object) bool) {
obj := d.cpyObj()
var cs C.pyCriticalSection
C.pyCriticalSection_Begin(&cs, obj)
return func(fn func(Object, Object) bool) {
defer C.pyCriticalSection_End(&cs)
var pos C.Py_ssize_t
var key, value *C.PyObject
for C.PyDict_Next(obj, &pos, &key, &value) == 1 {
if !fn(newObject(key), newObject(value)) {
return
}
}
}
}