diff -r 000000000000 -r 044383f39525 sbsv2/raptor/util/talon/buffer.c --- /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 +#include "buffer.h" +#include + +/* 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; +} +