Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/ClassTreeMask.h @ 7268

Last change on this file since 7268 was 7268, checked in by rgrieder, 14 years ago

operator=() should not return constant references.

  • Property svn:eol-style set to native
File size: 13.7 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
31    @brief Definition of the ClassTreeMask, ClassTreeMaskNode and ClassTreeMaskIterator classes.
32
33    ClassTreeMask is a class to define a mask of the class-tree beginning with BaseObject.
34    You can include or exclude classes by calling the corresponding functions with the
35    Identifier of the class.
36
37    You can work with a ClassTreeMask in the sense of the set-theory, meaning that you can create
38    unions, intersections, complements and differences by using overloaded operators.
39
40
41
42    The ClassTreeMask is internally represented by a tree. The nodes in the tree are
43    ClassTreeMaskNodes, containing the rule (included or excluded) for this class and all
44    subclasses and a list of all subnodes. To minimize the size, the tree contains only
45    nodes changing the mask. By adding new rules, the tree gets reordered dynamically.
46
47    Adding a new rule overwrites all rules assigned to inherited classes. Use overwrite = false
48    if you don't like this feature. Useless rules that don't change the information of the mask
49    aren't saved in the internal tree. Use clean = false if you wan't to save them.
50
51    With overwrite = false and clean = false it doesn't matter in which way you create the mask.
52    You can manually drop useless rules from the tree by calling clean().
53
54
55
56    Because of the complicated shape of the internal tree, there is an iterator to iterate
57    through all ClassTreeMaskNodes of a mask. It starts with the BaseObject and moves on to
58    the first subclass until it reaches a leaf of the tree. Then the iterator moves one step
59    back and iterates to the second subclass. If there are no more subclasses, it steps another
60    step back, and so on.
61
62    Example: A and B are children of BaseObject, A1 and A2 are children of A, B1 and B2 are children of B.
63    The ClassTreeMaskIterator would move trough the tree in the following order:
64    BaseObject, A, A1, A2, B, B1, B2.
65
66    Note that the iterator doesn't move trough the whole class-tree, but only through the
67    internal tree of the mask, containing the minimal needed set of nodes to describe the mask.
68*/
69
70#ifndef _ClassTreeMask_H__
71#define _ClassTreeMask_H__
72
73#include "CorePrereqs.h"
74
75#include <list>
76#include <stack>
77#include "BaseObject.h"
78#include "Iterator.h"
79
80namespace orxonox
81{
82    // ###################################
83    // ###      ClassTreeMaskNode      ###
84    // ###################################
85    //! The ClassTreeMaskNode is a node in the internal tree of the ClassTreeMask, containing the rules of the mask.
86    /**
87        The ClassTreeMaskNode is used to store the rule (included or excluded) for a given
88        class (described by the corresponding Identifier). The nodes are used in the internal
89        tree of ClassTreeMask. To build a tree, they store a list of all subnodes.
90    */
91    class _CoreExport ClassTreeMaskNode
92    {
93        friend class ClassTreeMask;
94        friend class ClassTreeMaskIterator;
95        friend class ClassTreeMaskObjectIterator;
96
97        public:
98            ClassTreeMaskNode(const Identifier* subclass, bool bIncluded = true);
99            ~ClassTreeMaskNode();
100
101            void include(bool overwrite = true);
102            void exclude(bool overwrite = true);
103            void setIncluded(bool bIncluded, bool overwrite = true);
104
105            void addSubnode(ClassTreeMaskNode* subnode);
106
107            /** @brief Tells if the rule is "included" or not. @return The rule: true = included, false = excluded */
108            inline bool isIncluded() const { return this->bIncluded_; }
109            /** @brief Tells if the rule is "excluded" or not. @return The inverted rule: true = excluded, false = included */
110            inline bool isExcluded() const { return (!this->bIncluded_); }
111
112            /** @brief Returns the Identifier of the class the rule refers to. @return The Identifier representing the class */
113            inline const Identifier* getClass() const { return this->subclass_; }
114
115            /** @brief Returns true if the Node has some subnodes. */
116            inline bool hasSubnodes() const { return !this->subnodes_.empty(); }
117
118        private:
119            void deleteAllSubnodes();
120
121            const Identifier* subclass_;                //!< The Identifier of the subclass the rule refers to
122            bool bIncluded_;                            //!< The rule: included or excluded
123            std::list<ClassTreeMaskNode*> subnodes_;    //!< A list containing all subnodes in the tree
124    };
125
126
127    // ###################################
128    // ###    ClassTreeMaskIterator    ###
129    // ###################################
130    //! The ClassTreeMaskIterator moves through all ClassTreeMaskNodes of the internal tree of a ClassTreeMask, containing the rules.
131    /**
132        Because of the complicated shape of the internal rule-tree of ClassTreeMask, an
133        iterator is used to move through all nodes of the tree. It starts with the BaseObject
134        and moves on to the first subclass until it reaches a leaf of the tree. Then the
135        iterator moves one step back and iterates to the second subclass. If there are no more
136        subclasses, it steps another step back, and so on.
137    */
138    class _CoreExport ClassTreeMaskIterator
139    {
140        public:
141            ClassTreeMaskIterator(ClassTreeMaskNode* node);
142            ~ClassTreeMaskIterator();
143
144            const ClassTreeMaskIterator& operator++();
145            ClassTreeMaskNode* operator*() const;
146            ClassTreeMaskNode* operator->() const;
147            operator bool() const;
148            bool operator==(ClassTreeMaskNode* compare) const;
149            bool operator!=(ClassTreeMaskNode* compare) const;
150
151        private:
152            std::stack<std::pair<std::list<ClassTreeMaskNode*>::iterator, std::list<ClassTreeMaskNode*>::iterator> > nodes_;    //!< A stack to store list-iterators
153            std::list<ClassTreeMaskNode*> rootlist_;                                                                            //!< A list for internal use (it only stores the root-node)
154    };
155
156
157    // ###################################
158    // ###        ClassTreeMask        ###
159    // ###################################
160    //! The ClassTreeMask is a set of rules, containing the information for each class whether it's included or not.
161    /**
162        With a ClassTreeMask, you can include or exclude subtrees of the class-tree, starting
163        with a given subclass, described by the corresponding Identifier. To minimize the size
164        of the mask, the mask saves only relevant rules. But you can manually add rules that
165        don't change the information of the mask by using clean = false. If you want to drop
166        useless rules, call the clean() function.
167    */
168    class _CoreExport ClassTreeMask
169    {
170        friend class ClassTreeMaskObjectIterator;
171
172        public:
173            ClassTreeMask();
174            ClassTreeMask(const ClassTreeMask& other);
175            ~ClassTreeMask();
176
177            void include(const Identifier* subclass, bool overwrite = true, bool clean = true);
178            void exclude(const Identifier* subclass, bool overwrite = true, bool clean = true);
179            void add(const Identifier* subclass, bool bInclude, bool overwrite = true, bool clean = true);
180
181            void includeSingle(const Identifier* subclass, bool clean = true);
182            void excludeSingle(const Identifier* subclass, bool clean = true);
183            void addSingle(const Identifier* subclass, bool bInclude, bool clean = true);
184
185            void reset();
186            void clean();
187
188            bool isIncluded(const Identifier* subclass) const;
189            bool isExcluded(const Identifier* subclass) const;
190
191            /** @brief Begin of the ClassTreeMaskObjectIterator. */
192            inline const ClassTreeMask& begin() const { return (*this); }
193            /** @brief End of the ClassTreeMaskObjectIterator. */
194            inline BaseObject*          end()   const { return 0; }
195
196            ClassTreeMask& operator=(const ClassTreeMask& other);
197
198            bool operator==(const ClassTreeMask& other) const;
199            bool operator!=(const ClassTreeMask& other) const;
200
201            const ClassTreeMask& operator+() const;
202            ClassTreeMask operator-() const;
203
204            ClassTreeMask operator+(const ClassTreeMask& other) const;
205            ClassTreeMask operator*(const ClassTreeMask& other) const;
206            ClassTreeMask operator-(const ClassTreeMask& other) const;
207            ClassTreeMask operator!() const;
208
209            const ClassTreeMask& operator+=(const ClassTreeMask& other);
210            const ClassTreeMask& operator*=(const ClassTreeMask& other);
211            const ClassTreeMask& operator-=(const ClassTreeMask& other);
212
213            ClassTreeMask operator&(const ClassTreeMask& other) const;
214            ClassTreeMask operator|(const ClassTreeMask& other) const;
215            ClassTreeMask operator^(const ClassTreeMask& other) const;
216            ClassTreeMask operator~() const;
217
218            const ClassTreeMask& operator&=(const ClassTreeMask& other);
219            const ClassTreeMask& operator|=(const ClassTreeMask& other);
220            const ClassTreeMask& operator^=(const ClassTreeMask& other);
221
222            friend std::ostream& operator<<(std::ostream& out, const ClassTreeMask& mask);
223
224        private:
225            void add(ClassTreeMaskNode* node, const Identifier* subclass, bool bInclude, bool overwrite = true);
226            bool isIncluded(ClassTreeMaskNode* node, const Identifier* subclass) const;
227            void clean(ClassTreeMaskNode* node);
228            bool nodeExists(const Identifier* subclass);
229
230            ClassTreeMaskNode* root_;   //!< The root-node of the internal rule-tree, usually BaseObject
231    };
232
233
234    // ###################################
235    // ### ClassTreeMaskObjectIterator ###
236    // ###################################
237    //! The ClassTreeMaskObjectIterator iterates through all objects of all classes, included by a ClassTreeMask.
238    /**
239        The ClassTreeMaskObjectIterator iterates through all objects of all classes,
240        included by a ClassTreeMask. This is done the following way:
241
242        ClassTreeMask mask;
243        for (ClassTreeMaskObjectIterator it = mask.begin(); it != mask.end(); ++it)
244            it->doSomething();
245
246        Note: The ClassTreeMaskObjectIterator handles all objects as BaseObjects. If
247              you want to use another class, you should use a dynamic_cast.
248
249        Performance of ClassTreeMaskObjectIterator is good as long as you don't exclude
250        subclasses of included classes. Of course you can still exlucde subclasses, but
251        if this is done more often, we need a new implementation using a second ObjectList
252        in the Identifier, containing all objects of exactly one class.
253    */
254    class _CoreExport ClassTreeMaskObjectIterator
255    {
256        public:
257            /** @brief Defaultconstructor: Does nothing. */
258            inline ClassTreeMaskObjectIterator() {}
259            /** @brief Constructor: Initializes the iterator from a given ClassTreeMask. @param mask The mask */
260            inline ClassTreeMaskObjectIterator(const ClassTreeMask& mask) { (*this) = mask; }
261
262            ClassTreeMaskObjectIterator& operator=(const ClassTreeMask& mask);
263
264            const ClassTreeMaskObjectIterator& operator++();
265
266            /** @brief Returns true if the ClassTreeMaskObjectIterator points at the given object. @param pointer The pointer of the object */
267            inline bool operator==(BaseObject* pointer) const { return (this->objectIterator_ && (*this->objectIterator_) == pointer) || (!this->objectIterator_ && pointer == 0); }
268            /** @brief Returns true if the ClassTreeMaskObjectIterator doesn't point at the given object. @param pointer The pointer of the object */
269            inline bool operator!=(BaseObject* pointer) const { return (this->objectIterator_ && (*this->objectIterator_) != pointer) || (!this->objectIterator_ && pointer != 0); }
270            /** @brief Returns true if the ClassTreeMaskObjectIterator hasn't already reached the end. */
271            inline operator bool() const { return (this->objectIterator_); }
272            /** @brief Returns the object the ClassTreeMaskObjectIterator currently points at. */
273            inline BaseObject* operator*() const { return (*this->objectIterator_); }
274            /** @brief Returns the object the ClassTreeMaskObjectIterator currently points at. */
275            inline BaseObject* operator->() const { return (*this->objectIterator_); }
276
277        private:
278            void create(ClassTreeMaskNode* node);
279
280            std::list<std::pair<const Identifier*, bool> >           subclasses_;       //!< A list of all Identifiers through which objects the iterator should iterate
281            std::list<std::pair<const Identifier*, bool> >::iterator subclassIterator_; //!< The current class of the iterator
282            Iterator<BaseObject>                                     objectIterator_;   //!< The current object of the iterator
283    };
284}
285
286#endif /* _ClassTreeMask_H__ */
Note: See TracBrowser for help on using the repository browser.