Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/console/src/core/ClassTreeMask.cc @ 1255

Last change on this file since 1255 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
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
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
29/**
30    @file ClassTreeMask.cc
31    @brief Implementation of the ClassTreeMask, ClassTreeMaskNode and ClassTreeMaskIterator classes.
32*/
33
34#include "ClassTreeMask.h"
35#include "Identifier.h"
36#include "BaseObject.h"
37
38namespace orxonox
39{
40    // ###############################
41    // ###    ClassTreeMaskNode    ###
42    // ###############################
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    */
48    ClassTreeMaskNode::ClassTreeMaskNode(const Identifier* subclass, bool bIncluded)
49    {
50        this->subclass_ = subclass;
51        this->bIncluded_ = bIncluded;
52    }
53
54    /**
55        @brief Destructor: Deletes all subnodes.
56    */
57    ClassTreeMaskNode::~ClassTreeMaskNode()
58    {
59        // Go through the list of all subnodes and delete them
60        this->deleteAllSubnodes();
61    }
62
63    /**
64        @brief Sets the rule for the node to "included".
65        @param overwrite True = overwrite previously added rules for inheriting classes
66    */
67    void ClassTreeMaskNode::include(bool overwrite)
68    {
69        this->setIncluded(true, overwrite);
70    }
71
72    /**
73        @brief Sets the rule for the node to "excluded".
74        @param overwrite True = overwrite previously added rules for inheriting classes
75    */
76    void ClassTreeMaskNode::exclude(bool overwrite)
77    {
78        this->setIncluded(false, overwrite);
79    }
80
81    /**
82        @brief Sets the rule for the node to a given value and erases all following rules.
83        @param bIncluded The rule: included (true) or excluded (false)
84        @param overwrite True = overwrite previously added rules for inheriting classes
85    */
86    void ClassTreeMaskNode::setIncluded(bool bIncluded, bool overwrite)
87    {
88        if (overwrite)
89            this->deleteAllSubnodes();
90
91        this->bIncluded_ = bIncluded;
92    }
93
94    /**
95        @brief Adds a new subnode to the list of subnodes.
96        @param subnode The new subnode
97    */
98    void ClassTreeMaskNode::addSubnode(ClassTreeMaskNode* subnode)
99    {
100        this->subnodes_.insert(this->subnodes_.end(), subnode);
101    }
102
103    /**
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    /**
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++));
138
139        // Clear the list
140        this->subnodes_.clear();
141    }
142
143
144    // ###############################
145    // ###  ClassTreeMaskIterator  ###
146    // ###############################
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    */
151    ClassTreeMaskIterator::ClassTreeMaskIterator(ClassTreeMaskNode* node)
152    {
153        // Create a list and put the root-note into it
154        std::list<ClassTreeMaskNode*>::iterator it = this->rootlist_.insert(this->rootlist_.end(), node);
155
156        // Put the iterator to the only element of the list and the corresponding end()-iterator on the stack
157        this->nodes_.push(std::pair<std::list<ClassTreeMaskNode*>::iterator, std::list<ClassTreeMaskNode*>::iterator>(it, this->rootlist_.end()));
158    }
159
160    /**
161        @brief Destructor: Does nothing.
162    */
163    ClassTreeMaskIterator::~ClassTreeMaskIterator()
164    {
165    }
166
167    /**
168        @brief Iterates through the rule-tree.
169        @return A reference to the iterator itself
170    */
171    ClassTreeMaskIterator& ClassTreeMaskIterator::operator++()
172    {
173        // Check if the actual node has subnodes
174        if ((*this->nodes_.top().first)->subnodes_.begin() != (*this->nodes_.top().first)->subnodes_.end())
175        {
176            // Yes it has: Push an iterator, pointing at the first subnode, on the stack
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()));
178        }
179        else
180        {
181            // No subnodes, meaning we reached a leaf: Go to the next node
182            do
183            {
184                // Iterate one step in the current list
185                ++this->nodes_.top().first;
186
187                // Check if we reached the end of the list (the second item in the stored pair always represents the end)
188                if (this->nodes_.top().first == this->nodes_.top().second)
189                {
190                    // Yes we've reached the end: Pop the list-iterator from the stack
191                    this->nodes_.pop();
192
193                    // Continue with the loop, meaning: Try to iterate through the previous list
194                    continue;
195                }
196
197                // If we reached this point, we aren't yet at the end of the list: Leave the loop
198                break;
199            } while (!this->nodes_.empty()); // Stop looping if the stack is empty, meaning: We've iterated to the end
200        }
201
202        // Finally return a reference to the iterator itself
203        return *this;
204    }
205
206    /**
207        @brief Returns a pointer to the ClassTreeMaskNode whereon the iterator points.
208        @return The pointer to the node
209    */
210    ClassTreeMaskNode* ClassTreeMaskIterator::operator*() const
211    {
212        return (*this->nodes_.top().first);
213    }
214
215    /**
216        @brief Returns a pointer to the ClassTreeMaskNode whereon the iterator points.
217        @return The pointer to the node
218    */
219    ClassTreeMaskNode* ClassTreeMaskIterator::operator->() const
220    {
221        return (*this->nodes_.top().first);
222    }
223
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    */
228    ClassTreeMaskIterator::operator bool()
229    {
230        return (!this->nodes_.empty());
231    }
232
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    */
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
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    */
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    // ###############################
261    // ###      ClassTreeMask      ###
262    // ###############################
263    /**
264        @brief Constructor: Adds the root-node of the tree with the first rule ("include everything").
265    */
266    ClassTreeMask::ClassTreeMask()
267    {
268        this->root_ = new ClassTreeMaskNode(ClassManager<BaseObject>::getIdentifier(), true);
269    }
270
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    */
275    ClassTreeMask::ClassTreeMask(const ClassTreeMask& other)
276    {
277        this->root_ = new ClassTreeMaskNode(ClassManager<BaseObject>::getIdentifier(), true);
278        for (ClassTreeMaskIterator it = other.root_; it; ++it)
279            this->add(it->getClass(), it->isIncluded(), false);
280    }
281
282    /**
283        @brief Destructor: Deletes the root node (which will delete all subnodes too).
284    */
285    ClassTreeMask::~ClassTreeMask()
286    {
287        delete this->root_;
288    }
289
290    /**
291        @brief Adds a new "include" rule for a given subclass to the mask.
292        @param subclass The subclass
293        @param overwrite True = overwrite previously added rules for inheriting classes
294        @param clean True = clean the tree after adding the new rule
295    */
296    void ClassTreeMask::include(const Identifier* subclass, bool overwrite, bool clean)
297    {
298        this->add(subclass, true, overwrite, clean);
299    }
300
301    /**
302        @brief Adds a new "exclude" rule for a given subclass to the mask.
303        @param subclass The subclass
304        @param overwrite True = overwrite previously added rules for inheriting classes
305        @param clean True = clean the tree after adding the new rule
306    */
307    void ClassTreeMask::exclude(const Identifier* subclass, bool overwrite, bool clean)
308    {
309        this->add(subclass, false, overwrite, clean);
310    }
311
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)
316        @param overwrite True = overwrite previously added rules for inheriting classes
317        @param clean True = clean the tree after adding the new rule
318    */
319    void ClassTreeMask::add(const Identifier* subclass, bool bInclude, bool overwrite, bool clean)
320    {
321        // Check if the given subclass is a child of our root-class
322        if (subclass->isA(this->root_->getClass()))
323        {
324            // Yes it is: Just add the rule to the three
325            this->add(this->root_, subclass, bInclude, overwrite);
326        }
327        else
328        {
329            // No it's not: Search for classes inheriting from the given class and add the rules for them
330            for (std::set<const Identifier*>::const_iterator it = subclass->getDirectChildrenBegin(); it != subclass->getDirectChildrenEnd(); ++it)
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);
334        }
335
336        // Clean the rule-tree
337        if (clean)
338            this->clean();
339    }
340
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)
346        @param overwrite True = overwrite previously added rules for inheriting classes
347    */
348    void ClassTreeMask::add(ClassTreeMaskNode* node, const Identifier* subclass, bool bInclude, bool overwrite)
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
354            node->setIncluded(bInclude, overwrite);
355            return;
356        }
357        else if (subclass->isA(node->getClass()))
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                {
364                    // We've found an existing node -> delegate the work with a recursive function-call and return
365                    this->add(*it, subclass, bInclude, overwrite);
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
373            // Search for nodes that should actually be subnodes of our new node and erase them
374            for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); )
375            {
376                if ((*it)->getClass()->isChildOf(subclass))
377                {
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
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
397    /**
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    {
425        for (std::set<const Identifier*>::const_iterator it = subclass->getDirectChildrenBegin(); it != subclass->getDirectChildrenEnd(); ++it)
426            this->add(*it, this->isIncluded(*it), false, false);
427
428        this->add(subclass, bInclude, false, clean);
429    }
430
431    /**
432        @brief Resets the mask to "include everything".
433    */
434    void ClassTreeMask::reset()
435    {
436        delete this->root_;
437        this->root_ = new ClassTreeMaskNode(ClassManager<BaseObject>::getIdentifier(), true);
438    }
439
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    */
445    bool ClassTreeMask::isIncluded(const Identifier* subclass) const
446    {
447        return this->isIncluded(this->root_, subclass);
448    }
449
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    */
456    bool ClassTreeMask::isIncluded(ClassTreeMaskNode* node, const Identifier* subclass) const
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
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.
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
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    */
485    bool ClassTreeMask::isExcluded(const Identifier* subclass) const
486    {
487        return (!this->isIncluded(subclass));
488    }
489
490    /**
491        @brief Removes all unneeded rules that don't change the information of the mask.
492    */
493    void ClassTreeMask::clean()
494    {
495        this->clean(this->root_);
496    }
497
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    */
502    void ClassTreeMask::clean(ClassTreeMaskNode* node)
503    {
504        // Iterate through all subnodes of the given node
505        for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); )
506        {
507            // Recursive function-call: Clean the subnode
508            this->clean(*it);
509
510            // Now check if the subnode contains the same rule as the current node
511            if ((*it)->isIncluded() == node->isIncluded())
512            {
513                // It does: Move all subnodes of the redundant subnode to the current node
514                node->subnodes_.insert(node->subnodes_.end(), (*it)->subnodes_.begin(), (*it)->subnodes_.end());
515                (*it)->subnodes_.clear();
516
517                // Remove the redundant subnode from the current node
518                node->subnodes_.erase(it++);
519            }
520            else
521            {
522                // The subnode is necessary: Move on to the next subnode
523                ++it;
524            }
525        }
526    }
527
528    /**
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    /**
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    */
547    ClassTreeMask& ClassTreeMask::operator=(const ClassTreeMask& other)
548    {
549        // Make a copy to avoid troubles with self-assignments (like A = A).
550        ClassTreeMask temp(other);
551
552        // Removes all current rules
553        this->reset();
554
555        // Copy all rules from the other mask
556        for (ClassTreeMaskIterator it = temp.root_; it; ++it)
557            this->add(it->getClass(), it->isIncluded(), false, false);
558
559        // Return a reference to the mask itself
560        return (*this);
561    }
562
563    /**
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    /**
597        @brief Prefix operator + does nothing.
598        @return A reference to the mask itself
599    */
600    ClassTreeMask& ClassTreeMask::operator+()
601    {
602        return (*this);
603    }
604
605    /**
606        @brief Prefix operator - inverts the mask.
607        @return The inverted mask
608    */
609    ClassTreeMask ClassTreeMask::operator-() const
610    {
611        return (!(*this));
612    }
613
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    */
619    ClassTreeMask ClassTreeMask::operator+(const ClassTreeMask& other) const
620    {
621        // Create a new mask
622        ClassTreeMask newmask;
623
624        // Add all nodes from the first mask, calculate the rule with the or-operation
625        for (ClassTreeMaskIterator it = this->root_; it; ++it)
626        {
627            const Identifier* subclass = it->getClass();
628            newmask.add(subclass, this->isIncluded(subclass) or other.isIncluded(subclass), false, false);
629        }
630
631        // Add all nodes from the second mask, calculate the rule with the or-operation
632        for (ClassTreeMaskIterator it = other.root_; it; ++it)
633        {
634            const Identifier* subclass = it->getClass();
635            newmask.add(subclass, this->isIncluded(subclass) or other.isIncluded(subclass), false, false);
636        }
637
638        // Drop all redundant rules
639        newmask.clean();
640
641        // Return the new mask
642        return newmask;
643    }
644
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    */
650    ClassTreeMask ClassTreeMask::operator*(const ClassTreeMask& other) const
651    {
652        // Create a new mask
653        ClassTreeMask newmask;
654
655        // Add all nodes from the first mask, calculate the rule with the and-operation
656        for (ClassTreeMaskIterator it = this->root_; it; ++it)
657        {
658            const Identifier* subclass = it->getClass();
659            newmask.add(subclass, this->isIncluded(subclass) and other.isIncluded(subclass), false, false);
660        }
661
662        // Add all nodes from the second mask, calculate the rule with the and-operation
663        for (ClassTreeMaskIterator it = other.root_; it; ++it)
664        {
665            const Identifier* subclass = it->getClass();
666            newmask.add(subclass, this->isIncluded(subclass) and other.isIncluded(subclass), false, false);
667        }
668
669        // Drop all redundant rules
670        newmask.clean();
671
672        // Return the new mask
673        return newmask;
674    }
675
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    */
681    ClassTreeMask ClassTreeMask::operator-(const ClassTreeMask& other) const
682    {
683        return ((*this) * (!other));
684    }
685
686    /**
687        @brief Inverts the mask (all included classes are now excluded and vice versa).
688        @return The complement
689    */
690    ClassTreeMask ClassTreeMask::operator!() const
691    {
692        // Create a new mask
693        ClassTreeMask newmask;
694
695        // Add all nodes from the other mask, inverting the rules
696        for (ClassTreeMaskIterator it = this->root_; it; ++it)
697        {
698            const Identifier* subclass = it->getClass();
699            newmask.add(subclass, !this->isIncluded(subclass), false, false);
700        }
701
702        // Return the new mask
703        return newmask;
704    }
705
706    /**
707        @brief Unites this mask with another mask.
708        @param other The other mask
709        @return A reference to the mask itself
710    */
711    ClassTreeMask& ClassTreeMask::operator+=(const ClassTreeMask& other)
712    {
713        (*this) = (*this) + other;
714        return (*this);
715    }
716
717    /**
718        @brief Intersects this mask with another mask.
719        @param other The other mask
720        @return A reference to the mask itself
721    */
722    ClassTreeMask& ClassTreeMask::operator*=(const ClassTreeMask& other)
723    {
724        (*this) = (*this) * other;
725        return (*this);
726    }
727
728    /**
729        @brief Subtracts another mask from this mask.
730        @param other The other mask
731        @return A reference to the mask itself
732    */
733    ClassTreeMask& ClassTreeMask::operator-=(const ClassTreeMask& other)
734    {
735        (*this) = (*this) - other;
736        return (*this);
737    }
738
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    */
744    ClassTreeMask ClassTreeMask::operator&(const ClassTreeMask& other) const
745    {
746        return ((*this) * other);
747    }
748
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    */
754    ClassTreeMask ClassTreeMask::operator|(const ClassTreeMask& other) const
755    {
756        return ((*this) + other);
757    }
758
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    */
764    ClassTreeMask ClassTreeMask::operator^(const ClassTreeMask& other) const
765    {
766        // Create a new mask
767        ClassTreeMask newmask;
768
769        // Add all nodes from the first mask, calculate the rule with the xor-operation
770        for (ClassTreeMaskIterator it = this->root_; it; ++it)
771        {
772            const Identifier* subclass = it->getClass();
773            newmask.add(subclass, this->isIncluded(subclass) xor other.isIncluded(subclass), false, false);
774        }
775
776        // Add all nodes from the second mask, calculate the rule with the xor-operation
777        for (ClassTreeMaskIterator it = other.root_; it; ++it)
778        {
779            const Identifier* subclass = it->getClass();
780            newmask.add(subclass, this->isIncluded(subclass) xor other.isIncluded(subclass), false, false);
781        }
782
783        // Drop all redundant rules
784        newmask.clean();
785
786        // Return the new mask
787        return newmask;
788    }
789
790    /**
791        @brief Inverts the mask (all included classes are now excluded and vice versa).
792        @return The complement
793    */
794    ClassTreeMask ClassTreeMask::operator~() const
795    {
796        return (!(*this));
797    }
798
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    */
804    ClassTreeMask& ClassTreeMask::operator&=(const ClassTreeMask& other)
805    {
806        (*this) = (*this) & other;
807        return (*this);
808    }
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    */
815    ClassTreeMask& ClassTreeMask::operator|=(const ClassTreeMask& other)
816    {
817        (*this) = (*this) | other;
818        return (*this);
819    }
820
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    */
826    ClassTreeMask& ClassTreeMask::operator^=(const ClassTreeMask& other)
827    {
828        (*this) = (*this) ^ other;
829        return (*this);
830    }
831
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    */
838    std::ostream& operator<<(std::ostream& out, const ClassTreeMask& mask)
839    {
840        // Iterate through all rules
841        for (ClassTreeMaskIterator it = mask.root_; it; ++it)
842        {
843            // Calculate the prefix: + means included, - means excluded
844            if (it->isIncluded())
845                out << "+";
846            else
847                out << "-";
848
849            // Put the name of the corresponding class on the stream
850            out << it->getClass()->getName() << " ";
851        }
852
853        return out;
854    }
855}
Note: See TracBrowser for help on using the repository browser.