1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.RESTRICTED_DOUBLY_LINKED_LISTS --
9 -- Copyright (C) 2004-2009, 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 System
; use type System
.Address
;
32 package body Ada
.Containers
.Restricted_Doubly_Linked_Lists
is
34 -----------------------
35 -- Local Subprograms --
36 -----------------------
39 (Container
: in out List
'Class;
40 New_Item
: Element_Type
;
41 New_Node
: out Count_Type
);
44 (Container
: in out List
'Class;
47 procedure Insert_Internal
48 (Container
: in out List
'Class;
50 New_Node
: Count_Type
);
52 function Vet
(Position
: Cursor
) return Boolean;
58 function "=" (Left
, Right
: List
) return Boolean is
59 LN
: Node_Array
renames Left
.Nodes
;
60 RN
: Node_Array
renames Right
.Nodes
;
62 LI
: Count_Type
:= Left
.First
;
63 RI
: Count_Type
:= Right
.First
;
66 if Left
'Address = Right
'Address then
70 if Left
.Length
/= Right
.Length
then
74 for J
in 1 .. Left
.Length
loop
75 if LN
(LI
).Element
/= RN
(RI
).Element
then
91 (Container
: in out List
'Class;
92 New_Item
: Element_Type
;
93 New_Node
: out Count_Type
)
95 N
: Node_Array
renames Container
.Nodes
;
98 if Container
.Free
>= 0 then
99 New_Node
:= Container
.Free
;
100 N
(New_Node
).Element
:= New_Item
;
101 Container
.Free
:= N
(New_Node
).Next
;
104 New_Node
:= abs Container
.Free
;
105 N
(New_Node
).Element
:= New_Item
;
106 Container
.Free
:= Container
.Free
- 1;
115 (Container
: in out List
;
116 New_Item
: Element_Type
;
117 Count
: Count_Type
:= 1)
120 Insert
(Container
, No_Element
, New_Item
, Count
);
127 procedure Assign
(Target
: in out List
; Source
: List
) is
129 if Target
'Address = Source
'Address then
133 if Target
.Capacity
< Source
.Length
then
134 raise Constraint_Error
; -- ???
140 N
: Node_Array
renames Source
.Nodes
;
141 J
: Count_Type
:= Source
.First
;
145 Append
(Target
, N
(J
).Element
);
155 procedure Clear
(Container
: in out List
) is
156 N
: Node_Array
renames Container
.Nodes
;
160 if Container
.Length
= 0 then
161 pragma Assert
(Container
.First
= 0);
162 pragma Assert
(Container
.Last
= 0);
163 -- pragma Assert (Container.Busy = 0);
164 -- pragma Assert (Container.Lock = 0);
168 pragma Assert
(Container
.First
>= 1);
169 pragma Assert
(Container
.Last
>= 1);
170 pragma Assert
(N
(Container
.First
).Prev
= 0);
171 pragma Assert
(N
(Container
.Last
).Next
= 0);
173 -- if Container.Busy > 0 then
174 -- raise Program_Error;
177 while Container
.Length
> 1 loop
178 X
:= Container
.First
;
180 Container
.First
:= N
(X
).Next
;
181 N
(Container
.First
).Prev
:= 0;
183 Container
.Length
:= Container
.Length
- 1;
188 X
:= Container
.First
;
190 Container
.First
:= 0;
192 Container
.Length
:= 0;
203 Item
: Element_Type
) return Boolean
206 return Find
(Container
, Item
) /= No_Element
;
214 (Container
: in out List
;
215 Position
: in out Cursor
;
216 Count
: Count_Type
:= 1)
218 N
: Node_Array
renames Container
.Nodes
;
222 if Position
.Node
= 0 then
223 raise Constraint_Error
;
226 if Position
.Container
/= Container
'Unrestricted_Access then
230 pragma Assert
(Vet
(Position
), "bad cursor in Delete");
232 if Position
.Node
= Container
.First
then
233 Delete_First
(Container
, Count
);
234 Position
:= No_Element
;
239 Position
:= No_Element
;
243 -- if Container.Busy > 0 then
244 -- raise Program_Error;
247 pragma Assert
(Container
.First
>= 1);
248 pragma Assert
(Container
.Last
>= 1);
249 pragma Assert
(N
(Container
.First
).Prev
= 0);
250 pragma Assert
(N
(Container
.Last
).Next
= 0);
252 for Index
in 1 .. Count
loop
253 pragma Assert
(Container
.Length
>= 2);
256 Container
.Length
:= Container
.Length
- 1;
258 if X
= Container
.Last
then
259 Position
:= No_Element
;
261 Container
.Last
:= N
(X
).Prev
;
262 N
(Container
.Last
).Next
:= 0;
268 Position
.Node
:= N
(X
).Next
;
270 N
(N
(X
).Next
).Prev
:= N
(X
).Prev
;
271 N
(N
(X
).Prev
).Next
:= N
(X
).Next
;
276 Position
:= No_Element
;
283 procedure Delete_First
284 (Container
: in out List
;
285 Count
: Count_Type
:= 1)
287 N
: Node_Array
renames Container
.Nodes
;
291 if Count
>= Container
.Length
then
300 -- if Container.Busy > 0 then
301 -- raise Program_Error;
304 for I
in 1 .. Count
loop
305 X
:= Container
.First
;
306 pragma Assert
(N
(N
(X
).Next
).Prev
= Container
.First
);
308 Container
.First
:= N
(X
).Next
;
309 N
(Container
.First
).Prev
:= 0;
311 Container
.Length
:= Container
.Length
- 1;
321 procedure Delete_Last
322 (Container
: in out List
;
323 Count
: Count_Type
:= 1)
325 N
: Node_Array
renames Container
.Nodes
;
329 if Count
>= Container
.Length
then
338 -- if Container.Busy > 0 then
339 -- raise Program_Error;
342 for I
in 1 .. Count
loop
344 pragma Assert
(N
(N
(X
).Prev
).Next
= Container
.Last
);
346 Container
.Last
:= N
(X
).Prev
;
347 N
(Container
.Last
).Next
:= 0;
349 Container
.Length
:= Container
.Length
- 1;
359 function Element
(Position
: Cursor
) return Element_Type
is
361 if Position
.Node
= 0 then
362 raise Constraint_Error
;
365 pragma Assert
(Vet
(Position
), "bad cursor in Element");
368 N
: Node_Array
renames Position
.Container
.Nodes
;
370 return N
(Position
.Node
).Element
;
381 Position
: Cursor
:= No_Element
) return Cursor
383 Nodes
: Node_Array
renames Container
.Nodes
;
384 Node
: Count_Type
:= Position
.Node
;
388 Node
:= Container
.First
;
391 if Position
.Container
/= Container
'Unrestricted_Access then
395 pragma Assert
(Vet
(Position
), "bad cursor in Find");
399 if Nodes
(Node
).Element
= Item
then
400 return Cursor
'(Container'Unrestricted_Access, Node);
403 Node := Nodes (Node).Next;
413 function First (Container : List) return Cursor is
415 if Container.First = 0 then
419 return Cursor'(Container
'Unrestricted_Access, Container
.First
);
426 function First_Element
(Container
: List
) return Element_Type
is
427 N
: Node_Array
renames Container
.Nodes
;
430 if Container
.First
= 0 then
431 raise Constraint_Error
;
434 return N
(Container
.First
).Element
;
442 (Container
: in out List
'Class;
445 pragma Assert
(X
> 0);
446 pragma Assert
(X
<= Container
.Capacity
);
448 N
: Node_Array
renames Container
.Nodes
;
451 N
(X
).Prev
:= -1; -- Node is deallocated (not on active list)
453 if Container
.Free
>= 0 then
454 N
(X
).Next
:= Container
.Free
;
457 elsif X
+ 1 = abs Container
.Free
then
458 N
(X
).Next
:= 0; -- Not strictly necessary, but marginally safer
459 Container
.Free
:= Container
.Free
+ 1;
462 Container
.Free
:= abs Container
.Free
;
464 if Container
.Free
> Container
.Capacity
then
468 for I
in Container
.Free
.. Container
.Capacity
- 1 loop
472 N
(Container
.Capacity
).Next
:= 0;
475 N
(X
).Next
:= Container
.Free
;
480 ---------------------
481 -- Generic_Sorting --
482 ---------------------
484 package body Generic_Sorting
is
490 function Is_Sorted
(Container
: List
) return Boolean is
491 Nodes
: Node_Array
renames Container
.Nodes
;
492 Node
: Count_Type
:= Container
.First
;
495 for I
in 2 .. Container
.Length
loop
496 if Nodes
(Nodes
(Node
).Next
).Element
< Nodes
(Node
).Element
then
500 Node
:= Nodes
(Node
).Next
;
510 procedure Sort
(Container
: in out List
) is
511 N
: Node_Array
renames Container
.Nodes
;
513 procedure Partition
(Pivot
, Back
: Count_Type
);
514 procedure Sort
(Front
, Back
: Count_Type
);
520 procedure Partition
(Pivot
, Back
: Count_Type
) is
521 Node
: Count_Type
:= N
(Pivot
).Next
;
524 while Node
/= Back
loop
525 if N
(Node
).Element
< N
(Pivot
).Element
then
527 Prev
: constant Count_Type
:= N
(Node
).Prev
;
528 Next
: constant Count_Type
:= N
(Node
).Next
;
531 N
(Prev
).Next
:= Next
;
534 Container
.Last
:= Prev
;
536 N
(Next
).Prev
:= Prev
;
539 N
(Node
).Next
:= Pivot
;
540 N
(Node
).Prev
:= N
(Pivot
).Prev
;
542 N
(Pivot
).Prev
:= Node
;
544 if N
(Node
).Prev
= 0 then
545 Container
.First
:= Node
;
547 N
(N
(Node
).Prev
).Next
:= Node
;
554 Node
:= N
(Node
).Next
;
563 procedure Sort
(Front
, Back
: Count_Type
) is
568 Pivot
:= Container
.First
;
570 Pivot
:= N
(Front
).Next
;
573 if Pivot
/= Back
then
574 Partition
(Pivot
, Back
);
580 -- Start of processing for Sort
583 if Container
.Length
<= 1 then
587 pragma Assert
(N
(Container
.First
).Prev
= 0);
588 pragma Assert
(N
(Container
.Last
).Next
= 0);
590 -- if Container.Busy > 0 then
591 -- raise Program_Error;
594 Sort
(Front
=> 0, Back
=> 0);
596 pragma Assert
(N
(Container
.First
).Prev
= 0);
597 pragma Assert
(N
(Container
.Last
).Next
= 0);
606 function Has_Element
(Position
: Cursor
) return Boolean is
608 pragma Assert
(Vet
(Position
), "bad cursor in Has_Element");
609 return Position
.Node
/= 0;
617 (Container
: in out List
;
619 New_Item
: Element_Type
;
620 Position
: out Cursor
;
621 Count
: Count_Type
:= 1)
626 if Before
.Container
/= null then
627 if Before
.Container
/= Container
'Unrestricted_Access then
631 pragma Assert
(Vet
(Before
), "bad cursor in Insert");
639 if Container
.Length
> Container
.Capacity
- Count
then
640 raise Constraint_Error
;
643 -- if Container.Busy > 0 then
644 -- raise Program_Error;
647 Allocate
(Container
, New_Item
, New_Node
=> J
);
648 Insert_Internal
(Container
, Before
.Node
, New_Node
=> J
);
649 Position
:= Cursor
'(Container'Unrestricted_Access, Node => J);
651 for Index in 2 .. Count loop
652 Allocate (Container, New_Item, New_Node => J);
653 Insert_Internal (Container, Before.Node, New_Node => J);
658 (Container : in out List;
660 New_Item : Element_Type;
661 Count : Count_Type := 1)
664 pragma Unreferenced (Position);
666 Insert (Container, Before, New_Item, Position, Count);
670 (Container : in out List;
672 Position : out Cursor;
673 Count : Count_Type := 1)
675 New_Item : Element_Type; -- Do we need to reinit node ???
676 pragma Warnings (Off, New_Item);
679 Insert (Container, Before, New_Item, Position, Count);
682 ---------------------
683 -- Insert_Internal --
684 ---------------------
686 procedure Insert_Internal
687 (Container : in out List'Class;
689 New_Node : Count_Type)
691 N : Node_Array renames Container.Nodes;
694 if Container.Length = 0 then
695 pragma Assert (Before = 0);
696 pragma Assert (Container.First = 0);
697 pragma Assert (Container.Last = 0);
699 Container.First := New_Node;
700 Container.Last := New_Node;
702 N (Container.First).Prev := 0;
703 N (Container.Last).Next := 0;
705 elsif Before = 0 then
706 pragma Assert (N (Container.Last).Next = 0);
708 N (Container.Last).Next := New_Node;
709 N (New_Node).Prev := Container.Last;
711 Container.Last := New_Node;
712 N (Container.Last).Next := 0;
714 elsif Before = Container.First then
715 pragma Assert (N (Container.First).Prev = 0);
717 N (Container.First).Prev := New_Node;
718 N (New_Node).Next := Container.First;
720 Container.First := New_Node;
721 N (Container.First).Prev := 0;
724 pragma Assert (N (Container.First).Prev = 0);
725 pragma Assert (N (Container.Last).Next = 0);
727 N (New_Node).Next := Before;
728 N (New_Node).Prev := N (Before).Prev;
730 N (N (Before).Prev).Next := New_Node;
731 N (Before).Prev := New_Node;
734 Container.Length := Container.Length + 1;
741 function Is_Empty (Container : List) return Boolean is
743 return Container.Length = 0;
752 Process : not null access procedure (Position : Cursor))
754 C : List renames Container'Unrestricted_Access.all;
755 N : Node_Array renames C.Nodes;
756 -- B : Natural renames C.Busy;
758 Node : Count_Type := Container.First;
760 Index : Count_Type := 0;
761 Index_Max : constant Count_Type := Container.Length;
764 if Index_Max = 0 then
765 pragma Assert (Node = 0);
770 pragma Assert (Node /= 0);
772 Process (Cursor'(C
'Unchecked_Access, Node
));
773 pragma Assert
(Container
.Length
= Index_Max
);
774 pragma Assert
(N
(Node
).Prev
/= -1);
776 Node
:= N
(Node
).Next
;
779 if Index
= Index_Max
then
780 pragma Assert
(Node
= 0);
790 function Last
(Container
: List
) return Cursor
is
792 if Container
.Last
= 0 then
796 return Cursor
'(Container'Unrestricted_Access, Container.Last);
803 function Last_Element (Container : List) return Element_Type is
804 N : Node_Array renames Container.Nodes;
807 if Container.Last = 0 then
808 raise Constraint_Error;
811 return N (Container.Last).Element;
818 function Length (Container : List) return Count_Type is
820 return Container.Length;
827 procedure Next (Position : in out Cursor) is
829 Position := Next (Position);
832 function Next (Position : Cursor) return Cursor is
834 if Position.Node = 0 then
838 pragma Assert (Vet (Position), "bad cursor in Next");
841 Nodes : Node_Array renames Position.Container.Nodes;
842 Node : constant Count_Type := Nodes (Position.Node).Next;
849 return Cursor'(Position
.Container
, Node
);
858 (Container
: in out List
;
859 New_Item
: Element_Type
;
860 Count
: Count_Type
:= 1)
863 Insert
(Container
, First
(Container
), New_Item
, Count
);
870 procedure Previous
(Position
: in out Cursor
) is
872 Position
:= Previous
(Position
);
875 function Previous
(Position
: Cursor
) return Cursor
is
877 if Position
.Node
= 0 then
881 pragma Assert
(Vet
(Position
), "bad cursor in Previous");
884 Nodes
: Node_Array
renames Position
.Container
.Nodes
;
885 Node
: constant Count_Type
:= Nodes
(Position
.Node
).Prev
;
891 return Cursor
'(Position.Container, Node);
899 procedure Query_Element
901 Process : not null access procedure (Element : Element_Type))
904 if Position.Node = 0 then
905 raise Constraint_Error;
908 pragma Assert (Vet (Position), "bad cursor in Query_Element");
911 C : List renames Position.Container.all'Unrestricted_Access.all;
912 N : Node_Type renames C.Nodes (Position.Node);
916 pragma Assert (N.Prev >= 0);
920 ---------------------
921 -- Replace_Element --
922 ---------------------
924 procedure Replace_Element
925 (Container : in out List;
927 New_Item : Element_Type)
930 if Position.Container = null then
931 raise Constraint_Error;
934 if Position.Container /= Container'Unrestricted_Access then
938 -- if Container.Lock > 0 then
939 -- raise Program_Error;
942 pragma Assert (Vet (Position), "bad cursor in Replace_Element");
945 N : Node_Array renames Container.Nodes;
947 N (Position.Node).Element := New_Item;
951 ----------------------
952 -- Reverse_Elements --
953 ----------------------
955 procedure Reverse_Elements (Container : in out List) is
956 N : Node_Array renames Container.Nodes;
957 I : Count_Type := Container.First;
958 J : Count_Type := Container.Last;
960 procedure Swap (L, R : Count_Type);
966 procedure Swap (L, R : Count_Type) is
967 LN : constant Count_Type := N (L).Next;
968 LP : constant Count_Type := N (L).Prev;
970 RN : constant Count_Type := N (R).Next;
971 RP : constant Count_Type := N (R).Prev;
986 pragma Assert (RP = L);
1000 -- Start of processing for Reverse_Elements
1003 if Container.Length <= 1 then
1007 pragma Assert (N (Container.First).Prev = 0);
1008 pragma Assert (N (Container.Last).Next = 0);
1010 -- if Container.Busy > 0 then
1011 -- raise Program_Error;
1014 Container.First := J;
1015 Container.Last := I;
1017 Swap (L => I, R => J);
1025 Swap (L => J, R => I);
1034 pragma Assert (N (Container.First).Prev = 0);
1035 pragma Assert (N (Container.Last).Next = 0);
1036 end Reverse_Elements;
1042 function Reverse_Find
1044 Item : Element_Type;
1045 Position : Cursor := No_Element) return Cursor
1047 N : Node_Array renames Container.Nodes;
1048 Node : Count_Type := Position.Node;
1052 Node := Container.Last;
1055 if Position.Container /= Container'Unrestricted_Access then
1056 raise Program_Error;
1059 pragma Assert (Vet (Position), "bad cursor in Reverse_Find");
1062 while Node /= 0 loop
1063 if N (Node).Element = Item then
1064 return Cursor'(Container
'Unrestricted_Access, Node
);
1067 Node
:= N
(Node
).Prev
;
1073 ---------------------
1074 -- Reverse_Iterate --
1075 ---------------------
1077 procedure Reverse_Iterate
1079 Process
: not null access procedure (Position
: Cursor
))
1081 C
: List
renames Container
'Unrestricted_Access.all;
1082 N
: Node_Array
renames C
.Nodes
;
1083 -- B : Natural renames C.Busy;
1085 Node
: Count_Type
:= Container
.Last
;
1087 Index
: Count_Type
:= 0;
1088 Index_Max
: constant Count_Type
:= Container
.Length
;
1091 if Index_Max
= 0 then
1092 pragma Assert
(Node
= 0);
1097 pragma Assert
(Node
> 0);
1099 Process
(Cursor
'(C'Unchecked_Access, Node));
1100 pragma Assert (Container.Length = Index_Max);
1101 pragma Assert (N (Node).Prev /= -1);
1103 Node := N (Node).Prev;
1106 if Index = Index_Max then
1107 pragma Assert (Node = 0);
1111 end Reverse_Iterate;
1118 (Container : in out List;
1120 Position : in out Cursor)
1122 N : Node_Array renames Container.Nodes;
1125 if Before.Container /= null then
1126 if Before.Container /= Container'Unrestricted_Access then
1127 raise Program_Error;
1130 pragma Assert (Vet (Before), "bad Before cursor in Splice");
1133 if Position.Node = 0 then
1134 raise Constraint_Error;
1137 if Position.Container /= Container'Unrestricted_Access then
1138 raise Program_Error;
1141 pragma Assert (Vet (Position), "bad Position cursor in Splice");
1143 if Position.Node = Before.Node
1144 or else N (Position.Node).Next = Before.Node
1149 pragma Assert (Container.Length >= 2);
1151 -- if Container.Busy > 0 then
1152 -- raise Program_Error;
1155 if Before.Node = 0 then
1156 pragma Assert (Position.Node /= Container.Last);
1158 if Position.Node = Container.First then
1159 Container.First := N (Position.Node).Next;
1160 N (Container.First).Prev := 0;
1163 N (N (Position.Node).Prev).Next := N (Position.Node).Next;
1164 N (N (Position.Node).Next).Prev := N (Position.Node).Prev;
1167 N (Container.Last).Next := Position.Node;
1168 N (Position.Node).Prev := Container.Last;
1170 Container.Last := Position.Node;
1171 N (Container.Last).Next := 0;
1176 if Before.Node = Container.First then
1177 pragma Assert (Position.Node /= Container.First);
1179 if Position.Node = Container.Last then
1180 Container.Last := N (Position.Node).Prev;
1181 N (Container.Last).Next := 0;
1184 N (N (Position.Node).Prev).Next := N (Position.Node).Next;
1185 N (N (Position.Node).Next).Prev := N (Position.Node).Prev;
1188 N (Container.First).Prev := Position.Node;
1189 N (Position.Node).Next := Container.First;
1191 Container.First := Position.Node;
1192 N (Container.First).Prev := 0;
1197 if Position.Node = Container.First then
1198 Container.First := N (Position.Node).Next;
1199 N (Container.First).Prev := 0;
1201 elsif Position.Node = Container.Last then
1202 Container.Last := N (Position.Node).Prev;
1203 N (Container.Last).Next := 0;
1206 N (N (Position.Node).Prev).Next := N (Position.Node).Next;
1207 N (N (Position.Node).Next).Prev := N (Position.Node).Prev;
1210 N (N (Before.Node).Prev).Next := Position.Node;
1211 N (Position.Node).Prev := N (Before.Node).Prev;
1213 N (Before.Node).Prev := Position.Node;
1214 N (Position.Node).Next := Before.Node;
1216 pragma Assert (N (Container.First).Prev = 0);
1217 pragma Assert (N (Container.Last).Next = 0);
1225 (Container : in out List;
1232 raise Constraint_Error;
1235 if I.Container /= Container'Unrestricted_Access
1236 or else J.Container /= Container'Unrestricted_Access
1238 raise Program_Error;
1241 if I.Node = J.Node then
1245 -- if Container.Lock > 0 then
1246 -- raise Program_Error;
1249 pragma Assert (Vet (I), "bad I cursor in Swap");
1250 pragma Assert (Vet (J), "bad J cursor in Swap");
1253 N : Node_Array renames Container.Nodes;
1255 EI : Element_Type renames N (I.Node).Element;
1256 EJ : Element_Type renames N (J.Node).Element;
1258 EI_Copy : constant Element_Type := EI;
1270 procedure Swap_Links
1271 (Container : in out List;
1278 raise Constraint_Error;
1281 if I.Container /= Container'Unrestricted_Access
1282 or else I.Container /= J.Container
1284 raise Program_Error;
1287 if I.Node = J.Node then
1291 -- if Container.Busy > 0 then
1292 -- raise Program_Error;
1295 pragma Assert (Vet (I), "bad I cursor in Swap_Links");
1296 pragma Assert (Vet (J), "bad J cursor in Swap_Links");
1299 I_Next : constant Cursor := Next (I);
1301 J_Copy : Cursor := J;
1302 pragma Warnings (Off, J_Copy);
1306 Splice (Container, Before => I, Position => J_Copy);
1310 J_Next : constant Cursor := Next (J);
1312 I_Copy : Cursor := I;
1313 pragma Warnings (Off, I_Copy);
1317 Splice (Container, Before => J, Position => I_Copy);
1320 pragma Assert (Container.Length >= 3);
1322 Splice (Container, Before => I_Next, Position => J_Copy);
1323 Splice (Container, Before => J_Next, Position => I_Copy);
1330 --------------------
1331 -- Update_Element --
1332 --------------------
1334 procedure Update_Element
1335 (Container : in out List;
1337 Process : not null access procedure (Element : in out Element_Type))
1340 if Position.Node = 0 then
1341 raise Constraint_Error;
1344 if Position.Container /= Container'Unrestricted_Access then
1345 raise Program_Error;
1348 pragma Assert (Vet (Position), "bad cursor in Update_Element");
1351 N : Node_Type renames Container.Nodes (Position.Node);
1354 Process (N.Element);
1355 pragma Assert (N.Prev >= 0);
1363 function Vet (Position : Cursor) return Boolean is
1365 if Position.Node = 0 then
1366 return Position.Container = null;
1369 if Position.Container = null then
1374 L : List renames Position.Container.all;
1375 N : Node_Array renames L.Nodes;
1378 if L.Length = 0 then
1390 if Position.Node > L.Capacity then
1394 if N (Position.Node).Prev < 0
1395 or else N (Position.Node).Prev > L.Capacity
1400 if N (Position.Node).Next > L.Capacity then
1404 if N (L.First).Prev /= 0 then
1408 if N (L.Last).Next /= 0 then
1412 if N (Position.Node).Prev = 0
1413 and then Position.Node /= L.First
1418 if N (Position.Node).Next = 0
1419 and then Position.Node /= L.Last
1424 if L.Length = 1 then
1425 return L.First = L.Last;
1428 if L.First = L.Last then
1432 if N (L.First).Next = 0 then
1436 if N (L.Last).Prev = 0 then
1440 if N (N (L.First).Next).Prev /= L.First then
1444 if N (N (L.Last).Prev).Next /= L.Last then
1448 if L.Length = 2 then
1449 if N (L.First).Next /= L.Last then
1453 if N (L.Last).Prev /= L.First then
1460 if N (L.First).Next = L.Last then
1464 if N (L.Last).Prev = L.First then
1468 if Position.Node = L.First then
1472 if Position.Node = L.Last then
1476 if N (Position.Node).Next = 0 then
1480 if N (Position.Node).Prev = 0 then
1484 if N (N (Position.Node).Next).Prev /= Position.Node then
1488 if N (N (Position.Node).Prev).Next /= Position.Node then
1492 if L.Length = 3 then
1493 if N (L.First).Next /= Position.Node then
1497 if N (L.Last).Prev /= Position.Node then
1506 end Ada.Containers.Restricted_Doubly_Linked_Lists;