From d3028dc2d7cf96e3c87de796dabb2faa450cb109 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 10 Nov 2009 11:35:09 +0000 Subject: [PATCH] Add a new memory buffer class. --- src/Makefile.am | 2 + src/buffer.c | 230 ++++++++++++++++++++++++++++++++++++ src/buffer.h | 61 ++++++++++ src/libdivecomputer.symbols | 10 ++ 4 files changed, 303 insertions(+) create mode 100644 src/buffer.c create mode 100644 src/buffer.h diff --git a/src/Makefile.am b/src/Makefile.am index 01819d6..42c918b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,6 +5,7 @@ libdivecomputerdir = $(includedir)/libdivecomputer libdivecomputer_HEADERS = \ utils.h \ + buffer.h \ device.h \ parser.h \ units.h \ @@ -70,6 +71,7 @@ libdivecomputer_la_SOURCES = \ ringbuffer.h ringbuffer.c \ checksum.h checksum.c \ array.h array.c \ + buffer.h buffer.c \ utils.h utils.c if OS_WIN32 diff --git a/src/buffer.c b/src/buffer.c new file mode 100644 index 0000000..ef4d659 --- /dev/null +++ b/src/buffer.c @@ -0,0 +1,230 @@ +/* + * libdivecomputer + * + * Copyright (C) 2009 Jef Driesen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include // malloc, realloc, free +#include // memcpy, memmove + +#include "buffer.h" + +struct dc_buffer_t { + unsigned char *data; + size_t capacity, offset, size; +}; + +dc_buffer_t * +dc_buffer_new (size_t capacity) +{ + dc_buffer_t *buffer = (dc_buffer_t *) malloc (sizeof (dc_buffer_t)); + if (buffer == NULL) + return NULL; + + if (capacity) { + buffer->data = (unsigned char *) malloc (capacity); + if (buffer->data == NULL) { + free (buffer); + return NULL; + } + } else { + buffer->data = NULL; + } + + buffer->capacity = capacity; + buffer->offset = 0; + buffer->size = 0; + + return buffer; +} + + +void +dc_buffer_free (dc_buffer_t *buffer) +{ + if (buffer == NULL) + return; + + if (buffer->data) + free (buffer->data); + + free (buffer); +} + + +int +dc_buffer_clear (dc_buffer_t *buffer) +{ + if (buffer == NULL) + return 0; + + buffer->offset = 0; + buffer->size = 0; + + return 1; +} + + +static int +dc_buffer_expand_append (dc_buffer_t *buffer, size_t n) +{ + if (n > buffer->capacity - buffer->offset) { + if (n > buffer->capacity) { + size_t capacity = n; + + unsigned char *data = (unsigned char *) malloc (capacity); + if (data == NULL) + return 0; + + memcpy (data, buffer->data + buffer->offset, buffer->size); + + free (buffer->data); + + buffer->data = data; + buffer->capacity = capacity; + buffer->offset = 0; + } else { + memmove (buffer->data, buffer->data + buffer->offset, buffer->size); + + buffer->offset = 0; + } + } + + return 1; +} + + +static int +dc_buffer_expand_prepend (dc_buffer_t *buffer, size_t n) +{ + size_t available = buffer->capacity - buffer->size; + + if (n > buffer->offset + buffer->size) { + if (n > buffer->capacity) { + size_t capacity = n; + + unsigned char *data = (unsigned char *) malloc (capacity); + if (data == NULL) + return 0; + + memcpy (data + capacity - buffer->size, buffer->data + buffer->offset, buffer->size); + + free (buffer->data); + + buffer->data = data; + buffer->capacity = capacity; + buffer->offset = capacity - buffer->size; + } else { + memmove (buffer->data + available, buffer->data + buffer->offset, buffer->size); + + buffer->offset = available; + } + } + + return 1; +} + + +int +dc_buffer_reserve (dc_buffer_t *buffer, size_t capacity) +{ + if (buffer == NULL) + return 0; + + if (capacity <= buffer->capacity) + return 1; + + unsigned char *data = (unsigned char *) realloc (buffer->data, capacity); + if (data == NULL) + return 0; + + buffer->data = data; + buffer->capacity = capacity; + + return 1; +} + + +int +dc_buffer_resize (dc_buffer_t *buffer, size_t size) +{ + if (buffer == NULL) + return 0; + + if (!dc_buffer_expand_append (buffer, size)) + return 0; + + buffer->size = size; + + return 1; +} + + +int +dc_buffer_append (dc_buffer_t *buffer, const unsigned char data[], size_t size) +{ + if (buffer == NULL) + return 0; + + if (!dc_buffer_expand_append (buffer, buffer->size + size)) + return 0; + + memcpy (buffer->data + buffer->offset + buffer->size, data, size); + + buffer->size += size; + + return 1; +} + + +int +dc_buffer_prepend (dc_buffer_t *buffer, const unsigned char data[], size_t size) +{ + if (buffer == NULL) + return 0; + + if (!dc_buffer_expand_prepend (buffer, buffer->size + size)) + return 0; + + memcpy (buffer->data + buffer->offset - size, data, size); + + buffer->size += size; + buffer->offset -= size; + + return 1; +} + + +size_t +dc_buffer_get_size (dc_buffer_t *buffer) +{ + if (buffer == NULL) + return 0; + + return buffer->size; +} + + +unsigned char * +dc_buffer_get_data (dc_buffer_t *buffer) +{ + if (buffer == NULL) + return NULL; + + return buffer->size ? buffer->data + buffer->offset : NULL; +} diff --git a/src/buffer.h b/src/buffer.h new file mode 100644 index 0000000..a26389f --- /dev/null +++ b/src/buffer.h @@ -0,0 +1,61 @@ +/* + * libdivecomputer + * + * Copyright (C) 2009 Jef Driesen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef DC_BUFFER_H +#define DC_BUFFER_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct dc_buffer_t dc_buffer_t; + +dc_buffer_t * +dc_buffer_new (size_t capacity); + +void +dc_buffer_free (dc_buffer_t *buffer); + +int +dc_buffer_clear (dc_buffer_t *buffer); + +int +dc_buffer_reserve (dc_buffer_t *buffer, size_t capacity); + +int +dc_buffer_resize (dc_buffer_t *buffer, size_t size); + +int +dc_buffer_append (dc_buffer_t *buffer, const unsigned char data[], size_t size); + +int +dc_buffer_prepend (dc_buffer_t *buffer, const unsigned char data[], size_t size); + +size_t +dc_buffer_get_size (dc_buffer_t *buffer); + +unsigned char * +dc_buffer_get_data (dc_buffer_t *buffer); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* DC_BUFFER_H */ diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index c1163b3..ae853bb 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -1,3 +1,13 @@ +dc_buffer_new +dc_buffer_free +dc_buffer_clear +dc_buffer_reserve +dc_buffer_resize +dc_buffer_append +dc_buffer_prepend +dc_buffer_get_size +dc_buffer_get_data + parser_get_type parser_set_data parser_samples_foreach