universe@103: /* universe@103: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. universe@103: * universe@259: * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved. universe@103: * universe@103: * Redistribution and use in source and binary forms, with or without universe@103: * modification, are permitted provided that the following conditions are met: universe@103: * universe@103: * 1. Redistributions of source code must retain the above copyright universe@103: * notice, this list of conditions and the following disclaimer. universe@103: * universe@103: * 2. Redistributions in binary form must reproduce the above copyright universe@103: * notice, this list of conditions and the following disclaimer in the universe@103: * documentation and/or other materials provided with the distribution. universe@103: * universe@103: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" universe@103: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE universe@103: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE universe@103: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE universe@103: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR universe@103: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF universe@103: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS universe@103: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN universe@103: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) universe@103: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE universe@103: * POSSIBILITY OF SUCH DAMAGE. universe@103: */ universe@103: universe@140: /** universe@140: * @file buffer.h universe@140: * universe@140: * Advanced buffer implementation. universe@140: * universe@140: * Instances of UcxBuffer can be used to read from or to write to like one universe@140: * would do with a stream. This allows the use of ucx_stream_copy() to copy universe@140: * contents from one buffer to another. universe@140: * universe@140: * Some features for convenient use of the buffer universe@140: * can be enabled. See the documentation of the macro constants for more universe@140: * information. universe@140: * universe@140: * @author Mike Becker universe@140: * @author Olaf Wintermann universe@140: */ universe@140: olaf@120: #ifndef UCX_BUFFER_H olaf@120: #define UCX_BUFFER_H universe@56: universe@259: #include "ucx.h" universe@62: #include universe@56: #include universe@56: universe@56: #ifdef __cplusplus universe@56: extern "C" { universe@56: #endif universe@56: universe@140: /** universe@140: * No buffer features enabled (all flags cleared). universe@140: */ universe@61: #define UCX_BUFFER_DEFAULT 0x00 universe@146: universe@140: /** universe@140: * If this flag is enabled, the buffer will automatically free its contents. universe@140: */ universe@61: #define UCX_BUFFER_AUTOFREE 0x01 universe@146: universe@140: /** universe@140: * If this flag is enabled, the buffer will automatically extends its capacity. universe@140: */ universe@63: #define UCX_BUFFER_AUTOEXTEND 0x02 universe@56: universe@140: /** UCX Buffer. */ universe@63: typedef struct { universe@140: /** A pointer to the buffer contents. */ olaf@76: char *space; universe@140: /** Current position of the buffer. */ universe@63: size_t pos; universe@140: /** Current capacity (i.e. maximum size) of the buffer. */ olaf@76: size_t capacity; universe@140: /** Current size of the buffer content. */ universe@63: size_t size; universe@140: /** universe@140: * Flag register for buffer features. universe@140: * @see #UCX_BUFFER_DEFAULT universe@140: * @see #UCX_BUFFER_AUTOFREE universe@140: * @see #UCX_BUFFER_AUTOEXTEND universe@140: */ universe@63: int flags; universe@63: } UcxBuffer; universe@56: universe@140: /** universe@140: * Creates a new buffer. universe@140: * universe@140: * Note: you may provide NULL as argument for universe@140: * space. Then this function will allocate the space and enforce universe@140: * the #UCX_BUFFER_AUTOFREE flag. universe@140: * universe@140: * @param space pointer to the memory area, or NULL to allocate universe@140: * new memory universe@169: * @param capacity the capacity of the buffer universe@140: * @param flags buffer features (see UcxBuffer.flags) universe@140: * @return the new buffer universe@140: */ universe@169: UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags); universe@140: universe@140: /** universe@140: * Destroys a buffer. universe@140: * universe@140: * If the #UCX_BUFFER_AUTOFREE feature is enabled, the contents of the buffer universe@140: * are also freed. universe@140: * universe@140: * @param buffer the buffer to destroy universe@140: */ universe@60: void ucx_buffer_free(UcxBuffer* buffer); universe@56: universe@140: /** universe@140: * Creates a new buffer and fills it with extracted content from another buffer. universe@140: * universe@140: * Note: the #UCX_BUFFER_AUTOFREE feature is enforced for the new buffer. universe@140: * universe@140: * @param src the source buffer universe@140: * @param start the start position of extraction universe@168: * @param length the count of bytes to extract (must not be zero) universe@140: * @param flags feature mask for the new buffer universe@163: * @return a new buffer containing the extraction universe@62: */ olaf@76: UcxBuffer* ucx_buffer_extract(UcxBuffer *src, universe@62: size_t start, size_t length, int flags); universe@140: universe@140: /** universe@140: * A shorthand macro for the full extraction of the buffer. universe@140: * universe@140: * @param src the source buffer universe@140: * @param flags feature mask for the new buffer universe@140: * @return a new buffer with the extracted content universe@140: */ universe@62: #define ucx_buffer_clone(src,flags) \ universe@168: ucx_buffer_extract(src, 0, (src)->capacity, flags) universe@62: universe@140: /** universe@140: * Moves the position of the buffer. universe@140: * universe@140: * The new position is relative to the whence argument. universe@56: * universe@140: * SEEK_SET marks the start of the buffer. universe@140: * SEEK_CUR marks the current position. universe@165: * SEEK_END marks the end of the buffer. universe@165: * universe@165: * With an offset of zero, this function sets the buffer position to zero universe@165: * (SEEK_SET), the buffer size (SEEK_END) or leaves the buffer position universe@165: * unchanged (SEEK_CUR). universe@140: * universe@140: * @param buffer universe@140: * @param offset position offset relative to whence universe@140: * @param whence one of SEEK_SET, SEEK_CUR or SEEK_END universe@140: * @return 0 on success, non-zero if the position is invalid universe@56: * universe@56: */ universe@60: int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence); universe@56: universe@140: /** universe@140: * Clears the buffer by resetting the position and deleting the data. universe@140: * universe@140: * The data is deleted by a zeroing it with call to memset(). universe@140: * universe@140: * @param buffer the buffer to be cleared universe@140: */ universe@140: #define ucx_buffer_clear(buffer) memset(buffer->space, 0, buffer->size); \ universe@140: buffer->size = 0; buffer->pos = 0; universe@85: universe@140: /** universe@140: * Tests, if the buffer position has exceeded the buffer capacity. universe@140: * universe@140: * @param buffer the buffer to test universe@140: * @return non-zero, if the current buffer position has exceeded the last universe@140: * available byte of the buffer. universe@56: */ universe@60: int ucx_buffer_eof(UcxBuffer *buffer); universe@56: olaf@76: universe@140: /** universe@140: * Extends the capacity of the buffer. universe@140: * universe@140: * Note: The buffer capacity increased by a power of two. I.e. universe@140: * the buffer capacity is doubled, as long as it would not hold the current universe@140: * content plus the additional required bytes. universe@140: * universe@168: * Attention: the argument provided is the number of additional universe@168: * bytes the buffer shall hold. It is NOT the total number of bytes the universe@140: * buffer shall hold. universe@140: * universe@140: * @param buffer the buffer to extend universe@168: * @param additional_bytes the number of additional bytes the buffer shall universe@140: * at least hold universe@140: * @return 0 on success or a non-zero value on failure universe@140: */ universe@140: int ucx_buffer_extend(UcxBuffer *buffer, size_t additional_bytes); olaf@76: universe@140: /** universe@225: * Writes data to a UcxBuffer. universe@140: * universe@215: * The position of the buffer is increased by the number of bytes written. universe@140: * universe@140: * @param ptr a pointer to the memory area containing the bytes to be written universe@140: * @param size the length of one element universe@140: * @param nitems the element count universe@140: * @param buffer the UcxBuffer to write to universe@140: * @return the total count of bytes written universe@140: */ olaf@76: size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, olaf@76: UcxBuffer *buffer); olaf@76: universe@140: /** universe@225: * Reads data from a UcxBuffer. universe@140: * universe@140: * The position of the buffer is increased by the number of bytes read. universe@140: * universe@140: * @param ptr a pointer to the memory area where to store the read data universe@140: * @param size the length of one element universe@140: * @param nitems the element count universe@140: * @param buffer the UcxBuffer to read from universe@166: * @return the total number of elements read universe@140: */ olaf@76: size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, olaf@76: UcxBuffer *buffer); olaf@76: universe@140: /** universe@140: * Writes a character to a buffer. universe@140: * universe@140: * The least significant byte of the argument is written to the buffer. If the universe@140: * end of the buffer is reached and #UCX_BUFFER_AUTOEXTEND feature is enabled, universe@140: * the buffer capacity is extended by ucx_buffer_extend(). If the feature is universe@140: * disabled or buffer extension fails, EOF is returned. universe@140: * universe@140: * On successful write the position of the buffer is increased. universe@140: * universe@140: * @param buffer the buffer to write to universe@140: * @param c the character to write as int value universe@140: * @return the byte that has bean written as int value or universe@140: * EOF when the end of the stream is reached and automatic universe@140: * extension is not enabled or not possible universe@140: */ universe@140: int ucx_buffer_putc(UcxBuffer *buffer, int c); universe@56: universe@140: /** universe@140: * Gets a character from a buffer. universe@140: * universe@140: * The current position of the buffer is increased after a successful read. universe@140: * universe@140: * @param buffer the buffer to read from universe@140: * @return the character as int value or EOF, if the universe@140: * end of the buffer is reached universe@140: */ universe@140: int ucx_buffer_getc(UcxBuffer *buffer); olaf@76: universe@140: /** universe@140: * Writes a string to a buffer. universe@140: * universe@140: * @param buffer the buffer universe@140: * @param str the string universe@140: * @return the number of bytes written olaf@76: */ universe@140: size_t ucx_buffer_puts(UcxBuffer *buffer, char *str); olaf@86: universe@56: #ifdef __cplusplus universe@56: } universe@56: #endif universe@56: olaf@120: #endif /* UCX_BUFFER_H */ universe@56: