Skip to content

Commit f563a9d

Browse files
committed
Fixed integrity check function, finalized code, so far it is working, and its very efficient as well as the amount of data-copies is minimized
1 parent 4098056 commit f563a9d

File tree

1 file changed

+65
-7
lines changed

1 file changed

+65
-7
lines changed

_fun.c

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ typedef uchar bool;
9595
const ull gDVC_grow_by = 50;
9696

9797
#ifdef DEBUG
98-
#define DBG_check(vec) DCV_dbg_check_integrity(vec)
98+
#define DBG_check(vec) asser(DCV_dbg_check_integrity(vec))
9999
#else
100100
#define DBG_check(vec)
101101
#endif
@@ -165,6 +165,26 @@ ull DC_rbound(const DeltaChunk* dc)
165165
return dc->to + dc->ts;
166166
}
167167

168+
// Apply
169+
inline
170+
void DC_apply(const DeltaChunk* dc, const uchar* base, PyObject* writer, PyObject* tmpargs)
171+
{
172+
PyObject* buffer = 0;
173+
if (dc->data){
174+
buffer = PyBuffer_FromMemory((void*)dc->data, dc->ts);
175+
} else {
176+
buffer = PyBuffer_FromMemory((void*)(base + dc->so), dc->ts);
177+
}
178+
179+
if (PyTuple_SetItem(tmpargs, 0, buffer)){
180+
assert(0);
181+
}
182+
183+
// tuple steals reference, and will take care about the deallocation
184+
PyObject_Call(writer, tmpargs, NULL);
185+
186+
}
187+
168188
// Copy all data from src to dest, the data pointer will be copied too
169189
inline
170190
void DC_copy_to(const DeltaChunk* src, DeltaChunk* dest)
@@ -423,9 +443,12 @@ DeltaChunk* DCV_closest_chunk(const DeltaChunkVector* vec, ull ofs)
423443
}
424444

425445
// Assert the given vector has correct datachunks
426-
void DCV_dbg_check_integrity(const DeltaChunkVector* vec)
446+
// return 1 on success
447+
int DCV_dbg_check_integrity(const DeltaChunkVector* vec)
427448
{
428-
assert(!DCV_empty(vec));
449+
if(DCV_empty(vec)){
450+
return 0;
451+
}
429452
const DeltaChunk* i = vec->mem;
430453
const DeltaChunk* end = DCV_end(vec);
431454

@@ -434,18 +457,22 @@ void DCV_dbg_check_integrity(const DeltaChunkVector* vec)
434457
for(; i < end; i++){
435458
acc_size += i->ts;
436459
}
437-
assert(acc_size == aparent_size);
460+
if (acc_size != aparent_size)
461+
return 0;
438462

439463
if (vec->size < 2){
440-
return;
464+
return 1;
441465
}
442466

443467
const DeltaChunk* endm1 = DCV_end(vec) - 1;
444468
for(i = vec->mem; i < endm1; i++){
445469
const DeltaChunk* n = i+1;
446-
assert(DC_rbound(i) == n->to);
470+
if (DC_rbound(i) != n->to){
471+
return 0;
472+
}
447473
}
448474

475+
return 1;
449476
}
450477

451478
// Write a slice as defined by its absolute offset in bytes and its size into the given
@@ -624,10 +651,41 @@ PyObject* DCL_py_rbound(DeltaChunkList* self)
624651
return PyLong_FromUnsignedLongLong(DCL_rbound(self));
625652
}
626653

654+
// Write using a write function, taking remaining bytes from a base buffer
627655
static
628-
PyObject* DCL_apply(PyObject* self, PyObject* args)
656+
PyObject* DCL_apply(DeltaChunkList* self, PyObject* args)
629657
{
658+
PyObject* pybuf = 0;
659+
PyObject* writeproc = 0;
660+
if (!PyArg_ParseTuple(args, "OO", &pybuf, &writeproc)){
661+
PyErr_BadArgument();
662+
return NULL;
663+
}
664+
665+
if (!PyObject_CheckReadBuffer(pybuf)){
666+
PyErr_SetString(PyExc_ValueError, "First argument must be a buffer-compatible object, like a string, or a memory map");
667+
return NULL;
668+
}
669+
670+
if (!PyCallable_Check(writeproc)){
671+
PyErr_SetString(PyExc_ValueError, "Second argument must be a writer method with signature write(buf)");
672+
return NULL;
673+
}
674+
675+
const DeltaChunk* i = self->vec.mem;
676+
const DeltaChunk* end = DCV_end(&self->vec);
677+
678+
const uchar* data;
679+
Py_ssize_t dlen;
680+
PyObject_AsReadBuffer(pybuf, (const void**)&data, &dlen);
681+
682+
PyObject* tmpargs = PyTuple_New(1);
683+
684+
for(; i < end; i++){
685+
DC_apply(i, data, writeproc, tmpargs);
686+
}
630687

688+
Py_DECREF(tmpargs);
631689
Py_RETURN_NONE;
632690
}
633691

0 commit comments

Comments
 (0)