1
- from libc.stdlib cimport malloc, free
1
+ from libc.stdlib cimport calloc, free
2
+
3
+ cdef extern from " Python.h" :
4
+ ctypedef struct PyObject
5
+ int PyObject_GetBuffer(PyObject * exporter, Py_buffer * view, int flags)
6
+ void PyBuffer_Release(Py_buffer * view)
7
+ const int PyBUF_C_CONTIGUOUS
2
8
3
9
4
10
cdef class DoubleArray:
@@ -41,26 +47,45 @@ cdef class DoubleArray:
41
47
lengths = None ,
42
48
values = None ):
43
49
cdef size_t num_keys = len (keys)
44
- cdef const char ** _keys = < const char ** > malloc(num_keys * sizeof(char * ))
50
+ cdef const char ** _keys = NULL
51
+ cdef Py_buffer* _buf = NULL
45
52
cdef size_t * _lengths = NULL
46
53
cdef int * _values = NULL
47
- for i, key in enumerate (keys):
48
- _keys[i] = key
49
- if lengths is not None :
50
- _lengths = < size_t * > malloc(num_keys * sizeof(size_t))
51
- for i, length in enumerate (lengths):
52
- _lengths[i] = length
53
- if values is not None :
54
- _values = < int * > malloc(num_keys * sizeof(int ))
55
- for i, value in enumerate (values):
56
- _values[i] = value
54
+
57
55
try :
56
+ _keys = < const char ** > calloc(num_keys, sizeof(char * ))
57
+ if _keys == NULL :
58
+ raise MemoryError (" failed to allocate memory for key array" )
59
+ _buf = < Py_buffer * > calloc(num_keys, sizeof(Py_buffer))
60
+ if _buf == NULL :
61
+ raise MemoryError (" failed to allocate memory for buffer" )
62
+ for i, key in enumerate (keys):
63
+ if PyObject_GetBuffer(< PyObject * > key, & _buf[i], PyBUF_C_CONTIGUOUS) < 0 :
64
+ return
65
+ _keys[i] = < const char * > _buf[i].buf
66
+ if lengths is not None :
67
+ _lengths = < size_t * > calloc(num_keys, sizeof(size_t))
68
+ if _lengths == NULL :
69
+ raise MemoryError (" failed to allocate memory for length array" )
70
+ for i, length in enumerate (lengths):
71
+ _lengths[i] = length
72
+ if values is not None :
73
+ _values = < int * > calloc(num_keys, sizeof(int ))
74
+ if _values == NULL :
75
+ raise MemoryError (" failed to allocate memory for value array" )
76
+ for i, value in enumerate (values):
77
+ _values[i] = value
58
78
self .wrapped.build(num_keys, _keys, < const size_t* > _lengths, < const int * > _values, NULL )
59
79
finally :
60
- free(_keys)
61
- if lengths is not None :
80
+ if _keys != NULL :
81
+ free(_keys)
82
+ if _buf != NULL :
83
+ for i in range (num_keys):
84
+ PyBuffer_Release(& _buf[i])
85
+ free(_buf)
86
+ if _lengths != NULL :
62
87
free(_lengths)
63
- if values is not None :
88
+ if _values ! = NULL :
64
89
free(_values)
65
90
66
91
def open (self , file_name ,
@@ -88,39 +113,66 @@ cdef class DoubleArray:
88
113
size_t length = 0 ,
89
114
size_t node_pos = 0 ,
90
115
pair_type = True ):
91
- cdef const char * _key = key
92
- if pair_type:
93
- return self .__exact_match_search_pair_type(_key, length, node_pos)
94
- else :
95
- return self .__exact_match_search(_key, length, node_pos)
116
+ cdef Py_buffer buf
117
+ if PyObject_GetBuffer(< PyObject * > key, & buf, PyBUF_C_CONTIGUOUS) < 0 :
118
+ return
119
+ try :
120
+ if length == 0 :
121
+ if buf.len == 0 :
122
+ raise ValueError (" buffer cannot be empty" )
123
+ length = buf.len
124
+ if pair_type:
125
+ return self .__exact_match_search_pair_type(< const char * > buf.buf, length, node_pos)
126
+ else :
127
+ return self .__exact_match_search(< const char * > buf.buf, length, node_pos)
128
+ finally :
129
+ PyBuffer_Release(& buf)
96
130
97
131
def common_prefix_search (self , key ,
98
132
size_t max_num_results = 0 ,
99
133
size_t length = 0 ,
100
134
size_t node_pos = 0 ,
101
135
pair_type = True ):
102
- cdef const char * _key = key
103
- if max_num_results == 0 :
104
- max_num_results = len (key)
105
- if pair_type:
106
- return self .__common_prefix_search_pair_type(_key, max_num_results, length, node_pos)
107
- else :
108
- return self .__common_prefix_search(_key, max_num_results, length, node_pos)
136
+ cdef Py_buffer buf
137
+ if PyObject_GetBuffer(< PyObject * > key, & buf, PyBUF_C_CONTIGUOUS) < 0 :
138
+ return
139
+ try :
140
+ if length == 0 :
141
+ if buf.len == 0 :
142
+ raise ValueError (" buffer cannot be empty" )
143
+ length = buf.len
144
+ if max_num_results == 0 :
145
+ max_num_results = len (key)
146
+ if pair_type:
147
+ return self .__common_prefix_search_pair_type(< const char * > buf.buf, max_num_results, length, node_pos)
148
+ else :
149
+ return self .__common_prefix_search(< const char * > buf.buf, max_num_results, length, node_pos)
150
+ finally :
151
+ PyBuffer_Release(& buf)
109
152
110
153
def traverse (self , key ,
111
154
size_t node_pos ,
112
155
size_t key_pos ,
113
156
size_t length = 0 ):
114
- cdef const char * _key = key
157
+ cdef Py_buffer buf
115
158
cdef int result
116
- with nogil:
117
- result = self .wrapped.traverse(_key, node_pos, key_pos, length)
118
- return result
159
+ if PyObject_GetBuffer(< PyObject * > key, & buf, PyBUF_C_CONTIGUOUS) < 0 :
160
+ return
161
+ try :
162
+ if length == 0 :
163
+ if buf.len == 0 :
164
+ raise ValueError (" buffer cannot be empty" )
165
+ length = buf.len
166
+ with nogil:
167
+ result = self .wrapped.traverse(< const char * > buf.buf, node_pos, key_pos, length)
168
+ return result
169
+ finally :
170
+ PyBuffer_Release(& buf)
119
171
120
172
def __exact_match_search (self , const char *key ,
121
173
size_t length = 0 ,
122
174
size_t node_pos = 0 ):
123
- cdef int result
175
+ cdef int result = 0
124
176
with nogil:
125
177
self .wrapped.exact_match_search(key, result, length, node_pos)
126
178
return result
@@ -137,7 +189,7 @@ cdef class DoubleArray:
137
189
size_t max_num_results ,
138
190
size_t length ,
139
191
size_t node_pos ):
140
- cdef int * results = < int * > malloc (max_num_results * sizeof(int ))
192
+ cdef int * results = < int * > calloc (max_num_results, sizeof(int ))
141
193
cdef int result_len
142
194
try :
143
195
with nogil:
@@ -153,7 +205,7 @@ cdef class DoubleArray:
153
205
size_t max_num_results ,
154
206
size_t length ,
155
207
size_t node_pos ):
156
- cdef result_pair_type * results = < result_pair_type * > malloc (max_num_results * sizeof(result_pair_type))
208
+ cdef result_pair_type * results = < result_pair_type * > calloc (max_num_results, sizeof(result_pair_type))
157
209
cdef result_pair_type result
158
210
cdef int result_len
159
211
try :
0 commit comments