Index: apps/buffering.c =================================================================== --- apps/buffering.c (revision 23172) +++ apps/buffering.c (working copy) @@ -403,9 +403,13 @@ { struct memory_handle *dest; const struct memory_handle *src; + char *here; + char *there; + size_t oldpos; size_t newpos; size_t size_to_move; size_t final_delta = *delta; + size_t n; int overlap; if (h == NULL || (src = *h) == NULL) @@ -423,22 +427,24 @@ mutex_lock(&llist_mutex); mutex_lock(&llist_mod_mutex); - newpos = RINGBUF_ADD((void *)src - (void *)buffer, final_delta); - overlap = RINGBUF_ADD_CROSS(newpos, size_to_move, buffer_len - 1); + oldpos = (void *)src - (void *)buffer; + newpos = RINGBUF_ADD(oldpos, final_delta); + overlap = RINGBUF_ADD_CROSS(newpos, size_to_move , buffer_len -1); if (overlap > 0) { /* Some part of the struct + data would wrap, maybe ok */ size_t correction = 0; - /* If the overlap lands inside the memory_handle */ - if ((unsigned)overlap > data_size) { + if (!can_wrap) { + /* The overlap falls in the data area or memory_handle struct and + must all be backed out */ + correction = overlap; + } + /* If the overlap lands inside the memory_handle and wrapping + allowed */ + else if ((unsigned)overlap > data_size) { /* Correct the position and real delta to prevent the struct from * wrapping, this guarantees an aligned delta, I think */ correction = overlap - data_size; - } else if (!can_wrap) { - /* Otherwise the overlap falls in the data area and must all be - * backed out. This may become conditional if ever we move - * data that is allowed to wrap (ie audio) */ - correction = overlap; /* Align correction to four bytes, up */ correction = (correction+3) & ~3; } @@ -484,13 +490,18 @@ if (src == cur_handle) cur_handle = dest; - if (overlap > 0) { - size_t first_part = size_to_move - overlap; - memmove(dest, src, first_part); - memmove(buffer, (const char *)src + first_part, overlap); - } else { - memmove(dest, src, size_to_move); + here = buffer + RINGBUF_ADD(oldpos, size_to_move - 1); + there = buffer + RINGBUF_ADD(newpos, size_to_move - 1); + n = size_to_move; + + while (n--) { + if (here < buffer) + here += buffer_len; + if (there < buffer) + there += buffer_len; + *there-- = *here--; } + /* Update the caller with the new location of h and the distance moved */ *h = dest;