Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core/src/orxonox/core/ClassTreeMask.cc @ 818

Last change on this file since 818 was 818, checked in by landauf, 16 years ago

new feature in ClassTreeMask:
you can include or exclude a single class without changing the rule for inheriting classes

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