diff options
| author | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
|---|---|---|
| committer | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
| commit | 268a53de823a6750d6256ee1fb1e7707b4b45740 (patch) | |
| tree | 42c1799a9a82b2f7d9790ee9fe181d72a7274751 /support/util/dbuf.c | |
| download | sdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz | |
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'support/util/dbuf.c')
| -rw-r--r-- | support/util/dbuf.c | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/support/util/dbuf.c b/support/util/dbuf.c new file mode 100644 index 0000000..3ae6560 --- /dev/null +++ b/support/util/dbuf.c @@ -0,0 +1,334 @@ +/* + dbuf.c - Dynamic buffer implementation + version 1.4.0, 2011-03-27 + + Copyright (c) 2002-2011 Borut Razem + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Borut Razem + borut.razem@siol.net +*/ + + +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "dbuf.h" + + +/* + * Assure that the buffer is large enough to hold + * current length + size bytes; enlarge it if necessary. + * + * Intended for internal use. + */ + +int _dbuf_expand(struct dbuf_s *dbuf, size_t size) +{ + assert(dbuf->alloc != 0); + assert(dbuf->buf != NULL); + + if (dbuf->len + size > dbuf->alloc) { + /* new_allocated_size = current_allocated_size * 2^n */ + /* can this be optimized? */ + do { + dbuf->alloc += dbuf->alloc; + } + while (dbuf->len + size > dbuf->alloc); + + if ((dbuf->buf = realloc(dbuf->buf, dbuf->alloc)) == NULL) + return 0; + } + + return 1; +} + + +/* + * Initialize the dbuf structure and + * allocate buffer to hold size bytes. + */ + +int dbuf_init(struct dbuf_s *dbuf, size_t size) +{ + assert(size != 0); + + if (size == 0) + size = 1; + + dbuf->len = 0; + dbuf->alloc = size; + return ((dbuf->buf = malloc(dbuf->alloc)) != NULL); +} + + +/* + * Test if dbuf is initialized. + * NOTE: the dbuf structure should be set + * to all zeroes at definition: + * struct dbuf_s dbuf = { 0 }; + * + * See: dbuf_init() + */ + +int dbuf_is_initialized (struct dbuf_s *dbuf) +{ + if (dbuf->buf == NULL) { + assert(dbuf->alloc == 0); + assert(dbuf->len == 0); + return 0; + } + else { + assert(dbuf->alloc != 0); + assert(dbuf->len >= 0 && dbuf->len <= dbuf->alloc); + return 1; + } +} + +/* + * Allocate new dbuf structure on the heap + * and initialize it. + * + * See: dbuf_delete() + */ + +struct dbuf_s *dbuf_new(size_t size) +{ + struct dbuf_s *dbuf; + + dbuf = (struct dbuf_s *)malloc(sizeof(struct dbuf_s)); + if (dbuf != NULL) { + if (dbuf_init(dbuf, size) == 0) { + free(dbuf); + return NULL; + } + } + return dbuf; +} + + +/* + * Set the buffer size. Buffer size can be only decreased. + */ + +int dbuf_set_length(struct dbuf_s *dbuf, size_t len) +{ + if (!dbuf_is_initialized (dbuf)) + dbuf_init (dbuf, len ? len : 1); + + assert(dbuf != NULL); + assert(dbuf->alloc != 0); + assert(len <= dbuf->len); + + if (len <= dbuf->len) { + dbuf->len = len; + return 1; + } + + return 0; +} + + +/* + * Append the buf to the end of the buffer. + */ + +int dbuf_append(struct dbuf_s *dbuf, const void *buf, size_t len) +{ + assert(dbuf != NULL); + assert(dbuf->alloc != 0); + assert(dbuf->buf != NULL); + + if (_dbuf_expand(dbuf, len) != 0) { + memcpy(&(((char *)dbuf->buf)[dbuf->len]), buf, len); + dbuf->len += len; + return 1; + } + + return 0; +} + +/* + * Prepend the buf to the beginning of the buffer. + */ + +int dbuf_prepend(struct dbuf_s *dbuf, const void *buf, size_t len) +{ + assert(dbuf); + assert(dbuf->alloc); + assert(dbuf->buf); + + if (_dbuf_expand(dbuf, len) != 0) { + memmove(&(((char *)dbuf->buf)[len]), dbuf->buf, dbuf->len); + memcpy(dbuf->buf, buf, len); + dbuf->len += len; + return 1; + } + + return 0; +} + +/* + * Add '\0' character at the end of the buffer without + * count it in the dbuf->len. + */ + +const char *dbuf_c_str(struct dbuf_s *dbuf) +{ + assert(dbuf != NULL); + assert(dbuf->alloc != 0); + assert(dbuf->buf != NULL); + + if (_dbuf_expand(dbuf, 1) != 0) { + ((char *)dbuf->buf)[dbuf->len] = '\0'; + return dbuf->buf; + } + + return NULL; +} + + +/* + * Get the buffer pointer. + */ + +const void *dbuf_get_buf(const struct dbuf_s *dbuf) +{ + assert(dbuf != NULL); + assert(dbuf->alloc != 0); + assert(dbuf->buf != NULL); + + return dbuf->buf; +} + + +/* + * Get the buffer length. + */ + +size_t dbuf_get_length(const struct dbuf_s *dbuf) +{ + assert(dbuf != NULL); + assert(dbuf->alloc != 0); + assert(dbuf->buf != NULL); + + return dbuf->len; +} + + +/* + * Trim the allocated buffer to required size + */ + +int dbuf_trim(struct dbuf_s *dbuf) +{ + void *buf; + + assert(dbuf != NULL); + assert(dbuf->alloc != 0); + assert(dbuf->buf != NULL); + + buf = realloc(dbuf->buf, dbuf->len); + + if (buf != NULL) { + dbuf->alloc = dbuf->len; + dbuf->buf = buf; + } + + return buf != NULL; +} + + +/* + * Detach the buffer from dbuf structure. + * The dbuf structure can be reused by + * reinitializing it. + * + * See: dbuf_init() + */ + +void *dbuf_detach(struct dbuf_s *dbuf) +{ + void *ret; + + assert(dbuf != NULL); + assert(dbuf->alloc != 0); + assert(dbuf->buf != NULL); + + ret = dbuf->buf; + dbuf->buf = NULL; + dbuf->len = 0; + dbuf->alloc = 0; + + return ret; +} + + +/* + * Add '\0' character at the end of the buffer without + * count it in the dbuf->len and detach the buffer from dbuf structure. + * The dbuf structure can be reused by reinitializing it. + * + * See: dbuf_init() + */ + +char *dbuf_detach_c_str(struct dbuf_s *dbuf) +{ + dbuf_c_str(dbuf); + return dbuf_detach(dbuf); +} + + +/* + * Destroy the dbuf structure and + * free the buffer + */ + +void dbuf_destroy(struct dbuf_s *dbuf) +{ + free(dbuf_detach(dbuf)); +} + + +/* + * Delete dbuf structure on the heap: + * destroy it and free the allocated space. + * The user's responsablity is not to use + * the pointer any more: the best think to do + * is to set the pointer to NULL value. + * + * See dbuf_new() + */ + +void dbuf_delete(struct dbuf_s *dbuf) +{ + dbuf_destroy(dbuf); + free(dbuf); +} + + +/* + * Free detached buffer. + * + * See dbuf_detach() + */ + +void dbuf_free(const void *buf) +{ + free((void *)buf); +} |
