docs/Writerside/topics/buffer.h.md

changeset 1571
25ead2ffb9b5
parent 1542
197450c2b0b3
equal deleted inserted replaced
1570:8fd491bc2940 1571:25ead2ffb9b5
4 4
5 This allows the use of `cx_stream_copy()` (see [](streams.h.md)) to copy contents from one buffer to another, 5 This allows the use of `cx_stream_copy()` (see [](streams.h.md)) to copy contents from one buffer to another,
6 or from a file or network stream to the buffer and vice versa. 6 or from a file or network stream to the buffer and vice versa.
7 7
8 More features for convenient use of the buffer can be enabled, like automatic memory management, 8 More features for convenient use of the buffer can be enabled, like automatic memory management,
9 automatic resizing of the buffer space, or automatic flushing of contents. 9 or automatic resizing of the buffer space.
10 10
11 The functions `cxBufferRead()` and `cxBufferWrite()` are `cx_read_func` and `cx_write_func` compatible, 11 The functions `cxBufferRead()` and `cxBufferWrite()` are `cx_read_func` and `cx_write_func` compatible,
12 which in turn have a compatible signature to `fread()` and `fwrite()`. 12 which in turn have a compatible signature to `fread()` and `fwrite()`.
13 However, due to the different pointer type the function pointers do not type check out of the box. 13 However, due to the different pointer type the function pointers do not type check out of the box.
14 For convenience, the macros `cxBufferReadFunc` and `cxBufferWriteFunc` are defined, which perform the necessary cast. 14 For convenience, the macros `cxBufferReadFunc` and `cxBufferWriteFunc` are defined, which perform the necessary cast.
120 ## Capacity Management 120 ## Capacity Management
121 121
122 ```C 122 ```C
123 #include <cx/buffer.h> 123 #include <cx/buffer.h>
124 124
125 int cxBufferMaximumCapacity(CxBuffer *buffer, size_t capacity);
126
127 int cxBufferMinimumCapacity(CxBuffer *buffer, size_t capacity);
128
125 int cxBufferReserve(CxBuffer *buffer, size_t capacity); 129 int cxBufferReserve(CxBuffer *buffer, size_t capacity);
126 130
127 int cxBufferMinimumCapacity(CxBuffer *buffer, size_t capacity);
128
129 void cxBufferShrink(CxBuffer *buffer, size_t reserve); 131 void cxBufferShrink(CxBuffer *buffer, size_t reserve);
130 ``` 132 ```
133
134 The function `cxBufferMaximumCapacity()` specifies an upper limit for auto-growing the buffer's capacity.
135 If the new threshold is smaller than the current capacity, this function fails and returns non-zero.
131 136
132 The function `cxBufferMinimumCapacity()` guarantees a buffer capacity of _at least_ `capacity`. 137 The function `cxBufferMinimumCapacity()` guarantees a buffer capacity of _at least_ `capacity`.
133 It will grow the capacity in powers of two until the system's page size is reached. 138 It will grow the capacity in powers of two until the system's page size is reached.
134 Then, the new capacity will be a multiple of the page size. 139 Then, the new capacity will be a multiple of the page size.
135 The function returns non-zero if increasing the capacity was attempted unsuccessfully. 140 The function returns non-zero if increasing the capacity was attempted unsuccessfully;
141 that includes attempts to specify a minimum capacity that exceeds the maximum capacity.
136 142
137 The function `cxBufferReserve()`, on the other hand, will reallocate the buffer's space to match exactly the requested `capacity` 143 The function `cxBufferReserve()`, on the other hand, will reallocate the buffer's space to match exactly the requested `capacity`
138 and the contents are truncated if required. 144 and the contents are truncated if required.
139 145
140 You should use `cxBufferReserve()` when you know precisely the required capacity beforehand 146 You should use `cxBufferReserve()` when you know precisely the required capacity beforehand
145 If the current capacity is not larger than the size plus the reserve bytes, the function will do nothing. 151 If the current capacity is not larger than the size plus the reserve bytes, the function will do nothing.
146 152
147 > If the buffer is in a copy-on-write state, `cxBufferMinimumCapacity()` will perform the copy-on-write action 153 > If the buffer is in a copy-on-write state, `cxBufferMinimumCapacity()` will perform the copy-on-write action
148 > before reallocating the space. 154 > before reallocating the space.
149 > The function `cxBufferShrink()` on the other hand does _nothing_ when the buffer is in a copy-on-write state, 155 > The function `cxBufferShrink()` on the other hand does _nothing_ when the buffer is in a copy-on-write state,
150 > because it does not make much sense to copy the memory just to have it in a smaller memory region. 156 > because it makes little sense to copy the memory just to have it in a smaller memory region.
151 157
152 ## Write 158 ## Write
153 159
154 ```C 160 ```C
155 #include <cx/buffer.h> 161 #include <cx/buffer.h>
170 The primary function for writing to a buffer is `cxBufferWrite()` 176 The primary function for writing to a buffer is `cxBufferWrite()`
171 which writes up to `nitems` with `size` bytes each from the memory pointed to by `ptr` to the buffer. 177 which writes up to `nitems` with `size` bytes each from the memory pointed to by `ptr` to the buffer.
172 178
173 When the capacity of the buffer is not sufficient and the `CX_BUFFER_AUTO_EXTEND` is not set in the buffer, 179 When the capacity of the buffer is not sufficient and the `CX_BUFFER_AUTO_EXTEND` is not set in the buffer,
174 items that do not fit into the buffer are discarded. 180 items that do not fit into the buffer are discarded.
175 The function always returns the actual number of items successfully written. 181 The function then returns the actual number of items successfully written.
176 This equals the number of bytes if and only if `size=1`. 182 This equals the number of bytes if and only if `size=1`.
183 If `CX_BUFFER_AUTO_EXTEND` is set, the buffer is grown to it's maximum capacity
184 (see `cxBufferMaximumCapacity()` in [](#capacity-management)).
185 In case the allocation for auto-extension fails, the function immediately returns zero and does not write any data.
177 186
178 The function `cxBufferPut()` is a `putc()`-like wrapper for `cxBufferWrite()` which writes the character `c`, 187 The function `cxBufferPut()` is a `putc()`-like wrapper for `cxBufferWrite()` which writes the character `c`,
179 converted to an `unsigned char` to the buffer. 188 converted to an `unsigned char` to the buffer.
180 Just like `putc()` this function returns the written character on success, and `EOF` on failure, 189 Just like `putc()` this function returns the written character on success, and `EOF` on failure,
181 but it does _not_ set `errno` on failure. 190 but it does _not_ set `errno` on failure.
188 On the other hand, `cxBufferTerminate()` writes a zero-byte at the current position, 197 On the other hand, `cxBufferTerminate()` writes a zero-byte at the current position,
189 effectively creating a zero-terminated string whose size equals the buffer size. 198 effectively creating a zero-terminated string whose size equals the buffer size.
190 199
191 The function `cxBufferAppend()` writes the data to the end of the buffer (given by its size) regardless of the current position, 200 The function `cxBufferAppend()` writes the data to the end of the buffer (given by its size) regardless of the current position,
192 and it also does _not_ advance the position. 201 and it also does _not_ advance the position.
193 If the write operation triggered a [flush](#flushing), however, the position will be shifted left alongside the shifted buffer contents.
194 In case the data at which the current position points gets flushed, the new position will be zero.
195 202
196 ## Read 203 ## Read
197 204
198 ```C 205 ```C
199 #include <cx/buffer.h> 206 #include <cx/buffer.h>
289 (which means, `cxBufferEof()` returns `true` after the operation). 296 (which means, `cxBufferEof()` returns `true` after the operation).
290 297
291 The functions `cxBufferShiftRight()` and `cxBufferShiftLeft()` accept a larger (but in both cases positive) shift offset, 298 The functions `cxBufferShiftRight()` and `cxBufferShiftLeft()` accept a larger (but in both cases positive) shift offset,
292 which usually makes little sense on a 64-bit platform where `off_t` is already large enough to represent any reasonable offset. 299 which usually makes little sense on a 64-bit platform where `off_t` is already large enough to represent any reasonable offset.
293 You may, however, still use those functions to express more explicitly in your code in which direction you want the contents to be shifted. 300 You may, however, still use those functions to express more explicitly in your code in which direction you want the contents to be shifted.
294
295 ## Flushing
296
297 ```C
298 #include <cx/buffer.h>
299
300 typedef struct cx_buffer_flush_config_s {
301 size_t threshold;
302 size_t blksize;
303 size_t blkmax;
304 void *target;
305 cx_write_func wfunc;
306 } CxBufferFlushConfig;
307
308 int cxBufferEnableFlushing(CxBuffer *buffer,
309 CxBufferFlushConfig config);
310
311 size_t cxBufferFlush(CxBuffer *buffer);
312 ```
313
314 With the function `cxBufferEnableFlushing()` you can configure a flushing strategy for the contents of the buffer.
315
316 Flushing, once enabled, may happen in the following cases:
317 1. when data is written to the buffer, the capacity is insufficient, and `CX_BUFFER_AUTO_EXTEND` is _not_ enabled
318 2. when data is written to the buffer, and the required capacity exceeds the `threshold` configuration
319 3. when `cxBufferFlush()` is called explicitly
320
321 > By combining the `CX_BUFFER_AUTO_EXTEND` flag and the `threshold` setting,
322 > you can create a buffer that initially starts with a small capacity, grows up to a certain threshold,
323 > and starts flushing only when that threshold is exceeded.
324
325 Flushing happens by invoking the `wfunc` up to `blkmax` times, writing up to `blksize` bytes from the buffer to the `target` with each call.
326 The target might not accept all bytes (i.e., the `wfunc` return value indicates that fewer items have been written than requested),
327 in which case the remaining data remains in the buffer.
328 That means the buffer is effectively [shifted](#shift-contents) left by the number of successfully flushed bytes.
329
330 > When you write large amounts of data to a buffer, multiple flush cycles might happen.
331 > After the first flush operations are completed, the reclaimed space in the buffer is filled first, but if that
332 > is not enough, another flush may be triggered within the same invocation of the write operation.
333 >
334 > That means as much data is written to the buffer and/or flushed as possible, until neither the flush target nor the buffer accept more data.
335 > {style="note"}
336
337 > The function `cxBufferFlush()` simply returns zero when flushing was not enabled via `cxBufferEnableFlushing()`.
338 301
339 <seealso> 302 <seealso>
340 <category ref="apidoc"> 303 <category ref="apidoc">
341 <a href="https://ucx.sourceforge.io/api/buffer_8h.html">buffer.h</a> 304 <a href="https://ucx.sourceforge.io/api/buffer_8h.html">buffer.h</a>
342 </category> 305 </category>

mercurial