1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . C O N T A I N E R S . D O U B L Y _ L I N K E D _ L I S T S --
9 -- Copyright (C) 2004-2005 Free Software Foundation, Inc. --
11 -- This specification is derived from the Ada Reference Manual for use with --
12 -- GNAT. The copyright notice above, and the license provisions that follow --
13 -- apply solely to the contents of the part following the private keyword. --
15 -- GNAT is free software; you can redistribute it and/or modify it under --
16 -- terms of the GNU General Public License as published by the Free Soft- --
17 -- ware Foundation; either version 2, or (at your option) any later ver- --
18 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
19 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
20 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
21 -- for more details. You should have received a copy of the GNU General --
22 -- Public License distributed with GNAT; see file COPYING. If not, write --
23 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
24 -- Boston, MA 02110-1301, USA. --
26 -- As a special exception, if other files instantiate generics from this --
27 -- unit, or you link this unit with other files to produce an executable, --
28 -- this unit does not by itself cause the resulting executable to be --
29 -- covered by the GNU General Public License. This exception does not --
30 -- however invalidate any other reasons why the executable file might be --
31 -- covered by the GNU Public License. --
33 -- This unit was originally developed by Matthew J Heaney. --
34 ------------------------------------------------------------------------------
36 with System
; use type System
.Address
;
37 with Ada
.Unchecked_Deallocation
;
39 package body Ada
.Containers
.Doubly_Linked_Lists
is
41 -----------------------
42 -- Local Subprograms --
43 -----------------------
45 procedure Free
(X
: in out Node_Access
);
47 procedure Insert_Internal
48 (Container
: in out List
;
50 New_Node
: Node_Access
);
52 function Vet
(Position
: Cursor
) return Boolean;
58 function "=" (Left
, Right
: List
) return Boolean is
59 L
: Node_Access
:= Left
.First
;
60 R
: Node_Access
:= Right
.First
;
63 if Left
'Address = Right
'Address then
67 if Left
.Length
/= Right
.Length
then
71 for J
in 1 .. Left
.Length
loop
72 if L
.Element
/= R
.Element
then
87 procedure Adjust
(Container
: in out List
) is
88 Src
: Node_Access
:= Container
.First
;
92 pragma Assert
(Container
.Last
= null);
93 pragma Assert
(Container
.Length
= 0);
94 pragma Assert
(Container
.Busy
= 0);
95 pragma Assert
(Container
.Lock
= 0);
99 pragma Assert
(Container
.First
.Prev
= null);
100 pragma Assert
(Container
.Last
.Next
= null);
101 pragma Assert
(Container
.Length
> 0);
103 Container
.First
:= null;
104 Container
.Last
:= null;
105 Container
.Length
:= 0;
109 Container
.First
:= new Node_Type
'(Src.Element, null, null);
110 Container.Last := Container.First;
111 Container.Length := 1;
114 while Src /= null loop
115 Container.Last.Next := new Node_Type'(Element
=> Src
.Element
,
116 Prev
=> Container
.Last
,
118 Container
.Last
:= Container
.Last
.Next
;
119 Container
.Length
:= Container
.Length
+ 1;
130 (Container
: in out List
;
131 New_Item
: Element_Type
;
132 Count
: Count_Type
:= 1) is
134 Insert
(Container
, No_Element
, New_Item
, Count
);
141 procedure Clear
(Container
: in out List
) is
145 if Container
.Length
= 0 then
146 pragma Assert
(Container
.First
= null);
147 pragma Assert
(Container
.Last
= null);
148 pragma Assert
(Container
.Busy
= 0);
149 pragma Assert
(Container
.Lock
= 0);
153 pragma Assert
(Container
.First
.Prev
= null);
154 pragma Assert
(Container
.Last
.Next
= null);
156 if Container
.Busy
> 0 then
160 while Container
.Length
> 1 loop
161 X
:= Container
.First
;
162 pragma Assert
(X
.Next
.Prev
= Container
.First
);
164 Container
.First
:= X
.Next
;
165 Container
.First
.Prev
:= null;
167 Container
.Length
:= Container
.Length
- 1;
172 X
:= Container
.First
;
173 pragma Assert
(X
= Container
.Last
);
175 Container
.First
:= null;
176 Container
.Last
:= null;
177 Container
.Length
:= 0;
188 Item
: Element_Type
) return Boolean is
190 return Find
(Container
, Item
) /= No_Element
;
198 (Container
: in out List
;
199 Position
: in out Cursor
;
200 Count
: Count_Type
:= 1)
205 pragma Assert
(Vet
(Position
), "bad cursor in Delete");
207 if Position
.Node
= null then
208 raise Constraint_Error
;
211 if Position
.Container
/= Container
'Unrestricted_Access then
215 if Position
.Node
= Container
.First
then
216 Delete_First
(Container
, Count
);
217 Position
:= First
(Container
);
225 if Container
.Busy
> 0 then
229 for Index
in 1 .. Count
loop
231 Container
.Length
:= Container
.Length
- 1;
233 if X
= Container
.Last
then
234 Position
:= No_Element
;
236 Container
.Last
:= X
.Prev
;
237 Container
.Last
.Next
:= null;
243 Position
.Node
:= X
.Next
;
245 X
.Next
.Prev
:= X
.Prev
;
246 X
.Prev
.Next
:= X
.Next
;
256 procedure Delete_First
257 (Container
: in out List
;
258 Count
: Count_Type
:= 1)
263 if Count
>= Container
.Length
then
272 if Container
.Busy
> 0 then
276 for I
in 1 .. Count
loop
277 X
:= Container
.First
;
278 pragma Assert
(X
.Next
.Prev
= Container
.First
);
280 Container
.First
:= X
.Next
;
281 Container
.First
.Prev
:= null;
283 Container
.Length
:= Container
.Length
- 1;
293 procedure Delete_Last
294 (Container
: in out List
;
295 Count
: Count_Type
:= 1)
300 if Count
>= Container
.Length
then
309 if Container
.Busy
> 0 then
313 for I
in 1 .. Count
loop
315 pragma Assert
(X
.Prev
.Next
= Container
.Last
);
317 Container
.Last
:= X
.Prev
;
318 Container
.Last
.Next
:= null;
320 Container
.Length
:= Container
.Length
- 1;
330 function Element
(Position
: Cursor
) return Element_Type
is
332 pragma Assert
(Vet
(Position
), "bad cursor in Element");
334 if Position
.Node
= null then
335 raise Constraint_Error
;
338 return Position
.Node
.Element
;
348 Position
: Cursor
:= No_Element
) return Cursor
350 Node
: Node_Access
:= Position
.Node
;
354 Node
:= Container
.First
;
357 pragma Assert
(Vet
(Position
), "bad cursor in Find");
359 if Position
.Container
/= Container
'Unrestricted_Access then
364 while Node
/= null loop
365 if Node
.Element
= Item
then
366 return Cursor
'(Container'Unchecked_Access, Node);
379 function First (Container : List) return Cursor is
381 if Container.First = null then
385 return Cursor'(Container
'Unchecked_Access, Container
.First
);
392 function First_Element
(Container
: List
) return Element_Type
is
394 if Container
.First
= null then
395 raise Constraint_Error
;
398 return Container
.First
.Element
;
405 procedure Free
(X
: in out Node_Access
) is
406 procedure Deallocate
is
407 new Ada
.Unchecked_Deallocation
(Node_Type
, Node_Access
);
415 ---------------------
416 -- Generic_Sorting --
417 ---------------------
419 package body Generic_Sorting
is
425 function Is_Sorted
(Container
: List
) return Boolean is
426 Node
: Node_Access
:= Container
.First
;
429 for I
in 2 .. Container
.Length
loop
430 if Node
.Next
.Element
< Node
.Element
then
445 (Target
: in out List
;
446 Source
: in out List
)
448 LI
: Cursor
:= First
(Target
);
449 RI
: Cursor
:= First
(Source
);
452 if Target
'Address = Source
'Address then
457 or else Source
.Busy
> 0
462 while RI
.Node
/= null loop
463 if LI
.Node
= null then
464 Splice
(Target
, No_Element
, Source
);
468 if RI
.Node
.Element
< LI
.Node
.Element
then
472 RI
.Node
:= RI
.Node
.Next
;
473 Splice
(Target
, LI
, Source
, RJ
);
477 LI
.Node
:= LI
.Node
.Next
;
486 procedure Sort
(Container
: in out List
) is
489 (Pivot
: in Node_Access
;
490 Back
: in Node_Access
);
492 procedure Sort
(Front
, Back
: Node_Access
);
499 (Pivot
: Node_Access
;
502 Node
: Node_Access
:= Pivot
.Next
;
505 while Node
/= Back
loop
506 if Node
.Element
< Pivot
.Element
then
508 Prev
: constant Node_Access
:= Node
.Prev
;
509 Next
: constant Node_Access
:= Node
.Next
;
515 Container
.Last
:= Prev
;
521 Node
.Prev
:= Pivot
.Prev
;
525 if Node
.Prev
= null then
526 Container
.First
:= Node
;
528 Node
.Prev
.Next
:= Node
;
544 procedure Sort
(Front
, Back
: Node_Access
) is
549 Pivot
:= Container
.First
;
554 if Pivot
/= Back
then
555 Partition
(Pivot
, Back
);
561 -- Start of processing for Sort
564 if Container
.Length
<= 1 then
568 pragma Assert
(Container
.First
.Prev
= null);
569 pragma Assert
(Container
.Last
.Next
= null);
571 if Container
.Busy
> 0 then
575 Sort
(Front
=> null, Back
=> null);
577 pragma Assert
(Container
.First
.Prev
= null);
578 pragma Assert
(Container
.Last
.Next
= null);
587 function Has_Element
(Position
: Cursor
) return Boolean is
589 pragma Assert
(Vet
(Position
), "bad cursor in Has_Element");
590 return Position
.Node
/= null;
598 (Container
: in out List
;
600 New_Item
: Element_Type
;
601 Position
: out Cursor
;
602 Count
: Count_Type
:= 1)
604 New_Node
: Node_Access
;
607 pragma Assert
(Vet
(Before
), "bad cursor in Insert");
609 if Before
.Container
/= null
610 and then Before
.Container
/= Container
'Unrestricted_Access
620 if Container
.Length
> Count_Type
'Last - Count
then
621 raise Constraint_Error
;
624 if Container
.Busy
> 0 then
628 New_Node
:= new Node_Type
'(New_Item, null, null);
629 Insert_Internal (Container, Before.Node, New_Node);
631 Position := Cursor'(Container
'Unchecked_Access, New_Node
);
633 for J
in Count_Type
'(2) .. Count loop
634 New_Node := new Node_Type'(New_Item
, null, null);
635 Insert_Internal
(Container
, Before
.Node
, New_Node
);
640 (Container
: in out List
;
642 New_Item
: Element_Type
;
643 Count
: Count_Type
:= 1)
647 Insert
(Container
, Before
, New_Item
, Position
, Count
);
651 (Container
: in out List
;
653 Position
: out Cursor
;
654 Count
: Count_Type
:= 1)
656 New_Node
: Node_Access
;
659 pragma Assert
(Vet
(Before
), "bad cursor in Insert");
661 if Before
.Container
/= null
662 and then Before
.Container
/= Container
'Unrestricted_Access
672 if Container
.Length
> Count_Type
'Last - Count
then
673 raise Constraint_Error
;
676 if Container
.Busy
> 0 then
680 New_Node
:= new Node_Type
;
681 Insert_Internal
(Container
, Before
.Node
, New_Node
);
683 Position
:= Cursor
'(Container'Unchecked_Access, New_Node);
685 for J in Count_Type'(2) .. Count
loop
686 New_Node
:= new Node_Type
;
687 Insert_Internal
(Container
, Before
.Node
, New_Node
);
691 ---------------------
692 -- Insert_Internal --
693 ---------------------
695 procedure Insert_Internal
696 (Container
: in out List
;
697 Before
: Node_Access
;
698 New_Node
: Node_Access
)
701 if Container
.Length
= 0 then
702 pragma Assert
(Before
= null);
703 pragma Assert
(Container
.First
= null);
704 pragma Assert
(Container
.Last
= null);
706 Container
.First
:= New_Node
;
707 Container
.Last
:= New_Node
;
709 elsif Before
= null then
710 pragma Assert
(Container
.Last
.Next
= null);
712 Container
.Last
.Next
:= New_Node
;
713 New_Node
.Prev
:= Container
.Last
;
715 Container
.Last
:= New_Node
;
717 elsif Before
= Container
.First
then
718 pragma Assert
(Container
.First
.Prev
= null);
720 Container
.First
.Prev
:= New_Node
;
721 New_Node
.Next
:= Container
.First
;
723 Container
.First
:= New_Node
;
726 pragma Assert
(Container
.First
.Prev
= null);
727 pragma Assert
(Container
.Last
.Next
= null);
729 New_Node
.Next
:= Before
;
730 New_Node
.Prev
:= Before
.Prev
;
732 Before
.Prev
.Next
:= New_Node
;
733 Before
.Prev
:= New_Node
;
736 Container
.Length
:= Container
.Length
+ 1;
743 function Is_Empty
(Container
: List
) return Boolean is
745 return Container
.Length
= 0;
754 Process
: not null access procedure (Position
: Cursor
))
756 C
: List
renames Container
'Unrestricted_Access.all;
757 B
: Natural renames C
.Busy
;
759 Node
: Node_Access
:= Container
.First
;
765 while Node
/= null loop
766 Process
(Cursor
'(Container'Unchecked_Access, Node));
782 function Last (Container : List) return Cursor is
784 if Container.Last = null then
788 return Cursor'(Container
'Unchecked_Access, Container
.Last
);
795 function Last_Element
(Container
: List
) return Element_Type
is
797 if Container
.Last
= null then
798 raise Constraint_Error
;
801 return Container
.Last
.Element
;
808 function Length
(Container
: List
) return Count_Type
is
810 return Container
.Length
;
818 (Target
: in out List
;
819 Source
: in out List
)
822 if Target
'Address = Source
'Address then
826 if Source
.Busy
> 0 then
832 Target
.First
:= Source
.First
;
833 Source
.First
:= null;
835 Target
.Last
:= Source
.Last
;
838 Target
.Length
:= Source
.Length
;
846 procedure Next
(Position
: in out Cursor
) is
848 pragma Assert
(Vet
(Position
), "bad cursor in procedure Next");
850 if Position
.Node
= null then
854 Position
.Node
:= Position
.Node
.Next
;
856 if Position
.Node
= null then
857 Position
.Container
:= null;
861 function Next
(Position
: Cursor
) return Cursor
is
863 pragma Assert
(Vet
(Position
), "bad cursor in function Next");
865 if Position
.Node
= null then
870 Next_Node
: constant Node_Access
:= Position
.Node
.Next
;
872 if Next_Node
= null then
876 return Cursor
'(Position.Container, Next_Node);
885 (Container : in out List;
886 New_Item : Element_Type;
887 Count : Count_Type := 1)
890 Insert (Container, First (Container), New_Item, Count);
897 procedure Previous (Position : in out Cursor) is
899 pragma Assert (Vet (Position), "bad cursor in procedure Previous");
901 if Position.Node = null then
905 Position.Node := Position.Node.Prev;
907 if Position.Node = null then
908 Position.Container := null;
912 function Previous (Position : Cursor) return Cursor is
914 pragma Assert (Vet (Position), "bad cursor in function Previous");
916 if Position.Node = null then
921 Prev_Node : constant Node_Access := Position.Node.Prev;
923 if Prev_Node = null then
927 return Cursor'(Position
.Container
, Prev_Node
);
935 procedure Query_Element
937 Process
: not null access procedure (Element
: in Element_Type
))
940 pragma Assert
(Vet
(Position
), "bad cursor in Query_Element");
942 if Position
.Node
= null then
943 raise Constraint_Error
;
947 C
: List
renames Position
.Container
.all'Unrestricted_Access.all;
948 B
: Natural renames C
.Busy
;
949 L
: Natural renames C
.Lock
;
956 Process
(Position
.Node
.Element
);
974 (Stream
: access Root_Stream_Type
'Class;
982 Count_Type
'Base'Read (Stream, N);
991 Element_Type'Read (Stream, X.Element);
1002 Item.Length := Item.Length + 1;
1003 exit when Item.Length = N;
1008 Element_Type'Read (Stream, X.Element);
1015 X.Prev := Item.Last;
1016 Item.Last.Next := X;
1021 ---------------------
1022 -- Replace_Element --
1023 ---------------------
1025 procedure Replace_Element
1030 pragma Assert (Vet (Position), "bad cursor in Replace_Element");
1032 if Position.Container = null then
1033 raise Constraint_Error;
1036 if Position.Container.Lock > 0 then
1037 raise Program_Error;
1040 Position.Node.Element := By;
1041 end Replace_Element;
1047 function Reverse_Find
1049 Item : Element_Type;
1050 Position : Cursor := No_Element) return Cursor
1052 Node : Node_Access := Position.Node;
1056 Node := Container.Last;
1059 pragma Assert (Vet (Position), "bad cursor in Reverse_Find");
1061 if Position.Container /= Container'Unrestricted_Access then
1062 raise Program_Error;
1066 while Node /= null loop
1067 if Node.Element = Item then
1068 return Cursor'(Container
'Unchecked_Access, Node
);
1077 ---------------------
1078 -- Reverse_Iterate --
1079 ---------------------
1081 procedure Reverse_Iterate
1083 Process
: not null access procedure (Position
: Cursor
))
1085 C
: List
renames Container
'Unrestricted_Access.all;
1086 B
: Natural renames C
.Busy
;
1088 Node
: Node_Access
:= Container
.Last
;
1094 while Node
/= null loop
1095 Process
(Cursor
'(Container'Unchecked_Access, Node));
1105 end Reverse_Iterate;
1111 procedure Reverse_List (Container : in out List) is
1112 I : Node_Access := Container.First;
1113 J : Node_Access := Container.Last;
1115 procedure Swap (L, R : Node_Access);
1121 procedure Swap (L, R : Node_Access) is
1122 LN : constant Node_Access := L.Next;
1123 LP : constant Node_Access := L.Prev;
1125 RN : constant Node_Access := R.Next;
1126 RP : constant Node_Access := R.Prev;
1141 pragma Assert (RP = L);
1155 -- Start of processing for Reverse_List
1158 if Container.Length <= 1 then
1162 pragma Assert (Container.First.Prev = null);
1163 pragma Assert (Container.Last.Next = null);
1165 if Container.Busy > 0 then
1166 raise Program_Error;
1169 Container.First := J;
1170 Container.Last := I;
1172 Swap (L => I, R => J);
1180 Swap (L => J, R => I);
1189 pragma Assert (Container.First.Prev = null);
1190 pragma Assert (Container.Last.Next = null);
1198 (Target : in out List;
1200 Source : in out List)
1203 pragma Assert (Vet (Before), "bad cursor in Splice");
1205 if Before.Container /= null
1206 and then Before.Container /= Target'Unrestricted_Access
1208 raise Program_Error;
1211 if Target'Address = Source'Address
1212 or else Source.Length = 0
1217 pragma Assert (Source.First.Prev = null);
1218 pragma Assert (Source.Last.Next = null);
1220 if Target.Length > Count_Type'Last - Source.Length then
1221 raise Constraint_Error;
1225 or else Source.Busy > 0
1227 raise Program_Error;
1230 if Target.Length = 0 then
1231 pragma Assert (Target.First = null);
1232 pragma Assert (Target.Last = null);
1233 pragma Assert (Before = No_Element);
1235 Target.First := Source.First;
1236 Target.Last := Source.Last;
1238 elsif Before.Node = null then
1239 pragma Assert (Target.Last.Next = null);
1241 Target.Last.Next := Source.First;
1242 Source.First.Prev := Target.Last;
1244 Target.Last := Source.Last;
1246 elsif Before.Node = Target.First then
1247 pragma Assert (Target.First.Prev = null);
1249 Source.Last.Next := Target.First;
1250 Target.First.Prev := Source.Last;
1252 Target.First := Source.First;
1255 pragma Assert (Target.Length >= 2);
1257 Before.Node.Prev.Next := Source.First;
1258 Source.First.Prev := Before.Node.Prev;
1260 Before.Node.Prev := Source.Last;
1261 Source.Last.Next := Before.Node;
1264 Source.First := null;
1265 Source.Last := null;
1267 Target.Length := Target.Length + Source.Length;
1272 (Target : in out List;
1277 pragma Assert (Vet (Before), "bad Before cursor in Splice");
1278 pragma Assert (Vet (Position), "bad Position cursor in Splice");
1280 if Before.Container /= null
1281 and then Before.Container /= Target'Unchecked_Access
1283 raise Program_Error;
1286 if Position.Node = null then
1287 raise Constraint_Error;
1290 if Position.Container /= Target'Unrestricted_Access then
1291 raise Program_Error;
1294 if Position.Node = Before.Node
1295 or else Position.Node.Next = Before.Node
1300 pragma Assert (Target.Length >= 2);
1302 if Target.Busy > 0 then
1303 raise Program_Error;
1306 if Before.Node = null then
1307 pragma Assert (Position.Node /= Target.Last);
1309 if Position.Node = Target.First then
1310 Target.First := Position.Node.Next;
1311 Target.First.Prev := null;
1313 Position.Node.Prev.Next := Position.Node.Next;
1314 Position.Node.Next.Prev := Position.Node.Prev;
1317 Target.Last.Next := Position.Node;
1318 Position.Node.Prev := Target.Last;
1320 Target.Last := Position.Node;
1321 Target.Last.Next := null;
1326 if Before.Node = Target.First then
1327 pragma Assert (Position.Node /= Target.First);
1329 if Position.Node = Target.Last then
1330 Target.Last := Position.Node.Prev;
1331 Target.Last.Next := null;
1333 Position.Node.Prev.Next := Position.Node.Next;
1334 Position.Node.Next.Prev := Position.Node.Prev;
1337 Target.First.Prev := Position.Node;
1338 Position.Node.Next := Target.First;
1340 Target.First := Position.Node;
1341 Target.First.Prev := null;
1346 if Position.Node = Target.First then
1347 Target.First := Position.Node.Next;
1348 Target.First.Prev := null;
1350 elsif Position.Node = Target.Last then
1351 Target.Last := Position.Node.Prev;
1352 Target.Last.Next := null;
1355 Position.Node.Prev.Next := Position.Node.Next;
1356 Position.Node.Next.Prev := Position.Node.Prev;
1359 Before.Node.Prev.Next := Position.Node;
1360 Position.Node.Prev := Before.Node.Prev;
1362 Before.Node.Prev := Position.Node;
1363 Position.Node.Next := Before.Node;
1365 pragma Assert (Target.First.Prev = null);
1366 pragma Assert (Target.Last.Next = null);
1370 (Target : in out List;
1372 Source : in out List;
1373 Position : in out Cursor)
1376 if Target'Address = Source'Address then
1377 Splice (Target, Before, Position);
1381 pragma Assert (Vet (Before), "bad Before cursor in Splice");
1382 pragma Assert (Vet (Position), "bad Position cursor in Splice");
1384 if Before.Container /= null
1385 and then Before.Container /= Target'Unrestricted_Access
1387 raise Program_Error;
1390 if Position.Node = null then
1391 raise Constraint_Error;
1394 if Position.Container /= Source'Unrestricted_Access then
1395 raise Program_Error;
1398 if Target.Length = Count_Type'Last then
1399 raise Constraint_Error;
1403 or else Source.Busy > 0
1405 raise Program_Error;
1408 if Position.Node = Source.First then
1409 Source.First := Position.Node.Next;
1411 if Position.Node = Source.Last then
1412 pragma Assert (Source.First = null);
1413 pragma Assert (Source.Length = 1);
1414 Source.Last := null;
1417 Source.First.Prev := null;
1420 elsif Position.Node = Source.Last then
1421 pragma Assert (Source.Length >= 2);
1422 Source.Last := Position.Node.Prev;
1423 Source.Last.Next := null;
1426 pragma Assert (Source.Length >= 3);
1427 Position.Node.Prev.Next := Position.Node.Next;
1428 Position.Node.Next.Prev := Position.Node.Prev;
1431 if Target.Length = 0 then
1432 pragma Assert (Target.First = null);
1433 pragma Assert (Target.Last = null);
1434 pragma Assert (Before = No_Element);
1436 Target.First := Position.Node;
1437 Target.Last := Position.Node;
1439 Target.First.Prev := null;
1440 Target.Last.Next := null;
1442 elsif Before.Node = null then
1443 pragma Assert (Target.Last.Next = null);
1444 Target.Last.Next := Position.Node;
1445 Position.Node.Prev := Target.Last;
1447 Target.Last := Position.Node;
1448 Target.Last.Next := null;
1450 elsif Before.Node = Target.First then
1451 pragma Assert (Target.First.Prev = null);
1452 Target.First.Prev := Position.Node;
1453 Position.Node.Next := Target.First;
1455 Target.First := Position.Node;
1456 Target.First.Prev := null;
1459 pragma Assert (Target.Length >= 2);
1460 Before.Node.Prev.Next := Position.Node;
1461 Position.Node.Prev := Before.Node.Prev;
1463 Before.Node.Prev := Position.Node;
1464 Position.Node.Next := Before.Node;
1467 Target.Length := Target.Length + 1;
1468 Source.Length := Source.Length - 1;
1470 Position.Container := Target'Unchecked_Access;
1477 procedure Swap (I, J : Cursor) is
1479 pragma Assert (Vet (I), "bad I cursor in Swap");
1480 pragma Assert (Vet (J), "bad J cursor in Swap");
1483 or else J.Node = null
1485 raise Constraint_Error;
1488 if I.Container /= J.Container then
1489 raise Program_Error;
1492 if I.Node = J.Node then
1496 if I.Container.Lock > 0 then
1497 raise Program_Error;
1501 EI : Element_Type renames I.Node.Element;
1502 EJ : Element_Type renames J.Node.Element;
1504 EI_Copy : constant Element_Type := EI;
1515 procedure Swap_Links
1516 (Container : in out List;
1519 pragma Assert (Vet (I), "bad I cursor in Swap_Links");
1520 pragma Assert (Vet (J), "bad J cursor in Swap_Links");
1523 or else J.Node = null
1525 raise Constraint_Error;
1528 if I.Container /= Container'Unrestricted_Access
1529 or else I.Container /= J.Container
1531 raise Program_Error;
1534 if I.Node = J.Node then
1538 if Container.Busy > 0 then
1539 raise Program_Error;
1543 I_Next : constant Cursor := Next (I);
1547 Splice (Container, Before => I, Position => J);
1551 J_Next : constant Cursor := Next (J);
1555 Splice (Container, Before => J, Position => I);
1558 pragma Assert (Container.Length >= 3);
1560 Splice (Container, Before => I_Next, Position => J);
1561 Splice (Container, Before => J_Next, Position => I);
1568 --------------------
1569 -- Update_Element --
1570 --------------------
1572 procedure Update_Element
1574 Process : not null access procedure (Element : in out Element_Type))
1577 pragma Assert (Vet (Position), "bad cursor in Update_Element");
1579 if Position.Node = null then
1580 raise Constraint_Error;
1584 C : List renames Position.Container.all'Unrestricted_Access.all;
1585 B : Natural renames C.Busy;
1586 L : Natural renames C.Lock;
1593 Process (Position.Node.Element);
1610 function Vet (Position : Cursor) return Boolean is
1612 if Position.Node = null then
1613 return Position.Container = null;
1616 if Position.Container = null then
1620 if Position.Node.Next = Position.Node then
1624 if Position.Node.Prev = Position.Node then
1629 L : List renames Position.Container.all;
1631 if L.Length = 0 then
1635 if L.First = null then
1639 if L.Last = null then
1643 if L.First.Prev /= null then
1647 if L.Last.Next /= null then
1651 if Position.Node.Prev = null
1652 and then Position.Node /= L.First
1657 if Position.Node.Next = null
1658 and then Position.Node /= L.Last
1663 if L.Length = 1 then
1664 return L.First = L.Last;
1667 if L.First = L.Last then
1671 if L.First.Next = null then
1675 if L.Last.Prev = null then
1679 if L.First.Next.Prev /= L.First then
1683 if L.Last.Prev.Next /= L.Last then
1687 if L.Length = 2 then
1688 if L.First.Next /= L.Last then
1692 if L.Last.Prev /= L.First then
1699 if L.First.Next = L.Last then
1703 if L.Last.Prev = L.First then
1707 if Position.Node = L.First then
1711 if Position.Node = L.Last then
1715 if Position.Node.Next = null then
1719 if Position.Node.Prev = null then
1723 if Position.Node.Next.Prev /= Position.Node then
1727 if Position.Node.Prev.Next /= Position.Node then
1731 if L.Length = 3 then
1732 if L.First.Next /= Position.Node then
1736 if L.Last.Prev /= Position.Node then
1750 (Stream : access Root_Stream_Type'Class;
1753 Node : Node_Access := Item.First;
1756 Count_Type'Base'Write
(Stream
, Item
.Length
);
1758 while Node
/= null loop
1759 Element_Type
'Write (Stream
, Node
.Element
);
1764 end Ada
.Containers
.Doubly_Linked_Lists
;