src/buffer.c

changeset 1028
3e4905241838
parent 1024
8f99f6c28bd3
child 1030
06091e067bee
equal deleted inserted replaced
1027:b1373253e202 1028:3e4905241838
29 #include "cx/buffer.h" 29 #include "cx/buffer.h"
30 30
31 #include <stdio.h> 31 #include <stdio.h>
32 #include <string.h> 32 #include <string.h>
33 33
34 static int buffer_copy_on_write(CxBuffer* buffer, size_t newcap) { 34 static int buffer_copy_on_write(CxBuffer* buffer) {
35 if (0 == (buffer->flags & CX_BUFFER_COPY_ON_WRITE)) return 0; 35 if (0 == (buffer->flags & CX_BUFFER_COPY_ON_WRITE)) return 0;
36 if (newcap == 0) newcap = buffer->capacity; 36 void *newspace = cxMalloc(buffer->allocator, buffer->capacity);
37 void *newspace = cxMalloc(buffer->allocator, newcap);
38 if (NULL == newspace) return -1; 37 if (NULL == newspace) return -1;
39 memcpy(newspace, buffer->space, buffer->size); 38 memcpy(newspace, buffer->space, buffer->size);
40 buffer->space = newspace; 39 buffer->space = newspace;
41 buffer->capacity = newcap;
42 buffer->flags &= ~CX_BUFFER_COPY_ON_WRITE; 40 buffer->flags &= ~CX_BUFFER_COPY_ON_WRITE;
43 buffer->flags |= CX_BUFFER_FREE_CONTENTS; 41 buffer->flags |= CX_BUFFER_FREE_CONTENTS;
44 return 0; 42 return 0;
45 } 43 }
46 44
51 const CxAllocator *allocator, 49 const CxAllocator *allocator,
52 int flags 50 int flags
53 ) { 51 ) {
54 if (allocator == NULL) { 52 if (allocator == NULL) {
55 allocator = cxDefaultAllocator; 53 allocator = cxDefaultAllocator;
54 }
55 if (flags & CX_BUFFER_COPY_ON_EXTEND) {
56 flags |= CX_BUFFER_AUTO_EXTEND;
56 } 57 }
57 buffer->allocator = allocator; 58 buffer->allocator = allocator;
58 buffer->flags = flags; 59 buffer->flags = flags;
59 if (!space) { 60 if (!space) {
60 buffer->bytes = cxMalloc(allocator, capacity); 61 buffer->bytes = cxMalloc(allocator, capacity);
168 ) { 169 ) {
169 if (newcap <= buffer->capacity) { 170 if (newcap <= buffer->capacity) {
170 return 0; 171 return 0;
171 } 172 }
172 173
173 if (buffer->flags & CX_BUFFER_COPY_ON_WRITE) { 174 const int force_copy_flags = CX_BUFFER_COPY_ON_WRITE | CX_BUFFER_COPY_ON_EXTEND;
174 return buffer_copy_on_write(buffer, newcap); 175 if (buffer->flags & force_copy_flags) {
176 void *newspace = cxMalloc(buffer->allocator, newcap);
177 if (NULL == newspace) return -1;
178 memcpy(newspace, buffer->space, buffer->size);
179 buffer->space = newspace;
180 buffer->capacity = newcap;
181 buffer->flags &= ~force_copy_flags;
182 buffer->flags |= CX_BUFFER_FREE_CONTENTS;
183 return 0;
175 } else if (cxReallocate(buffer->allocator, 184 } else if (cxReallocate(buffer->allocator,
176 (void **) &buffer->bytes, newcap) == 0) { 185 (void **) &buffer->bytes, newcap) == 0) {
177 buffer->capacity = newcap; 186 buffer->capacity = newcap;
178 return 0; 187 return 0;
179 } else { 188 } else {
222 size_t nitems, 231 size_t nitems,
223 CxBuffer *buffer 232 CxBuffer *buffer
224 ) { 233 ) {
225 // optimize for easy case 234 // optimize for easy case
226 if (size == 1 && (buffer->capacity - buffer->pos) >= nitems) { 235 if (size == 1 && (buffer->capacity - buffer->pos) >= nitems) {
227 if (buffer_copy_on_write(buffer, 0)) return 0; 236 if (buffer_copy_on_write(buffer)) return 0;
228 memcpy(buffer->bytes + buffer->pos, ptr, nitems); 237 memcpy(buffer->bytes + buffer->pos, ptr, nitems);
229 buffer->pos += nitems; 238 buffer->pos += nitems;
230 if (buffer->pos > buffer->size) { 239 if (buffer->pos > buffer->size) {
231 buffer->size = buffer->pos; 240 buffer->size = buffer->pos;
232 } 241 }
309 // we were partially successful, we shift left and try again 318 // we were partially successful, we shift left and try again
310 cxBufferShiftLeft(buffer, flush_pos); 319 cxBufferShiftLeft(buffer, flush_pos);
311 return cxBufferWrite(ptr, size, nitems, buffer); 320 return cxBufferWrite(ptr, size, nitems, buffer);
312 } 321 }
313 } else { 322 } else {
314 if (buffer_copy_on_write(buffer, 0)) return 0; 323 if (buffer_copy_on_write(buffer)) return 0;
315 memcpy(buffer->bytes + buffer->pos, ptr, len); 324 memcpy(buffer->bytes + buffer->pos, ptr, len);
316 buffer->pos += len; 325 buffer->pos += len;
317 if (buffer->pos > buffer->size) { 326 if (buffer->pos > buffer->size) {
318 buffer->size = buffer->pos; 327 buffer->size = buffer->pos;
319 } 328 }
393 size_t shift 402 size_t shift
394 ) { 403 ) {
395 if (shift >= buffer->size) { 404 if (shift >= buffer->size) {
396 buffer->pos = buffer->size = 0; 405 buffer->pos = buffer->size = 0;
397 } else { 406 } else {
398 if (buffer_copy_on_write(buffer, 0)) return -1; 407 if (buffer_copy_on_write(buffer)) return -1;
399 memmove(buffer->bytes, buffer->bytes + shift, buffer->size - shift); 408 memmove(buffer->bytes, buffer->bytes + shift, buffer->size - shift);
400 buffer->size -= shift; 409 buffer->size -= shift;
401 410
402 if (buffer->pos >= shift) { 411 if (buffer->pos >= shift) {
403 buffer->pos -= shift; 412 buffer->pos -= shift;
428 } else { 437 } else {
429 movebytes = buffer->size; 438 movebytes = buffer->size;
430 } 439 }
431 440
432 if (movebytes > 0) { 441 if (movebytes > 0) {
433 if (buffer_copy_on_write(buffer, 0)) return -1; 442 if (buffer_copy_on_write(buffer)) return -1;
434 memmove(buffer->bytes + shift, buffer->bytes, movebytes); 443 memmove(buffer->bytes + shift, buffer->bytes, movebytes);
435 buffer->size = shift + movebytes; 444 buffer->size = shift + movebytes;
436 } 445 }
437 446
438 buffer->pos += shift; 447 buffer->pos += shift;

mercurial