Adobe Source Libraries 1.49.0
A collection of C++ libraries.
Loading...
Searching...
No Matches
forest.hpp
Go to the documentation of this file.
1/*
2 Copyright 2013 Adobe
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5*/
6/**************************************************************************************************/
7
8#ifndef ADOBE_FOREST_HPP
9#define ADOBE_FOREST_HPP
10
11/**************************************************************************************************/
12
13#include <adobe/config.hpp>
14
17
18#include <boost/iterator/iterator_facade.hpp>
19#include <boost/range.hpp>
20
21#include <cassert>
22#include <cstddef>
23#include <functional>
24#include <iterator>
25#include <stack>
26
27/**************************************************************************************************/
28
29namespace adobe {
30
31/**************************************************************************************************/
32
33/*
34 NOTE (sparent) : These are the edge index value - trailing as 0 and leading as 1 is done to
35 reflect that it used to be a leading bool value. Changing the order of this enum requires
36 code review as some code relies on the test for leading.
37*/
38
40
41/**************************************************************************************************/
42
43template <typename I> // I models FullorderIterator
44inline void pivot(I& i) {
45 i.edge() ^= 1;
46}
47
48template <typename I> // I models FullorderIterator
49inline I pivot_of(I i) {
50 pivot(i);
51 return i;
52}
53
54/**************************************************************************************************/
55
56template <typename I> // I models a FullorderIterator
57inline I leading_of(I i) {
58 i.edge() = forest_leading_edge;
59 return i;
60}
61
62template <typename I> // I models a FullorderIterator
63inline I trailing_of(I i) {
64 i.edge() = forest_trailing_edge;
65 return i;
66}
67
68/**************************************************************************************************/
69
70template <typename I> // I models FullorderIterator
72 do {
73 i = trailing_of(i);
74 ++i;
75 } while (i.edge() != forest_trailing_edge);
76 return i;
77}
78
79/**************************************************************************************************/
80
81template <typename I> // I models FullorderIterator
82bool has_children(const I& i) {
83 return !i.equal_node(std::next(leading_of(i)));
84}
85
86/**************************************************************************************************/
87
88template <typename I> // I models FullorderIterator
89class child_iterator : public boost::iterator_adaptor<child_iterator<I>, I> {
90public:
92 explicit child_iterator(I x) : child_iterator::iterator_adaptor_(x) {}
93 template <typename U>
94 child_iterator(const child_iterator<U>& u) : child_iterator::iterator_adaptor_(u.base()) {}
95
96private:
97 friend class boost::iterator_core_access;
98
99 void increment() {
100 pivot(this->base_reference());
101 ++this->base_reference();
102 }
103 void decrement() {
104 --this->base_reference();
105 pivot(this->base_reference());
106 }
107};
108
109/**************************************************************************************************/
110
111template <typename I> // I models FullorderIterator
112I find_edge(I x, std::size_t edge) {
113 while (x.edge() != edge)
114 ++x;
115 return x;
116}
117
118template <typename I> // I models FullorderIterator
119I find_edge_reverse(I x, std::size_t edge) {
120 while (x.edge() != edge)
121 --x;
122 return x;
123}
124
125/**************************************************************************************************/
126
127template <typename I, std::size_t Edge> // I models FullorderIterator
128class edge_iterator : public boost::iterator_adaptor<edge_iterator<I, Edge>, I> {
129public:
131 explicit edge_iterator(I x) : edge_iterator::iterator_adaptor_(find_edge(x, Edge)) {}
132 template <typename U>
133 edge_iterator(const edge_iterator<U, Edge>& u) : edge_iterator::iterator_adaptor_(u.base()) {}
134
135private:
136 friend class boost::iterator_core_access;
137
138 void increment() { this->base_reference() = find_edge(std::next(this->base()), Edge); }
139
140 void decrement() { this->base_reference() = find_edge_reverse(std::prev(this->base()), Edge); }
141};
142
143/**************************************************************************************************/
144
145/*
146 I need to establish dereferencable range vs. traversable range.
147
148 Here [f, l) must be a dereferencable range and p() will not be applied outside that range
149 although the iterators may travel beyond that range.
150*/
151
152template <typename I, // I models a Forest
153 typename P> // P models UnaryPredicate of value_type(I)
155 : public boost::iterator_adaptor<filter_fullorder_iterator<I, P>, I> {
156public:
158
160 : filter_fullorder_iterator::iterator_adaptor_(skip_forward(f, l, p)), inside_m(true),
161 first_m(f), last_m(l), predicate_m(p) {}
162
164 : filter_fullorder_iterator::iterator_adaptor_(skip_forward(f, l, P())), inside_m(true),
165 first_m(f), last_m(l) {}
166
167 template <typename U>
169 : filter_fullorder_iterator::iterator_adaptor_(x.base()), inside_m(x.inside_m),
170 first_m(x.first_m), last_m(x.last_m), predicate_m(x.predicate_m) {}
171
172 P predicate() const { return predicate_m; }
173
174 std::size_t edge() const { return this->base().edge(); }
175 std::size_t& edge() { return this->base_reference().edge(); }
176
178 return this->base().equal_node(y.base());
179 }
180
181private:
183
184 void increment() {
185 I i = this->base();
186
187 if (i == last_m)
188 inside_m = false;
189 ++i;
190 if (i == first_m)
191 inside_m = true;
192 if (inside_m)
193 i = skip_forward(i, last_m, predicate_m);
194 this->base_reference() = i;
195 }
196
197 static I skip_forward(I f, I l, P p)
198 // Precondition: l is on a leading edge
199 {
200 while ((f.edge() == forest_leading_edge) && (f != l) && !p(*f)) {
201 f.edge() = forest_trailing_edge;
202 ++f;
203 }
204 return f;
205 }
206
207 static I skip_backward(I f, I l, P p)
208 // Precondition: f is on a trailing edge
209 {
210 while ((l.edge() == forest_trailing_edge) && (f != l) && !p(*l)) {
211 l.edge() = forest_leading_edge;
212 --l;
213 }
214 return l;
215 }
216
217 void decrement() {
218 I i = this->base();
219
220 if (i == first_m)
221 inside_m = false;
222 --i;
223 if (i == last_m)
224 inside_m = true;
225 if (inside_m)
226 i = skip_backward(first_m, i, predicate_m);
227 this->base_reference() = i;
228 }
229
230 bool inside_m;
231 I first_m;
232 I last_m;
233 P predicate_m;
234};
235
236/**************************************************************************************************/
237
238/*
239 REVISIT (sparent) : This is an interesting case - an edge is a property of an iterator but it
240 is determined by examining a vertex in the graph. Here we need to examine the prior vertex
241 to determine the edge. If the range is empty (or we are at the "end" of the range) then this
242 examination is questionable.
243
244 We let it go, because we know the forest structure is an infinite loop through the root. One
245 answer to this would be to construct a reverse iterator which was not "off by one" for forest -
246 but that might break people who assume base() is off by one for a reverse iterator, and it still
247 assumes a root().
248*/
249
250template <typename I> // I models a FullorderIterator
252 : public boost::iterator_facade<
253 reverse_fullorder_iterator<I>, typename boost::iterator_value<I>::type,
254 std::bidirectional_iterator_tag, typename boost::iterator_reference<I>::type> {
255 typedef typename boost::iterator_facade<
256 reverse_fullorder_iterator<I>, typename boost::iterator_value<I>::type,
257 std::bidirectional_iterator_tag, typename boost::iterator_reference<I>::type>
258 inherited_t;
259
260public:
261 typedef I iterator_type;
262 typedef typename inherited_t::reference reference;
263
266 : base_m(--x), edge_m(forest_leading_edge - base_m.edge()) {}
267 template <typename U>
269 : base_m(x.base()), edge_m(x.edge()) {}
270
271 iterator_type base() const { return std::next(base_m); }
272
273 std::size_t edge() const { return edge_m; }
274 std::size_t& edge() { return edge_m; }
275
277 return base_m.equal_node(y.base_m);
278 }
279
280private:
281 friend class boost::iterator_core_access;
282
283 void increment() {
284 base_m.edge() = forest_leading_edge - edge_m;
285 --base_m;
286 edge_m = forest_leading_edge - base_m.edge();
287 }
288 void decrement() {
289 base_m.edge() = forest_leading_edge - edge_m;
290 ++base_m;
291 edge_m = forest_leading_edge - base_m.edge();
292 }
293 reference dereference() const { return *base_m; }
294
295 bool equal(const reverse_fullorder_iterator& y) const {
296 return (base_m == y.base_m) && (edge_m == y.edge_m);
297 }
298
299 I base_m;
300 std::size_t edge_m;
301};
302
303/**************************************************************************************************/
304
305template <typename I> // I models FullorderIterator
306class depth_fullorder_iterator : public boost::iterator_adaptor<depth_fullorder_iterator<I>, I> {
307public:
308 typedef typename boost::iterator_adaptor<depth_fullorder_iterator<I>, I>::difference_type
310
313 : depth_fullorder_iterator::iterator_adaptor_(x), depth_m(d) {}
314 template <typename U>
316 : depth_fullorder_iterator::iterator_adaptor_(x.base()), depth_m(x.depth_m) {}
317
318 difference_type depth() const { return depth_m; }
319 std::size_t edge() const { return this->base().edge(); }
320 std::size_t& edge() { return this->base_reference().edge(); }
322 return this->base().equal_node(y.base());
323 }
324
325private:
327
328 void increment() {
329 std::size_t old_edge(edge());
330 ++this->base_reference();
331 if (old_edge == edge())
332 depth_m += difference_type(old_edge << 1) - 1;
333 }
334 void decrement() {
335 std::size_t old_edge(edge());
336 --this->base_reference();
337 if (old_edge == edge())
338 depth_m -= difference_type(old_edge << 1) - 1;
339 }
340
341 difference_type depth_m;
342};
343
344/**************************************************************************************************/
345
346template <typename Forest>
347class child_adaptor;
348template <typename T>
349class forest;
350
351/**************************************************************************************************/
352
353#if !defined(ADOBE_NO_DOCUMENTATION)
354namespace implementation {
355
356template <typename D> // derived class
357struct node_base {
358 enum next_prior_t { prior_s, next_s };
359
360 typedef D* node_ptr;
361 typedef node_ptr& reference;
362
363 node_ptr& link(std::size_t edge, next_prior_t link) { return nodes_m[edge][std::size_t(link)]; }
364
365 node_ptr link(std::size_t edge, next_prior_t link) const {
366 return nodes_m[edge][std::size_t(link)];
367 }
368
369#if 0
370 node_ptr nodes_m[2][2] = {
371 { static_cast<node_ptr>(this), static_cast<node_ptr>(this) },
372 { static_cast<node_ptr>(this), static_cast<node_ptr>(this) }
373 };
374#else
375 node_ptr nodes_m[2][2];
376
377 node_base()
378 : nodes_m{{static_cast<node_ptr>(this), static_cast<node_ptr>(this)},
379 {static_cast<node_ptr>(this), static_cast<node_ptr>(this)}} {}
380#endif
381};
382
383template <typename T> // T models Regular
384struct node : public node_base<node<T>> {
385 typedef T value_type;
386
387 explicit node(const value_type& data) : data_m(data) {}
388
389 value_type data_m;
390};
391
392/**************************************************************************************************/
393
394template <typename T>
395class forest_const_iterator;
396
397template <typename T> // T is value_type
398class forest_iterator
399 : public boost::iterator_facade<forest_iterator<T>, T, std::bidirectional_iterator_tag> {
400 typedef boost::iterator_facade<forest_iterator<T>, T, std::bidirectional_iterator_tag>
401 inherited_t;
402
403public:
404 typedef typename inherited_t::reference reference;
405 typedef typename inherited_t::difference_type difference_type;
406 typedef typename inherited_t::value_type value_type;
407
408 forest_iterator() : node_m(0), edge_m(forest_leading_edge) {}
409
410 forest_iterator(const forest_iterator& x) : node_m(x.node_m), edge_m(x.edge_m) {}
411
412 std::size_t edge() const { return edge_m; }
413 std::size_t& edge() { return edge_m; }
414 bool equal_node(forest_iterator const& y) const { return node_m == y.node_m; }
415
416private:
417 friend class adobe::forest<value_type>;
418 friend class boost::iterator_core_access;
419 template <typename>
420 friend class forest_iterator;
421 template <typename>
422 friend class forest_const_iterator;
423 friend struct unsafe::set_next_fn<forest_iterator>;
424
425 typedef node<T> node_t;
426
427 reference dereference() const { return node_m->data_m; }
428
429 void increment() {
430 node_t* next(node_m->link(edge_m, node_t::next_s));
431
432 if (edge_m)
433 edge_m = std::size_t(next != node_m);
434 else
435 edge_m = std::size_t(next->link(forest_leading_edge, node_t::prior_s) == node_m);
436
437 node_m = next;
438 }
439
440 void decrement() {
441 node_t* next(node_m->link(edge_m, node_t::prior_s));
442
443 if (edge_m)
444 edge_m = std::size_t(next->link(forest_trailing_edge, node_t::next_s) != node_m);
445 else
446 edge_m = std::size_t(next == node_m);
447
448 node_m = next;
449 }
450
451 bool equal(const forest_iterator& y) const {
452 return (node_m == y.node_m) && (edge_m == y.edge_m);
453 }
454
455 node_t* node_m;
456 std::size_t edge_m;
457
458 forest_iterator(node_t* node, std::size_t edge) : node_m(node), edge_m(edge) {}
459};
460
461
462/**************************************************************************************************/
463
464template <typename T> // T is value_type
465class forest_const_iterator : public boost::iterator_facade<forest_const_iterator<T>, const T,
466 std::bidirectional_iterator_tag> {
467 typedef boost::iterator_facade<forest_const_iterator<T>, const T,
468 std::bidirectional_iterator_tag>
469 inherited_t;
470
471public:
472 typedef typename inherited_t::reference reference;
473 typedef typename inherited_t::difference_type difference_type;
474 typedef typename inherited_t::value_type value_type;
475
476 forest_const_iterator() : node_m(0), edge_m(forest_leading_edge) {}
477
478 forest_const_iterator(const forest_const_iterator& x) : node_m(x.node_m), edge_m(x.edge_m) {}
479
480 forest_const_iterator(const forest_iterator<T>& x) : node_m(x.node_m), edge_m(x.edge_m) {}
481
482 std::size_t edge() const { return edge_m; }
483 std::size_t& edge() { return edge_m; }
484 bool equal_node(forest_const_iterator const& y) const { return node_m == y.node_m; }
485
486private:
487 friend class adobe::forest<value_type>;
488 friend class boost::iterator_core_access;
489 template <typename>
490 friend class forest_const_iterator;
491 friend struct unsafe::set_next_fn<forest_const_iterator>;
492
493 typedef const node<T> node_t;
494
495 reference dereference() const { return node_m->data_m; }
496
497 void increment() {
498 node_t* next(node_m->link(edge_m, node_t::next_s));
499
500 if (edge_m)
501 edge_m = std::size_t(next != node_m);
502 else
503 edge_m = std::size_t(next->link(forest_leading_edge, node_t::prior_s) == node_m);
504
505 node_m = next;
506 }
507
508 void decrement() {
509 node_t* next(node_m->link(edge_m, node_t::prior_s));
510
511 if (edge_m)
512 edge_m = std::size_t(next->link(forest_trailing_edge, node_t::next_s) != node_m);
513 else
514 edge_m = std::size_t(next == node_m);
515
516 node_m = next;
517 }
518
519 bool equal(const forest_const_iterator& y) const {
520 return (node_m == y.node_m) && (edge_m == y.edge_m);
521 }
522
523 node_t* node_m;
524 std::size_t edge_m;
525
526 forest_const_iterator(node_t* node, std::size_t edge) : node_m(node), edge_m(edge) {}
527};
528
529
530/**************************************************************************************************/
531
532} // namespace implementation
533#endif
534
535/**************************************************************************************************/
536
537namespace unsafe {
538
539template <typename T> // T is node<T>
540struct set_next_fn<implementation::forest_iterator<T>> {
541 void operator()(implementation::forest_iterator<T> x,
542 implementation::forest_iterator<T> y) const {
543 typedef typename implementation::node<T> node_t;
544
545 x.node_m->link(x.edge(), node_t::next_s) = y.node_m;
546 y.node_m->link(y.edge(), node_t::prior_s) = x.node_m;
547 }
548};
549
550} // namespace unsafe
551
552/**************************************************************************************************/
553
554template <typename T>
555class forest {
556private:
557 typedef implementation::node<T> node_t;
558 friend class child_adaptor<forest<T>>;
559
560public:
561 // types
562 typedef T& reference;
563 typedef const T& const_reference;
564 typedef implementation::forest_iterator<T> iterator;
565 typedef implementation::forest_const_iterator<T> const_iterator;
566 typedef std::size_t size_type;
567 typedef std::ptrdiff_t difference_type;
568 typedef T value_type;
569 typedef T* pointer;
570 typedef const T* const_pointer;
573
575 /* qualification needed since: A name N used in a class S shall refer to the same declaration
576 in its context and when re-evaluated in the completed scope of
577 S. */
578
580 typedef std::reverse_iterator<child_iterator> reverse_child_iterator;
581
586
587#if !defined(ADOBE_NO_DOCUMENTATION)
588 forest() = default;
589 ~forest() { clear(); }
590
591 forest(const forest&);
592 forest(forest&&) noexcept;
593 forest& operator=(const forest& x) {
594 auto tmp = x;
595 *this = std::move(tmp);
596 return *this;
597 }
598 forest& operator=(forest&& x) noexcept {
599 clear();
600 splice(end(), x);
601 return *this;
602 }
603
604 void swap(forest&);
605#endif
606
607 size_type size() const;
608 size_type max_size() const { return size_type(-1); }
609 bool size_valid() const { return size_m != 0 || empty(); }
610 bool empty() const { return begin() == end(); } // Don't test size which may be expensive
611
612 // iterators
615
616 iterator begin() { return ++root(); }
618 const_iterator begin() const { return ++root(); }
620
625
627 assert(!empty());
628 return *begin();
629 }
631 assert(!empty());
632 return *begin();
633 }
635 assert(!empty());
636 return *(--end());
637 }
639 assert(!empty());
640 return *(--end());
641 }
642
643 // modifiers
644 void clear() {
645 erase(begin(), end());
646 assert(empty()); // Make sure our erase is correct
647 }
648
649 iterator erase(const iterator& position);
650 iterator erase(const iterator& first, const iterator& last);
651
652 iterator insert(const iterator& position, T x) {
653 iterator result(new node_t(std::move(x)), true);
654
655 if (size_valid())
656 ++size_m;
657
658 unsafe::set_next(std::prev(position), result);
659 unsafe::set_next(std::next(result), position);
660
661 return result;
662 }
663
664 void push_front(const T& x) { insert(begin(), x); }
665 void push_back(const T& x) { insert(end(), x); }
666 void pop_front() {
667 assert(!empty());
668 erase(begin());
669 }
670 void pop_back() {
671 assert(!empty());
672 erase(--end());
673 }
674
675 iterator insert(iterator position, const_child_iterator first, const_child_iterator last);
676
677 iterator splice(iterator position, forest<T>& x);
678 iterator splice(iterator position, forest<T>& x, iterator i);
679 iterator splice(iterator position, forest<T>& x, child_iterator first, child_iterator last);
680 iterator splice(iterator position, forest<T>& x, child_iterator first, child_iterator last,
681 size_type count);
682
683 iterator insert_parent(child_iterator front, child_iterator back, const T& x);
685
686private:
687#if !defined(ADOBE_NO_DOCUMENTATION)
688
689 friend class implementation::forest_iterator<value_type>;
690 friend class implementation::forest_const_iterator<value_type>;
691 friend struct unsafe::set_next_fn<iterator>;
692
693 mutable size_type size_m = 0;
694 implementation::node_base<node_t> tail_m;
695
696 node_t* tail() { return static_cast<node_t*>(&tail_m); }
697 const node_t* tail() const { return static_cast<const node_t*>(&tail_m); }
698#endif
699};
700
701/**************************************************************************************************/
702
703template <typename T>
704bool operator==(const forest<T>& x, const forest<T>& y) {
705 if (x.size() != y.size())
706 return false;
707
708 for (typename forest<T>::const_iterator first(x.begin()), last(x.end()), pos(y.begin());
709 first != last; ++first, ++pos) {
710 if (first.edge() != pos.edge())
711 return false;
712 if (first.edge() && (*first != *pos))
713 return false;
714 }
715
716 return true;
717}
718
719/**************************************************************************************************/
720
721template <typename T>
722bool operator!=(const forest<T>& x, const forest<T>& y) {
723 return !(x == y);
724}
725
726/**************************************************************************************************/
727
728namespace unsafe {
729
730template <typename I> // I models a FullorderIterator
733 unsafe::set_next(pivot_of(x.base()), y.base());
734 }
735};
736
737} // namespace unsafe
738
739/**************************************************************************************************/
740
741#if !defined(ADOBE_NO_DOCUMENTATION)
742
743/**************************************************************************************************/
744
745template <typename T>
749
750/**************************************************************************************************/
751
752template <typename T>
753forest<T>::forest(forest&& x) noexcept : forest() {
754 splice(end(), x);
755}
756
757/**************************************************************************************************/
758
759template <typename T>
761 std::swap(*this, x);
762}
763
764#endif
765
766/**************************************************************************************************/
767
768template <typename T>
770 if (!size_valid()) {
773
774 size_m = size_type(std::distance(first, last));
775 }
776
777 return size_m;
778}
779
780/**************************************************************************************************/
781
782template <typename T>
783typename forest<T>::iterator forest<T>::erase(const iterator& first, const iterator& last) {
784 difference_type stack_depth(0);
785 iterator position(first);
786
787 while (position != last) {
788 if (position.edge() == forest_leading_edge) {
789 ++stack_depth;
790 ++position;
791 } else {
792 if (stack_depth > 0)
793 position = erase(position);
794 else
795 ++position;
796 stack_depth = std::max<difference_type>(0, stack_depth - 1);
797 }
798 }
799 return last;
800}
801
802/**************************************************************************************************/
803
804template <typename T>
806 /*
807 NOTE (sparent) : After the first call to set_next() the invariants of the forest are
808 violated and we can't determing leading/trailing if we navigate from the effected node.
809 So we gather all the iterators up front then do the set_next calls.
810 */
811
812 if (size_valid())
813 --size_m;
814
815 iterator leading_prior(std::prev(leading_of(position)));
816 iterator leading_next(std::next(leading_of(position)));
817 iterator trailing_prior(std::prev(trailing_of(position)));
818 iterator trailing_next(std::next(trailing_of(position)));
819
820 if (has_children(position)) {
821 unsafe::set_next(leading_prior, leading_next);
822 unsafe::set_next(trailing_prior, trailing_next);
823 } else {
824 unsafe::set_next(leading_prior, trailing_next);
825 }
826
827 delete position.node_m;
828
829 return position.edge() ? std::next(leading_prior) : trailing_next;
830}
831
832/**************************************************************************************************/
833
834template <typename T>
836 return splice(position, x, child_iterator(x.begin()), child_iterator(x.end()),
837 x.size_valid() ? x.size() : 0);
838}
839
840/**************************************************************************************************/
841
842template <typename T>
844 i.edge() = forest_leading_edge;
845 return splice(position, x, child_iterator(i), ++child_iterator(i), has_children(i) ? 0 : 1);
846}
847
848/**************************************************************************************************/
849
850template <typename T>
853 for (const_iterator first(f.base()), last(l.base()); first != last; ++first, ++pos) {
854 if (first.edge())
855 pos = insert(pos, *first);
856 }
857
858 return pos;
859}
860
861/**************************************************************************************************/
862
863template <typename T>
866 if (first == last || first.base() == pos)
867 return pos;
868
869 if (&x != this) {
870 if (count) {
871 if (size_valid())
872 size_m += count;
873 if (x.size_valid())
874 x.size_m -= count;
875 } else {
876 size_m = 0;
877 x.size_m = 0;
878 }
879 }
880
881 iterator back(std::prev(last.base()));
882
883 unsafe::set_next(std::prev(first), last);
884
885 unsafe::set_next(std::prev(pos), first.base());
887
888 return first.base();
889}
890
891/**************************************************************************************************/
892
893template <typename T>
895 child_iterator first, child_iterator last) {
896 return splice(pos, x, first, last, 0);
897}
898
899/**************************************************************************************************/
900
901template <typename T>
903 const T& x) {
904 iterator result(insert(last.base(), x));
905 if (first == last)
906 return result;
907 splice(trailing_of(result), *this, first, child_iterator(result));
908 return result;
909}
910
911/**************************************************************************************************/
912
913template <typename T>
915 iterator prior(first.base());
916 --prior;
917 first = unsafe::reverse_nodes(first, last);
918 unsafe::set_next(prior, first.base());
919}
920
921/**************************************************************************************************/
922
923template <typename I> // I models FullorderIterator
925 return child_iterator<I>(std::next(leading_of(x)));
926}
927
928/**************************************************************************************************/
929
930template <typename I> // I models FullorderIterator
933}
934
935/**************************************************************************************************/
936
937template <typename Forest>
939public:
940 typedef Forest forest_type;
941 typedef typename Forest::value_type value_type;
942 typedef typename Forest::iterator iterator_type;
943 typedef typename Forest::reference reference;
944 typedef typename Forest::const_reference const_reference;
945 typedef typename Forest::difference_type difference_type;
946 typedef typename Forest::child_iterator iterator;
947
948 child_adaptor(forest_type& f, iterator_type& i) : forest_m(f), iterator_m(i) {}
949
950 value_type& back() { return *(--child_end(iterator_m)); }
951 value_type& front() { return *(child_begin(iterator_m)); }
952
953 void push_back(const value_type& x) { forest_m.insert(child_end(iterator_m).base(), x); }
954 void push_front(const value_type& x) { forest_m.insert(child_begin(iterator_m).base(), x); }
955
956 void pop_back() { forest_m.erase(--child_end(iterator_m).base()); }
957 void pop_front() { forest_m.erase(child_begin(iterator_m).base()); }
958
959private:
960 child_adaptor(); // not defined
961
962 forest_type& forest_m;
963 iterator_type& iterator_m;
964};
965
966/**************************************************************************************************/
967
968template <typename I> // I models FullorderIterator
969auto child_range(const I& x) -> boost::iterator_range<child_iterator<I>> {
970 return {child_begin(x), child_end(x)};
971}
972
973/**************************************************************************************************/
974
975/*
976 NOTE (fbrereto) : The Doxygen documentation is inline for the functions below because their
977 signatures are particularly prone to translation error.
978*/
979
989
990template <typename R, typename P> // R models FullorderRange
991auto filter_fullorder_range(R& x, P p) -> boost::iterator_range<
994
995 return {iterator(std::begin(x), std::end(x), p), iterator(std::end(x), std::end(x), p)};
996}
997
1007
1008template <typename R, typename P> // R models FullorderRange
1009auto filter_fullorder_range(const R& x, P p) -> boost::iterator_range<
1012
1013 return {iterator(std::begin(x), std::end(x), p), iterator(std::end(x), std::end(x), p)};
1014}
1015
1016/**************************************************************************************************/
1017
1018/*
1019 REVISIT (sparent) : There should be some way to generalize this into a make_range - which is
1020 specialized.
1021
1022 One option -
1023
1024 reverse_range(R& x)
1025
1026 Hmmm - maybe reverse_fullorder_iterator should be a specialization of std::reverse_iterator?
1027*/
1028
1037
1038template <typename R> // R models FullorderRange
1040 -> boost::iterator_range<reverse_fullorder_iterator<typename boost::range_iterator<R>::type>> {
1042
1043 return {iterator(std::end(x)), iterator(std::begin(x))};
1044}
1045
1054
1055template <typename R> // R models FullorderRange
1056inline boost::iterator_range<
1060
1061 return {iterator(std::end(x)), iterator(std::begin(x))};
1062}
1063
1064
1065/**************************************************************************************************/
1066
1075
1076template <typename R> // R models FullorderRange
1077inline boost::iterator_range<depth_fullorder_iterator<typename boost::range_iterator<R>::type>>
1080
1081 return {iterator(std::begin(x)), iterator(std::end(x))};
1082}
1083
1092
1093template <typename R> // R models FullorderRange
1094inline boost::iterator_range<
1096depth_range(const R& x) {
1098
1099 return {iterator(std::begin(x)), iterator(std::end(x))};
1100}
1101
1102/**************************************************************************************************/
1103
1112
1113template <typename R> // R models FullorderRange
1114inline boost::iterator_range<
1118
1119 return {iterator(std::begin(x)), iterator(std::end(x))};
1120}
1121
1130
1131template <typename R> // R models FullorderRange
1132inline boost::iterator_range<
1134postorder_range(const R& x) {
1136 iterator;
1137
1138 return {iterator(std::begin(x)), iterator(std::end(x))};
1139}
1140
1141/**************************************************************************************************/
1142
1151
1152template <typename R> // R models FullorderRange
1153inline boost::iterator_range<
1157
1158 return {iterator(std::begin(x)), iterator(std::end(x))};
1159}
1160
1169
1170template <typename R> // R models FullorderRange
1171inline boost::iterator_range<
1173preorder_range(const R& x) {
1175 iterator;
1176
1177 return {iterator(std::begin(x)), iterator(std::end(x))};
1178}
1179
1180/**************************************************************************************************/
1181
1196
1197template <typename SourceForestIterType, typename DestForestType, typename UnaryFunction>
1198void transform_forest(SourceForestIterType first, SourceForestIterType last,
1199 DestForestType& destForest, typename DestForestType::iterator destIter,
1200 UnaryFunction transformFunc) {
1201
1202 std::stack<typename DestForestType::iterator> insertionIterStack;
1203 insertionIterStack.push(destIter);
1204
1205 while (first != last) {
1206 if (first.edge() == forest_leading_edge) {
1207 auto insertedIter =
1208 destForest.insert(!insertionIterStack.empty() ? insertionIterStack.top() : destIter,
1209 transformFunc(*first));
1210 insertionIterStack.push(trailing_of(insertedIter));
1211 } else {
1212 if (!insertionIterStack.empty())
1213 insertionIterStack.pop();
1214 }
1215 ++first;
1216 }
1217}
1218
1231
1232template <typename SourceForestIterType, typename DestForestType, typename UnaryFunction>
1233void transform_forest(SourceForestIterType first, SourceForestIterType last,
1234 DestForestType& destForest, UnaryFunction transformFunc) {
1235 transform_forest(first, last, destForest, destForest.end(), transformFunc);
1236}
1237
1251
1252template <typename SourceForestType, typename DestForestType, typename UnaryFunction>
1253void transform_forest(SourceForestType sourceForest, DestForestType& destForest,
1254 typename DestForestType::iterator destIter, UnaryFunction transformFunc) {
1255 transform_forest(sourceForest.begin(), sourceForest.end(), destForest, destIter, transformFunc);
1256}
1257
1258
1270
1271template <typename SourceForestType, typename DestForestType, typename UnaryFunction>
1272void transform_forest(SourceForestType sourceForest, DestForestType& destForest,
1273 UnaryFunction transformFunc) {
1274 transform_forest(sourceForest.begin(), sourceForest.end(), destForest, destForest.end(),
1275 transformFunc);
1276}
1277
1278/**************************************************************************************************/
1279
1280} // namespace adobe
1281
1282/**************************************************************************************************/
1283
1284#endif
1285
1286/**************************************************************************************************/
Forest::child_iterator iterator
Definition forest.hpp:946
Forest::iterator iterator_type
Definition forest.hpp:942
value_type & back()
Definition forest.hpp:950
void push_back(const value_type &x)
Definition forest.hpp:953
void push_front(const value_type &x)
Definition forest.hpp:954
Forest::difference_type difference_type
Definition forest.hpp:945
value_type & front()
Definition forest.hpp:951
Forest::value_type value_type
Definition forest.hpp:941
child_adaptor(forest_type &f, iterator_type &i)
Definition forest.hpp:948
Forest::reference reference
Definition forest.hpp:943
Forest::const_reference const_reference
Definition forest.hpp:944
An iterator used to traverse the children of a specific node in a forest.
Definition forest.hpp:89
child_iterator(const child_iterator< U > &u)
Definition forest.hpp:94
depth_fullorder_iterator(I x, difference_type d=0)
Definition forest.hpp:312
difference_type depth() const
Definition forest.hpp:318
depth_fullorder_iterator(const depth_fullorder_iterator< U > &x)
Definition forest.hpp:315
depth_fullorder_iterator(difference_type d=0)
Definition forest.hpp:311
std::size_t edge() const
Definition forest.hpp:319
friend class boost::iterator_core_access
Definition forest.hpp:326
boost::iterator_adaptor< depth_fullorder_iterator< I >, I >::difference_type difference_type
Definition forest.hpp:309
bool equal_node(depth_fullorder_iterator const &y) const
Definition forest.hpp:321
An iterator used to traverse a specific edge type within a forest.
Definition forest.hpp:128
edge_iterator(const edge_iterator< U, Edge > &u)
Definition forest.hpp:133
filter_fullorder_iterator(const filter_fullorder_iterator< U, P > &x)
Definition forest.hpp:168
filter_fullorder_iterator(I f, I l, P p)
Definition forest.hpp:159
std::size_t edge() const
Definition forest.hpp:174
friend class boost::iterator_core_access
Definition forest.hpp:182
bool equal_node(const filter_fullorder_iterator &y) const
Definition forest.hpp:177
A homogeneous hierarchical structure class.
Definition forest.hpp:555
void pop_back()
Definition forest.hpp:670
const_reverse_iterator rend() const
Definition forest.hpp:624
iterator splice(iterator position, forest< T > &x)
Definition forest.hpp:835
const_reference front() const
Definition forest.hpp:630
iterator insert_parent(child_iterator front, child_iterator back, const T &x)
Definition forest.hpp:902
bool size_valid() const
Definition forest.hpp:609
boost::iterator_range< depth_fullorder_iterator< typename boost::range_iterator< R >::type > > depth_range(R &x)
Definition forest.hpp:1078
const_iterator begin() const
Definition forest.hpp:618
edge_iterator< iterator, forest_trailing_edge > postorder_iterator
Definition forest.hpp:584
void transform_forest(SourceForestType sourceForest, DestForestType &destForest, UnaryFunction transformFunc)
Definition forest.hpp:1272
const_iterator root() const
Definition forest.hpp:614
void transform_forest(SourceForestType sourceForest, DestForestType &destForest, typename DestForestType::iterator destIter, UnaryFunction transformFunc)
Definition forest.hpp:1253
adobe::child_iterator< iterator > child_iterator
Definition forest.hpp:574
adobe::child_iterator< const_iterator > const_child_iterator
Definition forest.hpp:579
boost::iterator_range< edge_iterator< typename boost::range_const_iterator< R >::type, forest_leading_edge > > preorder_range(const R &x)
Definition forest.hpp:1173
const T * const_pointer
Definition forest.hpp:570
size_type size() const
Definition forest.hpp:769
void pop_front()
Definition forest.hpp:666
boost::iterator_range< edge_iterator< typename boost::range_iterator< R >::type, forest_leading_edge > > preorder_range(R &x)
Definition forest.hpp:1155
const_reference back() const
Definition forest.hpp:638
auto filter_fullorder_range(const R &x, P p) -> boost::iterator_range< filter_fullorder_iterator< typename boost::range_const_iterator< R >::type, P > >
Definition forest.hpp:1009
bool empty() const
Definition forest.hpp:610
reverse_iterator rend()
Definition forest.hpp:622
reference front()
Definition forest.hpp:626
std::reverse_iterator< child_iterator > reverse_child_iterator
Definition forest.hpp:580
boost::iterator_range< edge_iterator< typename boost::range_iterator< R >::type, forest_trailing_edge > > postorder_range(R &x)
Definition forest.hpp:1116
boost::iterator_range< reverse_fullorder_iterator< typename boost::range_const_iterator< R >::type > > reverse_fullorder_range(const R &x)
Definition forest.hpp:1058
void push_back(const T &x)
Definition forest.hpp:665
reverse_fullorder_iterator< iterator > reverse_iterator
Definition forest.hpp:571
edge_iterator< const_iterator, forest_trailing_edge > const_postorder_iterator
Definition forest.hpp:585
std::size_t size_type
Definition forest.hpp:566
size_type max_size() const
Definition forest.hpp:608
edge_iterator< const_iterator, forest_leading_edge > const_preorder_iterator
Definition forest.hpp:583
void reverse(child_iterator first, child_iterator last)
Definition forest.hpp:914
reverse_fullorder_iterator< const_iterator > const_reverse_iterator
Definition forest.hpp:572
iterator erase(const iterator &position)
Definition forest.hpp:805
void swap(forest &)
Definition forest.hpp:760
void push_front(const T &x)
Definition forest.hpp:664
iterator root()
Definition forest.hpp:613
edge_iterator< iterator, forest_leading_edge > preorder_iterator
Definition forest.hpp:582
forest & operator=(forest &&x) noexcept
Definition forest.hpp:598
void clear()
Definition forest.hpp:644
implementation::forest_iterator< T > iterator
Definition forest.hpp:564
iterator end()
Definition forest.hpp:617
const_iterator end() const
Definition forest.hpp:619
reverse_iterator rbegin()
Definition forest.hpp:621
iterator insert(const iterator &position, T x)
Definition forest.hpp:652
std::ptrdiff_t difference_type
Definition forest.hpp:567
boost::iterator_range< depth_fullorder_iterator< typename boost::range_const_iterator< R >::type > > depth_range(const R &x)
Definition forest.hpp:1096
iterator begin()
Definition forest.hpp:616
implementation::forest_const_iterator< T > const_iterator
Definition forest.hpp:565
forest()=default
boost::iterator_range< edge_iterator< typename boost::range_const_iterator< R >::type, forest_trailing_edge > > postorder_range(const R &x)
Definition forest.hpp:1134
void transform_forest(SourceForestIterType first, SourceForestIterType last, DestForestType &destForest, UnaryFunction transformFunc)
Definition forest.hpp:1233
auto filter_fullorder_range(R &x, P p) -> boost::iterator_range< filter_fullorder_iterator< typename boost::range_iterator< R >::type, P > >
Definition forest.hpp:991
const_reverse_iterator rbegin() const
Definition forest.hpp:623
auto reverse_fullorder_range(R &x) -> boost::iterator_range< reverse_fullorder_iterator< typename boost::range_iterator< R >::type > >
Definition forest.hpp:1039
void transform_forest(SourceForestIterType first, SourceForestIterType last, DestForestType &destForest, typename DestForestType::iterator destIter, UnaryFunction transformFunc)
Definition forest.hpp:1198
reference back()
Definition forest.hpp:634
const T & const_reference
Definition forest.hpp:563
reverse_fullorder_iterator(const reverse_fullorder_iterator< U > &x)
Definition forest.hpp:268
inherited_t::reference reference
Definition forest.hpp:262
bool equal_node(const reverse_fullorder_iterator &y) const
Definition forest.hpp:276
void set_next(I x, I y)
Definition set_next.hpp:44
boost::range_difference< InputRange >::type count(InputRange &range, T &value)
count implementation
Definition count.hpp:40
bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred)
Definition equal.hpp:36
T::iterator erase(T &x, typename T::iterator f, typename T::iterator l)
Definition erase_if.hpp:65
I reverse_nodes(I first, I last)
Definition reverse.hpp:69
boost::range_size< Selection >::type size(const Selection &x)
void swap(any_regular_t &x, any_regular_t &y)
bool operator==(const any_regular_t &x, const any_regular_t &y)
@ forest_trailing_edge
Definition forest.hpp:39
@ forest_leading_edge
Definition forest.hpp:39
child_iterator< I > child_begin(const I &x)
Definition forest.hpp:924
void pivot(I &i)
Definition forest.hpp:44
I find_edge_reverse(I x, std::size_t edge)
Definition forest.hpp:119
child_iterator< I > child_end(const I &x)
Definition forest.hpp:931
I trailing_of(I i)
Definition forest.hpp:63
bool has_children(const I &i)
Definition forest.hpp:82
I pivot_of(I i)
Definition forest.hpp:49
I leading_of(I i)
Definition forest.hpp:57
auto child_range(const I &x) -> boost::iterator_range< child_iterator< I > >
Definition forest.hpp:969
bool operator!=(const forest< T > &x, const forest< T > &y)
Definition forest.hpp:722
I find_edge(I x, std::size_t edge)
Definition forest.hpp:112
I find_parent(I i)
Definition forest.hpp:71
void swap(adobe::extents_t::slice_t &x, adobe::extents_t::slice_t &y) BOOST_NOEXCEPT
Definition extents.hpp:120
void operator()(child_iterator< I > x, child_iterator< I > y)
Definition forest.hpp:732