--- al.c 2002/10/23 16:49:29 1.31
+++ al.c 2002/10/25 13:29:02 1.32
@@ -611,7 +611,7 @@
al_splice(al_t *al, size_t off, size_t n, al_t *nal, al_t *tal)
{
al_rc_t rc;
- al_chunk_t *cur, *next, *ins, *splitbuf;
+ al_chunk_t *cur, *start, *end, *next, *ins, *splitbuf;
size_t pos, skip, len, step;
int doinsert;
@@ -730,12 +730,14 @@
}
else {
/*
- * the whole chunk has to be moved, simply move it
- * to the target chain
+ * the whole chunk has to be moved,
+ *
+ * scan ahead for more such chunks to unlink
+ * and relink a whole chain in a single operation
+ *
+ * move the chunks to the target chain
* manual accounting for total size
*/
- step = len;
- REMOVE(al, chunks, cur);
/*
* when the insertion chunk is removed, we have to adjust
@@ -745,14 +747,32 @@
* next pointer and the insertion method switches to append
* mode
*/
+
+ step = len;
+ start = cur;
+ end = cur;
+
if (cur == ins)
ins = next;
+ while (next && step + (len = AL_CHUNK_LEN(next)) <= n) {
+ step += len;
+ end = next;
+ next = NEXT(next, chunks);
+ if (end == ins)
+ ins = next;
+ }
+ REMOVE2(al, chunks, start, end);
+
al->bytes -= step;
- if (tal == NULL)
- dispose_chunk(al, cur);
- else {
- ADDTAIL(tal, chunks, cur);
+ if (tal == NULL) {
+ do {
+ cur = start;
+ start = NEXT(cur, chunks);
+ dispose_chunk(al, cur);
+ } while (cur != end);
+ } else {
+ ADDTAIL2(tal, chunks, start, end);
tal->bytes += step;
}
}
|