annotate gcc/ada/libgnat/a-cbmutr.adb @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 ------------------------------------------------------------------------------
kono
parents:
diff changeset
2 -- --
kono
parents:
diff changeset
3 -- GNAT LIBRARY COMPONENTS --
kono
parents:
diff changeset
4 -- --
kono
parents:
diff changeset
5 -- ADA.CONTAINERS.BOUNDED_MULTIWAY_TREES --
kono
parents:
diff changeset
6 -- --
kono
parents:
diff changeset
7 -- B o d y --
kono
parents:
diff changeset
8 -- --
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
9 -- Copyright (C) 2011-2019, Free Software Foundation, Inc. --
111
kono
parents:
diff changeset
10 -- --
kono
parents:
diff changeset
11 -- GNAT is free software; you can redistribute it and/or modify it under --
kono
parents:
diff changeset
12 -- terms of the GNU General Public License as published by the Free Soft- --
kono
parents:
diff changeset
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
kono
parents:
diff changeset
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
kono
parents:
diff changeset
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
kono
parents:
diff changeset
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
kono
parents:
diff changeset
17 -- --
kono
parents:
diff changeset
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
kono
parents:
diff changeset
19 -- additional permissions described in the GCC Runtime Library Exception, --
kono
parents:
diff changeset
20 -- version 3.1, as published by the Free Software Foundation. --
kono
parents:
diff changeset
21 -- --
kono
parents:
diff changeset
22 -- You should have received a copy of the GNU General Public License and --
kono
parents:
diff changeset
23 -- a copy of the GCC Runtime Library Exception along with this program; --
kono
parents:
diff changeset
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
kono
parents:
diff changeset
25 -- <http://www.gnu.org/licenses/>. --
kono
parents:
diff changeset
26 -- --
kono
parents:
diff changeset
27 -- This unit was originally developed by Matthew J Heaney. --
kono
parents:
diff changeset
28 ------------------------------------------------------------------------------
kono
parents:
diff changeset
29
kono
parents:
diff changeset
30 with Ada.Finalization;
kono
parents:
diff changeset
31 with System; use type System.Address;
kono
parents:
diff changeset
32
kono
parents:
diff changeset
33 package body Ada.Containers.Bounded_Multiway_Trees is
kono
parents:
diff changeset
34
kono
parents:
diff changeset
35 pragma Warnings (Off, "variable ""Busy*"" is not referenced");
kono
parents:
diff changeset
36 pragma Warnings (Off, "variable ""Lock*"" is not referenced");
kono
parents:
diff changeset
37 -- See comment in Ada.Containers.Helpers
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39 use Finalization;
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 --------------------
kono
parents:
diff changeset
42 -- Root_Iterator --
kono
parents:
diff changeset
43 --------------------
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 type Root_Iterator is abstract new Limited_Controlled and
kono
parents:
diff changeset
46 Tree_Iterator_Interfaces.Forward_Iterator with
kono
parents:
diff changeset
47 record
kono
parents:
diff changeset
48 Container : Tree_Access;
kono
parents:
diff changeset
49 Subtree : Count_Type;
kono
parents:
diff changeset
50 end record;
kono
parents:
diff changeset
51
kono
parents:
diff changeset
52 overriding procedure Finalize (Object : in out Root_Iterator);
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 -----------------------
kono
parents:
diff changeset
55 -- Subtree_Iterator --
kono
parents:
diff changeset
56 -----------------------
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 type Subtree_Iterator is new Root_Iterator with null record;
kono
parents:
diff changeset
59
kono
parents:
diff changeset
60 overriding function First (Object : Subtree_Iterator) return Cursor;
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 overriding function Next
kono
parents:
diff changeset
63 (Object : Subtree_Iterator;
kono
parents:
diff changeset
64 Position : Cursor) return Cursor;
kono
parents:
diff changeset
65
kono
parents:
diff changeset
66 ---------------------
kono
parents:
diff changeset
67 -- Child_Iterator --
kono
parents:
diff changeset
68 ---------------------
kono
parents:
diff changeset
69
kono
parents:
diff changeset
70 type Child_Iterator is new Root_Iterator and
kono
parents:
diff changeset
71 Tree_Iterator_Interfaces.Reversible_Iterator with null record;
kono
parents:
diff changeset
72
kono
parents:
diff changeset
73 overriding function First (Object : Child_Iterator) return Cursor;
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 overriding function Next
kono
parents:
diff changeset
76 (Object : Child_Iterator;
kono
parents:
diff changeset
77 Position : Cursor) return Cursor;
kono
parents:
diff changeset
78
kono
parents:
diff changeset
79 overriding function Last (Object : Child_Iterator) return Cursor;
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81 overriding function Previous
kono
parents:
diff changeset
82 (Object : Child_Iterator;
kono
parents:
diff changeset
83 Position : Cursor) return Cursor;
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 -----------------------
kono
parents:
diff changeset
86 -- Local Subprograms --
kono
parents:
diff changeset
87 -----------------------
kono
parents:
diff changeset
88
kono
parents:
diff changeset
89 procedure Initialize_Node (Container : in out Tree; Index : Count_Type);
kono
parents:
diff changeset
90 procedure Initialize_Root (Container : in out Tree);
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 procedure Allocate_Node
kono
parents:
diff changeset
93 (Container : in out Tree;
kono
parents:
diff changeset
94 Initialize_Element : not null access procedure (Index : Count_Type);
kono
parents:
diff changeset
95 New_Node : out Count_Type);
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 procedure Allocate_Node
kono
parents:
diff changeset
98 (Container : in out Tree;
kono
parents:
diff changeset
99 New_Item : Element_Type;
kono
parents:
diff changeset
100 New_Node : out Count_Type);
kono
parents:
diff changeset
101
kono
parents:
diff changeset
102 procedure Allocate_Node
kono
parents:
diff changeset
103 (Container : in out Tree;
kono
parents:
diff changeset
104 Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
105 New_Node : out Count_Type);
kono
parents:
diff changeset
106
kono
parents:
diff changeset
107 procedure Deallocate_Node
kono
parents:
diff changeset
108 (Container : in out Tree;
kono
parents:
diff changeset
109 X : Count_Type);
kono
parents:
diff changeset
110
kono
parents:
diff changeset
111 procedure Deallocate_Children
kono
parents:
diff changeset
112 (Container : in out Tree;
kono
parents:
diff changeset
113 Subtree : Count_Type;
kono
parents:
diff changeset
114 Count : in out Count_Type);
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 procedure Deallocate_Subtree
kono
parents:
diff changeset
117 (Container : in out Tree;
kono
parents:
diff changeset
118 Subtree : Count_Type;
kono
parents:
diff changeset
119 Count : in out Count_Type);
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 function Equal_Children
kono
parents:
diff changeset
122 (Left_Tree : Tree;
kono
parents:
diff changeset
123 Left_Subtree : Count_Type;
kono
parents:
diff changeset
124 Right_Tree : Tree;
kono
parents:
diff changeset
125 Right_Subtree : Count_Type) return Boolean;
kono
parents:
diff changeset
126
kono
parents:
diff changeset
127 function Equal_Subtree
kono
parents:
diff changeset
128 (Left_Tree : Tree;
kono
parents:
diff changeset
129 Left_Subtree : Count_Type;
kono
parents:
diff changeset
130 Right_Tree : Tree;
kono
parents:
diff changeset
131 Right_Subtree : Count_Type) return Boolean;
kono
parents:
diff changeset
132
kono
parents:
diff changeset
133 procedure Iterate_Children
kono
parents:
diff changeset
134 (Container : Tree;
kono
parents:
diff changeset
135 Subtree : Count_Type;
kono
parents:
diff changeset
136 Process : not null access procedure (Position : Cursor));
kono
parents:
diff changeset
137
kono
parents:
diff changeset
138 procedure Iterate_Subtree
kono
parents:
diff changeset
139 (Container : Tree;
kono
parents:
diff changeset
140 Subtree : Count_Type;
kono
parents:
diff changeset
141 Process : not null access procedure (Position : Cursor));
kono
parents:
diff changeset
142
kono
parents:
diff changeset
143 procedure Copy_Children
kono
parents:
diff changeset
144 (Source : Tree;
kono
parents:
diff changeset
145 Source_Parent : Count_Type;
kono
parents:
diff changeset
146 Target : in out Tree;
kono
parents:
diff changeset
147 Target_Parent : Count_Type;
kono
parents:
diff changeset
148 Count : in out Count_Type);
kono
parents:
diff changeset
149
kono
parents:
diff changeset
150 procedure Copy_Subtree
kono
parents:
diff changeset
151 (Source : Tree;
kono
parents:
diff changeset
152 Source_Subtree : Count_Type;
kono
parents:
diff changeset
153 Target : in out Tree;
kono
parents:
diff changeset
154 Target_Parent : Count_Type;
kono
parents:
diff changeset
155 Target_Subtree : out Count_Type;
kono
parents:
diff changeset
156 Count : in out Count_Type);
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 function Find_In_Children
kono
parents:
diff changeset
159 (Container : Tree;
kono
parents:
diff changeset
160 Subtree : Count_Type;
kono
parents:
diff changeset
161 Item : Element_Type) return Count_Type;
kono
parents:
diff changeset
162
kono
parents:
diff changeset
163 function Find_In_Subtree
kono
parents:
diff changeset
164 (Container : Tree;
kono
parents:
diff changeset
165 Subtree : Count_Type;
kono
parents:
diff changeset
166 Item : Element_Type) return Count_Type;
kono
parents:
diff changeset
167
kono
parents:
diff changeset
168 function Child_Count
kono
parents:
diff changeset
169 (Container : Tree;
kono
parents:
diff changeset
170 Parent : Count_Type) return Count_Type;
kono
parents:
diff changeset
171
kono
parents:
diff changeset
172 function Subtree_Node_Count
kono
parents:
diff changeset
173 (Container : Tree;
kono
parents:
diff changeset
174 Subtree : Count_Type) return Count_Type;
kono
parents:
diff changeset
175
kono
parents:
diff changeset
176 function Is_Reachable
kono
parents:
diff changeset
177 (Container : Tree;
kono
parents:
diff changeset
178 From, To : Count_Type) return Boolean;
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 function Root_Node (Container : Tree) return Count_Type;
kono
parents:
diff changeset
181
kono
parents:
diff changeset
182 procedure Remove_Subtree
kono
parents:
diff changeset
183 (Container : in out Tree;
kono
parents:
diff changeset
184 Subtree : Count_Type);
kono
parents:
diff changeset
185
kono
parents:
diff changeset
186 procedure Insert_Subtree_Node
kono
parents:
diff changeset
187 (Container : in out Tree;
kono
parents:
diff changeset
188 Subtree : Count_Type'Base;
kono
parents:
diff changeset
189 Parent : Count_Type;
kono
parents:
diff changeset
190 Before : Count_Type'Base);
kono
parents:
diff changeset
191
kono
parents:
diff changeset
192 procedure Insert_Subtree_List
kono
parents:
diff changeset
193 (Container : in out Tree;
kono
parents:
diff changeset
194 First : Count_Type'Base;
kono
parents:
diff changeset
195 Last : Count_Type'Base;
kono
parents:
diff changeset
196 Parent : Count_Type;
kono
parents:
diff changeset
197 Before : Count_Type'Base);
kono
parents:
diff changeset
198
kono
parents:
diff changeset
199 procedure Splice_Children
kono
parents:
diff changeset
200 (Container : in out Tree;
kono
parents:
diff changeset
201 Target_Parent : Count_Type;
kono
parents:
diff changeset
202 Before : Count_Type'Base;
kono
parents:
diff changeset
203 Source_Parent : Count_Type);
kono
parents:
diff changeset
204
kono
parents:
diff changeset
205 procedure Splice_Children
kono
parents:
diff changeset
206 (Target : in out Tree;
kono
parents:
diff changeset
207 Target_Parent : Count_Type;
kono
parents:
diff changeset
208 Before : Count_Type'Base;
kono
parents:
diff changeset
209 Source : in out Tree;
kono
parents:
diff changeset
210 Source_Parent : Count_Type);
kono
parents:
diff changeset
211
kono
parents:
diff changeset
212 procedure Splice_Subtree
kono
parents:
diff changeset
213 (Target : in out Tree;
kono
parents:
diff changeset
214 Parent : Count_Type;
kono
parents:
diff changeset
215 Before : Count_Type'Base;
kono
parents:
diff changeset
216 Source : in out Tree;
kono
parents:
diff changeset
217 Position : in out Count_Type); -- source on input, target on output
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219 ---------
kono
parents:
diff changeset
220 -- "=" --
kono
parents:
diff changeset
221 ---------
kono
parents:
diff changeset
222
kono
parents:
diff changeset
223 function "=" (Left, Right : Tree) return Boolean is
kono
parents:
diff changeset
224 begin
kono
parents:
diff changeset
225 if Left.Count /= Right.Count then
kono
parents:
diff changeset
226 return False;
kono
parents:
diff changeset
227 end if;
kono
parents:
diff changeset
228
kono
parents:
diff changeset
229 if Left.Count = 0 then
kono
parents:
diff changeset
230 return True;
kono
parents:
diff changeset
231 end if;
kono
parents:
diff changeset
232
kono
parents:
diff changeset
233 return Equal_Children
kono
parents:
diff changeset
234 (Left_Tree => Left,
kono
parents:
diff changeset
235 Left_Subtree => Root_Node (Left),
kono
parents:
diff changeset
236 Right_Tree => Right,
kono
parents:
diff changeset
237 Right_Subtree => Root_Node (Right));
kono
parents:
diff changeset
238 end "=";
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 -------------------
kono
parents:
diff changeset
241 -- Allocate_Node --
kono
parents:
diff changeset
242 -------------------
kono
parents:
diff changeset
243
kono
parents:
diff changeset
244 procedure Allocate_Node
kono
parents:
diff changeset
245 (Container : in out Tree;
kono
parents:
diff changeset
246 Initialize_Element : not null access procedure (Index : Count_Type);
kono
parents:
diff changeset
247 New_Node : out Count_Type)
kono
parents:
diff changeset
248 is
kono
parents:
diff changeset
249 begin
kono
parents:
diff changeset
250 if Container.Free >= 0 then
kono
parents:
diff changeset
251 New_Node := Container.Free;
kono
parents:
diff changeset
252 pragma Assert (New_Node in Container.Elements'Range);
kono
parents:
diff changeset
253
kono
parents:
diff changeset
254 -- We always perform the assignment first, before we change container
kono
parents:
diff changeset
255 -- state, in order to defend against exceptions duration assignment.
kono
parents:
diff changeset
256
kono
parents:
diff changeset
257 Initialize_Element (New_Node);
kono
parents:
diff changeset
258
kono
parents:
diff changeset
259 Container.Free := Container.Nodes (New_Node).Next;
kono
parents:
diff changeset
260
kono
parents:
diff changeset
261 else
kono
parents:
diff changeset
262 -- A negative free store value means that the links of the nodes in
kono
parents:
diff changeset
263 -- the free store have not been initialized. In this case, the nodes
kono
parents:
diff changeset
264 -- are physically contiguous in the array, starting at the index that
kono
parents:
diff changeset
265 -- is the absolute value of the Container.Free, and continuing until
kono
parents:
diff changeset
266 -- the end of the array (Nodes'Last).
kono
parents:
diff changeset
267
kono
parents:
diff changeset
268 New_Node := abs Container.Free;
kono
parents:
diff changeset
269 pragma Assert (New_Node in Container.Elements'Range);
kono
parents:
diff changeset
270
kono
parents:
diff changeset
271 -- As above, we perform this assignment first, before modifying any
kono
parents:
diff changeset
272 -- container state.
kono
parents:
diff changeset
273
kono
parents:
diff changeset
274 Initialize_Element (New_Node);
kono
parents:
diff changeset
275
kono
parents:
diff changeset
276 Container.Free := Container.Free - 1;
kono
parents:
diff changeset
277
kono
parents:
diff changeset
278 if abs Container.Free > Container.Capacity then
kono
parents:
diff changeset
279 Container.Free := 0;
kono
parents:
diff changeset
280 end if;
kono
parents:
diff changeset
281 end if;
kono
parents:
diff changeset
282
kono
parents:
diff changeset
283 Initialize_Node (Container, New_Node);
kono
parents:
diff changeset
284 end Allocate_Node;
kono
parents:
diff changeset
285
kono
parents:
diff changeset
286 procedure Allocate_Node
kono
parents:
diff changeset
287 (Container : in out Tree;
kono
parents:
diff changeset
288 New_Item : Element_Type;
kono
parents:
diff changeset
289 New_Node : out Count_Type)
kono
parents:
diff changeset
290 is
kono
parents:
diff changeset
291 procedure Initialize_Element (Index : Count_Type);
kono
parents:
diff changeset
292
kono
parents:
diff changeset
293 procedure Initialize_Element (Index : Count_Type) is
kono
parents:
diff changeset
294 begin
kono
parents:
diff changeset
295 Container.Elements (Index) := New_Item;
kono
parents:
diff changeset
296 end Initialize_Element;
kono
parents:
diff changeset
297
kono
parents:
diff changeset
298 begin
kono
parents:
diff changeset
299 Allocate_Node (Container, Initialize_Element'Access, New_Node);
kono
parents:
diff changeset
300 end Allocate_Node;
kono
parents:
diff changeset
301
kono
parents:
diff changeset
302 procedure Allocate_Node
kono
parents:
diff changeset
303 (Container : in out Tree;
kono
parents:
diff changeset
304 Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
305 New_Node : out Count_Type)
kono
parents:
diff changeset
306 is
kono
parents:
diff changeset
307 procedure Initialize_Element (Index : Count_Type);
kono
parents:
diff changeset
308
kono
parents:
diff changeset
309 procedure Initialize_Element (Index : Count_Type) is
kono
parents:
diff changeset
310 begin
kono
parents:
diff changeset
311 Element_Type'Read (Stream, Container.Elements (Index));
kono
parents:
diff changeset
312 end Initialize_Element;
kono
parents:
diff changeset
313
kono
parents:
diff changeset
314 begin
kono
parents:
diff changeset
315 Allocate_Node (Container, Initialize_Element'Access, New_Node);
kono
parents:
diff changeset
316 end Allocate_Node;
kono
parents:
diff changeset
317
kono
parents:
diff changeset
318 -------------------
kono
parents:
diff changeset
319 -- Ancestor_Find --
kono
parents:
diff changeset
320 -------------------
kono
parents:
diff changeset
321
kono
parents:
diff changeset
322 function Ancestor_Find
kono
parents:
diff changeset
323 (Position : Cursor;
kono
parents:
diff changeset
324 Item : Element_Type) return Cursor
kono
parents:
diff changeset
325 is
kono
parents:
diff changeset
326 R, N : Count_Type;
kono
parents:
diff changeset
327
kono
parents:
diff changeset
328 begin
kono
parents:
diff changeset
329 if Checks and then Position = No_Element then
kono
parents:
diff changeset
330 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
331 end if;
kono
parents:
diff changeset
332
kono
parents:
diff changeset
333 -- AI-0136 says to raise PE if Position equals the root node. This does
kono
parents:
diff changeset
334 -- not seem correct, as this value is just the limiting condition of the
kono
parents:
diff changeset
335 -- search. For now we omit this check, pending a ruling from the ARG.
kono
parents:
diff changeset
336 -- ???
kono
parents:
diff changeset
337 --
kono
parents:
diff changeset
338 -- if Checks and then Is_Root (Position) then
kono
parents:
diff changeset
339 -- raise Program_Error with "Position cursor designates root";
kono
parents:
diff changeset
340 -- end if;
kono
parents:
diff changeset
341
kono
parents:
diff changeset
342 R := Root_Node (Position.Container.all);
kono
parents:
diff changeset
343 N := Position.Node;
kono
parents:
diff changeset
344 while N /= R loop
kono
parents:
diff changeset
345 if Position.Container.Elements (N) = Item then
kono
parents:
diff changeset
346 return Cursor'(Position.Container, N);
kono
parents:
diff changeset
347 end if;
kono
parents:
diff changeset
348
kono
parents:
diff changeset
349 N := Position.Container.Nodes (N).Parent;
kono
parents:
diff changeset
350 end loop;
kono
parents:
diff changeset
351
kono
parents:
diff changeset
352 return No_Element;
kono
parents:
diff changeset
353 end Ancestor_Find;
kono
parents:
diff changeset
354
kono
parents:
diff changeset
355 ------------------
kono
parents:
diff changeset
356 -- Append_Child --
kono
parents:
diff changeset
357 ------------------
kono
parents:
diff changeset
358
kono
parents:
diff changeset
359 procedure Append_Child
kono
parents:
diff changeset
360 (Container : in out Tree;
kono
parents:
diff changeset
361 Parent : Cursor;
kono
parents:
diff changeset
362 New_Item : Element_Type;
kono
parents:
diff changeset
363 Count : Count_Type := 1)
kono
parents:
diff changeset
364 is
kono
parents:
diff changeset
365 Nodes : Tree_Node_Array renames Container.Nodes;
kono
parents:
diff changeset
366 First, Last : Count_Type;
kono
parents:
diff changeset
367
kono
parents:
diff changeset
368 begin
kono
parents:
diff changeset
369 if Checks and then Parent = No_Element then
kono
parents:
diff changeset
370 raise Constraint_Error with "Parent cursor has no element";
kono
parents:
diff changeset
371 end if;
kono
parents:
diff changeset
372
kono
parents:
diff changeset
373 if Checks and then Parent.Container /= Container'Unrestricted_Access then
kono
parents:
diff changeset
374 raise Program_Error with "Parent cursor not in container";
kono
parents:
diff changeset
375 end if;
kono
parents:
diff changeset
376
kono
parents:
diff changeset
377 if Count = 0 then
kono
parents:
diff changeset
378 return;
kono
parents:
diff changeset
379 end if;
kono
parents:
diff changeset
380
kono
parents:
diff changeset
381 if Checks and then Container.Count > Container.Capacity - Count then
kono
parents:
diff changeset
382 raise Capacity_Error
kono
parents:
diff changeset
383 with "requested count exceeds available storage";
kono
parents:
diff changeset
384 end if;
kono
parents:
diff changeset
385
kono
parents:
diff changeset
386 TC_Check (Container.TC);
kono
parents:
diff changeset
387
kono
parents:
diff changeset
388 if Container.Count = 0 then
kono
parents:
diff changeset
389 Initialize_Root (Container);
kono
parents:
diff changeset
390 end if;
kono
parents:
diff changeset
391
kono
parents:
diff changeset
392 Allocate_Node (Container, New_Item, First);
kono
parents:
diff changeset
393 Nodes (First).Parent := Parent.Node;
kono
parents:
diff changeset
394
kono
parents:
diff changeset
395 Last := First;
kono
parents:
diff changeset
396 for J in Count_Type'(2) .. Count loop
kono
parents:
diff changeset
397 Allocate_Node (Container, New_Item, Nodes (Last).Next);
kono
parents:
diff changeset
398 Nodes (Nodes (Last).Next).Parent := Parent.Node;
kono
parents:
diff changeset
399 Nodes (Nodes (Last).Next).Prev := Last;
kono
parents:
diff changeset
400
kono
parents:
diff changeset
401 Last := Nodes (Last).Next;
kono
parents:
diff changeset
402 end loop;
kono
parents:
diff changeset
403
kono
parents:
diff changeset
404 Insert_Subtree_List
kono
parents:
diff changeset
405 (Container => Container,
kono
parents:
diff changeset
406 First => First,
kono
parents:
diff changeset
407 Last => Last,
kono
parents:
diff changeset
408 Parent => Parent.Node,
kono
parents:
diff changeset
409 Before => No_Node); -- means "insert at end of list"
kono
parents:
diff changeset
410
kono
parents:
diff changeset
411 Container.Count := Container.Count + Count;
kono
parents:
diff changeset
412 end Append_Child;
kono
parents:
diff changeset
413
kono
parents:
diff changeset
414 ------------
kono
parents:
diff changeset
415 -- Assign --
kono
parents:
diff changeset
416 ------------
kono
parents:
diff changeset
417
kono
parents:
diff changeset
418 procedure Assign (Target : in out Tree; Source : Tree) is
kono
parents:
diff changeset
419 Target_Count : Count_Type;
kono
parents:
diff changeset
420
kono
parents:
diff changeset
421 begin
kono
parents:
diff changeset
422 if Target'Address = Source'Address then
kono
parents:
diff changeset
423 return;
kono
parents:
diff changeset
424 end if;
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 if Checks and then Target.Capacity < Source.Count then
kono
parents:
diff changeset
427 raise Capacity_Error -- ???
kono
parents:
diff changeset
428 with "Target capacity is less than Source count";
kono
parents:
diff changeset
429 end if;
kono
parents:
diff changeset
430
kono
parents:
diff changeset
431 Target.Clear; -- Checks busy bit
kono
parents:
diff changeset
432
kono
parents:
diff changeset
433 if Source.Count = 0 then
kono
parents:
diff changeset
434 return;
kono
parents:
diff changeset
435 end if;
kono
parents:
diff changeset
436
kono
parents:
diff changeset
437 Initialize_Root (Target);
kono
parents:
diff changeset
438
kono
parents:
diff changeset
439 -- Copy_Children returns the number of nodes that it allocates, but it
kono
parents:
diff changeset
440 -- does this by incrementing the count value passed in, so we must
kono
parents:
diff changeset
441 -- initialize the count before calling Copy_Children.
kono
parents:
diff changeset
442
kono
parents:
diff changeset
443 Target_Count := 0;
kono
parents:
diff changeset
444
kono
parents:
diff changeset
445 Copy_Children
kono
parents:
diff changeset
446 (Source => Source,
kono
parents:
diff changeset
447 Source_Parent => Root_Node (Source),
kono
parents:
diff changeset
448 Target => Target,
kono
parents:
diff changeset
449 Target_Parent => Root_Node (Target),
kono
parents:
diff changeset
450 Count => Target_Count);
kono
parents:
diff changeset
451
kono
parents:
diff changeset
452 pragma Assert (Target_Count = Source.Count);
kono
parents:
diff changeset
453 Target.Count := Source.Count;
kono
parents:
diff changeset
454 end Assign;
kono
parents:
diff changeset
455
kono
parents:
diff changeset
456 -----------------
kono
parents:
diff changeset
457 -- Child_Count --
kono
parents:
diff changeset
458 -----------------
kono
parents:
diff changeset
459
kono
parents:
diff changeset
460 function Child_Count (Parent : Cursor) return Count_Type is
kono
parents:
diff changeset
461 begin
kono
parents:
diff changeset
462 if Parent = No_Element then
kono
parents:
diff changeset
463 return 0;
kono
parents:
diff changeset
464
kono
parents:
diff changeset
465 elsif Parent.Container.Count = 0 then
kono
parents:
diff changeset
466 pragma Assert (Is_Root (Parent));
kono
parents:
diff changeset
467 return 0;
kono
parents:
diff changeset
468
kono
parents:
diff changeset
469 else
kono
parents:
diff changeset
470 return Child_Count (Parent.Container.all, Parent.Node);
kono
parents:
diff changeset
471 end if;
kono
parents:
diff changeset
472 end Child_Count;
kono
parents:
diff changeset
473
kono
parents:
diff changeset
474 function Child_Count
kono
parents:
diff changeset
475 (Container : Tree;
kono
parents:
diff changeset
476 Parent : Count_Type) return Count_Type
kono
parents:
diff changeset
477 is
kono
parents:
diff changeset
478 NN : Tree_Node_Array renames Container.Nodes;
kono
parents:
diff changeset
479 CC : Children_Type renames NN (Parent).Children;
kono
parents:
diff changeset
480
kono
parents:
diff changeset
481 Result : Count_Type;
kono
parents:
diff changeset
482 Node : Count_Type'Base;
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 begin
kono
parents:
diff changeset
485 Result := 0;
kono
parents:
diff changeset
486 Node := CC.First;
kono
parents:
diff changeset
487 while Node > 0 loop
kono
parents:
diff changeset
488 Result := Result + 1;
kono
parents:
diff changeset
489 Node := NN (Node).Next;
kono
parents:
diff changeset
490 end loop;
kono
parents:
diff changeset
491
kono
parents:
diff changeset
492 return Result;
kono
parents:
diff changeset
493 end Child_Count;
kono
parents:
diff changeset
494
kono
parents:
diff changeset
495 -----------------
kono
parents:
diff changeset
496 -- Child_Depth --
kono
parents:
diff changeset
497 -----------------
kono
parents:
diff changeset
498
kono
parents:
diff changeset
499 function Child_Depth (Parent, Child : Cursor) return Count_Type is
kono
parents:
diff changeset
500 Result : Count_Type;
kono
parents:
diff changeset
501 N : Count_Type'Base;
kono
parents:
diff changeset
502
kono
parents:
diff changeset
503 begin
kono
parents:
diff changeset
504 if Checks and then Parent = No_Element then
kono
parents:
diff changeset
505 raise Constraint_Error with "Parent cursor has no element";
kono
parents:
diff changeset
506 end if;
kono
parents:
diff changeset
507
kono
parents:
diff changeset
508 if Checks and then Child = No_Element then
kono
parents:
diff changeset
509 raise Constraint_Error with "Child cursor has no element";
kono
parents:
diff changeset
510 end if;
kono
parents:
diff changeset
511
kono
parents:
diff changeset
512 if Checks and then Parent.Container /= Child.Container then
kono
parents:
diff changeset
513 raise Program_Error with "Parent and Child in different containers";
kono
parents:
diff changeset
514 end if;
kono
parents:
diff changeset
515
kono
parents:
diff changeset
516 if Parent.Container.Count = 0 then
kono
parents:
diff changeset
517 pragma Assert (Is_Root (Parent));
kono
parents:
diff changeset
518 pragma Assert (Child = Parent);
kono
parents:
diff changeset
519 return 0;
kono
parents:
diff changeset
520 end if;
kono
parents:
diff changeset
521
kono
parents:
diff changeset
522 Result := 0;
kono
parents:
diff changeset
523 N := Child.Node;
kono
parents:
diff changeset
524 while N /= Parent.Node loop
kono
parents:
diff changeset
525 Result := Result + 1;
kono
parents:
diff changeset
526 N := Parent.Container.Nodes (N).Parent;
kono
parents:
diff changeset
527
kono
parents:
diff changeset
528 if Checks and then N < 0 then
kono
parents:
diff changeset
529 raise Program_Error with "Parent is not ancestor of Child";
kono
parents:
diff changeset
530 end if;
kono
parents:
diff changeset
531 end loop;
kono
parents:
diff changeset
532
kono
parents:
diff changeset
533 return Result;
kono
parents:
diff changeset
534 end Child_Depth;
kono
parents:
diff changeset
535
kono
parents:
diff changeset
536 -----------
kono
parents:
diff changeset
537 -- Clear --
kono
parents:
diff changeset
538 -----------
kono
parents:
diff changeset
539
kono
parents:
diff changeset
540 procedure Clear (Container : in out Tree) is
kono
parents:
diff changeset
541 Container_Count : constant Count_Type := Container.Count;
kono
parents:
diff changeset
542 Count : Count_Type;
kono
parents:
diff changeset
543
kono
parents:
diff changeset
544 begin
kono
parents:
diff changeset
545 TC_Check (Container.TC);
kono
parents:
diff changeset
546
kono
parents:
diff changeset
547 if Container_Count = 0 then
kono
parents:
diff changeset
548 return;
kono
parents:
diff changeset
549 end if;
kono
parents:
diff changeset
550
kono
parents:
diff changeset
551 Container.Count := 0;
kono
parents:
diff changeset
552
kono
parents:
diff changeset
553 -- Deallocate_Children returns the number of nodes that it deallocates,
kono
parents:
diff changeset
554 -- but it does this by incrementing the count value that is passed in,
kono
parents:
diff changeset
555 -- so we must first initialize the count return value before calling it.
kono
parents:
diff changeset
556
kono
parents:
diff changeset
557 Count := 0;
kono
parents:
diff changeset
558
kono
parents:
diff changeset
559 Deallocate_Children
kono
parents:
diff changeset
560 (Container => Container,
kono
parents:
diff changeset
561 Subtree => Root_Node (Container),
kono
parents:
diff changeset
562 Count => Count);
kono
parents:
diff changeset
563
kono
parents:
diff changeset
564 pragma Assert (Count = Container_Count);
kono
parents:
diff changeset
565 end Clear;
kono
parents:
diff changeset
566
kono
parents:
diff changeset
567 ------------------------
kono
parents:
diff changeset
568 -- Constant_Reference --
kono
parents:
diff changeset
569 ------------------------
kono
parents:
diff changeset
570
kono
parents:
diff changeset
571 function Constant_Reference
kono
parents:
diff changeset
572 (Container : aliased Tree;
kono
parents:
diff changeset
573 Position : Cursor) return Constant_Reference_Type
kono
parents:
diff changeset
574 is
kono
parents:
diff changeset
575 begin
kono
parents:
diff changeset
576 if Checks and then Position.Container = null then
kono
parents:
diff changeset
577 raise Constraint_Error with
kono
parents:
diff changeset
578 "Position cursor has no element";
kono
parents:
diff changeset
579 end if;
kono
parents:
diff changeset
580
kono
parents:
diff changeset
581 if Checks and then Position.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
582 then
kono
parents:
diff changeset
583 raise Program_Error with
kono
parents:
diff changeset
584 "Position cursor designates wrong container";
kono
parents:
diff changeset
585 end if;
kono
parents:
diff changeset
586
kono
parents:
diff changeset
587 if Checks and then Position.Node = Root_Node (Container) then
kono
parents:
diff changeset
588 raise Program_Error with "Position cursor designates root";
kono
parents:
diff changeset
589 end if;
kono
parents:
diff changeset
590
kono
parents:
diff changeset
591 -- Implement Vet for multiway tree???
kono
parents:
diff changeset
592 -- pragma Assert (Vet (Position),
kono
parents:
diff changeset
593 -- "Position cursor in Constant_Reference is bad");
kono
parents:
diff changeset
594
kono
parents:
diff changeset
595 declare
kono
parents:
diff changeset
596 TC : constant Tamper_Counts_Access :=
kono
parents:
diff changeset
597 Container.TC'Unrestricted_Access;
kono
parents:
diff changeset
598 begin
kono
parents:
diff changeset
599 return R : constant Constant_Reference_Type :=
kono
parents:
diff changeset
600 (Element => Container.Elements (Position.Node)'Access,
kono
parents:
diff changeset
601 Control => (Controlled with TC))
kono
parents:
diff changeset
602 do
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
603 Busy (TC.all);
111
kono
parents:
diff changeset
604 end return;
kono
parents:
diff changeset
605 end;
kono
parents:
diff changeset
606 end Constant_Reference;
kono
parents:
diff changeset
607
kono
parents:
diff changeset
608 --------------
kono
parents:
diff changeset
609 -- Contains --
kono
parents:
diff changeset
610 --------------
kono
parents:
diff changeset
611
kono
parents:
diff changeset
612 function Contains
kono
parents:
diff changeset
613 (Container : Tree;
kono
parents:
diff changeset
614 Item : Element_Type) return Boolean
kono
parents:
diff changeset
615 is
kono
parents:
diff changeset
616 begin
kono
parents:
diff changeset
617 return Find (Container, Item) /= No_Element;
kono
parents:
diff changeset
618 end Contains;
kono
parents:
diff changeset
619
kono
parents:
diff changeset
620 ----------
kono
parents:
diff changeset
621 -- Copy --
kono
parents:
diff changeset
622 ----------
kono
parents:
diff changeset
623
kono
parents:
diff changeset
624 function Copy
kono
parents:
diff changeset
625 (Source : Tree;
kono
parents:
diff changeset
626 Capacity : Count_Type := 0) return Tree
kono
parents:
diff changeset
627 is
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
628 C : constant Count_Type :=
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
629 (if Capacity = 0 then Source.Count
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
630 else Capacity);
111
kono
parents:
diff changeset
631 begin
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
632 if Checks and then C < Source.Count then
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
633 raise Capacity_Error with "Capacity too small";
111
kono
parents:
diff changeset
634 end if;
kono
parents:
diff changeset
635
kono
parents:
diff changeset
636 return Target : Tree (Capacity => C) do
kono
parents:
diff changeset
637 Initialize_Root (Target);
kono
parents:
diff changeset
638
kono
parents:
diff changeset
639 if Source.Count = 0 then
kono
parents:
diff changeset
640 return;
kono
parents:
diff changeset
641 end if;
kono
parents:
diff changeset
642
kono
parents:
diff changeset
643 Copy_Children
kono
parents:
diff changeset
644 (Source => Source,
kono
parents:
diff changeset
645 Source_Parent => Root_Node (Source),
kono
parents:
diff changeset
646 Target => Target,
kono
parents:
diff changeset
647 Target_Parent => Root_Node (Target),
kono
parents:
diff changeset
648 Count => Target.Count);
kono
parents:
diff changeset
649
kono
parents:
diff changeset
650 pragma Assert (Target.Count = Source.Count);
kono
parents:
diff changeset
651 end return;
kono
parents:
diff changeset
652 end Copy;
kono
parents:
diff changeset
653
kono
parents:
diff changeset
654 -------------------
kono
parents:
diff changeset
655 -- Copy_Children --
kono
parents:
diff changeset
656 -------------------
kono
parents:
diff changeset
657
kono
parents:
diff changeset
658 procedure Copy_Children
kono
parents:
diff changeset
659 (Source : Tree;
kono
parents:
diff changeset
660 Source_Parent : Count_Type;
kono
parents:
diff changeset
661 Target : in out Tree;
kono
parents:
diff changeset
662 Target_Parent : Count_Type;
kono
parents:
diff changeset
663 Count : in out Count_Type)
kono
parents:
diff changeset
664 is
kono
parents:
diff changeset
665 S_Nodes : Tree_Node_Array renames Source.Nodes;
kono
parents:
diff changeset
666 S_Node : Tree_Node_Type renames S_Nodes (Source_Parent);
kono
parents:
diff changeset
667
kono
parents:
diff changeset
668 T_Nodes : Tree_Node_Array renames Target.Nodes;
kono
parents:
diff changeset
669 T_Node : Tree_Node_Type renames T_Nodes (Target_Parent);
kono
parents:
diff changeset
670
kono
parents:
diff changeset
671 pragma Assert (T_Node.Children.First <= 0);
kono
parents:
diff changeset
672 pragma Assert (T_Node.Children.Last <= 0);
kono
parents:
diff changeset
673
kono
parents:
diff changeset
674 T_CC : Children_Type;
kono
parents:
diff changeset
675 C : Count_Type'Base;
kono
parents:
diff changeset
676
kono
parents:
diff changeset
677 begin
kono
parents:
diff changeset
678 -- We special-case the first allocation, in order to establish the
kono
parents:
diff changeset
679 -- representation invariants for type Children_Type.
kono
parents:
diff changeset
680
kono
parents:
diff changeset
681 C := S_Node.Children.First;
kono
parents:
diff changeset
682
kono
parents:
diff changeset
683 if C <= 0 then -- source parent has no children
kono
parents:
diff changeset
684 return;
kono
parents:
diff changeset
685 end if;
kono
parents:
diff changeset
686
kono
parents:
diff changeset
687 Copy_Subtree
kono
parents:
diff changeset
688 (Source => Source,
kono
parents:
diff changeset
689 Source_Subtree => C,
kono
parents:
diff changeset
690 Target => Target,
kono
parents:
diff changeset
691 Target_Parent => Target_Parent,
kono
parents:
diff changeset
692 Target_Subtree => T_CC.First,
kono
parents:
diff changeset
693 Count => Count);
kono
parents:
diff changeset
694
kono
parents:
diff changeset
695 T_CC.Last := T_CC.First;
kono
parents:
diff changeset
696
kono
parents:
diff changeset
697 -- The representation invariants for the Children_Type list have been
kono
parents:
diff changeset
698 -- established, so we can now copy the remaining children of Source.
kono
parents:
diff changeset
699
kono
parents:
diff changeset
700 C := S_Nodes (C).Next;
kono
parents:
diff changeset
701 while C > 0 loop
kono
parents:
diff changeset
702 Copy_Subtree
kono
parents:
diff changeset
703 (Source => Source,
kono
parents:
diff changeset
704 Source_Subtree => C,
kono
parents:
diff changeset
705 Target => Target,
kono
parents:
diff changeset
706 Target_Parent => Target_Parent,
kono
parents:
diff changeset
707 Target_Subtree => T_Nodes (T_CC.Last).Next,
kono
parents:
diff changeset
708 Count => Count);
kono
parents:
diff changeset
709
kono
parents:
diff changeset
710 T_Nodes (T_Nodes (T_CC.Last).Next).Prev := T_CC.Last;
kono
parents:
diff changeset
711 T_CC.Last := T_Nodes (T_CC.Last).Next;
kono
parents:
diff changeset
712
kono
parents:
diff changeset
713 C := S_Nodes (C).Next;
kono
parents:
diff changeset
714 end loop;
kono
parents:
diff changeset
715
kono
parents:
diff changeset
716 -- We add the newly-allocated children to their parent list only after
kono
parents:
diff changeset
717 -- the allocation has succeeded, in order to preserve invariants of the
kono
parents:
diff changeset
718 -- parent.
kono
parents:
diff changeset
719
kono
parents:
diff changeset
720 T_Node.Children := T_CC;
kono
parents:
diff changeset
721 end Copy_Children;
kono
parents:
diff changeset
722
kono
parents:
diff changeset
723 ------------------
kono
parents:
diff changeset
724 -- Copy_Subtree --
kono
parents:
diff changeset
725 ------------------
kono
parents:
diff changeset
726
kono
parents:
diff changeset
727 procedure Copy_Subtree
kono
parents:
diff changeset
728 (Target : in out Tree;
kono
parents:
diff changeset
729 Parent : Cursor;
kono
parents:
diff changeset
730 Before : Cursor;
kono
parents:
diff changeset
731 Source : Cursor)
kono
parents:
diff changeset
732 is
kono
parents:
diff changeset
733 Target_Subtree : Count_Type;
kono
parents:
diff changeset
734 Target_Count : Count_Type;
kono
parents:
diff changeset
735
kono
parents:
diff changeset
736 begin
kono
parents:
diff changeset
737 if Checks and then Parent = No_Element then
kono
parents:
diff changeset
738 raise Constraint_Error with "Parent cursor has no element";
kono
parents:
diff changeset
739 end if;
kono
parents:
diff changeset
740
kono
parents:
diff changeset
741 if Checks and then Parent.Container /= Target'Unrestricted_Access then
kono
parents:
diff changeset
742 raise Program_Error with "Parent cursor not in container";
kono
parents:
diff changeset
743 end if;
kono
parents:
diff changeset
744
kono
parents:
diff changeset
745 if Before /= No_Element then
kono
parents:
diff changeset
746 if Checks and then Before.Container /= Target'Unrestricted_Access then
kono
parents:
diff changeset
747 raise Program_Error with "Before cursor not in container";
kono
parents:
diff changeset
748 end if;
kono
parents:
diff changeset
749
kono
parents:
diff changeset
750 if Checks and then
kono
parents:
diff changeset
751 Before.Container.Nodes (Before.Node).Parent /= Parent.Node
kono
parents:
diff changeset
752 then
kono
parents:
diff changeset
753 raise Constraint_Error with "Before cursor not child of Parent";
kono
parents:
diff changeset
754 end if;
kono
parents:
diff changeset
755 end if;
kono
parents:
diff changeset
756
kono
parents:
diff changeset
757 if Source = No_Element then
kono
parents:
diff changeset
758 return;
kono
parents:
diff changeset
759 end if;
kono
parents:
diff changeset
760
kono
parents:
diff changeset
761 if Checks and then Is_Root (Source) then
kono
parents:
diff changeset
762 raise Constraint_Error with "Source cursor designates root";
kono
parents:
diff changeset
763 end if;
kono
parents:
diff changeset
764
kono
parents:
diff changeset
765 if Target.Count = 0 then
kono
parents:
diff changeset
766 Initialize_Root (Target);
kono
parents:
diff changeset
767 end if;
kono
parents:
diff changeset
768
kono
parents:
diff changeset
769 -- Copy_Subtree returns a count of the number of nodes that it
kono
parents:
diff changeset
770 -- allocates, but it works by incrementing the value that is passed
kono
parents:
diff changeset
771 -- in. We must therefore initialize the count value before calling
kono
parents:
diff changeset
772 -- Copy_Subtree.
kono
parents:
diff changeset
773
kono
parents:
diff changeset
774 Target_Count := 0;
kono
parents:
diff changeset
775
kono
parents:
diff changeset
776 Copy_Subtree
kono
parents:
diff changeset
777 (Source => Source.Container.all,
kono
parents:
diff changeset
778 Source_Subtree => Source.Node,
kono
parents:
diff changeset
779 Target => Target,
kono
parents:
diff changeset
780 Target_Parent => Parent.Node,
kono
parents:
diff changeset
781 Target_Subtree => Target_Subtree,
kono
parents:
diff changeset
782 Count => Target_Count);
kono
parents:
diff changeset
783
kono
parents:
diff changeset
784 Insert_Subtree_Node
kono
parents:
diff changeset
785 (Container => Target,
kono
parents:
diff changeset
786 Subtree => Target_Subtree,
kono
parents:
diff changeset
787 Parent => Parent.Node,
kono
parents:
diff changeset
788 Before => Before.Node);
kono
parents:
diff changeset
789
kono
parents:
diff changeset
790 Target.Count := Target.Count + Target_Count;
kono
parents:
diff changeset
791 end Copy_Subtree;
kono
parents:
diff changeset
792
kono
parents:
diff changeset
793 procedure Copy_Subtree
kono
parents:
diff changeset
794 (Source : Tree;
kono
parents:
diff changeset
795 Source_Subtree : Count_Type;
kono
parents:
diff changeset
796 Target : in out Tree;
kono
parents:
diff changeset
797 Target_Parent : Count_Type;
kono
parents:
diff changeset
798 Target_Subtree : out Count_Type;
kono
parents:
diff changeset
799 Count : in out Count_Type)
kono
parents:
diff changeset
800 is
kono
parents:
diff changeset
801 T_Nodes : Tree_Node_Array renames Target.Nodes;
kono
parents:
diff changeset
802
kono
parents:
diff changeset
803 begin
kono
parents:
diff changeset
804 -- First we allocate the root of the target subtree.
kono
parents:
diff changeset
805
kono
parents:
diff changeset
806 Allocate_Node
kono
parents:
diff changeset
807 (Container => Target,
kono
parents:
diff changeset
808 New_Item => Source.Elements (Source_Subtree),
kono
parents:
diff changeset
809 New_Node => Target_Subtree);
kono
parents:
diff changeset
810
kono
parents:
diff changeset
811 T_Nodes (Target_Subtree).Parent := Target_Parent;
kono
parents:
diff changeset
812 Count := Count + 1;
kono
parents:
diff changeset
813
kono
parents:
diff changeset
814 -- We now have a new subtree (for the Target tree), containing only a
kono
parents:
diff changeset
815 -- copy of the corresponding element in the Source subtree. Next we copy
kono
parents:
diff changeset
816 -- the children of the Source subtree as children of the new Target
kono
parents:
diff changeset
817 -- subtree.
kono
parents:
diff changeset
818
kono
parents:
diff changeset
819 Copy_Children
kono
parents:
diff changeset
820 (Source => Source,
kono
parents:
diff changeset
821 Source_Parent => Source_Subtree,
kono
parents:
diff changeset
822 Target => Target,
kono
parents:
diff changeset
823 Target_Parent => Target_Subtree,
kono
parents:
diff changeset
824 Count => Count);
kono
parents:
diff changeset
825 end Copy_Subtree;
kono
parents:
diff changeset
826
kono
parents:
diff changeset
827 -------------------------
kono
parents:
diff changeset
828 -- Deallocate_Children --
kono
parents:
diff changeset
829 -------------------------
kono
parents:
diff changeset
830
kono
parents:
diff changeset
831 procedure Deallocate_Children
kono
parents:
diff changeset
832 (Container : in out Tree;
kono
parents:
diff changeset
833 Subtree : Count_Type;
kono
parents:
diff changeset
834 Count : in out Count_Type)
kono
parents:
diff changeset
835 is
kono
parents:
diff changeset
836 Nodes : Tree_Node_Array renames Container.Nodes;
kono
parents:
diff changeset
837 Node : Tree_Node_Type renames Nodes (Subtree); -- parent
kono
parents:
diff changeset
838 CC : Children_Type renames Node.Children;
kono
parents:
diff changeset
839 C : Count_Type'Base;
kono
parents:
diff changeset
840
kono
parents:
diff changeset
841 begin
kono
parents:
diff changeset
842 while CC.First > 0 loop
kono
parents:
diff changeset
843 C := CC.First;
kono
parents:
diff changeset
844 CC.First := Nodes (C).Next;
kono
parents:
diff changeset
845
kono
parents:
diff changeset
846 Deallocate_Subtree (Container, C, Count);
kono
parents:
diff changeset
847 end loop;
kono
parents:
diff changeset
848
kono
parents:
diff changeset
849 CC.Last := 0;
kono
parents:
diff changeset
850 end Deallocate_Children;
kono
parents:
diff changeset
851
kono
parents:
diff changeset
852 ---------------------
kono
parents:
diff changeset
853 -- Deallocate_Node --
kono
parents:
diff changeset
854 ---------------------
kono
parents:
diff changeset
855
kono
parents:
diff changeset
856 procedure Deallocate_Node
kono
parents:
diff changeset
857 (Container : in out Tree;
kono
parents:
diff changeset
858 X : Count_Type)
kono
parents:
diff changeset
859 is
kono
parents:
diff changeset
860 NN : Tree_Node_Array renames Container.Nodes;
kono
parents:
diff changeset
861 pragma Assert (X > 0);
kono
parents:
diff changeset
862 pragma Assert (X <= NN'Last);
kono
parents:
diff changeset
863
kono
parents:
diff changeset
864 N : Tree_Node_Type renames NN (X);
kono
parents:
diff changeset
865 pragma Assert (N.Parent /= X); -- node is active
kono
parents:
diff changeset
866
kono
parents:
diff changeset
867 begin
kono
parents:
diff changeset
868 -- The tree container actually contains two lists: one for the "active"
kono
parents:
diff changeset
869 -- nodes that contain elements that have been inserted onto the tree,
kono
parents:
diff changeset
870 -- and another for the "inactive" nodes of the free store, from which
kono
parents:
diff changeset
871 -- nodes are allocated when a new child is inserted in the tree.
kono
parents:
diff changeset
872
kono
parents:
diff changeset
873 -- We desire that merely declaring a tree object should have only
kono
parents:
diff changeset
874 -- minimal cost; specially, we want to avoid having to initialize the
kono
parents:
diff changeset
875 -- free store (to fill in the links), especially if the capacity of the
kono
parents:
diff changeset
876 -- tree object is large.
kono
parents:
diff changeset
877
kono
parents:
diff changeset
878 -- The head of the free list is indicated by Container.Free. If its
kono
parents:
diff changeset
879 -- value is non-negative, then the free store has been initialized in
kono
parents:
diff changeset
880 -- the "normal" way: Container.Free points to the head of the list of
kono
parents:
diff changeset
881 -- free (inactive) nodes, and the value 0 means the free list is
kono
parents:
diff changeset
882 -- empty. Each node on the free list has been initialized to point to
kono
parents:
diff changeset
883 -- the next free node (via its Next component), and the value 0 means
kono
parents:
diff changeset
884 -- that this is the last node of the free list.
kono
parents:
diff changeset
885
kono
parents:
diff changeset
886 -- If Container.Free is negative, then the links on the free store have
kono
parents:
diff changeset
887 -- not been initialized. In this case the link values are implied: the
kono
parents:
diff changeset
888 -- free store comprises the components of the node array started with
kono
parents:
diff changeset
889 -- the absolute value of Container.Free, and continuing until the end of
kono
parents:
diff changeset
890 -- the array (Nodes'Last).
kono
parents:
diff changeset
891
kono
parents:
diff changeset
892 -- We prefer to lazy-init the free store (in fact, we would prefer to
kono
parents:
diff changeset
893 -- not initialize it at all, because such initialization is an O(n)
kono
parents:
diff changeset
894 -- operation). The time when we need to actually initialize the nodes in
kono
parents:
diff changeset
895 -- the free store is when the node that becomes inactive is not at the
kono
parents:
diff changeset
896 -- end of the active list. The free store would then be discontigous and
kono
parents:
diff changeset
897 -- so its nodes would need to be linked in the traditional way.
kono
parents:
diff changeset
898
kono
parents:
diff changeset
899 -- It might be possible to perform an optimization here. Suppose that
kono
parents:
diff changeset
900 -- the free store can be represented as having two parts: one comprising
kono
parents:
diff changeset
901 -- the non-contiguous inactive nodes linked together in the normal way,
kono
parents:
diff changeset
902 -- and the other comprising the contiguous inactive nodes (that are not
kono
parents:
diff changeset
903 -- linked together, at the end of the nodes array). This would allow us
kono
parents:
diff changeset
904 -- to never have to initialize the free store, except in a lazy way as
kono
parents:
diff changeset
905 -- nodes become inactive. ???
kono
parents:
diff changeset
906
kono
parents:
diff changeset
907 -- When an element is deleted from the list container, its node becomes
kono
parents:
diff changeset
908 -- inactive, and so we set its Parent and Prev components to an
kono
parents:
diff changeset
909 -- impossible value (the index of the node itself), to indicate that it
kono
parents:
diff changeset
910 -- is now inactive. This provides a useful way to detect a dangling
kono
parents:
diff changeset
911 -- cursor reference.
kono
parents:
diff changeset
912
kono
parents:
diff changeset
913 N.Parent := X; -- Node is deallocated (not on active list)
kono
parents:
diff changeset
914 N.Prev := X;
kono
parents:
diff changeset
915
kono
parents:
diff changeset
916 if Container.Free >= 0 then
kono
parents:
diff changeset
917 -- The free store has previously been initialized. All we need to do
kono
parents:
diff changeset
918 -- here is link the newly-free'd node onto the free list.
kono
parents:
diff changeset
919
kono
parents:
diff changeset
920 N.Next := Container.Free;
kono
parents:
diff changeset
921 Container.Free := X;
kono
parents:
diff changeset
922
kono
parents:
diff changeset
923 elsif X + 1 = abs Container.Free then
kono
parents:
diff changeset
924 -- The free store has not been initialized, and the node becoming
kono
parents:
diff changeset
925 -- inactive immediately precedes the start of the free store. All
kono
parents:
diff changeset
926 -- we need to do is move the start of the free store back by one.
kono
parents:
diff changeset
927
kono
parents:
diff changeset
928 N.Next := X; -- Not strictly necessary, but marginally safer
kono
parents:
diff changeset
929 Container.Free := Container.Free + 1;
kono
parents:
diff changeset
930
kono
parents:
diff changeset
931 else
kono
parents:
diff changeset
932 -- The free store has not been initialized, and the node becoming
kono
parents:
diff changeset
933 -- inactive does not immediately precede the free store. Here we
kono
parents:
diff changeset
934 -- first initialize the free store (meaning the links are given
kono
parents:
diff changeset
935 -- values in the traditional way), and then link the newly-free'd
kono
parents:
diff changeset
936 -- node onto the head of the free store.
kono
parents:
diff changeset
937
kono
parents:
diff changeset
938 -- See the comments above for an optimization opportunity. If the
kono
parents:
diff changeset
939 -- next link for a node on the free store is negative, then this
kono
parents:
diff changeset
940 -- means the remaining nodes on the free store are physically
kono
parents:
diff changeset
941 -- contiguous, starting at the absolute value of that index value.
kono
parents:
diff changeset
942 -- ???
kono
parents:
diff changeset
943
kono
parents:
diff changeset
944 Container.Free := abs Container.Free;
kono
parents:
diff changeset
945
kono
parents:
diff changeset
946 if Container.Free > Container.Capacity then
kono
parents:
diff changeset
947 Container.Free := 0;
kono
parents:
diff changeset
948
kono
parents:
diff changeset
949 else
kono
parents:
diff changeset
950 for J in Container.Free .. Container.Capacity - 1 loop
kono
parents:
diff changeset
951 NN (J).Next := J + 1;
kono
parents:
diff changeset
952 end loop;
kono
parents:
diff changeset
953
kono
parents:
diff changeset
954 NN (Container.Capacity).Next := 0;
kono
parents:
diff changeset
955 end if;
kono
parents:
diff changeset
956
kono
parents:
diff changeset
957 NN (X).Next := Container.Free;
kono
parents:
diff changeset
958 Container.Free := X;
kono
parents:
diff changeset
959 end if;
kono
parents:
diff changeset
960 end Deallocate_Node;
kono
parents:
diff changeset
961
kono
parents:
diff changeset
962 ------------------------
kono
parents:
diff changeset
963 -- Deallocate_Subtree --
kono
parents:
diff changeset
964 ------------------------
kono
parents:
diff changeset
965
kono
parents:
diff changeset
966 procedure Deallocate_Subtree
kono
parents:
diff changeset
967 (Container : in out Tree;
kono
parents:
diff changeset
968 Subtree : Count_Type;
kono
parents:
diff changeset
969 Count : in out Count_Type)
kono
parents:
diff changeset
970 is
kono
parents:
diff changeset
971 begin
kono
parents:
diff changeset
972 Deallocate_Children (Container, Subtree, Count);
kono
parents:
diff changeset
973 Deallocate_Node (Container, Subtree);
kono
parents:
diff changeset
974 Count := Count + 1;
kono
parents:
diff changeset
975 end Deallocate_Subtree;
kono
parents:
diff changeset
976
kono
parents:
diff changeset
977 ---------------------
kono
parents:
diff changeset
978 -- Delete_Children --
kono
parents:
diff changeset
979 ---------------------
kono
parents:
diff changeset
980
kono
parents:
diff changeset
981 procedure Delete_Children
kono
parents:
diff changeset
982 (Container : in out Tree;
kono
parents:
diff changeset
983 Parent : Cursor)
kono
parents:
diff changeset
984 is
kono
parents:
diff changeset
985 Count : Count_Type;
kono
parents:
diff changeset
986
kono
parents:
diff changeset
987 begin
kono
parents:
diff changeset
988 if Checks and then Parent = No_Element then
kono
parents:
diff changeset
989 raise Constraint_Error with "Parent cursor has no element";
kono
parents:
diff changeset
990 end if;
kono
parents:
diff changeset
991
kono
parents:
diff changeset
992 if Checks and then Parent.Container /= Container'Unrestricted_Access then
kono
parents:
diff changeset
993 raise Program_Error with "Parent cursor not in container";
kono
parents:
diff changeset
994 end if;
kono
parents:
diff changeset
995
kono
parents:
diff changeset
996 TC_Check (Container.TC);
kono
parents:
diff changeset
997
kono
parents:
diff changeset
998 if Container.Count = 0 then
kono
parents:
diff changeset
999 pragma Assert (Is_Root (Parent));
kono
parents:
diff changeset
1000 return;
kono
parents:
diff changeset
1001 end if;
kono
parents:
diff changeset
1002
kono
parents:
diff changeset
1003 -- Deallocate_Children returns a count of the number of nodes that it
kono
parents:
diff changeset
1004 -- deallocates, but it works by incrementing the value that is passed
kono
parents:
diff changeset
1005 -- in. We must therefore initialize the count value before calling
kono
parents:
diff changeset
1006 -- Deallocate_Children.
kono
parents:
diff changeset
1007
kono
parents:
diff changeset
1008 Count := 0;
kono
parents:
diff changeset
1009
kono
parents:
diff changeset
1010 Deallocate_Children (Container, Parent.Node, Count);
kono
parents:
diff changeset
1011 pragma Assert (Count <= Container.Count);
kono
parents:
diff changeset
1012
kono
parents:
diff changeset
1013 Container.Count := Container.Count - Count;
kono
parents:
diff changeset
1014 end Delete_Children;
kono
parents:
diff changeset
1015
kono
parents:
diff changeset
1016 -----------------
kono
parents:
diff changeset
1017 -- Delete_Leaf --
kono
parents:
diff changeset
1018 -----------------
kono
parents:
diff changeset
1019
kono
parents:
diff changeset
1020 procedure Delete_Leaf
kono
parents:
diff changeset
1021 (Container : in out Tree;
kono
parents:
diff changeset
1022 Position : in out Cursor)
kono
parents:
diff changeset
1023 is
kono
parents:
diff changeset
1024 X : Count_Type;
kono
parents:
diff changeset
1025
kono
parents:
diff changeset
1026 begin
kono
parents:
diff changeset
1027 if Checks and then Position = No_Element then
kono
parents:
diff changeset
1028 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
1029 end if;
kono
parents:
diff changeset
1030
kono
parents:
diff changeset
1031 if Checks and then Position.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
1032 then
kono
parents:
diff changeset
1033 raise Program_Error with "Position cursor not in container";
kono
parents:
diff changeset
1034 end if;
kono
parents:
diff changeset
1035
kono
parents:
diff changeset
1036 if Checks and then Is_Root (Position) then
kono
parents:
diff changeset
1037 raise Program_Error with "Position cursor designates root";
kono
parents:
diff changeset
1038 end if;
kono
parents:
diff changeset
1039
kono
parents:
diff changeset
1040 if Checks and then not Is_Leaf (Position) then
kono
parents:
diff changeset
1041 raise Constraint_Error with "Position cursor does not designate leaf";
kono
parents:
diff changeset
1042 end if;
kono
parents:
diff changeset
1043
kono
parents:
diff changeset
1044 TC_Check (Container.TC);
kono
parents:
diff changeset
1045
kono
parents:
diff changeset
1046 X := Position.Node;
kono
parents:
diff changeset
1047 Position := No_Element;
kono
parents:
diff changeset
1048
kono
parents:
diff changeset
1049 Remove_Subtree (Container, X);
kono
parents:
diff changeset
1050 Container.Count := Container.Count - 1;
kono
parents:
diff changeset
1051
kono
parents:
diff changeset
1052 Deallocate_Node (Container, X);
kono
parents:
diff changeset
1053 end Delete_Leaf;
kono
parents:
diff changeset
1054
kono
parents:
diff changeset
1055 --------------------
kono
parents:
diff changeset
1056 -- Delete_Subtree --
kono
parents:
diff changeset
1057 --------------------
kono
parents:
diff changeset
1058
kono
parents:
diff changeset
1059 procedure Delete_Subtree
kono
parents:
diff changeset
1060 (Container : in out Tree;
kono
parents:
diff changeset
1061 Position : in out Cursor)
kono
parents:
diff changeset
1062 is
kono
parents:
diff changeset
1063 X : Count_Type;
kono
parents:
diff changeset
1064 Count : Count_Type;
kono
parents:
diff changeset
1065
kono
parents:
diff changeset
1066 begin
kono
parents:
diff changeset
1067 if Checks and then Position = No_Element then
kono
parents:
diff changeset
1068 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
1069 end if;
kono
parents:
diff changeset
1070
kono
parents:
diff changeset
1071 if Checks and then Position.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
1072 then
kono
parents:
diff changeset
1073 raise Program_Error with "Position cursor not in container";
kono
parents:
diff changeset
1074 end if;
kono
parents:
diff changeset
1075
kono
parents:
diff changeset
1076 if Checks and then Is_Root (Position) then
kono
parents:
diff changeset
1077 raise Program_Error with "Position cursor designates root";
kono
parents:
diff changeset
1078 end if;
kono
parents:
diff changeset
1079
kono
parents:
diff changeset
1080 TC_Check (Container.TC);
kono
parents:
diff changeset
1081
kono
parents:
diff changeset
1082 X := Position.Node;
kono
parents:
diff changeset
1083 Position := No_Element;
kono
parents:
diff changeset
1084
kono
parents:
diff changeset
1085 Remove_Subtree (Container, X);
kono
parents:
diff changeset
1086
kono
parents:
diff changeset
1087 -- Deallocate_Subtree returns a count of the number of nodes that it
kono
parents:
diff changeset
1088 -- deallocates, but it works by incrementing the value that is passed
kono
parents:
diff changeset
1089 -- in. We must therefore initialize the count value before calling
kono
parents:
diff changeset
1090 -- Deallocate_Subtree.
kono
parents:
diff changeset
1091
kono
parents:
diff changeset
1092 Count := 0;
kono
parents:
diff changeset
1093
kono
parents:
diff changeset
1094 Deallocate_Subtree (Container, X, Count);
kono
parents:
diff changeset
1095 pragma Assert (Count <= Container.Count);
kono
parents:
diff changeset
1096
kono
parents:
diff changeset
1097 Container.Count := Container.Count - Count;
kono
parents:
diff changeset
1098 end Delete_Subtree;
kono
parents:
diff changeset
1099
kono
parents:
diff changeset
1100 -----------
kono
parents:
diff changeset
1101 -- Depth --
kono
parents:
diff changeset
1102 -----------
kono
parents:
diff changeset
1103
kono
parents:
diff changeset
1104 function Depth (Position : Cursor) return Count_Type is
kono
parents:
diff changeset
1105 Result : Count_Type;
kono
parents:
diff changeset
1106 N : Count_Type'Base;
kono
parents:
diff changeset
1107
kono
parents:
diff changeset
1108 begin
kono
parents:
diff changeset
1109 if Position = No_Element then
kono
parents:
diff changeset
1110 return 0;
kono
parents:
diff changeset
1111 end if;
kono
parents:
diff changeset
1112
kono
parents:
diff changeset
1113 if Is_Root (Position) then
kono
parents:
diff changeset
1114 return 1;
kono
parents:
diff changeset
1115 end if;
kono
parents:
diff changeset
1116
kono
parents:
diff changeset
1117 Result := 0;
kono
parents:
diff changeset
1118 N := Position.Node;
kono
parents:
diff changeset
1119 while N >= 0 loop
kono
parents:
diff changeset
1120 N := Position.Container.Nodes (N).Parent;
kono
parents:
diff changeset
1121 Result := Result + 1;
kono
parents:
diff changeset
1122 end loop;
kono
parents:
diff changeset
1123
kono
parents:
diff changeset
1124 return Result;
kono
parents:
diff changeset
1125 end Depth;
kono
parents:
diff changeset
1126
kono
parents:
diff changeset
1127 -------------
kono
parents:
diff changeset
1128 -- Element --
kono
parents:
diff changeset
1129 -------------
kono
parents:
diff changeset
1130
kono
parents:
diff changeset
1131 function Element (Position : Cursor) return Element_Type is
kono
parents:
diff changeset
1132 begin
kono
parents:
diff changeset
1133 if Checks and then Position.Container = null then
kono
parents:
diff changeset
1134 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
1135 end if;
kono
parents:
diff changeset
1136
kono
parents:
diff changeset
1137 if Checks and then Position.Node = Root_Node (Position.Container.all)
kono
parents:
diff changeset
1138 then
kono
parents:
diff changeset
1139 raise Program_Error with "Position cursor designates root";
kono
parents:
diff changeset
1140 end if;
kono
parents:
diff changeset
1141
kono
parents:
diff changeset
1142 return Position.Container.Elements (Position.Node);
kono
parents:
diff changeset
1143 end Element;
kono
parents:
diff changeset
1144
kono
parents:
diff changeset
1145 --------------------
kono
parents:
diff changeset
1146 -- Equal_Children --
kono
parents:
diff changeset
1147 --------------------
kono
parents:
diff changeset
1148
kono
parents:
diff changeset
1149 function Equal_Children
kono
parents:
diff changeset
1150 (Left_Tree : Tree;
kono
parents:
diff changeset
1151 Left_Subtree : Count_Type;
kono
parents:
diff changeset
1152 Right_Tree : Tree;
kono
parents:
diff changeset
1153 Right_Subtree : Count_Type) return Boolean
kono
parents:
diff changeset
1154 is
kono
parents:
diff changeset
1155 L_NN : Tree_Node_Array renames Left_Tree.Nodes;
kono
parents:
diff changeset
1156 R_NN : Tree_Node_Array renames Right_Tree.Nodes;
kono
parents:
diff changeset
1157
kono
parents:
diff changeset
1158 Left_Children : Children_Type renames L_NN (Left_Subtree).Children;
kono
parents:
diff changeset
1159 Right_Children : Children_Type renames R_NN (Right_Subtree).Children;
kono
parents:
diff changeset
1160
kono
parents:
diff changeset
1161 L, R : Count_Type'Base;
kono
parents:
diff changeset
1162
kono
parents:
diff changeset
1163 begin
kono
parents:
diff changeset
1164 if Child_Count (Left_Tree, Left_Subtree)
kono
parents:
diff changeset
1165 /= Child_Count (Right_Tree, Right_Subtree)
kono
parents:
diff changeset
1166 then
kono
parents:
diff changeset
1167 return False;
kono
parents:
diff changeset
1168 end if;
kono
parents:
diff changeset
1169
kono
parents:
diff changeset
1170 L := Left_Children.First;
kono
parents:
diff changeset
1171 R := Right_Children.First;
kono
parents:
diff changeset
1172 while L > 0 loop
kono
parents:
diff changeset
1173 if not Equal_Subtree (Left_Tree, L, Right_Tree, R) then
kono
parents:
diff changeset
1174 return False;
kono
parents:
diff changeset
1175 end if;
kono
parents:
diff changeset
1176
kono
parents:
diff changeset
1177 L := L_NN (L).Next;
kono
parents:
diff changeset
1178 R := R_NN (R).Next;
kono
parents:
diff changeset
1179 end loop;
kono
parents:
diff changeset
1180
kono
parents:
diff changeset
1181 return True;
kono
parents:
diff changeset
1182 end Equal_Children;
kono
parents:
diff changeset
1183
kono
parents:
diff changeset
1184 -------------------
kono
parents:
diff changeset
1185 -- Equal_Subtree --
kono
parents:
diff changeset
1186 -------------------
kono
parents:
diff changeset
1187
kono
parents:
diff changeset
1188 function Equal_Subtree
kono
parents:
diff changeset
1189 (Left_Position : Cursor;
kono
parents:
diff changeset
1190 Right_Position : Cursor) return Boolean
kono
parents:
diff changeset
1191 is
kono
parents:
diff changeset
1192 begin
kono
parents:
diff changeset
1193 if Checks and then Left_Position = No_Element then
kono
parents:
diff changeset
1194 raise Constraint_Error with "Left cursor has no element";
kono
parents:
diff changeset
1195 end if;
kono
parents:
diff changeset
1196
kono
parents:
diff changeset
1197 if Checks and then Right_Position = No_Element then
kono
parents:
diff changeset
1198 raise Constraint_Error with "Right cursor has no element";
kono
parents:
diff changeset
1199 end if;
kono
parents:
diff changeset
1200
kono
parents:
diff changeset
1201 if Left_Position = Right_Position then
kono
parents:
diff changeset
1202 return True;
kono
parents:
diff changeset
1203 end if;
kono
parents:
diff changeset
1204
kono
parents:
diff changeset
1205 if Is_Root (Left_Position) then
kono
parents:
diff changeset
1206 if not Is_Root (Right_Position) then
kono
parents:
diff changeset
1207 return False;
kono
parents:
diff changeset
1208 end if;
kono
parents:
diff changeset
1209
kono
parents:
diff changeset
1210 if Left_Position.Container.Count = 0 then
kono
parents:
diff changeset
1211 return Right_Position.Container.Count = 0;
kono
parents:
diff changeset
1212 end if;
kono
parents:
diff changeset
1213
kono
parents:
diff changeset
1214 if Right_Position.Container.Count = 0 then
kono
parents:
diff changeset
1215 return False;
kono
parents:
diff changeset
1216 end if;
kono
parents:
diff changeset
1217
kono
parents:
diff changeset
1218 return Equal_Children
kono
parents:
diff changeset
1219 (Left_Tree => Left_Position.Container.all,
kono
parents:
diff changeset
1220 Left_Subtree => Left_Position.Node,
kono
parents:
diff changeset
1221 Right_Tree => Right_Position.Container.all,
kono
parents:
diff changeset
1222 Right_Subtree => Right_Position.Node);
kono
parents:
diff changeset
1223 end if;
kono
parents:
diff changeset
1224
kono
parents:
diff changeset
1225 if Is_Root (Right_Position) then
kono
parents:
diff changeset
1226 return False;
kono
parents:
diff changeset
1227 end if;
kono
parents:
diff changeset
1228
kono
parents:
diff changeset
1229 return Equal_Subtree
kono
parents:
diff changeset
1230 (Left_Tree => Left_Position.Container.all,
kono
parents:
diff changeset
1231 Left_Subtree => Left_Position.Node,
kono
parents:
diff changeset
1232 Right_Tree => Right_Position.Container.all,
kono
parents:
diff changeset
1233 Right_Subtree => Right_Position.Node);
kono
parents:
diff changeset
1234 end Equal_Subtree;
kono
parents:
diff changeset
1235
kono
parents:
diff changeset
1236 function Equal_Subtree
kono
parents:
diff changeset
1237 (Left_Tree : Tree;
kono
parents:
diff changeset
1238 Left_Subtree : Count_Type;
kono
parents:
diff changeset
1239 Right_Tree : Tree;
kono
parents:
diff changeset
1240 Right_Subtree : Count_Type) return Boolean
kono
parents:
diff changeset
1241 is
kono
parents:
diff changeset
1242 begin
kono
parents:
diff changeset
1243 if Left_Tree.Elements (Left_Subtree) /=
kono
parents:
diff changeset
1244 Right_Tree.Elements (Right_Subtree)
kono
parents:
diff changeset
1245 then
kono
parents:
diff changeset
1246 return False;
kono
parents:
diff changeset
1247 end if;
kono
parents:
diff changeset
1248
kono
parents:
diff changeset
1249 return Equal_Children
kono
parents:
diff changeset
1250 (Left_Tree => Left_Tree,
kono
parents:
diff changeset
1251 Left_Subtree => Left_Subtree,
kono
parents:
diff changeset
1252 Right_Tree => Right_Tree,
kono
parents:
diff changeset
1253 Right_Subtree => Right_Subtree);
kono
parents:
diff changeset
1254 end Equal_Subtree;
kono
parents:
diff changeset
1255
kono
parents:
diff changeset
1256 --------------
kono
parents:
diff changeset
1257 -- Finalize --
kono
parents:
diff changeset
1258 --------------
kono
parents:
diff changeset
1259
kono
parents:
diff changeset
1260 procedure Finalize (Object : in out Root_Iterator) is
kono
parents:
diff changeset
1261 begin
kono
parents:
diff changeset
1262 Unbusy (Object.Container.TC);
kono
parents:
diff changeset
1263 end Finalize;
kono
parents:
diff changeset
1264
kono
parents:
diff changeset
1265 ----------
kono
parents:
diff changeset
1266 -- Find --
kono
parents:
diff changeset
1267 ----------
kono
parents:
diff changeset
1268
kono
parents:
diff changeset
1269 function Find
kono
parents:
diff changeset
1270 (Container : Tree;
kono
parents:
diff changeset
1271 Item : Element_Type) return Cursor
kono
parents:
diff changeset
1272 is
kono
parents:
diff changeset
1273 Node : Count_Type;
kono
parents:
diff changeset
1274
kono
parents:
diff changeset
1275 begin
kono
parents:
diff changeset
1276 if Container.Count = 0 then
kono
parents:
diff changeset
1277 return No_Element;
kono
parents:
diff changeset
1278 end if;
kono
parents:
diff changeset
1279
kono
parents:
diff changeset
1280 Node := Find_In_Children (Container, Root_Node (Container), Item);
kono
parents:
diff changeset
1281
kono
parents:
diff changeset
1282 if Node = 0 then
kono
parents:
diff changeset
1283 return No_Element;
kono
parents:
diff changeset
1284 end if;
kono
parents:
diff changeset
1285
kono
parents:
diff changeset
1286 return Cursor'(Container'Unrestricted_Access, Node);
kono
parents:
diff changeset
1287 end Find;
kono
parents:
diff changeset
1288
kono
parents:
diff changeset
1289 -----------
kono
parents:
diff changeset
1290 -- First --
kono
parents:
diff changeset
1291 -----------
kono
parents:
diff changeset
1292
kono
parents:
diff changeset
1293 overriding function First (Object : Subtree_Iterator) return Cursor is
kono
parents:
diff changeset
1294 begin
kono
parents:
diff changeset
1295 if Object.Subtree = Root_Node (Object.Container.all) then
kono
parents:
diff changeset
1296 return First_Child (Root (Object.Container.all));
kono
parents:
diff changeset
1297 else
kono
parents:
diff changeset
1298 return Cursor'(Object.Container, Object.Subtree);
kono
parents:
diff changeset
1299 end if;
kono
parents:
diff changeset
1300 end First;
kono
parents:
diff changeset
1301
kono
parents:
diff changeset
1302 overriding function First (Object : Child_Iterator) return Cursor is
kono
parents:
diff changeset
1303 begin
kono
parents:
diff changeset
1304 return First_Child (Cursor'(Object.Container, Object.Subtree));
kono
parents:
diff changeset
1305 end First;
kono
parents:
diff changeset
1306
kono
parents:
diff changeset
1307 -----------------
kono
parents:
diff changeset
1308 -- First_Child --
kono
parents:
diff changeset
1309 -----------------
kono
parents:
diff changeset
1310
kono
parents:
diff changeset
1311 function First_Child (Parent : Cursor) return Cursor is
kono
parents:
diff changeset
1312 Node : Count_Type'Base;
kono
parents:
diff changeset
1313
kono
parents:
diff changeset
1314 begin
kono
parents:
diff changeset
1315 if Checks and then Parent = No_Element then
kono
parents:
diff changeset
1316 raise Constraint_Error with "Parent cursor has no element";
kono
parents:
diff changeset
1317 end if;
kono
parents:
diff changeset
1318
kono
parents:
diff changeset
1319 if Parent.Container.Count = 0 then
kono
parents:
diff changeset
1320 pragma Assert (Is_Root (Parent));
kono
parents:
diff changeset
1321 return No_Element;
kono
parents:
diff changeset
1322 end if;
kono
parents:
diff changeset
1323
kono
parents:
diff changeset
1324 Node := Parent.Container.Nodes (Parent.Node).Children.First;
kono
parents:
diff changeset
1325
kono
parents:
diff changeset
1326 if Node <= 0 then
kono
parents:
diff changeset
1327 return No_Element;
kono
parents:
diff changeset
1328 end if;
kono
parents:
diff changeset
1329
kono
parents:
diff changeset
1330 return Cursor'(Parent.Container, Node);
kono
parents:
diff changeset
1331 end First_Child;
kono
parents:
diff changeset
1332
kono
parents:
diff changeset
1333 -------------------------
kono
parents:
diff changeset
1334 -- First_Child_Element --
kono
parents:
diff changeset
1335 -------------------------
kono
parents:
diff changeset
1336
kono
parents:
diff changeset
1337 function First_Child_Element (Parent : Cursor) return Element_Type is
kono
parents:
diff changeset
1338 begin
kono
parents:
diff changeset
1339 return Element (First_Child (Parent));
kono
parents:
diff changeset
1340 end First_Child_Element;
kono
parents:
diff changeset
1341
kono
parents:
diff changeset
1342 ----------------------
kono
parents:
diff changeset
1343 -- Find_In_Children --
kono
parents:
diff changeset
1344 ----------------------
kono
parents:
diff changeset
1345
kono
parents:
diff changeset
1346 function Find_In_Children
kono
parents:
diff changeset
1347 (Container : Tree;
kono
parents:
diff changeset
1348 Subtree : Count_Type;
kono
parents:
diff changeset
1349 Item : Element_Type) return Count_Type
kono
parents:
diff changeset
1350 is
kono
parents:
diff changeset
1351 N : Count_Type'Base;
kono
parents:
diff changeset
1352 Result : Count_Type;
kono
parents:
diff changeset
1353
kono
parents:
diff changeset
1354 begin
kono
parents:
diff changeset
1355 N := Container.Nodes (Subtree).Children.First;
kono
parents:
diff changeset
1356 while N > 0 loop
kono
parents:
diff changeset
1357 Result := Find_In_Subtree (Container, N, Item);
kono
parents:
diff changeset
1358
kono
parents:
diff changeset
1359 if Result > 0 then
kono
parents:
diff changeset
1360 return Result;
kono
parents:
diff changeset
1361 end if;
kono
parents:
diff changeset
1362
kono
parents:
diff changeset
1363 N := Container.Nodes (N).Next;
kono
parents:
diff changeset
1364 end loop;
kono
parents:
diff changeset
1365
kono
parents:
diff changeset
1366 return 0;
kono
parents:
diff changeset
1367 end Find_In_Children;
kono
parents:
diff changeset
1368
kono
parents:
diff changeset
1369 ---------------------
kono
parents:
diff changeset
1370 -- Find_In_Subtree --
kono
parents:
diff changeset
1371 ---------------------
kono
parents:
diff changeset
1372
kono
parents:
diff changeset
1373 function Find_In_Subtree
kono
parents:
diff changeset
1374 (Position : Cursor;
kono
parents:
diff changeset
1375 Item : Element_Type) return Cursor
kono
parents:
diff changeset
1376 is
kono
parents:
diff changeset
1377 Result : Count_Type;
kono
parents:
diff changeset
1378
kono
parents:
diff changeset
1379 begin
kono
parents:
diff changeset
1380 if Checks and then Position = No_Element then
kono
parents:
diff changeset
1381 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
1382 end if;
kono
parents:
diff changeset
1383
kono
parents:
diff changeset
1384 -- Commented-out pending ruling by ARG. ???
kono
parents:
diff changeset
1385
kono
parents:
diff changeset
1386 -- if Checks and then
kono
parents:
diff changeset
1387 -- Position.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
1388 -- then
kono
parents:
diff changeset
1389 -- raise Program_Error with "Position cursor not in container";
kono
parents:
diff changeset
1390 -- end if;
kono
parents:
diff changeset
1391
kono
parents:
diff changeset
1392 if Position.Container.Count = 0 then
kono
parents:
diff changeset
1393 pragma Assert (Is_Root (Position));
kono
parents:
diff changeset
1394 return No_Element;
kono
parents:
diff changeset
1395 end if;
kono
parents:
diff changeset
1396
kono
parents:
diff changeset
1397 if Is_Root (Position) then
kono
parents:
diff changeset
1398 Result := Find_In_Children
kono
parents:
diff changeset
1399 (Container => Position.Container.all,
kono
parents:
diff changeset
1400 Subtree => Position.Node,
kono
parents:
diff changeset
1401 Item => Item);
kono
parents:
diff changeset
1402
kono
parents:
diff changeset
1403 else
kono
parents:
diff changeset
1404 Result := Find_In_Subtree
kono
parents:
diff changeset
1405 (Container => Position.Container.all,
kono
parents:
diff changeset
1406 Subtree => Position.Node,
kono
parents:
diff changeset
1407 Item => Item);
kono
parents:
diff changeset
1408 end if;
kono
parents:
diff changeset
1409
kono
parents:
diff changeset
1410 if Result = 0 then
kono
parents:
diff changeset
1411 return No_Element;
kono
parents:
diff changeset
1412 end if;
kono
parents:
diff changeset
1413
kono
parents:
diff changeset
1414 return Cursor'(Position.Container, Result);
kono
parents:
diff changeset
1415 end Find_In_Subtree;
kono
parents:
diff changeset
1416
kono
parents:
diff changeset
1417 function Find_In_Subtree
kono
parents:
diff changeset
1418 (Container : Tree;
kono
parents:
diff changeset
1419 Subtree : Count_Type;
kono
parents:
diff changeset
1420 Item : Element_Type) return Count_Type
kono
parents:
diff changeset
1421 is
kono
parents:
diff changeset
1422 begin
kono
parents:
diff changeset
1423 if Container.Elements (Subtree) = Item then
kono
parents:
diff changeset
1424 return Subtree;
kono
parents:
diff changeset
1425 end if;
kono
parents:
diff changeset
1426
kono
parents:
diff changeset
1427 return Find_In_Children (Container, Subtree, Item);
kono
parents:
diff changeset
1428 end Find_In_Subtree;
kono
parents:
diff changeset
1429
kono
parents:
diff changeset
1430 ------------------------
kono
parents:
diff changeset
1431 -- Get_Element_Access --
kono
parents:
diff changeset
1432 ------------------------
kono
parents:
diff changeset
1433
kono
parents:
diff changeset
1434 function Get_Element_Access
kono
parents:
diff changeset
1435 (Position : Cursor) return not null Element_Access is
kono
parents:
diff changeset
1436 begin
kono
parents:
diff changeset
1437 return Position.Container.Elements (Position.Node)'Access;
kono
parents:
diff changeset
1438 end Get_Element_Access;
kono
parents:
diff changeset
1439
kono
parents:
diff changeset
1440 -----------------
kono
parents:
diff changeset
1441 -- Has_Element --
kono
parents:
diff changeset
1442 -----------------
kono
parents:
diff changeset
1443
kono
parents:
diff changeset
1444 function Has_Element (Position : Cursor) return Boolean is
kono
parents:
diff changeset
1445 begin
kono
parents:
diff changeset
1446 if Position = No_Element then
kono
parents:
diff changeset
1447 return False;
kono
parents:
diff changeset
1448 end if;
kono
parents:
diff changeset
1449
kono
parents:
diff changeset
1450 return Position.Node /= Root_Node (Position.Container.all);
kono
parents:
diff changeset
1451 end Has_Element;
kono
parents:
diff changeset
1452
kono
parents:
diff changeset
1453 ---------------------
kono
parents:
diff changeset
1454 -- Initialize_Node --
kono
parents:
diff changeset
1455 ---------------------
kono
parents:
diff changeset
1456
kono
parents:
diff changeset
1457 procedure Initialize_Node
kono
parents:
diff changeset
1458 (Container : in out Tree;
kono
parents:
diff changeset
1459 Index : Count_Type)
kono
parents:
diff changeset
1460 is
kono
parents:
diff changeset
1461 begin
kono
parents:
diff changeset
1462 Container.Nodes (Index) :=
kono
parents:
diff changeset
1463 (Parent => No_Node,
kono
parents:
diff changeset
1464 Prev => 0,
kono
parents:
diff changeset
1465 Next => 0,
kono
parents:
diff changeset
1466 Children => (others => 0));
kono
parents:
diff changeset
1467 end Initialize_Node;
kono
parents:
diff changeset
1468
kono
parents:
diff changeset
1469 ---------------------
kono
parents:
diff changeset
1470 -- Initialize_Root --
kono
parents:
diff changeset
1471 ---------------------
kono
parents:
diff changeset
1472
kono
parents:
diff changeset
1473 procedure Initialize_Root (Container : in out Tree) is
kono
parents:
diff changeset
1474 begin
kono
parents:
diff changeset
1475 Initialize_Node (Container, Root_Node (Container));
kono
parents:
diff changeset
1476 end Initialize_Root;
kono
parents:
diff changeset
1477
kono
parents:
diff changeset
1478 ------------------
kono
parents:
diff changeset
1479 -- Insert_Child --
kono
parents:
diff changeset
1480 ------------------
kono
parents:
diff changeset
1481
kono
parents:
diff changeset
1482 procedure Insert_Child
kono
parents:
diff changeset
1483 (Container : in out Tree;
kono
parents:
diff changeset
1484 Parent : Cursor;
kono
parents:
diff changeset
1485 Before : Cursor;
kono
parents:
diff changeset
1486 New_Item : Element_Type;
kono
parents:
diff changeset
1487 Count : Count_Type := 1)
kono
parents:
diff changeset
1488 is
kono
parents:
diff changeset
1489 Position : Cursor;
kono
parents:
diff changeset
1490 pragma Unreferenced (Position);
kono
parents:
diff changeset
1491
kono
parents:
diff changeset
1492 begin
kono
parents:
diff changeset
1493 Insert_Child (Container, Parent, Before, New_Item, Position, Count);
kono
parents:
diff changeset
1494 end Insert_Child;
kono
parents:
diff changeset
1495
kono
parents:
diff changeset
1496 procedure Insert_Child
kono
parents:
diff changeset
1497 (Container : in out Tree;
kono
parents:
diff changeset
1498 Parent : Cursor;
kono
parents:
diff changeset
1499 Before : Cursor;
kono
parents:
diff changeset
1500 New_Item : Element_Type;
kono
parents:
diff changeset
1501 Position : out Cursor;
kono
parents:
diff changeset
1502 Count : Count_Type := 1)
kono
parents:
diff changeset
1503 is
kono
parents:
diff changeset
1504 Nodes : Tree_Node_Array renames Container.Nodes;
kono
parents:
diff changeset
1505 First : Count_Type;
kono
parents:
diff changeset
1506 Last : Count_Type;
kono
parents:
diff changeset
1507
kono
parents:
diff changeset
1508 begin
kono
parents:
diff changeset
1509 if Checks and then Parent = No_Element then
kono
parents:
diff changeset
1510 raise Constraint_Error with "Parent cursor has no element";
kono
parents:
diff changeset
1511 end if;
kono
parents:
diff changeset
1512
kono
parents:
diff changeset
1513 if Checks and then Parent.Container /= Container'Unrestricted_Access then
kono
parents:
diff changeset
1514 raise Program_Error with "Parent cursor not in container";
kono
parents:
diff changeset
1515 end if;
kono
parents:
diff changeset
1516
kono
parents:
diff changeset
1517 if Before /= No_Element then
kono
parents:
diff changeset
1518 if Checks and then Before.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
1519 then
kono
parents:
diff changeset
1520 raise Program_Error with "Before cursor not in container";
kono
parents:
diff changeset
1521 end if;
kono
parents:
diff changeset
1522
kono
parents:
diff changeset
1523 if Checks and then
kono
parents:
diff changeset
1524 Before.Container.Nodes (Before.Node).Parent /= Parent.Node
kono
parents:
diff changeset
1525 then
kono
parents:
diff changeset
1526 raise Constraint_Error with "Parent cursor not parent of Before";
kono
parents:
diff changeset
1527 end if;
kono
parents:
diff changeset
1528 end if;
kono
parents:
diff changeset
1529
kono
parents:
diff changeset
1530 if Count = 0 then
kono
parents:
diff changeset
1531 Position := No_Element; -- Need ruling from ARG ???
kono
parents:
diff changeset
1532 return;
kono
parents:
diff changeset
1533 end if;
kono
parents:
diff changeset
1534
kono
parents:
diff changeset
1535 if Checks and then Container.Count > Container.Capacity - Count then
kono
parents:
diff changeset
1536 raise Capacity_Error
kono
parents:
diff changeset
1537 with "requested count exceeds available storage";
kono
parents:
diff changeset
1538 end if;
kono
parents:
diff changeset
1539
kono
parents:
diff changeset
1540 TC_Check (Container.TC);
kono
parents:
diff changeset
1541
kono
parents:
diff changeset
1542 if Container.Count = 0 then
kono
parents:
diff changeset
1543 Initialize_Root (Container);
kono
parents:
diff changeset
1544 end if;
kono
parents:
diff changeset
1545
kono
parents:
diff changeset
1546 Allocate_Node (Container, New_Item, First);
kono
parents:
diff changeset
1547 Nodes (First).Parent := Parent.Node;
kono
parents:
diff changeset
1548
kono
parents:
diff changeset
1549 Last := First;
kono
parents:
diff changeset
1550 for J in Count_Type'(2) .. Count loop
kono
parents:
diff changeset
1551 Allocate_Node (Container, New_Item, Nodes (Last).Next);
kono
parents:
diff changeset
1552 Nodes (Nodes (Last).Next).Parent := Parent.Node;
kono
parents:
diff changeset
1553 Nodes (Nodes (Last).Next).Prev := Last;
kono
parents:
diff changeset
1554
kono
parents:
diff changeset
1555 Last := Nodes (Last).Next;
kono
parents:
diff changeset
1556 end loop;
kono
parents:
diff changeset
1557
kono
parents:
diff changeset
1558 Insert_Subtree_List
kono
parents:
diff changeset
1559 (Container => Container,
kono
parents:
diff changeset
1560 First => First,
kono
parents:
diff changeset
1561 Last => Last,
kono
parents:
diff changeset
1562 Parent => Parent.Node,
kono
parents:
diff changeset
1563 Before => Before.Node);
kono
parents:
diff changeset
1564
kono
parents:
diff changeset
1565 Container.Count := Container.Count + Count;
kono
parents:
diff changeset
1566
kono
parents:
diff changeset
1567 Position := Cursor'(Parent.Container, First);
kono
parents:
diff changeset
1568 end Insert_Child;
kono
parents:
diff changeset
1569
kono
parents:
diff changeset
1570 procedure Insert_Child
kono
parents:
diff changeset
1571 (Container : in out Tree;
kono
parents:
diff changeset
1572 Parent : Cursor;
kono
parents:
diff changeset
1573 Before : Cursor;
kono
parents:
diff changeset
1574 Position : out Cursor;
kono
parents:
diff changeset
1575 Count : Count_Type := 1)
kono
parents:
diff changeset
1576 is
kono
parents:
diff changeset
1577 Nodes : Tree_Node_Array renames Container.Nodes;
kono
parents:
diff changeset
1578 First : Count_Type;
kono
parents:
diff changeset
1579 Last : Count_Type;
kono
parents:
diff changeset
1580
kono
parents:
diff changeset
1581 pragma Warnings (Off);
kono
parents:
diff changeset
1582 Default_Initialized_Item : Element_Type;
kono
parents:
diff changeset
1583 pragma Unmodified (Default_Initialized_Item);
kono
parents:
diff changeset
1584 -- OK to reference, see below
kono
parents:
diff changeset
1585
kono
parents:
diff changeset
1586 begin
kono
parents:
diff changeset
1587 if Checks and then Parent = No_Element then
kono
parents:
diff changeset
1588 raise Constraint_Error with "Parent cursor has no element";
kono
parents:
diff changeset
1589 end if;
kono
parents:
diff changeset
1590
kono
parents:
diff changeset
1591 if Checks and then Parent.Container /= Container'Unrestricted_Access then
kono
parents:
diff changeset
1592 raise Program_Error with "Parent cursor not in container";
kono
parents:
diff changeset
1593 end if;
kono
parents:
diff changeset
1594
kono
parents:
diff changeset
1595 if Before /= No_Element then
kono
parents:
diff changeset
1596 if Checks and then Before.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
1597 then
kono
parents:
diff changeset
1598 raise Program_Error with "Before cursor not in container";
kono
parents:
diff changeset
1599 end if;
kono
parents:
diff changeset
1600
kono
parents:
diff changeset
1601 if Checks and then
kono
parents:
diff changeset
1602 Before.Container.Nodes (Before.Node).Parent /= Parent.Node
kono
parents:
diff changeset
1603 then
kono
parents:
diff changeset
1604 raise Constraint_Error with "Parent cursor not parent of Before";
kono
parents:
diff changeset
1605 end if;
kono
parents:
diff changeset
1606 end if;
kono
parents:
diff changeset
1607
kono
parents:
diff changeset
1608 if Count = 0 then
kono
parents:
diff changeset
1609 Position := No_Element; -- Need ruling from ARG ???
kono
parents:
diff changeset
1610 return;
kono
parents:
diff changeset
1611 end if;
kono
parents:
diff changeset
1612
kono
parents:
diff changeset
1613 if Checks and then Container.Count > Container.Capacity - Count then
kono
parents:
diff changeset
1614 raise Capacity_Error
kono
parents:
diff changeset
1615 with "requested count exceeds available storage";
kono
parents:
diff changeset
1616 end if;
kono
parents:
diff changeset
1617
kono
parents:
diff changeset
1618 TC_Check (Container.TC);
kono
parents:
diff changeset
1619
kono
parents:
diff changeset
1620 if Container.Count = 0 then
kono
parents:
diff changeset
1621 Initialize_Root (Container);
kono
parents:
diff changeset
1622 end if;
kono
parents:
diff changeset
1623
kono
parents:
diff changeset
1624 -- There is no explicit element provided, but in an instance the element
kono
parents:
diff changeset
1625 -- type may be a scalar with a Default_Value aspect, or a composite
kono
parents:
diff changeset
1626 -- type with such a scalar component, or components with default
kono
parents:
diff changeset
1627 -- initialization, so insert the specified number of possibly
kono
parents:
diff changeset
1628 -- initialized elements at the given position.
kono
parents:
diff changeset
1629
kono
parents:
diff changeset
1630 Allocate_Node (Container, Default_Initialized_Item, First);
kono
parents:
diff changeset
1631 Nodes (First).Parent := Parent.Node;
kono
parents:
diff changeset
1632
kono
parents:
diff changeset
1633 Last := First;
kono
parents:
diff changeset
1634 for J in Count_Type'(2) .. Count loop
kono
parents:
diff changeset
1635 Allocate_Node
kono
parents:
diff changeset
1636 (Container, Default_Initialized_Item, Nodes (Last).Next);
kono
parents:
diff changeset
1637 Nodes (Nodes (Last).Next).Parent := Parent.Node;
kono
parents:
diff changeset
1638 Nodes (Nodes (Last).Next).Prev := Last;
kono
parents:
diff changeset
1639
kono
parents:
diff changeset
1640 Last := Nodes (Last).Next;
kono
parents:
diff changeset
1641 end loop;
kono
parents:
diff changeset
1642
kono
parents:
diff changeset
1643 Insert_Subtree_List
kono
parents:
diff changeset
1644 (Container => Container,
kono
parents:
diff changeset
1645 First => First,
kono
parents:
diff changeset
1646 Last => Last,
kono
parents:
diff changeset
1647 Parent => Parent.Node,
kono
parents:
diff changeset
1648 Before => Before.Node);
kono
parents:
diff changeset
1649
kono
parents:
diff changeset
1650 Container.Count := Container.Count + Count;
kono
parents:
diff changeset
1651
kono
parents:
diff changeset
1652 Position := Cursor'(Parent.Container, First);
kono
parents:
diff changeset
1653 pragma Warnings (On);
kono
parents:
diff changeset
1654 end Insert_Child;
kono
parents:
diff changeset
1655
kono
parents:
diff changeset
1656 -------------------------
kono
parents:
diff changeset
1657 -- Insert_Subtree_List --
kono
parents:
diff changeset
1658 -------------------------
kono
parents:
diff changeset
1659
kono
parents:
diff changeset
1660 procedure Insert_Subtree_List
kono
parents:
diff changeset
1661 (Container : in out Tree;
kono
parents:
diff changeset
1662 First : Count_Type'Base;
kono
parents:
diff changeset
1663 Last : Count_Type'Base;
kono
parents:
diff changeset
1664 Parent : Count_Type;
kono
parents:
diff changeset
1665 Before : Count_Type'Base)
kono
parents:
diff changeset
1666 is
kono
parents:
diff changeset
1667 NN : Tree_Node_Array renames Container.Nodes;
kono
parents:
diff changeset
1668 N : Tree_Node_Type renames NN (Parent);
kono
parents:
diff changeset
1669 CC : Children_Type renames N.Children;
kono
parents:
diff changeset
1670
kono
parents:
diff changeset
1671 begin
kono
parents:
diff changeset
1672 -- This is a simple utility operation to insert a list of nodes
kono
parents:
diff changeset
1673 -- (First..Last) as children of Parent. The Before node specifies where
kono
parents:
diff changeset
1674 -- the new children should be inserted relative to existing children.
kono
parents:
diff changeset
1675
kono
parents:
diff changeset
1676 if First <= 0 then
kono
parents:
diff changeset
1677 pragma Assert (Last <= 0);
kono
parents:
diff changeset
1678 return;
kono
parents:
diff changeset
1679 end if;
kono
parents:
diff changeset
1680
kono
parents:
diff changeset
1681 pragma Assert (Last > 0);
kono
parents:
diff changeset
1682 pragma Assert (Before <= 0 or else NN (Before).Parent = Parent);
kono
parents:
diff changeset
1683
kono
parents:
diff changeset
1684 if CC.First <= 0 then -- no existing children
kono
parents:
diff changeset
1685 CC.First := First;
kono
parents:
diff changeset
1686 NN (CC.First).Prev := 0;
kono
parents:
diff changeset
1687 CC.Last := Last;
kono
parents:
diff changeset
1688 NN (CC.Last).Next := 0;
kono
parents:
diff changeset
1689
kono
parents:
diff changeset
1690 elsif Before <= 0 then -- means "insert after existing nodes"
kono
parents:
diff changeset
1691 NN (CC.Last).Next := First;
kono
parents:
diff changeset
1692 NN (First).Prev := CC.Last;
kono
parents:
diff changeset
1693 CC.Last := Last;
kono
parents:
diff changeset
1694 NN (CC.Last).Next := 0;
kono
parents:
diff changeset
1695
kono
parents:
diff changeset
1696 elsif Before = CC.First then
kono
parents:
diff changeset
1697 NN (Last).Next := CC.First;
kono
parents:
diff changeset
1698 NN (CC.First).Prev := Last;
kono
parents:
diff changeset
1699 CC.First := First;
kono
parents:
diff changeset
1700 NN (CC.First).Prev := 0;
kono
parents:
diff changeset
1701
kono
parents:
diff changeset
1702 else
kono
parents:
diff changeset
1703 NN (NN (Before).Prev).Next := First;
kono
parents:
diff changeset
1704 NN (First).Prev := NN (Before).Prev;
kono
parents:
diff changeset
1705 NN (Last).Next := Before;
kono
parents:
diff changeset
1706 NN (Before).Prev := Last;
kono
parents:
diff changeset
1707 end if;
kono
parents:
diff changeset
1708 end Insert_Subtree_List;
kono
parents:
diff changeset
1709
kono
parents:
diff changeset
1710 -------------------------
kono
parents:
diff changeset
1711 -- Insert_Subtree_Node --
kono
parents:
diff changeset
1712 -------------------------
kono
parents:
diff changeset
1713
kono
parents:
diff changeset
1714 procedure Insert_Subtree_Node
kono
parents:
diff changeset
1715 (Container : in out Tree;
kono
parents:
diff changeset
1716 Subtree : Count_Type'Base;
kono
parents:
diff changeset
1717 Parent : Count_Type;
kono
parents:
diff changeset
1718 Before : Count_Type'Base)
kono
parents:
diff changeset
1719 is
kono
parents:
diff changeset
1720 begin
kono
parents:
diff changeset
1721 -- This is a simple wrapper operation to insert a single child into the
kono
parents:
diff changeset
1722 -- Parent's children list.
kono
parents:
diff changeset
1723
kono
parents:
diff changeset
1724 Insert_Subtree_List
kono
parents:
diff changeset
1725 (Container => Container,
kono
parents:
diff changeset
1726 First => Subtree,
kono
parents:
diff changeset
1727 Last => Subtree,
kono
parents:
diff changeset
1728 Parent => Parent,
kono
parents:
diff changeset
1729 Before => Before);
kono
parents:
diff changeset
1730 end Insert_Subtree_Node;
kono
parents:
diff changeset
1731
kono
parents:
diff changeset
1732 --------------
kono
parents:
diff changeset
1733 -- Is_Empty --
kono
parents:
diff changeset
1734 --------------
kono
parents:
diff changeset
1735
kono
parents:
diff changeset
1736 function Is_Empty (Container : Tree) return Boolean is
kono
parents:
diff changeset
1737 begin
kono
parents:
diff changeset
1738 return Container.Count = 0;
kono
parents:
diff changeset
1739 end Is_Empty;
kono
parents:
diff changeset
1740
kono
parents:
diff changeset
1741 -------------
kono
parents:
diff changeset
1742 -- Is_Leaf --
kono
parents:
diff changeset
1743 -------------
kono
parents:
diff changeset
1744
kono
parents:
diff changeset
1745 function Is_Leaf (Position : Cursor) return Boolean is
kono
parents:
diff changeset
1746 begin
kono
parents:
diff changeset
1747 if Position = No_Element then
kono
parents:
diff changeset
1748 return False;
kono
parents:
diff changeset
1749 end if;
kono
parents:
diff changeset
1750
kono
parents:
diff changeset
1751 if Position.Container.Count = 0 then
kono
parents:
diff changeset
1752 pragma Assert (Is_Root (Position));
kono
parents:
diff changeset
1753 return True;
kono
parents:
diff changeset
1754 end if;
kono
parents:
diff changeset
1755
kono
parents:
diff changeset
1756 return Position.Container.Nodes (Position.Node).Children.First <= 0;
kono
parents:
diff changeset
1757 end Is_Leaf;
kono
parents:
diff changeset
1758
kono
parents:
diff changeset
1759 ------------------
kono
parents:
diff changeset
1760 -- Is_Reachable --
kono
parents:
diff changeset
1761 ------------------
kono
parents:
diff changeset
1762
kono
parents:
diff changeset
1763 function Is_Reachable
kono
parents:
diff changeset
1764 (Container : Tree;
kono
parents:
diff changeset
1765 From, To : Count_Type) return Boolean
kono
parents:
diff changeset
1766 is
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1767 Idx : Count_Type'Base := From;
111
kono
parents:
diff changeset
1768 begin
kono
parents:
diff changeset
1769 while Idx >= 0 loop
kono
parents:
diff changeset
1770 if Idx = To then
kono
parents:
diff changeset
1771 return True;
kono
parents:
diff changeset
1772 end if;
kono
parents:
diff changeset
1773
kono
parents:
diff changeset
1774 Idx := Container.Nodes (Idx).Parent;
kono
parents:
diff changeset
1775 end loop;
kono
parents:
diff changeset
1776
kono
parents:
diff changeset
1777 return False;
kono
parents:
diff changeset
1778 end Is_Reachable;
kono
parents:
diff changeset
1779
kono
parents:
diff changeset
1780 -------------
kono
parents:
diff changeset
1781 -- Is_Root --
kono
parents:
diff changeset
1782 -------------
kono
parents:
diff changeset
1783
kono
parents:
diff changeset
1784 function Is_Root (Position : Cursor) return Boolean is
kono
parents:
diff changeset
1785 begin
kono
parents:
diff changeset
1786 return
kono
parents:
diff changeset
1787 (if Position.Container = null then False
kono
parents:
diff changeset
1788 else Position.Node = Root_Node (Position.Container.all));
kono
parents:
diff changeset
1789 end Is_Root;
kono
parents:
diff changeset
1790
kono
parents:
diff changeset
1791 -------------
kono
parents:
diff changeset
1792 -- Iterate --
kono
parents:
diff changeset
1793 -------------
kono
parents:
diff changeset
1794
kono
parents:
diff changeset
1795 procedure Iterate
kono
parents:
diff changeset
1796 (Container : Tree;
kono
parents:
diff changeset
1797 Process : not null access procedure (Position : Cursor))
kono
parents:
diff changeset
1798 is
kono
parents:
diff changeset
1799 Busy : With_Busy (Container.TC'Unrestricted_Access);
kono
parents:
diff changeset
1800 begin
kono
parents:
diff changeset
1801 if Container.Count = 0 then
kono
parents:
diff changeset
1802 return;
kono
parents:
diff changeset
1803 end if;
kono
parents:
diff changeset
1804
kono
parents:
diff changeset
1805 Iterate_Children
kono
parents:
diff changeset
1806 (Container => Container,
kono
parents:
diff changeset
1807 Subtree => Root_Node (Container),
kono
parents:
diff changeset
1808 Process => Process);
kono
parents:
diff changeset
1809 end Iterate;
kono
parents:
diff changeset
1810
kono
parents:
diff changeset
1811 function Iterate (Container : Tree)
kono
parents:
diff changeset
1812 return Tree_Iterator_Interfaces.Forward_Iterator'Class
kono
parents:
diff changeset
1813 is
kono
parents:
diff changeset
1814 begin
kono
parents:
diff changeset
1815 return Iterate_Subtree (Root (Container));
kono
parents:
diff changeset
1816 end Iterate;
kono
parents:
diff changeset
1817
kono
parents:
diff changeset
1818 ----------------------
kono
parents:
diff changeset
1819 -- Iterate_Children --
kono
parents:
diff changeset
1820 ----------------------
kono
parents:
diff changeset
1821
kono
parents:
diff changeset
1822 procedure Iterate_Children
kono
parents:
diff changeset
1823 (Parent : Cursor;
kono
parents:
diff changeset
1824 Process : not null access procedure (Position : Cursor))
kono
parents:
diff changeset
1825 is
kono
parents:
diff changeset
1826 begin
kono
parents:
diff changeset
1827 if Checks and then Parent = No_Element then
kono
parents:
diff changeset
1828 raise Constraint_Error with "Parent cursor has no element";
kono
parents:
diff changeset
1829 end if;
kono
parents:
diff changeset
1830
kono
parents:
diff changeset
1831 if Parent.Container.Count = 0 then
kono
parents:
diff changeset
1832 pragma Assert (Is_Root (Parent));
kono
parents:
diff changeset
1833 return;
kono
parents:
diff changeset
1834 end if;
kono
parents:
diff changeset
1835
kono
parents:
diff changeset
1836 declare
kono
parents:
diff changeset
1837 C : Count_Type;
kono
parents:
diff changeset
1838 NN : Tree_Node_Array renames Parent.Container.Nodes;
kono
parents:
diff changeset
1839 Busy : With_Busy (Parent.Container.TC'Unrestricted_Access);
kono
parents:
diff changeset
1840
kono
parents:
diff changeset
1841 begin
kono
parents:
diff changeset
1842 C := NN (Parent.Node).Children.First;
kono
parents:
diff changeset
1843 while C > 0 loop
kono
parents:
diff changeset
1844 Process (Cursor'(Parent.Container, Node => C));
kono
parents:
diff changeset
1845 C := NN (C).Next;
kono
parents:
diff changeset
1846 end loop;
kono
parents:
diff changeset
1847 end;
kono
parents:
diff changeset
1848 end Iterate_Children;
kono
parents:
diff changeset
1849
kono
parents:
diff changeset
1850 procedure Iterate_Children
kono
parents:
diff changeset
1851 (Container : Tree;
kono
parents:
diff changeset
1852 Subtree : Count_Type;
kono
parents:
diff changeset
1853 Process : not null access procedure (Position : Cursor))
kono
parents:
diff changeset
1854 is
kono
parents:
diff changeset
1855 NN : Tree_Node_Array renames Container.Nodes;
kono
parents:
diff changeset
1856 N : Tree_Node_Type renames NN (Subtree);
kono
parents:
diff changeset
1857 C : Count_Type;
kono
parents:
diff changeset
1858
kono
parents:
diff changeset
1859 begin
kono
parents:
diff changeset
1860 -- This is a helper function to recursively iterate over all the nodes
kono
parents:
diff changeset
1861 -- in a subtree, in depth-first fashion. This particular helper just
kono
parents:
diff changeset
1862 -- visits the children of this subtree, not the root of the subtree
kono
parents:
diff changeset
1863 -- itself. This is useful when starting from the ultimate root of the
kono
parents:
diff changeset
1864 -- entire tree (see Iterate), as that root does not have an element.
kono
parents:
diff changeset
1865
kono
parents:
diff changeset
1866 C := N.Children.First;
kono
parents:
diff changeset
1867 while C > 0 loop
kono
parents:
diff changeset
1868 Iterate_Subtree (Container, C, Process);
kono
parents:
diff changeset
1869 C := NN (C).Next;
kono
parents:
diff changeset
1870 end loop;
kono
parents:
diff changeset
1871 end Iterate_Children;
kono
parents:
diff changeset
1872
kono
parents:
diff changeset
1873 function Iterate_Children
kono
parents:
diff changeset
1874 (Container : Tree;
kono
parents:
diff changeset
1875 Parent : Cursor)
kono
parents:
diff changeset
1876 return Tree_Iterator_Interfaces.Reversible_Iterator'Class
kono
parents:
diff changeset
1877 is
kono
parents:
diff changeset
1878 C : constant Tree_Access := Container'Unrestricted_Access;
kono
parents:
diff changeset
1879 begin
kono
parents:
diff changeset
1880 if Checks and then Parent = No_Element then
kono
parents:
diff changeset
1881 raise Constraint_Error with "Parent cursor has no element";
kono
parents:
diff changeset
1882 end if;
kono
parents:
diff changeset
1883
kono
parents:
diff changeset
1884 if Checks and then Parent.Container /= C then
kono
parents:
diff changeset
1885 raise Program_Error with "Parent cursor not in container";
kono
parents:
diff changeset
1886 end if;
kono
parents:
diff changeset
1887
kono
parents:
diff changeset
1888 return It : constant Child_Iterator :=
kono
parents:
diff changeset
1889 Child_Iterator'(Limited_Controlled with
kono
parents:
diff changeset
1890 Container => C,
kono
parents:
diff changeset
1891 Subtree => Parent.Node)
kono
parents:
diff changeset
1892 do
kono
parents:
diff changeset
1893 Busy (C.TC);
kono
parents:
diff changeset
1894 end return;
kono
parents:
diff changeset
1895 end Iterate_Children;
kono
parents:
diff changeset
1896
kono
parents:
diff changeset
1897 ---------------------
kono
parents:
diff changeset
1898 -- Iterate_Subtree --
kono
parents:
diff changeset
1899 ---------------------
kono
parents:
diff changeset
1900
kono
parents:
diff changeset
1901 function Iterate_Subtree
kono
parents:
diff changeset
1902 (Position : Cursor)
kono
parents:
diff changeset
1903 return Tree_Iterator_Interfaces.Forward_Iterator'Class
kono
parents:
diff changeset
1904 is
kono
parents:
diff changeset
1905 C : constant Tree_Access := Position.Container;
kono
parents:
diff changeset
1906 begin
kono
parents:
diff changeset
1907 if Checks and then Position = No_Element then
kono
parents:
diff changeset
1908 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
1909 end if;
kono
parents:
diff changeset
1910
kono
parents:
diff changeset
1911 -- Implement Vet for multiway trees???
kono
parents:
diff changeset
1912 -- pragma Assert (Vet (Position), "bad subtree cursor");
kono
parents:
diff changeset
1913
kono
parents:
diff changeset
1914 return It : constant Subtree_Iterator :=
kono
parents:
diff changeset
1915 (Limited_Controlled with
kono
parents:
diff changeset
1916 Container => C,
kono
parents:
diff changeset
1917 Subtree => Position.Node)
kono
parents:
diff changeset
1918 do
kono
parents:
diff changeset
1919 Busy (C.TC);
kono
parents:
diff changeset
1920 end return;
kono
parents:
diff changeset
1921 end Iterate_Subtree;
kono
parents:
diff changeset
1922
kono
parents:
diff changeset
1923 procedure Iterate_Subtree
kono
parents:
diff changeset
1924 (Position : Cursor;
kono
parents:
diff changeset
1925 Process : not null access procedure (Position : Cursor))
kono
parents:
diff changeset
1926 is
kono
parents:
diff changeset
1927 begin
kono
parents:
diff changeset
1928 if Checks and then Position = No_Element then
kono
parents:
diff changeset
1929 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
1930 end if;
kono
parents:
diff changeset
1931
kono
parents:
diff changeset
1932 if Position.Container.Count = 0 then
kono
parents:
diff changeset
1933 pragma Assert (Is_Root (Position));
kono
parents:
diff changeset
1934 return;
kono
parents:
diff changeset
1935 end if;
kono
parents:
diff changeset
1936
kono
parents:
diff changeset
1937 declare
kono
parents:
diff changeset
1938 T : Tree renames Position.Container.all;
kono
parents:
diff changeset
1939 Busy : With_Busy (T.TC'Unrestricted_Access);
kono
parents:
diff changeset
1940 begin
kono
parents:
diff changeset
1941 if Is_Root (Position) then
kono
parents:
diff changeset
1942 Iterate_Children (T, Position.Node, Process);
kono
parents:
diff changeset
1943 else
kono
parents:
diff changeset
1944 Iterate_Subtree (T, Position.Node, Process);
kono
parents:
diff changeset
1945 end if;
kono
parents:
diff changeset
1946 end;
kono
parents:
diff changeset
1947 end Iterate_Subtree;
kono
parents:
diff changeset
1948
kono
parents:
diff changeset
1949 procedure Iterate_Subtree
kono
parents:
diff changeset
1950 (Container : Tree;
kono
parents:
diff changeset
1951 Subtree : Count_Type;
kono
parents:
diff changeset
1952 Process : not null access procedure (Position : Cursor))
kono
parents:
diff changeset
1953 is
kono
parents:
diff changeset
1954 begin
kono
parents:
diff changeset
1955 -- This is a helper function to recursively iterate over all the nodes
kono
parents:
diff changeset
1956 -- in a subtree, in depth-first fashion. It first visits the root of the
kono
parents:
diff changeset
1957 -- subtree, then visits its children.
kono
parents:
diff changeset
1958
kono
parents:
diff changeset
1959 Process (Cursor'(Container'Unrestricted_Access, Subtree));
kono
parents:
diff changeset
1960 Iterate_Children (Container, Subtree, Process);
kono
parents:
diff changeset
1961 end Iterate_Subtree;
kono
parents:
diff changeset
1962
kono
parents:
diff changeset
1963 ----------
kono
parents:
diff changeset
1964 -- Last --
kono
parents:
diff changeset
1965 ----------
kono
parents:
diff changeset
1966
kono
parents:
diff changeset
1967 overriding function Last (Object : Child_Iterator) return Cursor is
kono
parents:
diff changeset
1968 begin
kono
parents:
diff changeset
1969 return Last_Child (Cursor'(Object.Container, Object.Subtree));
kono
parents:
diff changeset
1970 end Last;
kono
parents:
diff changeset
1971
kono
parents:
diff changeset
1972 ----------------
kono
parents:
diff changeset
1973 -- Last_Child --
kono
parents:
diff changeset
1974 ----------------
kono
parents:
diff changeset
1975
kono
parents:
diff changeset
1976 function Last_Child (Parent : Cursor) return Cursor is
kono
parents:
diff changeset
1977 Node : Count_Type'Base;
kono
parents:
diff changeset
1978
kono
parents:
diff changeset
1979 begin
kono
parents:
diff changeset
1980 if Checks and then Parent = No_Element then
kono
parents:
diff changeset
1981 raise Constraint_Error with "Parent cursor has no element";
kono
parents:
diff changeset
1982 end if;
kono
parents:
diff changeset
1983
kono
parents:
diff changeset
1984 if Parent.Container.Count = 0 then
kono
parents:
diff changeset
1985 pragma Assert (Is_Root (Parent));
kono
parents:
diff changeset
1986 return No_Element;
kono
parents:
diff changeset
1987 end if;
kono
parents:
diff changeset
1988
kono
parents:
diff changeset
1989 Node := Parent.Container.Nodes (Parent.Node).Children.Last;
kono
parents:
diff changeset
1990
kono
parents:
diff changeset
1991 if Node <= 0 then
kono
parents:
diff changeset
1992 return No_Element;
kono
parents:
diff changeset
1993 end if;
kono
parents:
diff changeset
1994
kono
parents:
diff changeset
1995 return Cursor'(Parent.Container, Node);
kono
parents:
diff changeset
1996 end Last_Child;
kono
parents:
diff changeset
1997
kono
parents:
diff changeset
1998 ------------------------
kono
parents:
diff changeset
1999 -- Last_Child_Element --
kono
parents:
diff changeset
2000 ------------------------
kono
parents:
diff changeset
2001
kono
parents:
diff changeset
2002 function Last_Child_Element (Parent : Cursor) return Element_Type is
kono
parents:
diff changeset
2003 begin
kono
parents:
diff changeset
2004 return Element (Last_Child (Parent));
kono
parents:
diff changeset
2005 end Last_Child_Element;
kono
parents:
diff changeset
2006
kono
parents:
diff changeset
2007 ----------
kono
parents:
diff changeset
2008 -- Move --
kono
parents:
diff changeset
2009 ----------
kono
parents:
diff changeset
2010
kono
parents:
diff changeset
2011 procedure Move (Target : in out Tree; Source : in out Tree) is
kono
parents:
diff changeset
2012 begin
kono
parents:
diff changeset
2013 if Target'Address = Source'Address then
kono
parents:
diff changeset
2014 return;
kono
parents:
diff changeset
2015 end if;
kono
parents:
diff changeset
2016
kono
parents:
diff changeset
2017 TC_Check (Source.TC);
kono
parents:
diff changeset
2018
kono
parents:
diff changeset
2019 Target.Assign (Source);
kono
parents:
diff changeset
2020 Source.Clear;
kono
parents:
diff changeset
2021 end Move;
kono
parents:
diff changeset
2022
kono
parents:
diff changeset
2023 ----------
kono
parents:
diff changeset
2024 -- Next --
kono
parents:
diff changeset
2025 ----------
kono
parents:
diff changeset
2026
kono
parents:
diff changeset
2027 overriding function Next
kono
parents:
diff changeset
2028 (Object : Subtree_Iterator;
kono
parents:
diff changeset
2029 Position : Cursor) return Cursor
kono
parents:
diff changeset
2030 is
kono
parents:
diff changeset
2031 begin
kono
parents:
diff changeset
2032 if Position.Container = null then
kono
parents:
diff changeset
2033 return No_Element;
kono
parents:
diff changeset
2034 end if;
kono
parents:
diff changeset
2035
kono
parents:
diff changeset
2036 if Checks and then Position.Container /= Object.Container then
kono
parents:
diff changeset
2037 raise Program_Error with
kono
parents:
diff changeset
2038 "Position cursor of Next designates wrong tree";
kono
parents:
diff changeset
2039 end if;
kono
parents:
diff changeset
2040
kono
parents:
diff changeset
2041 pragma Assert (Object.Container.Count > 0);
kono
parents:
diff changeset
2042 pragma Assert (Position.Node /= Root_Node (Object.Container.all));
kono
parents:
diff changeset
2043
kono
parents:
diff changeset
2044 declare
kono
parents:
diff changeset
2045 Nodes : Tree_Node_Array renames Object.Container.Nodes;
kono
parents:
diff changeset
2046 Node : Count_Type;
kono
parents:
diff changeset
2047
kono
parents:
diff changeset
2048 begin
kono
parents:
diff changeset
2049 Node := Position.Node;
kono
parents:
diff changeset
2050
kono
parents:
diff changeset
2051 if Nodes (Node).Children.First > 0 then
kono
parents:
diff changeset
2052 return Cursor'(Object.Container, Nodes (Node).Children.First);
kono
parents:
diff changeset
2053 end if;
kono
parents:
diff changeset
2054
kono
parents:
diff changeset
2055 while Node /= Object.Subtree loop
kono
parents:
diff changeset
2056 if Nodes (Node).Next > 0 then
kono
parents:
diff changeset
2057 return Cursor'(Object.Container, Nodes (Node).Next);
kono
parents:
diff changeset
2058 end if;
kono
parents:
diff changeset
2059
kono
parents:
diff changeset
2060 Node := Nodes (Node).Parent;
kono
parents:
diff changeset
2061 end loop;
kono
parents:
diff changeset
2062
kono
parents:
diff changeset
2063 return No_Element;
kono
parents:
diff changeset
2064 end;
kono
parents:
diff changeset
2065 end Next;
kono
parents:
diff changeset
2066
kono
parents:
diff changeset
2067 overriding function Next
kono
parents:
diff changeset
2068 (Object : Child_Iterator;
kono
parents:
diff changeset
2069 Position : Cursor) return Cursor
kono
parents:
diff changeset
2070 is
kono
parents:
diff changeset
2071 begin
kono
parents:
diff changeset
2072 if Position.Container = null then
kono
parents:
diff changeset
2073 return No_Element;
kono
parents:
diff changeset
2074 end if;
kono
parents:
diff changeset
2075
kono
parents:
diff changeset
2076 if Checks and then Position.Container /= Object.Container then
kono
parents:
diff changeset
2077 raise Program_Error with
kono
parents:
diff changeset
2078 "Position cursor of Next designates wrong tree";
kono
parents:
diff changeset
2079 end if;
kono
parents:
diff changeset
2080
kono
parents:
diff changeset
2081 pragma Assert (Object.Container.Count > 0);
kono
parents:
diff changeset
2082 pragma Assert (Position.Node /= Root_Node (Object.Container.all));
kono
parents:
diff changeset
2083
kono
parents:
diff changeset
2084 return Next_Sibling (Position);
kono
parents:
diff changeset
2085 end Next;
kono
parents:
diff changeset
2086
kono
parents:
diff changeset
2087 ------------------
kono
parents:
diff changeset
2088 -- Next_Sibling --
kono
parents:
diff changeset
2089 ------------------
kono
parents:
diff changeset
2090
kono
parents:
diff changeset
2091 function Next_Sibling (Position : Cursor) return Cursor is
kono
parents:
diff changeset
2092 begin
kono
parents:
diff changeset
2093 if Position = No_Element then
kono
parents:
diff changeset
2094 return No_Element;
kono
parents:
diff changeset
2095 end if;
kono
parents:
diff changeset
2096
kono
parents:
diff changeset
2097 if Position.Container.Count = 0 then
kono
parents:
diff changeset
2098 pragma Assert (Is_Root (Position));
kono
parents:
diff changeset
2099 return No_Element;
kono
parents:
diff changeset
2100 end if;
kono
parents:
diff changeset
2101
kono
parents:
diff changeset
2102 declare
kono
parents:
diff changeset
2103 T : Tree renames Position.Container.all;
kono
parents:
diff changeset
2104 NN : Tree_Node_Array renames T.Nodes;
kono
parents:
diff changeset
2105 N : Tree_Node_Type renames NN (Position.Node);
kono
parents:
diff changeset
2106
kono
parents:
diff changeset
2107 begin
kono
parents:
diff changeset
2108 if N.Next <= 0 then
kono
parents:
diff changeset
2109 return No_Element;
kono
parents:
diff changeset
2110 end if;
kono
parents:
diff changeset
2111
kono
parents:
diff changeset
2112 return Cursor'(Position.Container, N.Next);
kono
parents:
diff changeset
2113 end;
kono
parents:
diff changeset
2114 end Next_Sibling;
kono
parents:
diff changeset
2115
kono
parents:
diff changeset
2116 procedure Next_Sibling (Position : in out Cursor) is
kono
parents:
diff changeset
2117 begin
kono
parents:
diff changeset
2118 Position := Next_Sibling (Position);
kono
parents:
diff changeset
2119 end Next_Sibling;
kono
parents:
diff changeset
2120
kono
parents:
diff changeset
2121 ----------------
kono
parents:
diff changeset
2122 -- Node_Count --
kono
parents:
diff changeset
2123 ----------------
kono
parents:
diff changeset
2124
kono
parents:
diff changeset
2125 function Node_Count (Container : Tree) return Count_Type is
kono
parents:
diff changeset
2126 begin
kono
parents:
diff changeset
2127 -- Container.Count is the number of nodes we have actually allocated. We
kono
parents:
diff changeset
2128 -- cache the value specifically so this Node_Count operation can execute
kono
parents:
diff changeset
2129 -- in O(1) time, which makes it behave similarly to how the Length
kono
parents:
diff changeset
2130 -- selector function behaves for other containers.
kono
parents:
diff changeset
2131 --
kono
parents:
diff changeset
2132 -- The cached node count value only describes the nodes we have
kono
parents:
diff changeset
2133 -- allocated; the root node itself is not included in that count. The
kono
parents:
diff changeset
2134 -- Node_Count operation returns a value that includes the root node
kono
parents:
diff changeset
2135 -- (because the RM says so), so we must add 1 to our cached value.
kono
parents:
diff changeset
2136
kono
parents:
diff changeset
2137 return 1 + Container.Count;
kono
parents:
diff changeset
2138 end Node_Count;
kono
parents:
diff changeset
2139
kono
parents:
diff changeset
2140 ------------
kono
parents:
diff changeset
2141 -- Parent --
kono
parents:
diff changeset
2142 ------------
kono
parents:
diff changeset
2143
kono
parents:
diff changeset
2144 function Parent (Position : Cursor) return Cursor is
kono
parents:
diff changeset
2145 begin
kono
parents:
diff changeset
2146 if Position = No_Element then
kono
parents:
diff changeset
2147 return No_Element;
kono
parents:
diff changeset
2148 end if;
kono
parents:
diff changeset
2149
kono
parents:
diff changeset
2150 if Position.Container.Count = 0 then
kono
parents:
diff changeset
2151 pragma Assert (Is_Root (Position));
kono
parents:
diff changeset
2152 return No_Element;
kono
parents:
diff changeset
2153 end if;
kono
parents:
diff changeset
2154
kono
parents:
diff changeset
2155 declare
kono
parents:
diff changeset
2156 T : Tree renames Position.Container.all;
kono
parents:
diff changeset
2157 NN : Tree_Node_Array renames T.Nodes;
kono
parents:
diff changeset
2158 N : Tree_Node_Type renames NN (Position.Node);
kono
parents:
diff changeset
2159
kono
parents:
diff changeset
2160 begin
kono
parents:
diff changeset
2161 if N.Parent < 0 then
kono
parents:
diff changeset
2162 pragma Assert (Position.Node = Root_Node (T));
kono
parents:
diff changeset
2163 return No_Element;
kono
parents:
diff changeset
2164 end if;
kono
parents:
diff changeset
2165
kono
parents:
diff changeset
2166 return Cursor'(Position.Container, N.Parent);
kono
parents:
diff changeset
2167 end;
kono
parents:
diff changeset
2168 end Parent;
kono
parents:
diff changeset
2169
kono
parents:
diff changeset
2170 -------------------
kono
parents:
diff changeset
2171 -- Prepend_Child --
kono
parents:
diff changeset
2172 -------------------
kono
parents:
diff changeset
2173
kono
parents:
diff changeset
2174 procedure Prepend_Child
kono
parents:
diff changeset
2175 (Container : in out Tree;
kono
parents:
diff changeset
2176 Parent : Cursor;
kono
parents:
diff changeset
2177 New_Item : Element_Type;
kono
parents:
diff changeset
2178 Count : Count_Type := 1)
kono
parents:
diff changeset
2179 is
kono
parents:
diff changeset
2180 Nodes : Tree_Node_Array renames Container.Nodes;
kono
parents:
diff changeset
2181 First, Last : Count_Type;
kono
parents:
diff changeset
2182
kono
parents:
diff changeset
2183 begin
kono
parents:
diff changeset
2184 if Checks and then Parent = No_Element then
kono
parents:
diff changeset
2185 raise Constraint_Error with "Parent cursor has no element";
kono
parents:
diff changeset
2186 end if;
kono
parents:
diff changeset
2187
kono
parents:
diff changeset
2188 if Checks and then Parent.Container /= Container'Unrestricted_Access then
kono
parents:
diff changeset
2189 raise Program_Error with "Parent cursor not in container";
kono
parents:
diff changeset
2190 end if;
kono
parents:
diff changeset
2191
kono
parents:
diff changeset
2192 if Count = 0 then
kono
parents:
diff changeset
2193 return;
kono
parents:
diff changeset
2194 end if;
kono
parents:
diff changeset
2195
kono
parents:
diff changeset
2196 if Checks and then Container.Count > Container.Capacity - Count then
kono
parents:
diff changeset
2197 raise Capacity_Error
kono
parents:
diff changeset
2198 with "requested count exceeds available storage";
kono
parents:
diff changeset
2199 end if;
kono
parents:
diff changeset
2200
kono
parents:
diff changeset
2201 TC_Check (Container.TC);
kono
parents:
diff changeset
2202
kono
parents:
diff changeset
2203 if Container.Count = 0 then
kono
parents:
diff changeset
2204 Initialize_Root (Container);
kono
parents:
diff changeset
2205 end if;
kono
parents:
diff changeset
2206
kono
parents:
diff changeset
2207 Allocate_Node (Container, New_Item, First);
kono
parents:
diff changeset
2208 Nodes (First).Parent := Parent.Node;
kono
parents:
diff changeset
2209
kono
parents:
diff changeset
2210 Last := First;
kono
parents:
diff changeset
2211 for J in Count_Type'(2) .. Count loop
kono
parents:
diff changeset
2212 Allocate_Node (Container, New_Item, Nodes (Last).Next);
kono
parents:
diff changeset
2213 Nodes (Nodes (Last).Next).Parent := Parent.Node;
kono
parents:
diff changeset
2214 Nodes (Nodes (Last).Next).Prev := Last;
kono
parents:
diff changeset
2215
kono
parents:
diff changeset
2216 Last := Nodes (Last).Next;
kono
parents:
diff changeset
2217 end loop;
kono
parents:
diff changeset
2218
kono
parents:
diff changeset
2219 Insert_Subtree_List
kono
parents:
diff changeset
2220 (Container => Container,
kono
parents:
diff changeset
2221 First => First,
kono
parents:
diff changeset
2222 Last => Last,
kono
parents:
diff changeset
2223 Parent => Parent.Node,
kono
parents:
diff changeset
2224 Before => Nodes (Parent.Node).Children.First);
kono
parents:
diff changeset
2225
kono
parents:
diff changeset
2226 Container.Count := Container.Count + Count;
kono
parents:
diff changeset
2227 end Prepend_Child;
kono
parents:
diff changeset
2228
kono
parents:
diff changeset
2229 --------------
kono
parents:
diff changeset
2230 -- Previous --
kono
parents:
diff changeset
2231 --------------
kono
parents:
diff changeset
2232
kono
parents:
diff changeset
2233 overriding function Previous
kono
parents:
diff changeset
2234 (Object : Child_Iterator;
kono
parents:
diff changeset
2235 Position : Cursor) return Cursor
kono
parents:
diff changeset
2236 is
kono
parents:
diff changeset
2237 begin
kono
parents:
diff changeset
2238 if Position.Container = null then
kono
parents:
diff changeset
2239 return No_Element;
kono
parents:
diff changeset
2240 end if;
kono
parents:
diff changeset
2241
kono
parents:
diff changeset
2242 if Checks and then Position.Container /= Object.Container then
kono
parents:
diff changeset
2243 raise Program_Error with
kono
parents:
diff changeset
2244 "Position cursor of Previous designates wrong tree";
kono
parents:
diff changeset
2245 end if;
kono
parents:
diff changeset
2246
kono
parents:
diff changeset
2247 return Previous_Sibling (Position);
kono
parents:
diff changeset
2248 end Previous;
kono
parents:
diff changeset
2249
kono
parents:
diff changeset
2250 ----------------------
kono
parents:
diff changeset
2251 -- Previous_Sibling --
kono
parents:
diff changeset
2252 ----------------------
kono
parents:
diff changeset
2253
kono
parents:
diff changeset
2254 function Previous_Sibling (Position : Cursor) return Cursor is
kono
parents:
diff changeset
2255 begin
kono
parents:
diff changeset
2256 if Position = No_Element then
kono
parents:
diff changeset
2257 return No_Element;
kono
parents:
diff changeset
2258 end if;
kono
parents:
diff changeset
2259
kono
parents:
diff changeset
2260 if Position.Container.Count = 0 then
kono
parents:
diff changeset
2261 pragma Assert (Is_Root (Position));
kono
parents:
diff changeset
2262 return No_Element;
kono
parents:
diff changeset
2263 end if;
kono
parents:
diff changeset
2264
kono
parents:
diff changeset
2265 declare
kono
parents:
diff changeset
2266 T : Tree renames Position.Container.all;
kono
parents:
diff changeset
2267 NN : Tree_Node_Array renames T.Nodes;
kono
parents:
diff changeset
2268 N : Tree_Node_Type renames NN (Position.Node);
kono
parents:
diff changeset
2269
kono
parents:
diff changeset
2270 begin
kono
parents:
diff changeset
2271 if N.Prev <= 0 then
kono
parents:
diff changeset
2272 return No_Element;
kono
parents:
diff changeset
2273 end if;
kono
parents:
diff changeset
2274
kono
parents:
diff changeset
2275 return Cursor'(Position.Container, N.Prev);
kono
parents:
diff changeset
2276 end;
kono
parents:
diff changeset
2277 end Previous_Sibling;
kono
parents:
diff changeset
2278
kono
parents:
diff changeset
2279 procedure Previous_Sibling (Position : in out Cursor) is
kono
parents:
diff changeset
2280 begin
kono
parents:
diff changeset
2281 Position := Previous_Sibling (Position);
kono
parents:
diff changeset
2282 end Previous_Sibling;
kono
parents:
diff changeset
2283
kono
parents:
diff changeset
2284 ----------------------
kono
parents:
diff changeset
2285 -- Pseudo_Reference --
kono
parents:
diff changeset
2286 ----------------------
kono
parents:
diff changeset
2287
kono
parents:
diff changeset
2288 function Pseudo_Reference
kono
parents:
diff changeset
2289 (Container : aliased Tree'Class) return Reference_Control_Type
kono
parents:
diff changeset
2290 is
kono
parents:
diff changeset
2291 TC : constant Tamper_Counts_Access := Container.TC'Unrestricted_Access;
kono
parents:
diff changeset
2292 begin
kono
parents:
diff changeset
2293 return R : constant Reference_Control_Type := (Controlled with TC) do
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2294 Busy (TC.all);
111
kono
parents:
diff changeset
2295 end return;
kono
parents:
diff changeset
2296 end Pseudo_Reference;
kono
parents:
diff changeset
2297
kono
parents:
diff changeset
2298 -------------------
kono
parents:
diff changeset
2299 -- Query_Element --
kono
parents:
diff changeset
2300 -------------------
kono
parents:
diff changeset
2301
kono
parents:
diff changeset
2302 procedure Query_Element
kono
parents:
diff changeset
2303 (Position : Cursor;
kono
parents:
diff changeset
2304 Process : not null access procedure (Element : Element_Type))
kono
parents:
diff changeset
2305 is
kono
parents:
diff changeset
2306 begin
kono
parents:
diff changeset
2307 if Checks and then Position = No_Element then
kono
parents:
diff changeset
2308 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
2309 end if;
kono
parents:
diff changeset
2310
kono
parents:
diff changeset
2311 if Checks and then Is_Root (Position) then
kono
parents:
diff changeset
2312 raise Program_Error with "Position cursor designates root";
kono
parents:
diff changeset
2313 end if;
kono
parents:
diff changeset
2314
kono
parents:
diff changeset
2315 declare
kono
parents:
diff changeset
2316 T : Tree renames Position.Container.all'Unrestricted_Access.all;
kono
parents:
diff changeset
2317 Lock : With_Lock (T.TC'Unrestricted_Access);
kono
parents:
diff changeset
2318 begin
kono
parents:
diff changeset
2319 Process (Element => T.Elements (Position.Node));
kono
parents:
diff changeset
2320 end;
kono
parents:
diff changeset
2321 end Query_Element;
kono
parents:
diff changeset
2322
kono
parents:
diff changeset
2323 ----------
kono
parents:
diff changeset
2324 -- Read --
kono
parents:
diff changeset
2325 ----------
kono
parents:
diff changeset
2326
kono
parents:
diff changeset
2327 procedure Read
kono
parents:
diff changeset
2328 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
2329 Container : out Tree)
kono
parents:
diff changeset
2330 is
kono
parents:
diff changeset
2331 procedure Read_Children (Subtree : Count_Type);
kono
parents:
diff changeset
2332
kono
parents:
diff changeset
2333 function Read_Subtree
kono
parents:
diff changeset
2334 (Parent : Count_Type) return Count_Type;
kono
parents:
diff changeset
2335
kono
parents:
diff changeset
2336 NN : Tree_Node_Array renames Container.Nodes;
kono
parents:
diff changeset
2337
kono
parents:
diff changeset
2338 Total_Count : Count_Type'Base;
kono
parents:
diff changeset
2339 -- Value read from the stream that says how many elements follow
kono
parents:
diff changeset
2340
kono
parents:
diff changeset
2341 Read_Count : Count_Type'Base;
kono
parents:
diff changeset
2342 -- Actual number of elements read from the stream
kono
parents:
diff changeset
2343
kono
parents:
diff changeset
2344 -------------------
kono
parents:
diff changeset
2345 -- Read_Children --
kono
parents:
diff changeset
2346 -------------------
kono
parents:
diff changeset
2347
kono
parents:
diff changeset
2348 procedure Read_Children (Subtree : Count_Type) is
kono
parents:
diff changeset
2349 Count : Count_Type'Base;
kono
parents:
diff changeset
2350 -- number of child subtrees
kono
parents:
diff changeset
2351
kono
parents:
diff changeset
2352 CC : Children_Type;
kono
parents:
diff changeset
2353
kono
parents:
diff changeset
2354 begin
kono
parents:
diff changeset
2355 Count_Type'Read (Stream, Count);
kono
parents:
diff changeset
2356
kono
parents:
diff changeset
2357 if Checks and then Count < 0 then
kono
parents:
diff changeset
2358 raise Program_Error with "attempt to read from corrupt stream";
kono
parents:
diff changeset
2359 end if;
kono
parents:
diff changeset
2360
kono
parents:
diff changeset
2361 if Count = 0 then
kono
parents:
diff changeset
2362 return;
kono
parents:
diff changeset
2363 end if;
kono
parents:
diff changeset
2364
kono
parents:
diff changeset
2365 CC.First := Read_Subtree (Parent => Subtree);
kono
parents:
diff changeset
2366 CC.Last := CC.First;
kono
parents:
diff changeset
2367
kono
parents:
diff changeset
2368 for J in Count_Type'(2) .. Count loop
kono
parents:
diff changeset
2369 NN (CC.Last).Next := Read_Subtree (Parent => Subtree);
kono
parents:
diff changeset
2370 NN (NN (CC.Last).Next).Prev := CC.Last;
kono
parents:
diff changeset
2371 CC.Last := NN (CC.Last).Next;
kono
parents:
diff changeset
2372 end loop;
kono
parents:
diff changeset
2373
kono
parents:
diff changeset
2374 -- Now that the allocation and reads have completed successfully, it
kono
parents:
diff changeset
2375 -- is safe to link the children to their parent.
kono
parents:
diff changeset
2376
kono
parents:
diff changeset
2377 NN (Subtree).Children := CC;
kono
parents:
diff changeset
2378 end Read_Children;
kono
parents:
diff changeset
2379
kono
parents:
diff changeset
2380 ------------------
kono
parents:
diff changeset
2381 -- Read_Subtree --
kono
parents:
diff changeset
2382 ------------------
kono
parents:
diff changeset
2383
kono
parents:
diff changeset
2384 function Read_Subtree
kono
parents:
diff changeset
2385 (Parent : Count_Type) return Count_Type
kono
parents:
diff changeset
2386 is
kono
parents:
diff changeset
2387 Subtree : Count_Type;
kono
parents:
diff changeset
2388
kono
parents:
diff changeset
2389 begin
kono
parents:
diff changeset
2390 Allocate_Node (Container, Stream, Subtree);
kono
parents:
diff changeset
2391 Container.Nodes (Subtree).Parent := Parent;
kono
parents:
diff changeset
2392
kono
parents:
diff changeset
2393 Read_Count := Read_Count + 1;
kono
parents:
diff changeset
2394
kono
parents:
diff changeset
2395 Read_Children (Subtree);
kono
parents:
diff changeset
2396
kono
parents:
diff changeset
2397 return Subtree;
kono
parents:
diff changeset
2398 end Read_Subtree;
kono
parents:
diff changeset
2399
kono
parents:
diff changeset
2400 -- Start of processing for Read
kono
parents:
diff changeset
2401
kono
parents:
diff changeset
2402 begin
kono
parents:
diff changeset
2403 Container.Clear; -- checks busy bit
kono
parents:
diff changeset
2404
kono
parents:
diff changeset
2405 Count_Type'Read (Stream, Total_Count);
kono
parents:
diff changeset
2406
kono
parents:
diff changeset
2407 if Checks and then Total_Count < 0 then
kono
parents:
diff changeset
2408 raise Program_Error with "attempt to read from corrupt stream";
kono
parents:
diff changeset
2409 end if;
kono
parents:
diff changeset
2410
kono
parents:
diff changeset
2411 if Total_Count = 0 then
kono
parents:
diff changeset
2412 return;
kono
parents:
diff changeset
2413 end if;
kono
parents:
diff changeset
2414
kono
parents:
diff changeset
2415 if Checks and then Total_Count > Container.Capacity then
kono
parents:
diff changeset
2416 raise Capacity_Error -- ???
kono
parents:
diff changeset
2417 with "node count in stream exceeds container capacity";
kono
parents:
diff changeset
2418 end if;
kono
parents:
diff changeset
2419
kono
parents:
diff changeset
2420 Initialize_Root (Container);
kono
parents:
diff changeset
2421
kono
parents:
diff changeset
2422 Read_Count := 0;
kono
parents:
diff changeset
2423
kono
parents:
diff changeset
2424 Read_Children (Root_Node (Container));
kono
parents:
diff changeset
2425
kono
parents:
diff changeset
2426 if Checks and then Read_Count /= Total_Count then
kono
parents:
diff changeset
2427 raise Program_Error with "attempt to read from corrupt stream";
kono
parents:
diff changeset
2428 end if;
kono
parents:
diff changeset
2429
kono
parents:
diff changeset
2430 Container.Count := Total_Count;
kono
parents:
diff changeset
2431 end Read;
kono
parents:
diff changeset
2432
kono
parents:
diff changeset
2433 procedure Read
kono
parents:
diff changeset
2434 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
2435 Position : out Cursor)
kono
parents:
diff changeset
2436 is
kono
parents:
diff changeset
2437 begin
kono
parents:
diff changeset
2438 raise Program_Error with "attempt to read tree cursor from stream";
kono
parents:
diff changeset
2439 end Read;
kono
parents:
diff changeset
2440
kono
parents:
diff changeset
2441 procedure Read
kono
parents:
diff changeset
2442 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
2443 Item : out Reference_Type)
kono
parents:
diff changeset
2444 is
kono
parents:
diff changeset
2445 begin
kono
parents:
diff changeset
2446 raise Program_Error with "attempt to stream reference";
kono
parents:
diff changeset
2447 end Read;
kono
parents:
diff changeset
2448
kono
parents:
diff changeset
2449 procedure Read
kono
parents:
diff changeset
2450 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
2451 Item : out Constant_Reference_Type)
kono
parents:
diff changeset
2452 is
kono
parents:
diff changeset
2453 begin
kono
parents:
diff changeset
2454 raise Program_Error with "attempt to stream reference";
kono
parents:
diff changeset
2455 end Read;
kono
parents:
diff changeset
2456
kono
parents:
diff changeset
2457 ---------------
kono
parents:
diff changeset
2458 -- Reference --
kono
parents:
diff changeset
2459 ---------------
kono
parents:
diff changeset
2460
kono
parents:
diff changeset
2461 function Reference
kono
parents:
diff changeset
2462 (Container : aliased in out Tree;
kono
parents:
diff changeset
2463 Position : Cursor) return Reference_Type
kono
parents:
diff changeset
2464 is
kono
parents:
diff changeset
2465 begin
kono
parents:
diff changeset
2466 if Checks and then Position.Container = null then
kono
parents:
diff changeset
2467 raise Constraint_Error with
kono
parents:
diff changeset
2468 "Position cursor has no element";
kono
parents:
diff changeset
2469 end if;
kono
parents:
diff changeset
2470
kono
parents:
diff changeset
2471 if Checks and then Position.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
2472 then
kono
parents:
diff changeset
2473 raise Program_Error with
kono
parents:
diff changeset
2474 "Position cursor designates wrong container";
kono
parents:
diff changeset
2475 end if;
kono
parents:
diff changeset
2476
kono
parents:
diff changeset
2477 if Checks and then Position.Node = Root_Node (Container) then
kono
parents:
diff changeset
2478 raise Program_Error with "Position cursor designates root";
kono
parents:
diff changeset
2479 end if;
kono
parents:
diff changeset
2480
kono
parents:
diff changeset
2481 -- Implement Vet for multiway tree???
kono
parents:
diff changeset
2482 -- pragma Assert (Vet (Position),
kono
parents:
diff changeset
2483 -- "Position cursor in Constant_Reference is bad");
kono
parents:
diff changeset
2484
kono
parents:
diff changeset
2485 declare
kono
parents:
diff changeset
2486 TC : constant Tamper_Counts_Access :=
kono
parents:
diff changeset
2487 Container.TC'Unrestricted_Access;
kono
parents:
diff changeset
2488 begin
kono
parents:
diff changeset
2489 return R : constant Reference_Type :=
kono
parents:
diff changeset
2490 (Element => Container.Elements (Position.Node)'Access,
kono
parents:
diff changeset
2491 Control => (Controlled with TC))
kono
parents:
diff changeset
2492 do
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2493 Busy (TC.all);
111
kono
parents:
diff changeset
2494 end return;
kono
parents:
diff changeset
2495 end;
kono
parents:
diff changeset
2496 end Reference;
kono
parents:
diff changeset
2497
kono
parents:
diff changeset
2498 --------------------
kono
parents:
diff changeset
2499 -- Remove_Subtree --
kono
parents:
diff changeset
2500 --------------------
kono
parents:
diff changeset
2501
kono
parents:
diff changeset
2502 procedure Remove_Subtree
kono
parents:
diff changeset
2503 (Container : in out Tree;
kono
parents:
diff changeset
2504 Subtree : Count_Type)
kono
parents:
diff changeset
2505 is
kono
parents:
diff changeset
2506 NN : Tree_Node_Array renames Container.Nodes;
kono
parents:
diff changeset
2507 N : Tree_Node_Type renames NN (Subtree);
kono
parents:
diff changeset
2508 CC : Children_Type renames NN (N.Parent).Children;
kono
parents:
diff changeset
2509
kono
parents:
diff changeset
2510 begin
kono
parents:
diff changeset
2511 -- This is a utility operation to remove a subtree node from its
kono
parents:
diff changeset
2512 -- parent's list of children.
kono
parents:
diff changeset
2513
kono
parents:
diff changeset
2514 if CC.First = Subtree then
kono
parents:
diff changeset
2515 pragma Assert (N.Prev <= 0);
kono
parents:
diff changeset
2516
kono
parents:
diff changeset
2517 if CC.Last = Subtree then
kono
parents:
diff changeset
2518 pragma Assert (N.Next <= 0);
kono
parents:
diff changeset
2519 CC.First := 0;
kono
parents:
diff changeset
2520 CC.Last := 0;
kono
parents:
diff changeset
2521
kono
parents:
diff changeset
2522 else
kono
parents:
diff changeset
2523 CC.First := N.Next;
kono
parents:
diff changeset
2524 NN (CC.First).Prev := 0;
kono
parents:
diff changeset
2525 end if;
kono
parents:
diff changeset
2526
kono
parents:
diff changeset
2527 elsif CC.Last = Subtree then
kono
parents:
diff changeset
2528 pragma Assert (N.Next <= 0);
kono
parents:
diff changeset
2529 CC.Last := N.Prev;
kono
parents:
diff changeset
2530 NN (CC.Last).Next := 0;
kono
parents:
diff changeset
2531
kono
parents:
diff changeset
2532 else
kono
parents:
diff changeset
2533 NN (N.Prev).Next := N.Next;
kono
parents:
diff changeset
2534 NN (N.Next).Prev := N.Prev;
kono
parents:
diff changeset
2535 end if;
kono
parents:
diff changeset
2536 end Remove_Subtree;
kono
parents:
diff changeset
2537
kono
parents:
diff changeset
2538 ----------------------
kono
parents:
diff changeset
2539 -- Replace_Element --
kono
parents:
diff changeset
2540 ----------------------
kono
parents:
diff changeset
2541
kono
parents:
diff changeset
2542 procedure Replace_Element
kono
parents:
diff changeset
2543 (Container : in out Tree;
kono
parents:
diff changeset
2544 Position : Cursor;
kono
parents:
diff changeset
2545 New_Item : Element_Type)
kono
parents:
diff changeset
2546 is
kono
parents:
diff changeset
2547 begin
kono
parents:
diff changeset
2548 if Checks and then Position = No_Element then
kono
parents:
diff changeset
2549 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
2550 end if;
kono
parents:
diff changeset
2551
kono
parents:
diff changeset
2552 if Checks and then Position.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
2553 then
kono
parents:
diff changeset
2554 raise Program_Error with "Position cursor not in container";
kono
parents:
diff changeset
2555 end if;
kono
parents:
diff changeset
2556
kono
parents:
diff changeset
2557 if Checks and then Is_Root (Position) then
kono
parents:
diff changeset
2558 raise Program_Error with "Position cursor designates root";
kono
parents:
diff changeset
2559 end if;
kono
parents:
diff changeset
2560
kono
parents:
diff changeset
2561 TE_Check (Container.TC);
kono
parents:
diff changeset
2562
kono
parents:
diff changeset
2563 Container.Elements (Position.Node) := New_Item;
kono
parents:
diff changeset
2564 end Replace_Element;
kono
parents:
diff changeset
2565
kono
parents:
diff changeset
2566 ------------------------------
kono
parents:
diff changeset
2567 -- Reverse_Iterate_Children --
kono
parents:
diff changeset
2568 ------------------------------
kono
parents:
diff changeset
2569
kono
parents:
diff changeset
2570 procedure Reverse_Iterate_Children
kono
parents:
diff changeset
2571 (Parent : Cursor;
kono
parents:
diff changeset
2572 Process : not null access procedure (Position : Cursor))
kono
parents:
diff changeset
2573 is
kono
parents:
diff changeset
2574 begin
kono
parents:
diff changeset
2575 if Checks and then Parent = No_Element then
kono
parents:
diff changeset
2576 raise Constraint_Error with "Parent cursor has no element";
kono
parents:
diff changeset
2577 end if;
kono
parents:
diff changeset
2578
kono
parents:
diff changeset
2579 if Parent.Container.Count = 0 then
kono
parents:
diff changeset
2580 pragma Assert (Is_Root (Parent));
kono
parents:
diff changeset
2581 return;
kono
parents:
diff changeset
2582 end if;
kono
parents:
diff changeset
2583
kono
parents:
diff changeset
2584 declare
kono
parents:
diff changeset
2585 NN : Tree_Node_Array renames Parent.Container.Nodes;
kono
parents:
diff changeset
2586 Busy : With_Busy (Parent.Container.TC'Unrestricted_Access);
kono
parents:
diff changeset
2587 C : Count_Type;
kono
parents:
diff changeset
2588
kono
parents:
diff changeset
2589 begin
kono
parents:
diff changeset
2590 C := NN (Parent.Node).Children.Last;
kono
parents:
diff changeset
2591 while C > 0 loop
kono
parents:
diff changeset
2592 Process (Cursor'(Parent.Container, Node => C));
kono
parents:
diff changeset
2593 C := NN (C).Prev;
kono
parents:
diff changeset
2594 end loop;
kono
parents:
diff changeset
2595 end;
kono
parents:
diff changeset
2596 end Reverse_Iterate_Children;
kono
parents:
diff changeset
2597
kono
parents:
diff changeset
2598 ----------
kono
parents:
diff changeset
2599 -- Root --
kono
parents:
diff changeset
2600 ----------
kono
parents:
diff changeset
2601
kono
parents:
diff changeset
2602 function Root (Container : Tree) return Cursor is
kono
parents:
diff changeset
2603 begin
kono
parents:
diff changeset
2604 return (Container'Unrestricted_Access, Root_Node (Container));
kono
parents:
diff changeset
2605 end Root;
kono
parents:
diff changeset
2606
kono
parents:
diff changeset
2607 ---------------
kono
parents:
diff changeset
2608 -- Root_Node --
kono
parents:
diff changeset
2609 ---------------
kono
parents:
diff changeset
2610
kono
parents:
diff changeset
2611 function Root_Node (Container : Tree) return Count_Type is
kono
parents:
diff changeset
2612 pragma Unreferenced (Container);
kono
parents:
diff changeset
2613
kono
parents:
diff changeset
2614 begin
kono
parents:
diff changeset
2615 return 0;
kono
parents:
diff changeset
2616 end Root_Node;
kono
parents:
diff changeset
2617
kono
parents:
diff changeset
2618 ---------------------
kono
parents:
diff changeset
2619 -- Splice_Children --
kono
parents:
diff changeset
2620 ---------------------
kono
parents:
diff changeset
2621
kono
parents:
diff changeset
2622 procedure Splice_Children
kono
parents:
diff changeset
2623 (Target : in out Tree;
kono
parents:
diff changeset
2624 Target_Parent : Cursor;
kono
parents:
diff changeset
2625 Before : Cursor;
kono
parents:
diff changeset
2626 Source : in out Tree;
kono
parents:
diff changeset
2627 Source_Parent : Cursor)
kono
parents:
diff changeset
2628 is
kono
parents:
diff changeset
2629 begin
kono
parents:
diff changeset
2630 if Checks and then Target_Parent = No_Element then
kono
parents:
diff changeset
2631 raise Constraint_Error with "Target_Parent cursor has no element";
kono
parents:
diff changeset
2632 end if;
kono
parents:
diff changeset
2633
kono
parents:
diff changeset
2634 if Checks and then Target_Parent.Container /= Target'Unrestricted_Access
kono
parents:
diff changeset
2635 then
kono
parents:
diff changeset
2636 raise Program_Error
kono
parents:
diff changeset
2637 with "Target_Parent cursor not in Target container";
kono
parents:
diff changeset
2638 end if;
kono
parents:
diff changeset
2639
kono
parents:
diff changeset
2640 if Before /= No_Element then
kono
parents:
diff changeset
2641 if Checks and then Before.Container /= Target'Unrestricted_Access then
kono
parents:
diff changeset
2642 raise Program_Error
kono
parents:
diff changeset
2643 with "Before cursor not in Target container";
kono
parents:
diff changeset
2644 end if;
kono
parents:
diff changeset
2645
kono
parents:
diff changeset
2646 if Checks and then
kono
parents:
diff changeset
2647 Target.Nodes (Before.Node).Parent /= Target_Parent.Node
kono
parents:
diff changeset
2648 then
kono
parents:
diff changeset
2649 raise Constraint_Error
kono
parents:
diff changeset
2650 with "Before cursor not child of Target_Parent";
kono
parents:
diff changeset
2651 end if;
kono
parents:
diff changeset
2652 end if;
kono
parents:
diff changeset
2653
kono
parents:
diff changeset
2654 if Checks and then Source_Parent = No_Element then
kono
parents:
diff changeset
2655 raise Constraint_Error with "Source_Parent cursor has no element";
kono
parents:
diff changeset
2656 end if;
kono
parents:
diff changeset
2657
kono
parents:
diff changeset
2658 if Checks and then Source_Parent.Container /= Source'Unrestricted_Access
kono
parents:
diff changeset
2659 then
kono
parents:
diff changeset
2660 raise Program_Error
kono
parents:
diff changeset
2661 with "Source_Parent cursor not in Source container";
kono
parents:
diff changeset
2662 end if;
kono
parents:
diff changeset
2663
kono
parents:
diff changeset
2664 if Source.Count = 0 then
kono
parents:
diff changeset
2665 pragma Assert (Is_Root (Source_Parent));
kono
parents:
diff changeset
2666 return;
kono
parents:
diff changeset
2667 end if;
kono
parents:
diff changeset
2668
kono
parents:
diff changeset
2669 if Target'Address = Source'Address then
kono
parents:
diff changeset
2670 if Target_Parent = Source_Parent then
kono
parents:
diff changeset
2671 return;
kono
parents:
diff changeset
2672 end if;
kono
parents:
diff changeset
2673
kono
parents:
diff changeset
2674 TC_Check (Target.TC);
kono
parents:
diff changeset
2675
kono
parents:
diff changeset
2676 if Checks and then Is_Reachable (Container => Target,
kono
parents:
diff changeset
2677 From => Target_Parent.Node,
kono
parents:
diff changeset
2678 To => Source_Parent.Node)
kono
parents:
diff changeset
2679 then
kono
parents:
diff changeset
2680 raise Constraint_Error
kono
parents:
diff changeset
2681 with "Source_Parent is ancestor of Target_Parent";
kono
parents:
diff changeset
2682 end if;
kono
parents:
diff changeset
2683
kono
parents:
diff changeset
2684 Splice_Children
kono
parents:
diff changeset
2685 (Container => Target,
kono
parents:
diff changeset
2686 Target_Parent => Target_Parent.Node,
kono
parents:
diff changeset
2687 Before => Before.Node,
kono
parents:
diff changeset
2688 Source_Parent => Source_Parent.Node);
kono
parents:
diff changeset
2689
kono
parents:
diff changeset
2690 return;
kono
parents:
diff changeset
2691 end if;
kono
parents:
diff changeset
2692
kono
parents:
diff changeset
2693 TC_Check (Target.TC);
kono
parents:
diff changeset
2694 TC_Check (Source.TC);
kono
parents:
diff changeset
2695
kono
parents:
diff changeset
2696 if Target.Count = 0 then
kono
parents:
diff changeset
2697 Initialize_Root (Target);
kono
parents:
diff changeset
2698 end if;
kono
parents:
diff changeset
2699
kono
parents:
diff changeset
2700 Splice_Children
kono
parents:
diff changeset
2701 (Target => Target,
kono
parents:
diff changeset
2702 Target_Parent => Target_Parent.Node,
kono
parents:
diff changeset
2703 Before => Before.Node,
kono
parents:
diff changeset
2704 Source => Source,
kono
parents:
diff changeset
2705 Source_Parent => Source_Parent.Node);
kono
parents:
diff changeset
2706 end Splice_Children;
kono
parents:
diff changeset
2707
kono
parents:
diff changeset
2708 procedure Splice_Children
kono
parents:
diff changeset
2709 (Container : in out Tree;
kono
parents:
diff changeset
2710 Target_Parent : Cursor;
kono
parents:
diff changeset
2711 Before : Cursor;
kono
parents:
diff changeset
2712 Source_Parent : Cursor)
kono
parents:
diff changeset
2713 is
kono
parents:
diff changeset
2714 begin
kono
parents:
diff changeset
2715 if Checks and then Target_Parent = No_Element then
kono
parents:
diff changeset
2716 raise Constraint_Error with "Target_Parent cursor has no element";
kono
parents:
diff changeset
2717 end if;
kono
parents:
diff changeset
2718
kono
parents:
diff changeset
2719 if Checks and then
kono
parents:
diff changeset
2720 Target_Parent.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
2721 then
kono
parents:
diff changeset
2722 raise Program_Error
kono
parents:
diff changeset
2723 with "Target_Parent cursor not in container";
kono
parents:
diff changeset
2724 end if;
kono
parents:
diff changeset
2725
kono
parents:
diff changeset
2726 if Before /= No_Element then
kono
parents:
diff changeset
2727 if Checks and then Before.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
2728 then
kono
parents:
diff changeset
2729 raise Program_Error
kono
parents:
diff changeset
2730 with "Before cursor not in container";
kono
parents:
diff changeset
2731 end if;
kono
parents:
diff changeset
2732
kono
parents:
diff changeset
2733 if Checks and then
kono
parents:
diff changeset
2734 Container.Nodes (Before.Node).Parent /= Target_Parent.Node
kono
parents:
diff changeset
2735 then
kono
parents:
diff changeset
2736 raise Constraint_Error
kono
parents:
diff changeset
2737 with "Before cursor not child of Target_Parent";
kono
parents:
diff changeset
2738 end if;
kono
parents:
diff changeset
2739 end if;
kono
parents:
diff changeset
2740
kono
parents:
diff changeset
2741 if Checks and then Source_Parent = No_Element then
kono
parents:
diff changeset
2742 raise Constraint_Error with "Source_Parent cursor has no element";
kono
parents:
diff changeset
2743 end if;
kono
parents:
diff changeset
2744
kono
parents:
diff changeset
2745 if Checks and then
kono
parents:
diff changeset
2746 Source_Parent.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
2747 then
kono
parents:
diff changeset
2748 raise Program_Error
kono
parents:
diff changeset
2749 with "Source_Parent cursor not in container";
kono
parents:
diff changeset
2750 end if;
kono
parents:
diff changeset
2751
kono
parents:
diff changeset
2752 if Target_Parent = Source_Parent then
kono
parents:
diff changeset
2753 return;
kono
parents:
diff changeset
2754 end if;
kono
parents:
diff changeset
2755
kono
parents:
diff changeset
2756 pragma Assert (Container.Count > 0);
kono
parents:
diff changeset
2757
kono
parents:
diff changeset
2758 TC_Check (Container.TC);
kono
parents:
diff changeset
2759
kono
parents:
diff changeset
2760 if Checks and then Is_Reachable (Container => Container,
kono
parents:
diff changeset
2761 From => Target_Parent.Node,
kono
parents:
diff changeset
2762 To => Source_Parent.Node)
kono
parents:
diff changeset
2763 then
kono
parents:
diff changeset
2764 raise Constraint_Error
kono
parents:
diff changeset
2765 with "Source_Parent is ancestor of Target_Parent";
kono
parents:
diff changeset
2766 end if;
kono
parents:
diff changeset
2767
kono
parents:
diff changeset
2768 Splice_Children
kono
parents:
diff changeset
2769 (Container => Container,
kono
parents:
diff changeset
2770 Target_Parent => Target_Parent.Node,
kono
parents:
diff changeset
2771 Before => Before.Node,
kono
parents:
diff changeset
2772 Source_Parent => Source_Parent.Node);
kono
parents:
diff changeset
2773 end Splice_Children;
kono
parents:
diff changeset
2774
kono
parents:
diff changeset
2775 procedure Splice_Children
kono
parents:
diff changeset
2776 (Container : in out Tree;
kono
parents:
diff changeset
2777 Target_Parent : Count_Type;
kono
parents:
diff changeset
2778 Before : Count_Type'Base;
kono
parents:
diff changeset
2779 Source_Parent : Count_Type)
kono
parents:
diff changeset
2780 is
kono
parents:
diff changeset
2781 NN : Tree_Node_Array renames Container.Nodes;
kono
parents:
diff changeset
2782 CC : constant Children_Type := NN (Source_Parent).Children;
kono
parents:
diff changeset
2783 C : Count_Type'Base;
kono
parents:
diff changeset
2784
kono
parents:
diff changeset
2785 begin
kono
parents:
diff changeset
2786 -- This is a utility operation to remove the children from Source parent
kono
parents:
diff changeset
2787 -- and insert them into Target parent.
kono
parents:
diff changeset
2788
kono
parents:
diff changeset
2789 NN (Source_Parent).Children := Children_Type'(others => 0);
kono
parents:
diff changeset
2790
kono
parents:
diff changeset
2791 -- Fix up the Parent pointers of each child to designate its new Target
kono
parents:
diff changeset
2792 -- parent.
kono
parents:
diff changeset
2793
kono
parents:
diff changeset
2794 C := CC.First;
kono
parents:
diff changeset
2795 while C > 0 loop
kono
parents:
diff changeset
2796 NN (C).Parent := Target_Parent;
kono
parents:
diff changeset
2797 C := NN (C).Next;
kono
parents:
diff changeset
2798 end loop;
kono
parents:
diff changeset
2799
kono
parents:
diff changeset
2800 Insert_Subtree_List
kono
parents:
diff changeset
2801 (Container => Container,
kono
parents:
diff changeset
2802 First => CC.First,
kono
parents:
diff changeset
2803 Last => CC.Last,
kono
parents:
diff changeset
2804 Parent => Target_Parent,
kono
parents:
diff changeset
2805 Before => Before);
kono
parents:
diff changeset
2806 end Splice_Children;
kono
parents:
diff changeset
2807
kono
parents:
diff changeset
2808 procedure Splice_Children
kono
parents:
diff changeset
2809 (Target : in out Tree;
kono
parents:
diff changeset
2810 Target_Parent : Count_Type;
kono
parents:
diff changeset
2811 Before : Count_Type'Base;
kono
parents:
diff changeset
2812 Source : in out Tree;
kono
parents:
diff changeset
2813 Source_Parent : Count_Type)
kono
parents:
diff changeset
2814 is
kono
parents:
diff changeset
2815 S_NN : Tree_Node_Array renames Source.Nodes;
kono
parents:
diff changeset
2816 S_CC : Children_Type renames S_NN (Source_Parent).Children;
kono
parents:
diff changeset
2817
kono
parents:
diff changeset
2818 Target_Count, Source_Count : Count_Type;
kono
parents:
diff changeset
2819 T, S : Count_Type'Base;
kono
parents:
diff changeset
2820
kono
parents:
diff changeset
2821 begin
kono
parents:
diff changeset
2822 -- This is a utility operation to copy the children from the Source
kono
parents:
diff changeset
2823 -- parent and insert them as children of the Target parent, and then
kono
parents:
diff changeset
2824 -- delete them from the Source. (This is not a true splice operation,
kono
parents:
diff changeset
2825 -- but it is the best we can do in a bounded form.) The Before position
kono
parents:
diff changeset
2826 -- specifies where among the Target parent's exising children the new
kono
parents:
diff changeset
2827 -- children are inserted.
kono
parents:
diff changeset
2828
kono
parents:
diff changeset
2829 -- Before we attempt the insertion, we must count the sources nodes in
kono
parents:
diff changeset
2830 -- order to determine whether the target have enough storage
kono
parents:
diff changeset
2831 -- available. Note that calculating this value is an O(n) operation.
kono
parents:
diff changeset
2832
kono
parents:
diff changeset
2833 -- Here is an optimization opportunity: iterate of each children the
kono
parents:
diff changeset
2834 -- source explicitly, and keep a running count of the total number of
kono
parents:
diff changeset
2835 -- nodes. Compare the running total to the capacity of the target each
kono
parents:
diff changeset
2836 -- pass through the loop. This is more efficient than summing the counts
kono
parents:
diff changeset
2837 -- of child subtree (which is what Subtree_Node_Count does) and then
kono
parents:
diff changeset
2838 -- comparing that total sum to the target's capacity. ???
kono
parents:
diff changeset
2839
kono
parents:
diff changeset
2840 -- Here is another possibility. We currently treat the splice as an
kono
parents:
diff changeset
2841 -- all-or-nothing proposition: either we can insert all of children of
kono
parents:
diff changeset
2842 -- the source, or we raise exception with modifying the target. The
kono
parents:
diff changeset
2843 -- price for not causing side-effect is an O(n) determination of the
kono
parents:
diff changeset
2844 -- source count. If we are willing to tolerate side-effect, then we
kono
parents:
diff changeset
2845 -- could loop over the children of the source, counting that subtree and
kono
parents:
diff changeset
2846 -- then immediately inserting it in the target. The issue here is that
kono
parents:
diff changeset
2847 -- the test for available storage could fail during some later pass,
kono
parents:
diff changeset
2848 -- after children have already been inserted into target. ???
kono
parents:
diff changeset
2849
kono
parents:
diff changeset
2850 Source_Count := Subtree_Node_Count (Source, Source_Parent) - 1;
kono
parents:
diff changeset
2851
kono
parents:
diff changeset
2852 if Source_Count = 0 then
kono
parents:
diff changeset
2853 return;
kono
parents:
diff changeset
2854 end if;
kono
parents:
diff changeset
2855
kono
parents:
diff changeset
2856 if Checks and then Target.Count > Target.Capacity - Source_Count then
kono
parents:
diff changeset
2857 raise Capacity_Error -- ???
kono
parents:
diff changeset
2858 with "Source count exceeds available storage on Target";
kono
parents:
diff changeset
2859 end if;
kono
parents:
diff changeset
2860
kono
parents:
diff changeset
2861 -- Copy_Subtree returns a count of the number of nodes it inserts, but
kono
parents:
diff changeset
2862 -- it does this by incrementing the value passed in. Therefore we must
kono
parents:
diff changeset
2863 -- initialize the count before calling Copy_Subtree.
kono
parents:
diff changeset
2864
kono
parents:
diff changeset
2865 Target_Count := 0;
kono
parents:
diff changeset
2866
kono
parents:
diff changeset
2867 S := S_CC.First;
kono
parents:
diff changeset
2868 while S > 0 loop
kono
parents:
diff changeset
2869 Copy_Subtree
kono
parents:
diff changeset
2870 (Source => Source,
kono
parents:
diff changeset
2871 Source_Subtree => S,
kono
parents:
diff changeset
2872 Target => Target,
kono
parents:
diff changeset
2873 Target_Parent => Target_Parent,
kono
parents:
diff changeset
2874 Target_Subtree => T,
kono
parents:
diff changeset
2875 Count => Target_Count);
kono
parents:
diff changeset
2876
kono
parents:
diff changeset
2877 Insert_Subtree_Node
kono
parents:
diff changeset
2878 (Container => Target,
kono
parents:
diff changeset
2879 Subtree => T,
kono
parents:
diff changeset
2880 Parent => Target_Parent,
kono
parents:
diff changeset
2881 Before => Before);
kono
parents:
diff changeset
2882
kono
parents:
diff changeset
2883 S := S_NN (S).Next;
kono
parents:
diff changeset
2884 end loop;
kono
parents:
diff changeset
2885
kono
parents:
diff changeset
2886 pragma Assert (Target_Count = Source_Count);
kono
parents:
diff changeset
2887 Target.Count := Target.Count + Target_Count;
kono
parents:
diff changeset
2888
kono
parents:
diff changeset
2889 -- As with Copy_Subtree, operation Deallocate_Children returns a count
kono
parents:
diff changeset
2890 -- of the number of nodes it deallocates, but it works by incrementing
kono
parents:
diff changeset
2891 -- the value passed in. We must therefore initialize the count before
kono
parents:
diff changeset
2892 -- calling it.
kono
parents:
diff changeset
2893
kono
parents:
diff changeset
2894 Source_Count := 0;
kono
parents:
diff changeset
2895
kono
parents:
diff changeset
2896 Deallocate_Children (Source, Source_Parent, Source_Count);
kono
parents:
diff changeset
2897 pragma Assert (Source_Count = Target_Count);
kono
parents:
diff changeset
2898
kono
parents:
diff changeset
2899 Source.Count := Source.Count - Source_Count;
kono
parents:
diff changeset
2900 end Splice_Children;
kono
parents:
diff changeset
2901
kono
parents:
diff changeset
2902 --------------------
kono
parents:
diff changeset
2903 -- Splice_Subtree --
kono
parents:
diff changeset
2904 --------------------
kono
parents:
diff changeset
2905
kono
parents:
diff changeset
2906 procedure Splice_Subtree
kono
parents:
diff changeset
2907 (Target : in out Tree;
kono
parents:
diff changeset
2908 Parent : Cursor;
kono
parents:
diff changeset
2909 Before : Cursor;
kono
parents:
diff changeset
2910 Source : in out Tree;
kono
parents:
diff changeset
2911 Position : in out Cursor)
kono
parents:
diff changeset
2912 is
kono
parents:
diff changeset
2913 begin
kono
parents:
diff changeset
2914 if Checks and then Parent = No_Element then
kono
parents:
diff changeset
2915 raise Constraint_Error with "Parent cursor has no element";
kono
parents:
diff changeset
2916 end if;
kono
parents:
diff changeset
2917
kono
parents:
diff changeset
2918 if Checks and then Parent.Container /= Target'Unrestricted_Access then
kono
parents:
diff changeset
2919 raise Program_Error with "Parent cursor not in Target container";
kono
parents:
diff changeset
2920 end if;
kono
parents:
diff changeset
2921
kono
parents:
diff changeset
2922 if Before /= No_Element then
kono
parents:
diff changeset
2923 if Checks and then Before.Container /= Target'Unrestricted_Access then
kono
parents:
diff changeset
2924 raise Program_Error with "Before cursor not in Target container";
kono
parents:
diff changeset
2925 end if;
kono
parents:
diff changeset
2926
kono
parents:
diff changeset
2927 if Checks and then Target.Nodes (Before.Node).Parent /= Parent.Node
kono
parents:
diff changeset
2928 then
kono
parents:
diff changeset
2929 raise Constraint_Error with "Before cursor not child of Parent";
kono
parents:
diff changeset
2930 end if;
kono
parents:
diff changeset
2931 end if;
kono
parents:
diff changeset
2932
kono
parents:
diff changeset
2933 if Checks and then Position = No_Element then
kono
parents:
diff changeset
2934 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
2935 end if;
kono
parents:
diff changeset
2936
kono
parents:
diff changeset
2937 if Checks and then Position.Container /= Source'Unrestricted_Access then
kono
parents:
diff changeset
2938 raise Program_Error with "Position cursor not in Source container";
kono
parents:
diff changeset
2939 end if;
kono
parents:
diff changeset
2940
kono
parents:
diff changeset
2941 if Checks and then Is_Root (Position) then
kono
parents:
diff changeset
2942 raise Program_Error with "Position cursor designates root";
kono
parents:
diff changeset
2943 end if;
kono
parents:
diff changeset
2944
kono
parents:
diff changeset
2945 if Target'Address = Source'Address then
kono
parents:
diff changeset
2946 if Target.Nodes (Position.Node).Parent = Parent.Node then
kono
parents:
diff changeset
2947 if Before = No_Element then
kono
parents:
diff changeset
2948 if Target.Nodes (Position.Node).Next <= 0 then -- last child
kono
parents:
diff changeset
2949 return;
kono
parents:
diff changeset
2950 end if;
kono
parents:
diff changeset
2951
kono
parents:
diff changeset
2952 elsif Position.Node = Before.Node then
kono
parents:
diff changeset
2953 return;
kono
parents:
diff changeset
2954
kono
parents:
diff changeset
2955 elsif Target.Nodes (Position.Node).Next = Before.Node then
kono
parents:
diff changeset
2956 return;
kono
parents:
diff changeset
2957 end if;
kono
parents:
diff changeset
2958 end if;
kono
parents:
diff changeset
2959
kono
parents:
diff changeset
2960 TC_Check (Target.TC);
kono
parents:
diff changeset
2961
kono
parents:
diff changeset
2962 if Checks and then Is_Reachable (Container => Target,
kono
parents:
diff changeset
2963 From => Parent.Node,
kono
parents:
diff changeset
2964 To => Position.Node)
kono
parents:
diff changeset
2965 then
kono
parents:
diff changeset
2966 raise Constraint_Error with "Position is ancestor of Parent";
kono
parents:
diff changeset
2967 end if;
kono
parents:
diff changeset
2968
kono
parents:
diff changeset
2969 Remove_Subtree (Target, Position.Node);
kono
parents:
diff changeset
2970
kono
parents:
diff changeset
2971 Target.Nodes (Position.Node).Parent := Parent.Node;
kono
parents:
diff changeset
2972 Insert_Subtree_Node (Target, Position.Node, Parent.Node, Before.Node);
kono
parents:
diff changeset
2973
kono
parents:
diff changeset
2974 return;
kono
parents:
diff changeset
2975 end if;
kono
parents:
diff changeset
2976
kono
parents:
diff changeset
2977 TC_Check (Target.TC);
kono
parents:
diff changeset
2978 TC_Check (Source.TC);
kono
parents:
diff changeset
2979
kono
parents:
diff changeset
2980 if Target.Count = 0 then
kono
parents:
diff changeset
2981 Initialize_Root (Target);
kono
parents:
diff changeset
2982 end if;
kono
parents:
diff changeset
2983
kono
parents:
diff changeset
2984 Splice_Subtree
kono
parents:
diff changeset
2985 (Target => Target,
kono
parents:
diff changeset
2986 Parent => Parent.Node,
kono
parents:
diff changeset
2987 Before => Before.Node,
kono
parents:
diff changeset
2988 Source => Source,
kono
parents:
diff changeset
2989 Position => Position.Node); -- modified during call
kono
parents:
diff changeset
2990
kono
parents:
diff changeset
2991 Position.Container := Target'Unrestricted_Access;
kono
parents:
diff changeset
2992 end Splice_Subtree;
kono
parents:
diff changeset
2993
kono
parents:
diff changeset
2994 procedure Splice_Subtree
kono
parents:
diff changeset
2995 (Container : in out Tree;
kono
parents:
diff changeset
2996 Parent : Cursor;
kono
parents:
diff changeset
2997 Before : Cursor;
kono
parents:
diff changeset
2998 Position : Cursor)
kono
parents:
diff changeset
2999 is
kono
parents:
diff changeset
3000 begin
kono
parents:
diff changeset
3001 if Checks and then Parent = No_Element then
kono
parents:
diff changeset
3002 raise Constraint_Error with "Parent cursor has no element";
kono
parents:
diff changeset
3003 end if;
kono
parents:
diff changeset
3004
kono
parents:
diff changeset
3005 if Checks and then Parent.Container /= Container'Unrestricted_Access then
kono
parents:
diff changeset
3006 raise Program_Error with "Parent cursor not in container";
kono
parents:
diff changeset
3007 end if;
kono
parents:
diff changeset
3008
kono
parents:
diff changeset
3009 if Before /= No_Element then
kono
parents:
diff changeset
3010 if Checks and then Before.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
3011 then
kono
parents:
diff changeset
3012 raise Program_Error with "Before cursor not in container";
kono
parents:
diff changeset
3013 end if;
kono
parents:
diff changeset
3014
kono
parents:
diff changeset
3015 if Checks and then Container.Nodes (Before.Node).Parent /= Parent.Node
kono
parents:
diff changeset
3016 then
kono
parents:
diff changeset
3017 raise Constraint_Error with "Before cursor not child of Parent";
kono
parents:
diff changeset
3018 end if;
kono
parents:
diff changeset
3019 end if;
kono
parents:
diff changeset
3020
kono
parents:
diff changeset
3021 if Checks and then Position = No_Element then
kono
parents:
diff changeset
3022 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
3023 end if;
kono
parents:
diff changeset
3024
kono
parents:
diff changeset
3025 if Checks and then Position.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
3026 then
kono
parents:
diff changeset
3027 raise Program_Error with "Position cursor not in container";
kono
parents:
diff changeset
3028 end if;
kono
parents:
diff changeset
3029
kono
parents:
diff changeset
3030 if Checks and then Is_Root (Position) then
kono
parents:
diff changeset
3031
kono
parents:
diff changeset
3032 -- Should this be PE instead? Need ARG confirmation. ???
kono
parents:
diff changeset
3033
kono
parents:
diff changeset
3034 raise Constraint_Error with "Position cursor designates root";
kono
parents:
diff changeset
3035 end if;
kono
parents:
diff changeset
3036
kono
parents:
diff changeset
3037 if Container.Nodes (Position.Node).Parent = Parent.Node then
kono
parents:
diff changeset
3038 if Before = No_Element then
kono
parents:
diff changeset
3039 if Container.Nodes (Position.Node).Next <= 0 then -- last child
kono
parents:
diff changeset
3040 return;
kono
parents:
diff changeset
3041 end if;
kono
parents:
diff changeset
3042
kono
parents:
diff changeset
3043 elsif Position.Node = Before.Node then
kono
parents:
diff changeset
3044 return;
kono
parents:
diff changeset
3045
kono
parents:
diff changeset
3046 elsif Container.Nodes (Position.Node).Next = Before.Node then
kono
parents:
diff changeset
3047 return;
kono
parents:
diff changeset
3048 end if;
kono
parents:
diff changeset
3049 end if;
kono
parents:
diff changeset
3050
kono
parents:
diff changeset
3051 TC_Check (Container.TC);
kono
parents:
diff changeset
3052
kono
parents:
diff changeset
3053 if Checks and then Is_Reachable (Container => Container,
kono
parents:
diff changeset
3054 From => Parent.Node,
kono
parents:
diff changeset
3055 To => Position.Node)
kono
parents:
diff changeset
3056 then
kono
parents:
diff changeset
3057 raise Constraint_Error with "Position is ancestor of Parent";
kono
parents:
diff changeset
3058 end if;
kono
parents:
diff changeset
3059
kono
parents:
diff changeset
3060 Remove_Subtree (Container, Position.Node);
kono
parents:
diff changeset
3061 Container.Nodes (Position.Node).Parent := Parent.Node;
kono
parents:
diff changeset
3062 Insert_Subtree_Node (Container, Position.Node, Parent.Node, Before.Node);
kono
parents:
diff changeset
3063 end Splice_Subtree;
kono
parents:
diff changeset
3064
kono
parents:
diff changeset
3065 procedure Splice_Subtree
kono
parents:
diff changeset
3066 (Target : in out Tree;
kono
parents:
diff changeset
3067 Parent : Count_Type;
kono
parents:
diff changeset
3068 Before : Count_Type'Base;
kono
parents:
diff changeset
3069 Source : in out Tree;
kono
parents:
diff changeset
3070 Position : in out Count_Type) -- Source on input, Target on output
kono
parents:
diff changeset
3071 is
kono
parents:
diff changeset
3072 Source_Count : Count_Type := Subtree_Node_Count (Source, Position);
kono
parents:
diff changeset
3073 pragma Assert (Source_Count >= 1);
kono
parents:
diff changeset
3074
kono
parents:
diff changeset
3075 Target_Subtree : Count_Type;
kono
parents:
diff changeset
3076 Target_Count : Count_Type;
kono
parents:
diff changeset
3077
kono
parents:
diff changeset
3078 begin
kono
parents:
diff changeset
3079 -- This is a utility operation to do the heavy lifting associated with
kono
parents:
diff changeset
3080 -- splicing a subtree from one tree to another. Note that "splicing"
kono
parents:
diff changeset
3081 -- is a bit of a misnomer here in the case of a bounded tree, because
kono
parents:
diff changeset
3082 -- the elements must be copied from the source to the target.
kono
parents:
diff changeset
3083
kono
parents:
diff changeset
3084 if Checks and then Target.Count > Target.Capacity - Source_Count then
kono
parents:
diff changeset
3085 raise Capacity_Error -- ???
kono
parents:
diff changeset
3086 with "Source count exceeds available storage on Target";
kono
parents:
diff changeset
3087 end if;
kono
parents:
diff changeset
3088
kono
parents:
diff changeset
3089 -- Copy_Subtree returns a count of the number of nodes it inserts, but
kono
parents:
diff changeset
3090 -- it does this by incrementing the value passed in. Therefore we must
kono
parents:
diff changeset
3091 -- initialize the count before calling Copy_Subtree.
kono
parents:
diff changeset
3092
kono
parents:
diff changeset
3093 Target_Count := 0;
kono
parents:
diff changeset
3094
kono
parents:
diff changeset
3095 Copy_Subtree
kono
parents:
diff changeset
3096 (Source => Source,
kono
parents:
diff changeset
3097 Source_Subtree => Position,
kono
parents:
diff changeset
3098 Target => Target,
kono
parents:
diff changeset
3099 Target_Parent => Parent,
kono
parents:
diff changeset
3100 Target_Subtree => Target_Subtree,
kono
parents:
diff changeset
3101 Count => Target_Count);
kono
parents:
diff changeset
3102
kono
parents:
diff changeset
3103 pragma Assert (Target_Count = Source_Count);
kono
parents:
diff changeset
3104
kono
parents:
diff changeset
3105 -- Now link the newly-allocated subtree into the target.
kono
parents:
diff changeset
3106
kono
parents:
diff changeset
3107 Insert_Subtree_Node
kono
parents:
diff changeset
3108 (Container => Target,
kono
parents:
diff changeset
3109 Subtree => Target_Subtree,
kono
parents:
diff changeset
3110 Parent => Parent,
kono
parents:
diff changeset
3111 Before => Before);
kono
parents:
diff changeset
3112
kono
parents:
diff changeset
3113 Target.Count := Target.Count + Target_Count;
kono
parents:
diff changeset
3114
kono
parents:
diff changeset
3115 -- The manipulation of the Target container is complete. Now we remove
kono
parents:
diff changeset
3116 -- the subtree from the Source container.
kono
parents:
diff changeset
3117
kono
parents:
diff changeset
3118 Remove_Subtree (Source, Position); -- unlink the subtree
kono
parents:
diff changeset
3119
kono
parents:
diff changeset
3120 -- As with Copy_Subtree, operation Deallocate_Subtree returns a count of
kono
parents:
diff changeset
3121 -- the number of nodes it deallocates, but it works by incrementing the
kono
parents:
diff changeset
3122 -- value passed in. We must therefore initialize the count before
kono
parents:
diff changeset
3123 -- calling it.
kono
parents:
diff changeset
3124
kono
parents:
diff changeset
3125 Source_Count := 0;
kono
parents:
diff changeset
3126
kono
parents:
diff changeset
3127 Deallocate_Subtree (Source, Position, Source_Count);
kono
parents:
diff changeset
3128 pragma Assert (Source_Count = Target_Count);
kono
parents:
diff changeset
3129
kono
parents:
diff changeset
3130 Source.Count := Source.Count - Source_Count;
kono
parents:
diff changeset
3131
kono
parents:
diff changeset
3132 Position := Target_Subtree;
kono
parents:
diff changeset
3133 end Splice_Subtree;
kono
parents:
diff changeset
3134
kono
parents:
diff changeset
3135 ------------------------
kono
parents:
diff changeset
3136 -- Subtree_Node_Count --
kono
parents:
diff changeset
3137 ------------------------
kono
parents:
diff changeset
3138
kono
parents:
diff changeset
3139 function Subtree_Node_Count (Position : Cursor) return Count_Type is
kono
parents:
diff changeset
3140 begin
kono
parents:
diff changeset
3141 if Position = No_Element then
kono
parents:
diff changeset
3142 return 0;
kono
parents:
diff changeset
3143 end if;
kono
parents:
diff changeset
3144
kono
parents:
diff changeset
3145 if Position.Container.Count = 0 then
kono
parents:
diff changeset
3146 pragma Assert (Is_Root (Position));
kono
parents:
diff changeset
3147 return 1;
kono
parents:
diff changeset
3148 end if;
kono
parents:
diff changeset
3149
kono
parents:
diff changeset
3150 return Subtree_Node_Count (Position.Container.all, Position.Node);
kono
parents:
diff changeset
3151 end Subtree_Node_Count;
kono
parents:
diff changeset
3152
kono
parents:
diff changeset
3153 function Subtree_Node_Count
kono
parents:
diff changeset
3154 (Container : Tree;
kono
parents:
diff changeset
3155 Subtree : Count_Type) return Count_Type
kono
parents:
diff changeset
3156 is
kono
parents:
diff changeset
3157 Result : Count_Type;
kono
parents:
diff changeset
3158 Node : Count_Type'Base;
kono
parents:
diff changeset
3159
kono
parents:
diff changeset
3160 begin
kono
parents:
diff changeset
3161 Result := 1;
kono
parents:
diff changeset
3162 Node := Container.Nodes (Subtree).Children.First;
kono
parents:
diff changeset
3163 while Node > 0 loop
kono
parents:
diff changeset
3164 Result := Result + Subtree_Node_Count (Container, Node);
kono
parents:
diff changeset
3165 Node := Container.Nodes (Node).Next;
kono
parents:
diff changeset
3166 end loop;
kono
parents:
diff changeset
3167 return Result;
kono
parents:
diff changeset
3168 end Subtree_Node_Count;
kono
parents:
diff changeset
3169
kono
parents:
diff changeset
3170 ----------
kono
parents:
diff changeset
3171 -- Swap --
kono
parents:
diff changeset
3172 ----------
kono
parents:
diff changeset
3173
kono
parents:
diff changeset
3174 procedure Swap
kono
parents:
diff changeset
3175 (Container : in out Tree;
kono
parents:
diff changeset
3176 I, J : Cursor)
kono
parents:
diff changeset
3177 is
kono
parents:
diff changeset
3178 begin
kono
parents:
diff changeset
3179 if Checks and then I = No_Element then
kono
parents:
diff changeset
3180 raise Constraint_Error with "I cursor has no element";
kono
parents:
diff changeset
3181 end if;
kono
parents:
diff changeset
3182
kono
parents:
diff changeset
3183 if Checks and then I.Container /= Container'Unrestricted_Access then
kono
parents:
diff changeset
3184 raise Program_Error with "I cursor not in container";
kono
parents:
diff changeset
3185 end if;
kono
parents:
diff changeset
3186
kono
parents:
diff changeset
3187 if Checks and then Is_Root (I) then
kono
parents:
diff changeset
3188 raise Program_Error with "I cursor designates root";
kono
parents:
diff changeset
3189 end if;
kono
parents:
diff changeset
3190
kono
parents:
diff changeset
3191 if I = J then -- make this test sooner???
kono
parents:
diff changeset
3192 return;
kono
parents:
diff changeset
3193 end if;
kono
parents:
diff changeset
3194
kono
parents:
diff changeset
3195 if Checks and then J = No_Element then
kono
parents:
diff changeset
3196 raise Constraint_Error with "J cursor has no element";
kono
parents:
diff changeset
3197 end if;
kono
parents:
diff changeset
3198
kono
parents:
diff changeset
3199 if Checks and then J.Container /= Container'Unrestricted_Access then
kono
parents:
diff changeset
3200 raise Program_Error with "J cursor not in container";
kono
parents:
diff changeset
3201 end if;
kono
parents:
diff changeset
3202
kono
parents:
diff changeset
3203 if Checks and then Is_Root (J) then
kono
parents:
diff changeset
3204 raise Program_Error with "J cursor designates root";
kono
parents:
diff changeset
3205 end if;
kono
parents:
diff changeset
3206
kono
parents:
diff changeset
3207 TE_Check (Container.TC);
kono
parents:
diff changeset
3208
kono
parents:
diff changeset
3209 declare
kono
parents:
diff changeset
3210 EE : Element_Array renames Container.Elements;
kono
parents:
diff changeset
3211 EI : constant Element_Type := EE (I.Node);
kono
parents:
diff changeset
3212
kono
parents:
diff changeset
3213 begin
kono
parents:
diff changeset
3214 EE (I.Node) := EE (J.Node);
kono
parents:
diff changeset
3215 EE (J.Node) := EI;
kono
parents:
diff changeset
3216 end;
kono
parents:
diff changeset
3217 end Swap;
kono
parents:
diff changeset
3218
kono
parents:
diff changeset
3219 --------------------
kono
parents:
diff changeset
3220 -- Update_Element --
kono
parents:
diff changeset
3221 --------------------
kono
parents:
diff changeset
3222
kono
parents:
diff changeset
3223 procedure Update_Element
kono
parents:
diff changeset
3224 (Container : in out Tree;
kono
parents:
diff changeset
3225 Position : Cursor;
kono
parents:
diff changeset
3226 Process : not null access procedure (Element : in out Element_Type))
kono
parents:
diff changeset
3227 is
kono
parents:
diff changeset
3228 begin
kono
parents:
diff changeset
3229 if Checks and then Position = No_Element then
kono
parents:
diff changeset
3230 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
3231 end if;
kono
parents:
diff changeset
3232
kono
parents:
diff changeset
3233 if Checks and then Position.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
3234 then
kono
parents:
diff changeset
3235 raise Program_Error with "Position cursor not in container";
kono
parents:
diff changeset
3236 end if;
kono
parents:
diff changeset
3237
kono
parents:
diff changeset
3238 if Checks and then Is_Root (Position) then
kono
parents:
diff changeset
3239 raise Program_Error with "Position cursor designates root";
kono
parents:
diff changeset
3240 end if;
kono
parents:
diff changeset
3241
kono
parents:
diff changeset
3242 declare
kono
parents:
diff changeset
3243 T : Tree renames Position.Container.all'Unrestricted_Access.all;
kono
parents:
diff changeset
3244 Lock : With_Lock (T.TC'Unrestricted_Access);
kono
parents:
diff changeset
3245 begin
kono
parents:
diff changeset
3246 Process (Element => T.Elements (Position.Node));
kono
parents:
diff changeset
3247 end;
kono
parents:
diff changeset
3248 end Update_Element;
kono
parents:
diff changeset
3249
kono
parents:
diff changeset
3250 -----------
kono
parents:
diff changeset
3251 -- Write --
kono
parents:
diff changeset
3252 -----------
kono
parents:
diff changeset
3253
kono
parents:
diff changeset
3254 procedure Write
kono
parents:
diff changeset
3255 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
3256 Container : Tree)
kono
parents:
diff changeset
3257 is
kono
parents:
diff changeset
3258 procedure Write_Children (Subtree : Count_Type);
kono
parents:
diff changeset
3259 procedure Write_Subtree (Subtree : Count_Type);
kono
parents:
diff changeset
3260
kono
parents:
diff changeset
3261 --------------------
kono
parents:
diff changeset
3262 -- Write_Children --
kono
parents:
diff changeset
3263 --------------------
kono
parents:
diff changeset
3264
kono
parents:
diff changeset
3265 procedure Write_Children (Subtree : Count_Type) is
kono
parents:
diff changeset
3266 CC : Children_Type renames Container.Nodes (Subtree).Children;
kono
parents:
diff changeset
3267 C : Count_Type'Base;
kono
parents:
diff changeset
3268
kono
parents:
diff changeset
3269 begin
kono
parents:
diff changeset
3270 Count_Type'Write (Stream, Child_Count (Container, Subtree));
kono
parents:
diff changeset
3271
kono
parents:
diff changeset
3272 C := CC.First;
kono
parents:
diff changeset
3273 while C > 0 loop
kono
parents:
diff changeset
3274 Write_Subtree (C);
kono
parents:
diff changeset
3275 C := Container.Nodes (C).Next;
kono
parents:
diff changeset
3276 end loop;
kono
parents:
diff changeset
3277 end Write_Children;
kono
parents:
diff changeset
3278
kono
parents:
diff changeset
3279 -------------------
kono
parents:
diff changeset
3280 -- Write_Subtree --
kono
parents:
diff changeset
3281 -------------------
kono
parents:
diff changeset
3282
kono
parents:
diff changeset
3283 procedure Write_Subtree (Subtree : Count_Type) is
kono
parents:
diff changeset
3284 begin
kono
parents:
diff changeset
3285 Element_Type'Write (Stream, Container.Elements (Subtree));
kono
parents:
diff changeset
3286 Write_Children (Subtree);
kono
parents:
diff changeset
3287 end Write_Subtree;
kono
parents:
diff changeset
3288
kono
parents:
diff changeset
3289 -- Start of processing for Write
kono
parents:
diff changeset
3290
kono
parents:
diff changeset
3291 begin
kono
parents:
diff changeset
3292 Count_Type'Write (Stream, Container.Count);
kono
parents:
diff changeset
3293
kono
parents:
diff changeset
3294 if Container.Count = 0 then
kono
parents:
diff changeset
3295 return;
kono
parents:
diff changeset
3296 end if;
kono
parents:
diff changeset
3297
kono
parents:
diff changeset
3298 Write_Children (Root_Node (Container));
kono
parents:
diff changeset
3299 end Write;
kono
parents:
diff changeset
3300
kono
parents:
diff changeset
3301 procedure Write
kono
parents:
diff changeset
3302 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
3303 Position : Cursor)
kono
parents:
diff changeset
3304 is
kono
parents:
diff changeset
3305 begin
kono
parents:
diff changeset
3306 raise Program_Error with "attempt to write tree cursor to stream";
kono
parents:
diff changeset
3307 end Write;
kono
parents:
diff changeset
3308
kono
parents:
diff changeset
3309 procedure Write
kono
parents:
diff changeset
3310 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
3311 Item : Reference_Type)
kono
parents:
diff changeset
3312 is
kono
parents:
diff changeset
3313 begin
kono
parents:
diff changeset
3314 raise Program_Error with "attempt to stream reference";
kono
parents:
diff changeset
3315 end Write;
kono
parents:
diff changeset
3316
kono
parents:
diff changeset
3317 procedure Write
kono
parents:
diff changeset
3318 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
3319 Item : Constant_Reference_Type)
kono
parents:
diff changeset
3320 is
kono
parents:
diff changeset
3321 begin
kono
parents:
diff changeset
3322 raise Program_Error with "attempt to stream reference";
kono
parents:
diff changeset
3323 end Write;
kono
parents:
diff changeset
3324
kono
parents:
diff changeset
3325 end Ada.Containers.Bounded_Multiway_Trees;