blob: 8a9552a9e2ea4555cf79198b52857be49524be32 [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 __LIST_H__
#define __LIST_H__
#include "capu/Error.h"
#include "capu/Config.h"
#include "capu/container/Comparator.h"
namespace capu {
template <class T, class C = Comparator >
class List {
class ListNode {
public:
ListNode() {
mNext = NULL;
mPrev = NULL;
}
ListNode(T data) {
mNext = NULL;
mPrev = NULL;
this->mData = data;
}
T mData;
ListNode * mNext;
ListNode * mPrev;
};
class ListIterator {
public:
friend class List<T, C>;
/**
* Default Constructor
*/
ListIterator();
/**
* constructor
* @param initial_node where the iterator will be pointing
*/
ListIterator(ListNode *initialNode);
/**
* destructor
*/
~ListIterator();
/**
* Check if iterator has next element.
* @return false if the next of current node that is pointed, is null otherwise true
*/
bool_t hasNext();
/**
* Shifts the iterator to the next position and returns the element if next != NULL
* @param element
* @return ETCH_ERANGE if the next of current node that is pointed, is null
* CAPU_OK if the next element has been gotten
*
*/
status_t next(T* element = NULL);
/**
* Get current iterator element.
* @param element
* @return ETCH_ERANGE if the current node that is pointed, is null
* CAPU_EINVAL if the value is NULL
* CAPU_OK if the current element has been gotten
*
*/
status_t current(T* element);
private:
ListNode *mNextPosition;
};
ListNode *mHead;
ListNode *mTail;
int_t mSize;
public:
typedef typename List<T, C>::ListIterator Iterator;
/**
* Default Constructor
*/
List();
/**
* Destructor
*/
virtual ~List();
/**
* Add element to the end of list
* @param element element that will be added
* @return CAPU_ENO_MEMORY if allocation of element is failed
* CAPU_OK if the element is successfully added
*/
status_t add(const T &element);
/**
* Add element to specified position
*
* @param index index of element which will be inserted
* @param element new value that will replace the old value
*
* @return CAPU_EINVAL if given index is invalid.
* CAPU_ENO_MEMORY if allocation of element is failed
* CAPU_OK if the element is successfully added
* CAPU_ERROR otherwise
*/
status_t add(int_t index, const T &element);
/**
* Add element to specified position
*
* @param iterator with the position to insert
* @param element new value that will replace the old value
*
* @return CAPU_ENO_MEMORY memory allocation failed.
* CAPU_OK otherwise
*/
status_t add(Iterator& iter, const T &element);
/**
* remove the element in the specified index and if the element_old
* parameter is not NULL, the removed element will be put to element_old
* @param index index of element that will be removed
* @param elementOld the buffer which will keep the copy of the removed element
* @return CAPU_EINVAL invalid index
* CAPU_OK if the element is successfully removed
*/
status_t removeAt(int_t index, T* elementOld = NULL);
/**
* remove the element in the specified iterator position and if the element_old
* parameter is not NULL, the removed element will be put to element_old
* @param iterator of element that will be removed
* @param element_old the buffer which will keep the copy of the removed element
* @return CAPU_EINVAL invalid iterator
* CAPU_OK if the element is successfully removed
*
*/
status_t removeAt(Iterator& listIterator, T* elementOld = NULL);
/**
* get a single element on specified index
* @param index index of element that will be get
* @param result the buffer that the retrieved element will be stored
* @return CAPU_EINVAL invalid index
* CAPU_OK otherwise
*/
status_t get(int_t index, T* result);
/**
* return size of list
* @return return the size of list
*/
int_t size();
/**
* check the list is empty or not
* @return true if empty
* false otherwise
*/
bool_t isEmpty();
/**
* returns an iterator pointing to the beginning of list
* @return iterator
*/
Iterator begin() const;
/**
* finds the index of given element in the link list
* if you are using an object you need to overload == operator
*
* @param element the value that will be searched
* @return -1 if the value either does not exist or given value is NULL
* otherwise index of value on linked list
*/
int_t find(const T &element);
/**
*
* @param index the index of element that will be replaced
* @param element element that will be overwritten to existing place
* @param elementOld the buffer to keep the existing
* @return CAPU_EINVAL if the index is not valid
* CAPU_OK otherwise
*/
status_t set(int_t index, const T &element, T* elementOld = NULL);
/**
* check that if the list contains the given parameter or not
* if you are using an object you need to overload == operator
* @param element element that will be checked
* @return true list contains it
* false otherwise
*/
bool_t contains(const T &element);
/**
* removes all elements from linked list
*
* @return CAPU_OK if all of the elements are deleted
*
*/
status_t clear();
};
template <class T, class C>
List<T, C>::List()
: mHead(NULL),
mTail(NULL),
mSize(0) {
//init linked list
}
template <class T, class C>
List<T, C>::~List() {
clear();
}
template <class T, class C>
status_t List<T, C>::clear() {
//on the deallocation delete all elements in the list
ListNode *cursor = mHead;
ListNode *tmp = NULL;
while (cursor != NULL) {
tmp = cursor;
cursor = cursor->mNext;
delete tmp;
}
mSize = 0;
mHead = NULL;
mTail = NULL;
return CAPU_OK;
}
template <class T, class C>
int_t List<T, C>::find(const T &element) {
int_t counter = 0;
ListNode * cursor = mHead;
C comparator;
while (cursor != NULL) {
if (comparator(cursor->mData, element)) {
return counter;
}
cursor = cursor->mNext;
++counter;
}
return -1;
}
template <class T, class C>
bool_t List<T, C>::contains(const T &element) {
return (find(element) != -1);
}
//add elements to the end of list
template <class T, class C>
status_t List<T, C>::add(const T &element) {
ListNode *listElem = new ListNode(element);
//NOT ALLOCATED
if (listElem == NULL) {
return CAPU_ENO_MEMORY;
}
//list is empty
if (mHead == NULL) {
mHead = listElem;
mTail = mHead;
} else {
//list contains some elements so add it to the end of list
mTail->mNext = listElem;
listElem->mPrev = mTail;
mTail = listElem;
mTail->mNext = NULL;
}
++mSize;
return CAPU_OK;
}
template <class T, class C>
status_t List<T, C>::add(int_t index, const T &element) {
if ((index > mSize) || (index < 0)) {
return CAPU_EINVAL;
}
ListNode *listElem = new ListNode(element);
//NOT ALLOCATED
if (listElem == NULL) {
return CAPU_ENO_MEMORY;
}
int_t counter = 0;
ListNode * cursor = mHead;
if (cursor == NULL) {
//empty list
mHead = listElem;
mTail = listElem;
mHead->mPrev = NULL;
mTail->mNext = NULL;
++mSize;
return CAPU_OK;
} else if (index == mSize) {
//list contains some elements so add it to the end of list
mTail->mNext = listElem;
listElem->mPrev = mTail;
mTail = listElem;
mTail->mNext = NULL;
++mSize;
return CAPU_OK;
} else if (index == 0) {
//add it to beginning of the list
listElem->mNext = mHead;
mHead->mPrev = listElem;
listElem->mPrev = NULL;
mHead = listElem;
++mSize;
return CAPU_OK;
}
while (cursor != NULL) {
if (index == counter) {
listElem->mNext = cursor;
listElem->mPrev = cursor->mPrev;
if (cursor->mPrev != NULL)
cursor->mPrev->mNext = listElem;
cursor->mPrev = listElem;
++mSize;
return CAPU_OK;
}
++counter;
cursor = cursor->mNext;
}
return CAPU_ERROR;
}
template <class T, class C>
status_t List<T, C>::add(Iterator& iter, const T &element) {
ListNode *listElem = new ListNode(element);
//NOT ALLOCATED
if (listElem == NULL) {
return CAPU_ENO_MEMORY;
}
if (mHead == NULL && mTail == NULL) {
mHead = listElem;
mTail = mHead;
} else if (iter.mNextPosition == NULL) {
listElem->mNext = NULL;
listElem->mPrev = mTail;
mTail->mNext = listElem;
mTail = listElem;
} else if (iter.mNextPosition->mNext == NULL) {
listElem->mNext = NULL;
listElem->mPrev = iter.mNextPosition;
iter.mNextPosition->mNext = listElem;
mTail = listElem;
} else if (iter.mNextPosition->mPrev == NULL) {
listElem->mPrev = NULL;
listElem->mNext = iter.mNextPosition;
mHead = listElem;
} else {
listElem->mPrev = iter.mNextPosition->mPrev;
listElem->mNext = iter.mNextPosition;
iter.mNextPosition->mPrev->mNext = listElem;
}
iter.mNextPosition = listElem;
++mSize;
return CAPU_OK;
}
//remove the specific element indicated by the index in the list
template <class T, class C>
status_t List<T, C>::removeAt(int_t index, T* elementOld) {
if ((index < 0) || (index >= mSize)) {
return CAPU_EINVAL;
}
ListNode * tmp = NULL;
if (mHead == mTail) {
tmp = mHead;
mHead = NULL;
mTail = NULL;
} else if (index == 0) {
tmp = mHead;
mHead = mHead->mNext;
mHead->mPrev = NULL;
} else if (index == mSize - 1) {
tmp = mTail;
mTail = mTail->mPrev;
mTail->mNext = NULL;
} else {
tmp = mHead;
for (int_t i = 0; i < index; ++i) {
tmp = tmp->mNext;
}
tmp->mNext->mPrev = tmp->mPrev;
tmp->mPrev->mNext = tmp->mNext;
}
if (elementOld != NULL)
*elementOld = tmp->mData;
delete tmp;
mSize--;
return CAPU_OK;
}
template <class T, class C>
status_t List<T, C>::removeAt(Iterator& listIterator, T* elementOld) {
ListNode* tmp = NULL;
if (mHead == mTail) {
tmp = mHead;
if (!tmp) {
return CAPU_EINVAL;
}
mHead = NULL;
mTail = NULL;
listIterator.mNextPosition = NULL;
} else if (listIterator.mNextPosition == mHead) {
tmp = mHead;
mHead = mHead->mNext;
mHead->mPrev = NULL;
listIterator.mNextPosition = mHead;
} else if (listIterator.mNextPosition == mTail) {
tmp = mTail;
mTail = mTail->mPrev;
mTail->mNext = NULL;
listIterator.mNextPosition = mTail;
} else {
tmp = listIterator.mNextPosition;
listIterator.mNextPosition->mPrev->mNext = listIterator.mNextPosition->mNext;
listIterator.mNextPosition->mNext->mPrev = listIterator.mNextPosition->mPrev;
listIterator.mNextPosition = listIterator.mNextPosition->mPrev;
}
if (elementOld != 0) {
*elementOld = tmp->mData;
}
delete tmp;
mSize--;
return CAPU_OK;
}
//get the specified element from list
template <class T, class C>
status_t List<T, C>::get(int_t index, T* result) {
if (((index < 0) || (index >= mSize)) || (result == NULL)) {
return CAPU_EINVAL;
}
if (index == 0) {
*result = mHead->mData;
return CAPU_OK;
} else if (index == mSize - 1) {
*result = mTail->mData;
return CAPU_OK;
}
ListNode *cursor = mHead;
for (int_t i = 0; i < index; ++i) {
cursor = cursor->mNext;
}
*result = cursor->mData;
return CAPU_OK;
}
template <class T, class C>
status_t List<T, C>::set(int_t index, const T &element, T* elementOld) {
if ((index < 0) || (index >= mSize))
return CAPU_EINVAL;
ListNode *cursor = mHead;
for (int_t i = 0; i < index; ++i) {
cursor = cursor->mNext;
}
if (elementOld != NULL)
*elementOld = cursor->mData;
cursor->mData = element;
return CAPU_OK;
}
//Return element count of list
template <class T, class C>
int_t List<T, C>::size() {
return mSize;
}
//checks if the list is empty or not
template <class T, class C>
bool_t List<T, C>::isEmpty() {
if (mSize == 0)
return true;
else
return false;
}
template <class T, class C>
typename List<T, C>::Iterator List<T, C>::begin() const {
return ListIterator(mHead);
}
template <class T, class C>
List<T, C>::ListIterator::ListIterator()
: mNextPosition(NULL) {
}
template <class T, class C>
List<T, C>::ListIterator::~ListIterator() {
}
template <class T, class C>
List<T, C>::ListIterator::ListIterator(ListNode *initialNode) {
mNextPosition = initialNode;
}
template <class T, class C>
bool_t List<T, C>::ListIterator::hasNext() {
if (mNextPosition == NULL) {
return false;
}
return true;
}
template <class T, class C>
status_t List<T, C>::ListIterator::next(T* element) {
T* result = 0;
if (mNextPosition == NULL) {
return CAPU_ERANGE;
} else {
result = &mNextPosition->mData;
mNextPosition = mNextPosition->mNext;
}
if (element != NULL) {
*element = *result;
}
return CAPU_OK;
}
template <class T, class C>
status_t List<T, C>::ListIterator::current(T* value) {
if (mNextPosition == 0) {
return CAPU_ERANGE;
} else if (value == 0) {
return CAPU_EINVAL;
} else {
*value = mNextPosition->mData;
return CAPU_OK;
}
}
}
#endif /* __LIST_H__ */