ucx/cx/buffer.h

changeset 16
04c9f8d8f03b
parent 11
0aa8cbd7912e
child 21
5ea41679e15d
equal deleted inserted replaced
15:862ab606ee06 16:04c9f8d8f03b
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 /** 29 /**
30 * \file buffer.h 30 * @file buffer.h
31 * 31 *
32 * \brief Advanced buffer implementation. 32 * @brief Advanced buffer implementation.
33 * 33 *
34 * Instances of CxBuffer can be used to read from or to write to like one 34 * Instances of CxBuffer can be used to read from or to write to like one
35 * would do with a stream. 35 * would do with a stream.
36 * 36 *
37 * Some features for convenient use of the buffer 37 * Some features for convenient use of the buffer
38 * can be enabled. See the documentation of the macro constants for more 38 * can be enabled. See the documentation of the macro constants for more
39 * information. 39 * information.
40 * 40 *
41 * \author Mike Becker 41 * @author Mike Becker
42 * \author Olaf Wintermann 42 * @author Olaf Wintermann
43 * \copyright 2-Clause BSD License 43 * @copyright 2-Clause BSD License
44 */ 44 */
45 45
46 #ifndef UCX_BUFFER_H 46 #ifndef UCX_BUFFER_H
47 #define UCX_BUFFER_H 47 #define UCX_BUFFER_H
48 48
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 90
91 /**
92 * Function pointer for cxBufferWrite that is compatible with cx_write_func.
93 * @see cx_write_func
94 */
95 #define cxBufferWriteFunc ((cx_write_func) cxBufferWrite)
96 /**
97 * Function pointer for cxBufferRead that is compatible with cx_read_func.
98 * @see cx_read_func
99 */
100 #define cxBufferReadFunc ((cx_read_func) cxBufferRead)
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 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
91 /** Structure for the UCX buffer data. */ 156 /** Structure for the UCX buffer data. */
92 typedef struct { 157 struct cx_buffer_s {
93 /** A pointer to the buffer contents. */ 158 /** A pointer to the buffer contents. */
94 union { 159 union {
95 /** 160 /**
96 * Data is interpreted as text. 161 * Data is interpreted as text.
97 */ 162 */
101 */ 166 */
102 unsigned char *bytes; 167 unsigned char *bytes;
103 }; 168 };
104 /** The allocator to use for automatic memory management. */ 169 /** The allocator to use for automatic memory management. */
105 const CxAllocator *allocator; 170 const CxAllocator *allocator;
171 /**
172 * Optional flush configuration
173 *
174 * @see cxBufferEnableFlushing()
175 */
176 CxBufferFlushConfig *flush;
106 /** Current position of the buffer. */ 177 /** Current position of the buffer. */
107 size_t pos; 178 size_t pos;
108 /** Current capacity (i.e. maximum size) of the buffer. */ 179 /** Current capacity (i.e. maximum size) of the buffer. */
109 size_t capacity; 180 size_t capacity;
110 /** Current size of the buffer content. */ 181 /** Current size of the buffer content. */
111 size_t size; 182 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 /** 183 /**
147 * Flag register for buffer features. 184 * Flag register for buffer features.
148 * @see #CX_BUFFER_DEFAULT 185 * @see #CX_BUFFER_DEFAULT
149 * @see #CX_BUFFER_FREE_CONTENTS 186 * @see #CX_BUFFER_FREE_CONTENTS
150 * @see #CX_BUFFER_AUTO_EXTEND 187 * @see #CX_BUFFER_AUTO_EXTEND
151 * @see #CX_BUFFER_COPY_ON_WRITE 188 * @see #CX_BUFFER_COPY_ON_WRITE
152 */ 189 */
153 int flags; 190 int flags;
154 } cx_buffer_s; 191 };
155 192
156 /** 193 /**
157 * UCX buffer. 194 * UCX buffer.
158 */ 195 */
159 typedef cx_buffer_s CxBuffer; 196 typedef struct cx_buffer_s CxBuffer;
160 197
161 /** 198 /**
162 * Initializes a fresh buffer. 199 * Initializes a fresh buffer.
163 * 200 *
164 * You may also provide a read-only \p space, in which case 201 * You may also provide a read-only @p space, in which case
165 * you will need to cast the pointer, and you should set the 202 * you will need to cast the pointer, and you should set the
166 * #CX_BUFFER_COPY_ON_WRITE flag. 203 * #CX_BUFFER_COPY_ON_WRITE flag.
167 * 204 *
168 * You need to set the size manually after initialization, if 205 * You need to set the size manually after initialization, if
169 * you provide \p space which already contains data. 206 * you provide @p space which already contains data.
170 * 207 *
171 * When you specify stack memory as \p space and decide to use 208 * When you specify stack memory as @p space and decide to use
172 * the auto-extension feature, you \em must use the 209 * the auto-extension feature, you @em must use the
173 * #CX_BUFFER_COPY_ON_EXTEND flag, instead of the 210 * #CX_BUFFER_COPY_ON_EXTEND flag, instead of the
174 * #CX_BUFFER_AUTO_EXTEND flag. 211 * #CX_BUFFER_AUTO_EXTEND flag.
175 * 212 *
176 * \note You may provide \c NULL as argument for \p space. 213 * @note You may provide @c NULL as argument for @p space.
177 * Then this function will allocate the space and enforce 214 * Then this function will allocate the space and enforce
178 * the #CX_BUFFER_FREE_CONTENTS flag. In that case, specifying 215 * the #CX_BUFFER_FREE_CONTENTS flag. In that case, specifying
179 * copy-on-write should be avoided, because the allocated 216 * copy-on-write should be avoided, because the allocated
180 * space will be leaking after the copy-on-write operation. 217 * space will be leaking after the copy-on-write operation.
181 * 218 *
182 * @param buffer the buffer to initialize 219 * @param buffer the buffer to initialize
183 * @param space pointer to the memory area, or \c NULL to allocate 220 * @param space pointer to the memory area, or @c NULL to allocate
184 * new memory 221 * new memory
185 * @param capacity the capacity of the buffer 222 * @param capacity the capacity of the buffer
186 * @param allocator the allocator this buffer shall use for automatic 223 * @param allocator the allocator this buffer shall use for automatic
187 * memory management 224 * memory management
188 * (if \c NULL, a default stdlib allocator will be used) 225 * (if @c NULL, a default stdlib allocator will be used)
189 * @param flags buffer features (see cx_buffer_s.flags) 226 * @param flags buffer features (see cx_buffer_s.flags)
190 * @return zero on success, non-zero if a required allocation failed 227 * @return zero on success, non-zero if a required allocation failed
191 */ 228 */
192 cx_attr_nonnull_arg(1) 229 cx_attr_nonnull_arg(1)
230 cx_attr_export
193 int cxBufferInit( 231 int cxBufferInit(
194 CxBuffer *buffer, 232 CxBuffer *buffer,
195 void *space, 233 void *space,
196 size_t capacity, 234 size_t capacity,
197 const CxAllocator *allocator, 235 const CxAllocator *allocator,
198 int flags 236 int flags
199 ); 237 );
200 238
201 /** 239 /**
240 * Configures the buffer for flushing.
241 *
242 * Flushing can happen automatically when data is written
243 * to the buffer (see cxBufferWrite()) or manually when
244 * cxBufferFlush() is called.
245 *
246 * @param buffer the buffer
247 * @param config the flush configuration
248 * @retval zero success
249 * @retval non-zero failure
250 * @see cxBufferFlush()
251 * @see cxBufferWrite()
252 */
253 cx_attr_nonnull
254 cx_attr_export
255 int cxBufferEnableFlushing(
256 CxBuffer *buffer,
257 CxBufferFlushConfig config
258 );
259
260 /**
202 * Destroys the buffer contents. 261 * Destroys the buffer contents.
203 * 262 *
204 * Has no effect if the #CX_BUFFER_FREE_CONTENTS feature is not enabled. 263 * 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(). 264 * If you want to free the memory of the entire buffer, use cxBufferFree().
206 * 265 *
207 * @param buffer the buffer which contents shall be destroyed 266 * @param buffer the buffer which contents shall be destroyed
208 * @see cxBufferInit() 267 * @see cxBufferInit()
209 */ 268 */
210 cx_attr_nonnull 269 cx_attr_nonnull
270 cx_attr_export
211 void cxBufferDestroy(CxBuffer *buffer); 271 void cxBufferDestroy(CxBuffer *buffer);
212 272
213 /** 273 /**
214 * Deallocates the buffer. 274 * Deallocates the buffer.
215 * 275 *
216 * If the #CX_BUFFER_FREE_CONTENTS feature is enabled, this function also destroys 276 * If the #CX_BUFFER_FREE_CONTENTS feature is enabled, this function also destroys
217 * the contents. If you \em only want to destroy the contents, use cxBufferDestroy(). 277 * the contents. If you @em only want to destroy the contents, use cxBufferDestroy().
218 * 278 *
219 * \remark As with all free() functions, this accepts \c NULL arguments in which 279 * @remark As with all free() functions, this accepts @c NULL arguments in which
220 * case it does nothing. 280 * case it does nothing.
221 * 281 *
222 * @param buffer the buffer to deallocate 282 * @param buffer the buffer to deallocate
223 * @see cxBufferCreate() 283 * @see cxBufferCreate()
224 */ 284 */
285 cx_attr_export
225 void cxBufferFree(CxBuffer *buffer); 286 void cxBufferFree(CxBuffer *buffer);
226 287
227 /** 288 /**
228 * Allocates and initializes a fresh buffer. 289 * Allocates and initializes a fresh buffer.
229 * 290 *
230 * You may also provide a read-only \p space, in which case 291 * You may also provide a read-only @p space, in which case
231 * you will need to cast the pointer, and you should set the 292 * you will need to cast the pointer, and you should set the
232 * #CX_BUFFER_COPY_ON_WRITE flag. 293 * #CX_BUFFER_COPY_ON_WRITE flag.
233 * When you specify stack memory as \p space and decide to use 294 * When you specify stack memory as @p space and decide to use
234 * the auto-extension feature, you \em must use the 295 * the auto-extension feature, you @em must use the
235 * #CX_BUFFER_COPY_ON_EXTEND flag, instead of the 296 * #CX_BUFFER_COPY_ON_EXTEND flag, instead of the
236 * #CX_BUFFER_AUTO_EXTEND flag. 297 * #CX_BUFFER_AUTO_EXTEND flag.
237 * 298 *
238 * \note You may provide \c NULL as argument for \p space. 299 * @note You may provide @c NULL as argument for @p space.
239 * Then this function will allocate the space and enforce 300 * Then this function will allocate the space and enforce
240 * the #CX_BUFFER_FREE_CONTENTS flag. 301 * the #CX_BUFFER_FREE_CONTENTS flag.
241 * 302 *
242 * @param space pointer to the memory area, or \c NULL to allocate 303 * @param space pointer to the memory area, or @c NULL to allocate
243 * new memory 304 * new memory
244 * @param capacity the capacity of the buffer 305 * @param capacity the capacity of the buffer
245 * @param allocator the allocator to use for allocating the structure and the automatic 306 * @param allocator the allocator to use for allocating the structure and the automatic
246 * memory management within the buffer 307 * memory management within the buffer
247 * (if \c NULL, a default stdlib allocator will be used) 308 * (if @c NULL, a default stdlib allocator will be used)
248 * @param flags buffer features (see cx_buffer_s.flags) 309 * @param flags buffer features (see cx_buffer_s.flags)
249 * @return a pointer to the buffer on success, \c NULL if a required allocation failed 310 * @return a pointer to the buffer on success, @c NULL if a required allocation failed
250 */ 311 */
251 cx_attr_malloc 312 cx_attr_malloc
252 cx_attr_dealloc(cxBufferFree, 1) 313 cx_attr_dealloc(cxBufferFree, 1)
253 cx_attr_nodiscard 314 cx_attr_nodiscard
315 cx_attr_export
254 CxBuffer *cxBufferCreate( 316 CxBuffer *cxBufferCreate(
255 void *space, 317 void *space,
256 size_t capacity, 318 size_t capacity,
257 const CxAllocator *allocator, 319 const CxAllocator *allocator,
258 int flags 320 int flags
267 * no contents are changed. 329 * no contents are changed.
268 * If auto extension is disabled, the contents that do not fit into the buffer 330 * If auto extension is disabled, the contents that do not fit into the buffer
269 * are discarded. 331 * are discarded.
270 * 332 *
271 * If the offset is negative, the contents are shifted to the left where the 333 * If the offset is negative, the contents are shifted to the left where the
272 * first \p shift bytes are discarded. 334 * first @p shift bytes are discarded.
273 * The new size of the buffer is the old size minus the absolute shift value. 335 * The new size of the buffer is the old size minus the absolute shift value.
274 * If this value is larger than the buffer size, the buffer is emptied (but 336 * If this value is larger than the buffer size, the buffer is emptied (but
275 * not cleared, see the security note below). 337 * not cleared, see the security note below).
276 * 338 *
277 * The buffer position gets shifted alongside with the content but is kept 339 * The buffer position gets shifted alongside with the content but is kept
278 * within the boundaries of the buffer. 340 * within the boundaries of the buffer.
279 * 341 *
280 * \note For situations where \c off_t is not large enough, there are specialized cxBufferShiftLeft() and 342 * @note For situations where @c off_t is not large enough, there are specialized cxBufferShiftLeft() and
281 * cxBufferShiftRight() functions using a \c size_t as parameter type. 343 * cxBufferShiftRight() functions using a @c size_t as parameter type.
282 * 344 *
283 * \attention 345 * @attention
284 * Security Note: The shifting operation does \em not erase the previously occupied memory cells. 346 * Security Note: The shifting operation does @em not erase the previously occupied memory cells.
285 * But you can easily do that manually, e.g. by calling 347 * But you can easily do that manually, e.g. by calling
286 * <code>memset(buffer->bytes, 0, shift)</code> for a right shift or 348 * <code>memset(buffer->bytes, 0, shift)</code> for a right shift or
287 * <code>memset(buffer->bytes + buffer->size, 0, buffer->capacity - buffer->size)</code> 349 * <code>memset(buffer->bytes + buffer->size, 0, buffer->capacity - buffer->size)</code>
288 * for a left shift. 350 * for a left shift.
289 * 351 *
290 * @param buffer the buffer 352 * @param buffer the buffer
291 * @param shift the shift offset (negative means left shift) 353 * @param shift the shift offset (negative means left shift)
292 * @return 0 on success, non-zero if a required auto-extension or copy-on-write fails 354 * @retval zero success
293 */ 355 * @retval non-zero if a required auto-extension or copy-on-write fails
294 cx_attr_nonnull 356 * @see cxBufferShiftLeft()
357 * @see cxBufferShiftRight()
358 */
359 cx_attr_nonnull
360 cx_attr_export
295 int cxBufferShift( 361 int cxBufferShift(
296 CxBuffer *buffer, 362 CxBuffer *buffer,
297 off_t shift 363 off_t shift
298 ); 364 );
299 365
301 * Shifts the buffer to the right. 367 * Shifts the buffer to the right.
302 * See cxBufferShift() for details. 368 * See cxBufferShift() for details.
303 * 369 *
304 * @param buffer the buffer 370 * @param buffer the buffer
305 * @param shift the shift offset 371 * @param shift the shift offset
306 * @return 0 on success, non-zero if a required auto-extension or copy-on-write fails 372 * @retval zero success
373 * @retval non-zero if a required auto-extension or copy-on-write fails
307 * @see cxBufferShift() 374 * @see cxBufferShift()
308 */ 375 */
309 cx_attr_nonnull 376 cx_attr_nonnull
377 cx_attr_export
310 int cxBufferShiftRight( 378 int cxBufferShiftRight(
311 CxBuffer *buffer, 379 CxBuffer *buffer,
312 size_t shift 380 size_t shift
313 ); 381 );
314 382
316 * Shifts the buffer to the left. 384 * Shifts the buffer to the left.
317 * See cxBufferShift() for details. 385 * See cxBufferShift() for details.
318 * 386 *
319 * @param buffer the buffer 387 * @param buffer the buffer
320 * @param shift the positive shift offset 388 * @param shift the positive shift offset
321 * @return usually zero, except the buffer uses copy-on-write and the allocation fails 389 * @retval zero success
390 * @retval non-zero if the buffer uses copy-on-write and the allocation fails
322 * @see cxBufferShift() 391 * @see cxBufferShift()
323 */ 392 */
324 cx_attr_nonnull 393 cx_attr_nonnull
394 cx_attr_export
325 int cxBufferShiftLeft( 395 int cxBufferShiftLeft(
326 CxBuffer *buffer, 396 CxBuffer *buffer,
327 size_t shift 397 size_t shift
328 ); 398 );
329 399
330 400
331 /** 401 /**
332 * Moves the position of the buffer. 402 * Moves the position of the buffer.
333 * 403 *
334 * The new position is relative to the \p whence argument. 404 * The new position is relative to the @p whence argument.
335 * 405 *
336 * \li \c SEEK_SET marks the start of the buffer. 406 * @li @c SEEK_SET marks the start of the buffer.
337 * \li \c SEEK_CUR marks the current position. 407 * @li @c SEEK_CUR marks the current position.
338 * \li \c SEEK_END marks the end of the buffer. 408 * @li @c SEEK_END marks the end of the buffer.
339 * 409 *
340 * With an offset of zero, this function sets the buffer position to zero 410 * With an offset of zero, this function sets the buffer position to zero
341 * (\c SEEK_SET), the buffer size (\c SEEK_END) or leaves the buffer position 411 * (@c SEEK_SET), the buffer size (@c SEEK_END) or leaves the buffer position
342 * unchanged (\c SEEK_CUR). 412 * unchanged (@c SEEK_CUR).
343 * 413 *
344 * @param buffer the buffer 414 * @param buffer the buffer
345 * @param offset position offset relative to \p whence 415 * @param offset position offset relative to @p whence
346 * @param whence one of \c SEEK_SET, \c SEEK_CUR or \c SEEK_END 416 * @param whence one of @c SEEK_SET, @c SEEK_CUR or @c SEEK_END
347 * @return 0 on success, non-zero if the position is invalid 417 * @retval zero success
348 * 418 * @retval non-zero if the position is invalid
349 */ 419 *
350 cx_attr_nonnull 420 */
421 cx_attr_nonnull
422 cx_attr_export
351 int cxBufferSeek( 423 int cxBufferSeek(
352 CxBuffer *buffer, 424 CxBuffer *buffer,
353 off_t offset, 425 off_t offset,
354 int whence 426 int whence
355 ); 427 );
358 * Clears the buffer by resetting the position and deleting the data. 430 * Clears the buffer by resetting the position and deleting the data.
359 * 431 *
360 * The data is deleted by zeroing it with a call to memset(). 432 * The data is deleted by zeroing it with a call to memset().
361 * If you do not need that, you can use the faster cxBufferReset(). 433 * If you do not need that, you can use the faster cxBufferReset().
362 * 434 *
363 * \note If the #CX_BUFFER_COPY_ON_WRITE flag is set, this function 435 * @note If the #CX_BUFFER_COPY_ON_WRITE flag is set, this function
364 * will not erase the data and behave exactly as cxBufferReset(). 436 * will not erase the data and behave exactly as cxBufferReset().
365 * 437 *
366 * @param buffer the buffer to be cleared 438 * @param buffer the buffer to be cleared
367 * @see cxBufferReset() 439 * @see cxBufferReset()
368 */ 440 */
369 cx_attr_nonnull 441 cx_attr_nonnull
442 cx_attr_export
370 void cxBufferClear(CxBuffer *buffer); 443 void cxBufferClear(CxBuffer *buffer);
371 444
372 /** 445 /**
373 * Resets the buffer by resetting the position and size to zero. 446 * Resets the buffer by resetting the position and size to zero.
374 * 447 *
377 * 450 *
378 * @param buffer the buffer to be cleared 451 * @param buffer the buffer to be cleared
379 * @see cxBufferClear() 452 * @see cxBufferClear()
380 */ 453 */
381 cx_attr_nonnull 454 cx_attr_nonnull
455 cx_attr_export
382 void cxBufferReset(CxBuffer *buffer); 456 void cxBufferReset(CxBuffer *buffer);
383 457
384 /** 458 /**
385 * Tests, if the buffer position has exceeded the buffer size. 459 * Tests, if the buffer position has exceeded the buffer size.
386 * 460 *
387 * @param buffer the buffer to test 461 * @param buffer the buffer to test
388 * @return true, if the current buffer position has exceeded the last 462 * @retval true if the current buffer position has exceeded the last
389 * byte of the buffer's contents. 463 * byte of the buffer's contents
464 * @retval false otherwise
390 */ 465 */
391 cx_attr_nonnull 466 cx_attr_nonnull
392 cx_attr_nodiscard 467 cx_attr_nodiscard
468 cx_attr_export
393 bool cxBufferEof(const CxBuffer *buffer); 469 bool cxBufferEof(const CxBuffer *buffer);
394 470
395 471
396 /** 472 /**
397 * Ensures that the buffer has a minimum capacity. 473 * Ensures that the buffer has a minimum capacity.
398 * 474 *
399 * If the current capacity is not sufficient, the buffer will be extended. 475 * If the current capacity is not sufficient, the buffer will be extended.
400 * 476 *
401 * @param buffer the buffer 477 * @param buffer the buffer
402 * @param capacity the minimum required capacity for this buffer 478 * @param capacity the minimum required capacity for this buffer
403 * @return 0 on success or a non-zero value on failure 479 * @retval zero the capacity was already sufficient or successfully increased
404 */ 480 * @retval non-zero on allocation failure
405 cx_attr_nonnull 481 */
482 cx_attr_nonnull
483 cx_attr_export
406 int cxBufferMinimumCapacity( 484 int cxBufferMinimumCapacity(
407 CxBuffer *buffer, 485 CxBuffer *buffer,
408 size_t capacity 486 size_t capacity
409 ); 487 );
410 488
411 /** 489 /**
412 * Writes data to a CxBuffer. 490 * Writes data to a CxBuffer.
491 *
492 * If automatic flushing is not enabled, the data is simply written into the
493 * buffer at the current position and the position of the buffer is increased
494 * by the number of bytes written.
413 * 495 *
414 * If flushing is enabled and the buffer needs to flush, the data is flushed to 496 * If flushing is enabled and the buffer needs to flush, the data is flushed to
415 * the target until the target signals that it cannot take more data by 497 * the target until the target signals that it cannot take more data by
416 * returning zero via the respective write function. In that case, the remaining 498 * returning zero via the respective write function. In that case, the remaining
417 * data in this buffer is shifted to the beginning of this buffer so that the 499 * data in this buffer is shifted to the beginning of this buffer so that the
418 * newly available space can be used to append as much data as possible. This 500 * newly available space can be used to append as much data as possible.
419 * function only stops writing more elements, when the flush target and this 501 *
502 * This function only stops writing more elements, when the flush target and this
420 * buffer are both incapable of taking more data or all data has been written. 503 * buffer are both incapable of taking more data or all data has been written.
421 * The number returned by this function is the total number of elements that 504 *
422 * could be written during the process. It does not necessarily mean that those 505 * If, after flushing, the number of items that shall be written still exceeds
423 * elements are still in this buffer, because some of them could have also be 506 * the capacity or flush threshold, this function tries to write all items directly
424 * flushed already. 507 * to the flush target, if possible.
425 * 508 *
426 * If automatic flushing is not enabled, the position of the buffer is increased 509 * The number returned by this function is the number of elements from
427 * by the number of bytes written. 510 * @c ptr that could be written to either the flush target or the buffer
428 * 511 * (so it does not include the number of items that had been already in the buffer
429 * \note The signature is compatible with the fwrite() family of functions. 512 * in were flushed during the process).
513 *
514 * @attention
515 * When @p size is larger than one and the contents of the buffer are not aligned
516 * with @p size, flushing stops after all complete items have been flushed, leaving
517 * the mis-aligned part in the buffer.
518 * Afterward, this function only writes as many items as possible to the buffer.
519 *
520 * @note The signature is compatible with the fwrite() family of functions.
430 * 521 *
431 * @param ptr a pointer to the memory area containing the bytes to be written 522 * @param ptr a pointer to the memory area containing the bytes to be written
432 * @param size the length of one element 523 * @param size the length of one element
433 * @param nitems the element count 524 * @param nitems the element count
434 * @param buffer the CxBuffer to write to 525 * @param buffer the CxBuffer to write to
435 * @return the total count of elements written 526 * @return the total count of elements written
436 */ 527 * @see cxBufferAppend()
437 cx_attr_nonnull 528 * @see cxBufferRead()
529 */
530 cx_attr_nonnull
531 cx_attr_export
438 size_t cxBufferWrite( 532 size_t cxBufferWrite(
439 const void *ptr, 533 const void *ptr,
440 size_t size, 534 size_t size,
441 size_t nitems, 535 size_t nitems,
442 CxBuffer *buffer 536 CxBuffer *buffer
449 * regardless of the current position. 543 * regardless of the current position.
450 * This is especially useful when the buffer is primarily meant for reading 544 * This is especially useful when the buffer is primarily meant for reading
451 * while additional data is added to the buffer occasionally. 545 * while additional data is added to the buffer occasionally.
452 * Consequently, the position of the buffer is unchanged after this operation. 546 * Consequently, the position of the buffer is unchanged after this operation.
453 * 547 *
454 * \note The signature is compatible with the fwrite() family of functions. 548 * @note The signature is compatible with the fwrite() family of functions.
455 * 549 *
456 * @param ptr a pointer to the memory area containing the bytes to be written 550 * @param ptr a pointer to the memory area containing the bytes to be written
457 * @param size the length of one element 551 * @param size the length of one element
458 * @param nitems the element count 552 * @param nitems the element count
459 * @param buffer the CxBuffer to write to 553 * @param buffer the CxBuffer to write to
460 * @return the total count of elements written 554 * @return the total count of elements written
461 * @see cxBufferWrite() 555 * @see cxBufferWrite()
462 */ 556 * @see cxBufferRead()
463 cx_attr_nonnull 557 */
558 cx_attr_nonnull
559 cx_attr_export
464 size_t cxBufferAppend( 560 size_t cxBufferAppend(
465 const void *ptr, 561 const void *ptr,
466 size_t size, 562 size_t size,
467 size_t nitems, 563 size_t nitems,
468 CxBuffer *buffer 564 CxBuffer *buffer
469 ); 565 );
470 566
471 /** 567 /**
568 * Performs a single flush-run on the specified buffer.
569 *
570 * Does nothing when the position in the buffer is zero.
571 * Otherwise, the data until the current position minus
572 * one is considered for flushing.
573 * Note carefully that flushing will never exceed the
574 * current @em position, even when the size of the
575 * buffer is larger than the current position.
576 *
577 * One flush run will try to flush @c blkmax many
578 * blocks of size @c blksize until either the @p buffer
579 * has no more data to flush or the write function
580 * used for flushing returns zero.
581 *
582 * The buffer is shifted left for that many bytes
583 * the flush operation has successfully flushed.
584 *
585 * @par Example 1
586 * Assume you have a buffer with size 340 and you are
587 * at position 200. The flush configuration is
588 * @c blkmax=4 and @c blksize=64 .
589 * Assume that the entire flush operation is successful.
590 * All 200 bytes on the left hand-side from the current
591 * position are written.
592 * That means, the size of the buffer is now 140 and the
593 * position is zero.
594 *
595 * @par Example 2
596 * Same as Example 1, but now the @c blkmax is 1.
597 * The size of the buffer is now 276 and the position is 136.
598 *
599 * @par Example 3
600 * Same as Example 1, but now assume the flush target
601 * only accepts 100 bytes before returning zero.
602 * That means, the flush operations manages to flush
603 * one complete block and one partial block, ending
604 * up with a buffer with size 240 and position 100.
605 *
606 * @remark Just returns zero when flushing was not enabled with
607 * cxBufferEnableFlushing().
608 *
609 * @remark When the buffer uses copy-on-write, the memory
610 * is copied first, before attempting any flush.
611 * This is, however, considered an erroneous use of the
612 * buffer, because it does not make much sense to put
613 * readonly data into an UCX buffer for flushing, instead
614 * of writing it directly to the target.
615 *
616 * @param buffer the buffer
617 * @return the number of successfully flushed bytes
618 * @see cxBufferEnableFlushing()
619 */
620 cx_attr_nonnull
621 cx_attr_export
622 size_t cxBufferFlush(CxBuffer *buffer);
623
624 /**
472 * Reads data from a CxBuffer. 625 * Reads data from a CxBuffer.
473 * 626 *
474 * The position of the buffer is increased by the number of bytes read. 627 * The position of the buffer is increased by the number of bytes read.
475 * 628 *
476 * \note The signature is compatible with the fread() family of functions. 629 * @note The signature is compatible with the fread() family of functions.
477 * 630 *
478 * @param ptr a pointer to the memory area where to store the read data 631 * @param ptr a pointer to the memory area where to store the read data
479 * @param size the length of one element 632 * @param size the length of one element
480 * @param nitems the element count 633 * @param nitems the element count
481 * @param buffer the CxBuffer to read from 634 * @param buffer the CxBuffer to read from
482 * @return the total number of elements read 635 * @return the total number of elements read
483 */ 636 * @see cxBufferWrite()
484 cx_attr_nonnull 637 * @see cxBufferAppend()
638 */
639 cx_attr_nonnull
640 cx_attr_export
485 size_t cxBufferRead( 641 size_t cxBufferRead(
486 void *ptr, 642 void *ptr,
487 size_t size, 643 size_t size,
488 size_t nitems, 644 size_t nitems,
489 CxBuffer *buffer 645 CxBuffer *buffer
493 * Writes a character to a buffer. 649 * Writes a character to a buffer.
494 * 650 *
495 * The least significant byte of the argument is written to the buffer. If the 651 * The least significant byte of the argument is written to the buffer. If the
496 * end of the buffer is reached and #CX_BUFFER_AUTO_EXTEND feature is enabled, 652 * end of the buffer is reached and #CX_BUFFER_AUTO_EXTEND feature is enabled,
497 * the buffer capacity is extended by cxBufferMinimumCapacity(). If the feature 653 * the buffer capacity is extended by cxBufferMinimumCapacity(). If the feature
498 * is disabled or buffer extension fails, \c EOF is returned. 654 * is disabled or buffer extension fails, @c EOF is returned.
499 * 655 *
500 * On successful write, the position of the buffer is increased. 656 * On successful write, the position of the buffer is increased.
657 *
658 * If you just want to write a null-terminator at the current position, you
659 * should use cxBufferTerminate() instead.
501 * 660 *
502 * @param buffer the buffer to write to 661 * @param buffer the buffer to write to
503 * @param c the character to write 662 * @param c the character to write
504 * @return the byte that has been written or \c EOF when the end of the stream is 663 * @return the byte that has been written or @c EOF when the end of the stream is
505 * reached and automatic extension is not enabled or not possible 664 * reached and automatic extension is not enabled or not possible
506 */ 665 * @see cxBufferTerminate()
507 cx_attr_nonnull 666 */
667 cx_attr_nonnull
668 cx_attr_export
508 int cxBufferPut( 669 int cxBufferPut(
509 CxBuffer *buffer, 670 CxBuffer *buffer,
510 int c 671 int c
511 ); 672 );
512 673
513 /** 674 /**
514 * Writes a terminating zero to a buffer. 675 * Writes a terminating zero to a buffer at the current position.
515 * 676 *
516 * On successful write, \em neither the position \em nor the size of the buffer is 677 * On successful write, @em neither the position @em nor the size of the buffer is
517 * increased. 678 * increased.
518 * 679 *
519 * The purpose of this function is to have the written data ready to be used as 680 * The purpose of this function is to have the written data ready to be used as
520 * a C string. 681 * a C string.
521 * 682 *
522 * @param buffer the buffer to write to 683 * @param buffer the buffer to write to
523 * @return zero, if the terminator could be written, non-zero otherwise 684 * @return zero, if the terminator could be written, non-zero otherwise
524 */ 685 */
525 cx_attr_nonnull 686 cx_attr_nonnull
687 cx_attr_export
526 int cxBufferTerminate(CxBuffer *buffer); 688 int cxBufferTerminate(CxBuffer *buffer);
527 689
528 /** 690 /**
529 * Writes a string to a buffer. 691 * Writes a string to a buffer.
692 *
693 * This is a convenience function for <code>cxBufferWrite(str, 1, strlen(str), buffer)</code>.
530 * 694 *
531 * @param buffer the buffer 695 * @param buffer the buffer
532 * @param str the zero-terminated string 696 * @param str the zero-terminated string
533 * @return the number of bytes written 697 * @return the number of bytes written
534 */ 698 */
535 cx_attr_nonnull 699 cx_attr_nonnull
536 cx_attr_cstr_arg(2) 700 cx_attr_cstr_arg(2)
701 cx_attr_export
537 size_t cxBufferPutString( 702 size_t cxBufferPutString(
538 CxBuffer *buffer, 703 CxBuffer *buffer,
539 const char *str 704 const char *str
540 ); 705 );
541 706
543 * Gets a character from a buffer. 708 * Gets a character from a buffer.
544 * 709 *
545 * The current position of the buffer is increased after a successful read. 710 * The current position of the buffer is increased after a successful read.
546 * 711 *
547 * @param buffer the buffer to read from 712 * @param buffer the buffer to read from
548 * @return the character or \c EOF, if the end of the buffer is reached 713 * @return the character or @c EOF, if the end of the buffer is reached
549 */ 714 */
550 cx_attr_nonnull 715 cx_attr_nonnull
716 cx_attr_export
551 int cxBufferGet(CxBuffer *buffer); 717 int cxBufferGet(CxBuffer *buffer);
552 718
553 #ifdef __cplusplus 719 #ifdef __cplusplus
554 } 720 }
555 #endif 721 #endif

mercurial