abyss_data.c

Go to the documentation of this file.
00001 /******************************************************************************
00002 **
00003 ** list.c
00004 **
00005 ** This file is part of the ABYSS Web server project.
00006 **
00007 ** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
00008 ** All rights reserved.
00009 **
00010 ** Redistribution and use in source and binary forms, with or without
00011 ** modification, are permitted provided that the following conditions
00012 ** are met:
00013 ** 1. Redistributions of source code must retain the above copyright
00014 **    notice, this list of conditions and the following disclaimer.
00015 ** 2. Redistributions in binary form must reproduce the above copyright
00016 **    notice, this list of conditions and the following disclaimer in the
00017 **    documentation and/or other materials provided with the distribution.
00018 ** 3. The name of the author may not be used to endorse or promote products
00019 **    derived from this software without specific prior written permission.
00020 ** 
00021 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
00022 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024 ** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00025 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00027 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00028 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031 ** SUCH DAMAGE.
00032 **
00033 *******************************************************************************/
00034 
00035 #include <assert.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 
00039 #include "abyss_mallocvar.h"
00040 #include "abyss_xmlrpc_int.h"
00041 
00042 #include <xmlrpc-c/abyss.h>
00043 
00044 #include "abyss_token.h"
00045 
00046 #include "abyss_data.h"
00047 
00048 /*********************************************************************
00049 ** List
00050 *********************************************************************/
00051 
00052 void ListInit(TList *sl)
00053 {
00054     sl->item=NULL;
00055     sl->size=sl->maxsize=0;
00056     sl->autofree=FALSE;
00057 }
00058 
00059 void ListInitAutoFree(TList *sl)
00060 {
00061     sl->item=NULL;
00062     sl->size=sl->maxsize=0;
00063     sl->autofree=TRUE;
00064 }
00065 
00066 
00067 
00068 void
00069 ListFree(TList * const sl) {
00070 
00071     if (sl->item) {
00072         if (sl->autofree) {
00073             unsigned int i;
00074             for (i = sl->size; i > 0; --i)
00075                 free(sl->item[i-1]);
00076             
00077         }
00078         free(sl->item);
00079     }
00080     sl->item = NULL;
00081     sl->size = 0;
00082     sl->maxsize = 0;
00083 }
00084 
00085 
00086 
00087 void
00088 ListFreeItems(TList * const sl) {
00089 
00090     if (sl->item) {
00091         unsigned int i;
00092         for (i = sl->size; i > 0; --i)
00093             free(sl->item[i-1]);
00094     }
00095 }
00096 
00097 
00098 
00099 abyss_bool
00100 ListAdd(TList * const sl,
00101         void *  const str) {
00102 /*----------------------------------------------------------------------------
00103    Add an item to the end of the list.
00104 -----------------------------------------------------------------------------*/
00105     abyss_bool success;
00106 
00107     if (sl->size >= sl->maxsize) {
00108         uint16_t newSize = sl->maxsize + 16;
00109         void **newitem;
00110         
00111         newitem = realloc(sl->item, newSize * sizeof(void *));
00112         if (newitem) {
00113             sl->item    = newitem;
00114             sl->maxsize = newSize;
00115         }
00116     }
00117 
00118     if (sl->size >= sl->maxsize)
00119         success = FALSE;
00120     else {
00121         success = TRUE;
00122         sl->item[sl->size++] = str;
00123     }
00124     return success;
00125 }
00126 
00127 
00128 
00129 void
00130 ListRemove(TList * const sl) {
00131 /*----------------------------------------------------------------------------
00132    Remove the last item from the list.
00133 -----------------------------------------------------------------------------*/
00134 
00135     assert(sl->size > 0);
00136 
00137     --sl->size;
00138 }
00139 
00140 
00141 
00142 abyss_bool
00143 ListAddFromString(TList *      const list,
00144                   const char * const stringArg) {
00145 
00146     abyss_bool retval;
00147     
00148     if (!stringArg)
00149         retval = TRUE;
00150     else {
00151         char * buffer;
00152         
00153         buffer = strdup(stringArg);
00154         if (!buffer)
00155             retval = FALSE;
00156         else {
00157             abyss_bool endOfString;
00158             abyss_bool error;
00159             char * c;
00160 
00161             for (c = &buffer[0], endOfString = FALSE, error = FALSE;
00162                  !endOfString && !error;
00163                 ) {
00164                 const char * t;
00165                 NextToken((const char **)&c);
00166                 
00167                 while (*c == ',')
00168                     ++c;
00169                 
00170                 t = GetToken(&c);
00171                 if (!t)
00172                     endOfString = TRUE;
00173                 else {
00174                     char * p;
00175 
00176                     for (p = c - 2; *p == ','; --p)
00177                         *p = '\0';
00178                     
00179                     if (t[0] != '\0') {
00180                         abyss_bool added;
00181                         added = ListAdd(list, (void*)t);
00182                         
00183                         if (!added)
00184                             error = TRUE;
00185                     }
00186                 }
00187             }
00188             retval = !error;
00189             xmlrpc_strfree(buffer);
00190         }
00191     }
00192     return retval;
00193 }
00194 
00195 
00196 
00197 abyss_bool
00198 ListFindString(TList *      const sl,
00199                const char * const str,
00200                uint16_t *   const indexP)
00201 {
00202     uint16_t i;
00203 
00204     if (sl->item && str)
00205         for (i=0;i<sl->size;i++)
00206             if (strcmp(str,(char *)(sl->item[i]))==0)
00207             {
00208                 *indexP=i;
00209                 return TRUE;
00210             };
00211 
00212     return FALSE;
00213 }
00214 
00215 /*********************************************************************
00216 ** Buffer
00217 *********************************************************************/
00218 
00219 abyss_bool BufferAlloc(TBuffer *buf,uint32_t memsize)
00220 {
00221     /* ************** Implement the static buffers ***/
00222     buf->staticid=0;
00223     buf->data=(void *)malloc(memsize);
00224     if (buf->data)
00225     {
00226         buf->size=memsize;
00227         return TRUE;
00228     }
00229     else
00230     {
00231         buf->size=0;
00232         return FALSE;
00233     };
00234 }
00235 
00236 void BufferFree(TBuffer *buf)
00237 {
00238     if (buf->staticid)
00239     {
00240         /* ************** Implement the static buffers ***/
00241     }
00242     else
00243         free(buf->data);
00244 
00245     buf->size=0;
00246     buf->staticid=0;
00247 }
00248 
00249 abyss_bool BufferRealloc(TBuffer *buf,uint32_t memsize)
00250 {
00251     if (buf->staticid)
00252     {
00253         TBuffer b;
00254 
00255         if (memsize<=buf->size)
00256             return TRUE;
00257 
00258         if (BufferAlloc(&b,memsize))
00259         {
00260             memcpy(b.data,buf->data,buf->size);
00261             BufferFree(buf);
00262             *buf=b;
00263             return TRUE;
00264         }
00265     }
00266     else
00267     {
00268         void *d;
00269         
00270         d=realloc(buf->data,memsize);
00271         if (d)
00272         {
00273             buf->data=d;
00274             buf->size=memsize;
00275             return TRUE;
00276         }
00277     }
00278 
00279     return FALSE;
00280 }
00281 
00282 
00283 /*********************************************************************
00284 ** String
00285 *********************************************************************/
00286 
00287 abyss_bool StringAlloc(TString *s)
00288 {
00289     s->size=0;
00290     if (BufferAlloc(&(s->buffer),256))
00291     {
00292         *(char *)(s->buffer.data)='\0';
00293         return TRUE;
00294     }
00295     else
00296         return FALSE;
00297 }
00298 
00299 abyss_bool StringConcat(TString *s,char *s2)
00300 {
00301     uint32_t len=strlen(s2);
00302 
00303     if (len+s->size+1>s->buffer.size)
00304         if (!BufferRealloc(&(s->buffer),((len+s->size+1+256)/256)*256))
00305             return FALSE;
00306     
00307     strcat((char *)(s->buffer.data),s2);
00308     s->size+=len;
00309     return TRUE;
00310 }
00311 
00312 abyss_bool StringBlockConcat(TString *s,char *s2,char **ref)
00313 {
00314     uint32_t len=strlen(s2)+1;
00315 
00316     if (len+s->size>s->buffer.size)
00317         if (!BufferRealloc(&(s->buffer),((len+s->size+1+256)/256)*256))
00318             return FALSE;
00319     
00320     *ref=(char *)(s->buffer.data)+s->size;
00321     memcpy(*ref,s2,len);
00322     s->size+=len;
00323     return TRUE;
00324 }
00325 
00326 void StringFree(TString *s)
00327 {
00328     s->size=0;
00329     BufferFree(&(s->buffer));
00330 }
00331 
00332 char *StringData(TString *s)
00333 {
00334     return (char *)(s->buffer.data);
00335 }
00336 
00337 /*********************************************************************
00338 ** Hash
00339 *********************************************************************/
00340 
00341 static uint16_t
00342 Hash16(const char * const start) {
00343 
00344     const char * s;
00345     
00346     uint16_t i;
00347     
00348     s = start;
00349     i = 0;
00350 
00351     while(*s)
00352         i = i * 37 + *s++;
00353 
00354     return i;
00355 }
00356 
00357 /*********************************************************************
00358 ** Table
00359 *********************************************************************/
00360 
00361 void TableInit(TTable *t)
00362 {
00363     t->item=NULL;
00364     t->size=t->maxsize=0;
00365 }
00366 
00367 void TableFree(TTable *t)
00368 {
00369     uint16_t i;
00370 
00371     if (t->item)
00372     {
00373         if (t->size)
00374             for (i=t->size;i>0;i--)
00375             {
00376                 free(t->item[i-1].name);
00377                 free(t->item[i-1].value);
00378             };
00379             
00380         free(t->item);
00381     }
00382 
00383     TableInit(t);
00384 }
00385 
00386 
00387 
00388 abyss_bool
00389 TableFindIndex(TTable *     const t,
00390                const char * const name,
00391                uint16_t *   const index) {
00392 
00393     uint16_t i,hash=Hash16(name);
00394 
00395     if ((t->item) && (t->size>0) && (*index<t->size))
00396     {
00397         for (i=*index;i<t->size;i++)
00398             if (hash==t->item[i].hash)
00399                 if (strcmp(t->item[i].name,name)==0)
00400                 {
00401                     *index=i;
00402                     return TRUE;
00403                 };
00404     };
00405 
00406     return FALSE;
00407 }
00408 
00409 
00410 
00411 abyss_bool
00412 TableAddReplace(TTable *     const t,
00413                 const char * const name,
00414                 const char * const value) {
00415 
00416     uint16_t i=0;
00417 
00418     if (TableFindIndex(t,name,&i))
00419     {
00420         free(t->item[i].value);
00421         if (value)
00422             t->item[i].value=strdup(value);
00423         else
00424         {
00425             free(t->item[i].name);
00426             if (--t->size>0)
00427                 t->item[i]=t->item[t->size];
00428         };
00429 
00430         return TRUE;
00431     }
00432     else
00433         return TableAdd(t,name,value);
00434 }
00435 
00436 
00437 
00438 abyss_bool
00439 TableAdd(TTable *     const t,
00440          const char * const name,
00441          const char * const value) {
00442 
00443     if (t->size>=t->maxsize) {
00444         TTableItem *newitem;
00445         
00446         t->maxsize+=16;
00447 
00448         newitem=(TTableItem *)realloc(t->item,(t->maxsize)*sizeof(TTableItem));
00449         if (newitem)
00450             t->item=newitem;
00451         else {
00452             t->maxsize-=16;
00453             return FALSE;
00454         }
00455     }
00456 
00457     t->item[t->size].name=strdup(name);
00458     t->item[t->size].value=strdup(value);
00459     t->item[t->size].hash=Hash16(name);
00460 
00461     ++t->size;
00462 
00463     return TRUE;
00464 }
00465 
00466 
00467 
00468 char *
00469 TableFind(TTable *     const t,
00470           const char * const name) {
00471 
00472     uint16_t i=0;
00473 
00474     if (TableFindIndex(t,name,&i))
00475         return t->item[i].value;
00476     else
00477         return NULL;
00478 }
00479 
00480 /*********************************************************************
00481 ** Pool
00482 *********************************************************************/
00483 
00484 static TPoolZone *
00485 PoolZoneAlloc(uint32_t const zonesize) {
00486 
00487     TPoolZone * poolZoneP;
00488     
00489     MALLOCARRAY(poolZoneP, zonesize);
00490     if (poolZoneP) {
00491         poolZoneP->pos    = &poolZoneP->data[0];
00492         poolZoneP->maxpos = poolZoneP->pos + zonesize;
00493         poolZoneP->next   = NULL;
00494         poolZoneP->prev   = NULL;
00495     }
00496     return poolZoneP;
00497 }
00498 
00499 
00500 
00501 static void
00502 PoolZoneFree(TPoolZone * const poolZoneP) {
00503 
00504     free(poolZoneP);
00505 }
00506 
00507 
00508 
00509 abyss_bool
00510 PoolCreate(TPool *  const poolP,
00511            uint32_t const zonesize) {
00512 
00513     abyss_bool success;
00514     abyss_bool mutexCreated;
00515 
00516     poolP->zonesize = zonesize;
00517 
00518     mutexCreated = MutexCreate(&poolP->mutex);
00519     if (mutexCreated) {
00520         TPoolZone * const firstZoneP = PoolZoneAlloc(zonesize);
00521 
00522         if (firstZoneP != NULL) {
00523             poolP->firstzone   = firstZoneP;
00524             poolP->currentzone = firstZoneP;
00525             success = TRUE;
00526         } else
00527             success = FALSE;
00528         if (!success)
00529             MutexFree(&poolP->mutex);
00530     } else
00531         success = FALSE;
00532 
00533     return success;
00534 }
00535 
00536 
00537 
00538 void *
00539 PoolAlloc(TPool *  const poolP,
00540           uint32_t const size) {
00541 /*----------------------------------------------------------------------------
00542    Allocate a block of size 'size' from pool 'poolP'.
00543 -----------------------------------------------------------------------------*/
00544     void * retval;
00545 
00546     if (size == 0)
00547         retval = NULL;
00548     else {
00549         abyss_bool gotMutexLock;
00550 
00551         gotMutexLock = MutexLock(&poolP->mutex);
00552         if (!gotMutexLock)
00553             retval = NULL;
00554         else {
00555             TPoolZone * const curPoolZoneP = poolP->currentzone;
00556 
00557             if (curPoolZoneP->pos + size < curPoolZoneP->maxpos) {
00558                 retval = curPoolZoneP->pos;
00559                 curPoolZoneP->pos += size;
00560             } else {
00561                 uint32_t const zonesize = MAX(size, poolP->zonesize);
00562 
00563                 TPoolZone * const newPoolZoneP = PoolZoneAlloc(zonesize);
00564                 if (newPoolZoneP) {
00565                     newPoolZoneP->prev = curPoolZoneP;
00566                     newPoolZoneP->next = curPoolZoneP->next;
00567                     curPoolZoneP->next = newPoolZoneP;
00568                     poolP->currentzone = newPoolZoneP;
00569                     retval= newPoolZoneP->data;
00570                     newPoolZoneP->pos = newPoolZoneP->data + size;
00571                 } else
00572                     retval = NULL;
00573             }
00574             MutexUnlock(&poolP->mutex);
00575         }
00576     }
00577     return retval;
00578 }
00579 
00580 
00581 
00582 void
00583 PoolReturn(TPool *  const poolP,
00584            void *   const blockP) {
00585 /*----------------------------------------------------------------------------
00586    Return the block at 'blockP' to the pool 'poolP'.  WE ASSUME THAT IS
00587    THE MOST RECENTLY ALLOCATED AND NOT RETURNED BLOCK IN THE POOL.
00588 -----------------------------------------------------------------------------*/
00589     TPoolZone * const curPoolZoneP = poolP->currentzone;
00590 
00591     assert((char*)curPoolZoneP->data < (char*)blockP &&
00592            (char*)blockP < (char*)curPoolZoneP->pos);
00593 
00594     curPoolZoneP->pos = blockP;
00595 
00596     if (curPoolZoneP->pos == curPoolZoneP->data) {
00597         /* That emptied out the current zone.  Free it and make the previous
00598            zone current.
00599         */
00600 
00601         assert(curPoolZoneP->prev);  /* entry condition */
00602 
00603         curPoolZoneP->prev->next = NULL;
00604 
00605         PoolZoneFree(curPoolZoneP);
00606     }
00607 }
00608 
00609 
00610 
00611 void
00612 PoolFree(TPool * const poolP) {
00613 
00614     TPoolZone * poolZoneP;
00615     TPoolZone * nextPoolZoneP;
00616     
00617     for (poolZoneP = poolP->firstzone; poolZoneP; poolZoneP = nextPoolZoneP) {
00618         nextPoolZoneP = poolZoneP->next;
00619         free(poolZoneP);
00620     }
00621 }
00622 
00623 
00624 
00625 const char *
00626 PoolStrdup(TPool *      const poolP,
00627            const char * const origString) {
00628 
00629     char * newString;
00630 
00631     if (origString == NULL)
00632         newString = NULL;
00633     else {
00634         newString = PoolAlloc(poolP, strlen(origString) + 1);
00635         if (newString != NULL)
00636             strcpy(newString, origString);
00637     }
00638     return newString;
00639 }

Generated on Thu May 17 10:00:23 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6