| 1 | /*
|
|---|
| 2 | Copyright (c) 2003-2006, Troy Aaron Johnson
|
|---|
| 3 | All rights reserved.
|
|---|
| 4 |
|
|---|
| 5 | Redistribution and use in source and binary forms, with or without
|
|---|
| 6 | modification, are permitted provided that the following conditions
|
|---|
| 7 | are met:
|
|---|
| 8 |
|
|---|
| 9 | * Redistributions of source code must retain the above copyright
|
|---|
| 10 | notice, this list of conditions and the following disclaimer.
|
|---|
| 11 | * Redistributions in binary form must reproduce the above copyright
|
|---|
| 12 | notice, this list of conditions and the following disclaimer in the
|
|---|
| 13 | documentation and/or other materials provided with the distribution.
|
|---|
| 14 | * Neither the name of Troy Aaron Johnson nor the names of any
|
|---|
| 15 | contributors may be used to endorse or promote products derived from
|
|---|
| 16 | this software without specific prior written permission.
|
|---|
| 17 |
|
|---|
| 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|---|
| 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|---|
| 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|---|
| 21 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|---|
| 22 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|---|
| 23 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|---|
| 24 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|---|
| 25 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|---|
| 26 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|---|
| 27 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|---|
| 28 | POSSIBILITY OF SUCH DAMAGE.
|
|---|
| 29 | */
|
|---|
| 30 |
|
|---|
| 31 | template<class N>
|
|---|
| 32 | void tree<N>::iterator::clear(void)
|
|---|
| 33 | {
|
|---|
| 34 | /* this line necessary for g++ 3.4 onward */
|
|---|
| 35 | tree_node<N>*& current = this->current;
|
|---|
| 36 |
|
|---|
| 37 | assert(current != NULL);
|
|---|
| 38 |
|
|---|
| 39 | for (sibling_iterator i(beginChildren());
|
|---|
| 40 | i != endChildren(); )
|
|---|
| 41 | {
|
|---|
| 42 | i.clear();
|
|---|
| 43 | ++i;
|
|---|
| 44 | (i - 1).destroy();
|
|---|
| 45 | }
|
|---|
| 46 |
|
|---|
| 47 | current->first_child = NULL;
|
|---|
| 48 | current->last_child = NULL;
|
|---|
| 49 | }
|
|---|
| 50 |
|
|---|
| 51 | template<class N>
|
|---|
| 52 | typename tree<N>::iterator tree<N>::iterator::erase(void)
|
|---|
| 53 | {
|
|---|
| 54 | tree_node<N>*& current = this->current;
|
|---|
| 55 |
|
|---|
| 56 | assert(current != NULL);
|
|---|
| 57 |
|
|---|
| 58 | /* remove all children and grandchildren */
|
|---|
| 59 | clear();
|
|---|
| 60 |
|
|---|
| 61 | /* make copies because there is an ordering
|
|---|
| 62 | problem updating the previous and next links */
|
|---|
| 63 | tree_node<N>* old_prev = current->prev_sibling;
|
|---|
| 64 | tree_node<N>* old_next = current->next_sibling;
|
|---|
| 65 |
|
|---|
| 66 | if (old_prev != NULL)
|
|---|
| 67 | old_prev->next_sibling = old_next;
|
|---|
| 68 |
|
|---|
| 69 | if (old_next != NULL)
|
|---|
| 70 | old_next->prev_sibling = old_prev;
|
|---|
| 71 |
|
|---|
| 72 | if (current->parent->first_child == current)
|
|---|
| 73 | current->parent->first_child = old_next;
|
|---|
| 74 |
|
|---|
| 75 | if (current->parent->last_child == current)
|
|---|
| 76 | current->parent->last_child = old_prev;
|
|---|
| 77 |
|
|---|
| 78 | /* destroy has no parameters, so gcc complains that it
|
|---|
| 79 | can't find the method unless this is made explicit */
|
|---|
| 80 | super::destroy();
|
|---|
| 81 |
|
|---|
| 82 | return iterator(old_next);
|
|---|
| 83 | }
|
|---|
| 84 |
|
|---|
| 85 | template<class N>
|
|---|
| 86 | typename tree<N>::iterator tree<N>::iterator::insert(const N& data)
|
|---|
| 87 | {
|
|---|
| 88 | tree_node<N>*& current = this->current;
|
|---|
| 89 |
|
|---|
| 90 | assert(current != NULL);
|
|---|
| 91 |
|
|---|
| 92 | tree_node<N>* p = new tree_node<N>(data);
|
|---|
| 93 | p->parent = current->parent;
|
|---|
| 94 | p->first_child = p->last_child = NULL;
|
|---|
| 95 |
|
|---|
| 96 | p->prev_sibling = current->prev_sibling;
|
|---|
| 97 | p->next_sibling = current;
|
|---|
| 98 |
|
|---|
| 99 | if (current->prev_sibling != NULL)
|
|---|
| 100 | current->prev_sibling->next_sibling = p;
|
|---|
| 101 | else
|
|---|
| 102 | current->parent->first_child = p;
|
|---|
| 103 |
|
|---|
| 104 | current->prev_sibling = p;
|
|---|
| 105 |
|
|---|
| 106 | return p;
|
|---|
| 107 | }
|
|---|
| 108 |
|
|---|
| 109 | template<class N>
|
|---|
| 110 | typename tree<N>::iterator tree<N>::iterator::insert(const tree<N>& t)
|
|---|
| 111 | {
|
|---|
| 112 | assert(this->current != NULL);
|
|---|
| 113 |
|
|---|
| 114 | return absorb_before(new tree<N>(t));
|
|---|
| 115 | }
|
|---|
| 116 |
|
|---|
| 117 | template<class N>
|
|---|
| 118 | typename tree<N>::iterator tree<N>::iterator::insert_after(const N& data)
|
|---|
| 119 | {
|
|---|
| 120 | /* this line necessary for g++ 3.4 onward */
|
|---|
| 121 | tree_node<N>*& current = this->current;
|
|---|
| 122 |
|
|---|
| 123 | assert(current != NULL);
|
|---|
| 124 |
|
|---|
| 125 | tree_node<N>* p = new tree_node<N>(data);
|
|---|
| 126 | p->parent = current->parent;
|
|---|
| 127 | p->first_child = p->last_child = NULL;
|
|---|
| 128 |
|
|---|
| 129 | p->prev_sibling = current;
|
|---|
| 130 | p->next_sibling = current->next_sibling;
|
|---|
| 131 |
|
|---|
| 132 | if (current->next_sibling != NULL)
|
|---|
| 133 | current->next_sibling->prev_sibling = p;
|
|---|
| 134 | else
|
|---|
| 135 | current->parent->last_child = p;
|
|---|
| 136 |
|
|---|
| 137 | current->next_sibling = p;
|
|---|
| 138 |
|
|---|
| 139 | return p;
|
|---|
| 140 | }
|
|---|
| 141 |
|
|---|
| 142 | template<class N>
|
|---|
| 143 | typename tree<N>::iterator tree<N>::iterator::insert_after(const tree<N>& t)
|
|---|
| 144 | {
|
|---|
| 145 | assert(this->current != NULL);
|
|---|
| 146 |
|
|---|
| 147 | return absorb_after(new tree<N>(t));
|
|---|
| 148 | }
|
|---|
| 149 |
|
|---|
| 150 | template<class N>
|
|---|
| 151 | void tree<N>::iterator::pop_back(void)
|
|---|
| 152 | {
|
|---|
| 153 | /* this line necessary for g++ 3.4 onward */
|
|---|
| 154 | tree_node<N>*& current = this->current;
|
|---|
| 155 |
|
|---|
| 156 | assert(current != NULL);
|
|---|
| 157 | assert(current->last_child != NULL);
|
|---|
| 158 | assert(current->last_child->next_sibling == NULL);
|
|---|
| 159 |
|
|---|
| 160 | tree_node<N>* p = current->last_child;
|
|---|
| 161 | current->last_child = p->prev_sibling;
|
|---|
| 162 |
|
|---|
| 163 | if (p->prev_sibling != NULL)
|
|---|
| 164 | p->prev_sibling->next_sibling = NULL;
|
|---|
| 165 | else
|
|---|
| 166 | current->first_child = NULL;
|
|---|
| 167 |
|
|---|
| 168 | delete p;
|
|---|
| 169 | }
|
|---|
| 170 |
|
|---|
| 171 | template<class N>
|
|---|
| 172 | void tree<N>::iterator::pop_front(void)
|
|---|
| 173 | {
|
|---|
| 174 | /* this line necessary for g++ 3.4 onward */
|
|---|
| 175 | tree_node<N>*& current = this->current;
|
|---|
| 176 |
|
|---|
| 177 | assert(current != NULL);
|
|---|
| 178 | assert(current->first_child != NULL);
|
|---|
| 179 | assert(current->first_child->prev_sibling == NULL);
|
|---|
| 180 |
|
|---|
| 181 | tree_node<N>* p = current->first_child;
|
|---|
| 182 | current->first_child = p->next_sibling;
|
|---|
| 183 |
|
|---|
| 184 | if (p->next_sibling != NULL)
|
|---|
| 185 | p->next_sibling->prev_sibling = NULL;
|
|---|
| 186 | else
|
|---|
| 187 | current->last_child = NULL;
|
|---|
| 188 |
|
|---|
| 189 | delete p;
|
|---|
| 190 | }
|
|---|
| 191 |
|
|---|
| 192 | template<class N>
|
|---|
| 193 | typename tree<N>::iterator tree<N>::iterator::push_back(const N& data)
|
|---|
| 194 | {
|
|---|
| 195 | /* this line necessary for g++ 3.4 onward */
|
|---|
| 196 | tree_node<N>*& current = this->current;
|
|---|
| 197 |
|
|---|
| 198 | assert(current != NULL);
|
|---|
| 199 |
|
|---|
| 200 | tree_node<N>* p = new tree_node<N>(data);
|
|---|
| 201 | p->parent = current;
|
|---|
| 202 | p->first_child = p->last_child = NULL;
|
|---|
| 203 |
|
|---|
| 204 | if (current->last_child == NULL)
|
|---|
| 205 | {
|
|---|
| 206 | current->first_child = current->last_child = p;
|
|---|
| 207 | p->prev_sibling = p->next_sibling = NULL;
|
|---|
| 208 | }
|
|---|
| 209 | else
|
|---|
| 210 | {
|
|---|
| 211 | p->prev_sibling = current->last_child;
|
|---|
| 212 | p->next_sibling = NULL;
|
|---|
| 213 | current->last_child->next_sibling = p;
|
|---|
| 214 | current->last_child = p;
|
|---|
| 215 | }
|
|---|
| 216 |
|
|---|
| 217 | return iterator(p);
|
|---|
| 218 | }
|
|---|
| 219 |
|
|---|
| 220 | template<class N>
|
|---|
| 221 | typename tree<N>::iterator tree<N>::iterator::push_back(const tree<N>& t)
|
|---|
| 222 | {
|
|---|
| 223 | assert(this->current != NULL);
|
|---|
| 224 |
|
|---|
| 225 | return absorb_back(new tree<N>(t));
|
|---|
| 226 | }
|
|---|
| 227 |
|
|---|
| 228 | template<class N>
|
|---|
| 229 | typename tree<N>::iterator tree<N>::iterator::push_front(const N& data)
|
|---|
| 230 | {
|
|---|
| 231 | /* this line necessary for g++ 3.4 onward */
|
|---|
| 232 | tree_node<N>*& current = this->current;
|
|---|
| 233 |
|
|---|
| 234 | assert(current != NULL);
|
|---|
| 235 |
|
|---|
| 236 | tree_node<N>* p = new tree_node<N>(data);
|
|---|
| 237 | p->parent = current;
|
|---|
| 238 | p->first_child = p->last_child = NULL;
|
|---|
| 239 |
|
|---|
| 240 | if (current->first_child == NULL)
|
|---|
| 241 | {
|
|---|
| 242 | current->first_child = current->last_child = p;
|
|---|
| 243 | p->prev_sibling = p->next_sibling = NULL;
|
|---|
| 244 | }
|
|---|
| 245 | else
|
|---|
| 246 | {
|
|---|
| 247 | p->prev_sibling = NULL;
|
|---|
| 248 | p->next_sibling = current->first_child;
|
|---|
| 249 | current->first_child->prev_sibling = p;
|
|---|
| 250 | current->first_child = p;
|
|---|
| 251 | }
|
|---|
| 252 |
|
|---|
| 253 | return iterator(p);
|
|---|
| 254 | }
|
|---|
| 255 |
|
|---|
| 256 | template<class N>
|
|---|
| 257 | typename tree<N>::iterator tree<N>::iterator::push_front(const tree<N>& t)
|
|---|
| 258 | {
|
|---|
| 259 | assert(this->current != NULL);
|
|---|
| 260 |
|
|---|
| 261 | return absorb_front(new tree<N>(t));
|
|---|
| 262 | }
|
|---|
| 263 |
|
|---|
| 264 | template<class N>
|
|---|
| 265 | N tree<N>::iterator::replace(const N& data)
|
|---|
| 266 | {
|
|---|
| 267 | N ret(this->current->data);
|
|---|
| 268 | this->current->data = data;
|
|---|
| 269 | return ret;
|
|---|
| 270 | }
|
|---|
| 271 |
|
|---|
| 272 | template<class N>
|
|---|
| 273 | size_t tree<N>::iterator::size(void) const
|
|---|
| 274 | {
|
|---|
| 275 | assert(this->current != NULL);
|
|---|
| 276 |
|
|---|
| 277 | size_t s = 1;
|
|---|
| 278 |
|
|---|
| 279 | for (typename tree<N>::sibling_iterator i(beginChildren());
|
|---|
| 280 | i != endChildren(); ++i)
|
|---|
| 281 | {
|
|---|
| 282 | s += i.size();
|
|---|
| 283 | }
|
|---|
| 284 |
|
|---|
| 285 | return s;
|
|---|
| 286 | }
|
|---|
| 287 |
|
|---|
| 288 | template<class N>
|
|---|
| 289 | typename tree<N>::iterator tree<N>::iterator::splice_after(tree<N>& t)
|
|---|
| 290 | {
|
|---|
| 291 | /* this line necessary for g++ 3.4 onward */
|
|---|
| 292 | tree_node<N>*& current = this->current;
|
|---|
| 293 |
|
|---|
| 294 | assert(current != NULL);
|
|---|
| 295 |
|
|---|
| 296 | tree_node<N>* p = t.master->next_sibling;
|
|---|
| 297 | t.master->next_sibling = t.master;
|
|---|
| 298 | t.master->prev_sibling = t.master;
|
|---|
| 299 |
|
|---|
| 300 | p->parent = current->parent;
|
|---|
| 301 |
|
|---|
| 302 | p->prev_sibling = current;
|
|---|
| 303 | p->next_sibling = current->next_sibling;
|
|---|
| 304 |
|
|---|
| 305 | if (current->next_sibling != NULL)
|
|---|
| 306 | current->next_sibling->prev_sibling = p;
|
|---|
| 307 | else
|
|---|
| 308 | current->parent->last_child = p;
|
|---|
| 309 |
|
|---|
| 310 | current->next_sibling = p;
|
|---|
| 311 |
|
|---|
| 312 | return p;
|
|---|
| 313 | }
|
|---|
| 314 |
|
|---|
| 315 | template<class N>
|
|---|
| 316 | typename tree<N>::iterator tree<N>::iterator::splice_back(tree<N>& t)
|
|---|
| 317 | {
|
|---|
| 318 | /* this line necessary for g++ 3.4 onward */
|
|---|
| 319 | tree_node<N>*& current = this->current;
|
|---|
| 320 |
|
|---|
| 321 | assert(current != NULL);
|
|---|
| 322 | assert(!t.empty());
|
|---|
| 323 |
|
|---|
| 324 | tree_node<N>* p = t.master->next_sibling;
|
|---|
| 325 | t.master->next_sibling = t.master;
|
|---|
| 326 | t.master->prev_sibling = t.master;
|
|---|
| 327 |
|
|---|
| 328 | p->parent = current;
|
|---|
| 329 |
|
|---|
| 330 | if (current->last_child == NULL)
|
|---|
| 331 | {
|
|---|
| 332 | current->first_child = current->last_child = p;
|
|---|
| 333 | p->prev_sibling = p->next_sibling = NULL;
|
|---|
| 334 | }
|
|---|
| 335 | else
|
|---|
| 336 | {
|
|---|
| 337 | p->prev_sibling = current->last_child;
|
|---|
| 338 | p->next_sibling = NULL;
|
|---|
| 339 | current->last_child->next_sibling = p;
|
|---|
| 340 | current->last_child = p;
|
|---|
| 341 | }
|
|---|
| 342 |
|
|---|
| 343 | return p;
|
|---|
| 344 | }
|
|---|
| 345 |
|
|---|
| 346 | template<class N>
|
|---|
| 347 | typename tree<N>::iterator tree<N>::iterator::splice_before(tree<N>& t)
|
|---|
| 348 | {
|
|---|
| 349 | /* TODO */
|
|---|
| 350 | assert(false);
|
|---|
| 351 | return NULL;
|
|---|
| 352 | }
|
|---|
| 353 |
|
|---|
| 354 | template<class N>
|
|---|
| 355 | typename tree<N>::iterator tree<N>::iterator::splice_front(tree<N>& t)
|
|---|
| 356 | {
|
|---|
| 357 | /* TODO */
|
|---|
| 358 | assert(false);
|
|---|
| 359 | return NULL;
|
|---|
| 360 | }
|
|---|
| 361 |
|
|---|