blob: 93a31d0982976206c1ddb4af4cf97b83ebf9ec02 [file] [log] [blame]
/* $Id$
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version
* 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __HASHSET_H__
#define __HASHSET_H__
#include "capu/container/Comparator.h"
#include "capu/container/Hash.h"
#include "capu/container/List.h"
namespace capu {
template <class T, class C = Comparator, class H = Hash >
class HashSet {
private:
class HashSetIterator {
public:
/**
* constructor
*
* @param list array of linked list which provide channing for hash set
* @param listSize size of hash set (size of linked list array)
*/
HashSetIterator(List<T, C> * list, uint_t listSize);
/**
* destructor
*/
~HashSetIterator();
/**
* Check if iterator has next element.
* @return false if the next of current node that is pointed, is null otherwise true
*/
bool_t hasNext();
/**
* Get next iterator element.
* @param value
* @return CAPU_ERANGE if the next of current node that is pointed, is null
* CAPU_EINVAL if the value is NULL
* CAPU_OK if the next element has been gotten
*
*/
status_t next(T* value);
private:
uint_t mCurrentListIndex;
typename List<T, C>::Iterator mCurrentListIterator;
List<T, C> * mList;
uint_t mMaxListSize;
};
public:
typedef HashSetIterator Iterator;
/**
* Default Constructor
*/
HashSet();
/**
* Parameterized Constructor
* @param size size of initial HashSet
*/
HashSet(uint_t size);
/**
* Destructor
*/
~HashSet();
/**
* put a new value to the hash set.
*
* @param value new value that will be put to hash set
*
* @return CAPU_OK if remove is successful
* CAPU_ERROR if value already exists in the set
*
*/
status_t put(const T &value);
/**
* Remove value associated with key in the hash set.
*
* @param value value that will be removed
*
* @return CAPU_OK if remove is successful
* CAPU_ERANGE if specified value does not exist in hash set
*
*/
status_t remove(const T &value);
/**
* Checks if the provided value is already contained in the hash set.
*
* @param value value that will be checked
*
* @return true if element is already contained in the hash set
* false otherwise
*
*/
bool_t hasElement(const T &value);
/**
* Returns count of the hash set.
* @return number of element in hash set
*/
uint_t count();
/**
* Clear all values of the hash set.
*
* @return CAPU_OK if all elements in list have been deleted
*/
status_t clear();
/**
* Return iterator for iterating key value tuples.
* @return Iterator
*/
Iterator begin();
private:
/**
* internally used function to check the same key exist in the specified linked list
*
* @param index specify which link list will be checked
* @param k specify which key will be searched
* @return -1 if the key is unique
* otherwise the index in the linked list
*/
int_t __check_duplicate_value(uint_t index, T k) {
int_t count = 0;
typename List<T, C>::Iterator it = mLists[index].begin();
T tmp;
C compare;
while (it.hasNext()) {
it.next(&tmp);
//NOT UNIQUE VALUE
if (compare(tmp, k))
return count;
count++;
}
//UNIQUE VALUE
return -1;
}
List<T, C> *mLists;
uint_t mSize;
uint_t mCount;
};
template <class T, class C, class H>
HashSet<T, C, H>::HashSet()
: mSize(HASH_SET_DEFAULT_SIZE)
, mCount(0) {
mLists = new List<T, C>[mSize];
}
template <class T, class C, class H>
HashSet<T, C, H>::~HashSet() {
delete [] mLists;
}
template <class T, class C, class H>
HashSet<T, C, H>::HashSet(uint_t size)
: mSize(size)
, mCount(0) {
mLists = new List<T, C>[mSize];
}
template <class T, class C, class H>
status_t HashSet< T, C, H>::put(const T &value) {
status_t result;
uint_t index = H::Digest(value) % mSize;
if (mLists[index].isEmpty()) {
result = mLists[index].add(value);
if (result != CAPU_OK) {
return result;
}
mCount++;
//THERE IS NO OLD VALUE
} else {
int_t key_duplicate_index = this->__check_duplicate_value(index, value);
if (key_duplicate_index < 0) {
result = mLists[index].add(value);
if (result != CAPU_OK) {
return result;
}
mCount++;
//THERE IS NO OLD VALUE
} else {
//THERE IS A NEW VALUE
return CAPU_ERROR;
}
}
return CAPU_OK;
}
template <class T, class C, class H>
status_t HashSet< T, C, H>::remove(const T &value) {
status_t result;
uint_t index = H::Digest(value) % mSize;
int_t key_index = this->__check_duplicate_value(index, value);
if (key_index < 0) {
return CAPU_ERANGE;
} else {
//delete the existing file
result = mLists[index].removeAt(key_index);
if (result != CAPU_OK) {
return result;
}
mCount--;
}
return CAPU_OK;
}
template <class T, class C, class H>
bool_t HashSet< T, C, H>::hasElement(const T &value) {
uint_t index = H::Digest(value) % mSize;
int_t key_index = this->__check_duplicate_value(index, value);
if (key_index < 0) {
return false;
} else {
return true;
}
}
template <class T, class C, class H>
uint_t HashSet< T, C, H>::count() {
return mCount;
}
template <class T, class C, class H>
status_t HashSet< T, C, H>::clear() {
for (uint_t i = 0; i < mSize; ++i) {
mLists[i].clear();
}
mCount = 0;
return CAPU_OK;
}
template <class T, class C, class H>
HashSet< T, C, H>::HashSetIterator::HashSetIterator(List<T, C> * list, uint_t list_size)
: mCurrentListIndex(0), mCurrentListIterator(list[0].begin()), mList(list), mMaxListSize(list_size) {
//to point the first non-empty one
for (uint_t i = 0; i < list_size; ++i) {
if (!mList[i].isEmpty()) {
mCurrentListIndex = i;
this->mCurrentListIterator = list[i].begin();
break;
}
}
}
template <class T, class C, class H>
HashSet< T, C, H>::HashSetIterator::~HashSetIterator() {
}
template <class T, class C, class H>
bool_t HashSet< T, C, H>::HashSetIterator::hasNext() {
if (mCurrentListIterator.hasNext()) {
return true;
} else {
do {
mCurrentListIndex++;
if (mCurrentListIndex >= mMaxListSize) {
return false;
}
} while (mList[mCurrentListIndex].isEmpty());
if (mCurrentListIndex < mMaxListSize) {
return true;
} else {
return false;
}
}
}
template <class T, class C, class H>
status_t HashSet< T, C, H>::HashSetIterator::next(T* value) {
if (value == NULL) {
return CAPU_EINVAL;
} else if (mCurrentListIndex >= mMaxListSize) {
return CAPU_ERANGE;
} else {
status_t result = mCurrentListIterator.next(value);
if (result != CAPU_OK)
return result;
if (!mCurrentListIterator.hasNext()) {
do {
mCurrentListIndex++;
if (mCurrentListIndex >= mMaxListSize) {
break;
}
} while (mList[mCurrentListIndex].isEmpty());
if (mCurrentListIndex < mMaxListSize) {
mCurrentListIterator = mList[mCurrentListIndex].begin();
}
}
}
return CAPU_OK;
}
template <class T, class C, class H>
typename HashSet<T, C, H>::Iterator HashSet<T, C, H>::begin() {
return typename HashSet<T, C, H>::Iterator(mLists, mSize);
}
}
#endif /* HASHSET_H */