/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #define DEFAULT_SIZE (4096) /** * Create a memory buffer * * \param alloc Memory (de)allocation function * \param pw Pointer to client-specific private data * \return Pointer to memory buffer, or NULL on memory exhaustion */ parserutils_buffer *parserutils_buffer_create(parserutils_alloc alloc, void *pw) { parserutils_buffer *buffer = alloc(NULL, sizeof(parserutils_buffer), pw); if (buffer == NULL) return NULL; buffer->data = alloc(NULL, DEFAULT_SIZE, pw); if (buffer->data == NULL) { alloc(buffer, 0, pw); return NULL; } buffer->length = 0; buffer->allocated = DEFAULT_SIZE; buffer->alloc = alloc; buffer->pw = pw; return buffer; } /** * Destroy a memory buffer * * \param buffer The buffer to destroy */ void parserutils_buffer_destroy(parserutils_buffer *buffer) { if (buffer == NULL) return; buffer->alloc(buffer->data, 0, buffer->pw); buffer->alloc(buffer, 0, buffer->pw); } /** * Append data to a memory buffer * * \param buffer The buffer to append to * \param data The data to append * \param len The length, in bytes, of the data to append * \return PARSERUTILS_OK on success, appropriate error otherwise. */ parserutils_error parserutils_buffer_append(parserutils_buffer *buffer, const uint8_t *data, size_t len) { while (len >= buffer->allocated - buffer->length) { parserutils_error error = parserutils_buffer_grow(buffer); if (error != PARSERUTILS_OK) return error; } memcpy(buffer->data + buffer->length, data, len); buffer->length += len; return PARSERUTILS_OK; } /** * Insert data into a memory buffer * * \param buffer The buffer to insert into * \param offset The offset into the buffer to insert at * \param data The data to insert * \param len The length, in bytes, of the data to insert * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_buffer_insert(parserutils_buffer *buffer, size_t offset, const uint8_t *data, size_t len) { if (offset > buffer->length) return PARSERUTILS_BADPARM; if (offset == buffer->length) return parserutils_buffer_append(buffer, data, len); while (len >= buffer->allocated - buffer->length) { parserutils_error error = parserutils_buffer_grow(buffer); if (error != PARSERUTILS_OK) return error; } memmove(buffer->data + buffer->length + len, buffer->data + offset, buffer->length - offset); memcpy(buffer->data + offset, data, len); buffer->length += len; return PARSERUTILS_OK; } /** * Discard a section of a memory buffer * * \param buffer The buffer to discard data from * \param offset The offset into the buffer of the start of the section * \param len The number of bytes to discard * \return PARSERUTILS_OK on success, appropriate error otherwise. */ parserutils_error parserutils_buffer_discard(parserutils_buffer *buffer, size_t offset, size_t len) { if (offset >= buffer->length || offset + len > buffer->length) return PARSERUTILS_BADPARM; memmove(buffer->data + offset, buffer->data + offset + len, buffer->length - len); buffer->length -= len; return PARSERUTILS_OK; } /** * Extend the amount of space allocated for a memory buffer * * \param buffer The buffer to extend * \return PARSERUTILS_OK on success, appropriate error otherwise. */ parserutils_error parserutils_buffer_grow(parserutils_buffer *buffer) { uint8_t *temp = buffer->alloc(buffer->data, buffer->allocated * 2, buffer->pw); if (temp == NULL) return PARSERUTILS_NOMEM; buffer->data = temp; buffer->allocated *= 2; return PARSERUTILS_OK; }