LCOV - code coverage report
Current view: top level - media/mtransport/third_party/nrappkit/src/util/libekr - r_assoc.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 194 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /**
       2             :    r_assoc.c
       3             : 
       4             : 
       5             :    Copyright (C) 2002-2003, Network Resonance, Inc.
       6             :    Copyright (C) 2006, Network Resonance, Inc.
       7             :    All Rights Reserved
       8             : 
       9             :    Redistribution and use in source and binary forms, with or without
      10             :    modification, are permitted provided that the following conditions
      11             :    are met:
      12             : 
      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. Neither the name of Network Resonance, Inc. nor the name of any
      19             :       contributors to this software may be used to endorse or promote
      20             :       products derived from this software without specific prior written
      21             :       permission.
      22             : 
      23             :    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
      24             :    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      25             :    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      26             :    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      27             :    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      28             :    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      29             :    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      30             :    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      31             :    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      32             :    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      33             :    POSSIBILITY OF SUCH DAMAGE.
      34             : 
      35             : 
      36             :  */
      37             : 
      38             : /**
      39             :    r_assoc.c
      40             : 
      41             :    This is an associative array implementation, using an open-chained
      42             :    hash bucket technique.
      43             : 
      44             :    Note that this implementation permits each data entry to have
      45             :    separate copy constructors and destructors. This currently wastes
      46             :    space, but could be implemented while saving space by using
      47             :    the high order bit of the length value or somesuch.
      48             : 
      49             :    The major problem with this code is it's not resizable, though it
      50             :    could be made so.
      51             : 
      52             : 
      53             :    Copyright (C) 1999-2000 RTFM, Inc.
      54             :    All Rights Reserved
      55             : 
      56             :    This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
      57             :    <ekr@rtfm.com> and licensed by RTFM, Inc.
      58             : 
      59             :    Redistribution and use in source and binary forms, with or without
      60             :    modification, are permitted provided that the following conditions
      61             :    are met:
      62             :    1. Redistributions of source code must retain the above copyright
      63             :       notice, this list of conditions and the following disclaimer.
      64             :    2. Redistributions in binary form must reproduce the above copyright
      65             :       notice, this list of conditions and the following disclaimer in the
      66             :       documentation and/or other materials provided with the distribution.
      67             :    3. All advertising materials mentioning features or use of this software
      68             :       must display the following acknowledgement:
      69             : 
      70             :       This product includes software developed by Eric Rescorla for
      71             :       RTFM, Inc.
      72             : 
      73             :    4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
      74             :       used to endorse or promote products derived from this
      75             :       software without specific prior written permission.
      76             : 
      77             :    THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
      78             :    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      79             :    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      80             :    ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      81             :    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      82             :    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      83             :    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      84             :    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      85             :    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      86             :    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
      87             : 
      88             :    $Id: r_assoc.c,v 1.4 2007/06/08 17:41:49 adamcain Exp $
      89             : 
      90             :    ekr@rtfm.com  Sun Jan 17 17:57:15 1999
      91             :  */
      92             : 
      93             : static char *RCSSTRING __UNUSED__ ="$Id: r_assoc.c,v 1.4 2007/06/08 17:41:49 adamcain Exp $";
      94             : 
      95             : #include <r_common.h>
      96             : #include <string.h>
      97             : #include "r_assoc.h"
      98             : 
      99             : typedef struct r_assoc_el_ {
     100             :      char *key;
     101             :      int key_len;
     102             :      void *data;
     103             :      struct r_assoc_el_ *prev;
     104             :      struct r_assoc_el_ *next;
     105             :      int (*copy)(void **n,void *old);
     106             :      int (*destroy)(void *ptr);
     107             : } r_assoc_el;
     108             : 
     109             : struct r_assoc_ {
     110             :      int size;
     111             :      int bits;
     112             :      int (*hash_func)(char *key,int len,int size);
     113             :      r_assoc_el **chains;
     114             :      UINT4 num_elements;
     115             : };
     116             : 
     117             : #define DEFAULT_TABLE_BITS 5
     118             : 
     119             : static int destroy_assoc_chain(r_assoc_el *chain);
     120             : static int r_assoc_fetch_bucket(r_assoc *assoc,
     121             :   char *key,int len,r_assoc_el **bucketp);
     122             : static int copy_assoc_chain(r_assoc_el **knewp, r_assoc_el *old);
     123             : 
     124           0 : int r_assoc_create(assocp,hash_func,bits)
     125             :   r_assoc **assocp;
     126             :   int (*hash_func)(char *key,int len,int size);
     127             :   int bits;
     128             :   {
     129           0 :     r_assoc *assoc=0;
     130             :     int _status;
     131             : 
     132           0 :     if(!(assoc=(r_assoc *)RCALLOC(sizeof(r_assoc))))
     133           0 :       ABORT(R_NO_MEMORY);
     134           0 :     assoc->size=(1<<bits);
     135           0 :     assoc->bits=bits;
     136           0 :     assoc->hash_func=hash_func;
     137             : 
     138           0 :     if(!(assoc->chains=(r_assoc_el **)RCALLOC(sizeof(r_assoc_el *)*
     139             :       assoc->size)))
     140           0 :       ABORT(R_NO_MEMORY);
     141             : 
     142           0 :     *assocp=assoc;
     143             : 
     144           0 :     _status=0;
     145             :   abort:
     146           0 :     if(_status){
     147           0 :       r_assoc_destroy(&assoc);
     148             :     }
     149           0 :     return(_status);
     150             :   }
     151             : 
     152           0 : int r_assoc_destroy(assocp)
     153             :   r_assoc **assocp;
     154             :   {
     155             :     r_assoc *assoc;
     156             :     int i;
     157             : 
     158           0 :     if(!assocp || !*assocp)
     159           0 :       return(0);
     160             : 
     161           0 :     assoc=*assocp;
     162           0 :     for(i=0;i<assoc->size;i++)
     163           0 :       destroy_assoc_chain(assoc->chains[i]);
     164             : 
     165           0 :     RFREE(assoc->chains);
     166           0 :     RFREE(*assocp);
     167             : 
     168           0 :     return(0);
     169             :   }
     170             : 
     171           0 : static int destroy_assoc_chain(chain)
     172             :   r_assoc_el *chain;
     173             :   {
     174             :     r_assoc_el *nxt;
     175             : 
     176           0 :     while(chain){
     177           0 :       nxt=chain->next;
     178             : 
     179           0 :       if(chain->destroy)
     180           0 :         chain->destroy(chain->data);
     181             : 
     182           0 :       RFREE(chain->key);
     183             : 
     184           0 :       RFREE(chain);
     185           0 :       chain=nxt;
     186             :     }
     187             : 
     188           0 :     return(0);
     189             :   }
     190             : 
     191           0 : static int copy_assoc_chain(knewp,old)
     192             :   r_assoc_el **knewp;
     193             :   r_assoc_el *old;
     194             :   {
     195           0 :     r_assoc_el *knew=0,*ptr,*tmp;
     196             :     int r,_status;
     197             : 
     198           0 :     ptr=0; /* Pacify GCC's uninitialized warning.
     199             :               It's not correct */
     200           0 :     if(!old) {
     201           0 :       *knewp=0;
     202           0 :       return(0);
     203             :     }
     204           0 :     for(;old;old=old->next){
     205           0 :       if(!(tmp=(r_assoc_el *)RCALLOC(sizeof(r_assoc_el))))
     206           0 :         ABORT(R_NO_MEMORY);
     207             : 
     208           0 :       if(!knew){
     209           0 :         knew=tmp;
     210           0 :         ptr=knew;
     211             :       }
     212             :       else{
     213           0 :         ptr->next=tmp;
     214           0 :         tmp->prev=ptr;
     215           0 :         ptr=tmp;
     216             :       }
     217             : 
     218           0 :       ptr->destroy=old->destroy;
     219           0 :       ptr->copy=old->copy;
     220             : 
     221           0 :       if(old->copy){
     222           0 :         if(r=old->copy(&ptr->data,old->data))
     223           0 :           ABORT(r);
     224             :       }
     225             :       else
     226           0 :         ptr->data=old->data;
     227             : 
     228           0 :       if(!(ptr->key=(char *)RMALLOC(old->key_len)))
     229           0 :         ABORT(R_NO_MEMORY);
     230           0 :       memcpy(ptr->key,old->key,ptr->key_len=old->key_len);
     231             :     }
     232             : 
     233           0 :     *knewp=knew;
     234             : 
     235           0 :     _status=0;
     236             :   abort:
     237           0 :     if(_status){
     238           0 :       destroy_assoc_chain(knew);
     239             :     }
     240           0 :     return(_status);
     241             :   }
     242             : 
     243           0 : static int r_assoc_fetch_bucket(assoc,key,len,bucketp)
     244             :   r_assoc *assoc;
     245             :   char *key;
     246             :   int len;
     247             :   r_assoc_el **bucketp;
     248             :   {
     249             :     UINT4 hash_value;
     250             :     r_assoc_el *bucket;
     251             : 
     252           0 :     hash_value=assoc->hash_func(key,len,assoc->bits);
     253             : 
     254           0 :     for(bucket=assoc->chains[hash_value];bucket;bucket=bucket->next){
     255           0 :       if(bucket->key_len == len && !memcmp(bucket->key,key,len)){
     256           0 :         *bucketp=bucket;
     257           0 :         return(0);
     258             :       }
     259             :     }
     260             : 
     261           0 :     return(R_NOT_FOUND);
     262             :   }
     263             : 
     264           0 : int r_assoc_fetch(assoc,key,len,datap)
     265             :   r_assoc *assoc;
     266             :   char *key;
     267             :   int len;
     268             :   void **datap;
     269             :   {
     270             :     r_assoc_el *bucket;
     271             :     int r;
     272             : 
     273           0 :     if(r=r_assoc_fetch_bucket(assoc,key,len,&bucket)){
     274           0 :       if(r!=R_NOT_FOUND)
     275           0 :         ERETURN(r);
     276           0 :       return(r);
     277             :     }
     278             : 
     279           0 :     *datap=bucket->data;
     280           0 :     return(0);
     281             :   }
     282             : 
     283           0 : int r_assoc_insert(assoc,key,len,data,copy,destroy,how)
     284             :   r_assoc *assoc;
     285             :   char *key;
     286             :   int len;
     287             :   void *data;
     288             :   int (*copy)(void **knew,void *old);
     289             :   int (*destroy)(void *ptr);
     290             :   int how;
     291             :   {
     292           0 :     r_assoc_el *bucket,*new_bucket=0;
     293             :     int r,_status;
     294             : 
     295           0 :     if(r=r_assoc_fetch_bucket(assoc,key,len,&bucket)){
     296             :       /*Note that we compute the hash value twice*/
     297             :       UINT4 hash_value;
     298             : 
     299           0 :       if(r!=R_NOT_FOUND)
     300           0 :         ABORT(r);
     301           0 :       hash_value=assoc->hash_func(key,len,assoc->bits);
     302             : 
     303           0 :       if(!(new_bucket=(r_assoc_el *)RCALLOC(sizeof(r_assoc_el))))
     304           0 :         ABORT(R_NO_MEMORY);
     305           0 :       if(!(new_bucket->key=(char *)RMALLOC(len)))
     306           0 :         ABORT(R_NO_MEMORY);
     307           0 :       memcpy(new_bucket->key,key,len);
     308           0 :       new_bucket->key_len=len;
     309             : 
     310             :       /*Insert at the list head. Is FIFO a good algorithm?*/
     311           0 :       if(assoc->chains[hash_value])
     312           0 :         assoc->chains[hash_value]->prev=new_bucket;
     313           0 :       new_bucket->next=assoc->chains[hash_value];
     314           0 :       assoc->chains[hash_value]=new_bucket;
     315           0 :       bucket=new_bucket;
     316             :     }
     317             :     else{
     318           0 :       if(!(how&R_ASSOC_REPLACE))
     319           0 :         ABORT(R_ALREADY);
     320             : 
     321           0 :       if(bucket->destroy)
     322           0 :         bucket->destroy(bucket->data);
     323             :     }
     324             : 
     325           0 :     bucket->data=data;
     326           0 :     bucket->copy=copy;
     327           0 :     bucket->destroy=destroy;
     328           0 :     assoc->num_elements++;
     329             : 
     330           0 :     _status=0;
     331             :   abort:
     332           0 :     if(_status && new_bucket){
     333           0 :       RFREE(new_bucket->key);
     334           0 :       RFREE(new_bucket);
     335             :     }
     336           0 :     return(_status);
     337             :   }
     338             : 
     339           0 : int r_assoc_delete(assoc,key,len)
     340             :   r_assoc *assoc;
     341             :   char *key;
     342             :   int len;
     343             :   {
     344             :     int r;
     345             :     r_assoc_el *bucket;
     346             :     UINT4 hash_value;
     347             : 
     348           0 :     if(r=r_assoc_fetch_bucket(assoc,key,len,&bucket)){
     349           0 :       if(r!=R_NOT_FOUND)
     350           0 :         ERETURN(r);
     351           0 :       return(r);
     352             :     }
     353             : 
     354             :     /* Now remove the element from the hash chain */
     355           0 :     if(bucket->prev){
     356           0 :       bucket->prev->next=bucket->next;
     357             :     }
     358             :     else {
     359           0 :       hash_value=assoc->hash_func(key,len,assoc->bits);
     360           0 :       assoc->chains[hash_value]=bucket->next;
     361             :     }
     362             : 
     363           0 :     if(bucket->next)
     364           0 :       bucket->next->prev=bucket->prev;
     365             : 
     366             :     /* Remove the data */
     367           0 :     if(bucket->destroy)
     368           0 :       bucket->destroy(bucket->data);
     369             : 
     370           0 :     RFREE(bucket->key);
     371           0 :     RFREE(bucket);
     372           0 :     assoc->num_elements--;
     373             : 
     374           0 :     return(0);
     375             :   }
     376             : 
     377           0 : int r_assoc_copy(knewp,old)
     378             :   r_assoc **knewp;
     379             :   r_assoc *old;
     380             :   {
     381             :     int r,_status,i;
     382             :     r_assoc *knew;
     383             : 
     384           0 :     if(!(knew=(r_assoc *)RCALLOC(sizeof(r_assoc))))
     385           0 :       ABORT(R_NO_MEMORY);
     386           0 :     knew->size=old->size;
     387           0 :     knew->bits=old->bits;
     388           0 :     knew->hash_func=old->hash_func;
     389             : 
     390           0 :     if(!(knew->chains=(r_assoc_el **)RCALLOC(sizeof(r_assoc_el)*old->size)))
     391           0 :       ABORT(R_NO_MEMORY);
     392           0 :     for(i=0;i<knew->size;i++){
     393           0 :       if(r=copy_assoc_chain(knew->chains+i,old->chains[i]))
     394           0 :         ABORT(r);
     395             :     }
     396           0 :     knew->num_elements=old->num_elements;
     397             : 
     398           0 :     *knewp=knew;
     399             : 
     400           0 :     _status=0;
     401             :   abort:
     402           0 :     if(_status){
     403           0 :       r_assoc_destroy(&knew);
     404             :     }
     405           0 :     return(_status);
     406             :   }
     407             : 
     408           0 : int r_assoc_num_elements(r_assoc *assoc,int *sizep)
     409             :   {
     410           0 :     *sizep=assoc->num_elements;
     411             : 
     412           0 :     return(0);
     413             :   }
     414             : 
     415           0 : int r_assoc_init_iter(assoc,iter)
     416             :   r_assoc *assoc;
     417             :   r_assoc_iterator *iter;
     418             :   {
     419             :     int i;
     420             : 
     421           0 :     iter->assoc=assoc;
     422           0 :     iter->prev_chain=-1;
     423           0 :     iter->prev=0;
     424             : 
     425           0 :     iter->next_chain=assoc->size;
     426           0 :     iter->next=0;
     427             : 
     428           0 :     for(i=0;i<assoc->size;i++){
     429           0 :       if(assoc->chains[i]!=0){
     430           0 :         iter->next_chain=i;
     431           0 :         iter->next=assoc->chains[i];
     432           0 :         break;
     433             :       }
     434             :     }
     435             : 
     436           0 :     return(0);
     437             :   }
     438             : 
     439           0 : int r_assoc_iter(iter,key,keyl,val)
     440             :   r_assoc_iterator *iter;
     441             :   void **key;
     442             :   int *keyl;
     443             :   void **val;
     444             :   {
     445             :     int i;
     446             :     r_assoc_el *ret;
     447             : 
     448           0 :     if(!iter->next)
     449           0 :       return(R_EOD);
     450           0 :     ret=iter->next;
     451             : 
     452           0 :     *key=ret->key;
     453           0 :     *keyl=ret->key_len;
     454           0 :     *val=ret->data;
     455             : 
     456             :     /* Now increment */
     457           0 :     iter->prev_chain=iter->next_chain;
     458           0 :     iter->prev=iter->next;
     459             : 
     460             :     /* More on this chain */
     461           0 :     if(iter->next->next){
     462           0 :       iter->next=iter->next->next;
     463             :     }
     464             :     else{
     465           0 :       iter->next=0;
     466             : 
     467             :       /* FInd the next occupied chain*/
     468           0 :       for(i=iter->next_chain+1;i<iter->assoc->size;i++){
     469           0 :         if(iter->assoc->chains[i]){
     470           0 :           iter->next_chain=i;
     471           0 :           iter->next=iter->assoc->chains[i];
     472           0 :           break;
     473             :         }
     474             :       }
     475             :     }
     476             : 
     477           0 :     return(0);
     478             :   }
     479             : 
     480             : /* Delete the last returned value*/
     481           0 : int r_assoc_iter_delete(iter)
     482             :   r_assoc_iterator *iter;
     483             :   {
     484             :     /* First unhook it from the list*/
     485           0 :     if(!iter->prev->prev){
     486             :       /* First element*/
     487           0 :       iter->assoc->chains[iter->prev_chain]=iter->prev->next;
     488             :     }
     489             :     else{
     490           0 :       iter->prev->prev->next=iter->prev->next;
     491             :     }
     492             : 
     493           0 :     if(iter->prev->next){
     494           0 :       iter->prev->next->prev=iter->prev->prev;
     495             :     }
     496             : 
     497           0 :     if (iter->prev->destroy)
     498           0 :       iter->prev->destroy(iter->prev->data);
     499             : 
     500           0 :     iter->assoc->num_elements--;
     501           0 :     RFREE(iter->prev->key);
     502           0 :     RFREE(iter->prev);
     503           0 :     return(0);
     504             :   }
     505             : 
     506             : 
     507             : /*This is a hack from AMS. Supposedly, it's pretty good for strings, even
     508             :  though it doesn't take into account all the data*/
     509           0 : int r_assoc_simple_hash_compute(key,len,bits)
     510             :   char *key;
     511             :   int len;
     512             :   int bits;
     513             :   {
     514           0 :     UINT4 h=0;
     515             : 
     516           0 :     h=key[0] +(key[len-1] * len);
     517             : 
     518           0 :     h &= (1<<bits) - 1;
     519             : 
     520           0 :     return(h);
     521             :   }
     522             : 
     523             : 
     524             : int r_crc32(char *data,int len,UINT4 *crcval);
     525             : 
     526           0 : int r_assoc_crc32_hash_compute(data,len,bits)
     527             :   char *data;
     528             :   int len;
     529             :   int bits;
     530             :   {
     531             :     UINT4 res;
     532             :     UINT4 mask;
     533             : 
     534             :     /* First compute the CRC value */
     535           0 :     if(r_crc32(data,len,&res))
     536           0 :       ERETURN(R_INTERNAL);
     537             : 
     538           0 :     mask=~(0xffffffff<<bits);
     539             : 
     540           0 :     return(res & mask);
     541             :   }

Generated by: LCOV version 1.13