| 85 * After performing the copy, the flag is automatically cleared. |
85 * After performing the copy, the flag is automatically cleared. |
| 86 * This flag has no effect on buffers which do not have #CX_BUFFER_AUTO_EXTEND set, which is why |
86 * This flag has no effect on buffers which do not have #CX_BUFFER_AUTO_EXTEND set, which is why |
| 87 * buffers automatically admit the auto-extend flag when initialized with copy-on-extend enabled. |
87 * buffers automatically admit the auto-extend flag when initialized with copy-on-extend enabled. |
| 88 */ |
88 */ |
| 89 #define CX_BUFFER_COPY_ON_EXTEND 0x08 |
89 #define CX_BUFFER_COPY_ON_EXTEND 0x08 |
| |
90 |
| |
91 /** |
| |
92 * Configuration for automatic flushing. |
| |
93 */ |
| |
94 struct cx_buffer_flush_config_s { |
| |
95 /** |
| |
96 * The buffer may not extend beyond this threshold before starting to flush. |
| |
97 * |
| |
98 * Only used when the buffer uses #CX_BUFFER_AUTO_EXTEND. |
| |
99 * The threshold will be the maximum capacity the buffer is extended to |
| |
100 * before flushing. |
| |
101 */ |
| |
102 size_t threshold; |
| |
103 /** |
| |
104 * The block size for the elements to flush. |
| |
105 */ |
| |
106 size_t blksize; |
| |
107 /** |
| |
108 * The maximum number of blocks to flush in one cycle. |
| |
109 * |
| |
110 * @attention while it is guaranteed that cxBufferFlush() will not flush |
| |
111 * more blocks, this is not necessarily the case for cxBufferWrite(). |
| |
112 * After performing a flush cycle, cxBufferWrite() will retry the write |
| |
113 * operation and potentially trigger another flush cycle, until the |
| |
114 * flush target accepts no more data. |
| |
115 */ |
| |
116 size_t blkmax; |
| |
117 |
| |
118 /** |
| |
119 * The target for write function. |
| |
120 */ |
| |
121 void *target; |
| |
122 |
| |
123 /** |
| |
124 * The write-function used for flushing. |
| |
125 * If NULL, the flushed content gets discarded. |
| |
126 */ |
| |
127 cx_write_func wfunc; |
| |
128 }; |
| |
129 |
| |
130 /** |
| |
131 * Type alais for the flush configuration struct. |
| |
132 * |
| |
133 * @code |
| |
134 * struct cx_buffer_flush_config_s { |
| |
135 * size_t threshold; |
| |
136 * size_t blksize; |
| |
137 * size_t blkmax; |
| |
138 * void *target; |
| |
139 * cx_write_func wfunc; |
| |
140 * }; |
| |
141 * @endcode |
| |
142 */ |
| |
143 typedef struct cx_buffer_flush_config_s CxBufferFlushConfig; |
| 90 |
144 |
| 91 /** Structure for the UCX buffer data. */ |
145 /** Structure for the UCX buffer data. */ |
| 92 struct cx_buffer_s { |
146 struct cx_buffer_s { |
| 93 /** A pointer to the buffer contents. */ |
147 /** A pointer to the buffer contents. */ |
| 94 union { |
148 union { |
| 101 */ |
155 */ |
| 102 unsigned char *bytes; |
156 unsigned char *bytes; |
| 103 }; |
157 }; |
| 104 /** The allocator to use for automatic memory management. */ |
158 /** The allocator to use for automatic memory management. */ |
| 105 const CxAllocator *allocator; |
159 const CxAllocator *allocator; |
| |
160 /** |
| |
161 * Optional flush configuration |
| |
162 * |
| |
163 * @see cxBufferEnableFlushing() |
| |
164 */ |
| |
165 CxBufferFlushConfig* flush; |
| 106 /** Current position of the buffer. */ |
166 /** Current position of the buffer. */ |
| 107 size_t pos; |
167 size_t pos; |
| 108 /** Current capacity (i.e. maximum size) of the buffer. */ |
168 /** Current capacity (i.e. maximum size) of the buffer. */ |
| 109 size_t capacity; |
169 size_t capacity; |
| 110 /** Current size of the buffer content. */ |
170 /** Current size of the buffer content. */ |
| 111 size_t size; |
171 size_t size; |
| 112 /** |
|
| 113 * The buffer may not extend beyond this threshold before starting to flush. |
|
| 114 * Default is @c SIZE_MAX (flushing disabled when auto extension is enabled). |
|
| 115 */ |
|
| 116 size_t flush_threshold; |
|
| 117 /** |
|
| 118 * The block size for the elements to flush. |
|
| 119 * Default is 4096 bytes. |
|
| 120 */ |
|
| 121 size_t flush_blksize; |
|
| 122 /** |
|
| 123 * The maximum number of blocks to flush in one cycle. |
|
| 124 * Zero disables flushing entirely (this is the default). |
|
| 125 * Set this to @c SIZE_MAX to flush the entire buffer. |
|
| 126 * |
|
| 127 * @attention if the maximum number of blocks multiplied with the block size |
|
| 128 * is smaller than the expected contents written to this buffer within one write |
|
| 129 * operation, multiple flush cycles are performed after that write. |
|
| 130 * That means the total number of blocks flushed after one write to this buffer may |
|
| 131 * be larger than @c flush_blkmax. |
|
| 132 */ |
|
| 133 size_t flush_blkmax; |
|
| 134 |
|
| 135 /** |
|
| 136 * The write function used for flushing. |
|
| 137 * If NULL, the flushed content gets discarded. |
|
| 138 */ |
|
| 139 cx_write_func flush_func; |
|
| 140 |
|
| 141 /** |
|
| 142 * The target for @c flush_func. |
|
| 143 */ |
|
| 144 void *flush_target; |
|
| 145 |
|
| 146 /** |
172 /** |
| 147 * Flag register for buffer features. |
173 * Flag register for buffer features. |
| 148 * @see #CX_BUFFER_DEFAULT |
174 * @see #CX_BUFFER_DEFAULT |
| 149 * @see #CX_BUFFER_FREE_CONTENTS |
175 * @see #CX_BUFFER_FREE_CONTENTS |
| 150 * @see #CX_BUFFER_AUTO_EXTEND |
176 * @see #CX_BUFFER_AUTO_EXTEND |
| 197 const CxAllocator *allocator, |
223 const CxAllocator *allocator, |
| 198 int flags |
224 int flags |
| 199 ); |
225 ); |
| 200 |
226 |
| 201 /** |
227 /** |
| |
228 * Configures the buffer for flushing. |
| |
229 * |
| |
230 * Flushing can happen automatically when data is written |
| |
231 * to the buffer (see cxBufferWrite()) or manually when |
| |
232 * cxBufferFlush() is called. |
| |
233 * |
| |
234 * @param buffer the buffer |
| |
235 * @param config the flush configuration |
| |
236 * @retval zero success |
| |
237 * @retval non-zero failure |
| |
238 * @see cxBufferFlush() |
| |
239 * @see cxBufferWrite() |
| |
240 */ |
| |
241 cx_attr_nonnull |
| |
242 int cxBufferEnableFlushing( |
| |
243 CxBuffer *buffer, |
| |
244 CxBufferFlushConfig config |
| |
245 ); |
| |
246 |
| |
247 /** |
| 202 * Destroys the buffer contents. |
248 * Destroys the buffer contents. |
| 203 * |
249 * |
| 204 * Has no effect if the #CX_BUFFER_FREE_CONTENTS feature is not enabled. |
250 * Has no effect if the #CX_BUFFER_FREE_CONTENTS feature is not enabled. |
| 205 * If you want to free the memory of the entire buffer, use cxBufferFree(). |
251 * If you want to free the memory of the entire buffer, use cxBufferFree(). |
| 206 * |
252 * |
| 417 ); |
463 ); |
| 418 |
464 |
| 419 /** |
465 /** |
| 420 * Writes data to a CxBuffer. |
466 * Writes data to a CxBuffer. |
| 421 * |
467 * |
| |
468 * If automatic flushing is not enabled, the data is simply written into the |
| |
469 * buffer at the current position and the position of the buffer is increased |
| |
470 * by the number of bytes written. |
| |
471 * |
| 422 * If flushing is enabled and the buffer needs to flush, the data is flushed to |
472 * If flushing is enabled and the buffer needs to flush, the data is flushed to |
| 423 * the target until the target signals that it cannot take more data by |
473 * the target until the target signals that it cannot take more data by |
| 424 * returning zero via the respective write function. In that case, the remaining |
474 * returning zero via the respective write function. In that case, the remaining |
| 425 * data in this buffer is shifted to the beginning of this buffer so that the |
475 * data in this buffer is shifted to the beginning of this buffer so that the |
| 426 * newly available space can be used to append as much data as possible. This |
476 * newly available space can be used to append as much data as possible. This |
| 427 * function only stops writing more elements, when the flush target and this |
477 * function only stops writing more elements, when the flush target and this |
| 428 * buffer are both incapable of taking more data or all data has been written. |
478 * buffer are both incapable of taking more data or all data has been written. |
| 429 * The number returned by this function is the total number of elements that |
479 * If number of items that shall be written is larger than the buffer can hold, |
| 430 * could be written during the process. It does not necessarily mean that those |
480 * the first items from @c ptr are directly relayed to the flush target, if |
| 431 * elements are still in this buffer, because some of them could have also been |
481 * possible. |
| 432 * flushed already. |
482 * The number returned by this function is only the number of elements from |
| 433 * |
483 * @c ptr that could be written to either the flush target or the buffer. |
| 434 * If automatic flushing is not enabled, the data is simply written into the |
|
| 435 * buffer at the current position and the position of the buffer is increased |
|
| 436 * by the number of bytes written. |
|
| 437 * Use cxBufferAppend() if you want to add data to this buffer regardless of |
|
| 438 * the position. |
|
| 439 * |
484 * |
| 440 * @note The signature is compatible with the fwrite() family of functions. |
485 * @note The signature is compatible with the fwrite() family of functions. |
| 441 * |
486 * |
| 442 * @param ptr a pointer to the memory area containing the bytes to be written |
487 * @param ptr a pointer to the memory area containing the bytes to be written |
| 443 * @param size the length of one element |
488 * @param size the length of one element |
| 481 size_t nitems, |
526 size_t nitems, |
| 482 CxBuffer *buffer |
527 CxBuffer *buffer |
| 483 ); |
528 ); |
| 484 |
529 |
| 485 /** |
530 /** |
| |
531 * Performs a single flush-run on the specified buffer. |
| |
532 * |
| |
533 * Does nothing when the position in the buffer is zero. |
| |
534 * Otherwise, the data until the current position minus |
| |
535 * one is considered for flushing. |
| |
536 * Note carefully that flushing will never exceed the |
| |
537 * current @em position, even when the size of the |
| |
538 * buffer is larger than the current position. |
| |
539 * |
| |
540 * One flush run will try to flush @c blkmax many |
| |
541 * blocks of size @c blksize until either the @p buffer |
| |
542 * has no more data to flush or the write function |
| |
543 * used for flushing returns zero. |
| |
544 * |
| |
545 * The buffer is shifted left for that many bytes |
| |
546 * the flush operation has successfully flushed. |
| |
547 * |
| |
548 * @par Example 1 |
| |
549 * Assume you have a buffer with size 340 and you are |
| |
550 * at position 200. The flush configuration is |
| |
551 * @c blkmax=4 and @c blksize=64 . |
| |
552 * Assume that the entire flush operation is successful. |
| |
553 * All 200 bytes on the left hand-side from the current |
| |
554 * position are written. |
| |
555 * That means, the size of the buffer is now 140 and the |
| |
556 * position is zero. |
| |
557 * |
| |
558 * @par Example 2 |
| |
559 * Same as Example 1, but now the @c blkmax is 1. |
| |
560 * The size of the buffer is now 276 and the position is 136. |
| |
561 * |
| |
562 * @par Example 3 |
| |
563 * Same as Example 1, but now assume the flush target |
| |
564 * only accepts 100 bytes before returning zero. |
| |
565 * That means, the flush operations manages to flush |
| |
566 * one complete block and one partial block, ending |
| |
567 * up with a buffer with size 240 and position 100. |
| |
568 * |
| |
569 * @remark Just returns zero when flushing was not enabled with |
| |
570 * cxBufferEnableFlushing(). |
| |
571 * |
| |
572 * @remark When the buffer uses copy-on-write, the memory |
| |
573 * is copied first, before attempting any flush. |
| |
574 * This is, however, considered an erroneous use of the |
| |
575 * buffer, because it does not make much sense to put |
| |
576 * readonly data into an UCX buffer for flushing, instead |
| |
577 * of writing it directly to the target. |
| |
578 * |
| |
579 * @param buffer the buffer |
| |
580 * @return the number of successfully flushed bytes |
| |
581 * @see cxBufferEnableFlushing() |
| |
582 */ |
| |
583 cx_attr_nonnull |
| |
584 size_t cxBufferFlush(CxBuffer *buffer); |
| |
585 |
| |
586 /** |
| 486 * Reads data from a CxBuffer. |
587 * Reads data from a CxBuffer. |
| 487 * |
588 * |
| 488 * The position of the buffer is increased by the number of bytes read. |
589 * The position of the buffer is increased by the number of bytes read. |
| 489 * |
590 * |
| 490 * @note The signature is compatible with the fread() family of functions. |
591 * @note The signature is compatible with the fread() family of functions. |