[asterisk-commits] twilson: branch twilson/sip_binarification r314470 - in /team/twilson/sip_bin...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Apr 20 14:30:31 CDT 2011


Author: twilson
Date: Wed Apr 20 14:30:29 2011
New Revision: 314470

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=314470
Log:
Add a binary buffer API similar to ast_str_


Added:
    team/twilson/sip_binarification/include/asterisk/buffers.h   (with props)
    team/twilson/sip_binarification/main/buffers.c   (with props)
    team/twilson/sip_binarification/tests/test_buffers.c   (with props)

Added: team/twilson/sip_binarification/include/asterisk/buffers.h
URL: http://svnview.digium.com/svn/asterisk/team/twilson/sip_binarification/include/asterisk/buffers.h?view=auto&rev=314470
==============================================================================
--- team/twilson/sip_binarification/include/asterisk/buffers.h (added)
+++ team/twilson/sip_binarification/include/asterisk/buffers.h Wed Apr 20 14:30:29 2011
@@ -1,0 +1,176 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2011, Digium, Inc.
+ *
+ * Mark Spencer <markster at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ * \brief Buffer manipulation functions
+ */
+
+#ifndef _ASTERISK_BUFFERS_H
+#define _ASTERISK_BUFFERS_H
+
+/*!
+ * Support for dynamic buffers.
+ *
+ * A dynamic buffer is just a allocated prefixed by a few control fields
+ * that help setting/appending/extending it.
+ *
+ * One should never declare a variable with this type, but only a pointer
+ * to it, e.g.
+ *
+ *	struct ast_buf *buf;
+ *
+ * The pointer can be initialized with the following:
+ *
+ *	buf = ast_buf_create(init_len);
+ *		creates a malloc()'ed dynamic buffer;
+ *
+ *	buf = ast_buf_thread_get(ts, init_len)
+ *		creates a malloc()'ed dynamic buffer associated to
+ *		the thread-local storage key ts
+ *
+ * Finally, the buffer can be manipulated with the following:
+ *
+ *	ast_buf_set(&buf, max_len, src, src_len)
+ *	ast_buf_append(&buf, max_len, src, src_len)
+ *
+ * \param max_len The maximum allowed capacity of the ast_buf. Note that
+ * 	0 means unlimited, -1 means "at most the available space"
+ *
+ * \return All the functions return < 0 in case of error, or the
+ *	length of the buffer added to the buffer otherwise. Note that
+ *	in most cases where an error is returned, characters ARE written
+ *	to the ast_buf.
+ */
+
+struct ast_buf;
+
+/*!
+ * \brief Create a malloc'ed dynamic length buffer
+ *
+ * \param init_len This is the initial length of the buffer buffer
+ *
+ * \return This function returns a pointer to the dynamic buffer length.  The
+ *         result will be NULL in the case of a memory allocation error.
+ *
+ * \note The result of this function is dynamically allocated memory, and must
+ *       be free()'d after it is no longer needed.
+ */
+#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#define	ast_buf_create(a)	_ast_buf_create(a,__FILE__,__LINE__,__PRETTY_FUNCTION__)
+struct ast_buf * attribute_malloc _ast_buf_create(size_t init_len,
+		const char  *file, int lineno, const char *func);
+#else
+struct ast_buf * attribute_malloc ast_buf_create(size_t init_len);
+#endif
+
+/*!\brief Resets the buffer length to 0
+ * \note Contents are then invalid, but not zeroed out.
+ */
+void ast_buf_reset(struct ast_buf *buf);
+
+/*!\brief Returns the current length of the buffer stored within buf.
+ * \param buf A pointer to the ast_buf structure.
+ * \return Number of bytes used
+ */
+size_t attribute_pure ast_buf_len(const struct ast_buf *buf);
+
+/*!\brief Returns the current maximum length (without reallocation) of the current buffer.
+ * \param buf A pointer to the ast_buf structure.
+ * \return Current maximum length of the buffer.
+ */
+size_t attribute_pure ast_buf_size(const struct ast_buf *buf);
+
+/*!\brief Returns the buffer buffer within the ast_buf buf.
+ * \param buf A pointer to the ast_buf structure.
+ * \return A pointer to the enclosed buffer contents.
+ */
+const unsigned char * attribute_pure ast_buf_buffer(const struct ast_buf *buf);
+
+/*!\brief Truncates the enclosed buffer to the given length.
+ * \param buf A pointer to the ast_buf structure.
+ * \param len Maximum length of the buffer. If negative, the number of bytes to remove.
+ * \return A pointer to the resulting buffer.
+ */
+unsigned char *ast_buf_truncate(struct ast_buf *buf, ssize_t len);
+
+/*!
+ * Make space in a new buffer (e.g. to read in data from a file)
+ */
+#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+int _ast_buf_make_space(struct ast_buf **buf, size_t new_len, const char *file, int lineno, const char *function);
+#define ast_buf_make_space(a,b)	_ast_buf_make_space(a,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
+#else
+int ast_buf_make_space(struct ast_buf **buf, size_t new_len);
+#endif
+
+int ast_buf_copy_buffer(struct ast_buf **dst, struct ast_buf *src);
+
+/*!
+ * \brief Retrieve a thread locally stored dynamic buffer
+ *
+ * \param ts This is a pointer to the thread storage structure declared by using
+ *      the AST_THREADSTORAGE macro.  If declared with 
+ *      AST_THREADSTORAGE(my_buf, my_buf_init), then this argument would be 
+ *      (&my_buf).
+ * \param init_len This is the initial length of the thread's dynamic buffer. The
+ *      current length may be bigger if previous operations in this thread have
+ *      caused it to increase.
+ *
+ * \return This function will return the thread locally stored dynamic buffer
+ *         associated with the thread storage management variable passed as the
+ *         first argument.
+ *         The result will be NULL in the case of a memory allocation error.
+ *
+ * Example usage:
+ * \code
+ * AST_THREADSTORAGE(my_buf, my_buf_init);
+ * #define MY_BUF_INIT_SIZE   128
+ * ...
+ * void my_func(const char *fmt, ...)
+ * {
+ *      struct ast_buf *buf;
+ *
+ *      if (!(buf = ast_buf_thread_get(&my_buf, MY_BUF_INIT_SIZE)))
+ *           return;
+ *      ...
+ * }
+ * \endcode
+ */
+
+struct ast_threadstorage;
+
+#if !defined(DEBUG_THREADLOCALS)
+struct ast_buf *ast_buf_thread_get(struct ast_threadstorage *ts, size_t init_len);
+#else /* defined(DEBUG_THREADLOCALS) */
+struct ast_buf *__ast_buf_thread_get(struct ast_threadstorage *ts,
+	size_t init_len, const char *file, const char *function, unsigned int line);
+
+#define ast_buf_thread_get(ts, init_len) __ast_buf_thread_get(ts, init_len, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#endif /* defined(DEBUG_THREADLOCALS) */
+
+/*!\brief Set a dynamic buffer to a non-NULL terminated subbuffer. */
+int ast_buf_set(struct ast_buf **buf, ssize_t maxlen, const unsigned char *src, size_t maxsrc);
+
+/*!\brief Set all bytes in a buffer to zero
+ */
+void ast_buf_zero(struct ast_buf *buf);
+
+/*!\brief Append a non-NULL terminated subbuffer to the end of a dynamic buffer. */
+int ast_buf_append(struct ast_buf **buf, ssize_t maxlen, const unsigned char *src, size_t maxsrc);
+
+#endif /* _ASTERISK_BUFFERS_H */

Propchange: team/twilson/sip_binarification/include/asterisk/buffers.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/twilson/sip_binarification/include/asterisk/buffers.h
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/twilson/sip_binarification/include/asterisk/buffers.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: team/twilson/sip_binarification/main/buffers.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/sip_binarification/main/buffers.c?view=auto&rev=314470
==============================================================================
--- team/twilson/sip_binarification/main/buffers.c (added)
+++ team/twilson/sip_binarification/main/buffers.c Wed Apr 20 14:30:29 2011
@@ -1,0 +1,270 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+* the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Buffer manipulation API
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/buffers.h"
+#include "asterisk/utils.h"
+#include "asterisk/threadstorage.h"
+
+/*! \brief The descriptor of a dynamic buffer
+ *  XXX storage will be optimized later if needed
+ * We use the ts field to indicate the type of storage.
+ * Three special constants indicate malloc, alloca() or static
+ * variables, all other values indicate a
+ * struct ast_threadstorage pointer.
+ */
+struct ast_buf {
+	size_t __AST_BUF_SIZE;			/*!< The current maximum length of the buffer */
+	size_t __AST_BUF_USED;			/*!< Amount of space used */
+	struct ast_threadstorage *__AST_BUF_TS;	/*!< What kind of storage is this ? */
+#define DS_MALLOC	((struct ast_threadstorage *)1)
+#define DS_ALLOCA	((struct ast_threadstorage *)2)
+#define DS_STATIC	((struct ast_threadstorage *)3)	/* not supported yet */
+	unsigned char __AST_BUF_BUFFER[0];			/*!< The buffer buffer */
+};
+
+static int __ast_buf_helper(struct ast_buf **buf, ssize_t maxlen, const unsigned char *src, size_t srclen, int append)
+{
+	int dynamic = 0;
+	size_t left = (*buf)->__AST_BUF_SIZE - (*buf)->__AST_BUF_USED;
+	unsigned char *ptr;
+
+	switch (maxlen) {
+	case -1 :
+		srclen = MIN(srclen, left);
+		break;
+	case 0 :
+		dynamic = 1;
+		break;
+	default :
+		srclen = MIN(srclen, maxlen);
+	}
+
+	if (left < srclen && dynamic) {
+		if (ast_buf_make_space(buf, MAX((*buf)->__AST_BUF_SIZE * 2, srclen - left + (*buf)->__AST_BUF_SIZE))) {
+			return -1;
+		}
+	}
+
+	ptr = append ? &((*buf)->__AST_BUF_BUFFER[(*buf)->__AST_BUF_USED]) : (*buf)->__AST_BUF_BUFFER;
+	memcpy(ptr, src, srclen);
+	(*buf)->__AST_BUF_USED += srclen;
+
+	return 0;
+}
+
+#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+struct ast_buf * attribute_malloc _ast_buf_create(size_t init_len,
+		const char *file, int lineno, const char *func)
+{
+	struct ast_buf *buf;
+
+	buf = (struct ast_buf *)__ast_malloc(sizeof(*buf) + init_len + 1, file, lineno, func);
+	if (buf == NULL)
+		return NULL;
+
+	buf->__AST_BUF_SIZE = init_len;
+	buf->__AST_BUF_USED = 0;
+	buf->__AST_BUF_TS = DS_MALLOC;
+	buf->__AST_BUF_BUFFER[init_len] = '\0';
+
+	return buf;
+}
+#else
+struct ast_buf * attribute_malloc ast_buf_create(size_t init_len)
+{
+	struct ast_buf *buf;
+
+	buf = (struct ast_buf *)ast_malloc(sizeof(*buf) + init_len + 1);
+	if (buf == NULL)
+		return NULL;
+
+	buf->__AST_BUF_SIZE = init_len;
+	buf->__AST_BUF_USED = 0;
+	buf->__AST_BUF_TS = DS_MALLOC;
+	buf->__AST_BUF_BUFFER[init_len] = '\0';
+
+	return buf;
+}
+#endif
+
+void ast_buf_reset(struct ast_buf *buf)
+{
+	if (buf) {
+		buf->__AST_BUF_USED = 0;
+	}
+}
+
+void ast_buf_zero(struct ast_buf *buf)
+{
+	size_t x;
+
+	for (x = 0; x < buf->__AST_BUF_SIZE; x++) {
+		buf->__AST_BUF_BUFFER[x] = '\0';
+	}
+}
+
+size_t attribute_pure ast_buf_len(const struct ast_buf *buf)
+{
+	return buf->__AST_BUF_USED;
+}
+
+size_t attribute_pure ast_buf_size(const struct ast_buf *buf)
+{
+	return buf->__AST_BUF_SIZE;
+}
+
+const unsigned char * attribute_pure ast_buf_buffer(const struct ast_buf *buf)
+{
+	return buf->__AST_BUF_BUFFER;
+}
+
+unsigned char *ast_buf_truncate(struct ast_buf *buf, ssize_t len)
+{
+	if (len < 0) {
+		buf->__AST_BUF_USED += ((ssize_t) abs(len)) > (ssize_t) buf->__AST_BUF_USED ? -buf->__AST_BUF_USED : len;
+	} else {
+		buf->__AST_BUF_USED = len;
+	}
+	return buf->__AST_BUF_BUFFER;
+}
+
+#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+int _ast_buf_make_space(struct ast_buf **buf, size_t new_len, const char *file, int lineno, const char *function)
+{
+	struct ast_buf *old_buf = *buf;
+
+	if (new_len <= (*buf)->__AST_BUF_SIZE) 
+		return 0;	/* success */
+	if ((*buf)->__AST_BUF_TS == DS_ALLOCA || (*buf)->__AST_BUF_TS == DS_STATIC)
+		return -1;	/* cannot extend */
+	*buf = (struct ast_buf *)__ast_realloc(*buf, new_len + sizeof(struct ast_buf) + 1, file, lineno, function);
+	if (*buf == NULL) {
+		*buf = old_buf;
+		return -1;
+	}
+	if ((*buf)->__AST_BUF_TS != DS_MALLOC) {
+		pthread_setspecific((*buf)->__AST_BUF_TS->key, *buf);
+#if defined(DEBUG_THREADLOCALS)
+		__ast_threadstorage_object_replace(old_buf, *buf, new_len + sizeof(struct ast_buf) + 1);
+#endif /* defined(DEBUG_THREADLOCALS) */
+	}
+
+	(*buf)->__AST_BUF_SIZE = new_len;
+	(*buf)->__AST_BUF_BUFFER[new_len] = '\0';
+	return 0;
+}
+#define ast_buf_make_space(a,b)	_ast_buf_make_space(a,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
+#else
+int ast_buf_make_space(struct ast_buf **buf, size_t new_len)
+{
+	struct ast_buf *old_buf = *buf;
+
+	if (new_len <= (*buf)->__AST_BUF_SIZE) 
+		return 0;	/* success */
+	if ((*buf)->__AST_BUF_TS == DS_ALLOCA || (*buf)->__AST_BUF_TS == DS_STATIC)
+		return -1;	/* cannot extend */
+	*buf = (struct ast_buf *)ast_realloc(*buf, new_len + sizeof(struct ast_buf) + 1);
+	if (*buf == NULL) {
+		*buf = old_buf;
+		return -1;
+	}
+	if ((*buf)->__AST_BUF_TS != DS_MALLOC) {
+		pthread_setspecific((*buf)->__AST_BUF_TS->key, *buf);
+#if defined(DEBUG_THREADLOCALS)
+		__ast_threadstorage_object_replace(old_buf, *buf, new_len + sizeof(struct ast_buf) + 1);
+#endif /* defined(DEBUG_THREADLOCALS) */
+	}
+
+	(*buf)->__AST_BUF_SIZE = new_len;
+	(*buf)->__AST_BUF_BUFFER[new_len] = '\0';
+	return 0;
+}
+#endif
+
+int ast_buf_copy_buffer(struct ast_buf **dst, struct ast_buf *src)
+{
+
+	/* make sure our destination is large enough */
+	if (src->__AST_BUF_USED > (*dst)->__AST_BUF_SIZE) {
+		if (ast_buf_make_space(dst, src->__AST_BUF_USED)) {
+			return -1;
+		}
+	}
+
+	memcpy((*dst)->__AST_BUF_BUFFER, src->__AST_BUF_BUFFER, src->__AST_BUF_USED);
+	(*dst)->__AST_BUF_USED = src->__AST_BUF_USED;
+	return 0;
+}
+
+#if !defined(DEBUG_THREADLOCALS)
+struct ast_buf *ast_buf_thread_get(struct ast_threadstorage *ts, size_t init_len)
+{
+	struct ast_buf *buf;
+
+	buf = (struct ast_buf *)ast_threadstorage_get(ts, sizeof(*buf) + init_len + 1);
+	if (buf == NULL)
+		return NULL;
+
+	if (!buf->__AST_BUF_SIZE) {
+		buf->__AST_BUF_SIZE = init_len;
+		buf->__AST_BUF_USED = 0;
+		buf->__AST_BUF_TS = ts;
+		buf->__AST_BUF_BUFFER[init_len] = '\0';
+	}
+
+	return buf;
+}
+#else /* defined(DEBUG_THREADLOCALS) */
+struct ast_buf *__ast_buf_thread_get(struct ast_threadstorage *ts,
+	size_t init_len, const char *file, const char *function, unsigned int line)
+{
+	struct ast_buf *buf;
+
+	buf = (struct ast_buf *)__ast_threadstorage_get(ts, sizeof(*buf) + init_len + 1, file, function, line);
+	if (buf == NULL)
+		return NULL;
+
+	if (!buf->__AST_BUF_SIZE) {
+		buf->__AST_BUF_SIZE = init_len;
+		buf->__AST_BUF_USED = 0;
+		buf->__AST_BUF_TS = ts;
+		buf->AST_BUF_BUFFER[init_len] = '\0';
+	}
+
+	return buf;
+}
+#endif
+
+/*!\brief Set a dynamic buffer to a non-NULL terminated subbuffer. */
+int ast_buf_set(struct ast_buf **buf, ssize_t maxlen, const unsigned char *src, size_t srclen)
+{
+	return __ast_buf_helper(buf, maxlen, src, srclen, 0);
+}
+
+/*!\brief Append a non-NULL terminated subbuffer to the end of a dynamic buffer. */
+int ast_buf_append(struct ast_buf **buf, ssize_t maxlen, const unsigned char *src, size_t srclen)
+{
+	return __ast_buf_helper(buf, maxlen, src, srclen, 1);
+}

Propchange: team/twilson/sip_binarification/main/buffers.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/twilson/sip_binarification/main/buffers.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/twilson/sip_binarification/main/buffers.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: team/twilson/sip_binarification/tests/test_buffers.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/sip_binarification/tests/test_buffers.c?view=auto&rev=314470
==============================================================================
--- team/twilson/sip_binarification/tests/test_buffers.c (added)
+++ team/twilson/sip_binarification/tests/test_buffers.c Wed Apr 20 14:30:29 2011
@@ -1,0 +1,261 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * Mark Michelson <mmichelson at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Dynamic buffer tests
+ *
+ * \author Terry Wilson <twilson at digium.com>
+ *
+ * This module will run some dyanmic buffer tests.
+ *
+ * \ingroup tests
+ */
+
+/*** MODULEINFO
+	<depend>TEST_FRAMEWORK</depend>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/test.h"
+#include "asterisk/buffers.h"
+#include "asterisk/module.h"
+
+#define TEST_BUF_INITIAL_SIZE 30
+AST_TEST_DEFINE(buf_test)
+{
+	struct ast_buf *buf = NULL, *bufcopy = NULL;
+	/* Do not change the contents of these buffers or certain tests will fail */
+	const unsigned char buf_one[] = { 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245 };
+	const unsigned char buf_two[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+	const unsigned char buf_both[] = { 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+	enum ast_test_result_state res = AST_TEST_PASS;
+	size_t x;
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "buf_test";
+		info->category = "/main/buffers/";
+		info->summary = "Test dynamic buffer operations";
+		info->description = "Test setting and appending heap-allocated dynamic buffers";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	if (!(buf = ast_buf_create(TEST_BUF_INITIAL_SIZE))) {
+		ast_test_status_update(test, "Failed to allocate an ast_buf on the heap\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+ 
+	if (ast_buf_len(buf) != 0) {
+		ast_test_status_update(test, "Newly created buffer has non-zero length\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (ast_buf_size(buf) != TEST_BUF_INITIAL_SIZE) {
+		ast_test_status_update(test, "Newly created buffer has incorrect size\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (ast_buf_buffer(buf)[ast_buf_size(buf)] != '\0') {
+		ast_test_status_update(test, "Safety NULL at end of buffer is missing after create!\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (ast_buf_set(&buf, 0, buf_one, sizeof(buf_one)) < 0) {
+		ast_test_status_update(test, "Error setting buffer\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (ast_buf_len(buf) != sizeof(buf_one)) {
+		ast_test_status_update(test, "Buffer length not updated properly after set\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (memcmp(ast_buf_buffer(buf), buf_one, MIN(sizeof(buf_one), ast_buf_len(buf)))) {
+		ast_test_status_update(test, "ast_buf_set failed for buffer\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (ast_buf_buffer(buf)[ast_buf_size(buf)] != '\0') {
+		ast_test_status_update(test, "Safety NULL at end of buffer is missing after set!\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (ast_buf_append(&buf, 0, buf_two, sizeof(buf_two)) < 0) {
+		ast_test_status_update(test, "Error appending buffer\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (sizeof(buf_both) != sizeof(buf_one) + sizeof(buf_two)) {
+		ast_test_status_update(test, "Error with test. buf_both is the wrong size!\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (ast_buf_len(buf) != sizeof(buf_both)) {
+		ast_test_status_update(test, "Buffer length not update properly after append\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (memcmp(ast_buf_buffer(buf), buf_both, sizeof(buf_both))) {
+		ast_test_status_update(test, "ast_buf_append failed for buffer\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (ast_buf_buffer(buf)[ast_buf_size(buf)] != '\0') {
+		ast_test_status_update(test, "Safety NULL at end of buffer is missing after append!\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (!ast_buf_truncate(buf, sizeof(buf_one))) {
+		ast_test_status_update(test, "Failed to truncate buffer!\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (ast_buf_len(buf) != sizeof(buf_one)) {
+		ast_test_status_update(test, "Truncate resulted in buffer of wrong length\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (memcmp(ast_buf_buffer(buf), buf_one, sizeof(buf_one))) {
+		ast_test_status_update(test, "Truncate caused buffer corruption\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	ast_buf_reset(buf);
+
+	if (ast_buf_len(buf) != 0) {
+		ast_test_status_update(test, "Rest buffer has non-zero length\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	for (x = ast_buf_size(buf); x >= ast_buf_size(buf); /* nothing */) {
+		if (ast_buf_append(&buf, 0, buf_two, sizeof(buf_two)) < 0) {
+			ast_test_status_update(test, "Failed to append in loop\n");
+			res = AST_TEST_FAIL;
+			goto cleanup;
+		}
+	}
+
+	if (ast_buf_len(buf) % sizeof(buf_two) != 0) {
+		ast_test_status_update(test, "Multiple appends result in wrong length\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	for (x = 0; x < ast_buf_len(buf) / sizeof(buf_two); x++) {
+		if (memcmp(ast_buf_buffer(buf) + (x * sizeof(buf_two)) , buf_two, sizeof(buf_two))) {
+			ast_test_status_update(test, "Multiple appends resulted in buffer corruption\n");
+			res = AST_TEST_FAIL;
+			goto cleanup;
+		}
+	}
+
+	if (ast_buf_buffer(buf)[ast_buf_size(buf)] != '\0') {
+		ast_test_status_update(test, "Safety NULL at end of buffer is missing after append causes expansion!\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (!(bufcopy = ast_buf_create(TEST_BUF_INITIAL_SIZE))) {
+		ast_test_status_update(test, "Failed to allocate bufcopy on the heap\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+ 
+	if (ast_buf_copy_buffer(&bufcopy, buf)) {
+		ast_test_status_update(test, "Buffer copy failed\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (ast_buf_len(buf) != ast_buf_len(bufcopy)) {
+		ast_test_status_update(test, "Copied buffer has different length. Expected %zu got %zu\n", ast_buf_len(buf), ast_buf_len(bufcopy));
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (memcmp(ast_buf_buffer(buf), ast_buf_buffer(bufcopy), ast_buf_len(buf))) {
+		ast_test_status_update(test, "Copied buffer has corrupted data\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	ast_buf_reset(buf);
+	ast_buf_zero(buf);
+
+	for (x = 0; x < ast_buf_size(buf); x++) {
+		if (ast_buf_buffer(buf)[x] != '\0') {
+			ast_test_status_update(test, "ast_buf_zero failed to set all bytes to 0\n");
+			res = AST_TEST_FAIL;
+			goto cleanup;
+		}
+	}
+
+	if (ast_buf_set(&buf, 3, buf_one, sizeof(buf_one)) < 0) {
+		ast_test_status_update(test, "Error setting buffer\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	if (ast_buf_buffer(buf)[4] != '\0') {
+		ast_test_status_update(test, "Copied more bytes to buffer than limit\n");
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+cleanup:
+	ast_free(buf);
+	ast_free(bufcopy);
+	return res;
+}
+
+static int unload_module(void)
+{
+	AST_TEST_UNREGISTER(buf_test);
+	return 0;
+}
+
+static int load_module(void)
+{
+	AST_TEST_REGISTER(buf_test);
+	return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dynamic string test module");

Propchange: team/twilson/sip_binarification/tests/test_buffers.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/twilson/sip_binarification/tests/test_buffers.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/twilson/sip_binarification/tests/test_buffers.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the asterisk-commits mailing list