2 /******************************************************************************
3 * MODULE : tree_position.cpp
4 * DESCRIPTION: Persistently attach cursor positions to trees
5 * COPYRIGHT : (C) 2005 Joris van der Hoeven
6 *******************************************************************************
7 * An inverse path observer maintains the inverse path of the position
8 * of the corresponding tree with respect to the global meta-tree.
9 *******************************************************************************
10 * This software falls under the GNU general public license version 3 or later.
11 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
12 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
13 ******************************************************************************/
20 /******************************************************************************
21 * Definition of the tree_position_rep class
22 ******************************************************************************/
24 class tree_position_rep
: public observer_rep
{
29 tree_position_rep (tree ref
, int index2
): ptr (ref
.rep
), index (index2
) {}
30 int get_type () { return OBSERVER_POSITION
; }
31 tm_ostream
& print (tm_ostream
& out
) { return out
<< " " << index
; }
33 void notify_assign (tree
& ref
, tree t
);
34 void notify_insert (tree
& ref
, int pos
, int nr
);
35 void notify_remove (tree
& ref
, int pos
, int nr
);
36 void notify_split (tree
& ref
, int pos
, tree prev
);
37 void notify_var_split (tree
& ref
, tree t1
, tree t2
);
38 void notify_join (tree
& ref
, int pos
, tree next
);
39 void notify_var_join (tree
& ref
, tree t
, int offset
);
40 void notify_assign_node (tree
& ref
, tree_label op
);
41 void notify_insert_node (tree
& ref
, int pos
);
42 void notify_remove_node (tree
& ref
, int pos
);
43 void notify_detach (tree
& ref
, tree closest
, bool right
);
45 bool get_position (tree
& t
, int& index
);
46 bool set_position (tree t
, int index
);
49 /******************************************************************************
50 * Re-attaching the position to another tree
51 ******************************************************************************/
54 tree_position_rep::get_position (tree
& t
, int& index2
) {
61 tree_position_rep::set_position (tree t
, int index2
) {
63 detach_observer (ref
, observer (this));
66 attach_observer (t
, observer (this));
71 reattach_at (tree_position_rep
* rep
, tree t
, int index
) {
72 rep
->set_position (t
, index
);
75 void reattach_left (tree_position_rep
* rep
, tree t
) {
76 reattach_at (rep
, t
, 0); }
77 void reattach_right (tree_position_rep
* rep
, tree t
) {
78 reattach_at (rep
, t
, right_index (t
)); }
80 /******************************************************************************
81 * Call back routines for modifications
82 ******************************************************************************/
85 tree_position_rep::notify_assign (tree
& ref
, tree t
) {
86 // cout << "Notify assign " << ref << ", " << t << "\n";
88 (is_atomic (ref
) && (index
<= (N(ref
->label
) >> 1))) || (index
== 0);
89 if (left
) reattach_left (this, t
);
90 else reattach_right (this, t
);
91 // cout << "position -> " << obtain_position (observer (this)) << "\n";
95 tree_position_rep::notify_insert (tree
& ref
, int pos
, int nr
) {
96 // cout << "Notify insert " << ref << ", " << pos << ", " << nr << "\n";
97 if (is_atomic (ref
) && index
>= pos
)
99 // cout << "position -> " << obtain_position (observer (this)) << "\n";
103 tree_position_rep::notify_remove (tree
& ref
, int pos
, int nr
) {
104 // cout << "Notify remove " << ref << ", " << pos << ", " << nr << "\n";
105 if (is_atomic (ref
)) {
107 index
= max (pos
, index
- nr
);
109 // cout << "position -> " << obtain_position (observer (this)) << "\n";
113 tree_position_rep::notify_split (tree
& ref
, int pos
, tree prev
) {
114 (void) ref
; (void) pos
; (void) prev
;
118 tree_position_rep::notify_var_split (tree
& ref
, tree t1
, tree t2
) {
119 // cout << "Notify var split " << ref << ", " << t1 << ", " << t2 << "\n";
120 if (is_atomic (ref
)) {
121 if (index
<= N(t1
->label
)) reattach_at (this, t1
, index
);
122 else reattach_at (this, t2
, index
- N(t1
->label
));
125 if (index
== 0) reattach_left (this, t1
);
126 else reattach_right (this, t2
);
128 // cout << "position -> " << obtain_position (observer (this)) << "\n";
132 tree_position_rep::notify_join (tree
& ref
, int pos
, tree next
) {
133 (void) ref
; (void) pos
; (void) next
;
137 tree_position_rep::notify_var_join (tree
& ref
, tree t
, int offset
) {
138 // cout << "Notify var join " << ref << ", " << t << ", " << offset << "\n";
140 reattach_at (this, t
, index
+ offset
);
142 if (index
== 0) reattach_right (this, t
[offset
-1]);
143 else reattach_right (this, t
);
145 // cout << "position -> " << obtain_position (observer (this)) << "\n";
149 tree_position_rep::notify_assign_node (tree
& ref
, tree_label op
) {
150 // cout << "Notify assign node " << ref << ", " << as_string (op) << "\n";
151 (void) ref
; (void) op
;
152 // cout << "position -> " << obtain_position (observer (this)) << "\n";
156 tree_position_rep::notify_insert_node (tree
& ref
, int pos
) {
157 // cout << "Notify insert node " << ref << ", " << pos << "\n";
158 (void) ref
; (void) pos
;
159 // cout << "position -> " << obtain_position (observer (this)) << "\n";
163 tree_position_rep::notify_remove_node (tree
& ref
, int pos
) {
164 // cout << "Notify remove node " << ref << ", " << pos << "\n";
165 if (index
== 0) reattach_left (this, ref
[pos
]);
166 else reattach_right (this, ref
[pos
]);
167 // cout << "position -> " << obtain_position (observer (this)) << "\n";
171 tree_position_rep::notify_detach (tree
& ref
, tree closest
, bool right
) {
173 // cout << "Notify detach " << ref << ", " << closest <<", "<< right << "\n";
174 if (right
) reattach_right (this, closest
);
175 else reattach_left (this, closest
);
176 // cout << "position -> " << obtain_position (observer (this)) << "\n";
179 /******************************************************************************
181 ******************************************************************************/
184 tree_position (tree ref
, int index
) {
185 return tm_new
<tree_position_rep
> (ref
, index
);
189 obtain_position (observer o
) {
192 if (!o
->get_position (t
, index
)) return path ();
193 path ip
= obtain_ip (t
);
194 if (ip
== path (DETACHED
)) return path ();
195 return reverse (ip
) * index
;