3 osrfHash* osrfNewHash() {
4 osrfHash* hash = safe_malloc(sizeof(osrfHash));
5 hash->hash = osrfNewList();
12 /* algorithm proposed by Donald E. Knuth
13 * in The Art Of Computer Programming Volume 3 (more or less..)*/
14 static unsigned int osrfHashMakeKey(char* str) {
16 unsigned int len = strlen(str);
19 for(i = 0; i < len; str++, i++)
20 h = ((h << 5) ^ (h >> 27)) ^ (*str);
25 /* returns the index of the item and points l to the sublist the item
26 * lives in if the item and points n to the hashnode the item
27 * lives in if the item is found. Otherwise -1 is returned */
28 static unsigned int osrfHashFindItem( osrfHash* hash, char* key, osrfList** l, osrfHashNode** n ) {
29 if(!(hash && key)) return -1;
31 int i = osrfHashMakeKey(key);
32 osrfList* list = osrfListGetIndex( hash->hash, i );
33 if( !list ) { return -1; }
37 osrfHashNode* node = NULL;
38 for( k = 0; k < list->size; k++ ) {
39 node = osrfListGetIndex(list, k);
40 if( node && node->key && !strcmp(node->key, key) )
52 osrfHashNode* osrfNewHashNode(char* key, void* item) {
53 if(!(key && item)) return NULL;
54 osrfHashNode* n = safe_malloc(sizeof(osrfHashNode));
60 void osrfHashNodeFree(osrfHashNode* node) {
66 void* osrfHashSet( osrfHash* hash, void* item, const char* key, ... ) {
67 if(!(hash && item && key )) return NULL;
69 VA_LIST_TO_STRING(key);
70 void* olditem = osrfHashRemove( hash, VA_BUF );
71 int bucketkey = osrfHashMakeKey(VA_BUF);
74 if( !(bucket = osrfListGetIndex(hash->hash, bucketkey)) ) {
75 bucket = osrfNewList();
76 osrfListSet( hash->hash, bucket, bucketkey );
79 osrfHashNode* node = osrfNewHashNode(VA_BUF, item);
80 osrfListPushFirst( bucket, node );
86 void* osrfHashRemove( osrfHash* hash, const char* key, ... ) {
87 if(!(hash && key )) return NULL;
89 VA_LIST_TO_STRING(key);
91 osrfList* list = NULL;
93 int index = osrfHashFindItem( hash, (char*) VA_BUF, &list, &node );
94 if( index == -1 ) return NULL;
96 osrfListRemove( list, index );
101 hash->freeItem((char*) VA_BUF, node->item);
102 else item = node->item;
104 osrfHashNodeFree(node);
109 void* osrfHashGet( osrfHash* hash, const char* key, ... ) {
110 if(!(hash && key )) return NULL;
111 VA_LIST_TO_STRING(key);
113 osrfHashNode* node = NULL;
114 int index = osrfHashFindItem( hash, (char*) VA_BUF, NULL, &node );
115 if( index == -1 ) return NULL;
120 osrfStringArray* osrfHashKeys( osrfHash* hash ) {
121 if(!hash) return NULL;
126 osrfStringArray* strings = osrfNewStringArray(8);
128 for( i = 0; i != hash->hash->size; i++ ) {
129 list = osrfListGetIndex( hash->hash, i );
131 for( k = 0; k != list->size; k++ ) {
132 node = osrfListGetIndex( list, k );
133 if( node ) osrfStringArrayAdd( strings, node->key );
142 unsigned long osrfHashGetCount( osrfHash* hash ) {
147 void osrfHashFree( osrfHash* hash ) {
154 for( i = 0; i != hash->hash->size; i++ ) {
155 if( ( list = osrfListGetIndex( hash->hash, i )) ) {
156 for( j = 0; j != list->size; j++ ) {
157 if( (node = osrfListGetIndex( list, j )) ) {
159 hash->freeItem( node->key, node->item );
160 osrfHashNodeFree(node);
167 osrfListFree(hash->hash);
173 osrfHashIterator* osrfNewHashIterator( osrfHash* hash ) {
174 if(!hash) return NULL;
175 osrfHashIterator* itr = safe_malloc(sizeof(osrfHashIterator));
178 itr->keys = osrfHashKeys(hash);
182 void* osrfHashIteratorNext( osrfHashIterator* itr ) {
183 if(!(itr && itr->hash)) return NULL;
184 if( itr->currentIdx >= itr->keys->size ) return NULL;
186 itr->current = strdup(
187 osrfStringArrayGetString(itr->keys, itr->currentIdx++));
188 char* val = osrfHashGet( itr->hash, itr->current );
192 void osrfHashIteratorFree( osrfHashIterator* itr ) {
195 osrfStringArrayFree(itr->keys);
199 void osrfHashIteratorReset( osrfHashIterator* itr ) {
202 osrfStringArrayFree(itr->keys);
203 itr->keys = osrfHashKeys(itr->hash);