annotate gcc/ada/libgnat/a-cidlli.adb @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
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.INDEFINITE_DOUBLY_LINKED_LISTS --
kono
parents:
diff changeset
6 -- --
kono
parents:
diff changeset
7 -- B o d y --
kono
parents:
diff changeset
8 -- --
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
9 -- Copyright (C) 2004-2018, 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.Unchecked_Deallocation;
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 with System; use type System.Address;
kono
parents:
diff changeset
33
kono
parents:
diff changeset
34 package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
kono
parents:
diff changeset
35
kono
parents:
diff changeset
36 pragma Warnings (Off, "variable ""Busy*"" is not referenced");
kono
parents:
diff changeset
37 pragma Warnings (Off, "variable ""Lock*"" is not referenced");
kono
parents:
diff changeset
38 -- See comment in Ada.Containers.Helpers
kono
parents:
diff changeset
39
kono
parents:
diff changeset
40 procedure Free is
kono
parents:
diff changeset
41 new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
kono
parents:
diff changeset
42
kono
parents:
diff changeset
43 -----------------------
kono
parents:
diff changeset
44 -- Local Subprograms --
kono
parents:
diff changeset
45 -----------------------
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 procedure Free (X : in out Node_Access);
kono
parents:
diff changeset
48
kono
parents:
diff changeset
49 procedure Insert_Internal
kono
parents:
diff changeset
50 (Container : in out List;
kono
parents:
diff changeset
51 Before : Node_Access;
kono
parents:
diff changeset
52 New_Node : Node_Access);
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 procedure Splice_Internal
kono
parents:
diff changeset
55 (Target : in out List;
kono
parents:
diff changeset
56 Before : Node_Access;
kono
parents:
diff changeset
57 Source : in out List);
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 procedure Splice_Internal
kono
parents:
diff changeset
60 (Target : in out List;
kono
parents:
diff changeset
61 Before : Node_Access;
kono
parents:
diff changeset
62 Source : in out List;
kono
parents:
diff changeset
63 Position : Node_Access);
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 function Vet (Position : Cursor) return Boolean;
kono
parents:
diff changeset
66 -- Checks invariants of the cursor and its designated container, as a
kono
parents:
diff changeset
67 -- simple way of detecting dangling references (see operation Free for a
kono
parents:
diff changeset
68 -- description of the detection mechanism), returning True if all checks
kono
parents:
diff changeset
69 -- pass. Invocations of Vet are used here as the argument of pragma Assert,
kono
parents:
diff changeset
70 -- so the checks are performed only when assertions are enabled.
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 ---------
kono
parents:
diff changeset
73 -- "=" --
kono
parents:
diff changeset
74 ---------
kono
parents:
diff changeset
75
kono
parents:
diff changeset
76 function "=" (Left, Right : List) return Boolean is
kono
parents:
diff changeset
77 begin
kono
parents:
diff changeset
78 if Left.Length /= Right.Length then
kono
parents:
diff changeset
79 return False;
kono
parents:
diff changeset
80 end if;
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 if Left.Length = 0 then
kono
parents:
diff changeset
83 return True;
kono
parents:
diff changeset
84 end if;
kono
parents:
diff changeset
85
kono
parents:
diff changeset
86 declare
kono
parents:
diff changeset
87 -- Per AI05-0022, the container implementation is required to detect
kono
parents:
diff changeset
88 -- element tampering by a generic actual subprogram.
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 Lock_Left : With_Lock (Left.TC'Unrestricted_Access);
kono
parents:
diff changeset
91 Lock_Right : With_Lock (Right.TC'Unrestricted_Access);
kono
parents:
diff changeset
92
kono
parents:
diff changeset
93 L : Node_Access := Left.First;
kono
parents:
diff changeset
94 R : Node_Access := Right.First;
kono
parents:
diff changeset
95 begin
kono
parents:
diff changeset
96 for J in 1 .. Left.Length loop
kono
parents:
diff changeset
97 if L.Element.all /= R.Element.all then
kono
parents:
diff changeset
98 return False;
kono
parents:
diff changeset
99 end if;
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 L := L.Next;
kono
parents:
diff changeset
102 R := R.Next;
kono
parents:
diff changeset
103 end loop;
kono
parents:
diff changeset
104 end;
kono
parents:
diff changeset
105
kono
parents:
diff changeset
106 return True;
kono
parents:
diff changeset
107 end "=";
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 ------------
kono
parents:
diff changeset
110 -- Adjust --
kono
parents:
diff changeset
111 ------------
kono
parents:
diff changeset
112
kono
parents:
diff changeset
113 procedure Adjust (Container : in out List) is
kono
parents:
diff changeset
114 Src : Node_Access := Container.First;
kono
parents:
diff changeset
115 Dst : Node_Access;
kono
parents:
diff changeset
116
kono
parents:
diff changeset
117 begin
kono
parents:
diff changeset
118 -- If the counts are nonzero, execution is technically erroneous, but
kono
parents:
diff changeset
119 -- it seems friendly to allow things like concurrent "=" on shared
kono
parents:
diff changeset
120 -- constants.
kono
parents:
diff changeset
121
kono
parents:
diff changeset
122 Zero_Counts (Container.TC);
kono
parents:
diff changeset
123
kono
parents:
diff changeset
124 if Src = null then
kono
parents:
diff changeset
125 pragma Assert (Container.Last = null);
kono
parents:
diff changeset
126 pragma Assert (Container.Length = 0);
kono
parents:
diff changeset
127 return;
kono
parents:
diff changeset
128 end if;
kono
parents:
diff changeset
129
kono
parents:
diff changeset
130 pragma Assert (Container.First.Prev = null);
kono
parents:
diff changeset
131 pragma Assert (Container.Last.Next = null);
kono
parents:
diff changeset
132 pragma Assert (Container.Length > 0);
kono
parents:
diff changeset
133
kono
parents:
diff changeset
134 Container.First := null;
kono
parents:
diff changeset
135 Container.Last := null;
kono
parents:
diff changeset
136 Container.Length := 0;
kono
parents:
diff changeset
137
kono
parents:
diff changeset
138 declare
kono
parents:
diff changeset
139 Element : Element_Access := new Element_Type'(Src.Element.all);
kono
parents:
diff changeset
140 begin
kono
parents:
diff changeset
141 Dst := new Node_Type'(Element, null, null);
kono
parents:
diff changeset
142 exception
kono
parents:
diff changeset
143 when others =>
kono
parents:
diff changeset
144 Free (Element);
kono
parents:
diff changeset
145 raise;
kono
parents:
diff changeset
146 end;
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 Container.First := Dst;
kono
parents:
diff changeset
149 Container.Last := Dst;
kono
parents:
diff changeset
150 Container.Length := 1;
kono
parents:
diff changeset
151
kono
parents:
diff changeset
152 Src := Src.Next;
kono
parents:
diff changeset
153 while Src /= null loop
kono
parents:
diff changeset
154 declare
kono
parents:
diff changeset
155 Element : Element_Access := new Element_Type'(Src.Element.all);
kono
parents:
diff changeset
156 begin
kono
parents:
diff changeset
157 Dst := new Node_Type'(Element, null, Prev => Container.Last);
kono
parents:
diff changeset
158 exception
kono
parents:
diff changeset
159 when others =>
kono
parents:
diff changeset
160 Free (Element);
kono
parents:
diff changeset
161 raise;
kono
parents:
diff changeset
162 end;
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 Container.Last.Next := Dst;
kono
parents:
diff changeset
165 Container.Last := Dst;
kono
parents:
diff changeset
166 Container.Length := Container.Length + 1;
kono
parents:
diff changeset
167
kono
parents:
diff changeset
168 Src := Src.Next;
kono
parents:
diff changeset
169 end loop;
kono
parents:
diff changeset
170 end Adjust;
kono
parents:
diff changeset
171
kono
parents:
diff changeset
172 ------------
kono
parents:
diff changeset
173 -- Append --
kono
parents:
diff changeset
174 ------------
kono
parents:
diff changeset
175
kono
parents:
diff changeset
176 procedure Append
kono
parents:
diff changeset
177 (Container : in out List;
kono
parents:
diff changeset
178 New_Item : Element_Type;
kono
parents:
diff changeset
179 Count : Count_Type := 1)
kono
parents:
diff changeset
180 is
kono
parents:
diff changeset
181 begin
kono
parents:
diff changeset
182 Insert (Container, No_Element, New_Item, Count);
kono
parents:
diff changeset
183 end Append;
kono
parents:
diff changeset
184
kono
parents:
diff changeset
185 ------------
kono
parents:
diff changeset
186 -- Assign --
kono
parents:
diff changeset
187 ------------
kono
parents:
diff changeset
188
kono
parents:
diff changeset
189 procedure Assign (Target : in out List; Source : List) is
kono
parents:
diff changeset
190 Node : Node_Access;
kono
parents:
diff changeset
191
kono
parents:
diff changeset
192 begin
kono
parents:
diff changeset
193 if Target'Address = Source'Address then
kono
parents:
diff changeset
194 return;
kono
parents:
diff changeset
195
kono
parents:
diff changeset
196 else
kono
parents:
diff changeset
197 Target.Clear;
kono
parents:
diff changeset
198
kono
parents:
diff changeset
199 Node := Source.First;
kono
parents:
diff changeset
200 while Node /= null loop
kono
parents:
diff changeset
201 Target.Append (Node.Element.all);
kono
parents:
diff changeset
202 Node := Node.Next;
kono
parents:
diff changeset
203 end loop;
kono
parents:
diff changeset
204 end if;
kono
parents:
diff changeset
205 end Assign;
kono
parents:
diff changeset
206
kono
parents:
diff changeset
207 -----------
kono
parents:
diff changeset
208 -- Clear --
kono
parents:
diff changeset
209 -----------
kono
parents:
diff changeset
210
kono
parents:
diff changeset
211 procedure Clear (Container : in out List) is
kono
parents:
diff changeset
212 X : Node_Access;
kono
parents:
diff changeset
213 pragma Warnings (Off, X);
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 begin
kono
parents:
diff changeset
216 if Container.Length = 0 then
kono
parents:
diff changeset
217 pragma Assert (Container.First = null);
kono
parents:
diff changeset
218 pragma Assert (Container.Last = null);
kono
parents:
diff changeset
219 pragma Assert (Container.TC = (Busy => 0, Lock => 0));
kono
parents:
diff changeset
220 return;
kono
parents:
diff changeset
221 end if;
kono
parents:
diff changeset
222
kono
parents:
diff changeset
223 pragma Assert (Container.First.Prev = null);
kono
parents:
diff changeset
224 pragma Assert (Container.Last.Next = null);
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 TC_Check (Container.TC);
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 while Container.Length > 1 loop
kono
parents:
diff changeset
229 X := Container.First;
kono
parents:
diff changeset
230 pragma Assert (X.Next.Prev = Container.First);
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 Container.First := X.Next;
kono
parents:
diff changeset
233 Container.First.Prev := null;
kono
parents:
diff changeset
234
kono
parents:
diff changeset
235 Container.Length := Container.Length - 1;
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237 Free (X);
kono
parents:
diff changeset
238 end loop;
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 X := Container.First;
kono
parents:
diff changeset
241 pragma Assert (X = Container.Last);
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 Container.First := null;
kono
parents:
diff changeset
244 Container.Last := null;
kono
parents:
diff changeset
245 Container.Length := 0;
kono
parents:
diff changeset
246
kono
parents:
diff changeset
247 Free (X);
kono
parents:
diff changeset
248 end Clear;
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 ------------------------
kono
parents:
diff changeset
251 -- Constant_Reference --
kono
parents:
diff changeset
252 ------------------------
kono
parents:
diff changeset
253
kono
parents:
diff changeset
254 function Constant_Reference
kono
parents:
diff changeset
255 (Container : aliased List;
kono
parents:
diff changeset
256 Position : Cursor) return Constant_Reference_Type
kono
parents:
diff changeset
257 is
kono
parents:
diff changeset
258 begin
kono
parents:
diff changeset
259 if Checks and then Position.Container = null then
kono
parents:
diff changeset
260 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
261 end if;
kono
parents:
diff changeset
262
kono
parents:
diff changeset
263 if Checks and then Position.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
264 then
kono
parents:
diff changeset
265 raise Program_Error with
kono
parents:
diff changeset
266 "Position cursor designates wrong container";
kono
parents:
diff changeset
267 end if;
kono
parents:
diff changeset
268
kono
parents:
diff changeset
269 if Checks and then Position.Node.Element = null then
kono
parents:
diff changeset
270 raise Program_Error with "Node has no element";
kono
parents:
diff changeset
271 end if;
kono
parents:
diff changeset
272
kono
parents:
diff changeset
273 pragma Assert (Vet (Position), "bad cursor in Constant_Reference");
kono
parents:
diff changeset
274
kono
parents:
diff changeset
275 declare
kono
parents:
diff changeset
276 TC : constant Tamper_Counts_Access :=
kono
parents:
diff changeset
277 Container.TC'Unrestricted_Access;
kono
parents:
diff changeset
278 begin
kono
parents:
diff changeset
279 return R : constant Constant_Reference_Type :=
kono
parents:
diff changeset
280 (Element => Position.Node.Element,
kono
parents:
diff changeset
281 Control => (Controlled with TC))
kono
parents:
diff changeset
282 do
kono
parents:
diff changeset
283 Lock (TC.all);
kono
parents:
diff changeset
284 end return;
kono
parents:
diff changeset
285 end;
kono
parents:
diff changeset
286 end Constant_Reference;
kono
parents:
diff changeset
287
kono
parents:
diff changeset
288 --------------
kono
parents:
diff changeset
289 -- Contains --
kono
parents:
diff changeset
290 --------------
kono
parents:
diff changeset
291
kono
parents:
diff changeset
292 function Contains
kono
parents:
diff changeset
293 (Container : List;
kono
parents:
diff changeset
294 Item : Element_Type) return Boolean
kono
parents:
diff changeset
295 is
kono
parents:
diff changeset
296 begin
kono
parents:
diff changeset
297 return Find (Container, Item) /= No_Element;
kono
parents:
diff changeset
298 end Contains;
kono
parents:
diff changeset
299
kono
parents:
diff changeset
300 ----------
kono
parents:
diff changeset
301 -- Copy --
kono
parents:
diff changeset
302 ----------
kono
parents:
diff changeset
303
kono
parents:
diff changeset
304 function Copy (Source : List) return List is
kono
parents:
diff changeset
305 begin
kono
parents:
diff changeset
306 return Target : List do
kono
parents:
diff changeset
307 Target.Assign (Source);
kono
parents:
diff changeset
308 end return;
kono
parents:
diff changeset
309 end Copy;
kono
parents:
diff changeset
310
kono
parents:
diff changeset
311 ------------
kono
parents:
diff changeset
312 -- Delete --
kono
parents:
diff changeset
313 ------------
kono
parents:
diff changeset
314
kono
parents:
diff changeset
315 procedure Delete
kono
parents:
diff changeset
316 (Container : in out List;
kono
parents:
diff changeset
317 Position : in out Cursor;
kono
parents:
diff changeset
318 Count : Count_Type := 1)
kono
parents:
diff changeset
319 is
kono
parents:
diff changeset
320 X : Node_Access;
kono
parents:
diff changeset
321
kono
parents:
diff changeset
322 begin
kono
parents:
diff changeset
323 if Checks and then Position.Node = null then
kono
parents:
diff changeset
324 raise Constraint_Error with
kono
parents:
diff changeset
325 "Position cursor has no element";
kono
parents:
diff changeset
326 end if;
kono
parents:
diff changeset
327
kono
parents:
diff changeset
328 if Checks and then Position.Node.Element = null then
kono
parents:
diff changeset
329 raise Program_Error with
kono
parents:
diff changeset
330 "Position cursor has no element";
kono
parents:
diff changeset
331 end if;
kono
parents:
diff changeset
332
kono
parents:
diff changeset
333 if Checks and then Position.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
334 then
kono
parents:
diff changeset
335 raise Program_Error with
kono
parents:
diff changeset
336 "Position cursor designates wrong container";
kono
parents:
diff changeset
337 end if;
kono
parents:
diff changeset
338
kono
parents:
diff changeset
339 pragma Assert (Vet (Position), "bad cursor in Delete");
kono
parents:
diff changeset
340
kono
parents:
diff changeset
341 if Position.Node = Container.First then
kono
parents:
diff changeset
342 Delete_First (Container, Count);
kono
parents:
diff changeset
343 Position := No_Element; -- Post-York behavior
kono
parents:
diff changeset
344 return;
kono
parents:
diff changeset
345 end if;
kono
parents:
diff changeset
346
kono
parents:
diff changeset
347 if Count = 0 then
kono
parents:
diff changeset
348 Position := No_Element; -- Post-York behavior
kono
parents:
diff changeset
349 return;
kono
parents:
diff changeset
350 end if;
kono
parents:
diff changeset
351
kono
parents:
diff changeset
352 TC_Check (Container.TC);
kono
parents:
diff changeset
353
kono
parents:
diff changeset
354 for Index in 1 .. Count loop
kono
parents:
diff changeset
355 X := Position.Node;
kono
parents:
diff changeset
356 Container.Length := Container.Length - 1;
kono
parents:
diff changeset
357
kono
parents:
diff changeset
358 if X = Container.Last then
kono
parents:
diff changeset
359 Position := No_Element;
kono
parents:
diff changeset
360
kono
parents:
diff changeset
361 Container.Last := X.Prev;
kono
parents:
diff changeset
362 Container.Last.Next := null;
kono
parents:
diff changeset
363
kono
parents:
diff changeset
364 Free (X);
kono
parents:
diff changeset
365 return;
kono
parents:
diff changeset
366 end if;
kono
parents:
diff changeset
367
kono
parents:
diff changeset
368 Position.Node := X.Next;
kono
parents:
diff changeset
369
kono
parents:
diff changeset
370 X.Next.Prev := X.Prev;
kono
parents:
diff changeset
371 X.Prev.Next := X.Next;
kono
parents:
diff changeset
372
kono
parents:
diff changeset
373 Free (X);
kono
parents:
diff changeset
374 end loop;
kono
parents:
diff changeset
375
kono
parents:
diff changeset
376 -- Fix this junk comment ???
kono
parents:
diff changeset
377
kono
parents:
diff changeset
378 Position := No_Element; -- Post-York behavior
kono
parents:
diff changeset
379 end Delete;
kono
parents:
diff changeset
380
kono
parents:
diff changeset
381 ------------------
kono
parents:
diff changeset
382 -- Delete_First --
kono
parents:
diff changeset
383 ------------------
kono
parents:
diff changeset
384
kono
parents:
diff changeset
385 procedure Delete_First
kono
parents:
diff changeset
386 (Container : in out List;
kono
parents:
diff changeset
387 Count : Count_Type := 1)
kono
parents:
diff changeset
388 is
kono
parents:
diff changeset
389 X : Node_Access;
kono
parents:
diff changeset
390
kono
parents:
diff changeset
391 begin
kono
parents:
diff changeset
392 if Count >= Container.Length then
kono
parents:
diff changeset
393 Clear (Container);
kono
parents:
diff changeset
394 return;
kono
parents:
diff changeset
395 end if;
kono
parents:
diff changeset
396
kono
parents:
diff changeset
397 if Count = 0 then
kono
parents:
diff changeset
398 return;
kono
parents:
diff changeset
399 end if;
kono
parents:
diff changeset
400
kono
parents:
diff changeset
401 TC_Check (Container.TC);
kono
parents:
diff changeset
402
kono
parents:
diff changeset
403 for J in 1 .. Count loop
kono
parents:
diff changeset
404 X := Container.First;
kono
parents:
diff changeset
405 pragma Assert (X.Next.Prev = Container.First);
kono
parents:
diff changeset
406
kono
parents:
diff changeset
407 Container.First := X.Next;
kono
parents:
diff changeset
408 Container.First.Prev := null;
kono
parents:
diff changeset
409
kono
parents:
diff changeset
410 Container.Length := Container.Length - 1;
kono
parents:
diff changeset
411
kono
parents:
diff changeset
412 Free (X);
kono
parents:
diff changeset
413 end loop;
kono
parents:
diff changeset
414 end Delete_First;
kono
parents:
diff changeset
415
kono
parents:
diff changeset
416 -----------------
kono
parents:
diff changeset
417 -- Delete_Last --
kono
parents:
diff changeset
418 -----------------
kono
parents:
diff changeset
419
kono
parents:
diff changeset
420 procedure Delete_Last
kono
parents:
diff changeset
421 (Container : in out List;
kono
parents:
diff changeset
422 Count : Count_Type := 1)
kono
parents:
diff changeset
423 is
kono
parents:
diff changeset
424 X : Node_Access;
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 begin
kono
parents:
diff changeset
427 if Count >= Container.Length then
kono
parents:
diff changeset
428 Clear (Container);
kono
parents:
diff changeset
429 return;
kono
parents:
diff changeset
430 end if;
kono
parents:
diff changeset
431
kono
parents:
diff changeset
432 if Count = 0 then
kono
parents:
diff changeset
433 return;
kono
parents:
diff changeset
434 end if;
kono
parents:
diff changeset
435
kono
parents:
diff changeset
436 TC_Check (Container.TC);
kono
parents:
diff changeset
437
kono
parents:
diff changeset
438 for J in 1 .. Count loop
kono
parents:
diff changeset
439 X := Container.Last;
kono
parents:
diff changeset
440 pragma Assert (X.Prev.Next = Container.Last);
kono
parents:
diff changeset
441
kono
parents:
diff changeset
442 Container.Last := X.Prev;
kono
parents:
diff changeset
443 Container.Last.Next := null;
kono
parents:
diff changeset
444
kono
parents:
diff changeset
445 Container.Length := Container.Length - 1;
kono
parents:
diff changeset
446
kono
parents:
diff changeset
447 Free (X);
kono
parents:
diff changeset
448 end loop;
kono
parents:
diff changeset
449 end Delete_Last;
kono
parents:
diff changeset
450
kono
parents:
diff changeset
451 -------------
kono
parents:
diff changeset
452 -- Element --
kono
parents:
diff changeset
453 -------------
kono
parents:
diff changeset
454
kono
parents:
diff changeset
455 function Element (Position : Cursor) return Element_Type is
kono
parents:
diff changeset
456 begin
kono
parents:
diff changeset
457 if Checks and then Position.Node = null then
kono
parents:
diff changeset
458 raise Constraint_Error with
kono
parents:
diff changeset
459 "Position cursor has no element";
kono
parents:
diff changeset
460 end if;
kono
parents:
diff changeset
461
kono
parents:
diff changeset
462 if Checks and then Position.Node.Element = null then
kono
parents:
diff changeset
463 raise Program_Error with
kono
parents:
diff changeset
464 "Position cursor has no element";
kono
parents:
diff changeset
465 end if;
kono
parents:
diff changeset
466
kono
parents:
diff changeset
467 pragma Assert (Vet (Position), "bad cursor in Element");
kono
parents:
diff changeset
468
kono
parents:
diff changeset
469 return Position.Node.Element.all;
kono
parents:
diff changeset
470 end Element;
kono
parents:
diff changeset
471
kono
parents:
diff changeset
472 --------------
kono
parents:
diff changeset
473 -- Finalize --
kono
parents:
diff changeset
474 --------------
kono
parents:
diff changeset
475
kono
parents:
diff changeset
476 procedure Finalize (Object : in out Iterator) is
kono
parents:
diff changeset
477 begin
kono
parents:
diff changeset
478 if Object.Container /= null then
kono
parents:
diff changeset
479 Unbusy (Object.Container.TC);
kono
parents:
diff changeset
480 end if;
kono
parents:
diff changeset
481 end Finalize;
kono
parents:
diff changeset
482
kono
parents:
diff changeset
483 ----------
kono
parents:
diff changeset
484 -- Find --
kono
parents:
diff changeset
485 ----------
kono
parents:
diff changeset
486
kono
parents:
diff changeset
487 function Find
kono
parents:
diff changeset
488 (Container : List;
kono
parents:
diff changeset
489 Item : Element_Type;
kono
parents:
diff changeset
490 Position : Cursor := No_Element) return Cursor
kono
parents:
diff changeset
491 is
kono
parents:
diff changeset
492 Node : Node_Access := Position.Node;
kono
parents:
diff changeset
493
kono
parents:
diff changeset
494 begin
kono
parents:
diff changeset
495 if Node = null then
kono
parents:
diff changeset
496 Node := Container.First;
kono
parents:
diff changeset
497
kono
parents:
diff changeset
498 else
kono
parents:
diff changeset
499 if Checks and then Node.Element = null then
kono
parents:
diff changeset
500 raise Program_Error;
kono
parents:
diff changeset
501 end if;
kono
parents:
diff changeset
502
kono
parents:
diff changeset
503 if Checks and then Position.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
504 then
kono
parents:
diff changeset
505 raise Program_Error with
kono
parents:
diff changeset
506 "Position cursor designates wrong container";
kono
parents:
diff changeset
507 end if;
kono
parents:
diff changeset
508
kono
parents:
diff changeset
509 pragma Assert (Vet (Position), "bad cursor in Find");
kono
parents:
diff changeset
510 end if;
kono
parents:
diff changeset
511
kono
parents:
diff changeset
512 -- Per AI05-0022, the container implementation is required to detect
kono
parents:
diff changeset
513 -- element tampering by a generic actual subprogram.
kono
parents:
diff changeset
514
kono
parents:
diff changeset
515 declare
kono
parents:
diff changeset
516 Lock : With_Lock (Container.TC'Unrestricted_Access);
kono
parents:
diff changeset
517 begin
kono
parents:
diff changeset
518 while Node /= null loop
kono
parents:
diff changeset
519 if Node.Element.all = Item then
kono
parents:
diff changeset
520 return Cursor'(Container'Unrestricted_Access, Node);
kono
parents:
diff changeset
521 end if;
kono
parents:
diff changeset
522
kono
parents:
diff changeset
523 Node := Node.Next;
kono
parents:
diff changeset
524 end loop;
kono
parents:
diff changeset
525
kono
parents:
diff changeset
526 return No_Element;
kono
parents:
diff changeset
527 end;
kono
parents:
diff changeset
528 end Find;
kono
parents:
diff changeset
529
kono
parents:
diff changeset
530 -----------
kono
parents:
diff changeset
531 -- First --
kono
parents:
diff changeset
532 -----------
kono
parents:
diff changeset
533
kono
parents:
diff changeset
534 function First (Container : List) return Cursor is
kono
parents:
diff changeset
535 begin
kono
parents:
diff changeset
536 if Container.First = null then
kono
parents:
diff changeset
537 return No_Element;
kono
parents:
diff changeset
538 else
kono
parents:
diff changeset
539 return Cursor'(Container'Unrestricted_Access, Container.First);
kono
parents:
diff changeset
540 end if;
kono
parents:
diff changeset
541 end First;
kono
parents:
diff changeset
542
kono
parents:
diff changeset
543 function First (Object : Iterator) return Cursor is
kono
parents:
diff changeset
544 begin
kono
parents:
diff changeset
545 -- The value of the iterator object's Node component influences the
kono
parents:
diff changeset
546 -- behavior of the First (and Last) selector function.
kono
parents:
diff changeset
547
kono
parents:
diff changeset
548 -- When the Node component is null, this means the iterator object was
kono
parents:
diff changeset
549 -- constructed without a start expression, in which case the (forward)
kono
parents:
diff changeset
550 -- iteration starts from the (logical) beginning of the entire sequence
kono
parents:
diff changeset
551 -- of items (corresponding to Container.First, for a forward iterator).
kono
parents:
diff changeset
552
kono
parents:
diff changeset
553 -- Otherwise, this is iteration over a partial sequence of items. When
kono
parents:
diff changeset
554 -- the Node component is non-null, the iterator object was constructed
kono
parents:
diff changeset
555 -- with a start expression, that specifies the position from which the
kono
parents:
diff changeset
556 -- (forward) partial iteration begins.
kono
parents:
diff changeset
557
kono
parents:
diff changeset
558 if Object.Node = null then
kono
parents:
diff changeset
559 return Indefinite_Doubly_Linked_Lists.First (Object.Container.all);
kono
parents:
diff changeset
560 else
kono
parents:
diff changeset
561 return Cursor'(Object.Container, Object.Node);
kono
parents:
diff changeset
562 end if;
kono
parents:
diff changeset
563 end First;
kono
parents:
diff changeset
564
kono
parents:
diff changeset
565 -------------------
kono
parents:
diff changeset
566 -- First_Element --
kono
parents:
diff changeset
567 -------------------
kono
parents:
diff changeset
568
kono
parents:
diff changeset
569 function First_Element (Container : List) return Element_Type is
kono
parents:
diff changeset
570 begin
kono
parents:
diff changeset
571 if Checks and then Container.First = null then
kono
parents:
diff changeset
572 raise Constraint_Error with "list is empty";
kono
parents:
diff changeset
573 end if;
kono
parents:
diff changeset
574
kono
parents:
diff changeset
575 return Container.First.Element.all;
kono
parents:
diff changeset
576 end First_Element;
kono
parents:
diff changeset
577
kono
parents:
diff changeset
578 ----------
kono
parents:
diff changeset
579 -- Free --
kono
parents:
diff changeset
580 ----------
kono
parents:
diff changeset
581
kono
parents:
diff changeset
582 procedure Free (X : in out Node_Access) is
kono
parents:
diff changeset
583 procedure Deallocate is
kono
parents:
diff changeset
584 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
kono
parents:
diff changeset
585
kono
parents:
diff changeset
586 begin
kono
parents:
diff changeset
587 -- While a node is in use, as an active link in a list, its Previous and
kono
parents:
diff changeset
588 -- Next components must be null, or designate a different node; this is
kono
parents:
diff changeset
589 -- a node invariant. For this indefinite list, there is an additional
kono
parents:
diff changeset
590 -- invariant: that the element access value be non-null. Before actually
kono
parents:
diff changeset
591 -- deallocating the node, we set the node access value components of the
kono
parents:
diff changeset
592 -- node to point to the node itself, and set the element access value to
kono
parents:
diff changeset
593 -- null (by deallocating the node's element), thus falsifying the node
kono
parents:
diff changeset
594 -- invariant. Subprogram Vet inspects the value of the node components
kono
parents:
diff changeset
595 -- when interrogating the node, in order to detect whether the cursor's
kono
parents:
diff changeset
596 -- node access value is dangling.
kono
parents:
diff changeset
597
kono
parents:
diff changeset
598 -- Note that we have no guarantee that the storage for the node isn't
kono
parents:
diff changeset
599 -- modified when it is deallocated, but there are other tests that Vet
kono
parents:
diff changeset
600 -- does if node invariants appear to be satisifed. However, in practice
kono
parents:
diff changeset
601 -- this simple test works well enough, detecting dangling references
kono
parents:
diff changeset
602 -- immediately, without needing further interrogation.
kono
parents:
diff changeset
603
kono
parents:
diff changeset
604 X.Next := X;
kono
parents:
diff changeset
605 X.Prev := X;
kono
parents:
diff changeset
606
kono
parents:
diff changeset
607 begin
kono
parents:
diff changeset
608 Free (X.Element);
kono
parents:
diff changeset
609 exception
kono
parents:
diff changeset
610 when others =>
kono
parents:
diff changeset
611 X.Element := null;
kono
parents:
diff changeset
612 Deallocate (X);
kono
parents:
diff changeset
613 raise;
kono
parents:
diff changeset
614 end;
kono
parents:
diff changeset
615
kono
parents:
diff changeset
616 Deallocate (X);
kono
parents:
diff changeset
617 end Free;
kono
parents:
diff changeset
618
kono
parents:
diff changeset
619 ---------------------
kono
parents:
diff changeset
620 -- Generic_Sorting --
kono
parents:
diff changeset
621 ---------------------
kono
parents:
diff changeset
622
kono
parents:
diff changeset
623 package body Generic_Sorting is
kono
parents:
diff changeset
624
kono
parents:
diff changeset
625 ---------------
kono
parents:
diff changeset
626 -- Is_Sorted --
kono
parents:
diff changeset
627 ---------------
kono
parents:
diff changeset
628
kono
parents:
diff changeset
629 function Is_Sorted (Container : List) return Boolean is
kono
parents:
diff changeset
630 -- Per AI05-0022, the container implementation is required to detect
kono
parents:
diff changeset
631 -- element tampering by a generic actual subprogram.
kono
parents:
diff changeset
632
kono
parents:
diff changeset
633 Lock : With_Lock (Container.TC'Unrestricted_Access);
kono
parents:
diff changeset
634
kono
parents:
diff changeset
635 Node : Node_Access;
kono
parents:
diff changeset
636 begin
kono
parents:
diff changeset
637 Node := Container.First;
kono
parents:
diff changeset
638 for J in 2 .. Container.Length loop
kono
parents:
diff changeset
639 if Node.Next.Element.all < Node.Element.all then
kono
parents:
diff changeset
640 return False;
kono
parents:
diff changeset
641 end if;
kono
parents:
diff changeset
642
kono
parents:
diff changeset
643 Node := Node.Next;
kono
parents:
diff changeset
644 end loop;
kono
parents:
diff changeset
645
kono
parents:
diff changeset
646 return True;
kono
parents:
diff changeset
647 end Is_Sorted;
kono
parents:
diff changeset
648
kono
parents:
diff changeset
649 -----------
kono
parents:
diff changeset
650 -- Merge --
kono
parents:
diff changeset
651 -----------
kono
parents:
diff changeset
652
kono
parents:
diff changeset
653 procedure Merge
kono
parents:
diff changeset
654 (Target : in out List;
kono
parents:
diff changeset
655 Source : in out List)
kono
parents:
diff changeset
656 is
kono
parents:
diff changeset
657 begin
kono
parents:
diff changeset
658 -- The semantics of Merge changed slightly per AI05-0021. It was
kono
parents:
diff changeset
659 -- originally the case that if Target and Source denoted the same
kono
parents:
diff changeset
660 -- container object, then the GNAT implementation of Merge did
kono
parents:
diff changeset
661 -- nothing. However, it was argued that RM05 did not precisely
kono
parents:
diff changeset
662 -- specify the semantics for this corner case. The decision of the
kono
parents:
diff changeset
663 -- ARG was that if Target and Source denote the same non-empty
kono
parents:
diff changeset
664 -- container object, then Program_Error is raised.
kono
parents:
diff changeset
665
kono
parents:
diff changeset
666 if Source.Is_Empty then
kono
parents:
diff changeset
667 return;
kono
parents:
diff changeset
668 end if;
kono
parents:
diff changeset
669
kono
parents:
diff changeset
670 if Checks and then Target'Address = Source'Address then
kono
parents:
diff changeset
671 raise Program_Error with
kono
parents:
diff changeset
672 "Target and Source denote same non-empty container";
kono
parents:
diff changeset
673 end if;
kono
parents:
diff changeset
674
kono
parents:
diff changeset
675 if Checks and then Target.Length > Count_Type'Last - Source.Length
kono
parents:
diff changeset
676 then
kono
parents:
diff changeset
677 raise Constraint_Error with "new length exceeds maximum";
kono
parents:
diff changeset
678 end if;
kono
parents:
diff changeset
679
kono
parents:
diff changeset
680 TC_Check (Target.TC);
kono
parents:
diff changeset
681 TC_Check (Source.TC);
kono
parents:
diff changeset
682
kono
parents:
diff changeset
683 declare
kono
parents:
diff changeset
684 Lock_Target : With_Lock (Target.TC'Unchecked_Access);
kono
parents:
diff changeset
685 Lock_Source : With_Lock (Source.TC'Unchecked_Access);
kono
parents:
diff changeset
686
kono
parents:
diff changeset
687 LI, RI, RJ : Node_Access;
kono
parents:
diff changeset
688
kono
parents:
diff changeset
689 begin
kono
parents:
diff changeset
690 LI := Target.First;
kono
parents:
diff changeset
691 RI := Source.First;
kono
parents:
diff changeset
692 while RI /= null loop
kono
parents:
diff changeset
693 pragma Assert (RI.Next = null
kono
parents:
diff changeset
694 or else not (RI.Next.Element.all <
kono
parents:
diff changeset
695 RI.Element.all));
kono
parents:
diff changeset
696
kono
parents:
diff changeset
697 if LI = null then
kono
parents:
diff changeset
698 Splice_Internal (Target, null, Source);
kono
parents:
diff changeset
699 exit;
kono
parents:
diff changeset
700 end if;
kono
parents:
diff changeset
701
kono
parents:
diff changeset
702 pragma Assert (LI.Next = null
kono
parents:
diff changeset
703 or else not (LI.Next.Element.all <
kono
parents:
diff changeset
704 LI.Element.all));
kono
parents:
diff changeset
705
kono
parents:
diff changeset
706 if RI.Element.all < LI.Element.all then
kono
parents:
diff changeset
707 RJ := RI;
kono
parents:
diff changeset
708 RI := RI.Next;
kono
parents:
diff changeset
709 Splice_Internal (Target, LI, Source, RJ);
kono
parents:
diff changeset
710
kono
parents:
diff changeset
711 else
kono
parents:
diff changeset
712 LI := LI.Next;
kono
parents:
diff changeset
713 end if;
kono
parents:
diff changeset
714 end loop;
kono
parents:
diff changeset
715 end;
kono
parents:
diff changeset
716 end Merge;
kono
parents:
diff changeset
717
kono
parents:
diff changeset
718 ----------
kono
parents:
diff changeset
719 -- Sort --
kono
parents:
diff changeset
720 ----------
kono
parents:
diff changeset
721
kono
parents:
diff changeset
722 procedure Sort (Container : in out List) is
kono
parents:
diff changeset
723 procedure Partition (Pivot : Node_Access; Back : Node_Access);
kono
parents:
diff changeset
724 -- Comment ???
kono
parents:
diff changeset
725
kono
parents:
diff changeset
726 procedure Sort (Front, Back : Node_Access);
kono
parents:
diff changeset
727 -- Comment??? Confusing name??? change name???
kono
parents:
diff changeset
728
kono
parents:
diff changeset
729 ---------------
kono
parents:
diff changeset
730 -- Partition --
kono
parents:
diff changeset
731 ---------------
kono
parents:
diff changeset
732
kono
parents:
diff changeset
733 procedure Partition (Pivot : Node_Access; Back : Node_Access) is
kono
parents:
diff changeset
734 Node : Node_Access;
kono
parents:
diff changeset
735
kono
parents:
diff changeset
736 begin
kono
parents:
diff changeset
737 Node := Pivot.Next;
kono
parents:
diff changeset
738 while Node /= Back loop
kono
parents:
diff changeset
739 if Node.Element.all < Pivot.Element.all then
kono
parents:
diff changeset
740 declare
kono
parents:
diff changeset
741 Prev : constant Node_Access := Node.Prev;
kono
parents:
diff changeset
742 Next : constant Node_Access := Node.Next;
kono
parents:
diff changeset
743
kono
parents:
diff changeset
744 begin
kono
parents:
diff changeset
745 Prev.Next := Next;
kono
parents:
diff changeset
746
kono
parents:
diff changeset
747 if Next = null then
kono
parents:
diff changeset
748 Container.Last := Prev;
kono
parents:
diff changeset
749 else
kono
parents:
diff changeset
750 Next.Prev := Prev;
kono
parents:
diff changeset
751 end if;
kono
parents:
diff changeset
752
kono
parents:
diff changeset
753 Node.Next := Pivot;
kono
parents:
diff changeset
754 Node.Prev := Pivot.Prev;
kono
parents:
diff changeset
755
kono
parents:
diff changeset
756 Pivot.Prev := Node;
kono
parents:
diff changeset
757
kono
parents:
diff changeset
758 if Node.Prev = null then
kono
parents:
diff changeset
759 Container.First := Node;
kono
parents:
diff changeset
760 else
kono
parents:
diff changeset
761 Node.Prev.Next := Node;
kono
parents:
diff changeset
762 end if;
kono
parents:
diff changeset
763
kono
parents:
diff changeset
764 Node := Next;
kono
parents:
diff changeset
765 end;
kono
parents:
diff changeset
766
kono
parents:
diff changeset
767 else
kono
parents:
diff changeset
768 Node := Node.Next;
kono
parents:
diff changeset
769 end if;
kono
parents:
diff changeset
770 end loop;
kono
parents:
diff changeset
771 end Partition;
kono
parents:
diff changeset
772
kono
parents:
diff changeset
773 ----------
kono
parents:
diff changeset
774 -- Sort --
kono
parents:
diff changeset
775 ----------
kono
parents:
diff changeset
776
kono
parents:
diff changeset
777 procedure Sort (Front, Back : Node_Access) is
kono
parents:
diff changeset
778 Pivot : constant Node_Access :=
kono
parents:
diff changeset
779 (if Front = null then Container.First else Front.Next);
kono
parents:
diff changeset
780 begin
kono
parents:
diff changeset
781 if Pivot /= Back then
kono
parents:
diff changeset
782 Partition (Pivot, Back);
kono
parents:
diff changeset
783 Sort (Front, Pivot);
kono
parents:
diff changeset
784 Sort (Pivot, Back);
kono
parents:
diff changeset
785 end if;
kono
parents:
diff changeset
786 end Sort;
kono
parents:
diff changeset
787
kono
parents:
diff changeset
788 -- Start of processing for Sort
kono
parents:
diff changeset
789
kono
parents:
diff changeset
790 begin
kono
parents:
diff changeset
791 if Container.Length <= 1 then
kono
parents:
diff changeset
792 return;
kono
parents:
diff changeset
793 end if;
kono
parents:
diff changeset
794
kono
parents:
diff changeset
795 pragma Assert (Container.First.Prev = null);
kono
parents:
diff changeset
796 pragma Assert (Container.Last.Next = null);
kono
parents:
diff changeset
797
kono
parents:
diff changeset
798 TC_Check (Container.TC);
kono
parents:
diff changeset
799
kono
parents:
diff changeset
800 -- Per AI05-0022, the container implementation is required to detect
kono
parents:
diff changeset
801 -- element tampering by a generic actual subprogram.
kono
parents:
diff changeset
802
kono
parents:
diff changeset
803 declare
kono
parents:
diff changeset
804 Lock : With_Lock (Container.TC'Unchecked_Access);
kono
parents:
diff changeset
805 begin
kono
parents:
diff changeset
806 Sort (Front => null, Back => null);
kono
parents:
diff changeset
807 end;
kono
parents:
diff changeset
808
kono
parents:
diff changeset
809 pragma Assert (Container.First.Prev = null);
kono
parents:
diff changeset
810 pragma Assert (Container.Last.Next = null);
kono
parents:
diff changeset
811 end Sort;
kono
parents:
diff changeset
812
kono
parents:
diff changeset
813 end Generic_Sorting;
kono
parents:
diff changeset
814
kono
parents:
diff changeset
815 ------------------------
kono
parents:
diff changeset
816 -- Get_Element_Access --
kono
parents:
diff changeset
817 ------------------------
kono
parents:
diff changeset
818
kono
parents:
diff changeset
819 function Get_Element_Access
kono
parents:
diff changeset
820 (Position : Cursor) return not null Element_Access is
kono
parents:
diff changeset
821 begin
kono
parents:
diff changeset
822 return Position.Node.Element;
kono
parents:
diff changeset
823 end Get_Element_Access;
kono
parents:
diff changeset
824
kono
parents:
diff changeset
825 -----------------
kono
parents:
diff changeset
826 -- Has_Element --
kono
parents:
diff changeset
827 -----------------
kono
parents:
diff changeset
828
kono
parents:
diff changeset
829 function Has_Element (Position : Cursor) return Boolean is
kono
parents:
diff changeset
830 begin
kono
parents:
diff changeset
831 pragma Assert (Vet (Position), "bad cursor in Has_Element");
kono
parents:
diff changeset
832 return Position.Node /= null;
kono
parents:
diff changeset
833 end Has_Element;
kono
parents:
diff changeset
834
kono
parents:
diff changeset
835 ------------
kono
parents:
diff changeset
836 -- Insert --
kono
parents:
diff changeset
837 ------------
kono
parents:
diff changeset
838
kono
parents:
diff changeset
839 procedure Insert
kono
parents:
diff changeset
840 (Container : in out List;
kono
parents:
diff changeset
841 Before : Cursor;
kono
parents:
diff changeset
842 New_Item : Element_Type;
kono
parents:
diff changeset
843 Position : out Cursor;
kono
parents:
diff changeset
844 Count : Count_Type := 1)
kono
parents:
diff changeset
845 is
kono
parents:
diff changeset
846 First_Node : Node_Access;
kono
parents:
diff changeset
847 New_Node : Node_Access;
kono
parents:
diff changeset
848
kono
parents:
diff changeset
849 begin
kono
parents:
diff changeset
850 if Before.Container /= null then
kono
parents:
diff changeset
851 if Checks and then Before.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
852 then
kono
parents:
diff changeset
853 raise Program_Error with
kono
parents:
diff changeset
854 "Before cursor designates wrong list";
kono
parents:
diff changeset
855 end if;
kono
parents:
diff changeset
856
kono
parents:
diff changeset
857 if Checks and then
kono
parents:
diff changeset
858 (Before.Node = null or else Before.Node.Element = null)
kono
parents:
diff changeset
859 then
kono
parents:
diff changeset
860 raise Program_Error with
kono
parents:
diff changeset
861 "Before cursor has no element";
kono
parents:
diff changeset
862 end if;
kono
parents:
diff changeset
863
kono
parents:
diff changeset
864 pragma Assert (Vet (Before), "bad cursor in Insert");
kono
parents:
diff changeset
865 end if;
kono
parents:
diff changeset
866
kono
parents:
diff changeset
867 if Count = 0 then
kono
parents:
diff changeset
868 Position := Before;
kono
parents:
diff changeset
869 return;
kono
parents:
diff changeset
870 end if;
kono
parents:
diff changeset
871
kono
parents:
diff changeset
872 if Checks and then Container.Length > Count_Type'Last - Count then
kono
parents:
diff changeset
873 raise Constraint_Error with "new length exceeds maximum";
kono
parents:
diff changeset
874 end if;
kono
parents:
diff changeset
875
kono
parents:
diff changeset
876 TC_Check (Container.TC);
kono
parents:
diff changeset
877
kono
parents:
diff changeset
878 declare
kono
parents:
diff changeset
879 -- The element allocator may need an accessibility check in the case
kono
parents:
diff changeset
880 -- the actual type is class-wide or has access discriminants (see
kono
parents:
diff changeset
881 -- RM 4.8(10.1) and AI12-0035). We don't unsuppress the check on the
kono
parents:
diff changeset
882 -- allocator in the loop below, because the one in this block would
kono
parents:
diff changeset
883 -- have failed already.
kono
parents:
diff changeset
884
kono
parents:
diff changeset
885 pragma Unsuppress (Accessibility_Check);
kono
parents:
diff changeset
886
kono
parents:
diff changeset
887 Element : Element_Access := new Element_Type'(New_Item);
kono
parents:
diff changeset
888
kono
parents:
diff changeset
889 begin
kono
parents:
diff changeset
890 New_Node := new Node_Type'(Element, null, null);
kono
parents:
diff changeset
891 First_Node := New_Node;
kono
parents:
diff changeset
892
kono
parents:
diff changeset
893 exception
kono
parents:
diff changeset
894 when others =>
kono
parents:
diff changeset
895 Free (Element);
kono
parents:
diff changeset
896 raise;
kono
parents:
diff changeset
897 end;
kono
parents:
diff changeset
898
kono
parents:
diff changeset
899 Insert_Internal (Container, Before.Node, New_Node);
kono
parents:
diff changeset
900
kono
parents:
diff changeset
901 for J in 2 .. Count loop
kono
parents:
diff changeset
902 declare
kono
parents:
diff changeset
903 Element : Element_Access := new Element_Type'(New_Item);
kono
parents:
diff changeset
904 begin
kono
parents:
diff changeset
905 New_Node := new Node_Type'(Element, null, null);
kono
parents:
diff changeset
906 exception
kono
parents:
diff changeset
907 when others =>
kono
parents:
diff changeset
908 Free (Element);
kono
parents:
diff changeset
909 raise;
kono
parents:
diff changeset
910 end;
kono
parents:
diff changeset
911
kono
parents:
diff changeset
912 Insert_Internal (Container, Before.Node, New_Node);
kono
parents:
diff changeset
913 end loop;
kono
parents:
diff changeset
914
kono
parents:
diff changeset
915 Position := Cursor'(Container'Unchecked_Access, First_Node);
kono
parents:
diff changeset
916 end Insert;
kono
parents:
diff changeset
917
kono
parents:
diff changeset
918 procedure Insert
kono
parents:
diff changeset
919 (Container : in out List;
kono
parents:
diff changeset
920 Before : Cursor;
kono
parents:
diff changeset
921 New_Item : Element_Type;
kono
parents:
diff changeset
922 Count : Count_Type := 1)
kono
parents:
diff changeset
923 is
kono
parents:
diff changeset
924 Position : Cursor;
kono
parents:
diff changeset
925 pragma Unreferenced (Position);
kono
parents:
diff changeset
926 begin
kono
parents:
diff changeset
927 Insert (Container, Before, New_Item, Position, Count);
kono
parents:
diff changeset
928 end Insert;
kono
parents:
diff changeset
929
kono
parents:
diff changeset
930 ---------------------
kono
parents:
diff changeset
931 -- Insert_Internal --
kono
parents:
diff changeset
932 ---------------------
kono
parents:
diff changeset
933
kono
parents:
diff changeset
934 procedure Insert_Internal
kono
parents:
diff changeset
935 (Container : in out List;
kono
parents:
diff changeset
936 Before : Node_Access;
kono
parents:
diff changeset
937 New_Node : Node_Access)
kono
parents:
diff changeset
938 is
kono
parents:
diff changeset
939 begin
kono
parents:
diff changeset
940 if Container.Length = 0 then
kono
parents:
diff changeset
941 pragma Assert (Before = null);
kono
parents:
diff changeset
942 pragma Assert (Container.First = null);
kono
parents:
diff changeset
943 pragma Assert (Container.Last = null);
kono
parents:
diff changeset
944
kono
parents:
diff changeset
945 Container.First := New_Node;
kono
parents:
diff changeset
946 Container.Last := New_Node;
kono
parents:
diff changeset
947
kono
parents:
diff changeset
948 elsif Before = null then
kono
parents:
diff changeset
949 pragma Assert (Container.Last.Next = null);
kono
parents:
diff changeset
950
kono
parents:
diff changeset
951 Container.Last.Next := New_Node;
kono
parents:
diff changeset
952 New_Node.Prev := Container.Last;
kono
parents:
diff changeset
953
kono
parents:
diff changeset
954 Container.Last := New_Node;
kono
parents:
diff changeset
955
kono
parents:
diff changeset
956 elsif Before = Container.First then
kono
parents:
diff changeset
957 pragma Assert (Container.First.Prev = null);
kono
parents:
diff changeset
958
kono
parents:
diff changeset
959 Container.First.Prev := New_Node;
kono
parents:
diff changeset
960 New_Node.Next := Container.First;
kono
parents:
diff changeset
961
kono
parents:
diff changeset
962 Container.First := New_Node;
kono
parents:
diff changeset
963
kono
parents:
diff changeset
964 else
kono
parents:
diff changeset
965 pragma Assert (Container.First.Prev = null);
kono
parents:
diff changeset
966 pragma Assert (Container.Last.Next = null);
kono
parents:
diff changeset
967
kono
parents:
diff changeset
968 New_Node.Next := Before;
kono
parents:
diff changeset
969 New_Node.Prev := Before.Prev;
kono
parents:
diff changeset
970
kono
parents:
diff changeset
971 Before.Prev.Next := New_Node;
kono
parents:
diff changeset
972 Before.Prev := New_Node;
kono
parents:
diff changeset
973 end if;
kono
parents:
diff changeset
974
kono
parents:
diff changeset
975 Container.Length := Container.Length + 1;
kono
parents:
diff changeset
976 end Insert_Internal;
kono
parents:
diff changeset
977
kono
parents:
diff changeset
978 --------------
kono
parents:
diff changeset
979 -- Is_Empty --
kono
parents:
diff changeset
980 --------------
kono
parents:
diff changeset
981
kono
parents:
diff changeset
982 function Is_Empty (Container : List) return Boolean is
kono
parents:
diff changeset
983 begin
kono
parents:
diff changeset
984 return Container.Length = 0;
kono
parents:
diff changeset
985 end Is_Empty;
kono
parents:
diff changeset
986
kono
parents:
diff changeset
987 -------------
kono
parents:
diff changeset
988 -- Iterate --
kono
parents:
diff changeset
989 -------------
kono
parents:
diff changeset
990
kono
parents:
diff changeset
991 procedure Iterate
kono
parents:
diff changeset
992 (Container : List;
kono
parents:
diff changeset
993 Process : not null access procedure (Position : Cursor))
kono
parents:
diff changeset
994 is
kono
parents:
diff changeset
995 Busy : With_Busy (Container.TC'Unrestricted_Access);
kono
parents:
diff changeset
996 Node : Node_Access := Container.First;
kono
parents:
diff changeset
997
kono
parents:
diff changeset
998 begin
kono
parents:
diff changeset
999 while Node /= null loop
kono
parents:
diff changeset
1000 Process (Cursor'(Container'Unrestricted_Access, Node));
kono
parents:
diff changeset
1001 Node := Node.Next;
kono
parents:
diff changeset
1002 end loop;
kono
parents:
diff changeset
1003 end Iterate;
kono
parents:
diff changeset
1004
kono
parents:
diff changeset
1005 function Iterate
kono
parents:
diff changeset
1006 (Container : List)
kono
parents:
diff changeset
1007 return List_Iterator_Interfaces.Reversible_Iterator'class
kono
parents:
diff changeset
1008 is
kono
parents:
diff changeset
1009 begin
kono
parents:
diff changeset
1010 -- The value of the Node component influences the behavior of the First
kono
parents:
diff changeset
1011 -- and Last selector functions of the iterator object. When the Node
kono
parents:
diff changeset
1012 -- component is null (as is the case here), this means the iterator
kono
parents:
diff changeset
1013 -- object was constructed without a start expression. This is a
kono
parents:
diff changeset
1014 -- complete iterator, meaning that the iteration starts from the
kono
parents:
diff changeset
1015 -- (logical) beginning of the sequence of items.
kono
parents:
diff changeset
1016
kono
parents:
diff changeset
1017 -- Note: For a forward iterator, Container.First is the beginning, and
kono
parents:
diff changeset
1018 -- for a reverse iterator, Container.Last is the beginning.
kono
parents:
diff changeset
1019
kono
parents:
diff changeset
1020 return It : constant Iterator :=
kono
parents:
diff changeset
1021 Iterator'(Limited_Controlled with
kono
parents:
diff changeset
1022 Container => Container'Unrestricted_Access,
kono
parents:
diff changeset
1023 Node => null)
kono
parents:
diff changeset
1024 do
kono
parents:
diff changeset
1025 Busy (Container.TC'Unrestricted_Access.all);
kono
parents:
diff changeset
1026 end return;
kono
parents:
diff changeset
1027 end Iterate;
kono
parents:
diff changeset
1028
kono
parents:
diff changeset
1029 function Iterate
kono
parents:
diff changeset
1030 (Container : List;
kono
parents:
diff changeset
1031 Start : Cursor)
kono
parents:
diff changeset
1032 return List_Iterator_Interfaces.Reversible_Iterator'Class
kono
parents:
diff changeset
1033 is
kono
parents:
diff changeset
1034 begin
kono
parents:
diff changeset
1035 -- It was formerly the case that when Start = No_Element, the partial
kono
parents:
diff changeset
1036 -- iterator was defined to behave the same as for a complete iterator,
kono
parents:
diff changeset
1037 -- and iterate over the entire sequence of items. However, those
kono
parents:
diff changeset
1038 -- semantics were unintuitive and arguably error-prone (it is too easy
kono
parents:
diff changeset
1039 -- to accidentally create an endless loop), and so they were changed,
kono
parents:
diff changeset
1040 -- per the ARG meeting in Denver on 2011/11. However, there was no
kono
parents:
diff changeset
1041 -- consensus about what positive meaning this corner case should have,
kono
parents:
diff changeset
1042 -- and so it was decided to simply raise an exception. This does imply,
kono
parents:
diff changeset
1043 -- however, that it is not possible to use a partial iterator to specify
kono
parents:
diff changeset
1044 -- an empty sequence of items.
kono
parents:
diff changeset
1045
kono
parents:
diff changeset
1046 if Checks and then Start = No_Element then
kono
parents:
diff changeset
1047 raise Constraint_Error with
kono
parents:
diff changeset
1048 "Start position for iterator equals No_Element";
kono
parents:
diff changeset
1049 end if;
kono
parents:
diff changeset
1050
kono
parents:
diff changeset
1051 if Checks and then Start.Container /= Container'Unrestricted_Access then
kono
parents:
diff changeset
1052 raise Program_Error with
kono
parents:
diff changeset
1053 "Start cursor of Iterate designates wrong list";
kono
parents:
diff changeset
1054 end if;
kono
parents:
diff changeset
1055
kono
parents:
diff changeset
1056 pragma Assert (Vet (Start), "Start cursor of Iterate is bad");
kono
parents:
diff changeset
1057
kono
parents:
diff changeset
1058 -- The value of the Node component influences the behavior of the
kono
parents:
diff changeset
1059 -- First and Last selector functions of the iterator object. When
kono
parents:
diff changeset
1060 -- the Node component is non-null (as is the case here), it means
kono
parents:
diff changeset
1061 -- that this is a partial iteration, over a subset of the complete
kono
parents:
diff changeset
1062 -- sequence of items. The iterator object was constructed with
kono
parents:
diff changeset
1063 -- a start expression, indicating the position from which the
kono
parents:
diff changeset
1064 -- iteration begins. Note that the start position has the same value
kono
parents:
diff changeset
1065 -- irrespective of whether this is a forward or reverse iteration.
kono
parents:
diff changeset
1066
kono
parents:
diff changeset
1067 return It : constant Iterator :=
kono
parents:
diff changeset
1068 Iterator'(Limited_Controlled with
kono
parents:
diff changeset
1069 Container => Container'Unrestricted_Access,
kono
parents:
diff changeset
1070 Node => Start.Node)
kono
parents:
diff changeset
1071 do
kono
parents:
diff changeset
1072 Busy (Container.TC'Unrestricted_Access.all);
kono
parents:
diff changeset
1073 end return;
kono
parents:
diff changeset
1074 end Iterate;
kono
parents:
diff changeset
1075
kono
parents:
diff changeset
1076 ----------
kono
parents:
diff changeset
1077 -- Last --
kono
parents:
diff changeset
1078 ----------
kono
parents:
diff changeset
1079
kono
parents:
diff changeset
1080 function Last (Container : List) return Cursor is
kono
parents:
diff changeset
1081 begin
kono
parents:
diff changeset
1082 if Container.Last = null then
kono
parents:
diff changeset
1083 return No_Element;
kono
parents:
diff changeset
1084 else
kono
parents:
diff changeset
1085 return Cursor'(Container'Unrestricted_Access, Container.Last);
kono
parents:
diff changeset
1086 end if;
kono
parents:
diff changeset
1087 end Last;
kono
parents:
diff changeset
1088
kono
parents:
diff changeset
1089 function Last (Object : Iterator) return Cursor is
kono
parents:
diff changeset
1090 begin
kono
parents:
diff changeset
1091 -- The value of the iterator object's Node component influences the
kono
parents:
diff changeset
1092 -- behavior of the Last (and First) selector function.
kono
parents:
diff changeset
1093
kono
parents:
diff changeset
1094 -- When the Node component is null, this means the iterator object was
kono
parents:
diff changeset
1095 -- constructed without a start expression, in which case the (reverse)
kono
parents:
diff changeset
1096 -- iteration starts from the (logical) beginning of the entire sequence
kono
parents:
diff changeset
1097 -- (corresponding to Container.Last, for a reverse iterator).
kono
parents:
diff changeset
1098
kono
parents:
diff changeset
1099 -- Otherwise, this is iteration over a partial sequence of items. When
kono
parents:
diff changeset
1100 -- the Node component is non-null, the iterator object was constructed
kono
parents:
diff changeset
1101 -- with a start expression, that specifies the position from which the
kono
parents:
diff changeset
1102 -- (reverse) partial iteration begins.
kono
parents:
diff changeset
1103
kono
parents:
diff changeset
1104 if Object.Node = null then
kono
parents:
diff changeset
1105 return Indefinite_Doubly_Linked_Lists.Last (Object.Container.all);
kono
parents:
diff changeset
1106 else
kono
parents:
diff changeset
1107 return Cursor'(Object.Container, Object.Node);
kono
parents:
diff changeset
1108 end if;
kono
parents:
diff changeset
1109 end Last;
kono
parents:
diff changeset
1110
kono
parents:
diff changeset
1111 ------------------
kono
parents:
diff changeset
1112 -- Last_Element --
kono
parents:
diff changeset
1113 ------------------
kono
parents:
diff changeset
1114
kono
parents:
diff changeset
1115 function Last_Element (Container : List) return Element_Type is
kono
parents:
diff changeset
1116 begin
kono
parents:
diff changeset
1117 if Checks and then Container.Last = null then
kono
parents:
diff changeset
1118 raise Constraint_Error with "list is empty";
kono
parents:
diff changeset
1119 end if;
kono
parents:
diff changeset
1120
kono
parents:
diff changeset
1121 return Container.Last.Element.all;
kono
parents:
diff changeset
1122 end Last_Element;
kono
parents:
diff changeset
1123
kono
parents:
diff changeset
1124 ------------
kono
parents:
diff changeset
1125 -- Length --
kono
parents:
diff changeset
1126 ------------
kono
parents:
diff changeset
1127
kono
parents:
diff changeset
1128 function Length (Container : List) return Count_Type is
kono
parents:
diff changeset
1129 begin
kono
parents:
diff changeset
1130 return Container.Length;
kono
parents:
diff changeset
1131 end Length;
kono
parents:
diff changeset
1132
kono
parents:
diff changeset
1133 ----------
kono
parents:
diff changeset
1134 -- Move --
kono
parents:
diff changeset
1135 ----------
kono
parents:
diff changeset
1136
kono
parents:
diff changeset
1137 procedure Move (Target : in out List; Source : in out List) is
kono
parents:
diff changeset
1138 begin
kono
parents:
diff changeset
1139 if Target'Address = Source'Address then
kono
parents:
diff changeset
1140 return;
kono
parents:
diff changeset
1141 end if;
kono
parents:
diff changeset
1142
kono
parents:
diff changeset
1143 TC_Check (Source.TC);
kono
parents:
diff changeset
1144
kono
parents:
diff changeset
1145 Clear (Target);
kono
parents:
diff changeset
1146
kono
parents:
diff changeset
1147 Target.First := Source.First;
kono
parents:
diff changeset
1148 Source.First := null;
kono
parents:
diff changeset
1149
kono
parents:
diff changeset
1150 Target.Last := Source.Last;
kono
parents:
diff changeset
1151 Source.Last := null;
kono
parents:
diff changeset
1152
kono
parents:
diff changeset
1153 Target.Length := Source.Length;
kono
parents:
diff changeset
1154 Source.Length := 0;
kono
parents:
diff changeset
1155 end Move;
kono
parents:
diff changeset
1156
kono
parents:
diff changeset
1157 ----------
kono
parents:
diff changeset
1158 -- Next --
kono
parents:
diff changeset
1159 ----------
kono
parents:
diff changeset
1160
kono
parents:
diff changeset
1161 procedure Next (Position : in out Cursor) is
kono
parents:
diff changeset
1162 begin
kono
parents:
diff changeset
1163 Position := Next (Position);
kono
parents:
diff changeset
1164 end Next;
kono
parents:
diff changeset
1165
kono
parents:
diff changeset
1166 function Next (Position : Cursor) return Cursor is
kono
parents:
diff changeset
1167 begin
kono
parents:
diff changeset
1168 if Position.Node = null then
kono
parents:
diff changeset
1169 return No_Element;
kono
parents:
diff changeset
1170
kono
parents:
diff changeset
1171 else
kono
parents:
diff changeset
1172 pragma Assert (Vet (Position), "bad cursor in Next");
kono
parents:
diff changeset
1173
kono
parents:
diff changeset
1174 declare
kono
parents:
diff changeset
1175 Next_Node : constant Node_Access := Position.Node.Next;
kono
parents:
diff changeset
1176 begin
kono
parents:
diff changeset
1177 if Next_Node = null then
kono
parents:
diff changeset
1178 return No_Element;
kono
parents:
diff changeset
1179 else
kono
parents:
diff changeset
1180 return Cursor'(Position.Container, Next_Node);
kono
parents:
diff changeset
1181 end if;
kono
parents:
diff changeset
1182 end;
kono
parents:
diff changeset
1183 end if;
kono
parents:
diff changeset
1184 end Next;
kono
parents:
diff changeset
1185
kono
parents:
diff changeset
1186 function Next (Object : Iterator; Position : Cursor) return Cursor is
kono
parents:
diff changeset
1187 begin
kono
parents:
diff changeset
1188 if Position.Container = null then
kono
parents:
diff changeset
1189 return No_Element;
kono
parents:
diff changeset
1190 end if;
kono
parents:
diff changeset
1191
kono
parents:
diff changeset
1192 if Checks and then Position.Container /= Object.Container then
kono
parents:
diff changeset
1193 raise Program_Error with
kono
parents:
diff changeset
1194 "Position cursor of Next designates wrong list";
kono
parents:
diff changeset
1195 end if;
kono
parents:
diff changeset
1196
kono
parents:
diff changeset
1197 return Next (Position);
kono
parents:
diff changeset
1198 end Next;
kono
parents:
diff changeset
1199
kono
parents:
diff changeset
1200 -------------
kono
parents:
diff changeset
1201 -- Prepend --
kono
parents:
diff changeset
1202 -------------
kono
parents:
diff changeset
1203
kono
parents:
diff changeset
1204 procedure Prepend
kono
parents:
diff changeset
1205 (Container : in out List;
kono
parents:
diff changeset
1206 New_Item : Element_Type;
kono
parents:
diff changeset
1207 Count : Count_Type := 1)
kono
parents:
diff changeset
1208 is
kono
parents:
diff changeset
1209 begin
kono
parents:
diff changeset
1210 Insert (Container, First (Container), New_Item, Count);
kono
parents:
diff changeset
1211 end Prepend;
kono
parents:
diff changeset
1212
kono
parents:
diff changeset
1213 --------------
kono
parents:
diff changeset
1214 -- Previous --
kono
parents:
diff changeset
1215 --------------
kono
parents:
diff changeset
1216
kono
parents:
diff changeset
1217 procedure Previous (Position : in out Cursor) is
kono
parents:
diff changeset
1218 begin
kono
parents:
diff changeset
1219 Position := Previous (Position);
kono
parents:
diff changeset
1220 end Previous;
kono
parents:
diff changeset
1221
kono
parents:
diff changeset
1222 function Previous (Position : Cursor) return Cursor is
kono
parents:
diff changeset
1223 begin
kono
parents:
diff changeset
1224 if Position.Node = null then
kono
parents:
diff changeset
1225 return No_Element;
kono
parents:
diff changeset
1226
kono
parents:
diff changeset
1227 else
kono
parents:
diff changeset
1228 pragma Assert (Vet (Position), "bad cursor in Previous");
kono
parents:
diff changeset
1229
kono
parents:
diff changeset
1230 declare
kono
parents:
diff changeset
1231 Prev_Node : constant Node_Access := Position.Node.Prev;
kono
parents:
diff changeset
1232 begin
kono
parents:
diff changeset
1233 if Prev_Node = null then
kono
parents:
diff changeset
1234 return No_Element;
kono
parents:
diff changeset
1235 else
kono
parents:
diff changeset
1236 return Cursor'(Position.Container, Prev_Node);
kono
parents:
diff changeset
1237 end if;
kono
parents:
diff changeset
1238 end;
kono
parents:
diff changeset
1239 end if;
kono
parents:
diff changeset
1240 end Previous;
kono
parents:
diff changeset
1241
kono
parents:
diff changeset
1242 function Previous (Object : Iterator; Position : Cursor) return Cursor is
kono
parents:
diff changeset
1243 begin
kono
parents:
diff changeset
1244 if Position.Container = null then
kono
parents:
diff changeset
1245 return No_Element;
kono
parents:
diff changeset
1246 end if;
kono
parents:
diff changeset
1247
kono
parents:
diff changeset
1248 if Checks and then Position.Container /= Object.Container then
kono
parents:
diff changeset
1249 raise Program_Error with
kono
parents:
diff changeset
1250 "Position cursor of Previous designates wrong list";
kono
parents:
diff changeset
1251 end if;
kono
parents:
diff changeset
1252
kono
parents:
diff changeset
1253 return Previous (Position);
kono
parents:
diff changeset
1254 end Previous;
kono
parents:
diff changeset
1255
kono
parents:
diff changeset
1256 ----------------------
kono
parents:
diff changeset
1257 -- Pseudo_Reference --
kono
parents:
diff changeset
1258 ----------------------
kono
parents:
diff changeset
1259
kono
parents:
diff changeset
1260 function Pseudo_Reference
kono
parents:
diff changeset
1261 (Container : aliased List'Class) return Reference_Control_Type
kono
parents:
diff changeset
1262 is
kono
parents:
diff changeset
1263 TC : constant Tamper_Counts_Access := Container.TC'Unrestricted_Access;
kono
parents:
diff changeset
1264 begin
kono
parents:
diff changeset
1265 return R : constant Reference_Control_Type := (Controlled with TC) do
kono
parents:
diff changeset
1266 Lock (TC.all);
kono
parents:
diff changeset
1267 end return;
kono
parents:
diff changeset
1268 end Pseudo_Reference;
kono
parents:
diff changeset
1269
kono
parents:
diff changeset
1270 -------------------
kono
parents:
diff changeset
1271 -- Query_Element --
kono
parents:
diff changeset
1272 -------------------
kono
parents:
diff changeset
1273
kono
parents:
diff changeset
1274 procedure Query_Element
kono
parents:
diff changeset
1275 (Position : Cursor;
kono
parents:
diff changeset
1276 Process : not null access procedure (Element : Element_Type))
kono
parents:
diff changeset
1277 is
kono
parents:
diff changeset
1278 begin
kono
parents:
diff changeset
1279 if Checks and then Position.Node = null then
kono
parents:
diff changeset
1280 raise Constraint_Error with
kono
parents:
diff changeset
1281 "Position cursor has no element";
kono
parents:
diff changeset
1282 end if;
kono
parents:
diff changeset
1283
kono
parents:
diff changeset
1284 if Checks and then Position.Node.Element = null then
kono
parents:
diff changeset
1285 raise Program_Error with
kono
parents:
diff changeset
1286 "Position cursor has no element";
kono
parents:
diff changeset
1287 end if;
kono
parents:
diff changeset
1288
kono
parents:
diff changeset
1289 pragma Assert (Vet (Position), "bad cursor in Query_Element");
kono
parents:
diff changeset
1290
kono
parents:
diff changeset
1291 declare
kono
parents:
diff changeset
1292 Lock : With_Lock (Position.Container.TC'Unrestricted_Access);
kono
parents:
diff changeset
1293 begin
kono
parents:
diff changeset
1294 Process (Position.Node.Element.all);
kono
parents:
diff changeset
1295 end;
kono
parents:
diff changeset
1296 end Query_Element;
kono
parents:
diff changeset
1297
kono
parents:
diff changeset
1298 ----------
kono
parents:
diff changeset
1299 -- Read --
kono
parents:
diff changeset
1300 ----------
kono
parents:
diff changeset
1301
kono
parents:
diff changeset
1302 procedure Read
kono
parents:
diff changeset
1303 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
1304 Item : out List)
kono
parents:
diff changeset
1305 is
kono
parents:
diff changeset
1306 N : Count_Type'Base;
kono
parents:
diff changeset
1307 Dst : Node_Access;
kono
parents:
diff changeset
1308
kono
parents:
diff changeset
1309 begin
kono
parents:
diff changeset
1310 Clear (Item);
kono
parents:
diff changeset
1311
kono
parents:
diff changeset
1312 Count_Type'Base'Read (Stream, N);
kono
parents:
diff changeset
1313
kono
parents:
diff changeset
1314 if N = 0 then
kono
parents:
diff changeset
1315 return;
kono
parents:
diff changeset
1316 end if;
kono
parents:
diff changeset
1317
kono
parents:
diff changeset
1318 declare
kono
parents:
diff changeset
1319 Element : Element_Access :=
kono
parents:
diff changeset
1320 new Element_Type'(Element_Type'Input (Stream));
kono
parents:
diff changeset
1321 begin
kono
parents:
diff changeset
1322 Dst := new Node_Type'(Element, null, null);
kono
parents:
diff changeset
1323 exception
kono
parents:
diff changeset
1324 when others =>
kono
parents:
diff changeset
1325 Free (Element);
kono
parents:
diff changeset
1326 raise;
kono
parents:
diff changeset
1327 end;
kono
parents:
diff changeset
1328
kono
parents:
diff changeset
1329 Item.First := Dst;
kono
parents:
diff changeset
1330 Item.Last := Dst;
kono
parents:
diff changeset
1331 Item.Length := 1;
kono
parents:
diff changeset
1332
kono
parents:
diff changeset
1333 while Item.Length < N loop
kono
parents:
diff changeset
1334 declare
kono
parents:
diff changeset
1335 Element : Element_Access :=
kono
parents:
diff changeset
1336 new Element_Type'(Element_Type'Input (Stream));
kono
parents:
diff changeset
1337 begin
kono
parents:
diff changeset
1338 Dst := new Node_Type'(Element, Next => null, Prev => Item.Last);
kono
parents:
diff changeset
1339 exception
kono
parents:
diff changeset
1340 when others =>
kono
parents:
diff changeset
1341 Free (Element);
kono
parents:
diff changeset
1342 raise;
kono
parents:
diff changeset
1343 end;
kono
parents:
diff changeset
1344
kono
parents:
diff changeset
1345 Item.Last.Next := Dst;
kono
parents:
diff changeset
1346 Item.Last := Dst;
kono
parents:
diff changeset
1347 Item.Length := Item.Length + 1;
kono
parents:
diff changeset
1348 end loop;
kono
parents:
diff changeset
1349 end Read;
kono
parents:
diff changeset
1350
kono
parents:
diff changeset
1351 procedure Read
kono
parents:
diff changeset
1352 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
1353 Item : out Cursor)
kono
parents:
diff changeset
1354 is
kono
parents:
diff changeset
1355 begin
kono
parents:
diff changeset
1356 raise Program_Error with "attempt to stream list cursor";
kono
parents:
diff changeset
1357 end Read;
kono
parents:
diff changeset
1358
kono
parents:
diff changeset
1359 procedure Read
kono
parents:
diff changeset
1360 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
1361 Item : out Reference_Type)
kono
parents:
diff changeset
1362 is
kono
parents:
diff changeset
1363 begin
kono
parents:
diff changeset
1364 raise Program_Error with "attempt to stream reference";
kono
parents:
diff changeset
1365 end Read;
kono
parents:
diff changeset
1366
kono
parents:
diff changeset
1367 procedure Read
kono
parents:
diff changeset
1368 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
1369 Item : out Constant_Reference_Type)
kono
parents:
diff changeset
1370 is
kono
parents:
diff changeset
1371 begin
kono
parents:
diff changeset
1372 raise Program_Error with "attempt to stream reference";
kono
parents:
diff changeset
1373 end Read;
kono
parents:
diff changeset
1374
kono
parents:
diff changeset
1375 ---------------
kono
parents:
diff changeset
1376 -- Reference --
kono
parents:
diff changeset
1377 ---------------
kono
parents:
diff changeset
1378
kono
parents:
diff changeset
1379 function Reference
kono
parents:
diff changeset
1380 (Container : aliased in out List;
kono
parents:
diff changeset
1381 Position : Cursor) return Reference_Type
kono
parents:
diff changeset
1382 is
kono
parents:
diff changeset
1383 begin
kono
parents:
diff changeset
1384 if Checks and then Position.Container = null then
kono
parents:
diff changeset
1385 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
1386 end if;
kono
parents:
diff changeset
1387
kono
parents:
diff changeset
1388 if Checks and then Position.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
1389 then
kono
parents:
diff changeset
1390 raise Program_Error with
kono
parents:
diff changeset
1391 "Position cursor designates wrong container";
kono
parents:
diff changeset
1392 end if;
kono
parents:
diff changeset
1393
kono
parents:
diff changeset
1394 if Checks and then Position.Node.Element = null then
kono
parents:
diff changeset
1395 raise Program_Error with "Node has no element";
kono
parents:
diff changeset
1396 end if;
kono
parents:
diff changeset
1397
kono
parents:
diff changeset
1398 pragma Assert (Vet (Position), "bad cursor in function Reference");
kono
parents:
diff changeset
1399
kono
parents:
diff changeset
1400 declare
kono
parents:
diff changeset
1401 TC : constant Tamper_Counts_Access :=
kono
parents:
diff changeset
1402 Container.TC'Unrestricted_Access;
kono
parents:
diff changeset
1403 begin
kono
parents:
diff changeset
1404 return R : constant Reference_Type :=
kono
parents:
diff changeset
1405 (Element => Position.Node.Element,
kono
parents:
diff changeset
1406 Control => (Controlled with TC))
kono
parents:
diff changeset
1407 do
kono
parents:
diff changeset
1408 Lock (TC.all);
kono
parents:
diff changeset
1409 end return;
kono
parents:
diff changeset
1410 end;
kono
parents:
diff changeset
1411 end Reference;
kono
parents:
diff changeset
1412
kono
parents:
diff changeset
1413 ---------------------
kono
parents:
diff changeset
1414 -- Replace_Element --
kono
parents:
diff changeset
1415 ---------------------
kono
parents:
diff changeset
1416
kono
parents:
diff changeset
1417 procedure Replace_Element
kono
parents:
diff changeset
1418 (Container : in out List;
kono
parents:
diff changeset
1419 Position : Cursor;
kono
parents:
diff changeset
1420 New_Item : Element_Type)
kono
parents:
diff changeset
1421 is
kono
parents:
diff changeset
1422 begin
kono
parents:
diff changeset
1423 if Checks and then Position.Container = null then
kono
parents:
diff changeset
1424 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
1425 end if;
kono
parents:
diff changeset
1426
kono
parents:
diff changeset
1427 if Checks and then Position.Container /= Container'Unchecked_Access then
kono
parents:
diff changeset
1428 raise Program_Error with
kono
parents:
diff changeset
1429 "Position cursor designates wrong container";
kono
parents:
diff changeset
1430 end if;
kono
parents:
diff changeset
1431
kono
parents:
diff changeset
1432 TE_Check (Container.TC);
kono
parents:
diff changeset
1433
kono
parents:
diff changeset
1434 if Checks and then Position.Node.Element = null then
kono
parents:
diff changeset
1435 raise Program_Error with
kono
parents:
diff changeset
1436 "Position cursor has no element";
kono
parents:
diff changeset
1437 end if;
kono
parents:
diff changeset
1438
kono
parents:
diff changeset
1439 pragma Assert (Vet (Position), "bad cursor in Replace_Element");
kono
parents:
diff changeset
1440
kono
parents:
diff changeset
1441 declare
kono
parents:
diff changeset
1442 -- The element allocator may need an accessibility check in the
kono
parents:
diff changeset
1443 -- case the actual type is class-wide or has access discriminants
kono
parents:
diff changeset
1444 -- (see RM 4.8(10.1) and AI12-0035).
kono
parents:
diff changeset
1445
kono
parents:
diff changeset
1446 pragma Unsuppress (Accessibility_Check);
kono
parents:
diff changeset
1447
kono
parents:
diff changeset
1448 X : Element_Access := Position.Node.Element;
kono
parents:
diff changeset
1449
kono
parents:
diff changeset
1450 begin
kono
parents:
diff changeset
1451 Position.Node.Element := new Element_Type'(New_Item);
kono
parents:
diff changeset
1452 Free (X);
kono
parents:
diff changeset
1453 end;
kono
parents:
diff changeset
1454 end Replace_Element;
kono
parents:
diff changeset
1455
kono
parents:
diff changeset
1456 ----------------------
kono
parents:
diff changeset
1457 -- Reverse_Elements --
kono
parents:
diff changeset
1458 ----------------------
kono
parents:
diff changeset
1459
kono
parents:
diff changeset
1460 procedure Reverse_Elements (Container : in out List) is
kono
parents:
diff changeset
1461 I : Node_Access := Container.First;
kono
parents:
diff changeset
1462 J : Node_Access := Container.Last;
kono
parents:
diff changeset
1463
kono
parents:
diff changeset
1464 procedure Swap (L, R : Node_Access);
kono
parents:
diff changeset
1465
kono
parents:
diff changeset
1466 ----------
kono
parents:
diff changeset
1467 -- Swap --
kono
parents:
diff changeset
1468 ----------
kono
parents:
diff changeset
1469
kono
parents:
diff changeset
1470 procedure Swap (L, R : Node_Access) is
kono
parents:
diff changeset
1471 LN : constant Node_Access := L.Next;
kono
parents:
diff changeset
1472 LP : constant Node_Access := L.Prev;
kono
parents:
diff changeset
1473
kono
parents:
diff changeset
1474 RN : constant Node_Access := R.Next;
kono
parents:
diff changeset
1475 RP : constant Node_Access := R.Prev;
kono
parents:
diff changeset
1476
kono
parents:
diff changeset
1477 begin
kono
parents:
diff changeset
1478 if LP /= null then
kono
parents:
diff changeset
1479 LP.Next := R;
kono
parents:
diff changeset
1480 end if;
kono
parents:
diff changeset
1481
kono
parents:
diff changeset
1482 if RN /= null then
kono
parents:
diff changeset
1483 RN.Prev := L;
kono
parents:
diff changeset
1484 end if;
kono
parents:
diff changeset
1485
kono
parents:
diff changeset
1486 L.Next := RN;
kono
parents:
diff changeset
1487 R.Prev := LP;
kono
parents:
diff changeset
1488
kono
parents:
diff changeset
1489 if LN = R then
kono
parents:
diff changeset
1490 pragma Assert (RP = L);
kono
parents:
diff changeset
1491
kono
parents:
diff changeset
1492 L.Prev := R;
kono
parents:
diff changeset
1493 R.Next := L;
kono
parents:
diff changeset
1494
kono
parents:
diff changeset
1495 else
kono
parents:
diff changeset
1496 L.Prev := RP;
kono
parents:
diff changeset
1497 RP.Next := L;
kono
parents:
diff changeset
1498
kono
parents:
diff changeset
1499 R.Next := LN;
kono
parents:
diff changeset
1500 LN.Prev := R;
kono
parents:
diff changeset
1501 end if;
kono
parents:
diff changeset
1502 end Swap;
kono
parents:
diff changeset
1503
kono
parents:
diff changeset
1504 -- Start of processing for Reverse_Elements
kono
parents:
diff changeset
1505
kono
parents:
diff changeset
1506 begin
kono
parents:
diff changeset
1507 if Container.Length <= 1 then
kono
parents:
diff changeset
1508 return;
kono
parents:
diff changeset
1509 end if;
kono
parents:
diff changeset
1510
kono
parents:
diff changeset
1511 pragma Assert (Container.First.Prev = null);
kono
parents:
diff changeset
1512 pragma Assert (Container.Last.Next = null);
kono
parents:
diff changeset
1513
kono
parents:
diff changeset
1514 TC_Check (Container.TC);
kono
parents:
diff changeset
1515
kono
parents:
diff changeset
1516 Container.First := J;
kono
parents:
diff changeset
1517 Container.Last := I;
kono
parents:
diff changeset
1518 loop
kono
parents:
diff changeset
1519 Swap (L => I, R => J);
kono
parents:
diff changeset
1520
kono
parents:
diff changeset
1521 J := J.Next;
kono
parents:
diff changeset
1522 exit when I = J;
kono
parents:
diff changeset
1523
kono
parents:
diff changeset
1524 I := I.Prev;
kono
parents:
diff changeset
1525 exit when I = J;
kono
parents:
diff changeset
1526
kono
parents:
diff changeset
1527 Swap (L => J, R => I);
kono
parents:
diff changeset
1528
kono
parents:
diff changeset
1529 I := I.Next;
kono
parents:
diff changeset
1530 exit when I = J;
kono
parents:
diff changeset
1531
kono
parents:
diff changeset
1532 J := J.Prev;
kono
parents:
diff changeset
1533 exit when I = J;
kono
parents:
diff changeset
1534 end loop;
kono
parents:
diff changeset
1535
kono
parents:
diff changeset
1536 pragma Assert (Container.First.Prev = null);
kono
parents:
diff changeset
1537 pragma Assert (Container.Last.Next = null);
kono
parents:
diff changeset
1538 end Reverse_Elements;
kono
parents:
diff changeset
1539
kono
parents:
diff changeset
1540 ------------------
kono
parents:
diff changeset
1541 -- Reverse_Find --
kono
parents:
diff changeset
1542 ------------------
kono
parents:
diff changeset
1543
kono
parents:
diff changeset
1544 function Reverse_Find
kono
parents:
diff changeset
1545 (Container : List;
kono
parents:
diff changeset
1546 Item : Element_Type;
kono
parents:
diff changeset
1547 Position : Cursor := No_Element) return Cursor
kono
parents:
diff changeset
1548 is
kono
parents:
diff changeset
1549 Node : Node_Access := Position.Node;
kono
parents:
diff changeset
1550
kono
parents:
diff changeset
1551 begin
kono
parents:
diff changeset
1552 if Node = null then
kono
parents:
diff changeset
1553 Node := Container.Last;
kono
parents:
diff changeset
1554
kono
parents:
diff changeset
1555 else
kono
parents:
diff changeset
1556 if Checks and then Node.Element = null then
kono
parents:
diff changeset
1557 raise Program_Error with "Position cursor has no element";
kono
parents:
diff changeset
1558 end if;
kono
parents:
diff changeset
1559
kono
parents:
diff changeset
1560 if Checks and then Position.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
1561 then
kono
parents:
diff changeset
1562 raise Program_Error with
kono
parents:
diff changeset
1563 "Position cursor designates wrong container";
kono
parents:
diff changeset
1564 end if;
kono
parents:
diff changeset
1565
kono
parents:
diff changeset
1566 pragma Assert (Vet (Position), "bad cursor in Reverse_Find");
kono
parents:
diff changeset
1567 end if;
kono
parents:
diff changeset
1568
kono
parents:
diff changeset
1569 -- Per AI05-0022, the container implementation is required to detect
kono
parents:
diff changeset
1570 -- element tampering by a generic actual subprogram.
kono
parents:
diff changeset
1571
kono
parents:
diff changeset
1572 declare
kono
parents:
diff changeset
1573 Lock : With_Lock (Container.TC'Unrestricted_Access);
kono
parents:
diff changeset
1574 begin
kono
parents:
diff changeset
1575 while Node /= null loop
kono
parents:
diff changeset
1576 if Node.Element.all = Item then
kono
parents:
diff changeset
1577 return Cursor'(Container'Unrestricted_Access, Node);
kono
parents:
diff changeset
1578 end if;
kono
parents:
diff changeset
1579
kono
parents:
diff changeset
1580 Node := Node.Prev;
kono
parents:
diff changeset
1581 end loop;
kono
parents:
diff changeset
1582
kono
parents:
diff changeset
1583 return No_Element;
kono
parents:
diff changeset
1584 end;
kono
parents:
diff changeset
1585 end Reverse_Find;
kono
parents:
diff changeset
1586
kono
parents:
diff changeset
1587 ---------------------
kono
parents:
diff changeset
1588 -- Reverse_Iterate --
kono
parents:
diff changeset
1589 ---------------------
kono
parents:
diff changeset
1590
kono
parents:
diff changeset
1591 procedure Reverse_Iterate
kono
parents:
diff changeset
1592 (Container : List;
kono
parents:
diff changeset
1593 Process : not null access procedure (Position : Cursor))
kono
parents:
diff changeset
1594 is
kono
parents:
diff changeset
1595 Busy : With_Busy (Container.TC'Unrestricted_Access);
kono
parents:
diff changeset
1596 Node : Node_Access := Container.Last;
kono
parents:
diff changeset
1597
kono
parents:
diff changeset
1598 begin
kono
parents:
diff changeset
1599 while Node /= null loop
kono
parents:
diff changeset
1600 Process (Cursor'(Container'Unrestricted_Access, Node));
kono
parents:
diff changeset
1601 Node := Node.Prev;
kono
parents:
diff changeset
1602 end loop;
kono
parents:
diff changeset
1603 end Reverse_Iterate;
kono
parents:
diff changeset
1604
kono
parents:
diff changeset
1605 ------------
kono
parents:
diff changeset
1606 -- Splice --
kono
parents:
diff changeset
1607 ------------
kono
parents:
diff changeset
1608
kono
parents:
diff changeset
1609 procedure Splice
kono
parents:
diff changeset
1610 (Target : in out List;
kono
parents:
diff changeset
1611 Before : Cursor;
kono
parents:
diff changeset
1612 Source : in out List)
kono
parents:
diff changeset
1613 is
kono
parents:
diff changeset
1614 begin
kono
parents:
diff changeset
1615 if Before.Container /= null then
kono
parents:
diff changeset
1616 if Checks and then Before.Container /= Target'Unrestricted_Access then
kono
parents:
diff changeset
1617 raise Program_Error with
kono
parents:
diff changeset
1618 "Before cursor designates wrong container";
kono
parents:
diff changeset
1619 end if;
kono
parents:
diff changeset
1620
kono
parents:
diff changeset
1621 if Checks and then
kono
parents:
diff changeset
1622 (Before.Node = null or else Before.Node.Element = null)
kono
parents:
diff changeset
1623 then
kono
parents:
diff changeset
1624 raise Program_Error with
kono
parents:
diff changeset
1625 "Before cursor has no element";
kono
parents:
diff changeset
1626 end if;
kono
parents:
diff changeset
1627
kono
parents:
diff changeset
1628 pragma Assert (Vet (Before), "bad cursor in Splice");
kono
parents:
diff changeset
1629 end if;
kono
parents:
diff changeset
1630
kono
parents:
diff changeset
1631 if Target'Address = Source'Address or else Source.Length = 0 then
kono
parents:
diff changeset
1632 return;
kono
parents:
diff changeset
1633 end if;
kono
parents:
diff changeset
1634
kono
parents:
diff changeset
1635 if Checks and then Target.Length > Count_Type'Last - Source.Length then
kono
parents:
diff changeset
1636 raise Constraint_Error with "new length exceeds maximum";
kono
parents:
diff changeset
1637 end if;
kono
parents:
diff changeset
1638
kono
parents:
diff changeset
1639 TC_Check (Target.TC);
kono
parents:
diff changeset
1640 TC_Check (Source.TC);
kono
parents:
diff changeset
1641
kono
parents:
diff changeset
1642 Splice_Internal (Target, Before.Node, Source);
kono
parents:
diff changeset
1643 end Splice;
kono
parents:
diff changeset
1644
kono
parents:
diff changeset
1645 procedure Splice
kono
parents:
diff changeset
1646 (Container : in out List;
kono
parents:
diff changeset
1647 Before : Cursor;
kono
parents:
diff changeset
1648 Position : Cursor)
kono
parents:
diff changeset
1649 is
kono
parents:
diff changeset
1650 begin
kono
parents:
diff changeset
1651 if Before.Container /= null then
kono
parents:
diff changeset
1652 if Checks and then Before.Container /= Container'Unchecked_Access then
kono
parents:
diff changeset
1653 raise Program_Error with
kono
parents:
diff changeset
1654 "Before cursor designates wrong container";
kono
parents:
diff changeset
1655 end if;
kono
parents:
diff changeset
1656
kono
parents:
diff changeset
1657 if Checks and then
kono
parents:
diff changeset
1658 (Before.Node = null or else Before.Node.Element = null)
kono
parents:
diff changeset
1659 then
kono
parents:
diff changeset
1660 raise Program_Error with
kono
parents:
diff changeset
1661 "Before cursor has no element";
kono
parents:
diff changeset
1662 end if;
kono
parents:
diff changeset
1663
kono
parents:
diff changeset
1664 pragma Assert (Vet (Before), "bad Before cursor in Splice");
kono
parents:
diff changeset
1665 end if;
kono
parents:
diff changeset
1666
kono
parents:
diff changeset
1667 if Checks and then Position.Node = null then
kono
parents:
diff changeset
1668 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
1669 end if;
kono
parents:
diff changeset
1670
kono
parents:
diff changeset
1671 if Checks and then Position.Node.Element = null then
kono
parents:
diff changeset
1672 raise Program_Error with "Position cursor has no element";
kono
parents:
diff changeset
1673 end if;
kono
parents:
diff changeset
1674
kono
parents:
diff changeset
1675 if Checks and then Position.Container /= Container'Unrestricted_Access
kono
parents:
diff changeset
1676 then
kono
parents:
diff changeset
1677 raise Program_Error with
kono
parents:
diff changeset
1678 "Position cursor designates wrong container";
kono
parents:
diff changeset
1679 end if;
kono
parents:
diff changeset
1680
kono
parents:
diff changeset
1681 pragma Assert (Vet (Position), "bad Position cursor in Splice");
kono
parents:
diff changeset
1682
kono
parents:
diff changeset
1683 if Position.Node = Before.Node
kono
parents:
diff changeset
1684 or else Position.Node.Next = Before.Node
kono
parents:
diff changeset
1685 then
kono
parents:
diff changeset
1686 return;
kono
parents:
diff changeset
1687 end if;
kono
parents:
diff changeset
1688
kono
parents:
diff changeset
1689 pragma Assert (Container.Length >= 2);
kono
parents:
diff changeset
1690
kono
parents:
diff changeset
1691 TC_Check (Container.TC);
kono
parents:
diff changeset
1692
kono
parents:
diff changeset
1693 if Before.Node = null then
kono
parents:
diff changeset
1694 pragma Assert (Position.Node /= Container.Last);
kono
parents:
diff changeset
1695
kono
parents:
diff changeset
1696 if Position.Node = Container.First then
kono
parents:
diff changeset
1697 Container.First := Position.Node.Next;
kono
parents:
diff changeset
1698 Container.First.Prev := null;
kono
parents:
diff changeset
1699 else
kono
parents:
diff changeset
1700 Position.Node.Prev.Next := Position.Node.Next;
kono
parents:
diff changeset
1701 Position.Node.Next.Prev := Position.Node.Prev;
kono
parents:
diff changeset
1702 end if;
kono
parents:
diff changeset
1703
kono
parents:
diff changeset
1704 Container.Last.Next := Position.Node;
kono
parents:
diff changeset
1705 Position.Node.Prev := Container.Last;
kono
parents:
diff changeset
1706
kono
parents:
diff changeset
1707 Container.Last := Position.Node;
kono
parents:
diff changeset
1708 Container.Last.Next := null;
kono
parents:
diff changeset
1709
kono
parents:
diff changeset
1710 return;
kono
parents:
diff changeset
1711 end if;
kono
parents:
diff changeset
1712
kono
parents:
diff changeset
1713 if Before.Node = Container.First then
kono
parents:
diff changeset
1714 pragma Assert (Position.Node /= Container.First);
kono
parents:
diff changeset
1715
kono
parents:
diff changeset
1716 if Position.Node = Container.Last then
kono
parents:
diff changeset
1717 Container.Last := Position.Node.Prev;
kono
parents:
diff changeset
1718 Container.Last.Next := null;
kono
parents:
diff changeset
1719 else
kono
parents:
diff changeset
1720 Position.Node.Prev.Next := Position.Node.Next;
kono
parents:
diff changeset
1721 Position.Node.Next.Prev := Position.Node.Prev;
kono
parents:
diff changeset
1722 end if;
kono
parents:
diff changeset
1723
kono
parents:
diff changeset
1724 Container.First.Prev := Position.Node;
kono
parents:
diff changeset
1725 Position.Node.Next := Container.First;
kono
parents:
diff changeset
1726
kono
parents:
diff changeset
1727 Container.First := Position.Node;
kono
parents:
diff changeset
1728 Container.First.Prev := null;
kono
parents:
diff changeset
1729
kono
parents:
diff changeset
1730 return;
kono
parents:
diff changeset
1731 end if;
kono
parents:
diff changeset
1732
kono
parents:
diff changeset
1733 if Position.Node = Container.First then
kono
parents:
diff changeset
1734 Container.First := Position.Node.Next;
kono
parents:
diff changeset
1735 Container.First.Prev := null;
kono
parents:
diff changeset
1736
kono
parents:
diff changeset
1737 elsif Position.Node = Container.Last then
kono
parents:
diff changeset
1738 Container.Last := Position.Node.Prev;
kono
parents:
diff changeset
1739 Container.Last.Next := null;
kono
parents:
diff changeset
1740
kono
parents:
diff changeset
1741 else
kono
parents:
diff changeset
1742 Position.Node.Prev.Next := Position.Node.Next;
kono
parents:
diff changeset
1743 Position.Node.Next.Prev := Position.Node.Prev;
kono
parents:
diff changeset
1744 end if;
kono
parents:
diff changeset
1745
kono
parents:
diff changeset
1746 Before.Node.Prev.Next := Position.Node;
kono
parents:
diff changeset
1747 Position.Node.Prev := Before.Node.Prev;
kono
parents:
diff changeset
1748
kono
parents:
diff changeset
1749 Before.Node.Prev := Position.Node;
kono
parents:
diff changeset
1750 Position.Node.Next := Before.Node;
kono
parents:
diff changeset
1751
kono
parents:
diff changeset
1752 pragma Assert (Container.First.Prev = null);
kono
parents:
diff changeset
1753 pragma Assert (Container.Last.Next = null);
kono
parents:
diff changeset
1754 end Splice;
kono
parents:
diff changeset
1755
kono
parents:
diff changeset
1756 procedure Splice
kono
parents:
diff changeset
1757 (Target : in out List;
kono
parents:
diff changeset
1758 Before : Cursor;
kono
parents:
diff changeset
1759 Source : in out List;
kono
parents:
diff changeset
1760 Position : in out Cursor)
kono
parents:
diff changeset
1761 is
kono
parents:
diff changeset
1762 begin
kono
parents:
diff changeset
1763 if Target'Address = Source'Address then
kono
parents:
diff changeset
1764 Splice (Target, Before, Position);
kono
parents:
diff changeset
1765 return;
kono
parents:
diff changeset
1766 end if;
kono
parents:
diff changeset
1767
kono
parents:
diff changeset
1768 if Before.Container /= null then
kono
parents:
diff changeset
1769 if Checks and then Before.Container /= Target'Unrestricted_Access then
kono
parents:
diff changeset
1770 raise Program_Error with
kono
parents:
diff changeset
1771 "Before cursor designates wrong container";
kono
parents:
diff changeset
1772 end if;
kono
parents:
diff changeset
1773
kono
parents:
diff changeset
1774 if Checks and then
kono
parents:
diff changeset
1775 (Before.Node = null or else Before.Node.Element = null)
kono
parents:
diff changeset
1776 then
kono
parents:
diff changeset
1777 raise Program_Error with
kono
parents:
diff changeset
1778 "Before cursor has no element";
kono
parents:
diff changeset
1779 end if;
kono
parents:
diff changeset
1780
kono
parents:
diff changeset
1781 pragma Assert (Vet (Before), "bad Before cursor in Splice");
kono
parents:
diff changeset
1782 end if;
kono
parents:
diff changeset
1783
kono
parents:
diff changeset
1784 if Checks and then Position.Node = null then
kono
parents:
diff changeset
1785 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
1786 end if;
kono
parents:
diff changeset
1787
kono
parents:
diff changeset
1788 if Checks and then Position.Node.Element = null then
kono
parents:
diff changeset
1789 raise Program_Error with
kono
parents:
diff changeset
1790 "Position cursor has no element";
kono
parents:
diff changeset
1791 end if;
kono
parents:
diff changeset
1792
kono
parents:
diff changeset
1793 if Checks and then Position.Container /= Source'Unrestricted_Access then
kono
parents:
diff changeset
1794 raise Program_Error with
kono
parents:
diff changeset
1795 "Position cursor designates wrong container";
kono
parents:
diff changeset
1796 end if;
kono
parents:
diff changeset
1797
kono
parents:
diff changeset
1798 pragma Assert (Vet (Position), "bad Position cursor in Splice");
kono
parents:
diff changeset
1799
kono
parents:
diff changeset
1800 if Checks and then Target.Length = Count_Type'Last then
kono
parents:
diff changeset
1801 raise Constraint_Error with "Target is full";
kono
parents:
diff changeset
1802 end if;
kono
parents:
diff changeset
1803
kono
parents:
diff changeset
1804 TC_Check (Target.TC);
kono
parents:
diff changeset
1805 TC_Check (Source.TC);
kono
parents:
diff changeset
1806
kono
parents:
diff changeset
1807 Splice_Internal (Target, Before.Node, Source, Position.Node);
kono
parents:
diff changeset
1808 Position.Container := Target'Unchecked_Access;
kono
parents:
diff changeset
1809 end Splice;
kono
parents:
diff changeset
1810
kono
parents:
diff changeset
1811 ---------------------
kono
parents:
diff changeset
1812 -- Splice_Internal --
kono
parents:
diff changeset
1813 ---------------------
kono
parents:
diff changeset
1814
kono
parents:
diff changeset
1815 procedure Splice_Internal
kono
parents:
diff changeset
1816 (Target : in out List;
kono
parents:
diff changeset
1817 Before : Node_Access;
kono
parents:
diff changeset
1818 Source : in out List)
kono
parents:
diff changeset
1819 is
kono
parents:
diff changeset
1820 begin
kono
parents:
diff changeset
1821 -- This implements the corresponding Splice operation, after the
kono
parents:
diff changeset
1822 -- parameters have been vetted, and corner-cases disposed of.
kono
parents:
diff changeset
1823
kono
parents:
diff changeset
1824 pragma Assert (Target'Address /= Source'Address);
kono
parents:
diff changeset
1825 pragma Assert (Source.Length > 0);
kono
parents:
diff changeset
1826 pragma Assert (Source.First /= null);
kono
parents:
diff changeset
1827 pragma Assert (Source.First.Prev = null);
kono
parents:
diff changeset
1828 pragma Assert (Source.Last /= null);
kono
parents:
diff changeset
1829 pragma Assert (Source.Last.Next = null);
kono
parents:
diff changeset
1830 pragma Assert (Target.Length <= Count_Type'Last - Source.Length);
kono
parents:
diff changeset
1831
kono
parents:
diff changeset
1832 if Target.Length = 0 then
kono
parents:
diff changeset
1833 pragma Assert (Before = null);
kono
parents:
diff changeset
1834 pragma Assert (Target.First = null);
kono
parents:
diff changeset
1835 pragma Assert (Target.Last = null);
kono
parents:
diff changeset
1836
kono
parents:
diff changeset
1837 Target.First := Source.First;
kono
parents:
diff changeset
1838 Target.Last := Source.Last;
kono
parents:
diff changeset
1839
kono
parents:
diff changeset
1840 elsif Before = null then
kono
parents:
diff changeset
1841 pragma Assert (Target.Last.Next = null);
kono
parents:
diff changeset
1842
kono
parents:
diff changeset
1843 Target.Last.Next := Source.First;
kono
parents:
diff changeset
1844 Source.First.Prev := Target.Last;
kono
parents:
diff changeset
1845
kono
parents:
diff changeset
1846 Target.Last := Source.Last;
kono
parents:
diff changeset
1847
kono
parents:
diff changeset
1848 elsif Before = Target.First then
kono
parents:
diff changeset
1849 pragma Assert (Target.First.Prev = null);
kono
parents:
diff changeset
1850
kono
parents:
diff changeset
1851 Source.Last.Next := Target.First;
kono
parents:
diff changeset
1852 Target.First.Prev := Source.Last;
kono
parents:
diff changeset
1853
kono
parents:
diff changeset
1854 Target.First := Source.First;
kono
parents:
diff changeset
1855
kono
parents:
diff changeset
1856 else
kono
parents:
diff changeset
1857 pragma Assert (Target.Length >= 2);
kono
parents:
diff changeset
1858 Before.Prev.Next := Source.First;
kono
parents:
diff changeset
1859 Source.First.Prev := Before.Prev;
kono
parents:
diff changeset
1860
kono
parents:
diff changeset
1861 Before.Prev := Source.Last;
kono
parents:
diff changeset
1862 Source.Last.Next := Before;
kono
parents:
diff changeset
1863 end if;
kono
parents:
diff changeset
1864
kono
parents:
diff changeset
1865 Source.First := null;
kono
parents:
diff changeset
1866 Source.Last := null;
kono
parents:
diff changeset
1867
kono
parents:
diff changeset
1868 Target.Length := Target.Length + Source.Length;
kono
parents:
diff changeset
1869 Source.Length := 0;
kono
parents:
diff changeset
1870 end Splice_Internal;
kono
parents:
diff changeset
1871
kono
parents:
diff changeset
1872 procedure Splice_Internal
kono
parents:
diff changeset
1873 (Target : in out List;
kono
parents:
diff changeset
1874 Before : Node_Access; -- node of Target
kono
parents:
diff changeset
1875 Source : in out List;
kono
parents:
diff changeset
1876 Position : Node_Access) -- node of Source
kono
parents:
diff changeset
1877 is
kono
parents:
diff changeset
1878 begin
kono
parents:
diff changeset
1879 -- This implements the corresponding Splice operation, after the
kono
parents:
diff changeset
1880 -- parameters have been vetted.
kono
parents:
diff changeset
1881
kono
parents:
diff changeset
1882 pragma Assert (Target'Address /= Source'Address);
kono
parents:
diff changeset
1883 pragma Assert (Target.Length < Count_Type'Last);
kono
parents:
diff changeset
1884 pragma Assert (Source.Length > 0);
kono
parents:
diff changeset
1885 pragma Assert (Source.First /= null);
kono
parents:
diff changeset
1886 pragma Assert (Source.First.Prev = null);
kono
parents:
diff changeset
1887 pragma Assert (Source.Last /= null);
kono
parents:
diff changeset
1888 pragma Assert (Source.Last.Next = null);
kono
parents:
diff changeset
1889 pragma Assert (Position /= null);
kono
parents:
diff changeset
1890
kono
parents:
diff changeset
1891 if Position = Source.First then
kono
parents:
diff changeset
1892 Source.First := Position.Next;
kono
parents:
diff changeset
1893
kono
parents:
diff changeset
1894 if Position = Source.Last then
kono
parents:
diff changeset
1895 pragma Assert (Source.First = null);
kono
parents:
diff changeset
1896 pragma Assert (Source.Length = 1);
kono
parents:
diff changeset
1897 Source.Last := null;
kono
parents:
diff changeset
1898
kono
parents:
diff changeset
1899 else
kono
parents:
diff changeset
1900 Source.First.Prev := null;
kono
parents:
diff changeset
1901 end if;
kono
parents:
diff changeset
1902
kono
parents:
diff changeset
1903 elsif Position = Source.Last then
kono
parents:
diff changeset
1904 pragma Assert (Source.Length >= 2);
kono
parents:
diff changeset
1905 Source.Last := Position.Prev;
kono
parents:
diff changeset
1906 Source.Last.Next := null;
kono
parents:
diff changeset
1907
kono
parents:
diff changeset
1908 else
kono
parents:
diff changeset
1909 pragma Assert (Source.Length >= 3);
kono
parents:
diff changeset
1910 Position.Prev.Next := Position.Next;
kono
parents:
diff changeset
1911 Position.Next.Prev := Position.Prev;
kono
parents:
diff changeset
1912 end if;
kono
parents:
diff changeset
1913
kono
parents:
diff changeset
1914 if Target.Length = 0 then
kono
parents:
diff changeset
1915 pragma Assert (Before = null);
kono
parents:
diff changeset
1916 pragma Assert (Target.First = null);
kono
parents:
diff changeset
1917 pragma Assert (Target.Last = null);
kono
parents:
diff changeset
1918
kono
parents:
diff changeset
1919 Target.First := Position;
kono
parents:
diff changeset
1920 Target.Last := Position;
kono
parents:
diff changeset
1921
kono
parents:
diff changeset
1922 Target.First.Prev := null;
kono
parents:
diff changeset
1923 Target.Last.Next := null;
kono
parents:
diff changeset
1924
kono
parents:
diff changeset
1925 elsif Before = null then
kono
parents:
diff changeset
1926 pragma Assert (Target.Last.Next = null);
kono
parents:
diff changeset
1927 Target.Last.Next := Position;
kono
parents:
diff changeset
1928 Position.Prev := Target.Last;
kono
parents:
diff changeset
1929
kono
parents:
diff changeset
1930 Target.Last := Position;
kono
parents:
diff changeset
1931 Target.Last.Next := null;
kono
parents:
diff changeset
1932
kono
parents:
diff changeset
1933 elsif Before = Target.First then
kono
parents:
diff changeset
1934 pragma Assert (Target.First.Prev = null);
kono
parents:
diff changeset
1935 Target.First.Prev := Position;
kono
parents:
diff changeset
1936 Position.Next := Target.First;
kono
parents:
diff changeset
1937
kono
parents:
diff changeset
1938 Target.First := Position;
kono
parents:
diff changeset
1939 Target.First.Prev := null;
kono
parents:
diff changeset
1940
kono
parents:
diff changeset
1941 else
kono
parents:
diff changeset
1942 pragma Assert (Target.Length >= 2);
kono
parents:
diff changeset
1943 Before.Prev.Next := Position;
kono
parents:
diff changeset
1944 Position.Prev := Before.Prev;
kono
parents:
diff changeset
1945
kono
parents:
diff changeset
1946 Before.Prev := Position;
kono
parents:
diff changeset
1947 Position.Next := Before;
kono
parents:
diff changeset
1948 end if;
kono
parents:
diff changeset
1949
kono
parents:
diff changeset
1950 Target.Length := Target.Length + 1;
kono
parents:
diff changeset
1951 Source.Length := Source.Length - 1;
kono
parents:
diff changeset
1952 end Splice_Internal;
kono
parents:
diff changeset
1953
kono
parents:
diff changeset
1954 ----------
kono
parents:
diff changeset
1955 -- Swap --
kono
parents:
diff changeset
1956 ----------
kono
parents:
diff changeset
1957
kono
parents:
diff changeset
1958 procedure Swap
kono
parents:
diff changeset
1959 (Container : in out List;
kono
parents:
diff changeset
1960 I, J : Cursor)
kono
parents:
diff changeset
1961 is
kono
parents:
diff changeset
1962 begin
kono
parents:
diff changeset
1963 if Checks and then I.Node = null then
kono
parents:
diff changeset
1964 raise Constraint_Error with "I cursor has no element";
kono
parents:
diff changeset
1965 end if;
kono
parents:
diff changeset
1966
kono
parents:
diff changeset
1967 if Checks and then J.Node = null then
kono
parents:
diff changeset
1968 raise Constraint_Error with "J cursor has no element";
kono
parents:
diff changeset
1969 end if;
kono
parents:
diff changeset
1970
kono
parents:
diff changeset
1971 if Checks and then I.Container /= Container'Unchecked_Access then
kono
parents:
diff changeset
1972 raise Program_Error with "I cursor designates wrong container";
kono
parents:
diff changeset
1973 end if;
kono
parents:
diff changeset
1974
kono
parents:
diff changeset
1975 if Checks and then J.Container /= Container'Unchecked_Access then
kono
parents:
diff changeset
1976 raise Program_Error with "J cursor designates wrong container";
kono
parents:
diff changeset
1977 end if;
kono
parents:
diff changeset
1978
kono
parents:
diff changeset
1979 if I.Node = J.Node then
kono
parents:
diff changeset
1980 return;
kono
parents:
diff changeset
1981 end if;
kono
parents:
diff changeset
1982
kono
parents:
diff changeset
1983 TE_Check (Container.TC);
kono
parents:
diff changeset
1984
kono
parents:
diff changeset
1985 pragma Assert (Vet (I), "bad I cursor in Swap");
kono
parents:
diff changeset
1986 pragma Assert (Vet (J), "bad J cursor in Swap");
kono
parents:
diff changeset
1987
kono
parents:
diff changeset
1988 declare
kono
parents:
diff changeset
1989 EI_Copy : constant Element_Access := I.Node.Element;
kono
parents:
diff changeset
1990
kono
parents:
diff changeset
1991 begin
kono
parents:
diff changeset
1992 I.Node.Element := J.Node.Element;
kono
parents:
diff changeset
1993 J.Node.Element := EI_Copy;
kono
parents:
diff changeset
1994 end;
kono
parents:
diff changeset
1995 end Swap;
kono
parents:
diff changeset
1996
kono
parents:
diff changeset
1997 ----------------
kono
parents:
diff changeset
1998 -- Swap_Links --
kono
parents:
diff changeset
1999 ----------------
kono
parents:
diff changeset
2000
kono
parents:
diff changeset
2001 procedure Swap_Links
kono
parents:
diff changeset
2002 (Container : in out List;
kono
parents:
diff changeset
2003 I, J : Cursor)
kono
parents:
diff changeset
2004 is
kono
parents:
diff changeset
2005 begin
kono
parents:
diff changeset
2006 if Checks and then I.Node = null then
kono
parents:
diff changeset
2007 raise Constraint_Error with "I cursor has no element";
kono
parents:
diff changeset
2008 end if;
kono
parents:
diff changeset
2009
kono
parents:
diff changeset
2010 if Checks and then J.Node = null then
kono
parents:
diff changeset
2011 raise Constraint_Error with "J cursor has no element";
kono
parents:
diff changeset
2012 end if;
kono
parents:
diff changeset
2013
kono
parents:
diff changeset
2014 if Checks and then I.Container /= Container'Unrestricted_Access then
kono
parents:
diff changeset
2015 raise Program_Error with "I cursor designates wrong container";
kono
parents:
diff changeset
2016 end if;
kono
parents:
diff changeset
2017
kono
parents:
diff changeset
2018 if Checks and then J.Container /= Container'Unrestricted_Access then
kono
parents:
diff changeset
2019 raise Program_Error with "J cursor designates wrong container";
kono
parents:
diff changeset
2020 end if;
kono
parents:
diff changeset
2021
kono
parents:
diff changeset
2022 if I.Node = J.Node then
kono
parents:
diff changeset
2023 return;
kono
parents:
diff changeset
2024 end if;
kono
parents:
diff changeset
2025
kono
parents:
diff changeset
2026 TC_Check (Container.TC);
kono
parents:
diff changeset
2027
kono
parents:
diff changeset
2028 pragma Assert (Vet (I), "bad I cursor in Swap_Links");
kono
parents:
diff changeset
2029 pragma Assert (Vet (J), "bad J cursor in Swap_Links");
kono
parents:
diff changeset
2030
kono
parents:
diff changeset
2031 declare
kono
parents:
diff changeset
2032 I_Next : constant Cursor := Next (I);
kono
parents:
diff changeset
2033
kono
parents:
diff changeset
2034 begin
kono
parents:
diff changeset
2035 if I_Next = J then
kono
parents:
diff changeset
2036 Splice (Container, Before => I, Position => J);
kono
parents:
diff changeset
2037
kono
parents:
diff changeset
2038 else
kono
parents:
diff changeset
2039 declare
kono
parents:
diff changeset
2040 J_Next : constant Cursor := Next (J);
kono
parents:
diff changeset
2041
kono
parents:
diff changeset
2042 begin
kono
parents:
diff changeset
2043 if J_Next = I then
kono
parents:
diff changeset
2044 Splice (Container, Before => J, Position => I);
kono
parents:
diff changeset
2045
kono
parents:
diff changeset
2046 else
kono
parents:
diff changeset
2047 pragma Assert (Container.Length >= 3);
kono
parents:
diff changeset
2048
kono
parents:
diff changeset
2049 Splice (Container, Before => I_Next, Position => J);
kono
parents:
diff changeset
2050 Splice (Container, Before => J_Next, Position => I);
kono
parents:
diff changeset
2051 end if;
kono
parents:
diff changeset
2052 end;
kono
parents:
diff changeset
2053 end if;
kono
parents:
diff changeset
2054 end;
kono
parents:
diff changeset
2055
kono
parents:
diff changeset
2056 pragma Assert (Container.First.Prev = null);
kono
parents:
diff changeset
2057 pragma Assert (Container.Last.Next = null);
kono
parents:
diff changeset
2058 end Swap_Links;
kono
parents:
diff changeset
2059
kono
parents:
diff changeset
2060 --------------------
kono
parents:
diff changeset
2061 -- Update_Element --
kono
parents:
diff changeset
2062 --------------------
kono
parents:
diff changeset
2063
kono
parents:
diff changeset
2064 procedure Update_Element
kono
parents:
diff changeset
2065 (Container : in out List;
kono
parents:
diff changeset
2066 Position : Cursor;
kono
parents:
diff changeset
2067 Process : not null access procedure (Element : in out Element_Type))
kono
parents:
diff changeset
2068 is
kono
parents:
diff changeset
2069 begin
kono
parents:
diff changeset
2070 if Checks and then Position.Node = null then
kono
parents:
diff changeset
2071 raise Constraint_Error with "Position cursor has no element";
kono
parents:
diff changeset
2072 end if;
kono
parents:
diff changeset
2073
kono
parents:
diff changeset
2074 if Checks and then Position.Node.Element = null then
kono
parents:
diff changeset
2075 raise Program_Error with
kono
parents:
diff changeset
2076 "Position cursor has no element";
kono
parents:
diff changeset
2077 end if;
kono
parents:
diff changeset
2078
kono
parents:
diff changeset
2079 if Checks and then Position.Container /= Container'Unchecked_Access then
kono
parents:
diff changeset
2080 raise Program_Error with
kono
parents:
diff changeset
2081 "Position cursor designates wrong container";
kono
parents:
diff changeset
2082 end if;
kono
parents:
diff changeset
2083
kono
parents:
diff changeset
2084 pragma Assert (Vet (Position), "bad cursor in Update_Element");
kono
parents:
diff changeset
2085
kono
parents:
diff changeset
2086 declare
kono
parents:
diff changeset
2087 Lock : With_Lock (Container.TC'Unchecked_Access);
kono
parents:
diff changeset
2088 begin
kono
parents:
diff changeset
2089 Process (Position.Node.Element.all);
kono
parents:
diff changeset
2090 end;
kono
parents:
diff changeset
2091 end Update_Element;
kono
parents:
diff changeset
2092
kono
parents:
diff changeset
2093 ---------
kono
parents:
diff changeset
2094 -- Vet --
kono
parents:
diff changeset
2095 ---------
kono
parents:
diff changeset
2096
kono
parents:
diff changeset
2097 function Vet (Position : Cursor) return Boolean is
kono
parents:
diff changeset
2098 begin
kono
parents:
diff changeset
2099 if Position.Node = null then
kono
parents:
diff changeset
2100 return Position.Container = null;
kono
parents:
diff changeset
2101 end if;
kono
parents:
diff changeset
2102
kono
parents:
diff changeset
2103 if Position.Container = null then
kono
parents:
diff changeset
2104 return False;
kono
parents:
diff changeset
2105 end if;
kono
parents:
diff changeset
2106
kono
parents:
diff changeset
2107 -- An invariant of a node is that its Previous and Next components can
kono
parents:
diff changeset
2108 -- be null, or designate a different node. Also, its element access
kono
parents:
diff changeset
2109 -- value must be non-null. Operation Free sets the node access value
kono
parents:
diff changeset
2110 -- components of the node to designate the node itself, and the element
kono
parents:
diff changeset
2111 -- access value to null, before actually deallocating the node, thus
kono
parents:
diff changeset
2112 -- deliberately violating the node invariant. This gives us a simple way
kono
parents:
diff changeset
2113 -- to detect a dangling reference to a node.
kono
parents:
diff changeset
2114
kono
parents:
diff changeset
2115 if Position.Node.Next = Position.Node then
kono
parents:
diff changeset
2116 return False;
kono
parents:
diff changeset
2117 end if;
kono
parents:
diff changeset
2118
kono
parents:
diff changeset
2119 if Position.Node.Prev = Position.Node then
kono
parents:
diff changeset
2120 return False;
kono
parents:
diff changeset
2121 end if;
kono
parents:
diff changeset
2122
kono
parents:
diff changeset
2123 if Position.Node.Element = null then
kono
parents:
diff changeset
2124 return False;
kono
parents:
diff changeset
2125 end if;
kono
parents:
diff changeset
2126
kono
parents:
diff changeset
2127 -- In practice the tests above will detect most instances of a dangling
kono
parents:
diff changeset
2128 -- reference. If we get here, it means that the invariants of the
kono
parents:
diff changeset
2129 -- designated node are satisfied (they at least appear to be satisfied),
kono
parents:
diff changeset
2130 -- so we perform some more tests, to determine whether invariants of the
kono
parents:
diff changeset
2131 -- designated list are satisfied too.
kono
parents:
diff changeset
2132
kono
parents:
diff changeset
2133 declare
kono
parents:
diff changeset
2134 L : List renames Position.Container.all;
kono
parents:
diff changeset
2135
kono
parents:
diff changeset
2136 begin
kono
parents:
diff changeset
2137 if L.Length = 0 then
kono
parents:
diff changeset
2138 return False;
kono
parents:
diff changeset
2139 end if;
kono
parents:
diff changeset
2140
kono
parents:
diff changeset
2141 if L.First = null then
kono
parents:
diff changeset
2142 return False;
kono
parents:
diff changeset
2143 end if;
kono
parents:
diff changeset
2144
kono
parents:
diff changeset
2145 if L.Last = null then
kono
parents:
diff changeset
2146 return False;
kono
parents:
diff changeset
2147 end if;
kono
parents:
diff changeset
2148
kono
parents:
diff changeset
2149 if L.First.Prev /= null then
kono
parents:
diff changeset
2150 return False;
kono
parents:
diff changeset
2151 end if;
kono
parents:
diff changeset
2152
kono
parents:
diff changeset
2153 if L.Last.Next /= null then
kono
parents:
diff changeset
2154 return False;
kono
parents:
diff changeset
2155 end if;
kono
parents:
diff changeset
2156
kono
parents:
diff changeset
2157 if Position.Node.Prev = null and then Position.Node /= L.First then
kono
parents:
diff changeset
2158 return False;
kono
parents:
diff changeset
2159 end if;
kono
parents:
diff changeset
2160
kono
parents:
diff changeset
2161 if Position.Node.Next = null and then Position.Node /= L.Last then
kono
parents:
diff changeset
2162 return False;
kono
parents:
diff changeset
2163 end if;
kono
parents:
diff changeset
2164
kono
parents:
diff changeset
2165 if L.Length = 1 then
kono
parents:
diff changeset
2166 return L.First = L.Last;
kono
parents:
diff changeset
2167 end if;
kono
parents:
diff changeset
2168
kono
parents:
diff changeset
2169 if L.First = L.Last then
kono
parents:
diff changeset
2170 return False;
kono
parents:
diff changeset
2171 end if;
kono
parents:
diff changeset
2172
kono
parents:
diff changeset
2173 if L.First.Next = null then
kono
parents:
diff changeset
2174 return False;
kono
parents:
diff changeset
2175 end if;
kono
parents:
diff changeset
2176
kono
parents:
diff changeset
2177 if L.Last.Prev = null then
kono
parents:
diff changeset
2178 return False;
kono
parents:
diff changeset
2179 end if;
kono
parents:
diff changeset
2180
kono
parents:
diff changeset
2181 if L.First.Next.Prev /= L.First then
kono
parents:
diff changeset
2182 return False;
kono
parents:
diff changeset
2183 end if;
kono
parents:
diff changeset
2184
kono
parents:
diff changeset
2185 if L.Last.Prev.Next /= L.Last then
kono
parents:
diff changeset
2186 return False;
kono
parents:
diff changeset
2187 end if;
kono
parents:
diff changeset
2188
kono
parents:
diff changeset
2189 if L.Length = 2 then
kono
parents:
diff changeset
2190 if L.First.Next /= L.Last then
kono
parents:
diff changeset
2191 return False;
kono
parents:
diff changeset
2192 end if;
kono
parents:
diff changeset
2193
kono
parents:
diff changeset
2194 if L.Last.Prev /= L.First then
kono
parents:
diff changeset
2195 return False;
kono
parents:
diff changeset
2196 end if;
kono
parents:
diff changeset
2197
kono
parents:
diff changeset
2198 return True;
kono
parents:
diff changeset
2199 end if;
kono
parents:
diff changeset
2200
kono
parents:
diff changeset
2201 if L.First.Next = L.Last then
kono
parents:
diff changeset
2202 return False;
kono
parents:
diff changeset
2203 end if;
kono
parents:
diff changeset
2204
kono
parents:
diff changeset
2205 if L.Last.Prev = L.First then
kono
parents:
diff changeset
2206 return False;
kono
parents:
diff changeset
2207 end if;
kono
parents:
diff changeset
2208
kono
parents:
diff changeset
2209 if Position.Node = L.First then
kono
parents:
diff changeset
2210 return True;
kono
parents:
diff changeset
2211 end if;
kono
parents:
diff changeset
2212
kono
parents:
diff changeset
2213 if Position.Node = L.Last then
kono
parents:
diff changeset
2214 return True;
kono
parents:
diff changeset
2215 end if;
kono
parents:
diff changeset
2216
kono
parents:
diff changeset
2217 if Position.Node.Next = null then
kono
parents:
diff changeset
2218 return False;
kono
parents:
diff changeset
2219 end if;
kono
parents:
diff changeset
2220
kono
parents:
diff changeset
2221 if Position.Node.Prev = null then
kono
parents:
diff changeset
2222 return False;
kono
parents:
diff changeset
2223 end if;
kono
parents:
diff changeset
2224
kono
parents:
diff changeset
2225 if Position.Node.Next.Prev /= Position.Node then
kono
parents:
diff changeset
2226 return False;
kono
parents:
diff changeset
2227 end if;
kono
parents:
diff changeset
2228
kono
parents:
diff changeset
2229 if Position.Node.Prev.Next /= Position.Node then
kono
parents:
diff changeset
2230 return False;
kono
parents:
diff changeset
2231 end if;
kono
parents:
diff changeset
2232
kono
parents:
diff changeset
2233 if L.Length = 3 then
kono
parents:
diff changeset
2234 if L.First.Next /= Position.Node then
kono
parents:
diff changeset
2235 return False;
kono
parents:
diff changeset
2236 end if;
kono
parents:
diff changeset
2237
kono
parents:
diff changeset
2238 if L.Last.Prev /= Position.Node then
kono
parents:
diff changeset
2239 return False;
kono
parents:
diff changeset
2240 end if;
kono
parents:
diff changeset
2241 end if;
kono
parents:
diff changeset
2242
kono
parents:
diff changeset
2243 return True;
kono
parents:
diff changeset
2244 end;
kono
parents:
diff changeset
2245 end Vet;
kono
parents:
diff changeset
2246
kono
parents:
diff changeset
2247 -----------
kono
parents:
diff changeset
2248 -- Write --
kono
parents:
diff changeset
2249 -----------
kono
parents:
diff changeset
2250
kono
parents:
diff changeset
2251 procedure Write
kono
parents:
diff changeset
2252 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
2253 Item : List)
kono
parents:
diff changeset
2254 is
kono
parents:
diff changeset
2255 Node : Node_Access := Item.First;
kono
parents:
diff changeset
2256
kono
parents:
diff changeset
2257 begin
kono
parents:
diff changeset
2258 Count_Type'Base'Write (Stream, Item.Length);
kono
parents:
diff changeset
2259
kono
parents:
diff changeset
2260 while Node /= null loop
kono
parents:
diff changeset
2261 Element_Type'Output (Stream, Node.Element.all);
kono
parents:
diff changeset
2262 Node := Node.Next;
kono
parents:
diff changeset
2263 end loop;
kono
parents:
diff changeset
2264 end Write;
kono
parents:
diff changeset
2265
kono
parents:
diff changeset
2266 procedure Write
kono
parents:
diff changeset
2267 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
2268 Item : Cursor)
kono
parents:
diff changeset
2269 is
kono
parents:
diff changeset
2270 begin
kono
parents:
diff changeset
2271 raise Program_Error with "attempt to stream list cursor";
kono
parents:
diff changeset
2272 end Write;
kono
parents:
diff changeset
2273
kono
parents:
diff changeset
2274 procedure Write
kono
parents:
diff changeset
2275 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
2276 Item : Reference_Type)
kono
parents:
diff changeset
2277 is
kono
parents:
diff changeset
2278 begin
kono
parents:
diff changeset
2279 raise Program_Error with "attempt to stream reference";
kono
parents:
diff changeset
2280 end Write;
kono
parents:
diff changeset
2281
kono
parents:
diff changeset
2282 procedure Write
kono
parents:
diff changeset
2283 (Stream : not null access Root_Stream_Type'Class;
kono
parents:
diff changeset
2284 Item : Constant_Reference_Type)
kono
parents:
diff changeset
2285 is
kono
parents:
diff changeset
2286 begin
kono
parents:
diff changeset
2287 raise Program_Error with "attempt to stream reference";
kono
parents:
diff changeset
2288 end Write;
kono
parents:
diff changeset
2289
kono
parents:
diff changeset
2290 end Ada.Containers.Indefinite_Doubly_Linked_Lists;