Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/ClassTreeMask.cc @ 1350

Last change on this file since 1350 was 1056, checked in by landauf, 17 years ago

don't panic, no codechanges!
added a link to www.orxonox.net

File size: 29.9 KB
RevLine 
[802]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
[1056]3 *                    > www.orxonox.net <
[802]4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
[813]29/**
[809]30    @file ClassTreeMask.cc
31    @brief Implementation of the ClassTreeMask, ClassTreeMaskNode and ClassTreeMaskIterator classes.
32*/
33
[802]34#include "ClassTreeMask.h"
35#include "Identifier.h"
36#include "BaseObject.h"
37
38namespace orxonox
39{
40    // ###############################
41    // ###    ClassTreeMaskNode    ###
42    // ###############################
[809]43    /**
44        @brief Constructor: Creates the node, sets the subclass and the rule.
45        @param subclass The subclass the rule refers to
46        @param bIncluded The rule: included (true) or excluded (false)
47    */
[802]48    ClassTreeMaskNode::ClassTreeMaskNode(const Identifier* subclass, bool bIncluded)
49    {
50        this->subclass_ = subclass;
51        this->bIncluded_ = bIncluded;
52    }
53
[809]54    /**
55        @brief Destructor: Deletes all subnodes.
56    */
[802]57    ClassTreeMaskNode::~ClassTreeMaskNode()
58    {
[809]59        // Go through the list of all subnodes and delete them
[817]60        this->deleteAllSubnodes();
[802]61    }
62
[809]63    /**
64        @brief Sets the rule for the node to "included".
[818]65        @param overwrite True = overwrite previously added rules for inheriting classes
[809]66    */
[817]67    void ClassTreeMaskNode::include(bool overwrite)
[802]68    {
[817]69        this->setIncluded(true, overwrite);
[802]70    }
71
[809]72    /**
73        @brief Sets the rule for the node to "excluded".
[818]74        @param overwrite True = overwrite previously added rules for inheriting classes
[809]75    */
[817]76    void ClassTreeMaskNode::exclude(bool overwrite)
[802]77    {
[817]78        this->setIncluded(false, overwrite);
[802]79    }
80
[809]81    /**
[817]82        @brief Sets the rule for the node to a given value and erases all following rules.
[809]83        @param bIncluded The rule: included (true) or excluded (false)
[818]84        @param overwrite True = overwrite previously added rules for inheriting classes
[809]85    */
[817]86    void ClassTreeMaskNode::setIncluded(bool bIncluded, bool overwrite)
[802]87    {
[817]88        if (overwrite)
89            this->deleteAllSubnodes();
90
[802]91        this->bIncluded_ = bIncluded;
92    }
93
[809]94    /**
95        @brief Adds a new subnode to the list of subnodes.
96        @param subnode The new subnode
97    */
[802]98    void ClassTreeMaskNode::addSubnode(ClassTreeMaskNode* subnode)
99    {
100        this->subnodes_.insert(this->subnodes_.end(), subnode);
101    }
102
[809]103    /**
104        @brief Tells if the rule is "included" or not.
105        @return The rule: true = included, false = excluded
106    */
[802]107    bool ClassTreeMaskNode::isIncluded() const
108    {
109        return this->bIncluded_;
110    }
111
[809]112    /**
113        @brief Tells if the rule is "excluded" or not.
114        @return The inverted rule: true = excluded, false = included
115    */
[802]116    bool ClassTreeMaskNode::isExcluded() const
117    {
118        return (!this->bIncluded_);
119    }
120
[809]121    /**
122        @brief Returns the Identifier of the class the rule refers to.
123        @return The Identifier representing the class
124    */
[802]125    const Identifier* ClassTreeMaskNode::getClass() const
126    {
127        return this->subclass_;
128    }
129
[817]130    /**
131        @brief Deletes all subnodes of this node.
132    */
133    void ClassTreeMaskNode::deleteAllSubnodes()
134    {
135        // Go through the list of all subnodes and delete them
136        for (std::list<ClassTreeMaskNode*>::iterator it = this->subnodes_.begin(); it != this->subnodes_.end(); )
137            delete (*(it++));
[802]138
[817]139        // Clear the list
140        this->subnodes_.clear();
141    }
142
143
[802]144    // ###############################
[803]145    // ###  ClassTreeMaskIterator  ###
146    // ###############################
[809]147    /**
148        @brief Constructor: Initializes the iterator by creating a helper-list with the root-node and putting it to the stack.
149        @param node The root-node
150    */
[803]151    ClassTreeMaskIterator::ClassTreeMaskIterator(ClassTreeMaskNode* node)
152    {
[809]153        // Create a list and put the root-note into it
[807]154        std::list<ClassTreeMaskNode*>::iterator it = this->rootlist_.insert(this->rootlist_.end(), node);
[809]155
156        // Put the iterator to the only element of the list and the corresponding end()-iterator on the stack
[807]157        this->nodes_.push(std::pair<std::list<ClassTreeMaskNode*>::iterator, std::list<ClassTreeMaskNode*>::iterator>(it, this->rootlist_.end()));
[803]158    }
159
[809]160    /**
161        @brief Destructor: Does nothing.
162    */
[803]163    ClassTreeMaskIterator::~ClassTreeMaskIterator()
164    {
165    }
166
[809]167    /**
168        @brief Iterates through the rule-tree.
169        @return A reference to the iterator itself
170    */
[803]171    ClassTreeMaskIterator& ClassTreeMaskIterator::operator++()
172    {
[809]173        // Check if the actual node has subnodes
[803]174        if ((*this->nodes_.top().first)->subnodes_.begin() != (*this->nodes_.top().first)->subnodes_.end())
[809]175        {
176            // Yes it has: Push an iterator, pointing at the first subnode, on the stack
[803]177            this->nodes_.push(std::pair<std::list<ClassTreeMaskNode*>::iterator, std::list<ClassTreeMaskNode*>::iterator>((*this->nodes_.top().first)->subnodes_.begin(), (*this->nodes_.top().first)->subnodes_.end()));
[809]178        }
[803]179        else
180        {
[809]181            // No subnodes, meaning we reached a leaf: Go to the next node
[803]182            do
183            {
[809]184                // Iterate one step in the current list
[803]185                ++this->nodes_.top().first;
[809]186
187                // Check if we reached the end of the list (the second item in the stored pair always represents the end)
[803]188                if (this->nodes_.top().first == this->nodes_.top().second)
189                {
[809]190                    // Yes we've reached the end: Pop the list-iterator from the stack
[803]191                    this->nodes_.pop();
[809]192
193                    // Continue with the loop, meaning: Try to iterate through the previous list
[803]194                    continue;
195                }
196
[809]197                // If we reached this point, we aren't yet at the end of the list: Leave the loop
[803]198                break;
[809]199            } while (!this->nodes_.empty()); // Stop looping if the stack is empty, meaning: We've iterated to the end
[803]200        }
201
[809]202        // Finally return a reference to the iterator itself
[803]203        return *this;
204    }
205
[809]206    /**
207        @brief Returns a pointer to the ClassTreeMaskNode whereon the iterator points.
208        @return The pointer to the node
209    */
[803]210    ClassTreeMaskNode* ClassTreeMaskIterator::operator*() const
211    {
212        return (*this->nodes_.top().first);
213    }
214
[809]215    /**
216        @brief Returns a pointer to the ClassTreeMaskNode whereon the iterator points.
217        @return The pointer to the node
218    */
[803]219    ClassTreeMaskNode* ClassTreeMaskIterator::operator->() const
220    {
221        return (*this->nodes_.top().first);
222    }
223
[809]224    /**
225        @brief Returns true if the stack is empty, meaning we've reached the end of the tree.
226        @return True if we've reached the end of the tree
227    */
[803]228    ClassTreeMaskIterator::operator bool()
229    {
230        return (!this->nodes_.empty());
231    }
232
[809]233    /**
234        @brief Compares the current node with the given one and returns true if they match.
235        @param compare The node to compare with
236        @return The result of the comparison (true if they match)
237    */
[803]238    bool ClassTreeMaskIterator::operator==(ClassTreeMaskNode* compare)
239    {
240        if (!this->nodes_.empty())
241            return ((*this->nodes_.top().first) == compare);
242        else
243            return (compare == 0);
244    }
245
[809]246    /**
247        @brief Compares the current node with the given one and returns true if they don't match.
248        @param compare The node to compare with
249        @return The result of the comparison (true if they don't match)
250    */
[803]251    bool ClassTreeMaskIterator::operator!=(ClassTreeMaskNode* compare)
252    {
253        if (!this->nodes_.empty())
254            return ((*this->nodes_.top().first) != compare);
255        else
256            return (compare != 0);
257    }
258
259
260    // ###############################
[802]261    // ###      ClassTreeMask      ###
262    // ###############################
[809]263    /**
264        @brief Constructor: Adds the root-node of the tree with the first rule ("include everything").
265    */
[802]266    ClassTreeMask::ClassTreeMask()
267    {
[811]268        this->root_ = new ClassTreeMaskNode(ClassManager<BaseObject>::getIdentifier(), true);
[802]269    }
270
[809]271    /**
272        @brief Copyconstructor: Adds the root-node of the tree with the first rule ("include everything") and adds all rules from the other mask.
273        @param other The other mask
274    */
[807]275    ClassTreeMask::ClassTreeMask(const ClassTreeMask& other)
276    {
[811]277        this->root_ = new ClassTreeMaskNode(ClassManager<BaseObject>::getIdentifier(), true);
[807]278        for (ClassTreeMaskIterator it = other.root_; it; ++it)
[817]279            this->add(it->getClass(), it->isIncluded(), false);
[807]280    }
281
[809]282    /**
283        @brief Destructor: Deletes the root node (which will delete all subnodes too).
284    */
[802]285    ClassTreeMask::~ClassTreeMask()
286    {
287        delete this->root_;
288    }
289
[809]290    /**
291        @brief Adds a new "include" rule for a given subclass to the mask.
292        @param subclass The subclass
[818]293        @param overwrite True = overwrite previously added rules for inheriting classes
294        @param clean True = clean the tree after adding the new rule
[809]295    */
[817]296    void ClassTreeMask::include(const Identifier* subclass, bool overwrite, bool clean)
[802]297    {
[817]298        this->add(subclass, true, overwrite, clean);
[802]299    }
300
[809]301    /**
302        @brief Adds a new "exclude" rule for a given subclass to the mask.
303        @param subclass The subclass
[818]304        @param overwrite True = overwrite previously added rules for inheriting classes
305        @param clean True = clean the tree after adding the new rule
[809]306    */
[817]307    void ClassTreeMask::exclude(const Identifier* subclass, bool overwrite, bool clean)
[802]308    {
[817]309        this->add(subclass, false, overwrite, clean);
[802]310    }
311
[809]312    /**
313        @brief Adds a new rule for a given subclass to the mask.
314        @param subclass The subclass
315        @param bInclude The rule: include (true) or exclude (false)
[818]316        @param overwrite True = overwrite previously added rules for inheriting classes
317        @param clean True = clean the tree after adding the new rule
[809]318    */
[817]319    void ClassTreeMask::add(const Identifier* subclass, bool bInclude, bool overwrite, bool clean)
[802]320    {
[817]321        // Check if the given subclass is a child of our root-class
[813]322        if (subclass->isA(this->root_->getClass()))
[817]323        {
324            // Yes it is: Just add the rule to the three
325            this->add(this->root_, subclass, bInclude, overwrite);
326        }
[813]327        else
328        {
[817]329            // No it's not: Search for classes inheriting from the given class and add the rules for them
[1052]330            for (std::set<const Identifier*>::const_iterator it = subclass->getDirectChildrenBegin(); it != subclass->getDirectChildrenEnd(); ++it)
[817]331                if ((*it)->isA(this->root_->getClass()))
332                    if (overwrite || (!this->nodeExists(*it))) // If we don't want to overwrite, only add nodes that don't already exist
333                        this->add(this->root_, *it, bInclude, overwrite);
[813]334        }
335
[817]336        // Clean the rule-tree
337        if (clean)
338            this->clean();
[802]339    }
340
[809]341    /**
342        @brief Adds a new rule for a given subclass to a node of the internal rule-tree (recursive function).
343        @param node The node
344        @param subclass The subclass
345        @param bInclude The rule: include (true) or exclude (false)
[818]346        @param overwrite True = overwrite previously added rules for inheriting classes
[809]347    */
[817]348    void ClassTreeMask::add(ClassTreeMaskNode* node, const Identifier* subclass, bool bInclude, bool overwrite)
[802]349    {
350        // Check if the current node contains exactly the subclass we want to add
351        if (subclass == node->getClass())
352        {
353            // We're at the right place, just change the mask and return
[817]354            node->setIncluded(bInclude, overwrite);
[802]355            return;
356        }
[817]357        else if (subclass->isA(node->getClass()))
[802]358        {
359            // Search for an already existing node, containing the subclass we want to add
360            for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); ++it)
361            {
362                if (subclass->isA((*it)->getClass()))
363                {
[809]364                    // We've found an existing node -> delegate the work with a recursive function-call and return
[817]365                    this->add(*it, subclass, bInclude, overwrite);
[802]366                    return;
367                }
368            }
369
370            // There is no existing node satisfying our needs -> we create a new node
371            ClassTreeMaskNode* newnode = new ClassTreeMaskNode(subclass, bInclude);
372
[817]373            // Search for nodes that should actually be subnodes of our new node and erase them
[802]374            for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); )
375            {
376                if ((*it)->getClass()->isChildOf(subclass))
377                {
[817]378                    // We've found a subnode: add it to the new node and erase it from the current node
379                    if (!overwrite)
380                        newnode->addSubnode(*it);
381                    else
382                        delete (*it);
383
[802]384                    node->subnodes_.erase(it++);
385                }
386                else
387                {
388                    ++it;
389                }
390            }
391
392            // Finally add the new node as a subnode to the current node
393            node->addSubnode(newnode);
394        }
395    }
396
[809]397    /**
[818]398        @brief Adds a new "include" rule for a single subclass. The new rule doesn't change the mask for inheriting classes.
399        @param subclass The subclass
400        @param clean True = clean the tree after adding the new rule
401    */
402    void ClassTreeMask::includeSingle(const Identifier* subclass, bool clean)
403    {
404        this->addSingle(subclass, true, clean);
405    }
406
407    /**
408        @brief Adds a new "exclude" rule for a single subclass. The new rule doesn't change the mask for inheriting classes.
409        @param subclass The subclass
410        @param clean True = clean the tree after adding the new rule
411    */
412    void ClassTreeMask::excludeSingle(const Identifier* subclass, bool clean)
413    {
414        this->addSingle(subclass, false, clean);
415    }
416
417    /**
418        @brief Adds a new rule for a single subclass. The new rule doesn't change the mask for inheriting classes.
419        @param bInclude The rule: include (true) or exclude (false)
420        @param subclass The subclass
421        @param clean True = clean the tree after adding the new rule
422    */
423    void ClassTreeMask::addSingle(const Identifier* subclass, bool bInclude, bool clean)
424    {
[1052]425        for (std::set<const Identifier*>::const_iterator it = subclass->getDirectChildrenBegin(); it != subclass->getDirectChildrenEnd(); ++it)
[818]426            this->add(*it, this->isIncluded(*it), false, false);
427
428        this->add(subclass, bInclude, false, clean);
429    }
430
431    /**
[809]432        @brief Resets the mask to "include everything".
433    */
[802]434    void ClassTreeMask::reset()
435    {
436        delete this->root_;
[811]437        this->root_ = new ClassTreeMaskNode(ClassManager<BaseObject>::getIdentifier(), true);
[802]438    }
439
[809]440    /**
441        @brief Tells if a given subclass is included or not.
442        @param subclass The subclass
443        @return Included (true) or excluded (false)
444    */
[803]445    bool ClassTreeMask::isIncluded(const Identifier* subclass) const
[802]446    {
447        return this->isIncluded(this->root_, subclass);
448    }
449
[809]450    /**
451        @brief Tells if a given subclass of a node in the rule-tree is included or not (recursive function).
452        @param node The node
453        @param subclass The subclass
454        @return Included (true) or excluded (false)
455    */
[803]456    bool ClassTreeMask::isIncluded(ClassTreeMaskNode* node, const Identifier* subclass) const
[802]457    {
458        // Check if the searched subclass is of the same type as the class in the current node or a derivative
459        if (subclass->isA(node->getClass()))
460        {
461            // Check for the special case
462            if (subclass == node->getClass())
463                return node->isIncluded();
464
[809]465            // Go through the list of subnodes and look for a node containing the searched subclass and delegate the request by a recursive function-call.
[802]466            for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); ++it)
467                if (subclass->isA((*it)->getClass()))
468                    return isIncluded(*it, subclass);
469
470            // There is no subnode containing our class -> the rule of the current node takes in effect
471            return node->isIncluded();
472        }
473        else
474        {
475            // The class is not included in the mask: return false
476            return false;
477        }
478    }
479
[809]480    /**
481        @brief Tells if a given subclass is excluded or not.
482        @param subclass The subclass
483        @return The inverted rule: Excluded (true) or included (false)
484    */
[803]485    bool ClassTreeMask::isExcluded(const Identifier* subclass) const
[802]486    {
487        return (!this->isIncluded(subclass));
488    }
[803]489
[809]490    /**
491        @brief Removes all unneeded rules that don't change the information of the mask.
492    */
[803]493    void ClassTreeMask::clean()
494    {
495        this->clean(this->root_);
496    }
497
[809]498    /**
499        @brief Removes all unneded rules that don't change the information of a node of a mask (recursive function).
500        @param node The node
501    */
[803]502    void ClassTreeMask::clean(ClassTreeMaskNode* node)
503    {
[809]504        // Iterate through all subnodes of the given node
[803]505        for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); )
506        {
[809]507            // Recursive function-call: Clean the subnode
[808]508            this->clean(*it);
[809]509
510            // Now check if the subnode contains the same rule as the current node
[803]511            if ((*it)->isIncluded() == node->isIncluded())
512            {
[809]513                // It does: Move all subnodes of the redundant subnode to the current node
[803]514                node->subnodes_.insert(node->subnodes_.end(), (*it)->subnodes_.begin(), (*it)->subnodes_.end());
515                (*it)->subnodes_.clear();
[809]516
517                // Remove the redundant subnode from the current node
518                node->subnodes_.erase(it++);
[803]519            }
520            else
521            {
[809]522                // The subnode is necessary: Move on to the next subnode
[803]523                ++it;
524            }
525        }
526    }
527
[809]528    /**
[817]529        @brief Checks if a node for the given subclass exists.
530        @param subclass The Identifier of the subclass
531        @return True = the node exists
532    */
533    bool ClassTreeMask::nodeExists(const Identifier* subclass)
534    {
535        for (ClassTreeMaskIterator it = this->root_; it; ++it)
536            if ((*it)->getClass() == subclass)
537                return true;
538
539        return false;
540    }
541
542    /**
[809]543        @brief Assignment operator: Adds all rules of the other mask.
544        @param other The other mask
545        @return A reference to the mask itself
546    */
[807]547    ClassTreeMask& ClassTreeMask::operator=(const ClassTreeMask& other)
548    {
[809]549        // Make a copy to avoid troubles with self-assignments (like A = A).
[807]550        ClassTreeMask temp(other);
551
[809]552        // Removes all current rules
[807]553        this->reset();
554
[809]555        // Copy all rules from the other mask
[807]556        for (ClassTreeMaskIterator it = temp.root_; it; ++it)
[817]557            this->add(it->getClass(), it->isIncluded(), false, false);
[807]558
[809]559        // Return a reference to the mask itself
[807]560        return (*this);
561    }
562
[809]563    /**
[1052]564        @brief Compares the mask with another mask and returns true if they represent the same logic.
565        @param other The other mask
566        @return True if both masks represent the same logic
567    */
568    bool ClassTreeMask::operator==(const ClassTreeMask& other) const
569    {
570        ClassTreeMask temp1 = other;
571        ClassTreeMask temp2 = (*this);
572
573        temp1.clean();
574        temp2.clean();
575
576        ClassTreeMaskIterator it1 = temp1.root_;
577        ClassTreeMaskIterator it2 = temp2.root_;
578
579        for ( ; it1 && it2; ++it1, ++it2)
580            if (it1->getClass() != it2->getClass())
581                return false;
582
583        return true;
584    }
585
586    /**
587        @brief Compares the mask with another mask and returns true if they represent different logics.
588        @param other The other mask
589        @return True if the masks represent different logics
590    */
591    bool ClassTreeMask::operator!=(const ClassTreeMask& other) const
592    {
593        return (!((*this) == other));
594    }
595
596    /**
[809]597        @brief Prefix operator + does nothing.
598        @return A reference to the mask itself
599    */
[807]600    ClassTreeMask& ClassTreeMask::operator+()
601    {
602        return (*this);
603    }
604
[809]605    /**
606        @brief Prefix operator - inverts the mask.
607        @return The inverted mask
608    */
[807]609    ClassTreeMask ClassTreeMask::operator-() const
610    {
611        return (!(*this));
612    }
613
[809]614    /**
615        @brief Adds two masks in the sense of a union (all classes that are included in at least one of the masks will be included in the resulting mask too).
616        @param other The mask to unite with
617        @return The union
618    */
[803]619    ClassTreeMask ClassTreeMask::operator+(const ClassTreeMask& other) const
620    {
[809]621        // Create a new mask
[803]622        ClassTreeMask newmask;
[809]623
624        // Add all nodes from the first mask, calculate the rule with the or-operation
[803]625        for (ClassTreeMaskIterator it = this->root_; it; ++it)
626        {
627            const Identifier* subclass = it->getClass();
[1021]628            newmask.add(subclass, this->isIncluded(subclass) or other.isIncluded(subclass), false, false);
[803]629        }
[809]630
631        // Add all nodes from the second mask, calculate the rule with the or-operation
[803]632        for (ClassTreeMaskIterator it = other.root_; it; ++it)
633        {
634            const Identifier* subclass = it->getClass();
[1021]635            newmask.add(subclass, this->isIncluded(subclass) or other.isIncluded(subclass), false, false);
[803]636        }
[809]637
638        // Drop all redundant rules
[803]639        newmask.clean();
640
[809]641        // Return the new mask
[803]642        return newmask;
643    }
644
[809]645    /**
646        @brief Intersects two masks (only classes that are included in both masks will be included in the resulting mask too).
647        @param other The mask to intersect with
648        @return The intersection
649    */
[803]650    ClassTreeMask ClassTreeMask::operator*(const ClassTreeMask& other) const
651    {
[809]652        // Create a new mask
[803]653        ClassTreeMask newmask;
[809]654
655        // Add all nodes from the first mask, calculate the rule with the and-operation
[803]656        for (ClassTreeMaskIterator it = this->root_; it; ++it)
657        {
658            const Identifier* subclass = it->getClass();
[1021]659            newmask.add(subclass, this->isIncluded(subclass) and other.isIncluded(subclass), false, false);
[803]660        }
[809]661
662        // Add all nodes from the second mask, calculate the rule with the and-operation
[803]663        for (ClassTreeMaskIterator it = other.root_; it; ++it)
664        {
665            const Identifier* subclass = it->getClass();
[1021]666            newmask.add(subclass, this->isIncluded(subclass) and other.isIncluded(subclass), false, false);
[803]667        }
[809]668
669        // Drop all redundant rules
[803]670        newmask.clean();
671
[809]672        // Return the new mask
[803]673        return newmask;
674    }
675
[809]676    /**
677        @brief Removes all elements of the second mask from the first mask (all classes that are included in the first mask stay included, except those that are included in the second mask too).
678        @param other The mask to subtract.
679        @return The difference
680    */
[807]681    ClassTreeMask ClassTreeMask::operator-(const ClassTreeMask& other) const
682    {
683        return ((*this) * (!other));
684    }
685
[809]686    /**
687        @brief Inverts the mask (all included classes are now excluded and vice versa).
688        @return The complement
689    */
[803]690    ClassTreeMask ClassTreeMask::operator!() const
691    {
[809]692        // Create a new mask
[803]693        ClassTreeMask newmask;
[809]694
695        // Add all nodes from the other mask, inverting the rules
[803]696        for (ClassTreeMaskIterator it = this->root_; it; ++it)
697        {
698            const Identifier* subclass = it->getClass();
[817]699            newmask.add(subclass, !this->isIncluded(subclass), false, false);
[803]700        }
[809]701
702        // Return the new mask
[803]703        return newmask;
704    }
705
[809]706    /**
707        @brief Unites this mask with another mask.
708        @param other The other mask
709        @return A reference to the mask itself
710    */
[807]711    ClassTreeMask& ClassTreeMask::operator+=(const ClassTreeMask& other)
[803]712    {
[807]713        (*this) = (*this) + other;
714        return (*this);
[803]715    }
716
[809]717    /**
718        @brief Intersects this mask with another mask.
719        @param other The other mask
720        @return A reference to the mask itself
721    */
[807]722    ClassTreeMask& ClassTreeMask::operator*=(const ClassTreeMask& other)
723    {
724        (*this) = (*this) * other;
725        return (*this);
726    }
727
[809]728    /**
729        @brief Subtracts another mask from this mask.
730        @param other The other mask
731        @return A reference to the mask itself
732    */
[807]733    ClassTreeMask& ClassTreeMask::operator-=(const ClassTreeMask& other)
734    {
735        (*this) = (*this) - other;
736        return (*this);
737    }
738
[809]739    /**
740        @brief Intersects two masks (only classes that are included in both masks will be included in the resulting mask too).
741        @param other The mask to intersect with
742        @return The intersection
743    */
[803]744    ClassTreeMask ClassTreeMask::operator&(const ClassTreeMask& other) const
745    {
746        return ((*this) * other);
747    }
748
[809]749    /**
750        @brief Adds two masks in the sense of a union (all classes that are included in at least one of the masks will be included in the resulting mask too).
751        @param other The mask to unite with
752        @return The union
753    */
[803]754    ClassTreeMask ClassTreeMask::operator|(const ClassTreeMask& other) const
755    {
756        return ((*this) + other);
757    }
758
[809]759    /**
760        @brief Joins two masks in the sense of a xor (exclusivity) operation (all classes that are included in exactly one of the masks, but not in both, will be included in the resulting mask too).
761        @param other The mask to join with
762        @return The result
763    */
[803]764    ClassTreeMask ClassTreeMask::operator^(const ClassTreeMask& other) const
765    {
[809]766        // Create a new mask
[803]767        ClassTreeMask newmask;
[809]768
769        // Add all nodes from the first mask, calculate the rule with the xor-operation
[803]770        for (ClassTreeMaskIterator it = this->root_; it; ++it)
771        {
772            const Identifier* subclass = it->getClass();
[1021]773            newmask.add(subclass, this->isIncluded(subclass) xor other.isIncluded(subclass), false, false);
[803]774        }
[809]775
776        // Add all nodes from the second mask, calculate the rule with the xor-operation
[803]777        for (ClassTreeMaskIterator it = other.root_; it; ++it)
778        {
779            const Identifier* subclass = it->getClass();
[1021]780            newmask.add(subclass, this->isIncluded(subclass) xor other.isIncluded(subclass), false, false);
[803]781        }
[809]782
783        // Drop all redundant rules
[803]784        newmask.clean();
785
[809]786        // Return the new mask
[803]787        return newmask;
788    }
789
[809]790    /**
791        @brief Inverts the mask (all included classes are now excluded and vice versa).
792        @return The complement
793    */
[803]794    ClassTreeMask ClassTreeMask::operator~() const
795    {
796        return (!(*this));
797    }
[807]798
[809]799    /**
800        @brief Intersects this mask with another mask (and-operation)
801        @param other The other mask
802        @return A reference to the mask itself
803    */
[807]804    ClassTreeMask& ClassTreeMask::operator&=(const ClassTreeMask& other)
805    {
806        (*this) = (*this) & other;
807        return (*this);
808    }
809
[809]810    /**
811        @brief Unites this mask with another mask (or-operation).
812        @param other The other mask
813        @return A reference to the mask itself
814    */
[807]815    ClassTreeMask& ClassTreeMask::operator|=(const ClassTreeMask& other)
816    {
817        (*this) = (*this) | other;
818        return (*this);
819    }
820
[809]821    /**
822        @brief Joins this mask with another mask with a xor-operation.
823        @param other The other mask
824        @return A reference to the mask itself
825    */
[807]826    ClassTreeMask& ClassTreeMask::operator^=(const ClassTreeMask& other)
827    {
828        (*this) = (*this) ^ other;
829        return (*this);
830    }
831
[809]832    /**
833        @brief Converts the content of a mask into a human readable string and puts it on the ostream.
834        @param out The ostream
835        @param mask The mask
836        @return A reference to the ostream
837    */
[807]838    std::ostream& operator<<(std::ostream& out, const ClassTreeMask& mask)
839    {
[809]840        // Iterate through all rules
[807]841        for (ClassTreeMaskIterator it = mask.root_; it; ++it)
842        {
[809]843            // Calculate the prefix: + means included, - means excluded
[807]844            if (it->isIncluded())
845                out << "+";
846            else
847                out << "-";
848
[809]849            // Put the name of the corresponding class on the stream
[807]850            out << it->getClass()->getName() << " ";
851        }
852
853        return out;
854    }
[802]855}
Note: See TracBrowser for help on using the repository browser.