| 97 * Function pointer for cxBufferRead that is compatible with cx_read_func. |
97 * Function pointer for cxBufferRead that is compatible with cx_read_func. |
| 98 * @see cx_read_func |
98 * @see cx_read_func |
| 99 */ |
99 */ |
| 100 #define cxBufferReadFunc ((cx_read_func) cxBufferRead) |
100 #define cxBufferReadFunc ((cx_read_func) cxBufferRead) |
| 101 |
101 |
| 102 /** |
|
| 103 * Configuration for automatic flushing. |
|
| 104 */ |
|
| 105 struct cx_buffer_flush_config_s { |
|
| 106 /** |
|
| 107 * The buffer may not extend beyond this threshold before starting to flush. |
|
| 108 * |
|
| 109 * Only used when the buffer uses #CX_BUFFER_AUTO_EXTEND. |
|
| 110 * The threshold will be the maximum capacity the buffer is extended to |
|
| 111 * before flushing. |
|
| 112 */ |
|
| 113 size_t threshold; |
|
| 114 /** |
|
| 115 * The block size for the elements to flush. |
|
| 116 */ |
|
| 117 size_t blksize; |
|
| 118 /** |
|
| 119 * The maximum number of blocks to flush in one cycle. |
|
| 120 * |
|
| 121 * @attention While it is guaranteed that cxBufferFlush() will not flush |
|
| 122 * more blocks, this is not necessarily the case for cxBufferWrite(). |
|
| 123 * After performing a flush cycle, cxBufferWrite() will retry the write |
|
| 124 * operation and potentially trigger another flush cycle, until the |
|
| 125 * flush target accepts no more data. |
|
| 126 */ |
|
| 127 size_t blkmax; |
|
| 128 |
|
| 129 /** |
|
| 130 * The target for the write function. |
|
| 131 */ |
|
| 132 void *target; |
|
| 133 |
|
| 134 /** |
|
| 135 * The write-function used for flushing. |
|
| 136 * If NULL, the flushed content gets discarded. |
|
| 137 */ |
|
| 138 cx_write_func wfunc; |
|
| 139 }; |
|
| 140 |
|
| 141 /** |
|
| 142 * Type alias for the flush configuration struct. |
|
| 143 * |
|
| 144 * @code |
|
| 145 * struct cx_buffer_flush_config_s { |
|
| 146 * size_t threshold; |
|
| 147 * size_t blksize; |
|
| 148 * size_t blkmax; |
|
| 149 * void *target; |
|
| 150 * cx_write_func wfunc; |
|
| 151 * }; |
|
| 152 * @endcode |
|
| 153 */ |
|
| 154 typedef struct cx_buffer_flush_config_s CxBufferFlushConfig; |
|
| 155 |
102 |
| 156 /** Structure for the UCX buffer data. */ |
103 /** Structure for the UCX buffer data. */ |
| 157 struct cx_buffer_s { |
104 struct cx_buffer_s { |
| 158 /** A pointer to the buffer contents. */ |
105 /** A pointer to the buffer contents. */ |
| 159 union { |
106 union { |
| 166 */ |
113 */ |
| 167 unsigned char *bytes; |
114 unsigned char *bytes; |
| 168 }; |
115 }; |
| 169 /** The allocator to use for automatic memory management. */ |
116 /** The allocator to use for automatic memory management. */ |
| 170 const CxAllocator *allocator; |
117 const CxAllocator *allocator; |
| 171 /** |
|
| 172 * Optional flush configuration |
|
| 173 * |
|
| 174 * @see cxBufferEnableFlushing() |
|
| 175 */ |
|
| 176 CxBufferFlushConfig *flush; |
|
| 177 /** Current position of the buffer. */ |
118 /** Current position of the buffer. */ |
| 178 size_t pos; |
119 size_t pos; |
| 179 /** Current capacity (i.e. maximum size) of the buffer. */ |
120 /** Current capacity (i.e. maximum size) of the buffer. */ |
| 180 size_t capacity; |
121 size_t capacity; |
| |
122 /** Maximum capacity that this buffer may grow to. */ |
| |
123 size_t max_capacity; |
| 181 /** Current size of the buffer content. */ |
124 /** Current size of the buffer content. */ |
| 182 size_t size; |
125 size_t size; |
| 183 /** |
126 /** |
| 184 * Flag register for buffer features. |
127 * Flag register for buffer features. |
| 185 * @see #CX_BUFFER_DEFAULT |
128 * @see #CX_BUFFER_DEFAULT |
| 229 cx_attr_nonnull_arg(1) |
172 cx_attr_nonnull_arg(1) |
| 230 CX_EXPORT int cxBufferInit(CxBuffer *buffer, void *space, size_t capacity, |
173 CX_EXPORT int cxBufferInit(CxBuffer *buffer, void *space, size_t capacity, |
| 231 const CxAllocator *allocator, int flags); |
174 const CxAllocator *allocator, int flags); |
| 232 |
175 |
| 233 /** |
176 /** |
| 234 * Configures the buffer for flushing. |
|
| 235 * |
|
| 236 * Flushing can happen automatically when data is written |
|
| 237 * to the buffer (see cxBufferWrite()) or manually when |
|
| 238 * cxBufferFlush() is called. |
|
| 239 * |
|
| 240 * @param buffer the buffer |
|
| 241 * @param config the flush configuration |
|
| 242 * @retval zero success |
|
| 243 * @retval non-zero failure |
|
| 244 * @see cxBufferFlush() |
|
| 245 * @see cxBufferWrite() |
|
| 246 */ |
|
| 247 cx_attr_nonnull |
|
| 248 CX_EXPORT int cxBufferEnableFlushing(CxBuffer *buffer, CxBufferFlushConfig config); |
|
| 249 |
|
| 250 /** |
|
| 251 * Destroys the buffer contents. |
177 * Destroys the buffer contents. |
| 252 * |
178 * |
| 253 * Has no effect if the #CX_BUFFER_FREE_CONTENTS feature is not enabled. |
179 * Has no effect if the #CX_BUFFER_FREE_CONTENTS feature is not enabled. |
| 254 * If you want to free the memory of the entire buffer, use cxBufferFree(). |
180 * If you want to free the memory of the entire buffer, use cxBufferFree(). |
| 255 * |
181 * |
| 459 */ |
385 */ |
| 460 cx_attr_nonnull |
386 cx_attr_nonnull |
| 461 CX_EXPORT int cxBufferReserve(CxBuffer *buffer, size_t capacity); |
387 CX_EXPORT int cxBufferReserve(CxBuffer *buffer, size_t capacity); |
| 462 |
388 |
| 463 /** |
389 /** |
| |
390 * Limits the buffer's capacity. |
| |
391 * |
| |
392 * If the current capacity is already larger, this function fails and returns |
| |
393 * non-zero. |
| |
394 * |
| |
395 * The capacity limit will affect auto-extension features, as well as future |
| |
396 * calls to cxBufferMinimumCapacity() and cxBufferReserve(). |
| |
397 * |
| |
398 * @param buffer the buffer |
| |
399 * @param capacity the maximum allowed capacity for this buffer |
| |
400 * @retval zero the limit is applied |
| |
401 * @retval non-zero the new limit is smaller than the current capacity |
| |
402 * @see cxBufferReserve() |
| |
403 * @see cxBufferMinimumCapacity() |
| |
404 */ |
| |
405 cx_attr_nonnull |
| |
406 CX_EXPORT int cxBufferMaximumCapacity(CxBuffer *buffer, size_t capacity); |
| |
407 |
| |
408 /** |
| 464 * Ensures that the buffer has a minimum capacity. |
409 * Ensures that the buffer has a minimum capacity. |
| 465 * |
410 * |
| 466 * If the current capacity is not sufficient, the buffer will be generously |
411 * If the current capacity is not sufficient, the buffer will be generously |
| 467 * extended. |
412 * extended. |
| 468 * |
413 * |
| 471 * |
416 * |
| 472 * @param buffer the buffer |
417 * @param buffer the buffer |
| 473 * @param capacity the minimum required capacity for this buffer |
418 * @param capacity the minimum required capacity for this buffer |
| 474 * @retval zero the capacity was already sufficient or successfully increased |
419 * @retval zero the capacity was already sufficient or successfully increased |
| 475 * @retval non-zero on allocation failure |
420 * @retval non-zero on allocation failure |
| |
421 * @see cxBufferMaximumCapacity() |
| 476 * @see cxBufferReserve() |
422 * @see cxBufferReserve() |
| 477 * @see cxBufferShrink() |
423 * @see cxBufferShrink() |
| 478 */ |
424 */ |
| 479 cx_attr_nonnull |
425 cx_attr_nonnull |
| 480 CX_EXPORT int cxBufferMinimumCapacity(CxBuffer *buffer, size_t capacity); |
426 CX_EXPORT int cxBufferMinimumCapacity(CxBuffer *buffer, size_t capacity); |
| 500 CX_EXPORT void cxBufferShrink(CxBuffer *buffer, size_t reserve); |
446 CX_EXPORT void cxBufferShrink(CxBuffer *buffer, size_t reserve); |
| 501 |
447 |
| 502 /** |
448 /** |
| 503 * Writes data to a CxBuffer. |
449 * Writes data to a CxBuffer. |
| 504 * |
450 * |
| 505 * If automatic flushing is not enabled, the data is simply written into the |
451 * If auto-extension is enabled, the buffer's capacity is automatically |
| 506 * buffer at the current position, and the position of the buffer is increased |
452 * increased when it is not large enough to hold all data. |
| 507 * by the number of bytes written. |
453 * By default, the capacity grows indefinitely, unless limited with |
| 508 * |
454 * cxBufferMaximumCapacity(). |
| 509 * If flushing is enabled and the buffer needs to flush, the data is flushed to |
455 * When auto-extension fails, this function writes no data and returns zero. |
| 510 * the target until the target signals that it cannot take more data by |
456 * |
| 511 * returning zero via the respective write function. In that case, the remaining |
457 * The position of the buffer is moved alongside the written data. |
| 512 * data in this buffer is shifted to the beginning of this buffer so that the |
|
| 513 * newly available space can be used to append as much data as possible. |
|
| 514 * |
|
| 515 * This function only stops writing more elements when the flush target and this |
|
| 516 * buffer are both incapable of taking more data or all data has been written. |
|
| 517 * |
|
| 518 * If, after flushing, the number of items that shall be written still exceeds |
|
| 519 * the capacity or flush threshold, this function tries to write all items directly |
|
| 520 * to the flush target, if possible. |
|
| 521 * |
|
| 522 * The number returned by this function is the number of elements from |
|
| 523 * @c ptr that could be written to either the flush target or the buffer. |
|
| 524 * That means it does @em not include the number of items that were already in |
|
| 525 * the buffer and were also flushed during the process. |
|
| 526 * |
|
| 527 * @attention |
|
| 528 * When @p size is larger than one and the contents of the buffer are not aligned |
|
| 529 * with @p size, flushing stops after all complete items have been flushed, leaving |
|
| 530 * the misaligned part in the buffer. |
|
| 531 * Afterward, this function only writes as many items as possible to the buffer. |
|
| 532 * |
458 * |
| 533 * @note The signature is compatible with the fwrite() family of functions. |
459 * @note The signature is compatible with the fwrite() family of functions. |
| 534 * |
460 * |
| 535 * @param ptr a pointer to the memory area containing the bytes to be written |
461 * @param ptr a pointer to the memory area containing the bytes to be written |
| 536 * @param size the length of one element |
462 * @param size the length of one element |
| 566 cx_attr_nonnull |
492 cx_attr_nonnull |
| 567 CX_EXPORT size_t cxBufferAppend(const void *ptr, size_t size, |
493 CX_EXPORT size_t cxBufferAppend(const void *ptr, size_t size, |
| 568 size_t nitems, CxBuffer *buffer); |
494 size_t nitems, CxBuffer *buffer); |
| 569 |
495 |
| 570 /** |
496 /** |
| 571 * Performs a single flush-run on the specified buffer. |
|
| 572 * |
|
| 573 * Does nothing when the position in the buffer is zero. |
|
| 574 * Otherwise, the data until the current position minus |
|
| 575 * one is considered for flushing. |
|
| 576 * Note carefully that flushing will never exceed the |
|
| 577 * current @em position, even when the size of the |
|
| 578 * buffer is larger than the current position. |
|
| 579 * |
|
| 580 * One flush run will try to flush @c blkmax many |
|
| 581 * blocks of size @c blksize until either the @p buffer |
|
| 582 * has no more data to flush or the write function |
|
| 583 * used for flushing returns zero. |
|
| 584 * |
|
| 585 * The buffer is shifted left for that many bytes |
|
| 586 * the flush operation has successfully flushed. |
|
| 587 * |
|
| 588 * @par Example 1 |
|
| 589 * Assume you have a buffer with size 340 and you are |
|
| 590 * at position 200. The flush configuration is |
|
| 591 * @c blkmax=4 and @c blksize=64 . |
|
| 592 * Assume that the entire flush operation is successful. |
|
| 593 * All 200 bytes on the left-hand-side from the current |
|
| 594 * position are written. |
|
| 595 * That means the size of the buffer is now 140 and the |
|
| 596 * position is zero. |
|
| 597 * |
|
| 598 * @par Example 2 |
|
| 599 * Same as Example 1, but now the @c blkmax is 1. |
|
| 600 * The size of the buffer is now 276, and the position is 136. |
|
| 601 * |
|
| 602 * @par Example 3 |
|
| 603 * Same as Example 1, but now assume the flush target |
|
| 604 * only accepts 100 bytes before returning zero. |
|
| 605 * That means the flush operation manages to flush |
|
| 606 * one complete block and one partial block, ending |
|
| 607 * up with a buffer with size 240 and position 100. |
|
| 608 * |
|
| 609 * @remark Just returns zero when flushing was not enabled with |
|
| 610 * cxBufferEnableFlushing(). |
|
| 611 * |
|
| 612 * @remark When the buffer uses copy-on-write, the memory |
|
| 613 * is copied first, before attempting any flush. |
|
| 614 * This is, however, considered an erroneous use of the |
|
| 615 * buffer because it makes little sense to put |
|
| 616 * readonly data into an UCX buffer for flushing instead |
|
| 617 * of writing it directly to the target. |
|
| 618 * |
|
| 619 * @param buffer the buffer |
|
| 620 * @return the number of successfully flushed bytes |
|
| 621 * @see cxBufferEnableFlushing() |
|
| 622 */ |
|
| 623 cx_attr_nonnull |
|
| 624 CX_EXPORT size_t cxBufferFlush(CxBuffer *buffer); |
|
| 625 |
|
| 626 /** |
|
| 627 * Reads data from a CxBuffer. |
497 * Reads data from a CxBuffer. |
| 628 * |
498 * |
| 629 * The position of the buffer is increased by the number of bytes read. |
499 * The position of the buffer is increased by the number of bytes read. |
| 630 * |
500 * |
| 631 * @note The signature is compatible with the fread() family of functions. |
501 * @note The signature is compatible with the fread() family of functions. |
| 645 /** |
515 /** |
| 646 * Writes a character to a buffer. |
516 * Writes a character to a buffer. |
| 647 * |
517 * |
| 648 * The least significant byte of the argument is written to the buffer. If the |
518 * The least significant byte of the argument is written to the buffer. If the |
| 649 * end of the buffer is reached and #CX_BUFFER_AUTO_EXTEND feature is enabled, |
519 * end of the buffer is reached and #CX_BUFFER_AUTO_EXTEND feature is enabled, |
| 650 * the buffer capacity is extended by cxBufferMinimumCapacity(). If the feature |
520 * the buffer capacity is extended, unless a limit set by |
| 651 * is disabled or the buffer extension fails, @c EOF is returned. |
521 * cxBufferMaximumCapacity() is reached. |
| |
522 * If the feature is disabled or the buffer extension fails, @c EOF is returned. |
| 652 * |
523 * |
| 653 * On successful writing, the position of the buffer is increased. |
524 * On successful writing, the position of the buffer is increased. |
| 654 * |
525 * |
| 655 * If you just want to write a null-terminator at the current position, you |
526 * If you just want to write a null-terminator at the current position, you |
| 656 * should use cxBufferTerminate() instead. |
527 * should use cxBufferTerminate() instead. |
| 657 * |
528 * |
| 658 * @param buffer the buffer to write to |
529 * @param buffer the buffer to write to |
| 659 * @param c the character to write |
530 * @param c the character to write |
| 660 * @return the byte that has been written or @c EOF when the end of the stream is |
531 * @return the byte that has been written or @c EOF when the end of the |
| 661 * reached, and automatic extension is not enabled or not possible |
532 * stream is reached, and automatic extension is not enabled or not possible |
| 662 * @see cxBufferTerminate() |
533 * @see cxBufferTerminate() |
| 663 */ |
534 */ |
| 664 cx_attr_nonnull |
535 cx_attr_nonnull |
| 665 CX_EXPORT int cxBufferPut(CxBuffer *buffer, int c); |
536 CX_EXPORT int cxBufferPut(CxBuffer *buffer, int c); |
| 666 |
537 |
| 667 /** |
538 /** |
| 668 * Writes a terminating zero to a buffer at the current position. |
539 * Writes a terminating zero to a buffer at the current position. |
| 669 * |
540 * |
| 670 * If successful, sets the size to the current position and advances the position by one. |
541 * If successful, sets the size to the current position and advances |
| |
542 * the position by one. |
| 671 * |
543 * |
| 672 * The purpose of this function is to have the written data ready to be used as |
544 * The purpose of this function is to have the written data ready to be used as |
| 673 * a C string with the buffer's size being the length of that string. |
545 * a C string with the buffer's size being the length of that string. |
| 674 * |
546 * |
| 675 * @param buffer the buffer to write to |
547 * @param buffer the buffer to write to |