src/cx/buffer.h

changeset 1571
25ead2ffb9b5
parent 1542
197450c2b0b3
equal deleted inserted replaced
1570:8fd491bc2940 1571:25ead2ffb9b5
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

mercurial