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. |