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