/* * * Copyright (C) 2002-2011, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by * * OFFIS e.V. * R&D Division Health * Escherweg 2 * D-26121 Oldenburg, Germany * * * Module: ofstd * * Author: Thomas Wilkens * * Purpose: Template class for administrating an ordered set of elements * of an arbitrary type. * */ #ifndef OFOrderedSet_h #define OFOrderedSet_h #include "dcmtk/config/osconfig.h" #include "dcmtk/ofstd/oftypes.h" #include "dcmtk/ofstd/ofset.h" /** This template class provides a data structure and operations for administrating an * ordered set of elements of an arbitrary type. Note the following properties of this * class: * - an element which is inserted into the set will be copied * - the datatype of the set's elements has to support operator== so that it is possible * to find a certain element * - it is allowed to insert identical elements into the set * - if a user requires to remove a certain element and if there are several elements * which are identical to this element, only one element will be removed from the set * - when removing an element, the indeces of the elements behind the removed element will * be reduced by one * - the set will be ordered according to the point in time at which an element is inserted * into the set; a new element will always be inserted at the end of the set */ template class OFOrderedSet : public OFSet { protected: public: /** Default constructor. */ OFOrderedSet() : OFSet() { } /** Copy constructor. * @param src Source object of which this will be a copy. */ OFOrderedSet( const OFOrderedSet &src ) : OFSet( src ) { } /** Destructor. */ virtual ~OFOrderedSet() { } /** operator=. * @param src Source object whose values will be assigned to this. * @return Reference to this. */ const OFOrderedSet &operator=( const OFOrderedSet &src ) { return( assign( src ) ); } /** This function is a workaround for avoiding a compiler warning on * Solaris 2.5.1 using compiler SC 2.0.1. */ const OFOrderedSet &assign( const OFOrderedSet &src ) { if( this != &src ) this->operator=( src ); return( *this ); } /** Determines if two sets are identical. Note that for ordered sets * not only their elements have to be identical, but also the order * of their elements has to be identical. * @param other Set which shall be compared with this. * @return OFTrue if sets are identical, OFFalse otherwise. */ virtual OFBool operator==( const OFOrderedSet &other ) const { // check if both sets contain the same // amount of items; if not, return OFFalse if( this->num != other.num ) return( OFFalse ); // initialize result with OFTrue OFBool result = OFTrue; // as long as result is OFTrue go through all items in this for( unsigned int i=0 ; i < this->num && result == OFTrue ; i++ ) { // in case the current element does not equal the current // element in other, result shall be set to OFFalse if( *this->items[i] != *other.items[i] ) result = OFFalse; } // return result return( result ); } /** Determines if two sets are not identical. * @param other Set which shall be compared with this. * @return OFTrue if sets are not identical, OFFalse otherwise. */ virtual OFBool operator!=( const OFOrderedSet &other ) const { return( !( *this == other ) ); } /** Inserts a new item into the set. * @param item Item which shall be inserted into the set. */ virtual void Insert( const T &item ) { // if size equals num, we need more space if( this->size == this->num ) this->Resize( this->size * 2 ); // copy item T *newItem = new T( item ); // insert copy into array this->items[this->num] = newItem; // increase counter this->num++; } /** Inserts all items of another set into this set. * @param other set whose items shall be inserted into the set. */ virtual void Insert( const OFOrderedSet &other ) { // go through all items in other and insert each item into this for( unsigned int i=0 ; i this->num - 1 ) Insert( item ); else { // if size equals num, we need more space if( this->size == this->num ) this->Resize( this->size * 2 ); // copy item T *newItem = new T( item ); // create a new temporary array and assign all pointers correspondingly T **tmp = new T*[this->size]; for( i=0 ; iitems[i]; tmp[idx] = newItem; for( i=idx ; i < this->size - 1 ; i++ ) { if( i < this->num ) tmp[i+1] = this->items[i]; else tmp[i+1] = NULL; } // delete old array delete this->items; // assign new array to member variable this->items = tmp; // increase counter this->num++; } } /** Removes one item from the set. * @param item Item which shall be inserted into the set. */ virtual void Remove( const T &item ) { // so far, nothing was deleted OFBool itemDeleted = OFFalse; // go through all items for( unsigned int i=0 ; i < this->num && !itemDeleted ; i++ ) { // if current item is the one which shall be deleted if( *this->items[i] == item ) { // delete item delete this->items[i]; // and - so that there are no holes in the array - move all elements // behind the current element up one array field; only do so in case // we did _not_ delete the last item if( i != this->num - 1 ) { unsigned int j; for( j=i+1 ; j < this->num ; j++ ) { this->items[j-1] = this->items[j]; } this->items[j-1] = NULL; } else this->items[i] = NULL; // reduce counter this->num--; // remember that an item was deleted (so that always only one item will be deleted) itemDeleted = OFTrue; } } } /** Removes one item from the set. * @param idx Index of the item which shall be removed from the set. */ virtual void RemoveByIndex( unsigned int idx ) { // do something only if the given index is not out of range if( idx < this->num ) { // delete item with given index delete this->items[idx]; // and - so that there are no holes in the array - move all elements // behind the current element up one array field; only do so in case // we did _not_ delete the last item if( idx != this->num - 1 ) { unsigned int j; for( j=idx+1 ; j < this->num ; j++ ) { this->items[j-1] = this->items[j]; } this->items[j-1] = NULL; } else this->items[idx] = NULL; // reduce counter this->num--; } } /** Tries to find a given object in the set. In case the specified object could * be found, a pointer to the corresponding element within the set is returned; * in case the specified object could not be found, NULL will be returned. * @param item Search pattern. * @return Pointer to the corresponding element within the set or NULL. */ virtual T *Find( const T &item ) const { unsigned int i; OFBool itemFound = OFFalse; for( i=0 ; i < this->num && !itemFound ; i++ ) { if( *this->items[i] == item ) itemFound = OFTrue; } if( itemFound ) return( this->items[i-1] ); else return( NULL ); } /** Determines if a certain item is contained in the set. * @param item - Item which shall be looked for. * @return OFTrue, if item is contained in the set, OFFalse otherwise. */ virtual OFBool Contains( const T &item ) const { OFBool itemFound = OFFalse; for( unsigned int i=0 ; i < this->num && !itemFound ; i++ ) { if( *this->items[i] == item ) itemFound = OFTrue; } return( itemFound ); } /** Determines if this is an actual superset of other, i.e. * if this completely contains other and furthermore has * additional elements. * @param other - Set which shall be compared with this. * @return OFTrue if this is a superset of other, OFFalse otherwise. */ virtual OFBool IsSupersetOf( const OFOrderedSet &other ) const { // if this contains less or the same amount of items than other, return OFFalse if( this->num <= other.num ) return( OFFalse ); // initialize result with OFTrue OFBool result = OFTrue; // make a copy of this OFOrderedSet s = *this; // as long as result is OFTrue go through all items in other for( unsigned int i=0 ; i &other ) const { return( other.IsSupersetOf( *this ) ); } /** Determines the union of the two sets this and other, i.e. the set * containing all items which can be found either in this or in other, * and returns the resulting new set. * @param other Second parameter for union. * @return New set. */ OFOrderedSet Union( const OFOrderedSet &other ) const { // initialize result set OFOrderedSet resultSet = *this; // insert other set into result set resultSet.Insert( other ); // return result set return( resultSet ); } /** Determines the intersection of the two sets this and other, i.e. the set * containing all items which can be found in both this and other, and * returns the resulting new set. * @param other Second parameter for intersection. * @return New set. */ OFOrderedSet Intersection( const OFOrderedSet &other ) const { // initialize result set OFOrderedSet resultSet; // make a copy of other OFOrderedSet s = other; // go through all items in this for( unsigned int i=0 ; i < this->num ; i++ ) { // if s contains the current item if( s.Contains( *this->items[i] ) ) { // insert the item into the result set resultSet.Insert( *this->items[i] ); // and remove the item from s so that it will not be // considered again in a later call to s.Contains() s.Remove( *this->items[i] ); } } // return result set return( resultSet ); } /** Determines the difference this - other, i.e. the set containing all * the items found in this but not in other, and returns the resulting * new set. * @param other Second parameter for difference. * @return New set. */ OFOrderedSet Difference( const OFOrderedSet &other ) const { // initialize result set OFOrderedSet resultSet; // make a copy of other OFOrderedSet s = other; // go through all items in this for( unsigned int i=0 ; i < this->num ; i++ ) { // if s does not contain the current item if( !s.Contains( *this->items[i] ) ) { // insert the item into the result set resultSet.Insert( *this->items[i] ); } else { // else remove the item from s so that it will not be // considered again in a later call to s.Contains() s.Remove( *this->items[i] ); } } // return result set return( resultSet ); } /** Determines the symmetric difference of this and other, i.e. the set * containing all the items which can be found either in this or in other * but not in the intersection of this and other, and returns the resulting * new set. * @param other Second parameter for symmetric difference. * @return New set. */ OFOrderedSet SymmetricDifference( const OFOrderedSet &other ) const { // determine s1 = this - other OFOrderedSet s1 = (*this).Difference( other ); // determine s2 = other - this OFOrderedSet s2 = other.Difference( *this ); // determine the union of s1 and s2 OFOrderedSet resultSet = s1.Union( s2 ); // return result set return( resultSet ); } }; #endif