1 /******************************************************************************
5 ** This file is part of the ABYSS Web server project.
7 ** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
8 ** All rights reserved.
10 ** Redistribution and use in source and binary forms, with or without
11 ** modification, are permitted provided that the following conditions
13 ** 1. Redistributions of source code must retain the above copyright
14 ** notice, this list of conditions and the following disclaimer.
15 ** 2. Redistributions in binary form must reproduce the above copyright
16 ** notice, this list of conditions and the following disclaimer in the
17 ** documentation and/or other materials provided with the distribution.
18 ** 3. The name of the author may not be used to endorse or promote products
19 ** derived from this software without specific prior written permission.
21 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 *******************************************************************************/
39 #include "mallocvar.h"
40 #include "xmlrpc-c/util_int.h"
41 #include "xmlrpc-c/string_int.h"
43 #include "xmlrpc-c/abyss.h"
49 /*********************************************************************
51 *********************************************************************/
53 void ListInit(TList *sl)
56 sl->size=sl->maxsize=0;
60 void ListInitAutoFree(TList *sl)
63 sl->size=sl->maxsize=0;
70 ListFree(TList * const sl) {
75 for (i = sl->size; i > 0; --i)
89 ListFreeItems(TList * const sl) {
93 for (i = sl->size; i > 0; --i)
101 ListAdd(TList * const sl,
103 /*----------------------------------------------------------------------------
104 Add an item to the end of the list.
105 -----------------------------------------------------------------------------*/
108 if (sl->size >= sl->maxsize) {
109 uint16_t newSize = sl->maxsize + 16;
112 newitem = realloc(sl->item, newSize * sizeof(void *));
115 sl->maxsize = newSize;
119 if (sl->size >= sl->maxsize)
123 sl->item[sl->size++] = str;
131 ListRemove(TList * const sl) {
132 /*----------------------------------------------------------------------------
133 Remove the last item from the list.
134 -----------------------------------------------------------------------------*/
136 assert(sl->size > 0);
144 ListAddFromString(TList * const list,
145 const char * const stringArg) {
154 buffer = strdup(stringArg);
158 abyss_bool endOfString;
162 for (c = &buffer[0], endOfString = FALSE, error = FALSE;
163 !endOfString && !error;
166 NextToken((const char **)&c);
177 for (p = c - 2; *p == ','; --p)
182 added = ListAdd(list, (void*)t);
190 xmlrpc_strfree(buffer);
199 ListFindString(TList * const sl,
200 const char * const str,
201 uint16_t * const indexP)
206 for (i=0;i<sl->size;i++)
207 if (strcmp(str,(char *)(sl->item[i]))==0)
216 /*********************************************************************
218 *********************************************************************/
220 abyss_bool BufferAlloc(TBuffer *buf,uint32_t memsize)
222 /* ************** Implement the static buffers ***/
224 buf->data=(void *)malloc(memsize);
237 void BufferFree(TBuffer *buf)
241 /* ************** Implement the static buffers ***/
250 abyss_bool BufferRealloc(TBuffer *buf,uint32_t memsize)
256 if (memsize<=buf->size)
259 if (BufferAlloc(&b,memsize))
261 memcpy(b.data,buf->data,buf->size);
271 d=realloc(buf->data,memsize);
284 /*********************************************************************
286 *********************************************************************/
288 abyss_bool StringAlloc(TString *s)
291 if (BufferAlloc(&(s->buffer),256))
293 *(char *)(s->buffer.data)='\0';
300 abyss_bool StringConcat(TString *s,char *s2)
302 uint32_t len=strlen(s2);
304 if (len+s->size+1>s->buffer.size)
305 if (!BufferRealloc(&(s->buffer),((len+s->size+1+256)/256)*256))
308 strcat((char *)(s->buffer.data),s2);
313 abyss_bool StringBlockConcat(TString *s,char *s2,char **ref)
315 uint32_t len=strlen(s2)+1;
317 if (len+s->size>s->buffer.size)
318 if (!BufferRealloc(&(s->buffer),((len+s->size+1+256)/256)*256))
321 *ref=(char *)(s->buffer.data)+s->size;
327 void StringFree(TString *s)
330 BufferFree(&(s->buffer));
333 char *StringData(TString *s)
335 return (char *)(s->buffer.data);
338 /*********************************************************************
340 *********************************************************************/
343 Hash16(const char * const start) {
358 /*********************************************************************
360 *********************************************************************/
362 void TableInit(TTable *t)
365 t->size=t->maxsize=0;
368 void TableFree(TTable *t)
375 for (i=t->size;i>0;i--)
377 free(t->item[i-1].name);
378 free(t->item[i-1].value);
390 TableFindIndex(TTable * const t,
391 const char * const name,
392 uint16_t * const index) {
394 uint16_t i,hash=Hash16(name);
396 if ((t->item) && (t->size>0) && (*index<t->size))
398 for (i=*index;i<t->size;i++)
399 if (hash==t->item[i].hash)
400 if (strcmp(t->item[i].name,name)==0)
413 TableAddReplace(TTable * const t,
414 const char * const name,
415 const char * const value) {
419 if (TableFindIndex(t,name,&i))
421 free(t->item[i].value);
423 t->item[i].value=strdup(value);
426 free(t->item[i].name);
428 t->item[i]=t->item[t->size];
434 return TableAdd(t,name,value);
440 TableAdd(TTable * const t,
441 const char * const name,
442 const char * const value) {
444 if (t->size>=t->maxsize) {
449 newitem=(TTableItem *)realloc(t->item,(t->maxsize)*sizeof(TTableItem));
458 t->item[t->size].name=strdup(name);
459 t->item[t->size].value=strdup(value);
460 t->item[t->size].hash=Hash16(name);
470 TableFind(TTable * const t,
471 const char * const name) {
475 if (TableFindIndex(t,name,&i))
476 return t->item[i].value;
481 /*********************************************************************
483 *********************************************************************/
486 PoolZoneAlloc(uint32_t const zonesize) {
488 TPoolZone * poolZoneP;
490 MALLOCARRAY(poolZoneP, zonesize);
492 poolZoneP->pos = &poolZoneP->data[0];
493 poolZoneP->maxpos = poolZoneP->pos + zonesize;
494 poolZoneP->next = NULL;
495 poolZoneP->prev = NULL;
503 PoolZoneFree(TPoolZone * const poolZoneP) {
511 PoolCreate(TPool * const poolP,
512 uint32_t const zonesize) {
515 abyss_bool mutexCreated;
517 poolP->zonesize = zonesize;
519 mutexCreated = MutexCreate(&poolP->mutex);
521 TPoolZone * const firstZoneP = PoolZoneAlloc(zonesize);
523 if (firstZoneP != NULL) {
524 poolP->firstzone = firstZoneP;
525 poolP->currentzone = firstZoneP;
530 MutexFree(&poolP->mutex);
540 PoolAlloc(TPool * const poolP,
541 uint32_t const size) {
542 /*----------------------------------------------------------------------------
543 Allocate a block of size 'size' from pool 'poolP'.
544 -----------------------------------------------------------------------------*/
550 abyss_bool gotMutexLock;
552 gotMutexLock = MutexLock(&poolP->mutex);
556 TPoolZone * const curPoolZoneP = poolP->currentzone;
558 if (curPoolZoneP->pos + size < curPoolZoneP->maxpos) {
559 retval = curPoolZoneP->pos;
560 curPoolZoneP->pos += size;
562 uint32_t const zonesize = MAX(size, poolP->zonesize);
564 TPoolZone * const newPoolZoneP = PoolZoneAlloc(zonesize);
566 newPoolZoneP->prev = curPoolZoneP;
567 newPoolZoneP->next = curPoolZoneP->next;
568 curPoolZoneP->next = newPoolZoneP;
569 poolP->currentzone = newPoolZoneP;
570 retval= newPoolZoneP->data;
571 newPoolZoneP->pos = newPoolZoneP->data + size;
575 MutexUnlock(&poolP->mutex);
584 PoolReturn(TPool * const poolP,
585 void * const blockP) {
586 /*----------------------------------------------------------------------------
587 Return the block at 'blockP' to the pool 'poolP'. WE ASSUME THAT IS
588 THE MOST RECENTLY ALLOCATED AND NOT RETURNED BLOCK IN THE POOL.
589 -----------------------------------------------------------------------------*/
590 TPoolZone * const curPoolZoneP = poolP->currentzone;
592 assert((char*)curPoolZoneP->data < (char*)blockP &&
593 (char*)blockP < (char*)curPoolZoneP->pos);
595 curPoolZoneP->pos = blockP;
597 if (curPoolZoneP->pos == curPoolZoneP->data) {
598 /* That emptied out the current zone. Free it and make the previous
602 assert(curPoolZoneP->prev); /* entry condition */
604 curPoolZoneP->prev->next = NULL;
606 PoolZoneFree(curPoolZoneP);
613 PoolFree(TPool * const poolP) {
615 TPoolZone * poolZoneP;
616 TPoolZone * nextPoolZoneP;
618 for (poolZoneP = poolP->firstzone; poolZoneP; poolZoneP = nextPoolZoneP) {
619 nextPoolZoneP = poolZoneP->next;
627 PoolStrdup(TPool * const poolP,
628 const char * const origString) {
632 if (origString == NULL)
635 newString = PoolAlloc(poolP, strlen(origString) + 1);
636 if (newString != NULL)
637 strcpy(newString, origString);