/* This file is part of the db4o object database http://www.db4o.com Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com db4o is free software; you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. db4o 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. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. */ package com.db4o.foundation; /** * @exclude */ public class HashtableBase { private static final float FILL = 0.5F; // FIELDS ARE PUBLIC SO THEY CAN BE REFLECTED ON IN JDKs <= 1.1 public int _tableSize; public int _mask; public int _maximumSize; public int _size; public HashtableIntEntry[] _table; public HashtableBase(int size) { size = newSize(size); // legacy for .NET conversion _tableSize = 1; while (_tableSize < size) { _tableSize = _tableSize << 1; } _mask = _tableSize - 1; _maximumSize = (int) (_tableSize * FILL); _table = new HashtableIntEntry[_tableSize]; } public HashtableBase() { this(1); } /** @param cloneOnlyCtor */ protected HashtableBase(DeepClone cloneOnlyCtor) { } public void clear() { _size = 0; Arrays4.fill(_table, null); } private final int newSize(int size) { return (int) (size / FILL); } public int size() { return _size; } protected HashtableIntEntry findWithSameKey(HashtableIntEntry newEntry) { HashtableIntEntry existing = _table[entryIndex(newEntry)]; while (null != existing) { if (existing.sameKeyAs(newEntry)) { return existing; } existing = existing._next; } return null; } protected int entryIndex(HashtableIntEntry entry) { return entry._key & _mask; } protected void putEntry(HashtableIntEntry newEntry) { HashtableIntEntry existing = findWithSameKey(newEntry); if (null != existing) { replace(existing, newEntry); } else { insert(newEntry); } } private void insert(HashtableIntEntry newEntry) { _size++; if (_size > _maximumSize) { increaseSize(); } int index = entryIndex(newEntry); newEntry._next = _table[index]; _table[index] = newEntry; } private void replace(HashtableIntEntry existing, HashtableIntEntry newEntry) { newEntry._next = existing._next; HashtableIntEntry entry = _table[entryIndex(existing)]; if (entry == existing) { _table[entryIndex(existing)] = newEntry; } else { while (entry._next != existing) { entry = entry._next; } entry._next = newEntry; } } private void increaseSize() { _tableSize = _tableSize << 1; _maximumSize = _maximumSize << 1; _mask = _tableSize - 1; HashtableIntEntry[] temp = _table; _table = new HashtableIntEntry[_tableSize]; for (int i = 0; i < temp.length; i++) { reposition(temp[i]); } } protected HashtableIterator hashtableIterator() { return new HashtableIterator(_table); } private void reposition(HashtableIntEntry entry) { HashtableIntEntry currentEntry = entry; HashtableIntEntry nextEntry = null; while (currentEntry != null) { nextEntry = currentEntry._next; currentEntry._next = _table[entryIndex(currentEntry)]; _table[entryIndex(currentEntry)] = currentEntry; currentEntry = nextEntry; } } public Iterator4 keys() { return Iterators.map(hashtableIterator(), new Function4() { public Object apply(Object current) { return ((Entry4)current).key(); } }); } public Iterable4 values() { return new Iterable4() { public Iterator4 iterator() { return valuesIterator(); } }; } /** * Iterates through all the values. * * @return value iterator */ public Iterator4 valuesIterator() { return Iterators.map(hashtableIterator(), new Function4() { public Object apply(Object current) { return ((Entry4)current).value(); } }); } public String toString() { return Iterators.join(hashtableIterator(), "{", "}", ", "); } protected void removeEntry(HashtableIntEntry predecessor, HashtableIntEntry entry) { if (predecessor != null) { predecessor._next = entry._next; } else { _table[entryIndex(entry)] = entry._next; } _size--; } protected Object removeObjectEntry(int intKey, Object objectKey) { HashtableObjectEntry entry = (HashtableObjectEntry) _table[intKey & _mask]; HashtableObjectEntry predecessor = null; while (entry != null) { if (entry._key == intKey && entry.hasKey(objectKey)) { removeEntry(predecessor, entry); return entry._object; } predecessor = entry; entry = (HashtableObjectEntry) entry._next; } return null; } protected Object removeLongEntry(int intKey, long longKey) { HashtableLongEntry entry = (HashtableLongEntry) _table[intKey & _mask]; HashtableLongEntry predecessor = null; while (entry != null) { if (entry._key == intKey && entry._longKey == longKey) { removeEntry(predecessor, entry); return entry._object; } predecessor = entry; entry = (HashtableLongEntry) entry._next; } return null; } protected Object removeIntEntry(int key) { HashtableIntEntry entry = _table[key & _mask]; HashtableIntEntry predecessor = null; while (entry != null) { if (entry._key == key) { removeEntry(predecessor, entry); return entry._object; } predecessor = entry; entry = entry._next; } return null; } }