ucx/cx/buffer.h

changeset 30
d33eaaec15da
parent 23
b26390e77237
equal deleted inserted replaced
29:b8c826c720f3 30:d33eaaec15da
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 *
441 367
442 /** 368 /**
443 * Ensures that the buffer has the required capacity. 369 * Ensures that the buffer has the required capacity.
444 * 370 *
445 * If the current capacity is not sufficient, the buffer will be extended. 371 * If the current capacity is not sufficient, the buffer will be extended.
372 * If the current capacity is larger, the buffer is shrunk and superfluous
373 * content is discarded.
446 * 374 *
447 * This function will reserve no more bytes than requested, in contrast to 375 * This function will reserve no more bytes than requested, in contrast to
448 * cxBufferMinimumCapacity(), which may reserve more bytes to improve the 376 * cxBufferMinimumCapacity(), which may reserve more bytes to improve the
449 * number of future necessary reallocations. 377 * number of future necessary reallocations.
450 * 378 *
451 * @param buffer the buffer 379 * @param buffer the buffer
452 * @param capacity the required capacity for this buffer 380 * @param capacity the required capacity for this buffer
453 * @retval zero the capacity was already sufficient or successfully increased 381 * @retval zero on success
454 * @retval non-zero on allocation failure 382 * @retval non-zero on allocation failure
455 * @see cxBufferShrink() 383 * @see cxBufferShrink()
456 * @see cxBufferMinimumCapacity() 384 * @see cxBufferMinimumCapacity()
457 */ 385 */
458 cx_attr_nonnull 386 cx_attr_nonnull
459 CX_EXPORT int cxBufferReserve(CxBuffer *buffer, size_t capacity); 387 CX_EXPORT int cxBufferReserve(CxBuffer *buffer, size_t capacity);
460 388
461 /** 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 /**
462 * Ensures that the buffer has a minimum capacity. 409 * Ensures that the buffer has a minimum capacity.
463 * 410 *
464 * 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
465 * extended. 412 * extended.
466 * 413 *
469 * 416 *
470 * @param buffer the buffer 417 * @param buffer the buffer
471 * @param capacity the minimum required capacity for this buffer 418 * @param capacity the minimum required capacity for this buffer
472 * @retval zero the capacity was already sufficient or successfully increased 419 * @retval zero the capacity was already sufficient or successfully increased
473 * @retval non-zero on allocation failure 420 * @retval non-zero on allocation failure
421 * @see cxBufferMaximumCapacity()
474 * @see cxBufferReserve() 422 * @see cxBufferReserve()
475 * @see cxBufferShrink() 423 * @see cxBufferShrink()
476 */ 424 */
477 cx_attr_nonnull 425 cx_attr_nonnull
478 CX_EXPORT int cxBufferMinimumCapacity(CxBuffer *buffer, size_t capacity); 426 CX_EXPORT int cxBufferMinimumCapacity(CxBuffer *buffer, size_t capacity);
498 CX_EXPORT void cxBufferShrink(CxBuffer *buffer, size_t reserve); 446 CX_EXPORT void cxBufferShrink(CxBuffer *buffer, size_t reserve);
499 447
500 /** 448 /**
501 * Writes data to a CxBuffer. 449 * Writes data to a CxBuffer.
502 * 450 *
503 * 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
504 * 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.
505 * by the number of bytes written. 453 * By default, the capacity grows indefinitely, unless limited with
506 * 454 * cxBufferMaximumCapacity().
507 * 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.
508 * the target until the target signals that it cannot take more data by 456 *
509 * returning zero via the respective write function. In that case, the remaining 457 * The position of the buffer is moved alongside the written data.
510 * data in this buffer is shifted to the beginning of this buffer so that the
511 * newly available space can be used to append as much data as possible.
512 *
513 * This function only stops writing more elements when the flush target and this
514 * buffer are both incapable of taking more data or all data has been written.
515 *
516 * If, after flushing, the number of items that shall be written still exceeds
517 * the capacity or flush threshold, this function tries to write all items directly
518 * to the flush target, if possible.
519 *
520 * The number returned by this function is the number of elements from
521 * @c ptr that could be written to either the flush target or the buffer.
522 * That means it does @em not include the number of items that were already in
523 * the buffer and were also flushed during the process.
524 *
525 * @attention
526 * When @p size is larger than one and the contents of the buffer are not aligned
527 * with @p size, flushing stops after all complete items have been flushed, leaving
528 * the misaligned part in the buffer.
529 * Afterward, this function only writes as many items as possible to the buffer.
530 * 458 *
531 * @note The signature is compatible with the fwrite() family of functions. 459 * @note The signature is compatible with the fwrite() family of functions.
532 * 460 *
533 * @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
534 * @param size the length of one element 462 * @param size the length of one element
564 cx_attr_nonnull 492 cx_attr_nonnull
565 CX_EXPORT size_t cxBufferAppend(const void *ptr, size_t size, 493 CX_EXPORT size_t cxBufferAppend(const void *ptr, size_t size,
566 size_t nitems, CxBuffer *buffer); 494 size_t nitems, CxBuffer *buffer);
567 495
568 /** 496 /**
569 * Performs a single flush-run on the specified buffer.
570 *
571 * Does nothing when the position in the buffer is zero.
572 * Otherwise, the data until the current position minus
573 * one is considered for flushing.
574 * Note carefully that flushing will never exceed the
575 * current @em position, even when the size of the
576 * buffer is larger than the current position.
577 *
578 * One flush run will try to flush @c blkmax many
579 * blocks of size @c blksize until either the @p buffer
580 * has no more data to flush or the write function
581 * used for flushing returns zero.
582 *
583 * The buffer is shifted left for that many bytes
584 * the flush operation has successfully flushed.
585 *
586 * @par Example 1
587 * Assume you have a buffer with size 340 and you are
588 * at position 200. The flush configuration is
589 * @c blkmax=4 and @c blksize=64 .
590 * Assume that the entire flush operation is successful.
591 * All 200 bytes on the left-hand-side from the current
592 * position are written.
593 * That means the size of the buffer is now 140 and the
594 * position is zero.
595 *
596 * @par Example 2
597 * Same as Example 1, but now the @c blkmax is 1.
598 * The size of the buffer is now 276, and the position is 136.
599 *
600 * @par Example 3
601 * Same as Example 1, but now assume the flush target
602 * only accepts 100 bytes before returning zero.
603 * That means the flush operation manages to flush
604 * one complete block and one partial block, ending
605 * up with a buffer with size 240 and position 100.
606 *
607 * @remark Just returns zero when flushing was not enabled with
608 * cxBufferEnableFlushing().
609 *
610 * @remark When the buffer uses copy-on-write, the memory
611 * is copied first, before attempting any flush.
612 * This is, however, considered an erroneous use of the
613 * buffer because it makes little sense to put
614 * readonly data into an UCX buffer for flushing instead
615 * of writing it directly to the target.
616 *
617 * @param buffer the buffer
618 * @return the number of successfully flushed bytes
619 * @see cxBufferEnableFlushing()
620 */
621 cx_attr_nonnull
622 CX_EXPORT size_t cxBufferFlush(CxBuffer *buffer);
623
624 /**
625 * Reads data from a CxBuffer. 497 * Reads data from a CxBuffer.
626 * 498 *
627 * 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.
628 * 500 *
629 * @note The signature is compatible with the fread() family of functions. 501 * @note The signature is compatible with the fread() family of functions.
643 /** 515 /**
644 * Writes a character to a buffer. 516 * Writes a character to a buffer.
645 * 517 *
646 * 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
647 * 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,
648 * the buffer capacity is extended by cxBufferMinimumCapacity(). If the feature 520 * the buffer capacity is extended, unless a limit set by
649 * 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.
650 * 523 *
651 * On successful writing, the position of the buffer is increased. 524 * On successful writing, the position of the buffer is increased.
652 * 525 *
653 * 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
654 * should use cxBufferTerminate() instead. 527 * should use cxBufferTerminate() instead.
655 * 528 *
656 * @param buffer the buffer to write to 529 * @param buffer the buffer to write to
657 * @param c the character to write 530 * @param c the character to write
658 * @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
659 * reached, and automatic extension is not enabled or not possible 532 * stream is reached, and automatic extension is not enabled or not possible
660 * @see cxBufferTerminate() 533 * @see cxBufferTerminate()
661 */ 534 */
662 cx_attr_nonnull 535 cx_attr_nonnull
663 CX_EXPORT int cxBufferPut(CxBuffer *buffer, int c); 536 CX_EXPORT int cxBufferPut(CxBuffer *buffer, int c);
664 537
665 /** 538 /**
666 * Writes a terminating zero to a buffer at the current position. 539 * Writes a terminating zero to a buffer at the current position.
667 * 540 *
668 * 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.
669 * 543 *
670 * 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
671 * 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.
672 * 546 *
673 * @param buffer the buffer to write to 547 * @param buffer the buffer to write to

mercurial