Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Sep 10, 2008, 2:30:36 AM (17 years ago)
Author:
landauf
Message:

added ClassTreeMaskObjectIterator
this iterator iterates through all objects of all classes, included by a given ClassTreeMask.

Note: The ClassTreeMaskObjectIterator is fast if you only include classes. If you exclude a subclass of an included class, the performance is not that good.
If we'll use this more often, we have to think about a new implementation, using a second ObjectList with all objects of exactly one class.

Additionally, there is a small change in MultiType.h

File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/trunk/src/core/ClassTreeMask.cc

    r1543 r1757  
    102102
    103103    /**
    104         @brief Tells if the rule is "included" or not.
    105         @return The rule: true = included, false = excluded
    106     */
    107     bool ClassTreeMaskNode::isIncluded() const
    108     {
    109         return this->bIncluded_;
    110     }
    111 
    112     /**
    113         @brief Tells if the rule is "excluded" or not.
    114         @return The inverted rule: true = excluded, false = included
    115     */
    116     bool ClassTreeMaskNode::isExcluded() const
    117     {
    118         return (!this->bIncluded_);
    119     }
    120 
    121     /**
    122         @brief Returns the Identifier of the class the rule refers to.
    123         @return The Identifier representing the class
    124     */
    125     const Identifier* ClassTreeMaskNode::getClass() const
    126     {
    127         return this->subclass_;
    128     }
    129 
    130     /**
    131104        @brief Deletes all subnodes of this node.
    132105    */
     
    169142        @return A reference to the iterator itself
    170143    */
    171     ClassTreeMaskIterator& ClassTreeMaskIterator::operator++()
     144    const ClassTreeMaskIterator& ClassTreeMaskIterator::operator++()
    172145    {
    173146        // Check if the actual node has subnodes
     
    226199        @return True if we've reached the end of the tree
    227200    */
    228     ClassTreeMaskIterator::operator bool()
     201    ClassTreeMaskIterator::operator bool() const
    229202    {
    230203        return (!this->nodes_.empty());
     
    236209        @return The result of the comparison (true if they match)
    237210    */
    238     bool ClassTreeMaskIterator::operator==(ClassTreeMaskNode* compare)
     211    bool ClassTreeMaskIterator::operator==(ClassTreeMaskNode* compare) const
    239212    {
    240213        if (!this->nodes_.empty())
     
    249222        @return The result of the comparison (true if they don't match)
    250223    */
    251     bool ClassTreeMaskIterator::operator!=(ClassTreeMaskNode* compare)
     224    bool ClassTreeMaskIterator::operator!=(ClassTreeMaskNode* compare) const
    252225    {
    253226        if (!this->nodes_.empty())
     
    545518        @return A reference to the mask itself
    546519    */
    547     ClassTreeMask& ClassTreeMask::operator=(const ClassTreeMask& other)
     520    const ClassTreeMask& ClassTreeMask::operator=(const ClassTreeMask& other)
    548521    {
    549522        // Make a copy to avoid troubles with self-assignments (like A = A).
     
    598571        @return A reference to the mask itself
    599572    */
    600     ClassTreeMask& ClassTreeMask::operator+()
     573    const ClassTreeMask& ClassTreeMask::operator+() const
    601574    {
    602575        return (*this);
     
    709682        @return A reference to the mask itself
    710683    */
    711     ClassTreeMask& ClassTreeMask::operator+=(const ClassTreeMask& other)
     684    const ClassTreeMask& ClassTreeMask::operator+=(const ClassTreeMask& other)
    712685    {
    713686        (*this) = (*this) + other;
     
    720693        @return A reference to the mask itself
    721694    */
    722     ClassTreeMask& ClassTreeMask::operator*=(const ClassTreeMask& other)
     695    const ClassTreeMask& ClassTreeMask::operator*=(const ClassTreeMask& other)
    723696    {
    724697        (*this) = (*this) * other;
     
    731704        @return A reference to the mask itself
    732705    */
    733     ClassTreeMask& ClassTreeMask::operator-=(const ClassTreeMask& other)
     706    const ClassTreeMask& ClassTreeMask::operator-=(const ClassTreeMask& other)
    734707    {
    735708        (*this) = (*this) - other;
     
    802775        @return A reference to the mask itself
    803776    */
    804     ClassTreeMask& ClassTreeMask::operator&=(const ClassTreeMask& other)
     777    const ClassTreeMask& ClassTreeMask::operator&=(const ClassTreeMask& other)
    805778    {
    806779        (*this) = (*this) & other;
     
    813786        @return A reference to the mask itself
    814787    */
    815     ClassTreeMask& ClassTreeMask::operator|=(const ClassTreeMask& other)
     788    const ClassTreeMask& ClassTreeMask::operator|=(const ClassTreeMask& other)
    816789    {
    817790        (*this) = (*this) | other;
     
    824797        @return A reference to the mask itself
    825798    */
    826     ClassTreeMask& ClassTreeMask::operator^=(const ClassTreeMask& other)
     799    const ClassTreeMask& ClassTreeMask::operator^=(const ClassTreeMask& other)
    827800    {
    828801        (*this) = (*this) ^ other;
     
    853826        return out;
    854827    }
     828
     829
     830    // ###################################
     831    // ### ClassTreeMaskObjectIterator ###
     832    // ###################################
     833    /**
     834        @brief Initializes the iterator from a given ClassTreeMask.
     835        @param mask The mask
     836    */
     837    const ClassTreeMaskObjectIterator& ClassTreeMaskObjectIterator::operator=(const ClassTreeMask& mask)
     838    {
     839        // Clear everything, use a cleaned copy of the mask
     840        this->subclasses_.clear();
     841        ClassTreeMask temp = mask;
     842        temp.clean();
     843
     844        // Create the subclass-list by going through the mask-tree, starting with the root-node
     845        this->create(temp.root_);
     846
     847        // Move the subclass-iterator to the beginning of the subclass-list
     848        this->subclassIterator_ = this->subclasses_.begin();
     849
     850        // If there is a first subclass, move the object-iterator to the first object of this class. Else go to the end
     851        if (this->subclassIterator_ != this->subclasses_.end())
     852            this->objectIterator_ = (*this->subclassIterator_).first->getObjects()->begin();
     853        else
     854            this->objectIterator_ = ObjectList<BaseObject>::end();
     855
     856        // Check if the iterator points on a valid object. If not, go to the next object by calling ++
     857        if (!this->objectIterator_ || ((*this->subclassIterator_).second && !this->objectIterator_->isExactlyA((*this->subclassIterator_).first)))
     858            this->operator++();
     859
     860        return (*this);
     861    }
     862
     863    /**
     864        @brief Iterate to the next object (if any).
     865        @return The iterator itself
     866    */
     867    const ClassTreeMaskObjectIterator& ClassTreeMaskObjectIterator::operator++()
     868    {
     869        if (this->objectIterator_)
     870        {
     871            // The iterator points on a valid object, therefore we also have a valid subclass-iterator at the moment
     872            do
     873            {
     874                // Go to the next object
     875                ++this->objectIterator_;
     876
     877                while (!this->objectIterator_)
     878                {
     879                    // We reached the end of the current objectlist - go to the next class
     880                    ++this->subclassIterator_;
     881
     882                    // Check if there really is a next class. If yes, move the object-iterator to the first object
     883                    if (this->subclassIterator_ != this->subclasses_.end())
     884                        this->objectIterator_ = (*this->subclassIterator_).first->getObjects()->begin();
     885                    else
     886                        return (*this);
     887                }
     888
     889            // Repeat this until we reach a valid object or the end
     890            } while ((*this->subclassIterator_).second && !this->objectIterator_->isExactlyA((*this->subclassIterator_).first));
     891        }
     892        return (*this);
     893    }
     894
     895    /**
     896        @brief Recursive function to create the Iterators subclass-list by going through the node-tree of the mask.
     897        @param node The current node
     898    */
     899    void ClassTreeMaskObjectIterator::create(ClassTreeMaskNode* node)
     900    {
     901        // Add the class of this node to the list, if the class is included
     902        if (node->isIncluded())
     903        {
     904            // If there are some subnodes, the bool is "true", meaning we have to check for the exact clss when iterating
     905            if (node->hasSubnodes())
     906                this->subclasses_.insert(this->subclasses_.end(), std::pair<const Identifier*, bool>(node->getClass(), true));
     907            else
     908                this->subclasses_.insert(this->subclasses_.end(), std::pair<const Identifier*, bool>(node->getClass(), false));
     909        }
     910
     911        // Now check if the node has subnodes
     912        if (node->hasSubnodes())
     913        {
     914            // Get all _direct_ children of the nodes class
     915            std::set<const Identifier*> directChildren = node->getClass()->getDirectChildren();
     916
     917            // Iterate through all subnodes
     918            for (std::list<ClassTreeMaskNode*>::iterator it1 = node->subnodes_.begin(); it1 != node->subnodes_.end(); ++it1)
     919            {
     920                // Recursive call to this function with the subnode
     921                this->create(*it1);
     922
     923                // Only execute the following code if the current node is included, meaning some of the subnodes might be included too
     924                if (node->isIncluded())
     925                {
     926                    scanChildren: // This is a label for goto
     927
     928                    // Iterate through all direct children
     929                    for (std::set<const Identifier*>::iterator it2 = directChildren.begin(); it2 != directChildren.end(); ++it2)
     930                    {
     931                        // Check if the subnode (it1) is a child of the directChild (it2)
     932                        if ((*it1)->getClass()->isA(*it2))
     933                        {
     934                            // Yes it is - remove the directChild (it2) from the list, because it will already be handled by a recursive call to the create() function
     935                            directChildren.erase(it2);
     936
     937                            // Check if the removed directChild was exactly the subnode
     938                            if (!(*it1)->getClass()->isExactlyA(*it2))
     939                            {
     940                                // No, it wasn't exactly the subnode - therefore there are some classes between
     941
     942                                // Add the previously removed directChild (it2) to the subclass-list
     943                                this->subclasses_.insert(this->subclasses_.end(), std::pair<const Identifier*, bool>(*it2, true));
     944
     945                                // Insert all directChildren of the directChild
     946                                directChildren.insert((*it2)->getDirectChildrenBegin(), (*it2)->getDirectChildrenEnd());
     947
     948                                // Restart the scan with the expanded set of directChildren
     949                                goto scanChildren;
     950                            }
     951                            break;
     952                        }
     953                    }
     954                }
     955            }
     956
     957            // Now add all directChildren which don't have subnodes on their own to the subclass-list
     958            // The bool is "false", meaning they have no subnodes and therefore need no further checks
     959            if (node->isIncluded())
     960                for (std::set<const Identifier*>::iterator it = directChildren.begin(); it != directChildren.end(); ++it)
     961                    this->subclasses_.insert(this->subclasses_.end(), std::pair<const Identifier*, bool>(*it, false));
     962        }
     963    }
    855964}
Note: See TracChangeset for help on using the changeset viewer.