include/it/hlist.h

Go to the documentation of this file.
00001 /*
00002    libit - Library for basic source and channel coding functions
00003    Copyright (C) 2005-2008 Francois Cayre, Vivien Chappelier, Herve Jegou
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public
00016    License along with this library; if not, write to the Free
00017    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 */
00019 
00020 /*
00021   Changelog: 5/17/07 - 1st version by FC / uses public domain 
00022                        hashlittle2() hash function from Bob Jenkins. 
00023            Lists are doubly-linked circular lists with 
00024            sentinel. 
00025            Objects are copied into the list with proper 
00026            memory allocation. In case an object contains 
00027            a pointer, it gets copied -- BEWARE!
00028            Hash lookup tables use open addressing with 
00029            list collision handling. 
00030  */
00031 
00032 /*
00033   Lists and hash lookup tables
00034   Copyright (C) 2007-2008 Francois Cayre
00035 */
00036 
00037 
00038 #ifndef __it_hlist_h
00039 #define __it_hlist_h 
00040 
00041 #ifndef __it_hlist_h_
00042 #define __it_hlist_h_ 
00043 
00044 #include <stdio.h>
00045 #include <stdlib.h>
00046 #include <string.h>
00047 #include <assert.h>
00048 #include <stdint.h>     /* defines uint32_t etc */
00049 #include <sys/param.h>  /* attempt to define endianness */
00050 #ifdef linux
00051 # include <endian.h>    /* attempt to define endianness */
00052 #endif
00053 
00054 
00055 #define __HLIST_MAXLEN 12      /* max length of list name and various strings */
00056 #define __HLIST_OUTPUT stderr  /* output for debug information when needed    */
00057 
00058   /* Basic structure for lists cells */
00059 typedef struct cell_t 
00060 {
00061   struct cell_t * prev, * next; /* *doubly*-linked circular lists */
00062   void * content;               /* address of content in the cell */
00063   unsigned short csz;           /* byte size of cell content      */
00064 } *cell, *list; 
00065 
00066   /* A list enjoys a header which contains various meta-data */
00067 typedef struct list_header_t 
00068 {
00069   char * lname;                 /* a list can have a name         */
00070   FILE * out;                   /* where to print list info       */
00071   unsigned int count;           /* number of cells in the list    */
00072 } list_header; 
00073 
00074   /* List head */
00075 typedef struct head_t 
00076 {
00077   list_header h;                /* the header is hidden in memory */
00078   struct cell_t data;           /* will contain sentinel cell     */
00079 } * head; 
00080 
00081 typedef list fifo;              /* we provide fifo/lifo at no     */
00082 typedef list lifo;              /* extra cost                     */
00083 
00084 
00085 /* Set object field to value */
00086 #define __object_set_field( o, field, value ) do {      \
00087     memcpy( &((o).field), &(value), sizeof(value);      \
00088   } while ( 0 ) 
00089 
00090 /* Copy object field into value */
00091 #define __object_get_field( o, field, value ) do {  \
00092     memcpy( &(value), &((o).field), sizeof(value);  \
00093   } while ( 0 )
00094 
00095 /* Retrieve list header address and type */
00096 #define __get_header(l) ((head)( (char *)(l)-sizeof( list_header )))
00097 
00098 /* Retrieve value of 'idx' field in structure 'target' of type 'object' */
00099 /* Return -1 if target==NULL */
00100 #define __idx_value(target,object,idx)          \
00101   (&(target)?*((int*)(((char*)(target))+((unsigned int)((char*)&(object).idx-(char*)&(object))))):-1)
00102 
00103 /* Allocation of a new cell */
00104 #define __new_cell( c ) do {      \
00105     (c) = malloc( sizeof( *(c) ) );   \
00106     (c)->content = NULL;      \
00107     (c)->prev = (c);        \
00108     (c)->next = (c);        \
00109   } while ( 0 ) 
00110 
00111 /* Print a cell */
00112 #define __cell_print( c, out ) do {           \
00113     fprintf( (out), "cell @ %p: prev @ %p, next @ %p (content @ %p, %d bytes)\n", (void*)(c), (void*)(c)->prev, (void*)(c)->next, (void*)(c)->content, (c)->csz ); \
00114   } while ( 0 )
00115 
00116 /* Main list memory allocation */
00117 /* At the end of the macro, 'l' points to the 'data' field of the newly allocated list head */
00118 #define __list_init_prealloc( l ) do {          \
00119     head hl = malloc( sizeof( *hl ) );          \
00120     hl->h.count = 0;              \
00121     hl->h.lname = NULL;             \
00122     hl->h.out = __HLIST_OUTPUT;           \
00123     (l) = (list)&(hl->data);            \
00124     (l)->content = NULL;            \
00125     (l)->prev = l;              \
00126     (l)->next = l;              \
00127   } while ( 0 )
00128 
00129 /* For short */ 
00130 #define __list_init( l ) __list_init_prealloc( l ) 
00131 
00132 /* Returns number of elements in the list */
00133 #define __list_get_count( l, cnt ) do {       \
00134     head hl = __get_header(l);          \
00135     assert( sizeof( (cnt) ) == sizeof( hl->h.count ) );   \
00136     memcpy( &(cnt), &(hl->h.count), sizeof( (cnt) ) );    \
00137   } while ( 0 ) 
00138 
00139 /* Decrement number of list elements */
00140 #define __list_decr_count( l ) do {     \
00141     head hl = __get_header(l);        \
00142     hl->h.count--;          \
00143   } while ( 0 )           \
00144 
00145 /* Set number of list elements */
00146 #define __list_set_count( l, n ) do {   \
00147       head hl = __get_header(l);    \
00148       hl->h.count = n;        \
00149   } while ( 0 ) 
00150 
00151 /* Increment numberof list elements */
00152 #define __list_incr_count( l ) do {     \
00153     head hl = __get_header(l);        \
00154     hl->h.count++;          \
00155   } while ( 0 )           \
00156 
00157 /* Set file descriptor for list output (use fopen!) */
00158 #define __list_set_output( l, file ) do {   \
00159     head hl = __get_header(l);        \
00160     fprintf( stderr, "Warning: Changing output!\n" ); \
00161     hl->h.out = (file);         \
00162   } while( 0 )
00163 
00164 /* Set list name */
00165 #define __list_set_name( l, newname ) do {        \
00166     unsigned int i, len;            \
00167     head hl = __get_header(l);            \
00168     len = strlen(newname)+1<__HLIST_MAXLEN?strlen(newname):__HLIST_MAXLEN; \
00169     if ( hl->h.lname )              \
00170       {                 \
00171   fprintf( stderr, "Warning: Changing name!\n" );     \
00172   free( hl->h.lname );            \
00173       }                 \
00174     hl->h.lname = malloc( (1+strlen(newname))*sizeof(char) );   \
00175     for ( i= 0; i< len; i++ ) hl->h.lname[i] = newname[i];    \
00176     hl->h.lname[i] = '\0';            \
00177   } while ( 0 )               \
00178 
00179 /* Print list header */
00180 #define __list_print_header( l ) do {         \
00181     head hl = __get_header(l);            \
00182     if ( hl->h.lname )              \
00183       fprintf( hl->h.out, "List %s @ %p ", hl->h.lname, (void*)(l) ); \
00184     else                \
00185       fprintf( hl->h.out, "List @ %p ", (void*)l );     \
00186     if ( hl->h.count==1 || hl->h.count==0)        \
00187       fprintf( hl->h.out, "(%d item)\n", hl->h.count );     \
00188     else                \
00189       fprintf( hl->h.out, "(%d items)\n", hl->h.count );    \
00190   } while ( 0 )               \
00191 
00192 /* Check whether list is empty */
00193 /* At the end, 'empty' contains 0 if 'l' is empty, else 1 */
00194 #define __list_is_empty( l, empty ) do {  \
00195     __list_get_count( l, empty );   \
00196     empty = !empty;       \
00197   } while ( 0 ) 
00198 
00199 /* Add 'object' in first position in 'l' */
00200 #define __list_add_first( l, object ) do {        \
00201     cell c;               \
00202     __new_cell( c );              \
00203     c->next = (l)->next;            \
00204     c->prev = (l);              \
00205     (l)->next->prev = c;            \
00206     (l)->next = c;              \
00207     c->content = malloc( sizeof( object ) );        \
00208     c->csz = sizeof(object);            \
00209     memcpy( (c->content), &(object), sizeof( object) );     \
00210     __list_incr_count( l );           \
00211   } while(0)
00212 
00213 /* Add 'object' in last position in 'l' */
00214 #define __list_add_last( l, object ) do {     \
00215     cell c;             \
00216     __new_cell( c );            \
00217     c->prev = (l)->prev;          \
00218     c->next = (l);            \
00219     (l)->prev->next = c;          \
00220     (l)->prev = c;            \
00221     c->content = malloc( sizeof( object ) );      \
00222     c->csz = sizeof(object);          \
00223     memcpy( c->content, &(object), sizeof( object) );   \
00224     __list_incr_count( l );         \
00225 } while(0)
00226 
00227 /* Add 'object' in 'l' based on increasing values of 'index' */
00228 #define __list_add_by_index( l, object, index ) do {      \
00229     cell c;               \
00230     cell i = (l)->next;             \
00231     while( i->content && (object).index > __idx_value( i->content, object, index ) ) \
00232       i = i->next;              \
00233     i = i->prev;              \
00234     __new_cell( c );              \
00235     c->next = (i)->next;            \
00236     c->prev = (i);              \
00237     (i)->next->prev = c;            \
00238     (i)->next = c;              \
00239     c->content = malloc( sizeof( object ) );        \
00240     c->csz = sizeof(object);          \
00241     memcpy( c->content, &(object), sizeof( object) );     \
00242     __list_incr_count( l );           \
00243   } while ( 0 )
00244 
00245 /* Add 'object' in 'l' based on decreasing values of 'index' */
00246 #define __list_add_by_index_reverse( l, object, index ) do {    \
00247     cell c;               \
00248     cell i = (l)->next;             \
00249     while( i->content && (object).index < __idx_value( i->content, object, index ) ) \
00250       i = i->next;              \
00251     i = i->prev;              \
00252     __new_cell( c );              \
00253     c->next = (i)->next;            \
00254     c->prev = (i);              \
00255     (i)->next->prev = c;            \
00256     (i)->next = c;              \
00257     c->content = malloc( sizeof( object ) );        \
00258     c->csz = sizeof(object);          \
00259     memcpy( c->content, &(object), sizeof( object) );     \
00260     __list_incr_count( l );           \
00261   } while ( 0 )
00262 
00263 /* Delete first 'object' from 'l' based on matching value of 'index' */
00264 #define __list_del_first_by_index( l, object, idx ) do {    \
00265     cell c;               \
00266     cell i = (l)->next;             \
00267     while( i->content && (object).idx != __idx_value( i->content, object, idx ) ) \
00268       i = i->next;              \
00269     if ( &(object) )              \
00270       memcpy( &(object), (i)->next->content, sizeof( (object) ) );  \
00271     if ( (i)->next->content ) {           \
00272       free( (i)->next->content );         \
00273       c = (i)->next;              \
00274       (i)->next->next->prev = (i);          \
00275       (i)->next = (i)->next->next;          \
00276       free( c );              \
00277       __list_decr_count( l );           \
00278     }                 \
00279   } while ( 0 ) 
00280 
00281 /* Delete all 'object' from 'l' based on matching value of 'index' */
00282 #define __list_del_all_by_index( l, object, idx ) do {      \
00283     cell i = (l)->next, c;            \
00284     while( i->content ) {           \
00285       if ( (object).idx==__idx_value(i->content,object,idx) ) {   \
00286   if ( &(object) )            \
00287     memcpy( &(object), i->content, sizeof( (object) ) );    \
00288   free( i->content );           \
00289   c = i;                \
00290   i->next->prev = i->prev;          \
00291   i->prev->next = i->next;          \
00292   free( c );              \
00293   __list_decr_count( l );           \
00294       }                 \
00295       i = i->next;              \
00296     }                 \
00297   } while ( 0 )
00298 
00299 /* Walking through a list forward */
00300 #define __list_foreach_forward( l, i )        \
00301   for( (i)=(l)->next; (i)->content; (i) = (i)->next ) 
00302 
00303 /* Walking through a list backward */
00304 #define __list_foreach_reverse( l, i )        \
00305   for( (i)=(l)->prev; (i)->content; (i) = (i)->prev ) 
00306 
00307 /* Walking through a list: default is forward */
00308 #define __list_foreach( l, i ) __list_foreach_forward( l, i )
00309 
00310 /* Print a list */
00311 #define _save_list_print( l ) do {          \
00312     cell c;               \
00313     head hl = __get_header(l);            \
00314     unsigned int sz = sizeof(*hl)+(hl->h.lname)?1+strlen(hl->h.lname):0; \
00315     unsigned int csz = 0;           \
00316     __list_print_header( l );           \
00317     __list_foreach( l, c ) {            \
00318       __cell_print( c, hl->h.out );         \
00319       csz+= c->csz;             \
00320       sz+= sizeof(*c);              \
00321       }                 \
00322   } while ( 0 )             
00323 
00324 #define __list_print( l ) do {          \
00325     cell c;               \
00326     head hl = __get_header(l);            \
00327     unsigned int tsz = sizeof(*hl)+(hl->h.lname)?1+strlen(hl->h.lname):0; \
00328     unsigned int csz = 0;           \
00329     __list_print_header( l );           \
00330     __list_foreach( l, c ) {            \
00331       __cell_print( c, hl->h.out );         \
00332       csz+= c->csz;             \
00333       tsz+= sizeof(*c);             \
00334       }                 \
00335     fprintf( hl->h.out, "Content total: %d bytes\n", csz );   \
00336   } while ( 0 )             
00337 
00338 /* Delete first object in list 'l' */
00339 #define __list_del_first( l, object ) do {        \
00340     cell c;               \
00341     if ( &(object) && (l)->next->content )        \
00342       memcpy( &(object), (l)->next->content, sizeof( (object) ) );  \
00343     if ( (l)->next->content ) {           \
00344       free( (l)->next->content );         \
00345       c = (l)->next;              \
00346       (l)->next->next->prev = (l);          \
00347       (l)->next = (l)->next->next;          \
00348       free( c );              \
00349       __list_decr_count( l );           \
00350     }                 \
00351   } while ( 0 ) 
00352 
00353 /* Delete last object in list 'l' */
00354 #define __list_del_last( l, object ) do {       \
00355     cell c;               \
00356     if ( &(object) )              \
00357       memcpy( &(object), (l)->prev->content, sizeof( (object) ) );  \
00358     if ( (l)->prev->content ) {           \
00359       free( (l)->prev->content );         \
00360       c = (l)->prev;              \
00361       (l)->prev->prev->next = (l);          \
00362       (l)->prev = (l)->prev->prev;          \
00363       free( c );              \
00364       __list_decr_count( l );           \
00365     }                 \
00366   } while ( 0 ) 
00367 
00368 /* Delete first occurence of 'object' in 'l' */
00369 #define __list_del_first_object( l, object ) do {     \
00370     cell i = (l)->next;             \
00371     while ( i->content && memcmp( i->content, &(object), sizeof(object) ) ) \
00372       i = i->next;              \
00373     i = i->prev;              \
00374     if ( (i)->next->content ) {           \
00375       cell c;               \
00376       free( (i)->next->content );         \
00377       c = (i)->next;              \
00378       (i)->next->next->prev = (i);          \
00379       (i)->next = (i)->next->next;          \
00380       free( c );              \
00381       __list_decr_count( l );           \
00382     }                 \
00383   } while ( 0 )
00384 
00385 /* Delete all occurences of 'object' in 'l' */
00386 #define __list_del_all_object( l, object ) do {       \
00387     cell i = (l)->next;             \
00388     while ( i->content ) {            \
00389       if ( !memcmp( i->content, &(object), sizeof(object) ) ) {   \
00390   cell c;               \
00391   i = i->prev;              \
00392   free( (i)->next->content );         \
00393   c = i->next;              \
00394   (i)->next->next->prev = i;          \
00395   (i)->next = (i)->next->next;          \
00396   free( c );              \
00397   __list_decr_count( l );           \
00398       }                 \
00399     i = i->next;              \
00400     }                 \
00401   } while ( 0 )
00402 
00403 /* Check whether 'object' belongs to 'l' */
00404 /* At the end, 'found' contains -1 if 'object' is not found in 'l' */
00405 /* Otherwise, it contains the index of the object in the list      */
00406 #define __list_contains( l, object, found ) do {      \
00407     cell i = (l)->next;             \
00408     int f = -1;               \
00409     memcpy( &(found), &f, sizeof(f) );          \
00410     while ( i->content ) {            \
00411       f++;                \
00412       if ( !memcmp( i->content, &(object), sizeof(object) ) ) {   \
00413   memcpy( &(found), &f, sizeof(f) );        \
00414   break;                \
00415       }                 \
00416       i = i->next;              \
00417     }                 \
00418   } while ( 0 )
00419 
00420 /* Free memory allocated to the list */
00421 #define __list_delete( l ) do {           \
00422     unsigned int cnt;             \
00423     cell c;               \
00424     head hl = (head)( (char *)l-sizeof( (hl->h)) );     \
00425     __list_get_count( l, cnt );           \
00426     while( cnt ) {              \
00427       free( (l)->next->content );         \
00428       c = (l)->next;              \
00429       (l)->next->next->prev = (l);          \
00430       (l)->next = (l)->next->next;          \
00431       free( c );              \
00432       __list_decr_count( l );           \
00433       __list_get_count( l, cnt );         \
00434     }                 \
00435     if ( hl->h.lname ) {            \
00436       free( hl->h.lname );            \
00437       hl->h.lname = NULL;           \
00438     }                 \
00439     free( hl );               \
00440   } while( 0 ) 
00441 
00442 /* Apply function 'function' to all objects in 'l' */
00443 #define __list_apply_function( l, function ) do { \
00444     cell c;           \
00445     __list_foreach_forward( l, c ) {      \
00446       function( (c)->content );       \
00447     }             \
00448   } while ( 0 )
00449 
00450 /* Compare whether two lists are equal */
00451 /* At the end, 'comp' == 0 is the lists are equal, otherwise        */
00452 /* 'comp' == 1 if lists have equal number of- but different objects */
00453 /* or if list 'l2' has fewer elements than 'l1'                     */
00454 /* 'comp' == -1 else */
00455 #define __list_compare(l1,l2,comp) do {   \
00456     unsigned int s1, s2;      \
00457     __list_get_count( l1, s1 );     \
00458     __list_get_count( l2, s2 );     \
00459     if ( s1 < s2 ) {        \
00460       s1 = -1;          \
00461       memcpy( &(comp), &s1, sizeof(comp) ); \
00462     }           \
00463     if ( s1 > s2 ) {        \
00464       s2 = 1;         \
00465       memcpy( &(comp), &s2, sizeof(comp) ); \
00466     }           \
00467     if ( s1==s2 ) {       \
00468       unsigned int t = 0;     \
00469       cell c1 = (l1)->next, c2 = (l2)->next;  \
00470       while ( (c1)->content ) {           \
00471   if ( (c1)->csz == (c2)->csz && !memcmp((c1)->content,(c2)->content, (c1)->csz)) { \
00472     c1 = c1->next;            \
00473     c2 = c2->next;            \
00474   }               \
00475   else {                \
00476     t = 1;              \
00477     break;              \
00478   }               \
00479       }                 \
00480       memcpy( &(comp), &t, sizeof(t) );         \
00481     }                 \
00482   } while ( 0 )
00483 
00484 /* Append list 'l2' at the end of list 'l1' */
00485 #define __list_append( l1, l2 ) do {    \
00486     head hl1 = __get_header(l1);    \
00487     head hl2 = __get_header(l2);    \
00488     l1->prev->next = l2->next;      \
00489     l2->next->prev = l1->prev;      \
00490     l2->prev->next = l1;      \
00491     hl1->h.count += hl1->h.count;   \
00492     l2 = &(hl2->data);        \
00493     if ( hl2->h.lname ) free( hl2->h.lname ); \
00494     free( hl2 );        \
00495   } while ( 0 ) 
00496 
00497 /* Proceed to fusion of lists 'l1' & 'l2'. Resulting list contains */ 
00498 /* unique occurences of each element                               */
00499 #define __list_fusion( l1, l2 ) do {          \
00500     cell cc;                \
00501     __list_foreach( l2, cc ) {            \
00502       unsigned int prst = 0;            \
00503       cell c;               \
00504       __list_foreach( l1, c ) {           \
00505   if ( !memcmp( cc->content, c->content, sizeof(c->csz) ) ) \
00506     prst = 1;             \
00507       }                 \
00508       if ( !prst ) {              \
00509   cell t;               \
00510   __new_cell( t );            \
00511   t->content = malloc( cc->csz );         \
00512   t->csz = cc->csz;           \
00513   t->prev = (l1)->prev;           \
00514   t->next = (l1);             \
00515   (l1)->prev->next = t;           \
00516   (l1)->prev = t;             \
00517   memcpy( t->content, cc->content, cc->csz );     \
00518   __list_incr_count(l1);            \
00519       }                 \
00520     }                 \
00521   } while ( 0 )
00522 
00523 /* Create list 'l1' and copy 'l2' into it */
00524 #define __list_copy( l1, l2 ) do {          \
00525       cell i;               \
00526       head hl2 = __get_header( l2 );          \
00527       __list_init( l1 );            \
00528       __list_foreach( l2, i ) {           \
00529   cell c;               \
00530   __new_cell( c );            \
00531   c->prev = (l1)->prev;           \
00532   c->next = (l1);             \
00533   (l1)->prev->next = c;           \
00534   (l1)->prev = c;             \
00535   c->content = malloc( i->csz );          \
00536   c->csz = i->csz;            \
00537   memcpy( c->content, i->content, c->csz );     \
00538       }                 \
00539       __list_set_count( l1, hl2->h.count );       \
00540       if ( hl2->h.lname ) __list_set_name( l1, hl2->h.lname );    \
00541   } while ( 0 )
00542 
00543 /* Uniquely insert 'object' into 'l' */
00544 #define __list_insert_once( l,object ) do {       \
00545     unsigned int prst = 0;            \
00546     cell c;               \
00547     __list_foreach( l, c ) {            \
00548       if ( !memcmp( &(object), c->content, sizeof(object) ) && sizeof(object)==c->csz ) \
00549   prst = 1;             \
00550     }                 \
00551     if ( !prst ) __list_add_first( l, object );       \
00552   } while ( 0 )
00553 
00554 /* Delete redundant occurences of objects in 'l' */
00555 #define __list_only_once( l ) do {          \
00556     list r;               \
00557     cell c;               \
00558     unsigned int cnt;             \
00559     __list_get_count( l, cnt );           \
00560     if ( cnt < 2 ) break;           \
00561     __list_init( r );             \
00562     __new_cell( c );              \
00563     c->next = r->next;              \
00564     c->prev = r;              \
00565     r->next->prev = c;              \
00566     r->next = c;              \
00567     c->content = malloc( l->next->csz );        \
00568     c->csz = l->next->csz;            \
00569     memcpy( c->content, l->next->content, l->next->csz );   \
00570     __list_incr_count( r );           \
00571     __list_foreach( l, c ) {            \
00572       cell tt;                \
00573       unsigned int prsnt = 0;           \
00574       __list_foreach( r, tt ) {           \
00575   if ( !memcmp( tt->content, c->content, c->csz ) && tt->csz==c->csz ) \
00576     prsnt = 1;              \
00577       }                 \
00578       if ( !prsnt ) {             \
00579   cell t;               \
00580   __new_cell( t );            \
00581   t->next = r->next;            \
00582   t->prev = r;              \
00583   r->next->prev = t;            \
00584   r->next = t;              \
00585   t->content = malloc( c->csz );          \
00586   t->csz = c->csz;            \
00587   memcpy( t->content, c->content, c->csz );     \
00588   __list_incr_count( r );           \
00589       }                 \
00590     }                       \
00591     __list_delete( l );             \
00592     l = r;                \
00593   } while ( 0 )
00594 
00595 /* At the end, 'l1' contains 'l1'-'l2' */
00596 #define __list_minus(l1,l2) do {          \
00597     cell c;               \
00598     list cl1, cl2;              \
00599     list r;               \
00600     __list_init( r );             \
00601     __list_copy( cl1, l1 );           \
00602     __list_copy( cl2, l2 );           \
00603     __list_only_once( cl1 );            \
00604     __list_only_once( cl2 );            \
00605     __list_foreach(cl2,c) {           \
00606       cell cc;                \
00607       __list_foreach( cl1,cc ) {          \
00608   if ( !memcmp(c->content, cc->content, c->csz) && c->csz==cc->csz ) { \
00609     cell t;             \
00610     __new_cell( t );            \
00611     t->next = r->next;            \
00612     t->prev = r;              \
00613     r->next->prev = t;            \
00614     r->next = t;              \
00615     t->content = malloc( c->csz );        \
00616     t->csz = c->csz;            \
00617     memcpy( t->content, c->content, c->csz );     \
00618     __list_incr_count( r );         \
00619   }               \
00620       }                 \
00621     }                 \
00622     __list_delete( l1 );            \
00623     __list_delete( cl2 );           \
00624     __list_delete( cl1 );           \
00625     l1 = r;               \
00626   } while ( 0 )
00627     
00628 /**************************************************************************************/
00629 
00630 /* List interface */
00631 
00632 #define list_init(l) __list_init(l)
00633 #define list_set_name(l,name) __list_set_name(l,name)
00634 #define list_get_count(l,cnt) __list_get_count(l, cnt)
00635 #define list_set_count(l,cnt) __list_set_count(l, cnt)
00636 #define list_set_output(l,file) __list_set_output(l,file)
00637 #define list_is_empty(l,empty) __list_is_empty(l,empty)
00638 #define list_add_first(l,object) __list_add_first(l,object)
00639 #define list_add_last(l,object) __list_add_last(l,object)
00640 #define list_add_by_index(l,object,index) __list_add_by_index(l,object,index)
00641 #define list_add_by_index_reverse(l,object,index) __list_add_by_index_reverse(l,object,index)
00642 #define list_del_first_by_index(l,object,index) __list_del_first_by_index(l,object,index)
00643 #define list_del_all_by_index(l,object,index) __list_del_all_by_index(l,object,index)
00644 #define list_foreach(l,i) __list_foreach(l,i)
00645 #define list_foreach_reverse(l,i) __list_foreach_reverse(l,i)
00646 #define list_print(l) __list_print(l)
00647 #define list_del_first(l,object) __list_del_first(l,object)
00648 #define list_del_last(l,object) __list_del_last(l,object)
00649 #define list_delete(l) __list_delete(l)
00650 #define list_apply_function(l,function) __list_apply_function(l,function)
00651 #define list_compare(l1,l2,comp) __list_compare(l1,l2,comp)
00652 #define list_del_first_object(l,object) __list_del_first_object(l,object)
00653 #define list_del_all_object(l,object) __list_del_all_object(l,object)
00654 #define list_contains(l,object,found) __list_contains(l,object,found)
00655 #define list_append(l1,l2) __list_append(l1,l2)
00656 #define list_fusion(l1,l2) __list_fusion(l1,l2)
00657 #define list_copy(l1,l2) __list_copy(l1,l2)
00658 #define list_insert_once(l,object) __list_insert_once(l,object)
00659 #define list_only_once(l) __list_only_once(l)
00660 
00661 #define fifo_init(f) __list_init(f)
00662 #define fifo_push(f,object) __list_add_first(f,object)
00663 #define fifo_pop(f,object) __list_del_last(f,object)
00664 #define fifo_delete(f) __list_delete(f)
00665 
00666 #define lifo_init(l) __list_init(l)
00667 #define lifo_push(l,object) __list_add_first(l,object)
00668 #define lifo_pop(l,object) __list_del_first(l,object)
00669 #define lifo_delete(l) __list_delete(l) 
00670 
00671 /**************************************************************************************/
00672 
00673 /* A hash lookup table (HLT) enjoys a header */
00674 typedef struct hash_header_t {
00675   char * hname;                /* A HLT can have a name                    */
00676   FILE * out;                  /* Where to print info from the HLT         */
00677   unsigned int count;          /* Log2 of the number of buckets of the HLT */
00678 } hash_header; 
00679 
00680 /* A HLT is basically a header and a list array */
00681 typedef struct hash_t {
00682   hash_header h; 
00683   list * data; 
00684 } * hash; 
00685 
00686 /*
00687   // Begin Bob Jenkins code for hashlittle2() hash function
00688  */
00689 
00690 /* My best guess at if you are big-endian or little-endian.  
00691  * This may need adjustment.
00692  */
00693 #if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
00694      __BYTE_ORDER == __LITTLE_ENDIAN) || \
00695     (defined(i386) || defined(__i386__) || defined(__i486__) || \
00696      defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
00697 # define HASH_LITTLE_ENDIAN 1
00698 # define HASH_BIG_ENDIAN 0
00699 #elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
00700        __BYTE_ORDER == __BIG_ENDIAN) || \
00701       (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
00702 # define HASH_LITTLE_ENDIAN 0
00703 # define HASH_BIG_ENDIAN 1
00704 #else
00705 # define HASH_LITTLE_ENDIAN 0
00706 # define HASH_BIG_ENDIAN 0
00707 #endif
00708 
00709 #define bj_hashsize(n) ((uint32_t)1<<(n))
00710 #define bj_hashmask(n) (bj_hashsize(n)-1)
00711 #define bj_rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
00712 
00713 #define bj_mix(a,b,c) do {         \
00714   a -= c;  a ^= bj_rot(c, 4);  c += b; \
00715   b -= a;  b ^= bj_rot(a, 6);  a += c; \
00716   c -= b;  c ^= bj_rot(b, 8);  b += a; \
00717   a -= c;  a ^= bj_rot(c,16);  c += b; \
00718   b -= a;  b ^= bj_rot(a,19);  a += c; \
00719   c -= b;  c ^= bj_rot(b, 4);  b += a; \
00720 } while ( 0 )
00721 
00722 #define bj_final(a,b,c) do {      \
00723   c ^= b; c -= bj_rot(b,14);      \
00724   a ^= c; a -= bj_rot(c,11);      \
00725   b ^= a; b -= bj_rot(a,25);      \
00726   c ^= b; c -= bj_rot(b,16);      \
00727   a ^= c; a -= bj_rot(c,4);     \
00728   b ^= a; b -= bj_rot(a,14);      \
00729   c ^= b; c -= bj_rot(b,24);      \
00730 } while ( 0 ) 
00731 
00732 #define hashlittle2( key, len, pc, pb) do {       \
00733     uint32_t ext=0,a,b,c,length=(len);          \
00734     union { const void *ptr; size_t i; } u;       \
00735     a = b = c = 0xdeadbeef + ((uint32_t)length);      \
00736     u.ptr = (void*)key;             \
00737     if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {     \
00738       const uint32_t *k = (const uint32_t *)(key);      \
00739       while (length > 12)           \
00740   {               \
00741     a += k[0];              \
00742     b += k[1];              \
00743     c += k[2];              \
00744     bj_mix(a,b,c);            \
00745     length -= 12;             \
00746     k += 3;             \
00747   }               \
00748       switch(length)              \
00749   {               \
00750   case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;      \
00751   case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;   \
00752   case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;   \
00753   case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;     \
00754   case 8 : b+=k[1]; a+=k[0]; break;       \
00755   case 7 : b+=k[1]&0xffffff; a+=k[0]; break;      \
00756   case 6 : b+=k[1]&0xffff; a+=k[0]; break;      \
00757   case 5 : b+=k[1]&0xff; a+=k[0]; break;        \
00758   case 4 : a+=k[0]; break;          \
00759   case 3 : a+=k[0]&0xffffff; break;       \
00760   case 2 : a+=k[0]&0xffff; break;         \
00761   case 1 : a+=k[0]&0xff; break;         \
00762   case 0 : memcpy(&(pc),&c,sizeof(c));        \
00763     memcpy(&(pb),&b,sizeof(b));         \
00764     ext = 1;              \
00765   }               \
00766       if ( ext ) break;             \
00767     } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {    \
00768       const uint16_t *k = (const uint16_t *)(key);      \
00769       const uint8_t  *k8;           \
00770       while (length > 12)           \
00771   {               \
00772     a += k[0] + (((uint32_t)k[1])<<16);       \
00773     b += k[2] + (((uint32_t)k[3])<<16);       \
00774     c += k[4] + (((uint32_t)k[5])<<16);       \
00775     bj_mix(a,b,c);            \
00776     length -= 12;             \
00777     k += 6;             \
00778   }               \
00779       k8 = (const uint8_t *)k;            \
00780       switch(length)              \
00781   {               \
00782   case 12: c+=k[4]+(((uint32_t)k[5])<<16);      \
00783     b+=k[2]+(((uint32_t)k[3])<<16);       \
00784     a+=k[0]+(((uint32_t)k[1])<<16);       \
00785     break;              \
00786   case 11: c+=((uint32_t)k8[10])<<16;     /* fall through */  \
00787   case 10: c+=k[4];           \
00788     b+=k[2]+(((uint32_t)k[3])<<16);       \
00789     a+=k[0]+(((uint32_t)k[1])<<16);       \
00790     break;              \
00791   case 9 : c+=k8[8];                      /* fall through */  \
00792   case 8 : b+=k[2]+(((uint32_t)k[3])<<16);      \
00793     a+=k[0]+(((uint32_t)k[1])<<16);       \
00794     break;              \
00795   case 7 : b+=((uint32_t)k8[6])<<16;      /* fall through */  \
00796   case 6 : b+=k[2];           \
00797     a+=k[0]+(((uint32_t)k[1])<<16);       \
00798     break;              \
00799   case 5 : b+=k8[4];                      /* fall through */  \
00800   case 4 : a+=k[0]+(((uint32_t)k[1])<<16);      \
00801     break;              \
00802   case 3 : a+=((uint32_t)k8[2])<<16;      /* fall through */  \
00803   case 2 : a+=k[0];           \
00804     break;              \
00805   case 1 : a+=k8[0];            \
00806     break;              \
00807   case 0 : memcpy(&(pc),&c,sizeof(c));        \
00808     memcpy(&(pb),&b,sizeof(b));         \
00809     ext = 1;              \
00810   }               \
00811       if ( ext ) break;             \
00812     } else {                \
00813       const uint8_t *k = (const uint8_t *)(key);      \
00814       while (length > 12)           \
00815   {               \
00816     a += k[0];              \
00817     a += ((uint32_t)k[1])<<8;         \
00818     a += ((uint32_t)k[2])<<16;          \
00819     a += ((uint32_t)k[3])<<24;          \
00820     b += k[4];              \
00821     b += ((uint32_t)k[5])<<8;         \
00822     b += ((uint32_t)k[6])<<16;          \
00823     b += ((uint32_t)k[7])<<24;          \
00824     c += k[8];              \
00825     c += ((uint32_t)k[9])<<8;         \
00826     c += ((uint32_t)k[10])<<16;         \
00827     c += ((uint32_t)k[11])<<24;         \
00828     bj_mix(a,b,c);            \
00829     length -= 12;             \
00830     k += 12;              \
00831   }               \
00832       switch(length)              \
00833   {               \
00834   case 12: c+=((uint32_t)k[11])<<24;        \
00835   case 11: c+=((uint32_t)k[10])<<16;        \
00836   case 10: c+=((uint32_t)k[9])<<8;        \
00837   case 9 : c+=k[8];           \
00838   case 8 : b+=((uint32_t)k[7])<<24;       \
00839   case 7 : b+=((uint32_t)k[6])<<16;       \
00840   case 6 : b+=((uint32_t)k[5])<<8;        \
00841   case 5 : b+=k[4];           \
00842   case 4 : a+=((uint32_t)k[3])<<24;       \
00843   case 3 : a+=((uint32_t)k[2])<<16;       \
00844   case 2 : a+=((uint32_t)k[1])<<8;        \
00845   case 1 : a+=k[0];           \
00846     break;              \
00847   case 0 : memcpy(&(pc),&c,sizeof(c));        \
00848     memcpy(&(pb),&b,sizeof(b));         \
00849     ext = 1;              \
00850   }               \
00851       if ( ext ) break;             \
00852     }                 \
00853     bj_final(a,b,c);              \
00854     memcpy(&(pc),&c,sizeof(c));           \
00855     memcpy(&(pb),&b,sizeof(b));           \
00856   } while (0)
00857 
00858 /*
00859   // End Bob Jenkins code for hashlittle2() hash function
00860  */
00861 
00862 /* Init HLT with 2^log2buckets buckets */
00863 #define __hash_init( h, log2buckets ) do {        \
00864     unsigned int i;             \
00865     (h) = malloc( sizeof( *(h) ) );         \
00866     (h)->h.count = log2buckets>32?32:log2buckets;     \
00867     (h)->h.out = __HLIST_OUTPUT;          \
00868     (h)->h.hname = NULL;            \
00869     (h)->data = malloc( (1<<(h)->h.count)*sizeof(struct cell_t) );  \
00870     for ( i= 0; i< (1<<(h)->h.count); i++ ) list_init( (h)->data[i] );  \
00871   } while ( 0 )
00872 
00873 /* Set output file descriptor for HLT (use fopen!) */
00874 #define __hash_set_output( l, file ) do {   \
00875     fprintf( stderr, "Warning: Changing output!\n" ); \
00876     (h)->h.out = (file);        \
00877   } while( 0 )
00878 
00879 /* Set HLT name */
00880 #define __hash_set_name( h, newname ) do {        \
00881     unsigned int i, len;            \
00882     len = strlen(newname)+1<__HLIST_MAXLEN?strlen(newname):__HLIST_MAXLEN; \
00883     if ( (h)->h.hname )             \
00884       {                 \
00885   fprintf( stderr, "Warning: Changing name!\n" );     \
00886   free( (h)->h.hname );           \
00887       }                 \
00888     (h)->h.hname = malloc( (1+strlen(newname))*sizeof(char) );    \
00889     for ( i= 0; i< len; i++ ) (h)->h.hname[i] = newname[i];   \
00890     (h)->h.hname[i] = '\0';           \
00891   } while ( 0 )               \
00892 
00893 /* Delete HLT from memory */
00894 #define __hash_delete( h ) do {     \
00895     unsigned int i;       \
00896     for ( i= 0; i< (1<<(h)->h.count); i++ ) \
00897       list_delete( (h)->data[i] );    \
00898     if ( (h)->h.hname ) free( (h)->h.hname ); \
00899     free( h );          \
00900   } while ( 0 ) 
00901 
00902 /* Print HLT (mostly useless if a lot of buckets) */
00903 #define __hash_print( h ) do {            \
00904     unsigned int i;             \
00905     if ( (h)->h.hname )             \
00906       fprintf( (h)->h.out, "Hash %s @ %p ", (h)->h.hname, (void*)(h) ); \
00907     else                \
00908       fprintf( (h)->h.out, "Hash @ %p ", (void*)(h) );      \
00909     fprintf( (h)->h.out, "(%d buckets)\n", (1<<(h)->h.count) );   \
00910     for ( i= 0; i< (1<<(h)->h.count); i++ )       \
00911       list_print( (h)->data[i] );         \
00912   } while ( 0 ) 
00913 
00914 /* Interface function to plug desired hash function */
00915 #define __hash_bytes( data, start, len, h ) do {    \
00916     unsigned int h2;            \
00917     hashlittle2( (((char*)data)+start), len, h, h2 );         \
00918   } while ( 0 )
00919 
00920 /*
00921   In case somebody feels better with Pearson's hash, the code is right here. 
00922  */
00923 /*
00924   #define __hash_bytes_save( data, start, len, h ) do {     \
00925   unsigned int i;             \
00926   unsigned char * p, res;           \
00927   unsigned char T[256] = { 77, 175, 85, 225, 174, 222, 120, 192, 66, 233, 198, 7, 116, 227, 229, 15, 248, 68, 99, 156, 195, 254, 98, 148, 164, 177, 171, 196, 124, 8, 224, 179, 72, 191, 137, 5, 65, 31, 226, 106, 144, 142, 113, 205, 208, 219, 97, 63, 131, 34, 30, 193, 223, 41, 44, 145, 12, 215, 178, 154, 251, 181, 19, 117, 230, 82, 52, 188, 58, 108, 92, 55, 36, 47, 10, 20, 221, 139, 109, 57, 236, 59, 46, 134, 93, 35, 146, 190, 252, 105, 169, 38, 228, 234, 189, 199, 180, 138, 115, 152, 13, 214, 173, 79, 111, 23, 73, 112, 232, 182, 75, 28, 141, 172, 122, 110, 130, 86, 2, 201, 14, 114, 140, 125, 95, 161, 220, 184, 162, 81, 119, 241, 153, 87, 69, 247, 48, 200, 94, 70, 88, 61, 255, 103, 136, 32, 27, 11, 202, 194, 17, 107, 235, 118, 22, 26, 91, 3, 209, 186, 100, 24, 183, 104, 167, 123, 207, 42, 90, 143, 217, 6, 4, 9, 132, 101, 237, 150, 168, 206, 102, 29, 80, 155, 62, 187, 51, 231, 64, 33, 239, 128, 163, 74, 43, 157, 253, 165, 160, 50, 54, 204, 147, 53, 16, 197, 121, 170, 216, 84, 151, 45, 21, 240, 127, 211, 56, 89, 40, 129, 166, 1, 133, 245, 76, 238, 176, 159, 18, 0, 243, 96, 158, 185, 149, 37, 49, 67, 135, 25, 218, 242, 83, 246, 249, 39, 250, 126, 213, 203, 78, 212, 210, 71, 60 }; \
00928   for ( res = 0, i= 0, p = ((unsigned char *)data)+start; i< len; res = T[res^p[i++]] ); \
00929   memcpy( &(h), &res, sizeof(unsigned char) );        \
00930   } while ( 0 )
00931 */
00932 
00933 /* Fit hash function result to required bit number */
00934 #define __hash_fit( h, hash ) do {      \
00935     unsigned int hfit = hash & ( (1<<(h)->h.count)-1 ); \
00936     memcpy( &hash, &hfit, sizeof(hash) );   \
00937   } while ( 0 ) 
00938 
00939 /* Hash entire object */
00940 #define __hash_object( object, hash ) __hash_bytes( &(object), 0, sizeof(object), hash )
00941 
00942 /* Hash objects from 'key' element of 'object' */
00943 #define __hash_from_key( object, key, hash ) __hash_bytes( &((object).key), (((char*)&((object).key))-((char*)&(object))), sizeof((object).key), hash )
00944 
00945 /* Insert object into HLT */
00946 #define __hash_insert_object( h, object ) do {    \
00947     unsigned int hash=0;        \
00948     __hash_object( object, hash );      \
00949     __hash_fit( h, hash );        \
00950     list_add_first( (h)->data[hash], object );    \
00951   } while ( 0 ) 
00952 
00953 /* Remove object from HLT */
00954 #define __hash_remove_object( h, object ) do {    \
00955     unsigned int hash=0;        \
00956     __hash_object( object, hash );      \
00957     __hash_fit( h, hash );        \
00958     list_del_all_object((h)->data[hash],object);  \
00959   } while ( 0 ) 
00960 
00961 /* Check whether object belongs to HLT        */
00962 /* See values for found in the list interface */
00963 /* -1 means 'object' does not belong to HLT   */
00964 #define __hash_lookup_object( h, object, found ) do { \
00965     unsigned int hash=0;        \
00966     __hash_object( object, hash );      \
00967     __hash_fit( h, hash );        \
00968     list_contains((h)->data[hash],object,found);  \
00969   } while ( 0 ) 
00970 
00971 /* Insert object into HLT based on 'key' value */
00972 #define __hash_insert_from_key( h, object, key ) do { \
00973     unsigned int hash=0;        \
00974     __hash_from_key( object, key, hash );   \
00975     __hash_fit( h, hash );        \
00976     list_add_first( (h)->data[hash], object );    \
00977   } while ( 0 ) 
00978 
00979 /* Remove all object occurences from HLT based on 'key' */
00980 #define __hash_remove_from_key( h, object, key ) do { \
00981     unsigned int hash=0;        \
00982     __hash_from_key( object, key, hash );   \
00983     __hash_fit( h, hash );        \
00984     list_del_all_object((h)->data[hash],object);  \
00985   } while ( 0 ) 
00986 
00987 /* Check whether object belongs to HLT base on 'key' */
00988 /* See values for found in the list interface        */
00989 /* -1 means 'object' does not belong to HLT          */
00990 #define __hash_lookup_from_key( h, object, key, found ) do {  \
00991     unsigned int hash=0;          \
00992     __hash_from_key( object, key, hash );     \
00993     __hash_fit( h, hash );          \
00994     list_contains((h)->data[hash],object,found);    \
00995   } while ( 0 ) 
00996 
00997 /* Hash lookup table interface */
00998 
00999 #define hash_init(h, l2b) __hash_init(h, l2b) 
01000 #define hash_set_name(h,name) __hash_set_name(h,name)
01001 #define hash_set_output(h,out) __hash_set_name(h,out)
01002 #define hash_print(h) __hash_print(h) 
01003 #define hash_insert_object(h,object) __hash_insert_object(h,object)
01004 #define hash_remove_object(h,object) __hash_remove_object(h,object)
01005 #define hash_lookup_object(h,object,found) __hash_lookup_object(h,object,found)
01006 #define hash_insert_from_key(h,object,key) __hash_insert_from_key(h,object,key)
01007 #define hash_remove_from_key(h,object,key) __hash_remove_from_key(h,object,key)
01008 #define hash_lookup_from_key(h,object,key,found) __hash_lookup_from_key(h,object,key,found)
01009 #define hash_delete(h) __hash_delete(h)
01010 
01011 #endif /* __it_hlist */

Hosted by
Copyright (C) 2005-2006 Hervé Jégou
Vivien Chappelier
Francois Cayre
libit logo courtesy of Jonathan Delhumeau