libstack/osrf_list.o \
libstack/osrf_big_list.o \
libstack/osrf_hash.o \
+ libstack/osrf_big_hash.o \
utils/socket_bundle.o \
utils/string_array.o \
utils/utils.o \
libstack/osrf_list.h \
libstack/osrf_big_list.h \
libstack/osrf_hash.h \
+ libstack/osrf_big_hash.h \
utils/socket_bundle.h \
utils/string_array.h \
utils/utils.h \
osrf_list.o \
osrf_big_list.o \
osrf_hash.o \
+ osrf_big_hash.o \
xml_utils.o
HEADERS = osrf_message.h \
osrf_list.h \
osrf_big_list.h \
osrf_hash.h \
+ osrf_big_hash.h \
xml_utils.h
all: xml_utils.o $(TARGETS) copy
osrf_list.o: osrf_list.c osrf_list.h
osrf_big_list.o: osrf_big_list.c osrf_big_list.h
osrf_hash.o: osrf_hash.c osrf_hash.h
+osrf_big_hash.o: osrf_big_hash.c osrf_big_hash.h
clean:
--- /dev/null
+#include "osrf_big_hash.h"
+
+osrfBigHash* osrfNewBigHash() {
+ osrfBigHash* hash = safe_malloc(sizeof(osrfBigHash));
+ hash->hash = (Pvoid_t) NULL;
+ hash->freeItem = NULL;
+ return hash;
+}
+
+void* osrfBigHashSet( osrfBigHash* hash, void* item, const char* key, ... ) {
+ if(!(hash && item && key )) return NULL;
+
+ Word_t* value;
+ VA_LIST_TO_STRING(key);
+ uint8_t idx[strlen(VA_BUF) + 1];
+ strcpy( idx, VA_BUF );
+
+ void* olditem = osrfBigHashRemove( hash, VA_BUF );
+
+ JSLI(value, hash->hash, idx);
+ if(value) *value = (Word_t) item;
+ return olditem;
+
+}
+
+void* osrfBigHashRemove( osrfBigHash* hash, const char* key, ... ) {
+ if(!(hash && key )) return NULL;
+
+ VA_LIST_TO_STRING(key);
+
+ Word_t* value;
+ uint8_t idx[strlen(VA_BUF) + 1];
+ strcpy( idx, VA_BUF );
+ void* item = NULL;
+ int retcode;
+
+ JSLG( value, hash->hash, idx);
+
+ if( value ) {
+ item = (void*) *value;
+ if(item) {
+ if( hash->freeItem ) {
+ hash->freeItem( (char*) idx, item );
+ item = NULL;
+ }
+ }
+ }
+
+
+ JSLD( retcode, hash->hash, idx );
+
+ return item;
+}
+
+
+void* osrfBigHashGet( osrfBigHash* hash, const char* key, ... ) {
+ if(!(hash && key )) return NULL;
+
+ VA_LIST_TO_STRING(key);
+
+ Word_t* value;
+ uint8_t idx[strlen(VA_BUF) + 1];
+ strcpy( idx, VA_BUF );
+
+ JSLG( value, hash->hash, idx );
+ if(value) return (void*) *value;
+ return NULL;
+}
+
+
+osrfStringArray* osrfBigHashKeys( osrfBigHash* hash ) {
+ if(!hash) return NULL;
+
+ Word_t* value;
+ uint8_t idx[OSRF_HASH_MAXKEY];
+ strcpy(idx, "");
+ char* key;
+ osrfStringArray* strings = osrfNewStringArray(8);
+
+ JSLF( value, hash->hash, idx );
+
+ while( value ) {
+ key = (char*) idx;
+ osrfStringArrayAdd( strings, key );
+ JSLN( value, hash->hash, idx );
+ }
+
+ return strings;
+}
+
+
+unsigned long osrfBigHashGetCount( osrfBigHash* hash ) {
+ if(!hash) return -1;
+
+ Word_t* value;
+ unsigned long count = 0;
+ uint8_t idx[OSRF_HASH_MAXKEY];
+
+ strcpy( (char*) idx, "");
+ JSLF(value, hash->hash, idx);
+
+ while(value) {
+ count++;
+ JSLN( value, hash->hash, idx );
+ }
+
+ return count;
+}
+
+void osrfBigHashFree( osrfBigHash* hash ) {
+ if(!hash) return;
+
+ int i;
+ osrfStringArray* keys = osrfBigHashKeys( hash );
+
+ for( i = 0; i != keys->size; i++ ) {
+ char* key = (char*) osrfStringArrayGetString( keys, i );
+ osrfBigHashRemove( hash, key );
+ }
+
+ osrfStringArrayFree(keys);
+ free(hash);
+}
+
+
+
+osrfBigHashIterator* osrfNewBigHashIterator( osrfBigHash* hash ) {
+ if(!hash) return NULL;
+ osrfBigHashIterator* itr = safe_malloc(sizeof(osrfBigHashIterator));
+ itr->hash = hash;
+ itr->current = NULL;
+ return itr;
+}
+
+void* osrfBigHashIteratorNext( osrfBigHashIterator* itr ) {
+ if(!(itr && itr->hash)) return NULL;
+
+ Word_t* value;
+ uint8_t idx[OSRF_HASH_MAXKEY];
+
+ if( itr->current == NULL ) { /* get the first item in the list */
+ strcpy(idx, "");
+ JSLF( value, itr->hash->hash, idx );
+
+ } else {
+ strcpy(idx, itr->current);
+ JSLN( value, itr->hash->hash, idx );
+ }
+
+ if(value) {
+ free(itr->current);
+ itr->current = strdup((char*) idx);
+ return (void*) *value;
+ }
+
+ return NULL;
+
+}
+
+void osrfBigHashIteratorFree( osrfBigHashIterator* itr ) {
+ if(!itr) return;
+ free(itr->current);
+ free(itr);
+}
+
+void osrfBigHashIteratorReset( osrfBigHashIterator* itr ) {
+ if(!itr) return;
+ free(itr->current);
+ itr->current = NULL;
+}
+
+
+
--- /dev/null
+#ifndef OSRF_HASH_H
+#define OSRF_HASH_H
+
+#include <Judy.h>
+#include "opensrf/utils.h"
+#include "opensrf/string_array.h"
+
+#define OSRF_HASH_MAXKEY 256
+
+struct __osrfBigHashStruct {
+ Pvoid_t hash; /* the hash */
+ void (*freeItem) (char* key, void* item); /* callback for freeing stored items */
+};
+typedef struct __osrfBigHashStruct osrfBigHash;
+
+
+struct __osrfBigHashIteratorStruct {
+ char* current;
+ osrfBigHash* hash;
+};
+typedef struct __osrfBigHashIteratorStruct osrfBigHashIterator;
+
+/**
+ Allocates a new hash object
+ */
+osrfBigHash* osrfNewBigHash();
+
+/**
+ Sets the given key with the given item
+ if "freeItem" is defined and an item already exists at the given location,
+ then old item is freed and the new item is put into place.
+ if "freeItem" is not defined and an item already exists, the old item
+ is returned.
+ @return The old item if exists and there is no 'freeItem', returns NULL
+ otherwise
+ */
+void* osrfBigHashSet( osrfBigHash* hash, void* item, const char* key, ... );
+
+/**
+ Removes an item from the hash.
+ if 'freeItem' is defined it is used and NULL is returned,
+ else the freed item is returned
+ */
+void* osrfBigHashRemove( osrfBigHash* hash, const char* key, ... );
+
+void* osrfBigHashGet( osrfBigHash* hash, const char* key, ... );
+
+
+/**
+ @return A list of strings representing the keys of the hash.
+ caller is responsible for freeing the returned string array
+ with osrfStringArrayFree();
+ */
+osrfStringArray* osrfBigHashKeys( osrfBigHash* hash );
+
+/**
+ Frees a hash
+ */
+void osrfBigHashFree( osrfBigHash* hash );
+
+/**
+ @return The number of items in the hash
+ */
+unsigned long osrfBigHashGetCount( osrfBigHash* hash );
+
+
+
+
+/**
+ Creates a new list iterator with the given list
+ */
+osrfBigHashIterator* osrfNewBigHashIterator( osrfBigHash* hash );
+
+/**
+ Returns the next non-NULL item in the list, return NULL when
+ the end of the list has been reached
+ */
+void* osrfBigHashIteratorNext( osrfBigHashIterator* itr );
+
+/**
+ Deallocates the given list
+ */
+void osrfBigHashIteratorFree( osrfBigHashIterator* itr );
+
+void osrfBigHashIteratorReset( osrfBigHashIterator* itr );
+
+#endif
osrfHash* osrfNewHash() {
osrfHash* hash = safe_malloc(sizeof(osrfHash));
- hash->hash = (Pvoid_t) NULL;
+ hash->hash = osrfNewList();
hash->freeItem = NULL;
+ hash->size = 0;
return hash;
}
+
+/* algorithm proposed by Donald E. Knuth
+ * in The Art Of Computer Programming Volume 3 (more or less..)*/
+static unsigned int osrfHashMakeKey(char* str) {
+ if(!str) return 0;
+ unsigned int len = strlen(str);
+ unsigned int h = len;
+ unsigned int i = 0;
+ for(i = 0; i < len; str++, i++)
+ h = ((h << 5) ^ (h >> 27)) ^ (*str);
+ return (h & 0x7FF);
+}
+
+
+/* returns the index of the item and points l to the sublist the item
+ * lives in if the item and points n to the hashnode the item
+ * lives in if the item is found. Otherwise -1 is returned */
+static unsigned int osrfHashFindItem( osrfHash* hash, char* key, osrfList** l, osrfHashNode** n ) {
+ if(!(hash && key)) return -1;
+
+ int i = osrfHashMakeKey(key);
+ osrfList* list = osrfListGetIndex( hash->hash, i );
+ if( !list ) { return -1; }
+
+
+ int k;
+ osrfHashNode* node = NULL;
+ for( k = 0; k < list->size; k++ ) {
+ node = osrfListGetIndex(list, k);
+ if( node && node->key && !strcmp(node->key, key) )
+ break;
+ node = NULL;
+ }
+
+ if(!node) return -1;
+
+ if(l) *l = list;
+ if(n) *n = node;
+ return k;
+}
+
+osrfHashNode* osrfNewHashNode(char* key, void* item) {
+ if(!(key && item)) return NULL;
+ osrfHashNode* n = safe_malloc(sizeof(osrfHashNode));
+ n->key = strdup(key);
+ n->item = item;
+ return n;
+}
+
+void osrfHashNodeFree(osrfHashNode* node) {
+ if(!node) return;
+ free(node->key);
+ free(node);
+}
+
void* osrfHashSet( osrfHash* hash, void* item, const char* key, ... ) {
if(!(hash && item && key )) return NULL;
- Word_t* value;
VA_LIST_TO_STRING(key);
- uint8_t idx[strlen(VA_BUF) + 1];
- strcpy( idx, VA_BUF );
-
void* olditem = osrfHashRemove( hash, VA_BUF );
+ int bucketkey = osrfHashMakeKey(VA_BUF);
+
+ osrfList* bucket;
+ if( !(bucket = osrfListGetIndex(hash->hash, bucketkey)) ) {
+ bucket = osrfNewList();
+ osrfListSet( hash->hash, bucket, bucketkey );
+ }
- JSLI(value, hash->hash, idx);
- if(value) *value = (Word_t) item;
+ osrfHashNode* node = osrfNewHashNode(VA_BUF, item);
+ osrfListPushFirst( bucket, node );
+
+ hash->size++;
return olditem;
-
}
void* osrfHashRemove( osrfHash* hash, const char* key, ... ) {
VA_LIST_TO_STRING(key);
- Word_t* value;
- uint8_t idx[strlen(VA_BUF) + 1];
- strcpy( idx, VA_BUF );
- void* item = NULL;
- int retcode;
-
- JSLG( value, hash->hash, idx);
+ osrfList* list = NULL;
+ osrfHashNode* node;
+ int index = osrfHashFindItem( hash, (char*) VA_BUF, &list, &node );
+ if( index == -1 ) return NULL;
- if( value ) {
- item = (void*) *value;
- if(item) {
- if( hash->freeItem ) {
- hash->freeItem( (char*) idx, item );
- item = NULL;
- }
- }
- }
+ osrfListRemove( list, index );
+ hash->size--;
+ void* item = NULL;
+ if(hash->freeItem)
+ hash->freeItem((char*) VA_BUF, node->item);
+ else item = node->item;
- JSLD( retcode, hash->hash, idx );
-
+ osrfHashNodeFree(node);
return item;
}
void* osrfHashGet( osrfHash* hash, const char* key, ... ) {
if(!(hash && key )) return NULL;
-
VA_LIST_TO_STRING(key);
- Word_t* value;
- uint8_t idx[strlen(VA_BUF) + 1];
- strcpy( idx, VA_BUF );
-
- JSLG( value, hash->hash, idx );
- if(value) return (void*) *value;
- return NULL;
+ osrfHashNode* node = NULL;
+ int index = osrfHashFindItem( hash, (char*) VA_BUF, NULL, &node );
+ if( index == -1 ) return NULL;
+ return node->item;
}
osrfStringArray* osrfHashKeys( osrfHash* hash ) {
if(!hash) return NULL;
- Word_t* value;
- uint8_t idx[OSRF_HASH_MAXKEY];
- strcpy(idx, "");
- char* key;
+ int i, k;
+ osrfList* list;
+ osrfHashNode* node;
osrfStringArray* strings = osrfNewStringArray(8);
- JSLF( value, hash->hash, idx );
-
- while( value ) {
- key = (char*) idx;
- osrfStringArrayAdd( strings, key );
- JSLN( value, hash->hash, idx );
+ for( i = 0; i != hash->hash->size; i++ ) {
+ list = osrfListGetIndex( hash->hash, i );
+ if(list) {
+ for( k = 0; k != list->size; k++ ) {
+ node = osrfListGetIndex( list, k );
+ if( node ) osrfStringArrayAdd( strings, node->key );
+ }
+ }
}
return strings;
unsigned long osrfHashGetCount( osrfHash* hash ) {
if(!hash) return -1;
-
- Word_t* value;
- unsigned long count = 0;
- uint8_t idx[OSRF_HASH_MAXKEY];
-
- strcpy( (char*) idx, "");
- JSLF(value, hash->hash, idx);
-
- while(value) {
- count++;
- JSLN( value, hash->hash, idx );
- }
-
- return count;
+ return hash->size;
}
void osrfHashFree( osrfHash* hash ) {
if(!hash) return;
- int i;
- osrfStringArray* keys = osrfHashKeys( hash );
-
- for( i = 0; i != keys->size; i++ ) {
- char* key = (char*) osrfStringArrayGetString( keys, i );
- osrfHashRemove( hash, key );
+ int i, j;
+ osrfList* list;
+ osrfHashNode* node;
+
+ for( i = 0; i != hash->hash->size; i++ ) {
+ if( ( list = osrfListGetIndex( hash->hash, i )) ) {
+ for( j = 0; j != list->size; j++ ) {
+ if( (node = osrfListGetIndex( list, j )) ) {
+ if( hash->freeItem )
+ hash->freeItem( node->key, node->item );
+ osrfHashNodeFree(node);
+ }
+ }
+ osrfListFree(list);
+ }
}
- osrfStringArrayFree(keys);
+ osrfListFree(hash->hash);
free(hash);
}
osrfHashIterator* itr = safe_malloc(sizeof(osrfHashIterator));
itr->hash = hash;
itr->current = NULL;
+ itr->keys = osrfHashKeys(hash);
return itr;
}
void* osrfHashIteratorNext( osrfHashIterator* itr ) {
if(!(itr && itr->hash)) return NULL;
-
- Word_t* value;
- uint8_t idx[OSRF_HASH_MAXKEY];
-
- if( itr->current == NULL ) { /* get the first item in the list */
- strcpy(idx, "");
- JSLF( value, itr->hash->hash, idx );
-
- } else {
- strcpy(idx, itr->current);
- JSLN( value, itr->hash->hash, idx );
- }
-
- if(value) {
- free(itr->current);
- itr->current = strdup((char*) idx);
- return (void*) *value;
- }
-
- return NULL;
-
+ if( itr->currentIdx >= itr->keys->size ) return NULL;
+ free(itr->current);
+ itr->current = strdup(
+ osrfStringArrayGetString(itr->keys, itr->currentIdx++));
+ char* val = osrfHashGet( itr->hash, itr->current );
+ return val;
}
void osrfHashIteratorFree( osrfHashIterator* itr ) {
if(!itr) return;
free(itr->current);
+ osrfStringArrayFree(itr->keys);
free(itr);
}
void osrfHashIteratorReset( osrfHashIterator* itr ) {
if(!itr) return;
free(itr->current);
+ osrfStringArrayFree(itr->keys);
+ itr->keys = osrfHashKeys(itr->hash);
+ itr->currentIdx = 0;
itr->current = NULL;
}
#ifndef OSRF_HASH_H
#define OSRF_HASH_H
-#include <Judy.h>
#include "opensrf/utils.h"
#include "opensrf/string_array.h"
+#include "osrf_list.h"
#define OSRF_HASH_MAXKEY 256
+#define OSRF_HASH_KEY_MASK 0x7FF /* hash keys are a maximun of 2047 in size */
+#define OSRF_HASH_KEY_SIZE 2048 /* size of the container list for the keys */
+
+
struct __osrfHashStruct {
- Pvoid_t hash; /* the hash */
+ osrfList* hash; /* this hash */
void (*freeItem) (char* key, void* item); /* callback for freeing stored items */
+ unsigned int size;
};
typedef struct __osrfHashStruct osrfHash;
+struct _osrfHashNodeStruct {
+ char* key;
+ void* item;
+};
+typedef struct _osrfHashNodeStruct osrfHashNode;
+
struct __osrfHashIteratorStruct {
char* current;
+ int currentIdx;
osrfHash* hash;
+ osrfStringArray* keys;
};
typedef struct __osrfHashIteratorStruct osrfHashIterator;
+osrfHashNode* osrfNewHashNode(char* key, void* item);
+void osrfHashNodeFree(osrfHashNode*);
+
/**
Allocates a new hash object
*/