You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ta...@apache.org on 2012/07/24 00:01:19 UTC
svn commit: r1364819 [1/2] - in
/activemq/activemq-cpp/trunk/activemq-cpp/src: main/decaf/lang/
main/decaf/util/ main/decaf/util/concurrent/ test/ test/decaf/util/
Author: tabish
Date: Mon Jul 23 22:01:19 2012
New Revision: 1364819
URL: http://svn.apache.org/viewvc?rev=1364819&view=rev
Log:
A more complete HashMap implementation with Unit tests, and some API updates
Modified:
activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/ArrayPointer.h
activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/AbstractMap.h
activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/HashCode.h
activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/HashMap.h
activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Map.h
activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/MapEntry.h
activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/StlMap.h
activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/ConcurrentStlMap.h
activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/HashMapTest.cpp
activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/HashMapTest.h
activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/StlMapTest.cpp
activemq/activemq-cpp/trunk/activemq-cpp/src/test/testRegistry.cpp
Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/ArrayPointer.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/ArrayPointer.h?rev=1364819&r1=1364818&r2=1364819&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/ArrayPointer.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/ArrayPointer.h Mon Jul 23 22:01:19 2012
@@ -118,6 +118,7 @@ namespace lang {
try {
T* value = new T[size];
this->array = new ArrayData(value, size);
+ decaf::util::Arrays::fill(value, size, 0, size, T());
} catch (std::exception& ex) {
throw ex;
} catch (...) {
Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/AbstractMap.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/AbstractMap.h?rev=1364819&r1=1364818&r2=1364819&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/AbstractMap.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/AbstractMap.h Mon Jul 23 22:01:19 2012
@@ -22,6 +22,8 @@
#include <decaf/lang/exceptions/UnsupportedOperationException.h>
#include <decaf/lang/exceptions/NullPointerException.h>
#include <decaf/lang/exceptions/IllegalArgumentException.h>
+#include <decaf/util/concurrent/Synchronizable.h>
+#include <decaf/util/concurrent/Mutex.h>
#include <decaf/util/Iterator.h>
#include <decaf/util/Map.h>
#include <decaf/util/Set.h>
@@ -55,10 +57,57 @@ namespace util {
*/
template< typename K, typename V>
class AbstractMap : public decaf::util::Map<K, V> {
+ protected:
+
+ mutable util::concurrent::Mutex mutex;
+
public:
+ AbstractMap() : Map<K, V>(), mutex() {
+ }
+
+ AbstractMap(const Map<K, V>& map) : Map<K, V>(), mutex() {
+ }
+
+ AbstractMap(const AbstractMap<K, V>& map) : Map<K, V>(), mutex() {
+ }
+
virtual ~AbstractMap() {}
+ public:
+
+ virtual void lock() {
+ mutex.lock();
+ }
+
+ virtual bool tryLock() {
+ return mutex.tryLock();
+ }
+
+ virtual void unlock() {
+ mutex.unlock();
+ }
+
+ virtual void wait() {
+ mutex.wait();
+ }
+
+ virtual void wait( long long millisecs ) {
+ mutex.wait( millisecs );
+ }
+
+ virtual void wait( long long millisecs, int nanos ) {
+ mutex.wait( millisecs, nanos );
+ }
+
+ virtual void notify() {
+ mutex.notify();
+ }
+
+ virtual void notifyAll() {
+ mutex.notifyAll();
+ }
+
};
}}
Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/HashCode.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/HashCode.h?rev=1364819&r1=1364818&r2=1364819&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/HashCode.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/HashCode.h Mon Jul 23 22:01:19 2012
@@ -39,103 +39,103 @@ namespace util {
template<typename T>
struct HashCode : public std::unary_function<T, int> {
public:
- int operator()(T arg);
+ int operator()(T arg) const;
};
template<typename T>
struct HashCode<T*> : public std::unary_function<T*, int> {
- int operator()(T* arg) {
+ int operator()(T* arg) const {
return reinterpret_cast<int>(arg);
}
};
template<typename T>
struct HashCode<const T&> : public std::unary_function<const T&, int> {
- int operator()(const T& arg) {
+ int operator()(const T& arg) const {
return HashCode<const T*>(&arg);
}
};
template<>
struct HashCode<bool> : public std::unary_function<bool, int> {
- int operator()(bool arg) {
+ int operator()(bool arg) const {
return arg ? 1231 : 1237;
}
};
template<>
struct HashCode<unsigned char> : public std::unary_function<unsigned char, int> {
- int operator()(unsigned char arg) {
+ int operator()(unsigned char arg) const {
return (int) arg;
}
};
template<>
struct HashCode<char> : public std::unary_function<char, int> {
- int operator()(char arg) {
+ int operator()(char arg) const {
return (int) arg;
}
};
template<>
struct HashCode<wchar_t> : public std::unary_function<wchar_t, int> {
- int operator()(wchar_t arg) {
+ int operator()(wchar_t arg) const {
return (int) arg;
}
};
template<>
struct HashCode<unsigned short> : public std::unary_function<unsigned short, int> {
- int operator()(unsigned short arg) {
+ int operator()(unsigned short arg) const {
return (int) arg;
}
};
template<>
struct HashCode<short> : public std::unary_function<short, int> {
- int operator()(short arg) {
+ int operator()(short arg) const {
return (int) arg;
}
};
template<>
struct HashCode<unsigned int> : public std::unary_function<unsigned int, int> {
- int operator()(unsigned int arg) {
+ int operator()(unsigned int arg) const {
return (int) arg;
}
};
template<>
struct HashCode<int> : public std::unary_function<int, int> {
- int operator()(int arg) {
+ int operator()(int arg) const {
return arg;
}
};
template<>
struct HashCode<unsigned long long> : public std::unary_function<unsigned long long, int> {
- int operator()(unsigned long long arg) {
+ int operator()(unsigned long long arg) const {
return (int) (arg ^ (arg >> 32));
}
};
template<>
struct HashCode<long long> : public std::unary_function<long long, int> {
- int operator()(long long arg) {
+ int operator()(long long arg) const {
return (int) (arg ^ ((unsigned long long) arg >> 32));
}
};
template<>
struct HashCode<float> : public std::unary_function<float, int> {
- int operator()(float arg) {
+ int operator()(float arg) const {
return decaf::lang::Float::floatToIntBits(arg);
}
};
template<>
struct HashCode<double> : public std::unary_function<double, int> {
- int operator()(double arg) {
+ int operator()(double arg) const {
long long value = decaf::lang::Double::doubleToLongBits(arg);
return (int) (value ^ ((unsigned long long) value >> 32));
}
@@ -143,7 +143,7 @@ namespace util {
template<>
struct HashCode<std::string> : public std::unary_function<const std::string&, int> {
- int operator()(const std::string& arg) {
+ int operator()(const std::string& arg) const {
int h = 0;
if (h == 0 && arg.length() > 0) {
std::string::const_iterator iter = arg.begin();
@@ -157,7 +157,7 @@ namespace util {
template<typename T>
struct HashCode< decaf::lang::Pointer<T> > : public std::unary_function<decaf::lang::Pointer<T>, int> {
- int operator()(decaf::lang::Pointer<T> arg) {
+ int operator()(decaf::lang::Pointer<T> arg) const {
if (arg != NULL) {
return HashCode<T>()(*arg);
}
Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/HashMap.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/HashMap.h?rev=1364819&r1=1364818&r2=1364819&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/HashMap.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/HashMap.h Mon Jul 23 22:01:19 2012
@@ -21,7 +21,11 @@
#include <decaf/util/Config.h>
#include <decaf/util/AbstractMap.h>
+#include <decaf/util/AbstractSet.h>
#include <decaf/util/HashCode.h>
+#include <decaf/util/ConcurrentModificationException.h>
+#include <decaf/lang/exceptions/UnsupportedOperationException.h>
+#include <decaf/lang/Pointer.h>
#include <decaf/lang/ArrayPointer.h>
namespace decaf {
@@ -92,14 +96,20 @@ namespace util {
private:
class HashMapEntry : public MapEntry<K, V> {
+ private:
+
+ HashMapEntry(const HashMapEntry&);
+ HashMapEntry& operator= (const HashMapEntry&);
+
public:
int origKeyHash;
HashMapEntry* next;
- HashMapEntry(const K& key, int hash) : MapEntry<K, V>(), origKeyHash(hash), next(NULL) {
+ HashMapEntry(const K& key, const V& value, int hash) : MapEntry<K, V>(), origKeyHash(hash), next(NULL) {
this->setKey(key);
+ this->setValue(value);
this->origKeyHash = hash;
}
@@ -111,6 +121,528 @@ namespace util {
private:
+ class AbstractMapIterator {
+ protected:
+
+ mutable int position;
+ int expectedModCount;
+ HashMapEntry* futureEntry;
+ HashMapEntry* currentEntry;
+ HashMapEntry* prevEntry;
+
+ HashMap* associatedMap;
+
+ public:
+
+ AbstractMapIterator(HashMap* parent) : position(0),
+ expectedModCount(parent->modCount),
+ futureEntry(NULL),
+ currentEntry(NULL),
+ prevEntry(NULL),
+ associatedMap(parent) {
+ }
+
+ virtual ~AbstractMapIterator() {}
+
+ virtual bool checkHasNext() const {
+ if (futureEntry != NULL) {
+ return true;
+ }
+ while (position < associatedMap->elementData.length()) {
+ if (associatedMap->elementData[position] == NULL) {
+ position++;
+ } else {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void checkConcurrentMod() const {
+ if (expectedModCount != associatedMap->modCount) {
+ throw ConcurrentModificationException(
+ __FILE__, __LINE__, "HashMap modified outside this iterator");
+ }
+ }
+
+ void makeNext() {
+ checkConcurrentMod();
+
+ if (!checkHasNext()) {
+ throw NoSuchElementException(__FILE__, __LINE__, "No next element");
+ }
+
+ if (futureEntry == NULL) {
+ currentEntry = associatedMap->elementData[position++];
+ futureEntry = currentEntry->next;
+ prevEntry = NULL;
+ } else {
+ if (currentEntry != NULL){
+ prevEntry = currentEntry;
+ }
+ currentEntry = futureEntry;
+ futureEntry = futureEntry->next;
+ }
+ }
+
+ virtual void doRemove() {
+
+ checkConcurrentMod();
+
+ if (currentEntry == NULL) {
+ throw decaf::lang::exceptions::IllegalStateException(
+ __FILE__, __LINE__, "Remove called before call to next()");
+ }
+
+ if (prevEntry == NULL){
+ int index = currentEntry->origKeyHash & (associatedMap->elementData.length() - 1);
+ associatedMap->elementData[index] = associatedMap->elementData[index]->next;
+ } else {
+ prevEntry->next = currentEntry->next;
+ }
+
+ currentEntry = NULL;
+ expectedModCount++;
+ associatedMap->modCount++;
+ associatedMap->elementCount--;
+ }
+ };
+
+ class EntryIterator : public Iterator< MapEntry<K,V> >, public AbstractMapIterator {
+ private:
+
+ EntryIterator(const EntryIterator&);
+ EntryIterator& operator= (const EntryIterator&);
+
+ public:
+
+ EntryIterator(HashMap* parent) : AbstractMapIterator(parent) {
+ }
+
+ virtual ~EntryIterator() {}
+
+ virtual bool hasNext() const {
+ return this->checkHasNext();
+ }
+
+ virtual MapEntry<K, V> next() {
+ this->makeNext();
+ return *(this->currentEntry);
+ }
+
+ virtual void remove() {
+ this->doRemove();
+ }
+ };
+
+ class KeyIterator : public Iterator<K>, public AbstractMapIterator {
+ private:
+
+ KeyIterator(const KeyIterator&);
+ KeyIterator& operator= (const KeyIterator&);
+
+ public:
+
+ KeyIterator(HashMap* parent) : AbstractMapIterator(parent) {
+ }
+
+ virtual ~KeyIterator() {}
+
+ virtual bool hasNext() const {
+ return this->checkHasNext();
+ }
+
+ virtual K next() {
+ this->makeNext();
+ return this->currentEntry->getKey();
+ }
+
+ virtual void remove() {
+ this->doRemove();
+ }
+ };
+
+ class ValueIterator : public Iterator<V>, public AbstractMapIterator {
+ private:
+
+ ValueIterator(const ValueIterator&);
+ ValueIterator& operator= (const ValueIterator&);
+
+ public:
+
+ ValueIterator(HashMap* parent) : AbstractMapIterator(parent) {
+ }
+
+ virtual ~ValueIterator() {}
+
+ virtual bool hasNext() const {
+ return this->checkHasNext();
+ }
+
+ virtual V next() {
+ this->makeNext();
+ return this->currentEntry->getValue();
+ }
+
+ virtual void remove() {
+ this->doRemove();
+ }
+ };
+
+ private:
+
+ class ConstAbstractMapIterator {
+ protected:
+
+ mutable int position;
+ int expectedModCount;
+ const HashMapEntry* futureEntry;
+ const HashMapEntry* currentEntry;
+ const HashMapEntry* prevEntry;
+
+ const HashMap* associatedMap;
+
+ public:
+
+ ConstAbstractMapIterator(const HashMap* parent) : position(0),
+ expectedModCount(parent->modCount),
+ futureEntry(NULL),
+ currentEntry(NULL),
+ prevEntry(NULL),
+ associatedMap(parent) {
+ }
+
+ virtual ~ConstAbstractMapIterator() {}
+
+ virtual bool checkHasNext() const {
+ if (futureEntry != NULL) {
+ return true;
+ }
+ while (position < associatedMap->elementData.length()) {
+ if (associatedMap->elementData[position] == NULL) {
+ position++;
+ } else {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void checkConcurrentMod() const {
+ if (expectedModCount != associatedMap->modCount) {
+ throw ConcurrentModificationException(
+ __FILE__, __LINE__, "HashMap modified outside this iterator");
+ }
+ }
+
+ void makeNext() {
+ checkConcurrentMod();
+
+ if (!checkHasNext()) {
+ throw NoSuchElementException(__FILE__, __LINE__, "No next element");
+ }
+
+ if (futureEntry == NULL) {
+ currentEntry = associatedMap->elementData[position++];
+ futureEntry = currentEntry->next;
+ prevEntry = NULL;
+ } else {
+ if (currentEntry != NULL){
+ prevEntry = currentEntry;
+ }
+ currentEntry = futureEntry;
+ futureEntry = futureEntry->next;
+ }
+ }
+ };
+
+ class ConstEntryIterator : public Iterator< MapEntry<K,V> >, public ConstAbstractMapIterator {
+ private:
+
+ ConstEntryIterator(const ConstEntryIterator&);
+ ConstEntryIterator& operator= (const ConstEntryIterator&);
+
+ public:
+
+ ConstEntryIterator(const HashMap* parent) : ConstAbstractMapIterator(parent) {
+ }
+
+ virtual ~ConstEntryIterator() {}
+
+ virtual bool hasNext() const {
+ return this->checkHasNext();
+ }
+
+ virtual MapEntry<K, V> next() {
+ this->makeNext();
+ return *(this->currentEntry);
+ }
+
+ virtual void remove() {
+ throw lang::exceptions::UnsupportedOperationException(
+ __FILE__, __LINE__, "Cannot write to a const Iterator." );
+ }
+ };
+
+ class ConstKeyIterator : public Iterator<K>, public ConstAbstractMapIterator {
+ private:
+
+ ConstKeyIterator(const ConstKeyIterator&);
+ ConstKeyIterator& operator= (const ConstKeyIterator&);
+
+ public:
+
+ ConstKeyIterator(const HashMap* parent) : ConstAbstractMapIterator(parent) {
+ }
+
+ virtual ~ConstKeyIterator() {}
+
+ virtual bool hasNext() const {
+ return this->checkHasNext();
+ }
+
+ virtual K next() {
+ this->makeNext();
+ return this->currentEntry->getKey();
+ }
+
+ virtual void remove() {
+ throw lang::exceptions::UnsupportedOperationException(
+ __FILE__, __LINE__, "Cannot write to a const Iterator." );
+ }
+ };
+
+ class ConstValueIterator : public Iterator<V>, public ConstAbstractMapIterator {
+ private:
+
+ ConstValueIterator(const ConstValueIterator&);
+ ConstValueIterator& operator= (const ConstValueIterator&);
+
+ public:
+
+ ConstValueIterator(const HashMap* parent) : ConstAbstractMapIterator(parent) {
+ }
+
+ virtual ~ConstValueIterator() {}
+
+ virtual bool hasNext() const {
+ return this->checkHasNext();
+ }
+
+ virtual V next() {
+ this->makeNext();
+ return this->currentEntry->getValue();
+ }
+
+ virtual void remove() {
+ throw lang::exceptions::UnsupportedOperationException(
+ __FILE__, __LINE__, "Cannot write to a const Iterator." );
+ }
+ };
+
+ private:
+
+ // Special Set implementation that is backed by this HashMap
+ class HashMapEntrySet : public AbstractSet< MapEntry<K, V> > {
+ private:
+
+ HashMap* associatedMap;
+
+ private:
+
+ HashMapEntrySet(const HashMapEntrySet&);
+ HashMapEntrySet& operator= (const HashMapEntrySet&);
+
+ public:
+
+ HashMapEntrySet(HashMap* parent) : AbstractSet< MapEntry<K,V> >(), associatedMap(parent) {
+ }
+
+ virtual ~HashMapEntrySet() {}
+
+ HashMap* hashMap() {
+ return this->associatedMap;
+ }
+
+ virtual int size() const {
+ return associatedMap->elementCount;
+ }
+
+ virtual void clear() {
+ associatedMap->clear();
+ }
+
+ virtual bool remove(const MapEntry<K,V>& entry) {
+ HashMapEntry* result = associatedMap->getEntry(entry.getKey());
+ if (result != NULL && entry.getValue() == result->getValue()) {
+ associatedMap->removeEntry(result);
+ return true;
+ }
+
+ return false;
+ }
+
+ virtual bool contains(const MapEntry<K,V>& entry) {
+ HashMapEntry* result = associatedMap->getEntry(entry.getKey());
+ if (result != NULL && entry.getValue() == result->getValue()) {
+ return true;
+ }
+ return false;
+ }
+
+ virtual Iterator< MapEntry<K, V> >* iterator() {
+ return new EntryIterator(associatedMap);
+ }
+
+ virtual Iterator< MapEntry<K, V> >* iterator() const {
+ return new ConstEntryIterator(associatedMap);
+ }
+ };
+
+ // Special Set implementation that is backed by this HashMap
+ class ConstHashMapEntrySet : public AbstractSet< MapEntry<K, V> > {
+ private:
+
+ const HashMap* associatedMap;
+
+ private:
+
+ ConstHashMapEntrySet(const ConstHashMapEntrySet&);
+ ConstHashMapEntrySet& operator= (const ConstHashMapEntrySet&);
+
+ public:
+
+ ConstHashMapEntrySet(const HashMap* parent) : AbstractSet< MapEntry<K,V> >(), associatedMap(parent) {
+ }
+
+ virtual ~ConstHashMapEntrySet() {}
+
+ HashMap* hashMap() {
+ return this->associatedMap;
+ }
+
+ virtual int size() const {
+ return associatedMap->elementCount;
+ }
+
+ virtual void clear() {
+ throw decaf::lang::exceptions::UnsupportedOperationException(
+ __FILE__, __LINE__, "Can't clear a const collection");
+ }
+
+ virtual bool remove(const MapEntry<K,V>& entry) {
+ throw decaf::lang::exceptions::UnsupportedOperationException(
+ __FILE__, __LINE__, "Can't remove from const collection");
+ }
+
+ virtual bool contains(const MapEntry<K,V>& entry) {
+ HashMapEntry* result = associatedMap->getEntry(entry.getKey());
+ if (result != NULL && entry.getValue() == result->getValue()) {
+ return true;
+ }
+ return false;
+ }
+
+ virtual Iterator< MapEntry<K, V> >* iterator() {
+ return new ConstEntryIterator(associatedMap);
+ }
+
+ virtual Iterator< MapEntry<K, V> >* iterator() const {
+ return new ConstEntryIterator(associatedMap);
+ }
+ };
+
+ private:
+
+ class HashMapKeySet : public AbstractSet<K> {
+ private:
+
+ HashMap* associatedMap;
+
+ private:
+
+ HashMapKeySet(const HashMapKeySet&);
+ HashMapKeySet& operator= (const HashMapKeySet&);
+
+ public:
+
+ HashMapKeySet(HashMap* parent) : AbstractSet<K>(), associatedMap(parent) {
+ }
+
+ virtual ~HashMapKeySet() {}
+
+ virtual bool contains(const K& key) const {
+ return this->associatedMap->containsKey(key);
+ }
+
+ virtual int size() const {
+ return this->associatedMap->size();
+ }
+
+ virtual void clear() {
+ this->associatedMap->clear();
+ }
+
+ virtual bool remove(const K& key) {
+ HashMapEntry* entry = this->associatedMap->removeEntry(key);
+ if (entry != NULL) {
+ delete entry;
+ return true;
+ }
+ return false;
+ }
+
+ virtual Iterator<K>* iterator() {
+ return new KeyIterator(this->associatedMap);
+ }
+
+ virtual Iterator<K>* iterator() const {
+ return new ConstKeyIterator(this->associatedMap);
+ }
+ };
+
+ private:
+
+ class HashMapValueCollection : public AbstractCollection<V> {
+ private:
+
+ HashMap* associatedMap;
+
+ private:
+
+ HashMapValueCollection(const HashMapValueCollection&);
+ HashMapValueCollection& operator= (const HashMapValueCollection&);
+
+ public:
+
+ HashMapValueCollection(HashMap* parent) : AbstractCollection<V>(), associatedMap(parent) {
+ }
+
+ virtual ~HashMapValueCollection() {}
+
+ virtual bool contains(const V& value) const {
+ return this->associatedMap->containsValue(value);
+ }
+
+ virtual int size() const {
+ return this->associatedMap->size();
+ }
+
+ virtual void clear() {
+ this->associatedMap->clear();
+ }
+
+ virtual Iterator<V>* iterator() {
+ return new ValueIterator(this->associatedMap);
+ }
+
+ virtual Iterator<V>* iterator() const {
+ return new ConstValueIterator(this->associatedMap);
+ }
+ };
+
+ private:
+
/**
* The Hash Code generator for this map's keys.
*/
@@ -145,7 +677,7 @@ namespace util {
private:
void computeThreshold() {
- threshold = (int) (elementData.length() * loadFactor);
+ threshold = (int) ((float) elementData.length() * loadFactor);
}
static int calculateCapacity(int x) {
@@ -156,7 +688,7 @@ namespace util {
if (x == 0) {
return 16;
}
- x = x -1;
+ x = x - 1;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
@@ -173,7 +705,7 @@ namespace util {
HashMap() : AbstractMap<K,V>(), hashFunc(), elementCount(0), elementData(), modCount(0), loadFactor(0.75), threshold(0) {
int capacity = calculateCapacity(12);
elementCount = 0;
- elementData.reset(NULL, capacity);
+ elementData = decaf::lang::ArrayPointer<HashMapEntry*>(capacity);
computeThreshold();
}
@@ -189,7 +721,7 @@ namespace util {
if (capacity >= 0) {
capacity = calculateCapacity(capacity);
elementCount = 0;
- elementData.reset(NULL, capacity);
+ elementData = decaf::lang::ArrayPointer<HashMapEntry*>(capacity);
computeThreshold();
} else {
throw decaf::lang::exceptions::IllegalArgumentException(
@@ -211,7 +743,7 @@ namespace util {
if (capacity >= 0 && loadFactor > 0) {
capacity = calculateCapacity(capacity);
elementCount = 0;
- elementData.reset(NULL, capacity);
+ elementData = decaf::lang::ArrayPointer<HashMapEntry*>(capacity);
this->loadFactor = loadFactor;
computeThreshold();
} else {
@@ -225,17 +757,41 @@ namespace util {
* of the given source Map instance.
*
* @param map
+ * The Map instance whose elements are copied into this HashMap instance.
+ */
+ HashMap(const HashMap<K,V>& map) : AbstractMap<K,V>(), hashFunc(), elementCount(0), elementData(), modCount(0), loadFactor(0.75), threshold(0) {
+ int capacity = calculateCapacity(map.size());
+ elementCount = 0;
+ elementData = decaf::lang::ArrayPointer<HashMapEntry*>(capacity);
+ computeThreshold();
+ putAll(map);
+ }
+
+ /**
+ * Creates a new HashMap with default configuration settings and fills it with the contents
+ * of the given source Map instance.
+ *
+ * @param map
* The Map instance whose elements are copied into this HashMap instance.
*/
HashMap(const Map<K,V>& map) : AbstractMap<K,V>(), hashFunc(), elementCount(0), elementData(), modCount(0), loadFactor(0.75), threshold(0) {
int capacity = calculateCapacity(map.size());
elementCount = 0;
- elementData.reset(NULL, capacity);
+ elementData = decaf::lang::ArrayPointer<HashMapEntry*>(capacity);
computeThreshold();
putAll(map);
}
- virtual ~HashMap() {}
+ virtual ~HashMap() {
+ for (int i = 0; i < elementData.length(); i++) {
+ HashMapEntry* entry = elementData[i];
+ while (entry != NULL) {
+ HashMapEntry* temp = entry;
+ entry = entry->next;
+ delete temp;
+ }
+ }
+ }
public:
@@ -243,8 +799,13 @@ namespace util {
if (elementCount > 0) {
elementCount = 0;
for (int i = 0; i < elementData.length(); ++i) {
- delete elementData[i];
+ HashMapEntry* entry = elementData[i];
elementData[i] = NULL;
+ while (entry != NULL) {
+ HashMapEntry* temp = entry;
+ entry = entry->next;
+ delete temp;
+ }
}
modCount++;
}
@@ -258,9 +819,14 @@ namespace util {
return elementCount;
}
+ virtual bool containsKey(const K& key) const {
+ const HashMapEntry* entry = getEntry(key);
+ return entry != NULL;
+ }
+
virtual bool containsValue(const V& value) const {
for (int i = 0; i < elementData.length(); i++) {
- HashMapEntry* entry = elementData[i];
+ const HashMapEntry* entry = elementData[i];
while (entry != NULL) {
if (value == entry->getValue()) {
return true;
@@ -271,8 +837,144 @@ namespace util {
return false;
}
+ virtual V& get(const K& key) {
+ HashMapEntry* entry = getEntry(key);
+ if (entry != NULL) {
+ return entry->getValue();
+ }
+
+ throw NoSuchElementException(
+ __FILE__, __LINE__, "The specified key is not present in the Map");
+ }
+
+ virtual const V& get(const K& key) const {
+ const HashMapEntry* entry = getEntry(key);
+ if (entry != NULL) {
+ return entry->getValue();
+ }
+
+ throw NoSuchElementException(
+ __FILE__, __LINE__, "The specified key is not present in the Map");
+ }
+
+ virtual void put(const K& key, const V& value) {
+ this->putImpl(key, value);
+ }
+
+ virtual void putAll(const Map<K, V>& map) {
+ if (!map.isEmpty()) {
+ putAllImpl(map);
+ }
+ }
+
+ virtual V remove(const K& key) {
+ HashMapEntry* entry = removeEntry(key);
+ if (entry != NULL) {
+ V oldValue = entry->getValue();
+ delete entry;
+ return oldValue;
+ }
+
+ throw NoSuchElementException(
+ __FILE__, __LINE__, "Specified key not present in the Map.");
+ }
+
+ virtual Set< MapEntry<K,V> >* entrySet() {
+ return new HashMapEntrySet(this);
+ }
+
+ virtual Set< MapEntry<K,V> >* entrySet() const {
+ return new ConstHashMapEntrySet(this);
+ }
+
+ virtual std::vector<K> keySet() const {
+ return std::vector<K>();
+ }
+
+ virtual Set<K>* keySet() {
+ return new HashMapKeySet(this);
+ }
+
+ virtual Collection<V>* values() {
+ return new HashMapValueCollection(this);
+ }
+
+ virtual std::vector<V> values() const {
+ return std::vector<V>();
+ }
+
+ virtual bool equals(const Map<K, V>& source) const {
+ return false;
+ }
+
+ virtual void copy(const Map<K, V>& source) {
+ int capacity = calculateCapacity(source.size());
+ this->clear();
+ if (capacity > elementData.length()) {
+ elementData = decaf::lang::ArrayPointer<HashMapEntry*>(capacity);
+ }
+ computeThreshold();
+ putAll(source);
+ }
+
+ virtual std::string toString() const {
+ return "HashMap";
+ }
+
protected:
+ HashMapEntry* getEntry(const K& key) const {
+ HashMapEntry* result = NULL;
+
+ int hash = hashFunc(key);
+ int index = hash & (elementData.length() - 1);
+ result = findKeyEntry(key, index, hash);
+
+ return result;
+ }
+
+ void putImpl(const K& key, const V& value) {
+
+ HashMapEntry* entry = NULL;
+
+ int hash = hashFunc(key);
+ int index = hash & (elementData.length() - 1);
+
+ entry = findKeyEntry(key, index, hash);
+
+ if (entry == NULL) {
+ modCount++;
+ entry = createHashedEntry(key, index, hash);
+ if (++elementCount > threshold) {
+ rehash();
+ }
+ }
+
+ entry->setValue(value);
+ }
+
+ void putAllImpl(const Map<K, V>& map) {
+ int capacity = elementCount + map.size();
+ if (capacity > threshold) {
+ rehash(capacity);
+ }
+
+ decaf::lang::Pointer<Set< MapEntry<K,V> > > entries(map.entrySet());
+ decaf::lang::Pointer<Iterator< MapEntry<K,V> > > iterator(entries->iterator());
+ while (iterator->hasNext()) {
+ MapEntry<K, V> entry = iterator->next();
+ this->putImpl(entry.getKey(), entry.getValue());
+ }
+ }
+
+ HashMapEntry* findKeyEntry(const K& key, int index, int keyHash) const {
+ HashMapEntry* entry = elementData[index];
+ while (entry != NULL && (entry->origKeyHash != keyHash || !(key == entry->getKey()))) {
+ entry = entry->next;
+ }
+ return entry;
+ }
+
void rehash(int capacity) {
int length = calculateCapacity((capacity == 0 ? 1 : capacity << 1));
@@ -296,6 +998,67 @@ namespace util {
rehash(elementData.length());
}
+ HashMapEntry* createEntry(const K& key, int index, const V& value) {
+ HashMapEntry* entry = new HashMapEntry(key, value);
+ entry->next = elementData[index];
+ elementData[index] = entry;
+ return entry;
+ }
+
+ HashMapEntry* createHashedEntry(const K& key, int index, int hash) {
+ HashMapEntry* entry = new HashMapEntry(key, V(), hash);
+ entry->next = elementData[index];
+ elementData[index] = entry;
+ return entry;
+ }
+
+ // Removes the given entry from the map and deletes it
+ void removeEntry(HashMapEntry* entry) {
+ int index = entry->origKeyHash & (elementData.length() - 1);
+ HashMapEntry* current = elementData[index];
+ if (current == entry) {
+ elementData[index] = entry->next;
+ } else {
+ while (current->next != entry) {
+ current = current->next;
+ }
+ current->next = entry->next;
+ }
+ delete entry;
+ modCount++;
+ elementCount--;
+ }
+
+ // Removes but doesn't delete the entry in the map with the given key.
+ HashMapEntry* removeEntry(const K& key) {
+
+ int index = 0;
+ HashMapEntry* current = NULL;
+ HashMapEntry* last = NULL;
+
+ int hash = hashFunc(key);
+ index = hash & (elementData.length() - 1);
+ current = elementData[index];
+ while (current != NULL && !(current->origKeyHash == hash && key == current->getKey())) {
+ last = current;
+ current = current->next;
+ }
+
+ if (current == NULL) {
+ return NULL;
+ }
+
+ if (last == NULL) {
+ elementData[index] = current->next;
+ } else {
+ last->next = current->next;
+ }
+
+ modCount++;
+ elementCount--;
+ return current;
+ }
+
};
}}
Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Map.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Map.h?rev=1364819&r1=1364818&r2=1364819&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Map.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Map.h Mon Jul 23 22:01:19 2012
@@ -131,7 +131,7 @@ namespace util{
* @param value The Value to look up.
* @return true if this map contains the value, otherwise false.
*/
- virtual bool containsValue( const V& value ) const = 0;
+ virtual bool containsValue(const V& value) const = 0;
/**
* @return if the Map contains any element or not, TRUE or FALSE
@@ -213,6 +213,7 @@ namespace util{
* pointer is owned by the caller.
*/
virtual Set< MapEntry<K,V> >* entrySet() = 0;
+ virtual Set< MapEntry<K,V> >* entrySet() const = 0;
/**
* @return the entire set of keys in this map as a std::vector.
Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/MapEntry.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/MapEntry.h?rev=1364819&r1=1364818&r2=1364819&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/MapEntry.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/MapEntry.h Mon Jul 23 22:01:19 2012
@@ -32,23 +32,32 @@ namespace util {
public:
- MapEntry();
+ MapEntry() : key(), value() {
+ }
- virtual ~MapEntry();
+ virtual ~MapEntry() {};
virtual void setKey(K key) {
this->key = key;
}
- virtual K getKey() const {
+ virtual K& getKey() {
+ return this->key;
+ }
+
+ virtual const K& getKey() const {
return this->key;
}
- virtual void setValue(V value) {
+ virtual void setValue(const V& value) {
this->value = value;
}
- virtual V getValue() const {
+ virtual V& getValue() {
+ return this->value;
+ }
+
+ virtual const V& getValue() const {
return this->value;
}
@@ -57,17 +66,20 @@ namespace util {
return true;
}
- if (this->key != entry.getKey()) {
+ if (!(this->key == entry.getKey())) {
return false;
}
- if (this->value != entry.getValue()) {
+ if (!(this->value != entry.getValue())) {
return false;
}
return true;
}
+ virtual bool operator==(const MapEntry<K, V>& other) const {
+ return this->equals(other);
+ }
};
}}
Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/StlMap.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/StlMap.h?rev=1364819&r1=1364818&r2=1364819&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/StlMap.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/StlMap.h Mon Jul 23 22:01:19 2012
@@ -269,6 +269,10 @@ namespace util{
throw decaf::lang::exceptions::UnsupportedOperationException();
}
+ virtual Set< MapEntry<K, V> >* entrySet() const {
+ throw decaf::lang::exceptions::UnsupportedOperationException();
+ }
+
public:
virtual void lock() {
Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/ConcurrentStlMap.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/ConcurrentStlMap.h?rev=1364819&r1=1364818&r2=1364819&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/ConcurrentStlMap.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/ConcurrentStlMap.h Mon Jul 23 22:01:19 2012
@@ -453,6 +453,10 @@ namespace concurrent{
throw decaf::lang::exceptions::UnsupportedOperationException();
}
+ virtual Set< MapEntry<K, V> >* entrySet() const {
+ throw decaf::lang::exceptions::UnsupportedOperationException();
+ }
+
public:
virtual void lock() {
Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/HashMapTest.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/HashMapTest.cpp?rev=1364819&r1=1364818&r2=1364819&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/HashMapTest.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/HashMapTest.cpp Mon Jul 23 22:01:19 2012
@@ -17,9 +17,31 @@
#include "HashMapTest.h"
+#include <decaf/util/Set.h>
+#include <decaf/util/Iterator.h>
+#include <decaf/util/HashMap.h>
+#include <decaf/util/StlMap.h>
+#include <decaf/util/ArrayList.h>
+#include <decaf/lang/Integer.h>
+#include <decaf/lang/exceptions/IllegalArgumentException.h>
+
using namespace std;
using namespace decaf;
using namespace decaf::util;
+using namespace decaf::lang;
+using namespace decaf::lang::exceptions;
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+ const int MAP_SIZE = 1000;
+
+ void populateMap(HashMap<int, std::string>& hashMap) {
+ for (int i = 0; i < MAP_SIZE; ++i) {
+ hashMap.put(i, Integer::toString(i));
+ }
+ }
+}
////////////////////////////////////////////////////////////////////////////////
HashMapTest::HashMapTest() {
@@ -30,6 +52,518 @@ HashMapTest::~HashMapTest() {
}
////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::setUp() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
void HashMapTest::testConstructor() {
+ HashMap<int, std::string> map;
+ CPPUNIT_ASSERT(map.isEmpty());
+ CPPUNIT_ASSERT_EQUAL(0, map.size());
+ CPPUNIT_ASSERT_EQUAL(false, map.containsKey(1));
+ CPPUNIT_ASSERT_EQUAL(false, map.containsValue("test"));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testConstructorI() {
+
+ HashMap<int, std::string> map(5);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Created incorrect HashMap", 0, map.size());
+
+ try {
+ HashMap<int, std::string> map(-1);
+ CPPUNIT_FAIL("Should have thrown IllegalArgumentException for negative arg.");
+ } catch (IllegalArgumentException& e) {
+ }
+
+ HashMap<int, std::string> empty(0);
+ CPPUNIT_ASSERT_THROW_MESSAGE(
+ "Should have thrown NoSuchElementException",
+ empty.get(1),
+ NoSuchElementException);
+ empty.put(1, "here");
+ CPPUNIT_ASSERT_MESSAGE("cannot get element", empty.get(1) == std::string("here"));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testConstructorIF() {
+
+ HashMap<int, std::string> map(5, 0.5f);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Created incorrect HashMap", 0, map.size());
+
+ try {
+ HashMap<int, std::string> map(0, 0);
+ CPPUNIT_FAIL("Should have thrown IllegalArgumentException for negative arg.");
+ } catch (IllegalArgumentException& e) {
+ }
+
+ HashMap<int, std::string> empty(0, 0.25f);
+ CPPUNIT_ASSERT_THROW_MESSAGE(
+ "Should have thrown NoSuchElementException",
+ empty.get(1),
+ NoSuchElementException);
+ empty.put(1, "here");
+ CPPUNIT_ASSERT_MESSAGE("cannot get element", empty.get(1) == std::string("here"));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testConstructorMap() {
+
+ HashMap<int, int> myMap;
+ for (int counter = 0; counter < 125; counter++) {
+ myMap.put(counter, counter);
+ }
+
+ HashMap<int, int> hashMap(myMap);
+ for (int counter = 0; counter < 125; counter++) {
+ CPPUNIT_ASSERT_MESSAGE("Failed to construct correct HashMap",
+ myMap.get(counter) == hashMap.get(counter));
+ }
+
+// try {
+// Map mockMap = new MockMap();
+// hm = new HashMap(mockMap);
+// fail("Should throw NullPointerException");
+// } catch (NullPointerException e) {
+// //empty
+// }
+//
+// HashMap map = new HashMap();
+// map.put("a", "a");
+// SubMap map2 = new SubMap(map);
+// assertTrue(map2.containsKey("a"));
+// assertTrue(map2.containsValue("a"));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testClear() {
+
+ HashMap<int, std::string> hashMap;
+ hashMap.put(1, "one");
+ hashMap.put(3, "three");
+ hashMap.put(2, "two");
+
+ hashMap.clear();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Clear failed to reset size", 0, hashMap.size());
+ for (int i = 0; i < 125; i++) {
+ CPPUNIT_ASSERT_THROW_MESSAGE(
+ "Failed to clear all elements",
+ hashMap.get(i),
+ NoSuchElementException);
+ }
+
+ // Check clear on a large loaded map of Integer keys
+ HashMap<int, std::string> map;
+ for (int i = -32767; i < 32768; i++) {
+ map.put(i, "foobar");
+ }
+ map.clear();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed to reset size on large integer map", 0, map.size());
+ for (int i = -32767; i < 32768; i++) {
+ CPPUNIT_ASSERT_THROW_MESSAGE(
+ "Failed to clear all elements",
+ map.get(i),
+ NoSuchElementException);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testContainsKey() {
+
+ HashMap<int, std::string> hashMap;
+
+ hashMap.put(876, "test");
+
+ CPPUNIT_ASSERT_MESSAGE("Returned false for valid key", hashMap.containsKey(876));
+ CPPUNIT_ASSERT_MESSAGE("Returned true for invalid key", !hashMap.containsKey(1));
+
+ HashMap<int, std::string> hashMap2;
+ hashMap2.put(0, "test");
+ CPPUNIT_ASSERT_MESSAGE("Failed with key", hashMap2.containsKey(0));
+ CPPUNIT_ASSERT_MESSAGE("Failed with missing key matching hash", !hashMap2.containsKey(1));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testContainsValue() {
+
+ HashMap<int, std::string> hashMap;
+
+ hashMap.put(876, "test");
+
+ CPPUNIT_ASSERT_MESSAGE("Returned false for valid value", hashMap.containsValue("test"));
+ CPPUNIT_ASSERT_MESSAGE("Returned true for invalid valie", !hashMap.containsValue(""));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testEntrySet() {
+
+ HashMap<int, std::string> hashMap;
+
+ for (int i = 0; i < 50; i++) {
+ hashMap.put(i, Integer::toString(i));
+ }
+
+ Pointer< Set<MapEntry<int, std::string> > > set(hashMap.entrySet());
+ Pointer< Iterator<MapEntry<int, std::string> > > iterator(set->iterator());
+
+ CPPUNIT_ASSERT_MESSAGE("Returned set of incorrect size", hashMap.size() == set->size());
+ while (iterator->hasNext()) {
+ MapEntry<int, std::string> entry = iterator->next();
+ CPPUNIT_ASSERT_MESSAGE("Returned incorrect entry set",
+ hashMap.containsKey(entry.getKey()) && hashMap.containsValue(entry.getValue()));
+ }
+
+ iterator.reset(set->iterator());
+ set->remove(iterator->next());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Remove on set didn't take", 49, set->size());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testGet() {
+
+ HashMap<int, std::string> hashMap;
+
+ CPPUNIT_ASSERT_THROW_MESSAGE(
+ "Should have thrown NoSuchElementException",
+ hashMap.get(1),
+ NoSuchElementException);
+ hashMap.put(22, "HELLO");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Get returned incorrect value for existing key",
+ std::string("HELLO"), hashMap.get(22));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testIsEmpty() {
+
+ HashMap<int, std::string> hashMap;
+
+ CPPUNIT_ASSERT_MESSAGE("Returned false for new map", hashMap.isEmpty());
+ hashMap.put(1, "1");
+ CPPUNIT_ASSERT_MESSAGE("Returned true for non-empty", !hashMap.isEmpty());
+ hashMap.clear();
+ CPPUNIT_ASSERT_MESSAGE("Returned false for cleared map", hashMap.isEmpty());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testKeySet() {
+
+ HashMap<int, std::string> hashMap;
+ populateMap(hashMap);
+ Pointer< Set<int> > set(hashMap.keySet());
+ CPPUNIT_ASSERT_MESSAGE("Returned set of incorrect size()", set->size() == hashMap.size());
+ for (int i = 0; i < MAP_SIZE; i++) {
+ CPPUNIT_ASSERT_MESSAGE("Returned set does not contain all keys", set->contains(i));
+ }
+
+ {
+ HashMap<int, std::string> localMap;
+ localMap.put(0, "test");
+ Pointer< Set<int> > intSet(localMap.keySet());
+ CPPUNIT_ASSERT_MESSAGE("Failed with zero key", intSet->contains(0));
+ }
+ {
+ HashMap<int, std::string> localMap;
+ localMap.put(1, "1");
+ localMap.put(102, "102");
+ localMap.put(203, "203");
+
+ Pointer< Set<int> > intSet(localMap.keySet());
+ Pointer< Iterator<int> > it(intSet->iterator());
+ int remove1 = it->next();
+ it->hasNext();
+ it->remove();
+ int remove2 = it->next();
+ it->remove();
+
+ ArrayList<int> list;
+ list.add(1);
+ list.add(102);
+ list.add(203);
+
+ list.remove(remove1);
+ list.remove(remove2);
+
+ CPPUNIT_ASSERT_MESSAGE("Wrong result", it->next() == list.get(0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong size", 1, localMap.size());
+ it.reset(intSet->iterator());
+ CPPUNIT_ASSERT_MESSAGE("Wrong contents", it->next() == list.get(0));
+ }
+ {
+ HashMap<int, std::string> map2(101);
+ map2.put(1, "1");
+ map2.put(4, "4");
+
+ Pointer< Set<int> > intSet(map2.keySet());
+ Pointer< Iterator<int> > it2(intSet->iterator());
+
+ int remove3 = it2->next();
+ int next;
+
+ if (remove3 == 1) {
+ next = 4;
+ } else {
+ next = 1;
+ }
+ it2->hasNext();
+ it2->remove();
+ CPPUNIT_ASSERT_MESSAGE("Wrong result 2", it2->next() == next);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong size 2", 1, map2.size());
+ it2.reset(intSet->iterator());
+ CPPUNIT_ASSERT_MESSAGE("Wrong contents 2", it2->next() == next);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+ class MyKey {
+ private:
+
+ static int COUNTER;
+
+ int id;
+
+ public:
+
+ MyKey() : id(++COUNTER) {
+ }
+
+ int hashCode() const {
+ return 0;
+ }
+
+ bool operator==(const MyKey& key) const {
+ return this->id == key.id;
+ }
+
+ friend std::ostream& operator<<(std::ostream& stream, const MyKey& key);
+ };
+
+ std::ostream& operator<<(std::ostream& stream, const MyKey& key) {
+ stream << "MyKey: " << key.id;
+ return stream;
+ }
+
+ int MyKey::COUNTER = 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace decaf {
+namespace util {
+
+ template<>
+ struct HashCode<MyKey> : public std::unary_function<const MyKey&, int> {
+ int operator()(const MyKey& arg) const {
+ return arg.hashCode();
+ }
+ };
+
+}}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testPut() {
+
+ {
+ HashMap<std::string, std::string> hashMap(101);
+ hashMap.put("KEY", "VALUE");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed to install key/value pair",
+ std::string("VALUE"), hashMap.get("KEY"));
+ }
+ {
+ // Check my actual key instance is returned
+ HashMap<int, std::string> map;
+ for (int i = -32767; i < 32768; i++) {
+ map.put(i, "foobar");
+ }
+ int myKey = 0;
+ // Put a new value at the old key position
+ map.put(myKey, "myValue");
+ CPPUNIT_ASSERT(map.containsKey(myKey));
+ CPPUNIT_ASSERT_EQUAL(std::string("myValue"), map.get(myKey));
+ bool found = false;
+ Pointer< Set<int> > intSet(map.keySet());
+ Pointer< Iterator<int> > itr(intSet->iterator());
+ while (itr->hasNext()) {
+ int key = itr->next();
+ if ((found = key) == myKey) {
+ break;
+ }
+ }
+ CPPUNIT_ASSERT_MESSAGE("Should not find new key instance in hashashMap", !found);
+
+ // Add a new key instance and check it is returned
+ CPPUNIT_ASSERT_NO_THROW(map.remove(myKey));
+ map.put(myKey, "myValue");
+ CPPUNIT_ASSERT(map.containsKey(myKey));
+ CPPUNIT_ASSERT_EQUAL(std::string("myValue"), map.get(myKey));
+ itr.reset(intSet->iterator());
+ while (itr->hasNext()) {
+ int key = itr->next();
+ if ((found = (key == myKey))) {
+ break;
+ }
+ }
+ CPPUNIT_ASSERT_MESSAGE("Did not find new key instance in hashashMap", found);
+ }
+ {
+ // Ensure keys with identical hashcode are stored separately
+ HashMap<MyKey, std::string> map;
+
+ // Put non-equal object with same hashcode
+ MyKey aKey;
+ CPPUNIT_ASSERT(!map.containsKey(aKey));
+ map.put(aKey, "value");
+ MyKey aKey2;
+ CPPUNIT_ASSERT_THROW_MESSAGE(
+ "Should have thrown NoSuchElementException",
+ map.remove(aKey2),
+ NoSuchElementException);
+ MyKey aKey3;
+ map.put(aKey3, "foobar");
+ CPPUNIT_ASSERT_EQUAL(std::string("foobar"), map.get(aKey3));
+ CPPUNIT_ASSERT_EQUAL(std::string("value"), map.get(aKey));
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testPutAll() {
+
+ HashMap<int, std::string> hashMap;
+ populateMap(hashMap);
+
+ HashMap<int, std::string> hashMap2;
+ hashMap2.putAll(hashMap);
+ for (int i = 0; i < 1000; i++) {
+ CPPUNIT_ASSERT_MESSAGE("Failed to put all elements into new Map",
+ hashMap2.get(i) == Integer::toString(i));
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testRemove() {
+
+ {
+ HashMap<int, std::string> hashMap;
+ populateMap(hashMap);
+
+ int size = hashMap.size();
+ CPPUNIT_ASSERT_NO_THROW_MESSAGE("Remove returned incorrect value", hashMap.remove(9));
+ CPPUNIT_ASSERT_THROW_MESSAGE(
+ "Should have thrown a NoSuchElementException on get of non-existent key.",
+ hashMap.get(9),
+ NoSuchElementException);
+
+ CPPUNIT_ASSERT_MESSAGE("Failed to decrement size", hashMap.size() == (size - 1));
+ CPPUNIT_ASSERT_THROW_MESSAGE(
+ "Should have thrown a NoSuchElementException on remove of non-existent key.",
+ hashMap.remove(9),
+ NoSuchElementException);
+ }
+ {
+ HashMap<int, std::string> hashMap;
+ for (int i = 0; i < 8192; i++) {
+ hashMap.put(i, "const");
+ }
+ for (int i = 0; i < 8192; i++) {
+ hashMap.put(i, Integer::toString(i));
+ }
+ for (int i = 8191; i >= 0; i--) {
+ std::string iValue = Integer::toString(i);
+ CPPUNIT_ASSERT_MESSAGE(std::string("Failed to replace value: ") + iValue,
+ hashMap.containsValue(iValue));
+ hashMap.remove(i);
+ CPPUNIT_ASSERT_MESSAGE(std::string("Failed to remove same value: ") + iValue,
+ !hashMap.containsValue(iValue));
+ }
+ }
+
+ {
+ // Ensure keys with identical hashcode are stored separately and removed correctly.
+ HashMap<MyKey, std::string> map;
+
+ // Put non-equal object with same hashcode
+ MyKey aKey;
+ CPPUNIT_ASSERT(!map.containsKey(aKey));
+ map.put(aKey, "value");
+ MyKey aKey2;
+ CPPUNIT_ASSERT_THROW_MESSAGE(
+ "Should have thrown NoSuchElementException",
+ map.remove(aKey2),
+ NoSuchElementException);
+ MyKey aKey3;
+ map.put(aKey3, "foobar");
+ CPPUNIT_ASSERT_EQUAL(std::string("foobar"), map.get(aKey3));
+ CPPUNIT_ASSERT_EQUAL(std::string("value"), map.get(aKey));
+ map.remove(aKey);
+ map.remove(aKey3);
+ CPPUNIT_ASSERT(!map.containsKey(aKey));
+ CPPUNIT_ASSERT(map.isEmpty());
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testRehash() {
+ // This map should rehash on adding the ninth element.
+ HashMap<MyKey, int> hashMap(10, 0.5f);
+
+ // Ordered set of keys.
+ MyKey keyOrder[9];
+
+ // Store eight elements
+ for (int i = 0; i < 8; i++) {
+ hashMap.put(keyOrder[i], i);
+ }
+
+ // Check expected ordering (inverse of adding order)
+ Pointer< Set<MyKey> > keySet(hashMap.keySet());
+ std::vector<MyKey> returnedKeys = keySet->toArray();
+ for (int i = 0; i < 8; i++) {
+ CPPUNIT_ASSERT_EQUAL(keyOrder[i], returnedKeys[7 - i]);
+ }
+
+ // The next put causes a rehash
+ hashMap.put(keyOrder[8], 8);
+ // Check expected new ordering (adding order)
+ returnedKeys = keySet->toArray();
+ for (int i = 0; i < 9; i++) {
+ CPPUNIT_ASSERT_EQUAL(keyOrder[i], returnedKeys[i]);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testSize() {
+ HashMap<int, std::string> hashMap;
+ populateMap(hashMap);
+
+ CPPUNIT_ASSERT_MESSAGE("Returned incorrect size", hashMap.size() == MAP_SIZE);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testValues() {
+
+ HashMap<int, std::string> hashMap;
+ populateMap(hashMap);
+
+ Pointer< Collection<std::string> > c(hashMap.values());
+ CPPUNIT_ASSERT_MESSAGE("Returned collection of incorrect size()", c->size() == hashMap.size());
+ for (int i = 0; i < MAP_SIZE; i++) {
+ CPPUNIT_ASSERT_MESSAGE("Returned collection does not contain all keys",
+ c->contains(Integer::toString(i)));
+ }
+
+ c->remove("10");
+ CPPUNIT_ASSERT_MESSAGE("Removing from collection should alter Map",
+ !hashMap.containsKey(10));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void HashMapTest::testToString() {
+
+ HashMap<int, std::string> hashMap;
+ populateMap(hashMap);
+ std::string result = hashMap.toString();
+ CPPUNIT_ASSERT_MESSAGE("should return something", result != "");
}
Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/HashMapTest.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/HashMapTest.h?rev=1364819&r1=1364818&r2=1364819&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/HashMapTest.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/HashMapTest.h Mon Jul 23 22:01:19 2012
@@ -28,6 +28,23 @@ namespace util {
CPPUNIT_TEST_SUITE( HashMapTest );
CPPUNIT_TEST( testConstructor );
+ CPPUNIT_TEST( testConstructorI );
+ CPPUNIT_TEST( testConstructorIF );
+ CPPUNIT_TEST( testConstructorMap );
+ CPPUNIT_TEST( testClear );
+ CPPUNIT_TEST( testContainsKey );
+ CPPUNIT_TEST( testContainsValue );
+ CPPUNIT_TEST( testEntrySet );
+ CPPUNIT_TEST( testGet );
+ CPPUNIT_TEST( testPut );
+ CPPUNIT_TEST( testRemove );
+ CPPUNIT_TEST( testIsEmpty );
+ CPPUNIT_TEST( testKeySet );
+ CPPUNIT_TEST( testPutAll );
+ CPPUNIT_TEST( testRehash );
+ CPPUNIT_TEST( testSize );
+ CPPUNIT_TEST( testValues );
+ CPPUNIT_TEST( testToString );
CPPUNIT_TEST_SUITE_END();
public:
@@ -35,7 +52,26 @@ namespace util {
HashMapTest();
virtual ~HashMapTest();
+ virtual void setUp();
+
void testConstructor();
+ void testConstructorI();
+ void testConstructorIF();
+ void testConstructorMap();
+ void testClear();
+ void testContainsKey();
+ void testContainsValue();
+ void testEntrySet();
+ void testGet();
+ void testPut();
+ void testRemove();
+ void testIsEmpty();
+ void testKeySet();
+ void testPutAll();
+ void testRehash();
+ void testSize();
+ void testValues();
+ void testToString();
};
Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/StlMapTest.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/StlMapTest.cpp?rev=1364819&r1=1364818&r2=1364819&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/StlMapTest.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/StlMapTest.cpp Mon Jul 23 22:01:19 2012
@@ -246,6 +246,10 @@ public:
throw decaf::lang::exceptions::UnsupportedOperationException();
}
+ virtual Set< MapEntry<K, V> >* entrySet() const {
+ throw decaf::lang::exceptions::UnsupportedOperationException();
+ }
+
public:
virtual void lock() {