%% options copyright owner = Dirk Krause copyright year = 2013-xxxx license = bsd %% header #include #include #include #include #include "Dk4Comparable.h" namespace DkTools4 { template class Container; template class Iterator; /** A container class for sorted storage. The objects must be derived from the Comparable class. */ template class Container { friend class Iterator; private: /** Storage to store elements. */ dk4_sto_t *sto; /** Iterator, used in destructor. */ dk4_sto_it_t *it; /** Comparison criteria for ordering elements. */ int cr; /** Flag: Container is owner of the objects and in charge for destruction. */ bool bOwner; public: /** Create container. @param crit Sort criteria for objects in container. @param owner Owner flag value. If a container is the owner of the objects stored in it, the objects are deleted in the containers destructor. */ Container(int crit, bool owner = false) throw (std::bad_alloc); /** Destructor. */ ~Container(); /** Add an object to the container. @param ptr Pointer to add. @return True on success, false on error (object not added). */ bool add(T *ptr); /** Remove object from container. @param ptr Pointer to remove. @return True on success, false on error. */ bool remove(T *ptr); /** Check owner flag. @return Owner flag value. */ void isOwner(void) const; /** Reset iterator. */ void reset(void); /** Set iterator to exact position. @param data @param crit @return Pointer to found object on success, NULL otherwise. */ T * findExact(void const *data, int crit); /** Set iterator to object evaluating equally. @param data @param crit @return Pointer to found object on success, NULL otherwise. */ T * findLike(void const *data, int crit); /** Step to next element. @return Pointe to next object (if there is one), NULL if there is no next object. */ T * next(void); }; /* End of class Container */ /** An iterator class to traverse a Containter. */ template class Iterator { private: /** Low-level iterator. */ dk4_sto_it_t *it; public: /** Constructor. @param cont Container for which the iterator is for. */ Iterator(Container& cont) throw (std::bad_alloc); /** Destructor. */ ~Iterator(); /** Reset iterator. */ void reset(void); /** Set iterator to exact position. @param data @param crit @return Pointer to found object on success, NULL otherwise. */ T * findExact(void const *data, int crit); /** Set iterator to object evaluating equally. @param data @param crit @return Pointer to found object on success, NULL otherwise. */ T * findLike(void const *data, int crit); /** Step to next element. @return Pointe to next object (if there is one), NULL if there is no next object. */ T * next(void); }; /* End of class Iterator */ } /* End of namespace DkTools4 */ $* Implementation for container methods. $* template DkTools4::Container::Container(int crit, bool owner) throw (std::bad_alloc) { bool mustThrow = true; bOwner = owner; cr = crit; it = NULL; sto = dk4sto_open(NULL); if(NULL != sto) { dk4sto_set_comp(sto,DkTools4::Comparable::compareTwoPointers,crit); it = dk4sto_it_open(sto, NULL); if (NULL != it) { mustThrow = false; } else { dk4sto_close(sto); sto = NULL; } } if (mustThrow) { throw(std::bad_alloc()); } } /* The destructor is also called when an exception is thrown by the constructor. So we must check the sto and it component for being not NULL. */ template DkTools4::Container::~Container() { T *ptr; if (NULL != it) { if (bOwner) { dk4sto_it_reset(it); while(NULL != (ptr = (T *)dk4sto_it_next(it))) { delete ptr; } } dk4sto_it_close(it); } if (NULL != sto) { dk4sto_close(sto); } sto = NULL; it = NULL; cr = 0; bOwner = false; } /* The remaining container methods are not called if there was an exception from the constructor. So no NULL pointer checks are necessary here. */ template bool DkTools4::Container::add(T *ptr) { bool back = false; if(0 != dk4sto_add(sto, (void *)ptr, NULL)) { back = true; } return back; } template bool DkTools4::Container::remove(T *ptr) { bool back = false; if(0 != dk4sto_remove(sto, (void *)ptr, NULL)) { back = true; } return back; } template void DkTools4::Container::isOwner(void) const { return bOwner; } /* The remaining iterator methods are not invoked if the constructor throws an exception, so we do not need to check the it component. */ template void DkTools4::Container::reset(void) { dk4sto_it_reset(it); } template T * DkTools4::Container::findExact(void const *data, int crit) { T *back = NULL; back = (T *)dk4sto_it_find_exact(it, data); return back; } template T * DkTools4::Container::findLike(void const *data, int crit) { T *back; back = (T *)dk4sto_it_find_like(it, data, crit); return back; } template T * DkTools4::Container::next(void) { T *back = NULL; back = (T *)dk4sto_it_next(it); return back; } $* Implementation for iterator methods. $* template DkTools4::Iterator::Iterator(Container& cont) throw (std::bad_alloc) { it = dk4sto_it_open(cont.sto, NULL); if(NULL != it) { dk4sto_it_reset(it); } else { throw(std::bad_alloc()); } } /* The iterators destructor is also invoked if the constructor throws an exception. So we must check the it component to be not NULL. */ template DkTools4::Iterator::~Iterator() { if (NULL != it) { dk4sto_it_close(it); it = NULL; } } /* The remaining iterator methods are not invoked if the constructor throws an exception, so we do not need to check the it component. */ template void DkTools4::Iterator::reset(void) { dk4sto_it_reset(it); } template T * DkTools4::Iterator::findExact(void const *data, int crit) { T *back = NULL; back = (T *)dk4sto_it_find_exact(it, data); return back; } template T * DkTools4::Iterator::findLike(void const *data, int crit) { T *back; back = (T *)dk4sto_it_find_like(it, data, crit); return back; } template T * DkTools4::Iterator::next(void) { T *back = NULL; back = (T *)dk4sto_it_next(it); return back; }