X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=lib%2Fabyss%2Fsrc%2Fdata.c;fp=lib%2Fabyss%2Fsrc%2Fdata.c;h=03f4c3f5dd90ebc26e446ca29f9c1893d2f0aa60;hb=ce67d0cdeaa37c3e856e23ae4010480887165630;hp=0000000000000000000000000000000000000000;hpb=e355d4e7962400470f467b88f5568de9c8324475;p=xmlrpc-c diff --git a/lib/abyss/src/data.c b/lib/abyss/src/data.c new file mode 100644 index 0000000..03f4c3f --- /dev/null +++ b/lib/abyss/src/data.c @@ -0,0 +1,640 @@ +/****************************************************************************** +** +** list.c +** +** This file is part of the ABYSS Web server project. +** +** Copyright (C) 2000 by Moez Mahfoudh . +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +** +*******************************************************************************/ + +#include +#include +#include + +#include "mallocvar.h" +#include "xmlrpc-c/util_int.h" +#include "xmlrpc-c/string_int.h" + +#include "xmlrpc-c/abyss.h" + +#include "token.h" + +#include "data.h" + +/********************************************************************* +** List +*********************************************************************/ + +void ListInit(TList *sl) +{ + sl->item=NULL; + sl->size=sl->maxsize=0; + sl->autofree=FALSE; +} + +void ListInitAutoFree(TList *sl) +{ + sl->item=NULL; + sl->size=sl->maxsize=0; + sl->autofree=TRUE; +} + + + +void +ListFree(TList * const sl) { + + if (sl->item) { + if (sl->autofree) { + unsigned int i; + for (i = sl->size; i > 0; --i) + free(sl->item[i-1]); + + } + free(sl->item); + } + sl->item = NULL; + sl->size = 0; + sl->maxsize = 0; +} + + + +void +ListFreeItems(TList * const sl) { + + if (sl->item) { + unsigned int i; + for (i = sl->size; i > 0; --i) + free(sl->item[i-1]); + } +} + + + +abyss_bool +ListAdd(TList * const sl, + void * const str) { +/*---------------------------------------------------------------------------- + Add an item to the end of the list. +-----------------------------------------------------------------------------*/ + abyss_bool success; + + if (sl->size >= sl->maxsize) { + uint16_t newSize = sl->maxsize + 16; + void **newitem; + + newitem = realloc(sl->item, newSize * sizeof(void *)); + if (newitem) { + sl->item = newitem; + sl->maxsize = newSize; + } + } + + if (sl->size >= sl->maxsize) + success = FALSE; + else { + success = TRUE; + sl->item[sl->size++] = str; + } + return success; +} + + + +void +ListRemove(TList * const sl) { +/*---------------------------------------------------------------------------- + Remove the last item from the list. +-----------------------------------------------------------------------------*/ + + assert(sl->size > 0); + + --sl->size; +} + + + +abyss_bool +ListAddFromString(TList * const list, + const char * const stringArg) { + + abyss_bool retval; + + if (!stringArg) + retval = TRUE; + else { + char * buffer; + + buffer = strdup(stringArg); + if (!buffer) + retval = FALSE; + else { + abyss_bool endOfString; + abyss_bool error; + char * c; + + for (c = &buffer[0], endOfString = FALSE, error = FALSE; + !endOfString && !error; + ) { + const char * t; + NextToken((const char **)&c); + + while (*c == ',') + ++c; + + t = GetToken(&c); + if (!t) + endOfString = TRUE; + else { + char * p; + + for (p = c - 2; *p == ','; --p) + *p = '\0'; + + if (t[0] != '\0') { + abyss_bool added; + added = ListAdd(list, (void*)t); + + if (!added) + error = TRUE; + } + } + } + retval = !error; + xmlrpc_strfree(buffer); + } + } + return retval; +} + + + +abyss_bool +ListFindString(TList * const sl, + const char * const str, + uint16_t * const indexP) +{ + uint16_t i; + + if (sl->item && str) + for (i=0;isize;i++) + if (strcmp(str,(char *)(sl->item[i]))==0) + { + *indexP=i; + return TRUE; + }; + + return FALSE; +} + +/********************************************************************* +** Buffer +*********************************************************************/ + +abyss_bool BufferAlloc(TBuffer *buf,uint32_t memsize) +{ + /* ************** Implement the static buffers ***/ + buf->staticid=0; + buf->data=(void *)malloc(memsize); + if (buf->data) + { + buf->size=memsize; + return TRUE; + } + else + { + buf->size=0; + return FALSE; + }; +} + +void BufferFree(TBuffer *buf) +{ + if (buf->staticid) + { + /* ************** Implement the static buffers ***/ + } + else + free(buf->data); + + buf->size=0; + buf->staticid=0; +} + +abyss_bool BufferRealloc(TBuffer *buf,uint32_t memsize) +{ + if (buf->staticid) + { + TBuffer b; + + if (memsize<=buf->size) + return TRUE; + + if (BufferAlloc(&b,memsize)) + { + memcpy(b.data,buf->data,buf->size); + BufferFree(buf); + *buf=b; + return TRUE; + } + } + else + { + void *d; + + d=realloc(buf->data,memsize); + if (d) + { + buf->data=d; + buf->size=memsize; + return TRUE; + } + } + + return FALSE; +} + + +/********************************************************************* +** String +*********************************************************************/ + +abyss_bool StringAlloc(TString *s) +{ + s->size=0; + if (BufferAlloc(&(s->buffer),256)) + { + *(char *)(s->buffer.data)='\0'; + return TRUE; + } + else + return FALSE; +} + +abyss_bool StringConcat(TString *s,char *s2) +{ + uint32_t len=strlen(s2); + + if (len+s->size+1>s->buffer.size) + if (!BufferRealloc(&(s->buffer),((len+s->size+1+256)/256)*256)) + return FALSE; + + strcat((char *)(s->buffer.data),s2); + s->size+=len; + return TRUE; +} + +abyss_bool StringBlockConcat(TString *s,char *s2,char **ref) +{ + uint32_t len=strlen(s2)+1; + + if (len+s->size>s->buffer.size) + if (!BufferRealloc(&(s->buffer),((len+s->size+1+256)/256)*256)) + return FALSE; + + *ref=(char *)(s->buffer.data)+s->size; + memcpy(*ref,s2,len); + s->size+=len; + return TRUE; +} + +void StringFree(TString *s) +{ + s->size=0; + BufferFree(&(s->buffer)); +} + +char *StringData(TString *s) +{ + return (char *)(s->buffer.data); +} + +/********************************************************************* +** Hash +*********************************************************************/ + +static uint16_t +Hash16(const char * const start) { + + const char * s; + + uint16_t i; + + s = start; + i = 0; + + while(*s) + i = i * 37 + *s++; + + return i; +} + +/********************************************************************* +** Table +*********************************************************************/ + +void TableInit(TTable *t) +{ + t->item=NULL; + t->size=t->maxsize=0; +} + +void TableFree(TTable *t) +{ + uint16_t i; + + if (t->item) + { + if (t->size) + for (i=t->size;i>0;i--) + { + free(t->item[i-1].name); + free(t->item[i-1].value); + }; + + free(t->item); + } + + TableInit(t); +} + + + +abyss_bool +TableFindIndex(TTable * const t, + const char * const name, + uint16_t * const index) { + + uint16_t i,hash=Hash16(name); + + if ((t->item) && (t->size>0) && (*indexsize)) + { + for (i=*index;isize;i++) + if (hash==t->item[i].hash) + if (strcmp(t->item[i].name,name)==0) + { + *index=i; + return TRUE; + }; + }; + + return FALSE; +} + + + +abyss_bool +TableAddReplace(TTable * const t, + const char * const name, + const char * const value) { + + uint16_t i=0; + + if (TableFindIndex(t,name,&i)) + { + free(t->item[i].value); + if (value) + t->item[i].value=strdup(value); + else + { + free(t->item[i].name); + if (--t->size>0) + t->item[i]=t->item[t->size]; + }; + + return TRUE; + } + else + return TableAdd(t,name,value); +} + + + +abyss_bool +TableAdd(TTable * const t, + const char * const name, + const char * const value) { + + if (t->size>=t->maxsize) { + TTableItem *newitem; + + t->maxsize+=16; + + newitem=(TTableItem *)realloc(t->item,(t->maxsize)*sizeof(TTableItem)); + if (newitem) + t->item=newitem; + else { + t->maxsize-=16; + return FALSE; + } + } + + t->item[t->size].name=strdup(name); + t->item[t->size].value=strdup(value); + t->item[t->size].hash=Hash16(name); + + ++t->size; + + return TRUE; +} + + + +char * +TableFind(TTable * const t, + const char * const name) { + + uint16_t i=0; + + if (TableFindIndex(t,name,&i)) + return t->item[i].value; + else + return NULL; +} + +/********************************************************************* +** Pool +*********************************************************************/ + +static TPoolZone * +PoolZoneAlloc(uint32_t const zonesize) { + + TPoolZone * poolZoneP; + + MALLOCARRAY(poolZoneP, zonesize); + if (poolZoneP) { + poolZoneP->pos = &poolZoneP->data[0]; + poolZoneP->maxpos = poolZoneP->pos + zonesize; + poolZoneP->next = NULL; + poolZoneP->prev = NULL; + } + return poolZoneP; +} + + + +static void +PoolZoneFree(TPoolZone * const poolZoneP) { + + free(poolZoneP); +} + + + +abyss_bool +PoolCreate(TPool * const poolP, + uint32_t const zonesize) { + + abyss_bool success; + abyss_bool mutexCreated; + + poolP->zonesize = zonesize; + + mutexCreated = MutexCreate(&poolP->mutex); + if (mutexCreated) { + TPoolZone * const firstZoneP = PoolZoneAlloc(zonesize); + + if (firstZoneP != NULL) { + poolP->firstzone = firstZoneP; + poolP->currentzone = firstZoneP; + success = TRUE; + } else + success = FALSE; + if (!success) + MutexFree(&poolP->mutex); + } else + success = FALSE; + + return success; +} + + + +void * +PoolAlloc(TPool * const poolP, + uint32_t const size) { +/*---------------------------------------------------------------------------- + Allocate a block of size 'size' from pool 'poolP'. +-----------------------------------------------------------------------------*/ + void * retval; + + if (size == 0) + retval = NULL; + else { + abyss_bool gotMutexLock; + + gotMutexLock = MutexLock(&poolP->mutex); + if (!gotMutexLock) + retval = NULL; + else { + TPoolZone * const curPoolZoneP = poolP->currentzone; + + if (curPoolZoneP->pos + size < curPoolZoneP->maxpos) { + retval = curPoolZoneP->pos; + curPoolZoneP->pos += size; + } else { + uint32_t const zonesize = MAX(size, poolP->zonesize); + + TPoolZone * const newPoolZoneP = PoolZoneAlloc(zonesize); + if (newPoolZoneP) { + newPoolZoneP->prev = curPoolZoneP; + newPoolZoneP->next = curPoolZoneP->next; + curPoolZoneP->next = newPoolZoneP; + poolP->currentzone = newPoolZoneP; + retval= newPoolZoneP->data; + newPoolZoneP->pos = newPoolZoneP->data + size; + } else + retval = NULL; + } + MutexUnlock(&poolP->mutex); + } + } + return retval; +} + + + +void +PoolReturn(TPool * const poolP, + void * const blockP) { +/*---------------------------------------------------------------------------- + Return the block at 'blockP' to the pool 'poolP'. WE ASSUME THAT IS + THE MOST RECENTLY ALLOCATED AND NOT RETURNED BLOCK IN THE POOL. +-----------------------------------------------------------------------------*/ + TPoolZone * const curPoolZoneP = poolP->currentzone; + + assert((char*)curPoolZoneP->data < (char*)blockP && + (char*)blockP < (char*)curPoolZoneP->pos); + + curPoolZoneP->pos = blockP; + + if (curPoolZoneP->pos == curPoolZoneP->data) { + /* That emptied out the current zone. Free it and make the previous + zone current. + */ + + assert(curPoolZoneP->prev); /* entry condition */ + + curPoolZoneP->prev->next = NULL; + + PoolZoneFree(curPoolZoneP); + } +} + + + +void +PoolFree(TPool * const poolP) { + + TPoolZone * poolZoneP; + TPoolZone * nextPoolZoneP; + + for (poolZoneP = poolP->firstzone; poolZoneP; poolZoneP = nextPoolZoneP) { + nextPoolZoneP = poolZoneP->next; + free(poolZoneP); + } +} + + + +const char * +PoolStrdup(TPool * const poolP, + const char * const origString) { + + char * newString; + + if (origString == NULL) + newString = NULL; + else { + newString = PoolAlloc(poolP, strlen(origString) + 1); + if (newString != NULL) + strcpy(newString, origString); + } + return newString; +}