@@ -116,9 +116,9 @@ void DC_destroy(DeltaChunk* dc)
116116typedef struct {
117117 PyObject_HEAD
118118 // -----------
119- DeltaChunk * head ;
120- DeltaChunk * tail ;
119+ DeltaChunk * mem ;
121120 ull size ;
121+ ull reserved_size ;
122122
123123} DeltaChunkList ;
124124
@@ -127,22 +127,65 @@ ull DC_rbound(DeltaChunk* dc)
127127 return dc -> to + dc -> ts ;
128128}
129129
130+ static
131+ int DCL_new (DeltaChunkList * self , PyObject * args , PyObject * kwds )
132+ {
133+ self -> mem = NULL ; // Memory
134+ self -> size = 0 ; // Size in DeltaChunks
135+ self -> reserved_size = 0 ; // Reserve in DeltaChunks
136+ return 1 ;
137+ }
138+
139+ /*
140+ Grow the delta chunk list by the given amount of bytes.
141+ This may trigger a realloc, but will do nothing if the reserved size is already
142+ large enough.
143+ Return 1 on success, 0 on failure
144+ */
145+ static
146+ int DCL_grow (DeltaChunkList * self , ull num_dc )
147+ {
148+ const ull grow_by_chunks = (self -> size + num_dc ) - self -> reserved_size ;
149+ if (grow_by_chunks <= 0 ){
150+ return 1 ;
151+ }
152+
153+ if (self -> mem ){
154+ self -> mem = PyMem_Malloc (grow_by_chunks * sizeof (DeltaChunk ));
155+ } else {
156+ self -> mem = PyMem_Realloc (self -> mem , (self -> size + grow_by_chunks )* sizeof (DeltaChunk ));
157+ }
158+
159+ return self -> mem != NULL ;
160+ }
161+
130162
131163static
132164int DCL_init (DeltaChunkList * self , PyObject * args , PyObject * kwds )
133165{
134- ((DeltaChunkList * )self )-> head = NULL ;
135- return 1 ;
166+ if (PySequence_Size (args ) > 1 ){
167+ PyErr_SetString (PyExc_ValueError , "Zero or one arguments are allowed, providing the initial size of the queue in DeltaChunks" );
168+ return 0 ;
169+ }
170+
171+ ull init_size = 0 ;
172+ PyArg_ParseTuple (args , "K" , & init_size );
173+ if (init_size == 0 ){
174+ init_size = 125000 ;
175+ }
176+
177+ return DCL_grow (self , init_size );
136178}
137179
138180static
139181void DCL_dealloc (DeltaChunkList * self )
140182{
141183 // TODO: deallocate linked list
142- if (self -> head ){
143- self -> head = NULL ;
144- self -> tail = NULL ;
184+ if (self -> mem ){
185+ PyMem_Free (self -> mem );
145186 self -> size = 0 ;
187+ self -> reserved_size = 0 ;
188+ self -> mem = 0 ;
146189 }
147190}
148191
@@ -153,11 +196,18 @@ PyObject* DCL_len(PyObject* self)
153196}
154197
155198static
156- PyObject * DCL_rbound (DeltaChunkList * self )
199+ inline
200+ ull DCL_rbound (DeltaChunkList * self )
201+ {
202+ if (!self -> mem | !self -> size )
203+ return 0 ;
204+ return DC_rbound (& (self -> mem [self -> size - 1 ]));
205+ }
206+
207+ static
208+ PyObject * DCL_py_rbound (DeltaChunkList * self )
157209{
158- if (!self -> head )
159- return PyLong_FromUnsignedLongLong (0 );
160- return PyLong_FromUnsignedLongLong (DC_rbound (self -> tail ));
210+ return PyLong_FromUnsignedLongLong (DCL_rbound (self ));
161211}
162212
163213static
@@ -172,7 +222,7 @@ PyObject* DCL_apply(PyObject* self, PyObject* args)
172222static PyMethodDef DCL_methods [] = {
173223 {"apply" , (PyCFunction )DCL_apply , METH_VARARGS , "Apply the given iterable of delta streams" },
174224 {"__len__" , (PyCFunction )DCL_len , METH_NOARGS , NULL },
175- {"rbound" , (PyCFunction )DCL_rbound , METH_NOARGS , NULL },
225+ {"rbound" , (PyCFunction )DCL_py_rbound , METH_NOARGS , NULL },
176226 {NULL } /* Sentinel */
177227};
178228
@@ -215,7 +265,7 @@ static PyTypeObject DeltaChunkListType = {
215265 0 , /* tp_dictoffset */
216266 (initproc )DCL_init , /* tp_init */
217267 0 , /* tp_alloc */
218- 0 , /* tp_new */
268+ ( newfunc ) DCL_new , /* tp_new */
219269};
220270
221271
@@ -233,6 +283,7 @@ ull msb_size(const char* data, Py_ssize_t dlen, Py_ssize_t offset, Py_ssize_t* o
233283 }// END while in range
234284
235285 * out_bytes_read = i + offset ;
286+ assert ((* out_bytes_read * 8 ) - (* out_bytes_read - 1 ) <= sizeof (ull ));
236287 return size ;
237288}
238289
0 commit comments