docs/Writerside/topics/buffer.h.md

changeset 1424
563033aa998c
parent 1298
0597f1f20ea9
equal deleted inserted replaced
1423:9a72258446cd 1424:563033aa998c
1 # Buffer 1 # Buffer
2 2
3 This buffer implementation can be used to read from or write to memory like you would do with a stream. 3 This buffer implementation can be used to read from or write to memory like you would do with a stream.
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 streams 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 automatic resizing of the buffer space, or automatic flushing of contents.
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.
15 15
16 ## Example 16 ## Example
17 17
18 In the following example we use a `CxBuffer`, the `bprintf()` macro from the [UCX printf header](printf.h.md), 18 In the following example we use a `CxBuffer`, the `bprintf()` macro from the [UCX printf header](printf.h.md),
78 #define CX_BUFFER_AUTO_EXTEND 78 #define CX_BUFFER_AUTO_EXTEND
79 #define CX_BUFFER_COPY_ON_WRITE 79 #define CX_BUFFER_COPY_ON_WRITE
80 #define CX_BUFFER_COPY_ON_EXTEND 80 #define CX_BUFFER_COPY_ON_EXTEND
81 ``` 81 ```
82 82
83 For creating a UCX buffer you have two options: initialize a pre-allocated structure, or allocate and initialize a new structure in one call. 83 For creating a UCX buffer, you have two options: initialize a pre-allocated structure, or allocate and initialize a new structure in one call.
84 84
85 For the first option, you can call `cxBufferInit()` with the `buffer` argument pointing to an uninitialized `CxBuffer` structure. 85 For the first option, you can call `cxBufferInit()` with the `buffer` argument pointing to an uninitialized `CxBuffer` structure.
86 You can pass a pre-allocated `space`, the desired `capacity`, and an `allocator`. 86 You can pass a pre-allocated `space`, the desired `capacity`, and an `allocator`.
87 If `space` is `NULL`, the `allocator` is used to allocate enough space to match the desired `capacity`. 87 If `space` is `NULL`, the `allocator` is used to allocate enough space to match the desired `capacity`.
88 88
173 but it does _not_ set `errno` on failure. 173 but it does _not_ set `errno` on failure.
174 174
175 The function `cxBufferPutString()` is a convenience function, 175 The function `cxBufferPutString()` is a convenience function,
176 that uses stdlib `strlen()` to compute the length of `str` and then invokes `cxBufferWrite()`. 176 that uses stdlib `strlen()` to compute the length of `str` and then invokes `cxBufferWrite()`.
177 177
178 All of the above functions advance the buffers position by the number of bytes written, 178 All the above functions advance the buffer position by the number of bytes written
179 and cause the _size_ of the buffer to grow, if necessary, to contain all written bytes. 179 and cause the _size_ of the buffer to grow, if necessary, to contain all written bytes.
180 On the other hand, `cxBufferTerminate()` writes a zero-byte at the current position, 180 On the other hand, `cxBufferTerminate()` writes a zero-byte at the current position,
181 effectively creating a zero-terminated string whose size equals the buffer size. 181 effectively creating a zero-terminated string whose size equals the buffer size.
182 182
183 The function `cxBufferAppend()` writes the data to end of the buffer (given by its size) regardless of the current position, 183 The function `cxBufferAppend()` writes the data to the end of the buffer (given by its size) regardless of the current position,
184 and it also does _not_ advance the position. 184 and it also does _not_ advance the position.
185 If the write operation triggered a [flush](#flushing), however, the position will be shifted left alongside the shifted buffer contents. 185 If the write operation triggered a [flush](#flushing), however, the position will be shifted left alongside the shifted buffer contents.
186 In case the data at which the current position points gets flushed, the new position will be zero. 186 In case the data at which the current position points gets flushed, the new position will be zero.
187 187
188 ## Read 188 ## Read
197 197
198 bool cxBufferEof(const CxBuffer *buffer); 198 bool cxBufferEof(const CxBuffer *buffer);
199 ``` 199 ```
200 200
201 The function `cxBufferRead()` reads `nitems` number of items of `size` bytes each from the `buffer` 201 The function `cxBufferRead()` reads `nitems` number of items of `size` bytes each from the `buffer`
202 and stores them into the memory pointed to by `ptr`, which must be sufficiently large to hold the contents. 202 and stores them into the memory pointed to by `ptr`, which must be large enough to hold the contents.
203 The function returns the actual bytes read, which might be lower, if the desired number of items is not available. 203 The function returns the actual bytes read, which might be lower if the desired number of items is not available.
204 204
205 The function `cxBufferGet()` is a `fgetc()`-like function which returns the next byte in the buffer converted to an `int`. 205 The function `cxBufferGet()` is a `fgetc()`-like function which returns the next byte in the buffer converted to an `int`.
206 Similar to `fgetc()` it returns `EOF` when there are no more bytes in the buffer. 206 Similar to `fgetc()` it returns `EOF` when there are no more bytes in the buffer.
207 207
208 When all bytes from the buffer have been read, the function `cxBufferEof()` returns true. 208 When all bytes from the buffer have been read, the function `cxBufferEof()` returns true.
223 ``` 223 ```
224 224
225 The function `cxBufferReset()` sets both size and position of the buffer to zero, 225 The function `cxBufferReset()` sets both size and position of the buffer to zero,
226 and `cxBufferClear()` additionally uses `memset()` to set every byte in the buffer to zero. 226 and `cxBufferClear()` additionally uses `memset()` to set every byte in the buffer to zero.
227 227
228 > When clearing the buffer, only the "live" data, i.e. bytes with indices `[0..size)`, are cleared. 228 > When clearing the buffer, only the "live" data, i.e., bytes with indices `[0..size)`, are cleared.
229 > If you which to clear the entire buffer's memory, you would need to set the size to the capacity, first. 229 > If you want to clear the entire buffer's memory, you would need to set the size to the capacity, first.
230 230
231 > If the `CX_BUFFER_COPY_ON_WRITE` flag is set, `cxBufferClear()` behaves exactly like `cxBufferReset()`, 231 > If the `CX_BUFFER_COPY_ON_WRITE` flag is set, `cxBufferClear()` behaves exactly like `cxBufferReset()`,
232 > because writing to the contents is disallowed. 232 > because writing to the contents is disallowed.
233 >{style="note"} 233 >{style="note"}
234 234
261 int cxBufferShiftLeft(CxBuffer *buffer, size_t shift); 261 int cxBufferShiftLeft(CxBuffer *buffer, size_t shift);
262 ``` 262 ```
263 263
264 The function `cxBufferShift()` moves the contents within the buffer by the specified `shift` offset, 264 The function `cxBufferShift()` moves the contents within the buffer by the specified `shift` offset,
265 where a negative offset means a shift to the left, and a positive offset means a shift to the right. 265 where a negative offset means a shift to the left, and a positive offset means a shift to the right.
266 It also adjusts the current position within the buffer, and in case of a right shift also the size, by the same offset. 266 It also adjusts the current position within the buffer, and in the case of a right shift also the size, by the same offset.
267 267
268 Data that is shift to the left, is always discarded when the new position of a byte would be smaller than zero. 268 Data shifted to the left is always discarded when the new position of a byte would be smaller than zero.
269 If the new position would be smaller than zero, it is set exactly to zero. 269 If the new position would be smaller than zero, it is set exactly to zero.
270 270
271 When data is shift to the right, the behavior depends on the `CX_BUFFER_AUTO_EXTEND` flag. 271 When data is shift to the right, the behavior depends on the `CX_BUFFER_AUTO_EXTEND` flag.
272 If set, the function extends the buffer's capacity before moving the data. 272 If set, the function extends the buffer's capacity before moving the data.
273 Otherwise, the function discards all data that would exceed the buffer's capacity, and both the size and the position are equal to the capacity 273 Otherwise, the function discards all data that would exceed the buffer's capacity, and both the size and the position are equal to the capacity
274 (which means, `cxBufferEof()` returns `true` after the operation). 274 (which means, `cxBufferEof()` returns `true` after the operation).
275 275
276 The functions `cxBufferShiftRight()` and `cxBufferShiftLeft()` accept a larger (but in both cases positive) shift offset, 276 The functions `cxBufferShiftRight()` and `cxBufferShiftLeft()` accept a larger (but in both cases positive) shift offset,
277 which usually does not make much sense on a 64-bit platform where `off_t` is already large enough to represent any reasonable offset. 277 which usually makes little sense on a 64-bit platform where `off_t` is already large enough to represent any reasonable offset.
278 You may, however, still use those function to express more explicitly in your code in which direction you want the contents to be shifted. 278 You may, however, still use those functions to express more explicitly in your code in which direction you want the contents to be shifted.
279 279
280 ## Flushing 280 ## Flushing
281 281
282 ```C 282 ```C
283 #include <cx/buffer.h> 283 #include <cx/buffer.h>
308 > and starts flushing only when that threshold is exceeded. 308 > and starts flushing only when that threshold is exceeded.
309 309
310 Flushing happens by invoking the `wfunc` up to `blkmax` times, writing up to `blksize` bytes from the buffer to the `target` with each call. 310 Flushing happens by invoking the `wfunc` up to `blkmax` times, writing up to `blksize` bytes from the buffer to the `target` with each call.
311 The target might not accept all bytes (i.e. the `wfunc` return value indicates that fewer items have been written than requested), 311 The target might not accept all bytes (i.e. the `wfunc` return value indicates that fewer items have been written than requested),
312 in which case the remaining data remains in the buffer. 312 in which case the remaining data remains in the buffer.
313 That means, the buffer is effectively [shifted](#shift-contents) left by the number of successfully flushed bytes. 313 That means the buffer is effectively [shifted](#shift-contents) left by the number of successfully flushed bytes.
314 314
315 > When you write large amounts of data to a buffer, multiple flush cycles might happen. 315 > When you write large amounts of data to a buffer, multiple flush cycles might happen.
316 > After the first flush operations completed, the reclaimed space in the buffer is filled first, but if that 316 > After the first flush operations are completed, the reclaimed space in the buffer is filled first, but if that
317 > is not sufficient, another flush may be triggered within the same invocation of the write operation. 317 > is not enough, another flush may be triggered within the same invocation of the write operation.
318 > 318 >
319 > 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. 319 > 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.
320 >{style="note"} 320 >{style="note"}
321 321
322 > The function `cxBufferFlush()` simply returns zero when flushing was not enabled via `cxBufferEnableFlushing()`. 322 > The function `cxBufferFlush()` simply returns zero when flushing was not enabled via `cxBufferEnableFlushing()`.
323 323
324 <seealso> 324 <seealso>

mercurial