Skip to content

Commit 60f7768

Browse files
committed
Implemented everything about the merging of the bases into the topmost delta list. Its not yet working, but at least its not crashing
1 parent 166e538 commit 60f7768

File tree

1 file changed

+101
-9
lines changed

1 file changed

+101
-9
lines changed

_fun.c

Lines changed: 101 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ typedef unsigned int uint;
9191
typedef unsigned char uchar;
9292
typedef uchar bool;
9393

94+
// Constants
95+
const ull gDVC_grow_by = 50;
96+
9497
// DELTA CHUNK
9598
////////////////
9699
// Internal Delta Chunk Objects
@@ -277,10 +280,17 @@ DeltaChunk* DCV_get(DeltaChunkVector* vec, Py_ssize_t i)
277280
return &vec->mem[i];
278281
}
279282

283+
// Return last item
284+
inline
285+
DeltaChunk* DCV_last(DeltaChunkVector* vec)
286+
{
287+
return DCV_get(vec, vec->size-1);
288+
}
289+
280290
inline
281291
ull DCV_rbound(DeltaChunkVector* vec)
282292
{
283-
return DC_rbound(DCV_get(vec, vec->size-1));
293+
return DC_rbound(DCV_last(vec));
284294
}
285295

286296
inline
@@ -371,14 +381,41 @@ static inline
371381
DeltaChunk* DCV_append(DeltaChunkVector* vec)
372382
{
373383
if (vec->size + 1 > vec->reserved_size){
374-
DCV_grow_by(vec, 1);
384+
DCV_grow_by(vec, gDVC_grow_by);
375385
}
376386

377387
DeltaChunk* next = vec->mem + vec->size;
378388
vec->size += 1;
379389
return next;
380390
}
381391

392+
// Return delta chunk being closest to the given absolute offset
393+
inline
394+
DeltaChunk* DCV_closest_chunk(DeltaChunkVector* vec, ull ofs)
395+
{
396+
assert(vec->mem);
397+
398+
ull lo = 0;
399+
ull hi = vec->size;
400+
ull mid;
401+
DeltaChunk* dc;
402+
403+
while (lo < hi)
404+
{
405+
mid = (lo + hi) / 2;
406+
dc = vec->mem + mid;
407+
if (dc->to > ofs){
408+
hi = mid;
409+
} else if ((DC_rbound(dc) > ofs) | (dc->to == ofs)) {
410+
return dc;
411+
} else {
412+
lo = mid + 1;
413+
}
414+
}
415+
416+
return DCV_last(vec);
417+
}
418+
382419
// Write a slice as defined by its absolute offset in bytes and its size into the given
383420
// destination. The individual chunks written will be a deep copy of the source
384421
// data chunks
@@ -387,14 +424,67 @@ DeltaChunk* DCV_append(DeltaChunkVector* vec)
387424
inline
388425
void DCV_copy_slice_to(DeltaChunkVector* src, DeltaChunkVector* dest, ull ofs, ull size)
389426
{
427+
assert(DCV_lbound(src) <= ofs);
428+
assert(DCV_rbound(src) <= ofs + size);
390429

430+
DeltaChunk* cdc = DCV_closest_chunk(src, ofs);
431+
432+
// partial overlap
433+
if (cdc->to != ofs) {
434+
DeltaChunk* destc = DCV_append(dest);
435+
const ull relofs = ofs - cdc->to;
436+
DC_offset_copy_to(cdc, destc, relofs, cdc->ts - relofs < size ? cdc->ts - relofs : size);
437+
cdc += 1;
438+
size -= destc->ts;
439+
440+
if (size == 0){
441+
return;
442+
}
443+
}
444+
445+
DeltaChunk* vecend = DCV_end(src);
446+
for( ;(cdc < vecend) && size; ++cdc)
447+
{
448+
if (cdc->ts < size) {
449+
DC_copy_to(cdc, DCV_append(dest));
450+
size -= cdc->ts;
451+
} else {
452+
DC_offset_copy_to(cdc, DCV_append(dest), 0, size);
453+
size = 0;
454+
break;
455+
}
456+
}
457+
458+
assert(size == 0);
391459
}
392460

393461

462+
// Insert all chunks in 'from' to 'to', starting at the delta chunk named 'at' which
463+
// originates in to
464+
// 'at' will be replaced by the items to insert ( special purpose )
465+
// 'at' will be properly destroyed, but all items will just be copied bytewise
466+
// using memcpy. Hence from must just forget about them !
467+
inline
468+
void DCV_replace_one_by_many(DeltaChunkVector* from, DeltaChunkVector* to, DeltaChunk* at)
469+
{
470+
assert(from->size > 1);
471+
472+
DCV_reserve_memory(to, to->size + from->size - 1); // -1 because we replace at
473+
DC_destroy(at);
474+
to->size -= 1 + from->size;
475+
476+
// If we are somewhere in the middle, we have to make some space
477+
if (DCV_last(to) != at) {
478+
memmove((void*)at+from->size, (void*)(at+1), (size_t)(DCV_end(to) - (at+1)));
479+
}
480+
481+
// Finally copy all the items in
482+
memcpy((void*) at, (void*)from->mem, from->size*sizeof(DeltaChunk));
483+
}
484+
394485
// Take slices of bdcv into the corresponding area of the tdcv, which is the topmost
395486
// delta to apply. tmpl is used as temporary space and must be initialzed and destroyed by the
396487
// caller
397-
static
398488
void DCV_connect_with_base(DeltaChunkVector* tdcv, DeltaChunkVector* bdcv, DeltaChunkVector* tmpl)
399489
{
400490
DeltaChunk* dc = tdcv->mem;
@@ -413,18 +503,20 @@ void DCV_connect_with_base(DeltaChunkVector* tdcv, DeltaChunkVector* bdcv, Delta
413503
// assert(tmpl->size);
414504

415505
// move target bounds
416-
DeltaChunk* cdc = tmpl->mem;
417-
DeltaChunk* cdcend = tmpl->mem + tmpl->size;
506+
DeltaChunk* tdc = tmpl->mem;
507+
DeltaChunk* tdcend = tmpl->mem + tmpl->size;
418508
const ull ofs = dc->to - dc->so;
419-
for(;cdc < cdcend; cdc++){
420-
cdc->to += ofs;
509+
for(;tdc < tdcend; tdc++){
510+
tdc->to += ofs;
421511
}
422512

423-
// insert slice into our list, replacing our current chunk
513+
// insert slice into our list
424514
if (tmpl->size == 1){
515+
// Its not data, so destroy is not really required, anyhow ...
516+
DC_destroy(dc);
425517
*dc = *DCV_get(tmpl, 0);
426518
} else {
427-
519+
DCV_replace_one_by_many(tmpl, tdcv, dc);
428520
}
429521

430522
// make sure the members will not be deallocated by the list

0 commit comments

Comments
 (0)