/* Generated automatically by jlpp - do not edit. */ #include static jakelib::lang::String* jakelib2_strings[] = {null, null, null, null, null}; // "Illegal Capacity: " static jchar chars_jakelib2_str_0[] = {73,108,108,101,103,97,108,32,67,97,112,97,99,105,116,121,58,32}; // "Illegal Load: <= 0" static jchar chars_jakelib2_str_1[] = {73,108,108,101,103,97,108,32,76,111,97,100,58,32,60,61,32,48}; // "Unable to enlarge table from " static jchar chars_jakelib2_str_2[] = {85,110,97,98,108,101,32,116,111,32,101,110,108,97,114,103,101,32,116,97,98,108,101,32,102,114,111,109,32}; // " to " static jchar chars_jakelib2_str_3[] = {32,116,111,32}; // " elements" static jchar chars_jakelib2_str_4[] = {32,101,108,101,109,101,110,116,115}; #line 1 "util/Hashtable.jlc" // -*- c++ -*- /* * Jakelib2 - General purpose C++ library * Copyright (C) 2001 Florian Wolff (florian@donuz.de) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: Hashtable.jlc,v 1.5 2003/09/27 08:10:29 florian Exp $ */ #include "jakelib2.h" #include "jakelib2/util/Hashtable.h" #include "jakelib2/util/HashEntry.h" #include "jakelib2/util/HashtableIterator.h" #include using namespace jakelib::lang; using namespace jakelib::util; JAKELIB_IMPLEMENT_CLASS("jakelib.util.Hashtable", Hashtable, Dictionary) /*****************************************************************************\ * Hashtable | *****************************************************************************/ Hashtable::Hashtable(int initialCapacity, float loadFactor) { if (initialCapacity < 0) throw new IllegalArgumentException(JAKELIB_ONDEMAND(jakelib2_strings[0], new jakelib::lang::String(chars_jakelib2_str_0, 0, 18)) ->plus( initialCapacity )->plus( JAKELIB_AT2("jakelib.util.Hashtable.Hashtable"))); if (loadFactor <= 0) throw new IllegalArgumentException(JAKELIB_ONDEMAND(jakelib2_strings[1], new jakelib::lang::String(chars_jakelib2_str_1, 0, 18)) ->plus( JAKELIB_AT2("jakelib.util.Hashtable.Hashtable"))); if (initialCapacity==0) initialCapacity = 1; this->loadFactor = loadFactor; table = (HashEntry**) GC_MALLOC(sizeof(HashEntry**) * initialCapacity); memset(table, 0, sizeof(HashEntry**) * initialCapacity); threshold = (int) (initialCapacity * loadFactor); capacity = initialCapacity; elementCount = 0; } Hashtable::~Hashtable() { clear(); GC_FREE(table); } /*****************************************************************************\ * get | *****************************************************************************/ Object* Hashtable::get(Object* key) { int hash = key->hashCode(); int startIndex = (hash & 0x7FFFFFFF) % capacity; int index = startIndex ; HashEntry* e; while((e = table[index ++]) != null) { if ((e->hash == hash) && (e->key->equals(key))) { return e->value; } if (index >= capacity) index = 0; if (index == startIndex) return null; } return null; } Object* Hashtable::get(char* key) { String keyStr(key); return get(&keyStr); } /*****************************************************************************\ * put | *****************************************************************************/ void Hashtable::put(Object* key, Object* value) { if (key == null) throw new NullPointerException(JAKELIB_AT2("jakelib.util.Hashtable.put")); int hash = key->hashCode(); int startIndex = (hash & 0x7FFFFFFF) % capacity; int index = startIndex ; // Creates the new entry. HashEntry* newEntry = new HashEntry(hash, key, value); // Makes sure the key is not already in the hashtable. HashEntry* e; while((e = table[index]) != null) { if ((e->hash == hash) && (e->key->equals(key))) { delete e; table[index] = newEntry; return; } index = (index + 1) % capacity; } if (elementCount >= threshold -1) { // Rehash the table if the threshold is exceeded rehash(); index = (hash & 0x7FFFFFFF) % capacity; } // look for empty space to store new entry while((table[index]) != null) { index ++; if (index >= capacity) index = 0; } table[index] = newEntry; elementCount ++; return; } void Hashtable::put(char* key, char* value) { put(new String(key), new String(value)); } void Hashtable::put(char* key, Object* value) { put(new String(key), value); } /*****************************************************************************\ * remove | *****************************************************************************/ void Hashtable::remove(Object* key) { if (key == null) { throw new NullPointerException(JAKELIB_AT2("jakelib.util.Hashtable.remove")); } int hash = key->hashCode(); int index = (hash & 0x7FFFFFFF) % capacity; int prevIndex; HashEntry* e; while((e = table[index]) != null) { if ((e->hash == hash) && (e->key->equals(key))) { // We have found the item to be deleted: delete e; elementCount --; table[index] = null; prevIndex = index; index = (index + 1) % capacity; while((e = table[index]) != null) { if ((e->hash & 0x7FFFFFFF) % capacity == index) break; table[prevIndex] = table[index]; table[index] = null; prevIndex = index; index = (index + 1) % capacity; } break; } index = (index + 1) % capacity; } } void Hashtable::remove(char* key) { String keyStr(key); remove(&keyStr); } /*****************************************************************************\ * rehash | *****************************************************************************/ void Hashtable::rehash() { int newCapacity = capacity * 2 + 1; HashEntry** newMap = (HashEntry**) GC_MALLOC(sizeof(HashEntry**) * newCapacity); memset(newMap, 0, sizeof(HashEntry**) * newCapacity); if (newMap == null) throw new MemoryException(JAKELIB_ONDEMAND(jakelib2_strings[2], new jakelib::lang::String(chars_jakelib2_str_2, 0, 29)) ->plus( capacity )->plus( JAKELIB_ONDEMAND(jakelib2_strings[3], new jakelib::lang::String(chars_jakelib2_str_3, 0, 4)) )->plus( newCapacity )->plus( JAKELIB_ONDEMAND(jakelib2_strings[4], new jakelib::lang::String(chars_jakelib2_str_4, 0, 9)) )->plus( JAKELIB_AT2("jakelib.util.Hashtable.rehash"))); threshold = (int) (newCapacity * loadFactor); HashEntry* old; int index; for (int idx = 0; idx < capacity; idx++) { old = table[idx]; if (old != null) { index = (old->hash & 0x7FFFFFFF) % newCapacity; while((newMap[index]) != null) { index ++; if (index >= newCapacity) index = 0; } // Creates the new entry. newMap[index] = old; } } GC_FREE(table); table = newMap; capacity = newCapacity; } /*****************************************************************************\ * isEmpty | *****************************************************************************/ jboolean Hashtable::isEmpty() { return elementCount == 0; } /*****************************************************************************\ * size | *****************************************************************************/ int Hashtable::size() { return elementCount; } /*****************************************************************************\ * clear | *****************************************************************************/ void Hashtable::clear() { for (int idx = 0; idx < capacity; idx++) { delete table[idx]; table[idx] = null; } elementCount = 0; } /*****************************************************************************\ * keys | *****************************************************************************/ HashtableIterator* Hashtable::keys() { return new HashtableIterator(this); } /*****************************************************************************\ * toString | *****************************************************************************/ String* Hashtable::toString() { StringBuffer buf("{"); jboolean first = true; for (int idx = 0; idx < capacity; idx++) { HashEntry* e = table[idx]; if (e != null) { if (!first) buf.append(", "); first = false; buf.append(e->key->toString())-> append("=")->append(e->value->toString()); } } buf.append("}"); return buf.toString(); }