OSDN Git Service

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