]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ada/libgnat/a-cborse.adb
[Ada] Add Ada 2022 features to sets containers
[thirdparty/gcc.git] / gcc / ada / libgnat / a-cborse.adb
CommitLineData
ff2efe85
AC
1------------------------------------------------------------------------------
2-- --
3-- GNAT LIBRARY COMPONENTS --
4-- --
5-- A D A . C O N T A I N E R S . B O U N D E D _ O R D E R E D _ S E T S --
6-- --
7-- B o d y --
8-- --
bc0b26b9 9-- Copyright (C) 2004-2022, Free Software Foundation, Inc. --
ff2efe85
AC
10-- --
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. --
17-- --
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. --
21-- --
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/>. --
26-- --
27-- This unit was originally developed by Matthew J Heaney. --
28------------------------------------------------------------------------------
29
14f73211
BD
30with Ada.Containers.Helpers; use Ada.Containers.Helpers;
31
ff2efe85
AC
32with Ada.Containers.Red_Black_Trees.Generic_Bounded_Operations;
33pragma Elaborate_All
34 (Ada.Containers.Red_Black_Trees.Generic_Bounded_Operations);
35
36with Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys;
37pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys);
38
39with Ada.Containers.Red_Black_Trees.Generic_Bounded_Set_Operations;
40pragma Elaborate_All
41 (Ada.Containers.Red_Black_Trees.Generic_Bounded_Set_Operations);
42
43with System; use type System.Address;
26349b6d 44with System.Put_Images;
ff2efe85 45
3221be14
YM
46package body Ada.Containers.Bounded_Ordered_Sets with
47 SPARK_Mode => Off
48is
ff2efe85 49
14f73211
BD
50 pragma Warnings (Off, "variable ""Busy*"" is not referenced");
51 pragma Warnings (Off, "variable ""Lock*"" is not referenced");
52 -- See comment in Ada.Containers.Helpers
53
ff2efe85
AC
54 ------------------------------
55 -- Access to Fields of Node --
56 ------------------------------
57
58 -- These subprograms provide functional notation for access to fields
59 -- of a node, and procedural notation for modifying these fields.
60
61 function Color (Node : Node_Type) return Red_Black_Trees.Color_Type;
62 pragma Inline (Color);
63
64 function Left (Node : Node_Type) return Count_Type;
65 pragma Inline (Left);
66
67 function Parent (Node : Node_Type) return Count_Type;
68 pragma Inline (Parent);
69
70 function Right (Node : Node_Type) return Count_Type;
71 pragma Inline (Right);
72
73 procedure Set_Color
74 (Node : in out Node_Type;
75 Color : Red_Black_Trees.Color_Type);
76 pragma Inline (Set_Color);
77
78 procedure Set_Left (Node : in out Node_Type; Left : Count_Type);
79 pragma Inline (Set_Left);
80
81 procedure Set_Right (Node : in out Node_Type; Right : Count_Type);
82 pragma Inline (Set_Right);
83
84 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type);
85 pragma Inline (Set_Parent);
86
87 -----------------------
88 -- Local Subprograms --
89 -----------------------
90
91 procedure Insert_Sans_Hint
92 (Container : in out Set;
93 New_Item : Element_Type;
94 Node : out Count_Type;
95 Inserted : out Boolean);
96
97 procedure Insert_With_Hint
98 (Dst_Set : in out Set;
99 Dst_Hint : Count_Type;
100 Src_Node : Node_Type;
101 Dst_Node : out Count_Type);
102
103 function Is_Greater_Element_Node
104 (Left : Element_Type;
105 Right : Node_Type) return Boolean;
106 pragma Inline (Is_Greater_Element_Node);
107
108 function Is_Less_Element_Node
109 (Left : Element_Type;
110 Right : Node_Type) return Boolean;
111 pragma Inline (Is_Less_Element_Node);
112
113 function Is_Less_Node_Node (L, R : Node_Type) return Boolean;
114 pragma Inline (Is_Less_Node_Node);
115
116 procedure Replace_Element
117 (Container : in out Set;
118 Index : Count_Type;
119 Item : Element_Type);
120
121 --------------------------
122 -- Local Instantiations --
123 --------------------------
124
125 package Tree_Operations is
126 new Red_Black_Trees.Generic_Bounded_Operations (Tree_Types);
127
128 use Tree_Operations;
129
130 package Element_Keys is
131 new Red_Black_Trees.Generic_Bounded_Keys
132 (Tree_Operations => Tree_Operations,
133 Key_Type => Element_Type,
134 Is_Less_Key_Node => Is_Less_Element_Node,
135 Is_Greater_Key_Node => Is_Greater_Element_Node);
136
137 package Set_Ops is
138 new Red_Black_Trees.Generic_Bounded_Set_Operations
139 (Tree_Operations => Tree_Operations,
140 Set_Type => Set,
141 Assign => Assign,
142 Insert_With_Hint => Insert_With_Hint,
143 Is_Less => Is_Less_Node_Node);
144
145 ---------
146 -- "<" --
147 ---------
148
149 function "<" (Left, Right : Cursor) return Boolean is
150 begin
14f73211 151 if Checks and then Left.Node = 0 then
ff2efe85
AC
152 raise Constraint_Error with "Left cursor equals No_Element";
153 end if;
154
14f73211 155 if Checks and then Right.Node = 0 then
ff2efe85
AC
156 raise Constraint_Error with "Right cursor equals No_Element";
157 end if;
158
159 pragma Assert (Vet (Left.Container.all, Left.Node),
160 "bad Left cursor in ""<""");
161
162 pragma Assert (Vet (Right.Container.all, Right.Node),
163 "bad Right cursor in ""<""");
164
165 declare
166 LN : Nodes_Type renames Left.Container.Nodes;
167 RN : Nodes_Type renames Right.Container.Nodes;
168 begin
169 return LN (Left.Node).Element < RN (Right.Node).Element;
170 end;
171 end "<";
172
173 function "<" (Left : Cursor; Right : Element_Type) return Boolean is
174 begin
14f73211 175 if Checks and then Left.Node = 0 then
ff2efe85
AC
176 raise Constraint_Error with "Left cursor equals No_Element";
177 end if;
178
179 pragma Assert (Vet (Left.Container.all, Left.Node),
180 "bad Left cursor in ""<""");
181
182 return Left.Container.Nodes (Left.Node).Element < Right;
183 end "<";
184
185 function "<" (Left : Element_Type; Right : Cursor) return Boolean is
186 begin
14f73211 187 if Checks and then Right.Node = 0 then
ff2efe85
AC
188 raise Constraint_Error with "Right cursor equals No_Element";
189 end if;
190
191 pragma Assert (Vet (Right.Container.all, Right.Node),
192 "bad Right cursor in ""<""");
193
194 return Left < Right.Container.Nodes (Right.Node).Element;
195 end "<";
196
197 ---------
198 -- "=" --
199 ---------
200
201 function "=" (Left, Right : Set) return Boolean is
202 function Is_Equal_Node_Node (L, R : Node_Type) return Boolean;
203 pragma Inline (Is_Equal_Node_Node);
204
205 function Is_Equal is
206 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
207
208 ------------------------
209 -- Is_Equal_Node_Node --
210 ------------------------
211
212 function Is_Equal_Node_Node (L, R : Node_Type) return Boolean is
213 begin
214 return L.Element = R.Element;
215 end Is_Equal_Node_Node;
216
217 -- Start of processing for Is_Equal
218
219 begin
220 return Is_Equal (Left, Right);
221 end "=";
222
223 ---------
224 -- ">" --
225 ---------
226
227 function ">" (Left, Right : Cursor) return Boolean is
228 begin
14f73211 229 if Checks and then Left.Node = 0 then
ff2efe85
AC
230 raise Constraint_Error with "Left cursor equals No_Element";
231 end if;
232
14f73211 233 if Checks and then Right.Node = 0 then
ff2efe85
AC
234 raise Constraint_Error with "Right cursor equals No_Element";
235 end if;
236
237 pragma Assert (Vet (Left.Container.all, Left.Node),
238 "bad Left cursor in "">""");
239
240 pragma Assert (Vet (Right.Container.all, Right.Node),
241 "bad Right cursor in "">""");
242
243 -- L > R same as R < L
244
245 declare
246 LN : Nodes_Type renames Left.Container.Nodes;
247 RN : Nodes_Type renames Right.Container.Nodes;
248 begin
249 return RN (Right.Node).Element < LN (Left.Node).Element;
250 end;
251 end ">";
252
253 function ">" (Left : Element_Type; Right : Cursor) return Boolean is
254 begin
14f73211 255 if Checks and then Right.Node = 0 then
ff2efe85
AC
256 raise Constraint_Error with "Right cursor equals No_Element";
257 end if;
258
259 pragma Assert (Vet (Right.Container.all, Right.Node),
260 "bad Right cursor in "">""");
261
262 return Right.Container.Nodes (Right.Node).Element < Left;
263 end ">";
264
265 function ">" (Left : Cursor; Right : Element_Type) return Boolean is
266 begin
14f73211 267 if Checks and then Left.Node = 0 then
ff2efe85
AC
268 raise Constraint_Error with "Left cursor equals No_Element";
269 end if;
270
271 pragma Assert (Vet (Left.Container.all, Left.Node),
272 "bad Left cursor in "">""");
273
274 return Right < Left.Container.Nodes (Left.Node).Element;
275 end ">";
276
277 ------------
278 -- Assign --
279 ------------
280
281 procedure Assign (Target : in out Set; Source : Set) is
282 procedure Append_Element (Source_Node : Count_Type);
283
284 procedure Append_Elements is
285 new Tree_Operations.Generic_Iteration (Append_Element);
286
287 --------------------
288 -- Append_Element --
289 --------------------
290
291 procedure Append_Element (Source_Node : Count_Type) is
292 SN : Node_Type renames Source.Nodes (Source_Node);
293
294 procedure Set_Element (Node : in out Node_Type);
295 pragma Inline (Set_Element);
296
297 function New_Node return Count_Type;
298 pragma Inline (New_Node);
299
300 procedure Insert_Post is
301 new Element_Keys.Generic_Insert_Post (New_Node);
302
303 procedure Unconditional_Insert_Sans_Hint is
304 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
305
306 procedure Unconditional_Insert_Avec_Hint is
307 new Element_Keys.Generic_Unconditional_Insert_With_Hint
308 (Insert_Post,
309 Unconditional_Insert_Sans_Hint);
310
311 procedure Allocate is
312 new Tree_Operations.Generic_Allocate (Set_Element);
313
314 --------------
315 -- New_Node --
316 --------------
317
318 function New_Node return Count_Type is
319 Result : Count_Type;
ff2efe85
AC
320 begin
321 Allocate (Target, Result);
322 return Result;
323 end New_Node;
324
325 -----------------
326 -- Set_Element --
327 -----------------
328
329 procedure Set_Element (Node : in out Node_Type) is
330 begin
331 Node.Element := SN.Element;
332 end Set_Element;
333
334 Target_Node : Count_Type;
335
336 -- Start of processing for Append_Element
337
338 begin
339 Unconditional_Insert_Avec_Hint
340 (Tree => Target,
341 Hint => 0,
342 Key => SN.Element,
343 Node => Target_Node);
344 end Append_Element;
345
346 -- Start of processing for Assign
347
348 begin
349 if Target'Address = Source'Address then
350 return;
351 end if;
352
14f73211 353 if Checks and then Target.Capacity < Source.Length then
ff2efe85
AC
354 raise Capacity_Error
355 with "Target capacity is less than Source length";
356 end if;
357
358 Target.Clear;
359 Append_Elements (Source);
360 end Assign;
361
362 -------------
363 -- Ceiling --
364 -------------
365
366 function Ceiling (Container : Set; Item : Element_Type) return Cursor is
367 Node : constant Count_Type :=
15f0f591 368 Element_Keys.Ceiling (Container, Item);
ff2efe85 369 begin
ce72a9a3
AC
370 return (if Node = 0 then No_Element
371 else Cursor'(Container'Unrestricted_Access, Node));
ff2efe85
AC
372 end Ceiling;
373
374 -----------
375 -- Clear --
376 -----------
377
378 procedure Clear (Container : in out Set) is
379 begin
cbdb0df1
BD
380 while not Container.Is_Empty loop
381 Container.Delete_Last;
382 end loop;
ff2efe85
AC
383 end Clear;
384
385 -----------
386 -- Color --
387 -----------
388
389 function Color (Node : Node_Type) return Red_Black_Trees.Color_Type is
390 begin
391 return Node.Color;
392 end Color;
393
c9423ca3
AC
394 ------------------------
395 -- Constant_Reference --
396 ------------------------
397
398 function Constant_Reference
399 (Container : aliased Set;
400 Position : Cursor) return Constant_Reference_Type
401 is
402 begin
14f73211 403 if Checks and then Position.Container = null then
c9423ca3
AC
404 raise Constraint_Error with "Position cursor has no element";
405 end if;
406
14f73211
BD
407 if Checks and then Position.Container /= Container'Unrestricted_Access
408 then
c9423ca3
AC
409 raise Program_Error with
410 "Position cursor designates wrong container";
411 end if;
412
413 pragma Assert
414 (Vet (Container, Position.Node),
415 "bad cursor in Constant_Reference");
416
417 declare
418 N : Node_Type renames Container.Nodes (Position.Node);
14f73211
BD
419 TC : constant Tamper_Counts_Access :=
420 Container.TC'Unrestricted_Access;
c9423ca3 421 begin
3bd783ec 422 return R : constant Constant_Reference_Type :=
c5b1e8e9 423 (Element => N.Element'Unchecked_Access,
14f73211 424 Control => (Controlled with TC))
3bd783ec 425 do
2f26abcc 426 Busy (TC.all);
3bd783ec 427 end return;
c9423ca3
AC
428 end;
429 end Constant_Reference;
430
ff2efe85
AC
431 --------------
432 -- Contains --
433 --------------
434
435 function Contains
436 (Container : Set;
437 Item : Element_Type) return Boolean
438 is
439 begin
440 return Find (Container, Item) /= No_Element;
441 end Contains;
442
443 ----------
444 -- Copy --
445 ----------
446
447 function Copy (Source : Set; Capacity : Count_Type := 0) return Set is
5ce1c773
BD
448 C : constant Count_Type :=
449 (if Capacity = 0 then Source.Length
450 else Capacity);
ff2efe85 451 begin
5ce1c773
BD
452 if Checks and then C < Source.Length then
453 raise Capacity_Error with "Capacity too small";
ff2efe85
AC
454 end if;
455
456 return Target : Set (Capacity => C) do
457 Assign (Target => Target, Source => Source);
458 end return;
459 end Copy;
460
461 ------------
462 -- Delete --
463 ------------
464
465 procedure Delete (Container : in out Set; Position : in out Cursor) is
466 begin
c602003b
BD
467 TC_Check (Container.TC);
468
14f73211 469 if Checks and then Position.Node = 0 then
ff2efe85
AC
470 raise Constraint_Error with "Position cursor equals No_Element";
471 end if;
472
14f73211
BD
473 if Checks and then Position.Container /= Container'Unrestricted_Access
474 then
ff2efe85
AC
475 raise Program_Error with "Position cursor designates wrong set";
476 end if;
477
478 pragma Assert (Vet (Container, Position.Node),
479 "bad cursor in Delete");
480
481 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
482 Tree_Operations.Free (Container, Position.Node);
483
484 Position := No_Element;
485 end Delete;
486
487 procedure Delete (Container : in out Set; Item : Element_Type) is
488 X : constant Count_Type := Element_Keys.Find (Container, Item);
489
490 begin
1ebc2612
AC
491 Tree_Operations.Delete_Node_Sans_Free (Container, X);
492
14f73211 493 if Checks and then X = 0 then
1ebc2612 494 raise Constraint_Error with "attempt to delete element not in set";
ff2efe85
AC
495 end if;
496
ff2efe85
AC
497 Tree_Operations.Free (Container, X);
498 end Delete;
499
500 ------------------
501 -- Delete_First --
502 ------------------
503
504 procedure Delete_First (Container : in out Set) is
505 X : constant Count_Type := Container.First;
ff2efe85
AC
506 begin
507 if X /= 0 then
508 Tree_Operations.Delete_Node_Sans_Free (Container, X);
509 Tree_Operations.Free (Container, X);
510 end if;
511 end Delete_First;
512
513 -----------------
514 -- Delete_Last --
515 -----------------
516
517 procedure Delete_Last (Container : in out Set) is
518 X : constant Count_Type := Container.Last;
ff2efe85
AC
519 begin
520 if X /= 0 then
521 Tree_Operations.Delete_Node_Sans_Free (Container, X);
522 Tree_Operations.Free (Container, X);
523 end if;
524 end Delete_Last;
525
526 ----------------
527 -- Difference --
528 ----------------
529
530 procedure Difference (Target : in out Set; Source : Set)
531 renames Set_Ops.Set_Difference;
532
533 function Difference (Left, Right : Set) return Set
534 renames Set_Ops.Set_Difference;
535
536 -------------
537 -- Element --
538 -------------
539
540 function Element (Position : Cursor) return Element_Type is
541 begin
14f73211 542 if Checks and then Position.Node = 0 then
ff2efe85
AC
543 raise Constraint_Error with "Position cursor equals No_Element";
544 end if;
545
546 pragma Assert (Vet (Position.Container.all, Position.Node),
547 "bad cursor in Element");
548
549 return Position.Container.Nodes (Position.Node).Element;
550 end Element;
551
3bb4836f
ES
552 -----------
553 -- Empty --
554 -----------
555
556 function Empty (Capacity : Count_Type := 10) return Set is
557 begin
558 return Result : Set (Capacity) do
559 null;
560 end return;
561 end Empty;
562
ff2efe85
AC
563 -------------------------
564 -- Equivalent_Elements --
565 -------------------------
566
567 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
568 begin
ce72a9a3 569 return (if Left < Right or else Right < Left then False else True);
ff2efe85
AC
570 end Equivalent_Elements;
571
572 ---------------------
573 -- Equivalent_Sets --
574 ---------------------
575
576 function Equivalent_Sets (Left, Right : Set) return Boolean is
577 function Is_Equivalent_Node_Node (L, R : Node_Type) return Boolean;
578 pragma Inline (Is_Equivalent_Node_Node);
579
580 function Is_Equivalent is
581 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
582
583 -----------------------------
584 -- Is_Equivalent_Node_Node --
585 -----------------------------
586
587 function Is_Equivalent_Node_Node (L, R : Node_Type) return Boolean is
588 begin
ce72a9a3
AC
589 return (if L.Element < R.Element then False
590 elsif R.Element < L.Element then False
591 else True);
ff2efe85
AC
592 end Is_Equivalent_Node_Node;
593
594 -- Start of processing for Equivalent_Sets
595
596 begin
597 return Is_Equivalent (Left, Right);
598 end Equivalent_Sets;
599
600 -------------
601 -- Exclude --
602 -------------
603
604 procedure Exclude (Container : in out Set; Item : Element_Type) is
605 X : constant Count_Type := Element_Keys.Find (Container, Item);
ff2efe85
AC
606 begin
607 if X /= 0 then
608 Tree_Operations.Delete_Node_Sans_Free (Container, X);
609 Tree_Operations.Free (Container, X);
610 end if;
611 end Exclude;
612
ef992452
AC
613 --------------
614 -- Finalize --
615 --------------
616
617 procedure Finalize (Object : in out Iterator) is
618 begin
619 if Object.Container /= null then
14f73211 620 Unbusy (Object.Container.TC);
3bd783ec
AC
621 end if;
622 end Finalize;
623
ff2efe85
AC
624 ----------
625 -- Find --
626 ----------
627
628 function Find (Container : Set; Item : Element_Type) return Cursor is
629 Node : constant Count_Type := Element_Keys.Find (Container, Item);
ff2efe85 630 begin
ce72a9a3
AC
631 return (if Node = 0 then No_Element
632 else Cursor'(Container'Unrestricted_Access, Node));
ff2efe85
AC
633 end Find;
634
635 -----------
636 -- First --
637 -----------
638
639 function First (Container : Set) return Cursor is
640 begin
ce72a9a3
AC
641 return (if Container.First = 0 then No_Element
642 else Cursor'(Container'Unrestricted_Access, Container.First));
ff2efe85
AC
643 end First;
644
ffb35bbf
ES
645 function First (Object : Iterator) return Cursor is
646 begin
b38c20a6
AC
647 -- The value of the iterator object's Node component influences the
648 -- behavior of the First (and Last) selector function.
649
650 -- When the Node component is 0, this means the iterator object was
651 -- constructed without a start expression, in which case the (forward)
652 -- iteration starts from the (logical) beginning of the entire sequence
653 -- of items (corresponding to Container.First, for a forward iterator).
654
655 -- Otherwise, this is iteration over a partial sequence of items. When
656 -- the Node component is positive, the iterator object was constructed
657 -- with a start expression, that specifies the position from which the
658 -- (forward) partial iteration begins.
659
660 if Object.Node = 0 then
661 return Bounded_Ordered_Sets.First (Object.Container.all);
662 else
663 return Cursor'(Object.Container, Object.Node);
664 end if;
ffb35bbf
ES
665 end First;
666
ff2efe85
AC
667 -------------------
668 -- First_Element --
669 -------------------
670
671 function First_Element (Container : Set) return Element_Type is
672 begin
14f73211 673 if Checks and then Container.First = 0 then
ff2efe85
AC
674 raise Constraint_Error with "set is empty";
675 end if;
676
677 return Container.Nodes (Container.First).Element;
678 end First_Element;
679
680 -----------
681 -- Floor --
682 -----------
683
684 function Floor (Container : Set; Item : Element_Type) return Cursor is
685 Node : constant Count_Type := Element_Keys.Floor (Container, Item);
ff2efe85 686 begin
ce72a9a3
AC
687 return (if Node = 0 then No_Element
688 else Cursor'(Container'Unrestricted_Access, Node));
ff2efe85
AC
689 end Floor;
690
a8a1da10
BD
691 -- Ada 2022 features:
692
693 function Has_Element (Container : Set; Position : Cursor) return Boolean is
694 begin
695 pragma Assert
696 (Position.Container = null or else Vet (Container, Position.Node),
697 "bad cursor in Has_Element");
698 pragma Assert ((Position.Container = null) = (Position.Node = 0),
699 "bad nullity in Has_Element");
700 return Position.Container = Container'Unrestricted_Access;
701 end Has_Element;
702
703 function Tampering_With_Cursors_Prohibited
704 (Container : Set) return Boolean
705 is
706 begin
707 return Is_Busy (Container.TC);
708 end Tampering_With_Cursors_Prohibited;
709
710 function Element (Container : Set; Position : Cursor) return Element_Type is
711 begin
712 if Checks and then not Has_Element (Container, Position) then
713 raise Program_Error with "Position for wrong Container";
714 end if;
715
716 return Element (Position);
717 end Element;
718
719 procedure Query_Element
720 (Container : Set;
721 Position : Cursor;
722 Process : not null access procedure (Element : Element_Type)) is
723 begin
724 if Checks and then not Has_Element (Container, Position) then
725 raise Program_Error with "Position for wrong Container";
726 end if;
727
728 Query_Element (Position, Process);
729 end Query_Element;
730
731 function Next (Container : Set; Position : Cursor) return Cursor is
732 begin
733 if Checks and then
734 not (Position = No_Element or else Has_Element (Container, Position))
735 then
736 raise Program_Error with "Position for wrong Container";
737 end if;
738
739 return Next (Position);
740 end Next;
741
742 procedure Next (Container : Set; Position : in out Cursor) is
743 begin
744 Position := Next (Container, Position);
745 end Next;
746
ff2efe85
AC
747 ------------------
748 -- Generic_Keys --
749 ------------------
750
751 package body Generic_Keys is
752
753 -----------------------
754 -- Local Subprograms --
755 -----------------------
756
757 function Is_Greater_Key_Node
758 (Left : Key_Type;
759 Right : Node_Type) return Boolean;
760 pragma Inline (Is_Greater_Key_Node);
761
762 function Is_Less_Key_Node
763 (Left : Key_Type;
764 Right : Node_Type) return Boolean;
765 pragma Inline (Is_Less_Key_Node);
766
767 --------------------------
768 -- Local Instantiations --
769 --------------------------
770
771 package Key_Keys is
772 new Red_Black_Trees.Generic_Bounded_Keys
773 (Tree_Operations => Tree_Operations,
774 Key_Type => Key_Type,
775 Is_Less_Key_Node => Is_Less_Key_Node,
776 Is_Greater_Key_Node => Is_Greater_Key_Node);
777
778 -------------
779 -- Ceiling --
780 -------------
781
782 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
783 Node : constant Count_Type :=
15f0f591 784 Key_Keys.Ceiling (Container, Key);
ff2efe85 785 begin
ce72a9a3
AC
786 return (if Node = 0 then No_Element
787 else Cursor'(Container'Unrestricted_Access, Node));
ff2efe85
AC
788 end Ceiling;
789
c9423ca3
AC
790 ------------------------
791 -- Constant_Reference --
792 ------------------------
793
794 function Constant_Reference
795 (Container : aliased Set;
796 Key : Key_Type) return Constant_Reference_Type
797 is
ab599684 798 Position : constant Cursor := Find (Container, Key);
c9423ca3
AC
799
800 begin
ab599684 801 if Checks and then Position = No_Element then
c9423ca3
AC
802 raise Constraint_Error with "key not in set";
803 end if;
804
ab599684 805 return Constant_Reference (Container, Position);
c9423ca3
AC
806 end Constant_Reference;
807
ff2efe85
AC
808 --------------
809 -- Contains --
810 --------------
811
812 function Contains (Container : Set; Key : Key_Type) return Boolean is
813 begin
814 return Find (Container, Key) /= No_Element;
815 end Contains;
816
817 ------------
818 -- Delete --
819 ------------
820
821 procedure Delete (Container : in out Set; Key : Key_Type) is
822 X : constant Count_Type := Key_Keys.Find (Container, Key);
823
824 begin
14f73211 825 if Checks and then X = 0 then
ff2efe85
AC
826 raise Constraint_Error with "attempt to delete key not in set";
827 end if;
828
829 Tree_Operations.Delete_Node_Sans_Free (Container, X);
830 Tree_Operations.Free (Container, X);
831 end Delete;
832
833 -------------
834 -- Element --
835 -------------
836
837 function Element (Container : Set; Key : Key_Type) return Element_Type is
838 Node : constant Count_Type := Key_Keys.Find (Container, Key);
839
840 begin
14f73211 841 if Checks and then Node = 0 then
ff2efe85
AC
842 raise Constraint_Error with "key not in set";
843 end if;
844
845 return Container.Nodes (Node).Element;
846 end Element;
847
848 ---------------------
849 -- Equivalent_Keys --
850 ---------------------
851
852 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
853 begin
ce72a9a3 854 return (if Left < Right or else Right < Left then False else True);
ff2efe85
AC
855 end Equivalent_Keys;
856
857 -------------
858 -- Exclude --
859 -------------
860
861 procedure Exclude (Container : in out Set; Key : Key_Type) is
862 X : constant Count_Type := Key_Keys.Find (Container, Key);
ff2efe85
AC
863 begin
864 if X /= 0 then
865 Tree_Operations.Delete_Node_Sans_Free (Container, X);
866 Tree_Operations.Free (Container, X);
867 end if;
868 end Exclude;
869
6b6bce61
AC
870 --------------
871 -- Finalize --
872 --------------
873
874 procedure Finalize (Control : in out Reference_Control_Type) is
875 begin
876 if Control.Container /= null then
14f73211
BD
877 Impl.Reference_Control_Type (Control).Finalize;
878
879 if Checks and then not (Key (Control.Pos) = Control.Old_Key.all)
880 then
6b6bce61
AC
881 Delete (Control.Container.all, Key (Control.Pos));
882 raise Program_Error;
883 end if;
884
885 Control.Container := null;
886 end if;
887 end Finalize;
888
ff2efe85
AC
889 ----------
890 -- Find --
891 ----------
892
893 function Find (Container : Set; Key : Key_Type) return Cursor is
894 Node : constant Count_Type := Key_Keys.Find (Container, Key);
ff2efe85 895 begin
ce72a9a3
AC
896 return (if Node = 0 then No_Element
897 else Cursor'(Container'Unrestricted_Access, Node));
ff2efe85
AC
898 end Find;
899
900 -----------
901 -- Floor --
902 -----------
903
904 function Floor (Container : Set; Key : Key_Type) return Cursor is
905 Node : constant Count_Type := Key_Keys.Floor (Container, Key);
ff2efe85 906 begin
ce72a9a3
AC
907 return (if Node = 0 then No_Element
908 else Cursor'(Container'Unrestricted_Access, Node));
ff2efe85
AC
909 end Floor;
910
911 -------------------------
912 -- Is_Greater_Key_Node --
913 -------------------------
914
915 function Is_Greater_Key_Node
916 (Left : Key_Type;
917 Right : Node_Type) return Boolean
918 is
919 begin
920 return Key (Right.Element) < Left;
921 end Is_Greater_Key_Node;
922
923 ----------------------
924 -- Is_Less_Key_Node --
925 ----------------------
926
927 function Is_Less_Key_Node
928 (Left : Key_Type;
929 Right : Node_Type) return Boolean
930 is
931 begin
932 return Left < Key (Right.Element);
933 end Is_Less_Key_Node;
934
935 ---------
936 -- Key --
937 ---------
938
939 function Key (Position : Cursor) return Key_Type is
940 begin
14f73211 941 if Checks and then Position.Node = 0 then
ff2efe85
AC
942 raise Constraint_Error with
943 "Position cursor equals No_Element";
944 end if;
945
946 pragma Assert (Vet (Position.Container.all, Position.Node),
947 "bad cursor in Key");
948
949 return Key (Position.Container.Nodes (Position.Node).Element);
950 end Key;
951
c9423ca3
AC
952 ----------
953 -- Read --
954 ----------
955
adfa6cb8 956 procedure Read
c9423ca3
AC
957 (Stream : not null access Root_Stream_Type'Class;
958 Item : out Reference_Type)
959 is
960 begin
961 raise Program_Error with "attempt to stream reference";
962 end Read;
963
964 ------------------------------
965 -- Reference_Preserving_Key --
966 ------------------------------
967
968 function Reference_Preserving_Key
969 (Container : aliased in out Set;
970 Position : Cursor) return Reference_Type
971 is
972 begin
14f73211 973 if Checks and then Position.Container = null then
c9423ca3
AC
974 raise Constraint_Error with "Position cursor has no element";
975 end if;
976
14f73211
BD
977 if Checks and then Position.Container /= Container'Unrestricted_Access
978 then
c9423ca3
AC
979 raise Program_Error with
980 "Position cursor designates wrong container";
981 end if;
982
983 pragma Assert
984 (Vet (Container, Position.Node),
985 "bad cursor in function Reference_Preserving_Key");
986
c9423ca3
AC
987 declare
988 N : Node_Type renames Container.Nodes (Position.Node);
989 begin
6b6bce61 990 return R : constant Reference_Type :=
c5b1e8e9 991 (Element => N.Element'Unchecked_Access,
d6e8719d
RD
992 Control =>
993 (Controlled with
14f73211 994 Container.TC'Unrestricted_Access,
da566eeb 995 Container => Container'Unchecked_Access,
d6e8719d
RD
996 Pos => Position,
997 Old_Key => new Key_Type'(Key (Position))))
6b6bce61 998 do
2f26abcc 999 Busy (Container.TC);
6b6bce61 1000 end return;
c9423ca3
AC
1001 end;
1002 end Reference_Preserving_Key;
1003
1004 function Reference_Preserving_Key
1005 (Container : aliased in out Set;
1006 Key : Key_Type) return Reference_Type
1007 is
ab599684 1008 Position : constant Cursor := Find (Container, Key);
c9423ca3
AC
1009
1010 begin
ab599684 1011 if Checks and then Position = No_Element then
c9423ca3
AC
1012 raise Constraint_Error with "key not in set";
1013 end if;
1014
ab599684 1015 return Reference_Preserving_Key (Container, Position);
c9423ca3
AC
1016 end Reference_Preserving_Key;
1017
ff2efe85
AC
1018 -------------
1019 -- Replace --
1020 -------------
1021
1022 procedure Replace
1023 (Container : in out Set;
1024 Key : Key_Type;
1025 New_Item : Element_Type)
1026 is
1027 Node : constant Count_Type := Key_Keys.Find (Container, Key);
1028
1029 begin
14f73211 1030 if Checks and then Node = 0 then
ff2efe85
AC
1031 raise Constraint_Error with
1032 "attempt to replace key not in set";
1033 end if;
1034
1035 Replace_Element (Container, Node, New_Item);
1036 end Replace;
1037
1038 -----------------------------------
1039 -- Update_Element_Preserving_Key --
1040 -----------------------------------
1041
1042 procedure Update_Element_Preserving_Key
1043 (Container : in out Set;
1044 Position : Cursor;
1045 Process : not null access procedure (Element : in out Element_Type))
1046 is
1047 begin
14f73211 1048 if Checks and then Position.Node = 0 then
ff2efe85
AC
1049 raise Constraint_Error with
1050 "Position cursor equals No_Element";
1051 end if;
1052
14f73211
BD
1053 if Checks and then Position.Container /= Container'Unrestricted_Access
1054 then
ff2efe85
AC
1055 raise Program_Error with
1056 "Position cursor designates wrong set";
1057 end if;
1058
1059 pragma Assert (Vet (Container, Position.Node),
1060 "bad cursor in Update_Element_Preserving_Key");
1061
e7f11067
AC
1062 -- Per AI05-0022, the container implementation is required to detect
1063 -- element tampering by a generic actual subprogram.
1064
ff2efe85
AC
1065 declare
1066 N : Node_Type renames Container.Nodes (Position.Node);
1067 E : Element_Type renames N.Element;
1068 K : constant Key_Type := Key (E);
14f73211 1069 Lock : With_Lock (Container.TC'Unrestricted_Access);
ff2efe85 1070 begin
14f73211
BD
1071 Process (E);
1072 if Equivalent_Keys (K, Key (E)) then
ff2efe85
AC
1073 return;
1074 end if;
1075 end;
1076
1077 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
1078 Tree_Operations.Free (Container, Position.Node);
1079
1080 raise Program_Error with "key was modified";
1081 end Update_Element_Preserving_Key;
1082
c9423ca3
AC
1083 -----------
1084 -- Write --
1085 -----------
ffb35bbf
ES
1086
1087 procedure Write
1088 (Stream : not null access Root_Stream_Type'Class;
1089 Item : Reference_Type)
1090 is
1091 begin
1092 raise Program_Error with "attempt to stream reference";
1093 end Write;
ff2efe85
AC
1094 end Generic_Keys;
1095
14f73211
BD
1096 ------------------------
1097 -- Get_Element_Access --
1098 ------------------------
1099
1100 function Get_Element_Access
1101 (Position : Cursor) return not null Element_Access is
1102 begin
1103 return Position.Container.Nodes (Position.Node).Element'Access;
1104 end Get_Element_Access;
1105
ff2efe85
AC
1106 -----------------
1107 -- Has_Element --
1108 -----------------
1109
1110 function Has_Element (Position : Cursor) return Boolean is
1111 begin
1112 return Position /= No_Element;
1113 end Has_Element;
1114
1115 -------------
1116 -- Include --
1117 -------------
1118
1119 procedure Include (Container : in out Set; New_Item : Element_Type) is
1120 Position : Cursor;
1121 Inserted : Boolean;
1122
1123 begin
1124 Insert (Container, New_Item, Position, Inserted);
1125
1126 if not Inserted then
14f73211 1127 TE_Check (Container.TC);
ff2efe85
AC
1128
1129 Container.Nodes (Position.Node).Element := New_Item;
1130 end if;
1131 end Include;
1132
1133 ------------
1134 -- Insert --
1135 ------------
1136
1137 procedure Insert
1138 (Container : in out Set;
1139 New_Item : Element_Type;
1140 Position : out Cursor;
1141 Inserted : out Boolean)
1142 is
1143 begin
1144 Insert_Sans_Hint
1145 (Container,
1146 New_Item,
1147 Position.Node,
1148 Inserted);
1149
1150 Position.Container := Container'Unrestricted_Access;
1151 end Insert;
1152
1153 procedure Insert
1154 (Container : in out Set;
1155 New_Item : Element_Type)
1156 is
1157 Position : Cursor;
ff2efe85
AC
1158 Inserted : Boolean;
1159
1160 begin
1161 Insert (Container, New_Item, Position, Inserted);
1162
14f73211 1163 if Checks and then not Inserted then
ff2efe85
AC
1164 raise Constraint_Error with
1165 "attempt to insert element already in set";
1166 end if;
1167 end Insert;
1168
1169 ----------------------
1170 -- Insert_Sans_Hint --
1171 ----------------------
1172
1173 procedure Insert_Sans_Hint
1174 (Container : in out Set;
1175 New_Item : Element_Type;
1176 Node : out Count_Type;
1177 Inserted : out Boolean)
1178 is
1179 procedure Set_Element (Node : in out Node_Type);
1180 pragma Inline (Set_Element);
1181
1182 function New_Node return Count_Type;
1183 pragma Inline (New_Node);
1184
1185 procedure Insert_Post is
1186 new Element_Keys.Generic_Insert_Post (New_Node);
1187
1188 procedure Conditional_Insert_Sans_Hint is
1189 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1190
1191 procedure Allocate is
1192 new Tree_Operations.Generic_Allocate (Set_Element);
1193
1194 --------------
1195 -- New_Node --
1196 --------------
1197
1198 function New_Node return Count_Type is
1199 Result : Count_Type;
ff2efe85
AC
1200 begin
1201 Allocate (Container, Result);
1202 return Result;
1203 end New_Node;
1204
1205 -----------------
1206 -- Set_Element --
1207 -----------------
1208
1209 procedure Set_Element (Node : in out Node_Type) is
1210 begin
1211 Node.Element := New_Item;
1212 end Set_Element;
1213
1214 -- Start of processing for Insert_Sans_Hint
1215
1216 begin
14f73211 1217 TC_Check (Container.TC);
6b6bce61 1218
ff2efe85
AC
1219 Conditional_Insert_Sans_Hint
1220 (Container,
1221 New_Item,
1222 Node,
1223 Inserted);
1224 end Insert_Sans_Hint;
1225
1226 ----------------------
1227 -- Insert_With_Hint --
1228 ----------------------
1229
1230 procedure Insert_With_Hint
1231 (Dst_Set : in out Set;
1232 Dst_Hint : Count_Type;
1233 Src_Node : Node_Type;
1234 Dst_Node : out Count_Type)
1235 is
1236 Success : Boolean;
ff2efe85
AC
1237
1238 procedure Set_Element (Node : in out Node_Type);
1239 pragma Inline (Set_Element);
1240
1241 function New_Node return Count_Type;
1242 pragma Inline (New_Node);
1243
1244 procedure Insert_Post is
1245 new Element_Keys.Generic_Insert_Post (New_Node);
1246
1247 procedure Insert_Sans_Hint is
1248 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1249
1250 procedure Local_Insert_With_Hint is
1251 new Element_Keys.Generic_Conditional_Insert_With_Hint
1252 (Insert_Post,
1253 Insert_Sans_Hint);
1254
1255 procedure Allocate is
1256 new Tree_Operations.Generic_Allocate (Set_Element);
1257
1258 --------------
1259 -- New_Node --
1260 --------------
1261
1262 function New_Node return Count_Type is
1263 Result : Count_Type;
ff2efe85
AC
1264 begin
1265 Allocate (Dst_Set, Result);
1266 return Result;
1267 end New_Node;
1268
1269 -----------------
1270 -- Set_Element --
1271 -----------------
1272
1273 procedure Set_Element (Node : in out Node_Type) is
1274 begin
1275 Node.Element := Src_Node.Element;
1276 end Set_Element;
1277
1278 -- Start of processing for Insert_With_Hint
1279
1280 begin
1281 Local_Insert_With_Hint
1282 (Dst_Set,
1283 Dst_Hint,
1284 Src_Node.Element,
1285 Dst_Node,
1286 Success);
1287 end Insert_With_Hint;
1288
1289 ------------------
1290 -- Intersection --
1291 ------------------
1292
1293 procedure Intersection (Target : in out Set; Source : Set)
1294 renames Set_Ops.Set_Intersection;
1295
1296 function Intersection (Left, Right : Set) return Set
1297 renames Set_Ops.Set_Intersection;
1298
1299 --------------
1300 -- Is_Empty --
1301 --------------
1302
1303 function Is_Empty (Container : Set) return Boolean is
1304 begin
1305 return Container.Length = 0;
1306 end Is_Empty;
1307
1308 -----------------------------
1309 -- Is_Greater_Element_Node --
1310 -----------------------------
1311
1312 function Is_Greater_Element_Node
1313 (Left : Element_Type;
1314 Right : Node_Type) return Boolean
1315 is
1316 begin
1317 -- Compute e > node same as node < e
1318
1319 return Right.Element < Left;
1320 end Is_Greater_Element_Node;
1321
1322 --------------------------
1323 -- Is_Less_Element_Node --
1324 --------------------------
1325
1326 function Is_Less_Element_Node
1327 (Left : Element_Type;
1328 Right : Node_Type) return Boolean
1329 is
1330 begin
1331 return Left < Right.Element;
1332 end Is_Less_Element_Node;
1333
1334 -----------------------
1335 -- Is_Less_Node_Node --
1336 -----------------------
1337
1338 function Is_Less_Node_Node (L, R : Node_Type) return Boolean is
1339 begin
1340 return L.Element < R.Element;
1341 end Is_Less_Node_Node;
1342
1343 ---------------
1344 -- Is_Subset --
1345 ---------------
1346
1347 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean
1348 renames Set_Ops.Set_Subset;
1349
1350 -------------
1351 -- Iterate --
1352 -------------
1353
1354 procedure Iterate
1355 (Container : Set;
1356 Process : not null access procedure (Position : Cursor))
1357 is
1358 procedure Process_Node (Node : Count_Type);
1359 pragma Inline (Process_Node);
1360
1361 procedure Local_Iterate is
1362 new Tree_Operations.Generic_Iteration (Process_Node);
1363
1364 ------------------
1365 -- Process_Node --
1366 ------------------
1367
1368 procedure Process_Node (Node : Count_Type) is
1369 begin
1370 Process (Cursor'(Container'Unrestricted_Access, Node));
1371 end Process_Node;
1372
1373 S : Set renames Container'Unrestricted_Access.all;
14f73211 1374 Busy : With_Busy (S.TC'Unrestricted_Access);
ff2efe85
AC
1375
1376 -- Start of processing for Iterate
1377
1378 begin
14f73211 1379 Local_Iterate (S);
ff2efe85
AC
1380 end Iterate;
1381
ffb35bbf 1382 function Iterate (Container : Set)
ef992452 1383 return Set_Iterator_Interfaces.Reversible_Iterator'class
ffb35bbf
ES
1384 is
1385 begin
b38c20a6
AC
1386 -- The value of the Node component influences the behavior of the First
1387 -- and Last selector functions of the iterator object. When the Node
1388 -- component is 0 (as is the case here), this means the iterator object
1389 -- was constructed without a start expression. This is a complete
1390 -- iterator, meaning that the iteration starts from the (logical)
1391 -- beginning of the sequence of items.
1392
1393 -- Note: For a forward iterator, Container.First is the beginning, and
1394 -- for a reverse iterator, Container.Last is the beginning.
1395
ef992452 1396 return It : constant Iterator :=
15f0f591
AC
1397 Iterator'(Limited_Controlled with
1398 Container => Container'Unrestricted_Access,
1399 Node => 0)
ef992452 1400 do
14f73211 1401 Busy (Container.TC'Unrestricted_Access.all);
ef992452 1402 end return;
ffb35bbf
ES
1403 end Iterate;
1404
1405 function Iterate (Container : Set; Start : Cursor)
ef992452 1406 return Set_Iterator_Interfaces.Reversible_Iterator'class
ffb35bbf 1407 is
ffb35bbf 1408 begin
b38c20a6
AC
1409 -- It was formerly the case that when Start = No_Element, the partial
1410 -- iterator was defined to behave the same as for a complete iterator,
1411 -- and iterate over the entire sequence of items. However, those
1412 -- semantics were unintuitive and arguably error-prone (it is too easy
1413 -- to accidentally create an endless loop), and so they were changed,
1414 -- per the ARG meeting in Denver on 2011/11. However, there was no
1415 -- consensus about what positive meaning this corner case should have,
1416 -- and so it was decided to simply raise an exception. This does imply,
1417 -- however, that it is not possible to use a partial iterator to specify
1418 -- an empty sequence of items.
1419
14f73211 1420 if Checks and then Start = No_Element then
b38c20a6
AC
1421 raise Constraint_Error with
1422 "Start position for iterator equals No_Element";
1423 end if;
1424
14f73211 1425 if Checks and then Start.Container /= Container'Unrestricted_Access then
b38c20a6
AC
1426 raise Program_Error with
1427 "Start cursor of Iterate designates wrong set";
1428 end if;
1429
1430 pragma Assert (Vet (Container, Start.Node),
1431 "Start cursor of Iterate is bad");
1432
1433 -- The value of the Node component influences the behavior of the First
1434 -- and Last selector functions of the iterator object. When the Node
1435 -- component is positive (as is the case here), it means that this
1436 -- is a partial iteration, over a subset of the complete sequence of
1437 -- items. The iterator object was constructed with a start expression,
1438 -- indicating the position from which the iteration begins. (Note that
1439 -- the start position has the same value irrespective of whether this
1440 -- is a forward or reverse iteration.)
1441
ef992452 1442 return It : constant Iterator :=
15f0f591
AC
1443 Iterator'(Limited_Controlled with
1444 Container => Container'Unrestricted_Access,
1445 Node => Start.Node)
ef992452 1446 do
14f73211 1447 Busy (Container.TC'Unrestricted_Access.all);
ef992452 1448 end return;
ffb35bbf
ES
1449 end Iterate;
1450
ff2efe85
AC
1451 ----------
1452 -- Last --
1453 ----------
1454
1455 function Last (Container : Set) return Cursor is
1456 begin
ce72a9a3
AC
1457 return (if Container.Last = 0 then No_Element
1458 else Cursor'(Container'Unrestricted_Access, Container.Last));
ff2efe85
AC
1459 end Last;
1460
ffb35bbf
ES
1461 function Last (Object : Iterator) return Cursor is
1462 begin
b38c20a6
AC
1463 -- The value of the iterator object's Node component influences the
1464 -- behavior of the Last (and First) selector function.
1465
1466 -- When the Node component is 0, this means the iterator object was
1467 -- constructed without a start expression, in which case the (reverse)
1468 -- iteration starts from the (logical) beginning of the entire sequence
1469 -- (corresponding to Container.Last, for a reverse iterator).
1470
1471 -- Otherwise, this is iteration over a partial sequence of items. When
1472 -- the Node component is positive, the iterator object was constructed
1473 -- with a start expression, that specifies the position from which the
1474 -- (reverse) partial iteration begins.
1475
1476 if Object.Node = 0 then
1477 return Bounded_Ordered_Sets.Last (Object.Container.all);
1478 else
1479 return Cursor'(Object.Container, Object.Node);
1480 end if;
ffb35bbf
ES
1481 end Last;
1482
ff2efe85
AC
1483 ------------------
1484 -- Last_Element --
1485 ------------------
1486
1487 function Last_Element (Container : Set) return Element_Type is
1488 begin
14f73211 1489 if Checks and then Container.Last = 0 then
ff2efe85
AC
1490 raise Constraint_Error with "set is empty";
1491 end if;
1492
1493 return Container.Nodes (Container.Last).Element;
1494 end Last_Element;
1495
1496 ----------
1497 -- Left --
1498 ----------
1499
1500 function Left (Node : Node_Type) return Count_Type is
1501 begin
1502 return Node.Left;
1503 end Left;
1504
1505 ------------
1506 -- Length --
1507 ------------
1508
1509 function Length (Container : Set) return Count_Type is
1510 begin
1511 return Container.Length;
1512 end Length;
1513
1514 ----------
1515 -- Move --
1516 ----------
1517
1518 procedure Move (Target : in out Set; Source : in out Set) is
1519 begin
1520 if Target'Address = Source'Address then
1521 return;
1522 end if;
1523
14f73211 1524 TC_Check (Source.TC);
ff2efe85 1525
dfbf013f
MH
1526 Target.Assign (Source);
1527 Source.Clear;
ff2efe85
AC
1528 end Move;
1529
1530 ----------
1531 -- Next --
1532 ----------
1533
1534 function Next (Position : Cursor) return Cursor is
1535 begin
1536 if Position = No_Element then
1537 return No_Element;
1538 end if;
1539
1540 pragma Assert (Vet (Position.Container.all, Position.Node),
1541 "bad cursor in Next");
1542
1543 declare
1544 Node : constant Count_Type :=
15f0f591 1545 Tree_Operations.Next (Position.Container.all, Position.Node);
ff2efe85
AC
1546
1547 begin
1548 if Node = 0 then
1549 return No_Element;
1550 end if;
1551
1552 return Cursor'(Position.Container, Node);
1553 end;
1554 end Next;
1555
1556 procedure Next (Position : in out Cursor) is
1557 begin
1558 Position := Next (Position);
1559 end Next;
1560
ffb35bbf 1561 function Next (Object : Iterator; Position : Cursor) return Cursor is
ffb35bbf 1562 begin
b38c20a6
AC
1563 if Position.Container = null then
1564 return No_Element;
1565 end if;
1566
14f73211 1567 if Checks and then Position.Container /= Object.Container then
b38c20a6
AC
1568 raise Program_Error with
1569 "Position cursor of Next designates wrong set";
1570 end if;
1571
ffb35bbf
ES
1572 return Next (Position);
1573 end Next;
1574
ff2efe85
AC
1575 -------------
1576 -- Overlap --
1577 -------------
1578
1579 function Overlap (Left, Right : Set) return Boolean
1580 renames Set_Ops.Set_Overlap;
1581
1582 ------------
1583 -- Parent --
1584 ------------
1585
1586 function Parent (Node : Node_Type) return Count_Type is
1587 begin
1588 return Node.Parent;
1589 end Parent;
1590
1591 --------------
1592 -- Previous --
1593 --------------
1594
1595 function Previous (Position : Cursor) return Cursor is
1596 begin
1597 if Position = No_Element then
1598 return No_Element;
1599 end if;
1600
1601 pragma Assert (Vet (Position.Container.all, Position.Node),
1602 "bad cursor in Previous");
1603
1604 declare
1605 Node : constant Count_Type :=
15f0f591 1606 Tree_Operations.Previous (Position.Container.all, Position.Node);
ff2efe85 1607 begin
ce72a9a3
AC
1608 return (if Node = 0 then No_Element
1609 else Cursor'(Position.Container, Node));
ff2efe85
AC
1610 end;
1611 end Previous;
1612
1613 procedure Previous (Position : in out Cursor) is
1614 begin
1615 Position := Previous (Position);
1616 end Previous;
1617
ffb35bbf 1618 function Previous (Object : Iterator; Position : Cursor) return Cursor is
ffb35bbf 1619 begin
b38c20a6
AC
1620 if Position.Container = null then
1621 return No_Element;
1622 end if;
1623
14f73211 1624 if Checks and then Position.Container /= Object.Container then
b38c20a6
AC
1625 raise Program_Error with
1626 "Position cursor of Previous designates wrong set";
1627 end if;
1628
ffb35bbf
ES
1629 return Previous (Position);
1630 end Previous;
1631
14f73211
BD
1632 ----------------------
1633 -- Pseudo_Reference --
1634 ----------------------
1635
1636 function Pseudo_Reference
1637 (Container : aliased Set'Class) return Reference_Control_Type
1638 is
1639 TC : constant Tamper_Counts_Access :=
1640 Container.TC'Unrestricted_Access;
1641 begin
1642 return R : constant Reference_Control_Type := (Controlled with TC) do
2f26abcc 1643 Busy (TC.all);
14f73211
BD
1644 end return;
1645 end Pseudo_Reference;
1646
ff2efe85
AC
1647 -------------------
1648 -- Query_Element --
1649 -------------------
1650
1651 procedure Query_Element
1652 (Position : Cursor;
1653 Process : not null access procedure (Element : Element_Type))
1654 is
1655 begin
14f73211 1656 if Checks and then Position.Node = 0 then
ff2efe85
AC
1657 raise Constraint_Error with "Position cursor equals No_Element";
1658 end if;
1659
1660 pragma Assert (Vet (Position.Container.all, Position.Node),
1661 "bad cursor in Query_Element");
1662
1663 declare
1664 S : Set renames Position.Container.all;
14f73211 1665 Lock : With_Lock (S.TC'Unrestricted_Access);
ff2efe85 1666 begin
14f73211 1667 Process (S.Nodes (Position.Node).Element);
ff2efe85
AC
1668 end;
1669 end Query_Element;
1670
26349b6d
BD
1671 ---------------
1672 -- Put_Image --
1673 ---------------
1674
1675 procedure Put_Image
20922782 1676 (S : in out Ada.Strings.Text_Buffers.Root_Buffer_Type'Class; V : Set)
26349b6d
BD
1677 is
1678 First_Time : Boolean := True;
1679 use System.Put_Images;
1680 begin
1681 Array_Before (S);
1682
1683 for X of V loop
1684 if First_Time then
1685 First_Time := False;
1686 else
1687 Simple_Array_Between (S);
1688 end if;
1689
1690 Element_Type'Put_Image (S, X);
1691 end loop;
1692
1693 Array_After (S);
1694 end Put_Image;
1695
ff2efe85
AC
1696 ----------
1697 -- Read --
1698 ----------
1699
1700 procedure Read
1701 (Stream : not null access Root_Stream_Type'Class;
1702 Container : out Set)
1703 is
1704 procedure Read_Element (Node : in out Node_Type);
1705 pragma Inline (Read_Element);
1706
1707 procedure Allocate is
1708 new Tree_Operations.Generic_Allocate (Read_Element);
1709
1710 procedure Read_Elements is
1711 new Tree_Operations.Generic_Read (Allocate);
1712
1713 ------------------
1714 -- Read_Element --
1715 ------------------
1716
1717 procedure Read_Element (Node : in out Node_Type) is
1718 begin
1719 Element_Type'Read (Stream, Node.Element);
1720 end Read_Element;
1721
1722 -- Start of processing for Read
1723
1724 begin
1725 Read_Elements (Stream, Container);
1726 end Read;
1727
1728 procedure Read
1729 (Stream : not null access Root_Stream_Type'Class;
1730 Item : out Cursor)
1731 is
1732 begin
1733 raise Program_Error with "attempt to stream set cursor";
1734 end Read;
1735
ffb35bbf
ES
1736 procedure Read
1737 (Stream : not null access Root_Stream_Type'Class;
1738 Item : out Constant_Reference_Type)
1739 is
1740 begin
1741 raise Program_Error with "attempt to stream reference";
1742 end Read;
1743
ff2efe85
AC
1744 -------------
1745 -- Replace --
1746 -------------
1747
1748 procedure Replace (Container : in out Set; New_Item : Element_Type) is
1749 Node : constant Count_Type := Element_Keys.Find (Container, New_Item);
1750
1751 begin
c602003b
BD
1752 TE_Check (Container.TC);
1753
14f73211 1754 if Checks and then Node = 0 then
ff2efe85
AC
1755 raise Constraint_Error with
1756 "attempt to replace element not in set";
1757 end if;
1758
ff2efe85
AC
1759 Container.Nodes (Node).Element := New_Item;
1760 end Replace;
1761
1762 ---------------------
1763 -- Replace_Element --
1764 ---------------------
1765
1766 procedure Replace_Element
1767 (Container : in out Set;
1768 Index : Count_Type;
1769 Item : Element_Type)
1770 is
1771 pragma Assert (Index /= 0);
1772
1773 function New_Node return Count_Type;
1774 pragma Inline (New_Node);
1775
1776 procedure Local_Insert_Post is
1777 new Element_Keys.Generic_Insert_Post (New_Node);
1778
1779 procedure Local_Insert_Sans_Hint is
1780 new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
1781
1782 procedure Local_Insert_With_Hint is
1783 new Element_Keys.Generic_Conditional_Insert_With_Hint
1784 (Local_Insert_Post,
1785 Local_Insert_Sans_Hint);
1786
1787 Nodes : Nodes_Type renames Container.Nodes;
1788 Node : Node_Type renames Nodes (Index);
1789
1790 --------------
1791 -- New_Node --
1792 --------------
1793
1794 function New_Node return Count_Type is
1795 begin
1796 Node.Element := Item;
ce72a9a3
AC
1797 Node.Color := Red_Black_Trees.Red;
1798 Node.Parent := 0;
1799 Node.Right := 0;
1800 Node.Left := 0;
ff2efe85
AC
1801 return Index;
1802 end New_Node;
1803
1804 Hint : Count_Type;
1805 Result : Count_Type;
1806 Inserted : Boolean;
e7f11067
AC
1807 Compare : Boolean;
1808
ff2efe85
AC
1809 -- Start of processing for Replace_Element
1810
1811 begin
e7f11067
AC
1812 -- Replace_Element assigns value Item to the element designated by Node,
1813 -- per certain semantic constraints, described as follows.
1814
1815 -- If Item is equivalent to the element, then element is replaced and
1816 -- there's nothing else to do. This is the easy case.
1817
1818 -- If Item is not equivalent, then the node will (possibly) have to move
1819 -- to some other place in the tree. This is slighly more complicated,
1820 -- because we must ensure that Item is not equivalent to some other
1821 -- element in the tree (in which case, the replacement is not allowed).
1822
1823 -- Determine whether Item is equivalent to element on the specified
1824 -- node.
1825
14f73211
BD
1826 declare
1827 Lock : With_Lock (Container.TC'Unrestricted_Access);
e7f11067 1828 begin
e7f11067
AC
1829 Compare := (if Item < Node.Element then False
1830 elsif Node.Element < Item then False
1831 else True);
e7f11067
AC
1832 end;
1833
1834 if Compare then
03eb6036 1835
e7f11067
AC
1836 -- Item is equivalent to the node's element, so we will not have to
1837 -- move the node.
ff2efe85 1838
14f73211 1839 TE_Check (Container.TC);
ff2efe85
AC
1840
1841 Node.Element := Item;
1842 return;
1843 end if;
1844
e7f11067
AC
1845 -- The replacement Item is not equivalent to the element on the
1846 -- specified node, which means that it will need to be re-inserted in a
1847 -- different position in the tree. We must now determine whether Item is
1848 -- equivalent to some other element in the tree (which would prohibit
1849 -- the assignment and hence the move).
1850
1851 -- Ceiling returns the smallest element equivalent or greater than the
1852 -- specified Item; if there is no such element, then it returns 0.
1853
ff2efe85
AC
1854 Hint := Element_Keys.Ceiling (Container, Item);
1855
e7f11067 1856 if Hint /= 0 then -- Item <= Nodes (Hint).Element
14f73211
BD
1857 declare
1858 Lock : With_Lock (Container.TC'Unrestricted_Access);
e7f11067 1859 begin
e7f11067 1860 Compare := Item < Nodes (Hint).Element;
e7f11067
AC
1861 end;
1862
03eb6036
AC
1863 -- Item is equivalent to Nodes (Hint).Element
1864
14f73211 1865 if Checks and then not Compare then
03eb6036 1866
e7f11067
AC
1867 -- Ceiling returns an element that is equivalent or greater than
1868 -- Item. If Item is "not less than" the element, then by
1869 -- elimination we know that Item is equivalent to the element.
1870
1871 -- But this means that it is not possible to assign the value of
1872 -- Item to the specified element (on Node), because a different
1873 -- element (on Hint) equivalent to Item already exsits. (Were we
1874 -- to change Node's element value, we would have to move Node, but
1875 -- we would be unable to move the Node, because its new position
1876 -- in the tree is already occupied by an equivalent element.)
1877
1878 raise Program_Error with "attempt to replace existing element";
1879 end if;
1880
1881 -- Item is not equivalent to any other element in the tree
2995860f 1882 -- (specifically, it is less than Nodes (Hint).Element), so it is
e7f11067
AC
1883 -- safe to assign the value of Item to Node.Element. This means that
1884 -- the node will have to move to a different position in the tree
1885 -- (because its element will have a different value).
1886
1887 -- The nearest (greater) neighbor of Item is Hint. This will be the
1888 -- insertion position of Node (because its element will have Item as
1889 -- its new value).
1890
1891 -- If Node equals Hint, the relative position of Node does not
1892 -- change. This allows us to perform an optimization: we need not
1893 -- remove Node from the tree and then reinsert it with its new value,
1894 -- because it would only be placed in the exact same position.
ff2efe85 1895
ff2efe85 1896 if Hint = Index then
14f73211 1897 TE_Check (Container.TC);
ff2efe85
AC
1898
1899 Node.Element := Item;
1900 return;
1901 end if;
ff2efe85
AC
1902 end if;
1903
e7f11067
AC
1904 -- If we get here, it is because Item was greater than all elements in
1905 -- the tree (Hint = 0), or because Item was less than some element at a
1906 -- different place in the tree (Item < Nodes (Hint).Element and Hint /=
1907 -- Index). In either case, we remove Node from the tree and then insert
1908 -- Item into the tree, onto the same Node.
1909
ff2efe85
AC
1910 Tree_Operations.Delete_Node_Sans_Free (Container, Index);
1911
1912 Local_Insert_With_Hint
1913 (Tree => Container,
1914 Position => Hint,
1915 Key => Item,
1916 Node => Result,
1917 Inserted => Inserted);
1918
1919 pragma Assert (Inserted);
1920 pragma Assert (Result = Index);
1921 end Replace_Element;
1922
1923 procedure Replace_Element
1924 (Container : in out Set;
1925 Position : Cursor;
1926 New_Item : Element_Type)
1927 is
1928 begin
14f73211 1929 if Checks and then Position.Node = 0 then
ff2efe85
AC
1930 raise Constraint_Error with
1931 "Position cursor equals No_Element";
1932 end if;
1933
14f73211
BD
1934 if Checks and then Position.Container /= Container'Unrestricted_Access
1935 then
ff2efe85
AC
1936 raise Program_Error with
1937 "Position cursor designates wrong set";
1938 end if;
1939
1940 pragma Assert (Vet (Container, Position.Node),
1941 "bad cursor in Replace_Element");
1942
1943 Replace_Element (Container, Position.Node, New_Item);
1944 end Replace_Element;
1945
1946 ---------------------
1947 -- Reverse_Iterate --
1948 ---------------------
1949
1950 procedure Reverse_Iterate
1951 (Container : Set;
1952 Process : not null access procedure (Position : Cursor))
1953 is
1954 procedure Process_Node (Node : Count_Type);
1955 pragma Inline (Process_Node);
1956
1957 procedure Local_Reverse_Iterate is
1958 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1959
1960 ------------------
1961 -- Process_Node --
1962 ------------------
1963
1964 procedure Process_Node (Node : Count_Type) is
1965 begin
1966 Process (Cursor'(Container'Unrestricted_Access, Node));
1967 end Process_Node;
1968
1969 S : Set renames Container'Unrestricted_Access.all;
14f73211 1970 Busy : With_Busy (S.TC'Unrestricted_Access);
ff2efe85
AC
1971
1972 -- Start of processing for Reverse_Iterate
1973
1974 begin
14f73211 1975 Local_Reverse_Iterate (S);
ff2efe85
AC
1976 end Reverse_Iterate;
1977
1978 -----------
1979 -- Right --
1980 -----------
1981
1982 function Right (Node : Node_Type) return Count_Type is
1983 begin
1984 return Node.Right;
1985 end Right;
1986
1987 ---------------
1988 -- Set_Color --
1989 ---------------
1990
1991 procedure Set_Color
1992 (Node : in out Node_Type;
1993 Color : Red_Black_Trees.Color_Type)
1994 is
1995 begin
1996 Node.Color := Color;
1997 end Set_Color;
1998
1999 --------------
2000 -- Set_Left --
2001 --------------
2002
2003 procedure Set_Left (Node : in out Node_Type; Left : Count_Type) is
2004 begin
2005 Node.Left := Left;
2006 end Set_Left;
2007
2008 ----------------
2009 -- Set_Parent --
2010 ----------------
2011
2012 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type) is
2013 begin
2014 Node.Parent := Parent;
2015 end Set_Parent;
2016
2017 ---------------
2018 -- Set_Right --
2019 ---------------
2020
2021 procedure Set_Right (Node : in out Node_Type; Right : Count_Type) is
2022 begin
2023 Node.Right := Right;
2024 end Set_Right;
2025
2026 --------------------------
2027 -- Symmetric_Difference --
2028 --------------------------
2029
2030 procedure Symmetric_Difference (Target : in out Set; Source : Set)
2031 renames Set_Ops.Set_Symmetric_Difference;
2032
2033 function Symmetric_Difference (Left, Right : Set) return Set
2034 renames Set_Ops.Set_Symmetric_Difference;
2035
2036 ------------
2037 -- To_Set --
2038 ------------
2039
2040 function To_Set (New_Item : Element_Type) return Set is
2041 Node : Count_Type;
2042 Inserted : Boolean;
72a29376 2043
ff2efe85
AC
2044 begin
2045 return S : Set (1) do
2046 Insert_Sans_Hint (S, New_Item, Node, Inserted);
2047 pragma Assert (Inserted);
2048 end return;
2049 end To_Set;
2050
2051 -----------
2052 -- Union --
2053 -----------
2054
2055 procedure Union (Target : in out Set; Source : Set)
2056 renames Set_Ops.Set_Union;
2057
2058 function Union (Left, Right : Set) return Set
2059 renames Set_Ops.Set_Union;
2060
2061 -----------
2062 -- Write --
2063 -----------
2064
2065 procedure Write
2066 (Stream : not null access Root_Stream_Type'Class;
2067 Container : Set)
2068 is
2069 procedure Write_Element
2070 (Stream : not null access Root_Stream_Type'Class;
2071 Node : Node_Type);
2072 pragma Inline (Write_Element);
2073
2074 procedure Write_Elements is
2075 new Tree_Operations.Generic_Write (Write_Element);
2076
2077 -------------------
2078 -- Write_Element --
2079 -------------------
2080
2081 procedure Write_Element
2082 (Stream : not null access Root_Stream_Type'Class;
2083 Node : Node_Type)
2084 is
2085 begin
2086 Element_Type'Write (Stream, Node.Element);
2087 end Write_Element;
2088
2089 -- Start of processing for Write
2090
2091 begin
2092 Write_Elements (Stream, Container);
2093 end Write;
2094
2095 procedure Write
2096 (Stream : not null access Root_Stream_Type'Class;
2097 Item : Cursor)
2098 is
2099 begin
2100 raise Program_Error with "attempt to stream set cursor";
2101 end Write;
2102
ffb35bbf
ES
2103 procedure Write
2104 (Stream : not null access Root_Stream_Type'Class;
2105 Item : Constant_Reference_Type)
2106 is
2107 begin
2108 raise Program_Error with "attempt to stream reference";
2109 end Write;
2110
ff2efe85 2111end Ada.Containers.Bounded_Ordered_Sets;