📄 data.c
字号:
/********************************************************************************** list.c**** This file is part of the ABYSS Web server project.**** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.** 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 <assert.h>#include <stdlib.h>#include <string.h>#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;}voidListFree(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;}voidListFreeItems(TList * const sl) { if (sl->item) { unsigned int i; for (i = sl->size; i > 0; --i) free(sl->item[i-1]); }}abyss_boolListAdd(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;}voidListRemove(TList * const sl) {/*---------------------------------------------------------------------------- Remove the last item from the list.-----------------------------------------------------------------------------*/ assert(sl->size > 0); --sl->size;}abyss_boolListAddFromString(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_boolListFindString(TList * const sl, const char * const str, uint16_t * const indexP){ uint16_t i; if (sl->item && str) for (i=0;i<sl->size;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_tHash16(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_boolTableFindIndex(TTable * const t, const char * const name, uint16_t * const index) { uint16_t i,hash=Hash16(name); if ((t->item) && (t->size>0) && (*index<t->size)) { for (i=*index;i<t->size;i++) if (hash==t->item[i].hash) if (strcmp(t->item[i].name,name)==0) { *index=i; return TRUE; }; }; return FALSE;}abyss_boolTableAddReplace(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_boolTableAdd(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 voidPoolZoneFree(TPoolZone * const poolZoneP) { free(poolZoneP);}abyss_boolPoolCreate(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;}voidPoolReturn(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); }}voidPoolFree(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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -