sbsv2/raptor/util/talon/buffer.c
changeset 0 044383f39525
child 3 e1eecf4d390d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sbsv2/raptor/util/talon/buffer.c	Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,205 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+* Expanding text buffer
+*
+*/
+
+
+
+
+#include <malloc.h>
+#include "buffer.h"
+#include <string.h>
+
+/* efficient allocation unit: */
+#define ALLOCSIZE 4096
+#define INITIALBLOCKCOUNT 128
+
+byteblock *buffer_newblock(buffer *b, unsigned int size)
+{
+	byteblock *bb;
+	if (!b)
+		return NULL;
+	
+	b->lastblock++;
+	
+	if (b->lastblock == b->maxblocks)
+	{
+		byteblock **nbb = (byteblock **)realloc(b->blocks, sizeof(byteblock *) * (b->maxblocks + INITIALBLOCKCOUNT));
+		if (!nbb)
+			return NULL;
+
+		b->blocks = nbb;
+		b->maxblocks += INITIALBLOCKCOUNT;
+	}
+
+	bb = malloc(sizeof(byteblock) + size-1);
+
+	if (!bb)
+	{
+		
+		return NULL;
+	}
+	
+	b->blocks[b->lastblock] = bb;
+
+	bb->fill = 0;
+	bb->size = size;
+
+	return bb;
+}
+
+buffer *buffer_new(void)
+{
+	buffer *b = malloc(sizeof(buffer));
+
+	if (b)
+	{
+		b->lastblock = -1; /* no blocks as yet */
+		b->maxblocks = INITIALBLOCKCOUNT;
+		b->blocks = (byteblock **)malloc(sizeof(byteblock *) * b->maxblocks);
+		if (!b->blocks)
+		{
+			free(b);
+			return NULL;
+		}
+
+		buffer_newblock(b, ALLOCSIZE);
+	}
+	
+	return b;
+}
+
+
+char *buffer_append(buffer *b, char *bytes, unsigned int size)
+{
+	if (!b || !bytes) 
+		return NULL;
+
+	char *space = buffer_makespace(b, size);
+	if (!space)
+		return NULL;
+	memcpy(space, bytes, size);
+	buffer_usespace(b, size);
+
+	return space;
+}
+
+char *buffer_prepend(buffer *b, char *bytes, unsigned int size)
+{
+	byteblock *bb;
+
+	if (!b || !bytes) 
+		return NULL;
+	
+    	bb = buffer_newblock(b, size);
+	/* cheat by moving the new block from the end to the start. */
+
+	bb = b->blocks[b->lastblock];
+	if (b->lastblock != 0)
+	{
+		memmove(b->blocks+1, b->blocks, sizeof(byteblock *) * b->lastblock );
+		b->blocks[0] = bb;
+	}
+
+	memcpy(&(b->blocks[0]->byte0), bytes, size);
+
+	b->blocks[0]->fill = size;
+
+	return &(b->blocks[0]->byte0);
+}
+
+/* Allocate memory at the end of the buffer (if there isn't
+ * enough already) so that the user can append at least that 
+ * many bytes without overrunning the buffer.  This is useful
+ * where one may not know in advance how many bytes are to be
+ * added (e.g. reading from a socket) but one does know the 
+ * upper limit.
+ */
+char *buffer_makespace(buffer *b, unsigned int size)
+{
+	byteblock *bb;
+	byteblock *last;
+	if (!b)
+		return NULL;
+
+	last = b->blocks[b->lastblock];
+
+	if (last->size - last->fill > size)
+		return (&last->byte0 + last->fill);
+
+	if (size > ALLOCSIZE)
+	{
+       		bb = buffer_newblock(b, size);
+	} else {
+       		bb = buffer_newblock(b, ALLOCSIZE);
+	}
+	
+	if (!bb) 
+		return NULL;
+
+	return &bb->byte0;
+}
+
+void buffer_usespace(buffer *b, unsigned int nbytes)
+{
+	byteblock *last;
+      
+       	if (!b)
+		return;	
+
+	last = b->blocks[b->lastblock];
+
+	if (last->fill + nbytes < last->size)
+		last->fill += nbytes;
+	else
+		last->fill = last->size; /* really an error - no exceptions though. */
+}
+
+byteblock *buffer_getbytes(buffer *b, int *iterator)
+{
+	if (!b)
+		return NULL;
+
+	if (*iterator > b->lastblock)
+		return NULL;
+
+	return b->blocks[(*iterator)++];
+}
+
+void buffer_free(buffer **b)
+{
+	int i;
+	buffer *bf;
+
+	if (!b || !*b)
+		return;
+
+	bf=*b;
+
+	if (bf->blocks)
+	{
+		for (i=0; i <= bf->lastblock; i++)
+		{
+			if (bf->blocks[i])
+				free(bf->blocks[i]);
+		}
+		free(bf->blocks);
+	}
+	free(bf);
+
+	*b = NULL;
+}
+