summaryrefslogtreecommitdiff
path: root/lout
diff options
context:
space:
mode:
Diffstat (limited to 'lout')
-rw-r--r--lout/container.cc230
-rw-r--r--lout/container.hh105
-rw-r--r--lout/object.cc3
3 files changed, 241 insertions, 97 deletions
diff --git a/lout/container.cc b/lout/container.cc
index 0a3d6acd..deeede57 100644
--- a/lout/container.cc
+++ b/lout/container.cc
@@ -17,7 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
+#define PRINTF(fmt, ...)
+//#define PRINTF printf
#include "container.hh"
#include "misc.hh"
@@ -302,13 +303,12 @@ Collection0::AbstractIterator* List::createIterator()
// ---------------
-// HashTable
+// HashSet
// ---------------
-HashTable::HashTable(bool ownerOfKeys, bool ownerOfValues, int tableSize)
+HashSet::HashSet(bool ownerOfObjects, int tableSize)
{
- this->ownerOfKeys = ownerOfKeys;
- this->ownerOfValues = ownerOfValues;
+ this->ownerOfObjects = ownerOfObjects;
this->tableSize = tableSize;
table = new Node*[tableSize];
@@ -316,19 +316,24 @@ HashTable::HashTable(bool ownerOfKeys, bool ownerOfValues, int tableSize)
table[i] = NULL;
}
-HashTable::~HashTable()
+HashSet::~HashSet()
{
for (int i = 0; i < tableSize; i++) {
Node *n1 = table[i];
while (n1) {
Node *n2 = n1->next;
- if (ownerOfValues && n1->value)
- delete n1->value;
- if (ownerOfKeys)
- delete n1->key;
- delete n1;
+ // It seems appropriate to call "clearNode(n1)" here instead
+ // of "delete n1->object", but since this is the destructor,
+ // the implementation of a sub class would not be called
+ // anymore. This is the reason why HashTable has an
+ // destructor.
+ if (ownerOfObjects) {
+ PRINTF ("- deleting object: %s\n", n1->object->toString());
+ delete n1->object;
+ }
+ delete n1;
n1 = n2;
}
}
@@ -336,73 +341,77 @@ HashTable::~HashTable()
delete[] table;
}
-void HashTable::intoStringBuffer(misc::StringBuffer *sb)
+HashSet::Node *HashSet::createNode()
{
- sb->append("{ ");
+ return new Node;
+}
- bool first = true;
- for (int i = 0; i < tableSize; i++) {
- for (Node *node = table[i]; node; node = node->next) {
- if (!first)
- sb->append(", ");
- node->key->intoStringBuffer(sb);
- sb->append(" => ");
- node->value->intoStringBuffer(sb);
- first = false;
- }
+void HashSet::clearNode(HashSet::Node *node)
+{
+ if (ownerOfObjects) {
+ PRINTF ("- deleting object: %s\n", node->object->toString());
+ delete node->object;
}
-
- sb->append(" }");
}
-void HashTable::put(Object *key, Object *value)
+HashSet::Node *HashSet::findNode(Object *object)
{
- int h = calcHashValue(key);
- Node *n = new Node;
- n->key = key;
- n->value = value;
- n->next = table[h];
- table[h] = n;
+ int h = calcHashValue(object);
+ for (Node *node = table[h]; node; node = node->next) {
+ if (object->equals(node->object))
+ return node;
+ }
+
+ return NULL;
}
-bool HashTable::contains(Object *key)
+HashSet::Node *HashSet::insertNode(Object *object)
{
- int h = calcHashValue(key);
- for (Node *n = table[h]; n; n = n->next) {
- if (key->equals(n->key))
- return true;
+ // Look whether object is already contained.
+ Node *node = findNode(object);
+ if (node)
+ clearNode(node);
+ else {
+ int h = calcHashValue(object);
+ node = createNode ();
+ node->next = table[h];
+ table[h] = node;
}
- return false;
+ node->object = object;
+ return node;
}
-Object *HashTable::get(Object *key)
+
+void HashSet::put(Object *object)
+{
+ insertNode (object);
+}
+
+bool HashSet::contains(Object *object)
{
- int h = calcHashValue(key);
+ int h = calcHashValue(object);
for (Node *n = table[h]; n; n = n->next) {
- if (key->equals(n->key))
- return n->value;
+ if (object->equals(n->object))
+ return true;
}
- return NULL;
+ return false;
}
-bool HashTable::remove(Object *key)
+bool HashSet::remove(Object *object)
{
- int h = calcHashValue(key);
+ int h = calcHashValue(object);
Node *last, *cur;
for (last = NULL, cur = table[h]; cur; last = cur, cur = cur->next) {
- if (key->equals(cur->key)) {
+ if (object->equals(cur->object)) {
if (last)
last->next = cur->next;
else
table[h] = cur->next;
- if (ownerOfValues && cur->value)
- delete cur->value;
- if (ownerOfKeys)
- delete cur->key;
+ clearNode (cur);
delete cur;
return true;
@@ -410,46 +419,53 @@ bool HashTable::remove(Object *key)
}
return false;
+
+ // TODO for HashTable: also remove value.
}
-Object *HashTable::getKey (Object *key)
+// For historical reasons: this method once existed under the name
+// "getKey" in HashTable. It could be used to get the real object from
+// the table, but it was dangerous, because a change of this object
+// would also change the hash value, and so confuse the table.
+
+/*Object *HashSet::getReference (Object *object)
{
- int h = calcHashValue(key);
+ int h = calcHashValue(object);
for (Node *n = table[h]; n; n = n->next) {
- if (key->equals(n->key))
- return n->key;
+ if (object->equals(n->object))
+ return n->object;
}
return NULL;
-}
+}*/
-HashTable::HashTableIterator::HashTableIterator(HashTable *table)
+HashSet::HashSetIterator::HashSetIterator(HashSet *set)
{
- this->table = table;
+ this->set = set;
node = NULL;
pos = -1;
gotoNext();
}
-void HashTable::HashTableIterator::gotoNext()
+void HashSet::HashSetIterator::gotoNext()
{
if (node)
node = node->next;
while (node == NULL) {
- if (pos >= table->tableSize - 1)
+ if (pos >= set->tableSize - 1)
return;
pos++;
- node = table->table[pos];
+ node = set->table[pos];
}
}
-Object *HashTable::HashTableIterator::getNext()
+Object *HashSet::HashSetIterator::getNext()
{
Object *result;
if (node)
- result = node->key;
+ result = node->object;
else
result = NULL;
@@ -457,14 +473,98 @@ Object *HashTable::HashTableIterator::getNext()
return result;
}
-bool HashTable::HashTableIterator::hasNext()
+bool HashSet::HashSetIterator::hasNext()
{
return node != NULL;
}
-Collection0::AbstractIterator* HashTable::createIterator()
+Collection0::AbstractIterator* HashSet::createIterator()
+{
+ return new HashSetIterator(this);
+}
+
+// ---------------
+// HashTable
+// ---------------
+
+HashTable::HashTable(bool ownerOfKeys, bool ownerOfValues, int tableSize) :
+ HashSet (ownerOfKeys, tableSize)
+{
+ this->ownerOfValues = ownerOfValues;
+}
+
+HashTable::~HashTable()
+{
+ // See comment in the destructor of HashSet.
+ for (int i = 0; i < tableSize; i++) {
+ for (Node *n = table[i]; n; n = n->next) {
+ if (ownerOfValues) {
+ Object *value = ((KeyValuePair*)n)->value;
+ if (value) {
+ PRINTF ("- deleting value: %s\n", value->toString());
+ delete value;
+ }
+ }
+ }
+ }
+}
+
+HashSet::Node *HashTable::createNode()
+{
+ return new KeyValuePair;
+}
+
+void HashTable::clearNode(HashSet::Node *node)
+{
+ HashSet::clearNode (node);
+ if (ownerOfValues) {
+ Object *value = ((KeyValuePair*)node)->value;
+ if (value) {
+ PRINTF ("- deleting value: %s\n", value->toString());
+ delete value;
+ }
+ }
+}
+
+void HashTable::intoStringBuffer(misc::StringBuffer *sb)
+{
+ sb->append("{ ");
+
+ bool first = true;
+ for (int i = 0; i < tableSize; i++) {
+ for (Node *node = table[i]; node; node = node->next) {
+ if (!first)
+ sb->append(", ");
+ node->object->intoStringBuffer(sb);
+
+ sb->append(" => ");
+
+ Object *value = ((KeyValuePair*)node)->value;
+ if (value)
+ value->intoStringBuffer(sb);
+ else
+ sb->append ("null");
+
+ first = false;
+ }
+ }
+
+ sb->append(" }");
+}
+
+void HashTable::put(Object *key, Object *value)
+{
+ KeyValuePair *node = (KeyValuePair*)insertNode(key);
+ node->value = value;
+}
+
+Object *HashTable::get(Object *key)
{
- return new HashTableIterator(this);
+ Node *node = findNode(key);
+ if (node)
+ return ((KeyValuePair*)node)->value;
+ else
+ return NULL;
}
// -----------
diff --git a/lout/container.hh b/lout/container.hh
index d2484b13..f1008e82 100644
--- a/lout/container.hh
+++ b/lout/container.hh
@@ -179,46 +179,78 @@ public:
/**
- * \brief A hash table.
+ * \brief A hash set.
*/
-class HashTable: public Collection
+class HashSet: public Collection
{
- friend class HashTableIterator;
+ friend class HashSetIterator;
-private:
+protected:
struct Node
{
- object::Object *key, *value;
+ object::Object *object;
Node *next;
};
- class HashTableIterator: public Collection0::AbstractIterator
+ Node **table;
+ int tableSize;
+ bool ownerOfObjects;
+
+ inline int calcHashValue(object::Object *object)
+ {
+ return abs(object->hashValue()) % tableSize;
+ }
+
+ virtual Node *createNode();
+ virtual void clearNode(Node *node);
+
+ Node *findNode(object::Object *object);
+ Node *insertNode(object::Object *object);
+
+ AbstractIterator* createIterator();
+
+private:
+ class HashSetIterator: public Collection0::AbstractIterator
{
private:
- HashTable *table;
- HashTable::Node *node;
+ HashSet *set;
+ HashSet::Node *node;
int pos;
void gotoNext();
public:
- HashTableIterator(HashTable *table);
+ HashSetIterator(HashSet *set);
bool hasNext();
Object *getNext();
};
- Node **table;
- int tableSize;
- bool ownerOfKeys, ownerOfValues;
+public:
+ HashSet(bool ownerOfObjects, int tableSize = 251);
+ ~HashSet();
+ void put (object::Object *object);
+ bool contains (object::Object *key);
+ bool remove (object::Object *key);
+ //Object *getReference (object::Object *object);
+};
+
+/**
+ * \brief A hash table.
+ */
+class HashTable: public HashSet
+{
private:
- inline int calcHashValue(object::Object *key)
+ bool ownerOfValues;
+
+ struct KeyValuePair: public Node
{
- return abs(key->hashValue()) % tableSize;
- }
+ object::Object *value;
+ };
protected:
- AbstractIterator* createIterator();
+ Node *createNode();
+ void clearNode(Node *node);
public:
HashTable(bool ownerOfKeys, bool ownerOfValues, int tableSize = 251);
@@ -227,10 +259,7 @@ public:
void intoStringBuffer(misc::StringBuffer *sb);
void put (object::Object *key, object::Object *value);
- bool contains (object::Object *key);
- Object *get (object::Object *key);
- bool remove (object::Object *key);
- Object *getKey (Object *key);
+ object::Object *get (object::Object *key);
};
/**
@@ -328,6 +357,9 @@ protected:
untyped::Collection *base;
public:
+ Collection () { this->base = NULL; }
+ ~Collection () { if (this->base) delete this->base; }
+
void intoStringBuffer(misc::StringBuffer *sb)
{ this->base->intoStringBuffer(sb); }
@@ -344,7 +376,6 @@ template <class T> class Vector: public Collection <T>
public:
inline Vector(int initSize, bool ownerOfObjects) {
this->base = new untyped::Vector(initSize, ownerOfObjects); }
- ~Vector() { delete this->base; }
inline void put(T *newElement, int newPos = -1)
{ ((untyped::Vector*)this->base)->put(newElement, newPos); }
@@ -367,7 +398,6 @@ template <class T> class List: public Collection <T>
public:
inline List(bool ownerOfObjects)
{ this->base = new untyped::List(ownerOfObjects); }
- ~List() { delete this->base; }
inline void clear() { ((untyped::List*)this->base)->clear(); }
inline void append(T *element)
@@ -388,28 +418,42 @@ public:
{ return (T*)((untyped::List*)this->base)->getLast(); }
};
+/**
+ * \brief Typed version of container::untyped::HashSet.
+ */
+template <class T> class HashSet: public Collection <T>
+{
+protected:
+ inline HashSet() { }
+
+public:
+ inline HashSet(bool owner, int tableSize = 251)
+ { this->base = new untyped::HashSet(owner, tableSize); }
+
+ inline void put(T *object)
+ { return ((untyped::HashSet*)this->base)->put(object); }
+ inline bool contains(T *object)
+ { return ((untyped::HashSet*)this->base)->contains(object); }
+ inline bool remove(T *object)
+ { return ((untyped::HashSet*)this->base)->remove(object); }
+ //inline T *getReference(T *object)
+ //{ return (T*)((untyped::HashSet*)this->base)->getReference(object); }
+};
/**
* \brief Typed version of container::untyped::HashTable.
*/
-template <class K, class V> class HashTable: public Collection <K>
+template <class K, class V> class HashTable: public HashSet <K>
{
public:
inline HashTable(bool ownerOfKeys, bool ownerOfValues, int tableSize = 251)
{ this->base = new untyped::HashTable(ownerOfKeys, ownerOfValues,
tableSize); }
- ~HashTable() { delete this->base; }
inline void put(K *key, V *value)
{ return ((untyped::HashTable*)this->base)->put(key, value); }
- inline bool contains(K *key)
- { return ((untyped::HashTable*)this->base)->contains(key); }
inline V *get(K *key)
{ return (V*)((untyped::HashTable*)this->base)->get(key); }
- inline bool remove(K *key)
- { return ((untyped::HashTable*)this->base)->remove(key); }
- inline K *getKey(K *key)
- { return (K*)((untyped::HashTable*)this->base)->getKey(key); }
};
/**
@@ -420,7 +464,6 @@ template <class T> class Stack: public Collection <T>
public:
inline Stack (bool ownerOfObjects)
{ this->base = new untyped::Stack (ownerOfObjects); }
- ~Stack() { delete this->base; }
inline void push (T *object) {
((untyped::Stack*)this->base)->push (object); }
diff --git a/lout/object.cc b/lout/object.cc
index 843c0ae4..85a908b9 100644
--- a/lout/object.cc
+++ b/lout/object.cc
@@ -21,6 +21,7 @@
#include "object.hh"
#include <stdio.h>
+#include <stdint.h>
#include <config.h>
namespace lout {
@@ -132,7 +133,7 @@ int Pointer::hashValue()
// Combine both parts of the pointer value *itself*, not what it
// points to, by first referencing it (operator "&"), then
// dereferencing it again (operator "[]").
- return ((int*)&value)[0] ^ ((int*)&value)[1];
+ return ((intptr_t)value >> 32) ^ ((intptr_t)value);
#endif
}