// file: $isip/class/dstr/Set/Set.h // version: $Id: Set.h 10636 2007-01-26 22:18:09Z tm334 $ // // make sure definitions are made only once // #ifndef ISIP_SET_LIST #define ISIP_SET_LIST // include files // #include // isip include files // #ifndef ISIP_DOUBLE_LINKED_LIST #include #endif #ifndef ISIP_STRING #include #endif #ifndef ISIP_CONSOLE #include #endif // Set: this class builds a collection of unique objects. in other words, // the difference between a set and a linked list is that two objects // of the same value will not appear twice in a set. every object must // have a unique value. // template class Set : public DoubleLinkedList { //--------------------------------------------------------------------------- // // public constants // //--------------------------------------------------------------------------- public: // define the class name // static const String CLASS_NAME; //---------------------------------------- // // default values and arguments // //---------------------------------------- // default values // // default arguments to methods // //---------------------------------------- // // error codes // //---------------------------------------- static const int32 ERR = 42200; //--------------------------------------------------------------------------- // // protected data // //--------------------------------------------------------------------------- protected: // define the memory manager // static MemoryManager mgr_d; //--------------------------------------------------------------------------- // // required public methods // //--------------------------------------------------------------------------- public: // static methods: // diagnose method is moved outside the class header file and // defined in the SetDiagnose.h in order to avoid issues // related to preprocessing of the diagnose code. // static const String& name(); // setDebug is inherited from the DoubleLinkedList class // // other debug methods // bool8 debug(const unichar* message) const; // method: destructor // ~Set() {} // method: default constructor // Set(DstrBase::ALLOCATION alloc = DstrBase::DEF_ALLOCATION) { this->alloc_d = alloc; } // method: copy constructor // Set(const Set& arg) { this->alloc_d = arg.alloc_d; assign(arg); } // method: assign // bool8 assign(const Set& arg) { return DoubleLinkedList::assign(arg); } // method: operator= // Set& operator=(const Set& arg) { assign(arg); return *this; } // equality methods are inherited from the DoubleLinkedList class // // i/o methods: // sofSize is inherited from the DoubleLinkedList class // // method: read // bool8 read(Sof& sof, int32 tag) { return read(sof, tag, name()); } // method: write // bool8 write(Sof& sof, int32 tag) const { return write(sof, tag, name()); } // other i/o methods // bool8 read(Sof& sof, int32 tag, const String& name); bool8 write(Sof& sof, int32 tag, const String& name) const; // method: readData // bool8 readData(Sof& sof, const String& pname = DoubleLinkedList::DEF_PARAM, int32 size = SofParser::FULL_OBJECT, bool8 param = true, bool8 nested = false) { return DoubleLinkedList::readData(sof, pname, size, param, nested); } // method: writeData // bool8 writeData(Sof& sof, const String& pname = DoubleLinkedList::DEF_PARAM) const { return DoubleLinkedList::writeData(sof, pname); } // method: new // static void* operator new(size_t size) { return mgr_d.get(); } // method: new[] // static void* operator new[](size_t size) { return mgr_d.getBlock(size); } // method: delete // static void operator delete(void* ptr) { mgr_d.release(ptr); } // method: delete[] // static void operator delete[](void* ptr) { mgr_d.releaseBlock(ptr); } // method: setGrowSize // static bool8 setGrowSize(int32 grow_size) { return mgr_d.setGrow(grow_size); } // other memory management methods // clear is inherited from the DoubleLinkedList class //--------------------------------------------------------------------------- // // class-specific public methods: // overloaded operators and extensions to required methods // //--------------------------------------------------------------------------- // method: operator() // const TObject& operator() (int32 index) const { return (*((DoubleLinkedList*)this))(index); } //--------------------------------------------------------------------------- // // class-specific public methods: // access methods. note that only the const versions are allowed. // //--------------------------------------------------------------------------- // method: getFirst // const TObject* getFirst() const { return DoubleLinkedList::getFirst(); } // method: getLast // const TObject* getLast() const { return DoubleLinkedList::getLast(); } // method: getNext // const TObject* getNext() const { return DoubleLinkedList::getNext(); } // method: getPrev // const TObject* getPrev() const { return DoubleLinkedList::getPrev(); } // method: getMark // const TObject* getMark() const { return DoubleLinkedList::getMark(); } // method: getCurr // const TObject* getCurr() const { return DoubleLinkedList::getCurr(); } //--------------------------------------------------------------------------- // // class-specific public methods: // insert and remove methods // //--------------------------------------------------------------------------- // insert and remove methods: // the current pointer is moved to the node inserted. // bool8 insert(TObject* item); // remove methods are inherited from the list class // //--------------------------------------------------------------------------- // // class-specific public methods: // property methods // //--------------------------------------------------------------------------- // these methods take advantage of the list being in sorted order // bool8 find(const TObject* item); bool8 contains(const TObject* item) const; //--------------------------------------------------------------------------- // // private methods // //--------------------------------------------------------------------------- private: // block these list methods from being used in Set // bool8 sort(Integral::ORDER sort_order = Integral::ASCENDING, DstrBase::SORT_ALGO = DstrBase::DEF_SORT_ALGO); bool8 reverse(); bool8 swap(int32 i, int32 j); bool8 insertFirst(TObject* item); bool8 insertFirst(Set& item_list); bool8 insertLast(TObject* item); bool8 insertLast(Set& item_list); bool8 apply(bool8 (TObject::*method)()); bool8 apply(bool8 (TObject::*method)(), Set& arg); // friend class // template friend class SetDiagnose; }; //----------------------------------------------------------------------------- // // we define non-integral constants at the end of class definition for // templates (for non-templates these are defined in the default constructor) // //----------------------------------------------------------------------------- // constants: required constants such as the class name // template const String Set::CLASS_NAME(L"Set"); template MemoryManager Set::mgr_d(sizeof(Set), CLASS_NAME); // below are all the methods for the Set template class // //---------------------------------------------------------------------- // // required static methods // //---------------------------------------------------------------------- // method: name // // arguments: none // // return: a static String& containing the class name // // this method returns the class name // template const String& Set::name() { // create the static name string for this class and return it // static String cname(CLASS_NAME); cname.clear(); cname.concat(CLASS_NAME); cname.concat(L"<"); cname.concat(TObject::name()); cname.concat(L">"); // return the name // return cname; } //---------------------------------------------------------------------- // // required debug methods // //---------------------------------------------------------------------- // method: debug // // arguments: // const unichar* message: (input) information message // // return: a bool8 value indicating status // // this method dumps the contents of an object to the console // template bool8 Set::debug(const unichar* message_a) const { // declare local variables // String output; String value; String extras; // print out the debug level // value.assign(DoubleLinkedList::debug_level_d); output.debugStr(name(), message_a, L"debug_level_d", value); Console::put(output); // print out the list // output.debugStr(name(), message_a, L"list"); Console::put(output); DoubleLinkedList::debug(L""); // exit gracefully // return true; } //------------------------------------------------------------------------ // // required i/o methods // //------------------------------------------------------------------------ // method: read // // arguments: // Sof& sof: (input) sof file object // int32 tag: (input) sof object instance tag // const String& name: (input) sof object instance name // // return: a bool8 value indicating status // // this method has the object read itself from an Sof file // template bool8 Set::read(Sof& sof_a, int32 tag_a, const String& name_a) { // get the instance of the object from the Sof file // if (!sof_a.find(name_a, tag_a)) { return false; } // read the actual data from the sof file // if (!readData(sof_a)) { return false; } // exit gracefully // return true; } // method: write // // arguments: // Sof& sof: (input) sof file object // int32 tag: (input) sof object instance tag // const String& name: (input) sof object instance name // // return: a bool8 value indicating status // // this method has the object write itself to an Sof file // template bool8 Set::write(Sof& sof_a, int32 tag_a, const String& name_a) const { // declare a temporary size variable // int32 obj_size = 0; // switch on ascii or binary mode // if (sof_a.isText()) { // set the size to be dynamic // obj_size = Sof::ANY_SIZE; } else { // the size of the binary data to write // obj_size = this->sofSize(); } // put the object into the sof file's index // if (!sof_a.put(name_a, tag_a, obj_size)) { return false; } // exit gracefully // return writeData(sof_a); } //--------------------------------------------------------------------------- // // class-specific public methods: // insert methods // //--------------------------------------------------------------------------- // method: insert // // arguments: // TObject* item: (input) the item to be added // // return: a bool8 value indicating status // // this method adds a new node containing the item after the current position // of this list // template bool8 Set::insert(TObject* item_a) { // make sure the item is not NULL // if (item_a == (TObject*)NULL) { return Error::handle(name(), L"insert", Error::NULL_ARG, __FILE__, __LINE__); } // the list was empty, add the input item to the beginning // if (this->isEmpty()) { return DoubleLinkedList::insertFirst(item_a); } // call the find method. it will return true if the item already // exists in the list, in which case we do not insert the item and // return false. // if (find(item_a)) { return false; } // special case: if the item is less than the first item, call // insertFirst. // if (item_a->lt(*DoubleLinkedList::getFirst())) { return DoubleLinkedList::insertFirst(item_a); } // if find returns false it means that the item was not found in the // list. the find method will leave the list positioned to the // correct place to insert the new node, so just insert // return DoubleLinkedList::insert(item_a); } //--------------------------------------------------------------------------- // // class-specific public methods: // property methods // //--------------------------------------------------------------------------- // method: contains // // arguments: // TObject* item: (input) the item to be found // // return: a bool8 value indicating status // // this method determines if an item is contained in this list. it is // unchanged from the DoubleLinkedList version, the only reason it is // defined here is so the faster find method can be used. // template bool8 Set::contains(const TObject* item_a) const { // check if the input item is NULL // if (item_a == (TObject*)NULL) { return Error::handle(name(), L"contains", Error::NULL_ARG, __FILE__, __LINE__); } // save the current position // DoubleLinkedNode* temp_curr = this->curr_d; // call the find method // bool8 item_found = const_cast*>(this)->find(item_a); // revert the current pointer so as to leave the list unchanged // const_cast*>(this)->curr_d = temp_curr; // return whether or not the item was found // return item_found; } // method: find // // arguments: // TObject* item: (input) the item to be found // // return: a bool8 value indicating status // // this method finds the first item in the list which is equivalent to // the item passed in. if no equivalent item is found, false is // returned. if an item is found, the list is positioned to that // point, otherwise the list is left in a place where the new item can // be inserted into the sorted order. // template bool8 Set::find(const TObject* item_a) { // check if the input item is NULL // if (item_a == (TObject*)NULL) { return Error::handle(name(), L"find", Error::NULL_ARG, __FILE__, __LINE__); } // find the item // for (bool8 more = this->gotoFirst(); more; more = this->gotoNext()) { if (item_a->eq(*getCurr())) { return true; } else if (item_a->lt(*getCurr())) { this->gotoPrev(); return false; } } // return false, it was not found. // return false; } // end of include file // #endif