Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 1757


Ignore:
Timestamp:
Sep 10, 2008, 2:30:36 AM (16 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

Location:
code/trunk/src
Files:
4 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}
  • code/trunk/src/core/ClassTreeMask.h

    r1755 r1757  
    7676#include <stack>
    7777
     78#include "Iterator.h"
     79
    7880namespace orxonox
    7981{
     
    9193        friend class ClassTreeMask;
    9294        friend class ClassTreeMaskIterator;
     95        friend class ClassTreeMaskObjectIterator;
    9396
    9497        public:
     
    102105            void addSubnode(ClassTreeMaskNode* subnode);
    103106
    104             bool isIncluded() const;
    105             bool isExcluded() const;
    106 
    107             const Identifier* getClass() const;
     107            /** @brief Tells if the rule is "included" or not. @return The rule: true = included, false = excluded */
     108            inline bool isIncluded() const { return this->bIncluded_; }
     109            /** @brief Tells if the rule is "excluded" or not. @return The inverted rule: true = excluded, false = included */
     110            inline bool isExcluded() const { return (!this->bIncluded_); }
     111
     112            /** @brief Returns the Identifier of the class the rule refers to. @return The Identifier representing the class */
     113            inline const Identifier* getClass() const { return this->subclass_; }
     114
     115            /** @brief Returns true if the Node has some subnodes. */
     116            inline bool hasSubnodes() const { return !this->subnodes_.empty(); }
    108117
    109118        private:
     
    133142            ~ClassTreeMaskIterator();
    134143
    135             ClassTreeMaskIterator& operator++();
     144            const ClassTreeMaskIterator& operator++();
    136145            ClassTreeMaskNode* operator*() const;
    137146            ClassTreeMaskNode* operator->() const;
    138             operator bool();
    139             bool operator==(ClassTreeMaskNode* compare);
    140             bool operator!=(ClassTreeMaskNode* compare);
     147            operator bool() const;
     148            bool operator==(ClassTreeMaskNode* compare) const;
     149            bool operator!=(ClassTreeMaskNode* compare) const;
    141150
    142151        private:
     
    159168    class _CoreExport ClassTreeMask
    160169    {
     170        friend class ClassTreeMaskObjectIterator;
     171
    161172        public:
    162173            ClassTreeMask();
     
    178189            bool isExcluded(const Identifier* subclass) const;
    179190
    180             ClassTreeMask& operator=(const ClassTreeMask& other);
     191            /** @brief Begin of the ClassTreeMaskObjectIterator. */
     192            inline const ClassTreeMask& begin() const { return (*this); }
     193            /** @brief End of the ClassTreeMaskObjectIterator. */
     194            inline BaseObject*          end()   const { return 0; }
     195
     196            const ClassTreeMask& operator=(const ClassTreeMask& other);
    181197
    182198            bool operator==(const ClassTreeMask& other) const;
    183199            bool operator!=(const ClassTreeMask& other) const;
    184200
    185             ClassTreeMask& operator+();
     201            const ClassTreeMask& operator+() const;
    186202            ClassTreeMask operator-() const;
    187203
     
    191207            ClassTreeMask operator!() const;
    192208
    193             ClassTreeMask& operator+=(const ClassTreeMask& other);
    194             ClassTreeMask& operator*=(const ClassTreeMask& other);
    195             ClassTreeMask& operator-=(const ClassTreeMask& other);
     209            const ClassTreeMask& operator+=(const ClassTreeMask& other);
     210            const ClassTreeMask& operator*=(const ClassTreeMask& other);
     211            const ClassTreeMask& operator-=(const ClassTreeMask& other);
    196212
    197213            ClassTreeMask operator&(const ClassTreeMask& other) const;
     
    200216            ClassTreeMask operator~() const;
    201217
    202             ClassTreeMask& operator&=(const ClassTreeMask& other);
    203             ClassTreeMask& operator|=(const ClassTreeMask& other);
    204             ClassTreeMask& operator^=(const ClassTreeMask& other);
     218            const ClassTreeMask& operator&=(const ClassTreeMask& other);
     219            const ClassTreeMask& operator|=(const ClassTreeMask& other);
     220            const ClassTreeMask& operator^=(const ClassTreeMask& other);
    205221
    206222            friend std::ostream& operator<<(std::ostream& out, const ClassTreeMask& mask);
     
    219235    // ### ClassTreeMaskObjectIterator ###
    220236    // ###################################
    221     //! ...
    222     /**
    223         ...
     237    //! The ClassTreeMaskObjectIterator iterates through all objects of all classes, included by a ClassTreeMask.
     238    /**
     239        The ClassTreeMaskObjectIterator iterates through all objects of all classes,
     240        included by a ClassTreeMask. This is done the following way:
     241
     242        ClassTreeMask mask;
     243        for (ClassTreeMaskObjectIterator it = mask.begin(); it != mask.end(); ++it)
     244            it->doSomething();
     245
     246        Note: The ClassTreeMaskObjectIterator handles all objects as BaseObjects. If
     247              you want to use another class, you should use a dynamic_cast.
     248
     249        Performance of ClassTreeMaskObjectIterator is good as long as you don't exclude
     250        subclasses of included classes. Of course you can still exlucde subclasses, but
     251        if this is done more often, we need a new implementation using a second ObjectList
     252        in the Identifier, containing all objects of exactly one class.
    224253    */
    225254    class _CoreExport ClassTreeMaskObjectIterator
    226255    {
     256        public:
     257            /** @brief Defaultconstructor: Does nothing. */
     258            inline ClassTreeMaskObjectIterator() {}
     259            /** @brief Constructor: Initializes the iterator from a given ClassTreeMask. @param mask The mask */
     260            inline ClassTreeMaskObjectIterator(const ClassTreeMask& mask) { (*this) = mask; }
     261
     262            const ClassTreeMaskObjectIterator& operator=(const ClassTreeMask& mask);
     263
     264            const ClassTreeMaskObjectIterator& operator++();
     265
     266            /** @brief Returns true if the ClassTreeMaskObjectIterator points at the given object. @param pointer The pointer of the object */
     267            inline bool operator==(BaseObject* pointer) const { return ((*this->objectIterator_) == pointer); }
     268            /** @brief Returns true if the ClassTreeMaskObjectIterator doesn't point at the given object. @param pointer The pointer of the object */
     269            inline bool operator!=(BaseObject* pointer) const { return ((*this->objectIterator_) != pointer); }
     270            /** @brief Returns true if the ClassTreeMaskObjectIterator hasn't already reached the end. */
     271            inline operator bool() const { return (this->objectIterator_); }
     272            /** @brief Returns the object the ClassTreeMaskObjectIterator currently points at. */
     273            inline BaseObject* operator*() const { return (*this->objectIterator_); }
     274            /** @brief Returns the object the ClassTreeMaskObjectIterator currently points at. */
     275            inline BaseObject* operator->() const { return (*this->objectIterator_); }
     276
     277        private:
     278            void create(ClassTreeMaskNode* node);
     279
     280            std::list<std::pair<const Identifier*, bool> >           subclasses_;       //!< A list of all Identifiers through which objects the iterator should iterate
     281            std::list<std::pair<const Identifier*, bool> >::iterator subclassIterator_; //!< The current class of the iterator
     282            Iterator<BaseObject>                                     objectIterator_;   //!< The current object of the iterator
    227283    };
    228284}
  • code/trunk/src/core/CorePrereqs.h

    r1755 r1757  
    9898  class ClassTreeMaskIterator;
    9999  class ClassTreeMaskNode;
     100  class ClassTreeMaskObjectIterator;
    100101  class Clock;
    101102  class CommandEvaluation;
  • code/trunk/src/util/MultiType.h

    r1747 r1757  
    164164        inline ~MultiType() { if (this->value_) { delete this->value_; } }
    165165
    166         template <typename V> inline MultiType& operator=(const V& value)         { this->setValue(value); return (*this); }
    167         inline                       MultiType& operator=(const MultiType& other) { this->setValue(other); return (*this); }
    168         inline                       MultiType& operator=(MT_Type type)           { this->setType(type);   return (*this); }
     166        template <typename V> inline const MultiType& operator=(const V& value)         { this->setValue(value); return (*this); }
     167        inline                       const MultiType& operator=(const MultiType& other) { this->setValue(other); return (*this); }
     168        inline                       const MultiType& operator=(MT_Type type)           { this->setType(type);   return (*this); }
    169169
    170170        inline void                                   setValue(const char& value);
Note: See TracChangeset for help on using the changeset viewer.