1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.RESTRICTED_DOUBLY_LINKED_LISTS --
9 -- Copyright (C) 2004-2024, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- This unit was originally developed by Matthew J Heaney. --
28 ------------------------------------------------------------------------------
30 with Ada
.Containers
.Stable_Sorting
; use Ada
.Containers
.Stable_Sorting
;
32 with System
; use type System
.Address
;
34 package body Ada
.Containers
.Restricted_Doubly_Linked_Lists
is
36 -----------------------
37 -- Local Subprograms --
38 -----------------------
41 (Container
: in out List
'Class;
42 New_Item
: Element_Type
;
43 New_Node
: out Count_Type
);
46 (Container
: in out List
'Class;
49 procedure Insert_Internal
50 (Container
: in out List
'Class;
52 New_Node
: Count_Type
);
54 function Vet
(Position
: Cursor
) return Boolean with Inline
;
60 function "=" (Left
, Right
: List
) return Boolean is
61 LN
: Node_Array
renames Left
.Nodes
;
62 RN
: Node_Array
renames Right
.Nodes
;
64 LI
: Count_Type
:= Left
.First
;
65 RI
: Count_Type
:= Right
.First
;
68 if Left
'Address = Right
'Address then
72 if Left
.Length
/= Right
.Length
then
76 for J
in 1 .. Left
.Length
loop
77 if LN
(LI
).Element
/= RN
(RI
).Element
then
93 (Container
: in out List
'Class;
94 New_Item
: Element_Type
;
95 New_Node
: out Count_Type
)
97 N
: Node_Array
renames Container
.Nodes
;
100 if Container
.Free
>= 0 then
101 New_Node
:= Container
.Free
;
102 N
(New_Node
).Element
:= New_Item
;
103 Container
.Free
:= N
(New_Node
).Next
;
106 New_Node
:= abs Container
.Free
;
107 N
(New_Node
).Element
:= New_Item
;
108 Container
.Free
:= Container
.Free
- 1;
117 (Container
: in out List
;
118 New_Item
: Element_Type
;
119 Count
: Count_Type
:= 1)
122 Insert
(Container
, No_Element
, New_Item
, Count
);
129 procedure Assign
(Target
: in out List
; Source
: List
) is
131 if Target
'Address = Source
'Address then
135 if Target
.Capacity
< Source
.Length
then
136 raise Constraint_Error
; -- ???
142 N
: Node_Array
renames Source
.Nodes
;
143 J
: Count_Type
:= Source
.First
;
147 Append
(Target
, N
(J
).Element
);
157 procedure Clear
(Container
: in out List
) is
158 N
: Node_Array
renames Container
.Nodes
;
162 if Container
.Length
= 0 then
163 pragma Assert
(Container
.First
= 0);
164 pragma Assert
(Container
.Last
= 0);
165 -- pragma Assert (Container.Busy = 0);
166 -- pragma Assert (Container.Lock = 0);
170 pragma Assert
(Container
.First
>= 1);
171 pragma Assert
(Container
.Last
>= 1);
172 pragma Assert
(N
(Container
.First
).Prev
= 0);
173 pragma Assert
(N
(Container
.Last
).Next
= 0);
175 -- if Container.Busy > 0 then
176 -- raise Program_Error;
179 while Container
.Length
> 1 loop
180 X
:= Container
.First
;
182 Container
.First
:= N
(X
).Next
;
183 N
(Container
.First
).Prev
:= 0;
185 Container
.Length
:= Container
.Length
- 1;
190 X
:= Container
.First
;
192 Container
.First
:= 0;
194 Container
.Length
:= 0;
205 Item
: Element_Type
) return Boolean
208 return Find
(Container
, Item
) /= No_Element
;
216 (Container
: in out List
;
217 Position
: in out Cursor
;
218 Count
: Count_Type
:= 1)
220 N
: Node_Array
renames Container
.Nodes
;
224 if Position
.Node
= 0 then
225 raise Constraint_Error
;
228 if Position
.Container
/= Container
'Unrestricted_Access then
232 pragma Assert
(Vet
(Position
), "bad cursor in Delete");
234 if Position
.Node
= Container
.First
then
235 Delete_First
(Container
, Count
);
236 Position
:= No_Element
;
241 Position
:= No_Element
;
245 -- if Container.Busy > 0 then
246 -- raise Program_Error;
249 pragma Assert
(Container
.First
>= 1);
250 pragma Assert
(Container
.Last
>= 1);
251 pragma Assert
(N
(Container
.First
).Prev
= 0);
252 pragma Assert
(N
(Container
.Last
).Next
= 0);
254 for Index
in 1 .. Count
loop
255 pragma Assert
(Container
.Length
>= 2);
258 Container
.Length
:= Container
.Length
- 1;
260 if X
= Container
.Last
then
261 Position
:= No_Element
;
263 Container
.Last
:= N
(X
).Prev
;
264 N
(Container
.Last
).Next
:= 0;
270 Position
.Node
:= N
(X
).Next
;
272 N
(N
(X
).Next
).Prev
:= N
(X
).Prev
;
273 N
(N
(X
).Prev
).Next
:= N
(X
).Next
;
278 Position
:= No_Element
;
285 procedure Delete_First
286 (Container
: in out List
;
287 Count
: Count_Type
:= 1)
289 N
: Node_Array
renames Container
.Nodes
;
293 if Count
>= Container
.Length
then
302 -- if Container.Busy > 0 then
303 -- raise Program_Error;
306 for I
in 1 .. Count
loop
307 X
:= Container
.First
;
308 pragma Assert
(N
(N
(X
).Next
).Prev
= Container
.First
);
310 Container
.First
:= N
(X
).Next
;
311 N
(Container
.First
).Prev
:= 0;
313 Container
.Length
:= Container
.Length
- 1;
323 procedure Delete_Last
324 (Container
: in out List
;
325 Count
: Count_Type
:= 1)
327 N
: Node_Array
renames Container
.Nodes
;
331 if Count
>= Container
.Length
then
340 -- if Container.Busy > 0 then
341 -- raise Program_Error;
344 for I
in 1 .. Count
loop
346 pragma Assert
(N
(N
(X
).Prev
).Next
= Container
.Last
);
348 Container
.Last
:= N
(X
).Prev
;
349 N
(Container
.Last
).Next
:= 0;
351 Container
.Length
:= Container
.Length
- 1;
361 function Element
(Position
: Cursor
) return Element_Type
is
363 if Position
.Node
= 0 then
364 raise Constraint_Error
;
367 pragma Assert
(Vet
(Position
), "bad cursor in Element");
370 N
: Node_Array
renames Position
.Container
.Nodes
;
372 return N
(Position
.Node
).Element
;
383 Position
: Cursor
:= No_Element
) return Cursor
385 Nodes
: Node_Array
renames Container
.Nodes
;
386 Node
: Count_Type
:= Position
.Node
;
390 Node
:= Container
.First
;
393 if Position
.Container
/= Container
'Unrestricted_Access then
397 pragma Assert
(Vet
(Position
), "bad cursor in Find");
401 if Nodes
(Node
).Element
= Item
then
402 return Cursor
'(Container'Unrestricted_Access, Node);
405 Node := Nodes (Node).Next;
415 function First (Container : List) return Cursor is
417 if Container.First = 0 then
421 return Cursor'(Container
'Unrestricted_Access, Container
.First
);
428 function First_Element
(Container
: List
) return Element_Type
is
429 N
: Node_Array
renames Container
.Nodes
;
432 if Container
.First
= 0 then
433 raise Constraint_Error
;
436 return N
(Container
.First
).Element
;
444 (Container
: in out List
'Class;
447 pragma Assert
(X
> 0);
448 pragma Assert
(X
<= Container
.Capacity
);
450 N
: Node_Array
renames Container
.Nodes
;
453 N
(X
).Prev
:= -1; -- Node is deallocated (not on active list)
455 if Container
.Free
>= 0 then
456 N
(X
).Next
:= Container
.Free
;
459 elsif X
+ 1 = abs Container
.Free
then
460 N
(X
).Next
:= 0; -- Not strictly necessary, but marginally safer
461 Container
.Free
:= Container
.Free
+ 1;
464 Container
.Free
:= abs Container
.Free
;
466 if Container
.Free
> Container
.Capacity
then
470 for I
in Container
.Free
.. Container
.Capacity
- 1 loop
474 N
(Container
.Capacity
).Next
:= 0;
477 N
(X
).Next
:= Container
.Free
;
482 ---------------------
483 -- Generic_Sorting --
484 ---------------------
486 package body Generic_Sorting
is
492 function Is_Sorted
(Container
: List
) return Boolean is
493 Nodes
: Node_Array
renames Container
.Nodes
;
494 Node
: Count_Type
:= Container
.First
;
497 for I
in 2 .. Container
.Length
loop
498 if Nodes
(Nodes
(Node
).Next
).Element
< Nodes
(Node
).Element
then
502 Node
:= Nodes
(Node
).Next
;
512 procedure Sort
(Container
: in out List
) is
513 N
: Node_Array
renames Container
.Nodes
;
515 if Container
.Length
<= 1 then
519 -- if Container.Busy > 0 then
520 -- raise Program_Error;
524 package Descriptors
is new List_Descriptors
525 (Node_Ref
=> Count_Type
, Nil
=> 0);
528 function Next
(Idx
: Count_Type
) return Count_Type
is
530 procedure Set_Next
(Idx
: Count_Type
; Next
: Count_Type
)
532 procedure Set_Prev
(Idx
: Count_Type
; Prev
: Count_Type
)
534 function "<" (L
, R
: Count_Type
) return Boolean is
535 (N
(L
).Element
< N
(R
).Element
);
536 procedure Update_Container
(List
: List_Descriptor
) with Inline
;
538 procedure Set_Next
(Idx
: Count_Type
; Next
: Count_Type
) is
540 N
(Idx
).Next
:= Next
;
543 procedure Set_Prev
(Idx
: Count_Type
; Prev
: Count_Type
) is
545 N
(Idx
).Prev
:= Prev
;
548 procedure Update_Container
(List
: List_Descriptor
) is
550 Container
.First
:= List
.First
;
551 Container
.Last
:= List
.Last
;
552 Container
.Length
:= List
.Length
;
553 end Update_Container
;
555 procedure Sort_List
is new Doubly_Linked_List_Sort
;
557 Sort_List
(List_Descriptor
'(First => Container.First,
558 Last => Container.Last,
559 Length => Container.Length));
562 pragma Assert (N (Container.First).Prev = 0);
563 pragma Assert (N (Container.Last).Next = 0);
572 function Has_Element (Position : Cursor) return Boolean is
574 pragma Assert (Vet (Position), "bad cursor in Has_Element");
575 return Position.Node /= 0;
583 (Container : in out List;
585 New_Item : Element_Type;
586 Position : out Cursor;
587 Count : Count_Type := 1)
589 First_Node : Count_Type;
590 New_Node : Count_Type;
593 if Before.Container /= null then
594 if Before.Container /= Container'Unrestricted_Access then
598 pragma Assert (Vet (Before), "bad cursor in Insert");
606 if Container.Length > Container.Capacity - Count then
607 raise Constraint_Error;
610 -- if Container.Busy > 0 then
611 -- raise Program_Error;
614 Allocate (Container, New_Item, New_Node);
615 First_Node := New_Node;
616 Insert_Internal (Container, Before.Node, New_Node);
618 for Index in 2 .. Count loop
619 Allocate (Container, New_Item, New_Node);
620 Insert_Internal (Container, Before.Node, New_Node);
623 Position := Cursor'(Container
'Unrestricted_Access, First_Node
);
627 (Container
: in out List
;
629 New_Item
: Element_Type
;
630 Count
: Count_Type
:= 1)
634 Insert
(Container
, Before
, New_Item
, Position
, Count
);
638 (Container
: in out List
;
640 Position
: out Cursor
;
641 Count
: Count_Type
:= 1)
643 New_Item
: Element_Type
; -- Do we need to reinit node ???
644 pragma Warnings
(Off
, New_Item
);
647 Insert
(Container
, Before
, New_Item
, Position
, Count
);
650 ---------------------
651 -- Insert_Internal --
652 ---------------------
654 procedure Insert_Internal
655 (Container
: in out List
'Class;
657 New_Node
: Count_Type
)
659 N
: Node_Array
renames Container
.Nodes
;
662 if Container
.Length
= 0 then
663 pragma Assert
(Before
= 0);
664 pragma Assert
(Container
.First
= 0);
665 pragma Assert
(Container
.Last
= 0);
667 Container
.First
:= New_Node
;
668 Container
.Last
:= New_Node
;
670 N
(Container
.First
).Prev
:= 0;
671 N
(Container
.Last
).Next
:= 0;
673 elsif Before
= 0 then
674 pragma Assert
(N
(Container
.Last
).Next
= 0);
676 N
(Container
.Last
).Next
:= New_Node
;
677 N
(New_Node
).Prev
:= Container
.Last
;
679 Container
.Last
:= New_Node
;
680 N
(Container
.Last
).Next
:= 0;
682 elsif Before
= Container
.First
then
683 pragma Assert
(N
(Container
.First
).Prev
= 0);
685 N
(Container
.First
).Prev
:= New_Node
;
686 N
(New_Node
).Next
:= Container
.First
;
688 Container
.First
:= New_Node
;
689 N
(Container
.First
).Prev
:= 0;
692 pragma Assert
(N
(Container
.First
).Prev
= 0);
693 pragma Assert
(N
(Container
.Last
).Next
= 0);
695 N
(New_Node
).Next
:= Before
;
696 N
(New_Node
).Prev
:= N
(Before
).Prev
;
698 N
(N
(Before
).Prev
).Next
:= New_Node
;
699 N
(Before
).Prev
:= New_Node
;
702 Container
.Length
:= Container
.Length
+ 1;
709 function Is_Empty
(Container
: List
) return Boolean is
711 return Container
.Length
= 0;
720 Process
: not null access procedure (Position
: Cursor
))
722 C
: List
renames Container
'Unrestricted_Access.all;
723 N
: Node_Array
renames C
.Nodes
;
724 -- B : Natural renames C.Busy;
726 Node
: Count_Type
:= Container
.First
;
728 Index
: Count_Type
:= 0;
729 Index_Max
: constant Count_Type
:= Container
.Length
;
732 if Index_Max
= 0 then
733 pragma Assert
(Node
= 0);
738 pragma Assert
(Node
/= 0);
740 Process
(Cursor
'(C'Unchecked_Access, Node));
741 pragma Assert (Container.Length = Index_Max);
742 pragma Assert (N (Node).Prev /= -1);
744 Node := N (Node).Next;
747 if Index = Index_Max then
748 pragma Assert (Node = 0);
758 function Last (Container : List) return Cursor is
760 if Container.Last = 0 then
764 return Cursor'(Container
'Unrestricted_Access, Container
.Last
);
771 function Last_Element
(Container
: List
) return Element_Type
is
772 N
: Node_Array
renames Container
.Nodes
;
775 if Container
.Last
= 0 then
776 raise Constraint_Error
;
779 return N
(Container
.Last
).Element
;
786 function Length
(Container
: List
) return Count_Type
is
788 return Container
.Length
;
795 procedure Next
(Position
: in out Cursor
) is
797 Position
:= Next
(Position
);
800 function Next
(Position
: Cursor
) return Cursor
is
802 if Position
.Node
= 0 then
806 pragma Assert
(Vet
(Position
), "bad cursor in Next");
809 Nodes
: Node_Array
renames Position
.Container
.Nodes
;
810 Node
: constant Count_Type
:= Nodes
(Position
.Node
).Next
;
817 return Cursor
'(Position.Container, Node);
826 (Container : in out List;
827 New_Item : Element_Type;
828 Count : Count_Type := 1)
831 Insert (Container, First (Container), New_Item, Count);
838 procedure Previous (Position : in out Cursor) is
840 Position := Previous (Position);
843 function Previous (Position : Cursor) return Cursor is
845 if Position.Node = 0 then
849 pragma Assert (Vet (Position), "bad cursor in Previous");
852 Nodes : Node_Array renames Position.Container.Nodes;
853 Node : constant Count_Type := Nodes (Position.Node).Prev;
859 return Cursor'(Position
.Container
, Node
);
867 procedure Query_Element
869 Process
: not null access procedure (Element
: Element_Type
))
872 if Position
.Node
= 0 then
873 raise Constraint_Error
;
876 pragma Assert
(Vet
(Position
), "bad cursor in Query_Element");
879 C
: List
renames Position
.Container
.all'Unrestricted_Access.all;
880 N
: Node_Type
renames C
.Nodes
(Position
.Node
);
884 pragma Assert
(N
.Prev
>= 0);
888 ---------------------
889 -- Replace_Element --
890 ---------------------
892 procedure Replace_Element
893 (Container
: in out List
;
895 New_Item
: Element_Type
)
898 if Position
.Container
= null then
899 raise Constraint_Error
;
902 if Position
.Container
/= Container
'Unrestricted_Access then
906 -- if Container.Lock > 0 then
907 -- raise Program_Error;
910 pragma Assert
(Vet
(Position
), "bad cursor in Replace_Element");
913 N
: Node_Array
renames Container
.Nodes
;
915 N
(Position
.Node
).Element
:= New_Item
;
919 ----------------------
920 -- Reverse_Elements --
921 ----------------------
923 procedure Reverse_Elements
(Container
: in out List
) is
924 N
: Node_Array
renames Container
.Nodes
;
925 I
: Count_Type
:= Container
.First
;
926 J
: Count_Type
:= Container
.Last
;
928 procedure Swap
(L
, R
: Count_Type
);
934 procedure Swap
(L
, R
: Count_Type
) is
935 LN
: constant Count_Type
:= N
(L
).Next
;
936 LP
: constant Count_Type
:= N
(L
).Prev
;
938 RN
: constant Count_Type
:= N
(R
).Next
;
939 RP
: constant Count_Type
:= N
(R
).Prev
;
954 pragma Assert
(RP
= L
);
968 -- Start of processing for Reverse_Elements
971 if Container
.Length
<= 1 then
975 pragma Assert
(N
(Container
.First
).Prev
= 0);
976 pragma Assert
(N
(Container
.Last
).Next
= 0);
978 -- if Container.Busy > 0 then
979 -- raise Program_Error;
982 Container
.First
:= J
;
985 Swap
(L
=> I
, R
=> J
);
993 Swap
(L
=> J
, R
=> I
);
1002 pragma Assert
(N
(Container
.First
).Prev
= 0);
1003 pragma Assert
(N
(Container
.Last
).Next
= 0);
1004 end Reverse_Elements
;
1010 function Reverse_Find
1012 Item
: Element_Type
;
1013 Position
: Cursor
:= No_Element
) return Cursor
1015 N
: Node_Array
renames Container
.Nodes
;
1016 Node
: Count_Type
:= Position
.Node
;
1020 Node
:= Container
.Last
;
1023 if Position
.Container
/= Container
'Unrestricted_Access then
1024 raise Program_Error
;
1027 pragma Assert
(Vet
(Position
), "bad cursor in Reverse_Find");
1030 while Node
/= 0 loop
1031 if N
(Node
).Element
= Item
then
1032 return Cursor
'(Container'Unrestricted_Access, Node);
1035 Node := N (Node).Prev;
1041 ---------------------
1042 -- Reverse_Iterate --
1043 ---------------------
1045 procedure Reverse_Iterate
1047 Process : not null access procedure (Position : Cursor))
1049 C : List renames Container'Unrestricted_Access.all;
1050 N : Node_Array renames C.Nodes;
1051 -- B : Natural renames C.Busy;
1053 Node : Count_Type := Container.Last;
1055 Index : Count_Type := 0;
1056 Index_Max : constant Count_Type := Container.Length;
1059 if Index_Max = 0 then
1060 pragma Assert (Node = 0);
1065 pragma Assert (Node > 0);
1067 Process (Cursor'(C
'Unchecked_Access, Node
));
1068 pragma Assert
(Container
.Length
= Index_Max
);
1069 pragma Assert
(N
(Node
).Prev
/= -1);
1071 Node
:= N
(Node
).Prev
;
1074 if Index
= Index_Max
then
1075 pragma Assert
(Node
= 0);
1079 end Reverse_Iterate
;
1086 (Container
: in out List
;
1088 Position
: in out Cursor
)
1090 N
: Node_Array
renames Container
.Nodes
;
1093 if Before
.Container
/= null then
1094 if Before
.Container
/= Container
'Unrestricted_Access then
1095 raise Program_Error
;
1098 pragma Assert
(Vet
(Before
), "bad Before cursor in Splice");
1101 if Position
.Node
= 0 then
1102 raise Constraint_Error
;
1105 if Position
.Container
/= Container
'Unrestricted_Access then
1106 raise Program_Error
;
1109 pragma Assert
(Vet
(Position
), "bad Position cursor in Splice");
1111 if Position
.Node
= Before
.Node
1112 or else N
(Position
.Node
).Next
= Before
.Node
1117 pragma Assert
(Container
.Length
>= 2);
1119 -- if Container.Busy > 0 then
1120 -- raise Program_Error;
1123 if Before
.Node
= 0 then
1124 pragma Assert
(Position
.Node
/= Container
.Last
);
1126 if Position
.Node
= Container
.First
then
1127 Container
.First
:= N
(Position
.Node
).Next
;
1128 N
(Container
.First
).Prev
:= 0;
1131 N
(N
(Position
.Node
).Prev
).Next
:= N
(Position
.Node
).Next
;
1132 N
(N
(Position
.Node
).Next
).Prev
:= N
(Position
.Node
).Prev
;
1135 N
(Container
.Last
).Next
:= Position
.Node
;
1136 N
(Position
.Node
).Prev
:= Container
.Last
;
1138 Container
.Last
:= Position
.Node
;
1139 N
(Container
.Last
).Next
:= 0;
1144 if Before
.Node
= Container
.First
then
1145 pragma Assert
(Position
.Node
/= Container
.First
);
1147 if Position
.Node
= Container
.Last
then
1148 Container
.Last
:= N
(Position
.Node
).Prev
;
1149 N
(Container
.Last
).Next
:= 0;
1152 N
(N
(Position
.Node
).Prev
).Next
:= N
(Position
.Node
).Next
;
1153 N
(N
(Position
.Node
).Next
).Prev
:= N
(Position
.Node
).Prev
;
1156 N
(Container
.First
).Prev
:= Position
.Node
;
1157 N
(Position
.Node
).Next
:= Container
.First
;
1159 Container
.First
:= Position
.Node
;
1160 N
(Container
.First
).Prev
:= 0;
1165 if Position
.Node
= Container
.First
then
1166 Container
.First
:= N
(Position
.Node
).Next
;
1167 N
(Container
.First
).Prev
:= 0;
1169 elsif Position
.Node
= Container
.Last
then
1170 Container
.Last
:= N
(Position
.Node
).Prev
;
1171 N
(Container
.Last
).Next
:= 0;
1174 N
(N
(Position
.Node
).Prev
).Next
:= N
(Position
.Node
).Next
;
1175 N
(N
(Position
.Node
).Next
).Prev
:= N
(Position
.Node
).Prev
;
1178 N
(N
(Before
.Node
).Prev
).Next
:= Position
.Node
;
1179 N
(Position
.Node
).Prev
:= N
(Before
.Node
).Prev
;
1181 N
(Before
.Node
).Prev
:= Position
.Node
;
1182 N
(Position
.Node
).Next
:= Before
.Node
;
1184 pragma Assert
(N
(Container
.First
).Prev
= 0);
1185 pragma Assert
(N
(Container
.Last
).Next
= 0);
1193 (Container
: in out List
;
1200 raise Constraint_Error
;
1203 if I
.Container
/= Container
'Unrestricted_Access
1204 or else J
.Container
/= Container
'Unrestricted_Access
1206 raise Program_Error
;
1209 if I
.Node
= J
.Node
then
1213 -- if Container.Lock > 0 then
1214 -- raise Program_Error;
1217 pragma Assert
(Vet
(I
), "bad I cursor in Swap");
1218 pragma Assert
(Vet
(J
), "bad J cursor in Swap");
1221 N
: Node_Array
renames Container
.Nodes
;
1223 EI
: Element_Type
renames N
(I
.Node
).Element
;
1224 EJ
: Element_Type
renames N
(J
.Node
).Element
;
1226 EI_Copy
: constant Element_Type
:= EI
;
1238 procedure Swap_Links
1239 (Container
: in out List
;
1246 raise Constraint_Error
;
1249 if I
.Container
/= Container
'Unrestricted_Access
1250 or else I
.Container
/= J
.Container
1252 raise Program_Error
;
1255 if I
.Node
= J
.Node
then
1259 -- if Container.Busy > 0 then
1260 -- raise Program_Error;
1263 pragma Assert
(Vet
(I
), "bad I cursor in Swap_Links");
1264 pragma Assert
(Vet
(J
), "bad J cursor in Swap_Links");
1267 I_Next
: constant Cursor
:= Next
(I
);
1269 J_Copy
: Cursor
:= J
;
1270 pragma Warnings
(Off
, J_Copy
);
1274 Splice
(Container
, Before
=> I
, Position
=> J_Copy
);
1278 J_Next
: constant Cursor
:= Next
(J
);
1280 I_Copy
: Cursor
:= I
;
1281 pragma Warnings
(Off
, I_Copy
);
1285 Splice
(Container
, Before
=> J
, Position
=> I_Copy
);
1288 pragma Assert
(Container
.Length
>= 3);
1290 Splice
(Container
, Before
=> I_Next
, Position
=> J_Copy
);
1291 Splice
(Container
, Before
=> J_Next
, Position
=> I_Copy
);
1298 --------------------
1299 -- Update_Element --
1300 --------------------
1302 procedure Update_Element
1303 (Container
: in out List
;
1305 Process
: not null access procedure (Element
: in out Element_Type
))
1308 if Position
.Node
= 0 then
1309 raise Constraint_Error
;
1312 if Position
.Container
/= Container
'Unrestricted_Access then
1313 raise Program_Error
;
1316 pragma Assert
(Vet
(Position
), "bad cursor in Update_Element");
1319 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1322 Process
(N
.Element
);
1323 pragma Assert
(N
.Prev
>= 0);
1331 function Vet
(Position
: Cursor
) return Boolean is
1333 if not Container_Checks
'Enabled then
1337 if Position
.Node
= 0 then
1338 return Position
.Container
= null;
1341 if Position
.Container
= null then
1346 L
: List
renames Position
.Container
.all;
1347 N
: Node_Array
renames L
.Nodes
;
1350 if L
.Length
= 0 then
1362 if Position
.Node
> L
.Capacity
then
1366 if N
(Position
.Node
).Prev
< 0
1367 or else N
(Position
.Node
).Prev
> L
.Capacity
1372 if N
(Position
.Node
).Next
> L
.Capacity
then
1376 if N
(L
.First
).Prev
/= 0 then
1380 if N
(L
.Last
).Next
/= 0 then
1384 if N
(Position
.Node
).Prev
= 0
1385 and then Position
.Node
/= L
.First
1390 if N
(Position
.Node
).Next
= 0
1391 and then Position
.Node
/= L
.Last
1396 if L
.Length
= 1 then
1397 return L
.First
= L
.Last
;
1400 if L
.First
= L
.Last
then
1404 if N
(L
.First
).Next
= 0 then
1408 if N
(L
.Last
).Prev
= 0 then
1412 if N
(N
(L
.First
).Next
).Prev
/= L
.First
then
1416 if N
(N
(L
.Last
).Prev
).Next
/= L
.Last
then
1420 if L
.Length
= 2 then
1421 if N
(L
.First
).Next
/= L
.Last
then
1425 if N
(L
.Last
).Prev
/= L
.First
then
1432 if N
(L
.First
).Next
= L
.Last
then
1436 if N
(L
.Last
).Prev
= L
.First
then
1440 if Position
.Node
= L
.First
then
1444 if Position
.Node
= L
.Last
then
1448 if N
(Position
.Node
).Next
= 0 then
1452 if N
(Position
.Node
).Prev
= 0 then
1456 if N
(N
(Position
.Node
).Next
).Prev
/= Position
.Node
then
1460 if N
(N
(Position
.Node
).Prev
).Next
/= Position
.Node
then
1464 if L
.Length
= 3 then
1465 if N
(L
.First
).Next
/= Position
.Node
then
1469 if N
(L
.Last
).Prev
/= Position
.Node
then
1478 end Ada
.Containers
.Restricted_Doubly_Linked_Lists
;