// Copyright 2009, 2010, 2011, 2012 Christopher Benner // // This file is part of HOMER // // HOMER is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // HOMER is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. #include "Hashtable.h" LinkedListItem::LinkedListItem() { next = NULL; obj = NULL; } LinkedList::LinkedList() { firstItem = NULL; lastItem = NULL; total = 0; } LinkedList::~LinkedList() { while (firstItem != NULL) { LinkedListItem* next = firstItem->next; delete firstItem; firstItem = next; } lastItem = NULL; total = 0; } void LinkedList::add(void* obj) { LinkedListItem* item = new LinkedListItem(); item->obj = obj; if (lastItem == NULL) { firstItem = item; } else { lastItem->next = item; } lastItem = item; total++; } void* LinkedList::get(int index) { LinkedListItem* item = firstItem; for (int i=1;inext; } if (item == NULL) return NULL; return item->obj; } void* LinkedList::remove(int index) { if (firstItem == NULL) return NULL; LinkedListItem* item = firstItem; LinkedListItem* last = NULL; for (int i=1;inext; } if (item == NULL) return NULL; if (last == NULL) {//first item; firstItem = item->next; } if (item->next == NULL) { lastItem = NULL; if (last != NULL) { lastItem = last; last->next = NULL; } } else { if (last != NULL) { last->next = item->next; } } void *obj = item->obj; delete item; total--; return obj; } void** LinkedList::toArray(int &numberOfItems) { if (total == 0) return NULL; void** array = new void*[total]; for (int i=0;iobj; item = item->next; } return array; } Hashlist::Hashlist(void* obj, char* str) { elements = new void*[1]; hashstrs = new char*[1]; lowMemFlag = 0; elements[0] = obj; hashstrs[0] = new char[strlen(str)+1]; strcpy(hashstrs[0], str); length = 1; } Hashlist::Hashlist() { } Intlist::Intlist() { } LongIntlist::LongIntlist() { } Floatlist::Floatlist() { } Doublelist::Doublelist() { } Intlist::Intlist(int I, char* str) { elements = new int[1]; hashstrs = new char*[1]; elements[0] = I; hashstrs[0] = new char[strlen(str)+1]; strcpy(hashstrs[0], str); length = 1; } LongIntlist::LongIntlist(long long int I, char* str) { elements = new long long int[1]; hashstrs = new char*[1]; elements[0] = I; hashstrs[0] = new char[strlen(str)+1]; strcpy(hashstrs[0], str); length = 1; } Floatlist::Floatlist(float I, char* str) { elements = new float[1]; hashstrs = new char*[1]; elements[0] = I; hashstrs[0] = new char[strlen(str)+1]; strcpy(hashstrs[0], str); length = 1; } Doublelist::Doublelist(double I, char* str) { elements = new double[1]; hashstrs = new char*[1]; elements[0] = I; hashstrs[0] = new char[strlen(str)+1]; strcpy(hashstrs[0], str); length = 1; } Hashlist::~Hashlist() { if (hashstrs != NULL) { for (int i=0;ilowMemFlag = a; } } } void* Hashtable::search(char* hashstr) { if (hashstr == NULL) return NULL; unsigned int hashval = hashfunc(hashstr); unsigned int bin = hashval % maxsize; if (hash[bin] == NULL) { return NULL; } else { return hash[bin]->search(hashstr); } } int Inttable::search(char* hashstr) { if (hashstr == NULL) return EMPTY_INT; unsigned int hashval = hashfunc(hashstr); unsigned int bin = hashval % maxsize; if (hash[bin] == NULL) { return EMPTY_INT; } else { return hash[bin]->search(hashstr); } } long long int LongInttable::search(char* hashstr) { if (hashstr == NULL) return EMPTY_INT; unsigned int hashval = hashfunc(hashstr); unsigned int bin = hashval % maxsize; if (hash[bin] == NULL) { return EMPTY_INT; } else { return hash[bin]->search(hashstr); } } float Floattable::search(char* hashstr) { unsigned int hashval = hashfunc(hashstr); unsigned int bin = hashval % maxsize; if (hash[bin] == NULL) { return EMPTY_FLOAT; } else { return hash[bin]->search(hashstr); } } double Doubletable::search(char* hashstr) { unsigned int hashval = hashfunc(hashstr); unsigned int bin = hashval % maxsize; if (hash[bin] == NULL) { return EMPTY_DOUBLE; } else { return hash[bin]->search(hashstr); } } void Hashtable::insert(void* obj, char* hashstr) { unsigned int hashval = hashfunc(hashstr); unsigned int bin = hashval % maxsize; int add = 1; if (hash[bin] == NULL) { hash[bin] = new Hashlist(obj,hashstr); } else { add = hash[bin]->insert(obj,hashstr); } total+=add; } void Inttable::insert(int I, char* hashstr) { unsigned int hashval = hashfunc(hashstr); unsigned int bin = hashval % maxsize; int add = 1; if (hash[bin] == NULL) { hash[bin] = new Intlist(I,hashstr); } else { add = hash[bin]->insert(I,hashstr); } total+=add; } void LongInttable::insert(long long int I, char* hashstr) { unsigned int hashval = hashfunc(hashstr); unsigned int bin = hashval % maxsize; int add = 1; if (hash[bin] == NULL) { hash[bin] = new LongIntlist(I,hashstr); } else { add = hash[bin]->insert(I,hashstr); } total+=add; } void Floattable::insert(float I, char* hashstr) { unsigned int hashval = hashfunc(hashstr); unsigned int bin = hashval % maxsize; int add = 1; if (hash[bin] == NULL) { hash[bin] = new Floatlist(I,hashstr); } else { add = hash[bin]->insert(I,hashstr); } total+=add; } void Doubletable::insert(double I, char* hashstr) { unsigned int hashval = hashfunc(hashstr); unsigned int bin = hashval % maxsize; int add = 1; if (hash[bin] == NULL) { hash[bin] = new Doublelist(I,hashstr); } else { add = hash[bin]->insert(I,hashstr); } total+=add; } void* Hashtable::remove(char* str) { unsigned int hashval = hashfunc(str); unsigned int bin = hashval % maxsize; if (hash[bin] == NULL) { return NULL; } else { void* val = NULL; val = hash[bin]->remove(str); if (val != NULL) total--; return val; } } int Inttable::remove(char* str) { unsigned int hashval = hashfunc(str); unsigned int bin = hashval % maxsize; if (hash[bin] == NULL) { return EMPTY_INT; } else { int val = 0; val = hash[bin]->remove(str); if (val != EMPTY_INT) total--; return val; } } int LongInttable::remove(char* str) { unsigned int hashval = hashfunc(str); unsigned int bin = hashval % maxsize; if (hash[bin] == NULL) { return EMPTY_INT; } else { int val = 0; val = hash[bin]->remove(str); if (val != EMPTY_INT) total--; return val; } } float Floattable::remove(char* str) { unsigned int hashval = hashfunc(str); unsigned int bin = hashval % maxsize; if (hash[bin] == NULL) { return EMPTY_FLOAT; } else { float val = 0.0; val = hash[bin]->remove(str); if (val < EMPTY_FLOAT-1e3 || val > EMPTY_FLOAT+1e3) total--; return val; } } double Doubletable::remove(char* str) { unsigned int hashval = hashfunc(str); unsigned int bin = hashval % maxsize; if (hash[bin] == NULL) { return EMPTY_DOUBLE; } else { double val = 0.0; val = hash[bin]->remove(str); if (val != EMPTY_DOUBLE) total--; return val; } } char** Hashtable::keys() { char** allkeys = new char*[total]; int index = 0; for (int i=0;ilength;j++) { if (lowMemFlag) { allkeys[index++] = hash[i]->hashstrs[j]; } else { copystrhash(allkeys[index++], hash[i]->hashstrs[j]); } } } } return allkeys; } char** Inttable::keys() { char** allkeys = new char*[total]; int index = 0; for (int i=0;ilength;j++) { copystrhash(allkeys[index++], hash[i]->hashstrs[j]); } } } return allkeys; } char** LongInttable::keys() { char** allkeys = new char*[total]; int index = 0; for (int i=0;ilength;j++) { copystrhash(allkeys[index++], hash[i]->hashstrs[j]); } } } return allkeys; } char** Floattable::keys() { char** allkeys = new char*[total]; int index = 0; for (int i=0;ilength;j++) { copystrhash(allkeys[index++], hash[i]->hashstrs[j]); } } } return allkeys; } char** Doubletable::keys() { char** allkeys = new char*[total]; int index = 0; for (int i=0;ilength;j++) { copystrhash(allkeys[index++], hash[i]->hashstrs[j]); } } } return allkeys; } void copystrhash(char* &dest, char* src) { if (src == NULL) { dest = NULL; return; } int length = strlen(src)+1; dest = new char[length]; strcpy(dest, src); } unsigned int Hashtable::hashfunc(char* str) { unsigned int hashNum = 5381; int c = *str++; while (c) { hashNum = ((hashNum << 5) + hashNum*33) + c; c=*str++; } return hashNum; } unsigned int Inttable::hashfunc(char* str) { unsigned int hashNum = 5381; int c = *str++; while (c) { hashNum = ((hashNum << 5) + hashNum*33) + c; c=*str++; } return hashNum; } unsigned int LongInttable::hashfunc(char* str) { unsigned int hashNum = 5381; int c = *str++; while (c) { hashNum = ((hashNum << 5) + hashNum*33) + c; c=*str++; } return hashNum; } unsigned int Floattable::hashfunc(char* str) { unsigned int hashNum = 5381; int c = *str++; while (c) { hashNum = ((hashNum << 5) + hashNum*33) + c; c=*str++; } return hashNum; } unsigned int Doubletable::hashfunc(char* str) { unsigned int hashNum = 5381; int c = *str++; while (c) { hashNum = ((hashNum << 5) + hashNum*33) + c; c=*str++; } return hashNum; } void Floattable::stats() { int a=0,b=0,c=0,d=0; for (int i=0;ilength < 2) { b++; } else if (hash[i]->length < 5) { c++; } else { d++; } } } fprintf(stderr, "Stats:\nNULL: %d\n1: %d\n2-4: %d\n>4: %d\n",a,b,c,d); }