ucx/buffer.c

changeset 31
287484519844
parent 30
d33eaaec15da
equal deleted inserted replaced
30:d33eaaec15da 31:287484519844
43 return 0; 43 return 0;
44 } 44 }
45 45
46 int cxBufferInit( 46 int cxBufferInit(
47 CxBuffer *buffer, 47 CxBuffer *buffer,
48 const CxAllocator *allocator,
48 void *space, 49 void *space,
49 size_t capacity, 50 size_t capacity,
50 const CxAllocator *allocator,
51 int flags 51 int flags
52 ) { 52 ) {
53 if (allocator == NULL) { 53 if (allocator == NULL) {
54 allocator = cxDefaultAllocator; 54 allocator = cxDefaultAllocator;
55 } 55 }
56 if (flags & CX_BUFFER_COPY_ON_EXTEND) { 56 if (flags & CX_BUFFER_COPY_ON_EXTEND) {
57 flags |= CX_BUFFER_AUTO_EXTEND; 57 flags |= CX_BUFFER_AUTO_EXTEND;
72 72
73 return 0; 73 return 0;
74 } 74 }
75 75
76 void cxBufferDestroy(CxBuffer *buffer) { 76 void cxBufferDestroy(CxBuffer *buffer) {
77 if (buffer->flags & CX_BUFFER_FREE_CONTENTS) { 77 if ((buffer->flags & (CX_BUFFER_FREE_CONTENTS | CX_BUFFER_DO_NOT_FREE))
78 == CX_BUFFER_FREE_CONTENTS) {
78 cxFree(buffer->allocator, buffer->bytes); 79 cxFree(buffer->allocator, buffer->bytes);
79 } 80 }
80 memset(buffer, 0, sizeof(CxBuffer)); 81 memset(buffer, 0, sizeof(CxBuffer));
81 } 82 }
82 83
83 CxBuffer *cxBufferCreate( 84 CxBuffer *cxBufferCreate(
85 const CxAllocator *allocator,
84 void *space, 86 void *space,
85 size_t capacity, 87 size_t capacity,
86 const CxAllocator *allocator,
87 int flags 88 int flags
88 ) { 89 ) {
89 if (allocator == NULL) { 90 if (allocator == NULL) {
90 allocator = cxDefaultAllocator; 91 allocator = cxDefaultAllocator;
91 } 92 }
92 CxBuffer *buf = cxMalloc(allocator, sizeof(CxBuffer)); 93 CxBuffer *buf = cxMalloc(allocator, sizeof(CxBuffer));
93 if (buf == NULL) return NULL; // LCOV_EXCL_LINE 94 if (buf == NULL) return NULL; // LCOV_EXCL_LINE
94 if (0 == cxBufferInit(buf, space, capacity, allocator, flags)) { 95 if (0 == cxBufferInit(buf, allocator, space, capacity, flags)) {
95 return buf; 96 return buf;
96 } else { 97 } else {
97 // LCOV_EXCL_START 98 // LCOV_EXCL_START
98 cxFree(allocator, buf); 99 cxFree(allocator, buf);
99 return NULL; 100 return NULL;
296 const void *ptr, 297 const void *ptr,
297 size_t size, 298 size_t size,
298 size_t nitems, 299 size_t nitems,
299 CxBuffer *buffer 300 CxBuffer *buffer
300 ) { 301 ) {
302 // trivial case
303 if (size == 0 || nitems == 0) return 0;
304
301 // optimize for easy case 305 // optimize for easy case
302 if (size == 1 && (buffer->capacity - buffer->pos) >= nitems) { 306 if (size == 1 && (buffer->capacity - buffer->pos) >= nitems) {
303 if (buffer_copy_on_write(buffer)) return 0; 307 if (buffer_copy_on_write(buffer)) return 0;
304 memcpy(buffer->bytes + buffer->pos, ptr, nitems); 308 memcpy(buffer->bytes + buffer->pos, ptr, nitems);
305 buffer->pos += nitems; 309 buffer->pos += nitems;
361 const void *ptr, 365 const void *ptr,
362 size_t size, 366 size_t size,
363 size_t nitems, 367 size_t nitems,
364 CxBuffer *buffer 368 CxBuffer *buffer
365 ) { 369 ) {
366 size_t pos = buffer->pos; 370 // trivial case
367 size_t append_pos = buffer->size; 371 if (size == 0 || nitems == 0) return 0;
368 buffer->pos = append_pos; 372
369 size_t written = cxBufferWrite(ptr, size, nitems, buffer); 373 const size_t pos = buffer->pos;
370 // the buffer might have been flushed 374 buffer->pos = buffer->size;
371 // we must compute a possible delta for the position 375 const size_t written = cxBufferWrite(ptr, size, nitems, buffer);
372 // expected: pos = append_pos + written 376 buffer->pos = pos;
373 // -> if this is not the case, there is a delta
374 size_t delta = append_pos + written*size - buffer->pos;
375 if (delta > pos) {
376 buffer->pos = 0;
377 } else {
378 buffer->pos = pos - delta;
379 }
380 return written; 377 return written;
381 } 378 }
382 379
383 int cxBufferPut( 380 int cxBufferPut(
384 CxBuffer *buffer, 381 CxBuffer *buffer,
392 return EOF; 389 return EOF;
393 } 390 }
394 } 391 }
395 392
396 int cxBufferTerminate(CxBuffer *buffer) { 393 int cxBufferTerminate(CxBuffer *buffer) {
397 if (0 == cxBufferPut(buffer, 0)) { 394 // try to extend / shrink the buffer
398 buffer->size = buffer->pos - 1; 395 if (buffer->pos >= buffer->capacity) {
399 return 0; 396 if ((buffer->flags & CX_BUFFER_AUTO_EXTEND) == 0) {
400 } else { 397 return -1;
401 return -1; 398 }
402 } 399 if (cxBufferReserve(buffer, buffer->pos + 1)) {
403 } 400 return -1; // LCOV_EXCL_LINE
404 401 }
405 size_t cxBufferPutString( 402 } else {
406 CxBuffer *buffer, 403 buffer->size = buffer->pos;
407 const char *str 404 cxBufferShrink(buffer, 1);
408 ) { 405 // set the capacity explicitly, in case shrink was skipped due to CoW
409 return cxBufferWrite(str, 1, strlen(str), buffer); 406 buffer->capacity = buffer->size + 1;
407 }
408
409 // check if we are still on read-only memory
410 if (buffer_copy_on_write(buffer)) return -1;
411
412 // write the terminator and exit
413 buffer->space[buffer->pos] = '\0';
414 return 0;
415 }
416
417 size_t cx_buffer_put_string(CxBuffer *buffer, cxstring str) {
418 return cxBufferWrite(str.ptr, 1, str.length, buffer);
419 }
420
421 size_t cx_buffer_append_string(CxBuffer *buffer, cxstring str) {
422 return cxBufferAppend(str.ptr, 1, str.length, buffer);
410 } 423 }
411 424
412 size_t cxBufferRead( 425 size_t cxBufferRead(
413 void *ptr, 426 void *ptr,
414 size_t size, 427 size_t size,

mercurial