1 /** 2 ** Objiter.h - Game objects iterator. 3 ** 4 ** Written: 7/29/2000 - JSF 5 **/ 6 7 /* 8 Copyright (C) 2000 Jeffrey S. Freedman 9 10 This program is free software; you can redistribute it and/or 11 modify it under the terms of the GNU General Public License 12 as published by the Free Software Foundation; either version 2 13 of the License, or (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 */ 24 25 #ifndef INCL_OBJITER 26 #define INCL_OBJITER 1 27 28 #include "objlist.h" 29 30 class Map_chunk; 31 class Game_object; 32 33 /* 34 * Want to make all object iterators modification-safe. For now, just 35 * trying to detect modification during iteration. 36 */ 37 template<class T> 38 class T_Safe_object_iterator { 39 T_Object_list<T> &list; 40 public: T_Safe_object_iterator(T_Object_list<T> & l)41 T_Safe_object_iterator(T_Object_list<T> &l) : list(l) { 42 list.add_iterator(); 43 } ~T_Safe_object_iterator()44 ~T_Safe_object_iterator() { 45 list.remove_iterator(); 46 } 47 }; 48 49 /* 50 * Iterate through list of objects. 51 */ 52 template<class T> 53 class T_Object_iterator : public T_Safe_object_iterator<T> { 54 protected: 55 T *first; 56 T *stop; 57 T *cur; // Next to return. 58 public: reset()59 void reset() { 60 cur = first; 61 stop = nullptr; 62 } T_Object_iterator(T_Object_list<T> & objects)63 T_Object_iterator(T_Object_list<T> &objects) 64 : T_Safe_object_iterator<T>(objects), first(objects.get_first()) { 65 reset(); 66 } get_next()67 T *get_next() { 68 if (cur == stop) 69 return nullptr; 70 T *ret = cur; 71 cur = cur->next.get(); 72 stop = first; 73 return ret; 74 } 75 }; 76 77 using Object_iterator = T_Object_iterator<Game_object>; 78 79 /* 80 * Iterate through a chunk's nonflat objects. 81 */ 82 template<class T, class L> 83 class T_Nonflat_object_iterator : public T_Object_iterator<T> { 84 T *nonflats; 85 public: reset()86 void reset() { 87 this->cur = nonflats; 88 this->stop = nullptr; 89 } T_Nonflat_object_iterator(L chunk)90 T_Nonflat_object_iterator(L chunk) 91 : T_Object_iterator<T>(chunk->get_objects()), nonflats(chunk->get_first_nonflat()) { 92 reset(); 93 } 94 }; 95 96 using Nonflat_object_iterator = T_Nonflat_object_iterator<Game_object, Map_chunk *>; 97 98 /* 99 * Iterate through a chunk's flat objects. 100 */ 101 template<class T, class L> 102 class T_Flat_object_iterator : public T_Safe_object_iterator<T> { 103 T *first; 104 T *stop; 105 T *cur; // Next to return. 106 T *stop_at; 107 public: reset()108 void reset() { 109 cur = first; 110 stop = nullptr; 111 } T_Flat_object_iterator(L chunk)112 T_Flat_object_iterator(L chunk) 113 : T_Safe_object_iterator<T>(chunk->get_objects()) { 114 first = chunk->get_objects().get_first() == chunk->get_first_nonflat() ? nullptr : 115 chunk->get_objects().get_first(); 116 stop_at = chunk->get_first_nonflat() ? chunk->get_first_nonflat() 117 : chunk->get_objects().get_first(); 118 reset(); 119 } get_next()120 T *get_next() { 121 if (cur == stop) 122 return nullptr; 123 T *ret = cur; 124 cur = cur->get_next(); 125 stop = stop_at; 126 return ret; 127 } 128 }; 129 130 using Flat_object_iterator = T_Flat_object_iterator<Game_object, Map_chunk *>; 131 132 /* 133 * Iterate backwards through list of objects. 134 */ 135 template<class T, class L> 136 class T_Object_iterator_backwards : public T_Safe_object_iterator<T> { 137 T *first; 138 T *stop; 139 T *cur; // Return prev. to this. 140 public: reset()141 void reset() { 142 cur = first; 143 stop = nullptr; 144 } T_Object_iterator_backwards(L chunk)145 T_Object_iterator_backwards(L chunk) 146 : T_Safe_object_iterator<T>(chunk->get_objects()), 147 first(chunk->get_objects().get_first()) { 148 reset(); 149 } T_Object_iterator_backwards(T_Object_list<T> & objects)150 T_Object_iterator_backwards(T_Object_list<T> &objects) 151 : T_Safe_object_iterator<T>(objects), 152 first(objects.get_first()) { 153 reset(); 154 } get_next()155 T *get_next() { 156 if (cur == stop) 157 return nullptr; 158 cur = cur->prev; 159 stop = first; 160 return cur; 161 } 162 }; 163 164 using Object_iterator_backwards = T_Object_iterator_backwards<Game_object, Map_chunk *>; 165 166 /* 167 * Iterate through a list of objects (recursively). 168 */ 169 template<class D> class D_Recursive_object_iterator { 170 // Child we're going through, or nullptr. 171 D_Recursive_object_iterator<D> *child; 172 D elems; // Goes through our elements. 173 public: D_Recursive_object_iterator(Object_list & objs)174 D_Recursive_object_iterator(Object_list &objs) 175 : child(nullptr), elems(objs) 176 { } 177 // Start at given object. 178 D_Recursive_object_iterator(Game_object *start); 179 Game_object *get_next(); // Get next, going into containers. 180 }; 181 182 /* 183 * Iterate forwards/backwards through a list of objects (recursively). 184 */ 185 using Recursive_object_iterator_backwards = D_Recursive_object_iterator<Object_iterator_backwards>; 186 using Recursive_object_iterator = D_Recursive_object_iterator<Object_iterator>; 187 188 #endif 189