OSDN Git Service

2007-04-20 Vincent Celier <celier@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / a-ciorse.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT LIBRARY COMPONENTS                          --
4 --                                                                          --
5 --                      A D A . C O N T A I N E R S .                       --
6 --              I N D E F I N I T E _ O R D E R E D _ S E T S               --
7 --                                                                          --
8 --                                 B o d y                                  --
9 --                                                                          --
10 --          Copyright (C) 2004-2006, Free Software Foundation, Inc.         --
11 --                                                                          --
12 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
13 -- terms of the  GNU General Public License as published  by the Free Soft- --
14 -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
15 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
18 -- for  more details.  You should have  received  a copy of the GNU General --
19 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
20 -- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
21 -- Boston, MA 02110-1301, USA.                                              --
22 --                                                                          --
23 -- As a special exception,  if other files  instantiate  generics from this --
24 -- unit, or you link  this unit with other files  to produce an executable, --
25 -- this  unit  does not  by itself cause  the resulting  executable  to  be --
26 -- covered  by the  GNU  General  Public  License.  This exception does not --
27 -- however invalidate  any other reasons why  the executable file  might be --
28 -- covered by the  GNU Public License.                                      --
29 --                                                                          --
30 -- This unit was originally developed by Matthew J Heaney.                  --
31 ------------------------------------------------------------------------------
32
33 with Ada.Containers.Red_Black_Trees.Generic_Operations;
34 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Operations);
35
36 with Ada.Containers.Red_Black_Trees.Generic_Keys;
37 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
38
39 with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
40 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
41
42 with Ada.Unchecked_Deallocation;
43
44 package body Ada.Containers.Indefinite_Ordered_Sets is
45
46    -----------------------
47    -- Local Subprograms --
48    -----------------------
49
50    function Color (Node : Node_Access) return Color_Type;
51    pragma Inline (Color);
52
53    function Copy_Node (Source : Node_Access) return Node_Access;
54    pragma Inline (Copy_Node);
55
56    procedure Free (X : in out Node_Access);
57
58    procedure Insert_Sans_Hint
59      (Tree     : in out Tree_Type;
60       New_Item : Element_Type;
61       Node     : out Node_Access;
62       Inserted : out Boolean);
63
64    procedure Insert_With_Hint
65      (Dst_Tree : in out Tree_Type;
66       Dst_Hint : Node_Access;
67       Src_Node : Node_Access;
68       Dst_Node : out Node_Access);
69
70    function Is_Greater_Element_Node
71      (Left  : Element_Type;
72       Right : Node_Access) return Boolean;
73    pragma Inline (Is_Greater_Element_Node);
74
75    function Is_Less_Element_Node
76      (Left  : Element_Type;
77       Right : Node_Access) return Boolean;
78    pragma Inline (Is_Less_Element_Node);
79
80    function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
81    pragma Inline (Is_Less_Node_Node);
82
83    function Left (Node : Node_Access) return Node_Access;
84    pragma Inline (Left);
85
86    function Parent (Node : Node_Access) return Node_Access;
87    pragma Inline (Parent);
88
89    procedure Replace_Element
90      (Tree : in out Tree_Type;
91       Node : Node_Access;
92       Item : Element_Type);
93
94    function Right (Node : Node_Access) return Node_Access;
95    pragma Inline (Right);
96
97    procedure Set_Color (Node : Node_Access; Color : Color_Type);
98    pragma Inline (Set_Color);
99
100    procedure Set_Left (Node : Node_Access; Left : Node_Access);
101    pragma Inline (Set_Left);
102
103    procedure Set_Parent (Node   : Node_Access; Parent : Node_Access);
104    pragma Inline (Set_Parent);
105
106    procedure Set_Right (Node : Node_Access; Right : Node_Access);
107    pragma Inline (Set_Right);
108
109    --------------------------
110    -- Local Instantiations --
111    --------------------------
112
113    procedure Free_Element is
114      new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
115
116    package Tree_Operations is
117      new Red_Black_Trees.Generic_Operations (Tree_Types);
118
119    procedure Delete_Tree is
120      new Tree_Operations.Generic_Delete_Tree (Free);
121
122    function Copy_Tree is
123      new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
124
125    use Tree_Operations;
126
127    package Element_Keys is
128      new Red_Black_Trees.Generic_Keys
129        (Tree_Operations     => Tree_Operations,
130         Key_Type            => Element_Type,
131         Is_Less_Key_Node    => Is_Less_Element_Node,
132         Is_Greater_Key_Node => Is_Greater_Element_Node);
133
134    package Set_Ops is
135       new Generic_Set_Operations
136         (Tree_Operations  => Tree_Operations,
137          Insert_With_Hint => Insert_With_Hint,
138          Copy_Tree        => Copy_Tree,
139          Delete_Tree      => Delete_Tree,
140          Is_Less          => Is_Less_Node_Node,
141          Free             => Free);
142
143    ---------
144    -- "<" --
145    ---------
146
147    function "<" (Left, Right : Cursor) return Boolean is
148    begin
149       if Left.Node = null then
150          raise Constraint_Error with "Left cursor equals No_Element";
151       end if;
152
153       if Right.Node = null then
154          raise Constraint_Error with "Right cursor equals No_Element";
155       end if;
156
157       if Left.Node.Element = null then
158          raise Program_Error with "Left cursor is bad";
159       end if;
160
161       if Right.Node.Element = null then
162          raise Program_Error with "Right cursor is bad";
163       end if;
164
165       pragma Assert (Vet (Left.Container.Tree, Left.Node),
166                      "bad Left cursor in ""<""");
167
168       pragma Assert (Vet (Right.Container.Tree, Right.Node),
169                      "bad Right cursor in ""<""");
170
171       return Left.Node.Element.all < Right.Node.Element.all;
172    end "<";
173
174    function "<" (Left : Cursor; Right : Element_Type) return Boolean is
175    begin
176       if Left.Node = null then
177          raise Constraint_Error with "Left cursor equals No_Element";
178       end if;
179
180       if Left.Node.Element = null then
181          raise Program_Error with "Left cursor is bad";
182       end if;
183
184       pragma Assert (Vet (Left.Container.Tree, Left.Node),
185                      "bad Left cursor in ""<""");
186
187       return Left.Node.Element.all < Right;
188    end "<";
189
190    function "<" (Left : Element_Type; Right : Cursor) return Boolean is
191    begin
192       if Right.Node = null then
193          raise Constraint_Error with "Right cursor equals No_Element";
194       end if;
195
196       if Right.Node.Element = null then
197          raise Program_Error with "Right cursor is bad";
198       end if;
199
200       pragma Assert (Vet (Right.Container.Tree, Right.Node),
201                      "bad Right cursor in ""<""");
202
203       return Left < Right.Node.Element.all;
204    end "<";
205
206    ---------
207    -- "=" --
208    ---------
209
210    function "=" (Left, Right : Set) return Boolean is
211
212       function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
213       pragma Inline (Is_Equal_Node_Node);
214
215       function Is_Equal is
216         new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
217
218       ------------------------
219       -- Is_Equal_Node_Node --
220       ------------------------
221
222       function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
223       begin
224          return L.Element.all = R.Element.all;
225       end Is_Equal_Node_Node;
226
227    --  Start of processing for "="
228
229    begin
230       return Is_Equal (Left.Tree, Right.Tree);
231    end "=";
232
233    ---------
234    -- ">" --
235    ---------
236
237    function ">" (Left, Right : Cursor) return Boolean is
238    begin
239       if Left.Node = null then
240          raise Constraint_Error with "Left cursor equals No_Element";
241       end if;
242
243       if Right.Node = null then
244          raise Constraint_Error with "Right cursor equals No_Element";
245       end if;
246
247       if Left.Node.Element = null then
248          raise Program_Error with "Left cursor is bad";
249       end if;
250
251       if Right.Node.Element = null then
252          raise Program_Error with "Right cursor is bad";
253       end if;
254
255       pragma Assert (Vet (Left.Container.Tree, Left.Node),
256                      "bad Left cursor in "">""");
257
258       pragma Assert (Vet (Right.Container.Tree, Right.Node),
259                      "bad Right cursor in "">""");
260
261       --  L > R same as R < L
262
263       return Right.Node.Element.all < Left.Node.Element.all;
264    end ">";
265
266    function ">" (Left : Cursor; Right : Element_Type) return Boolean is
267    begin
268       if Left.Node = null then
269          raise Constraint_Error with "Left cursor equals No_Element";
270       end if;
271
272       if Left.Node.Element = null then
273          raise Program_Error with "Left cursor is bad";
274       end if;
275
276       pragma Assert (Vet (Left.Container.Tree, Left.Node),
277                      "bad Left cursor in "">""");
278
279       return Right < Left.Node.Element.all;
280    end ">";
281
282    function ">" (Left : Element_Type; Right : Cursor) return Boolean is
283    begin
284       if Right.Node = null then
285          raise Constraint_Error with "Right cursor equals No_Element";
286       end if;
287
288       if Right.Node.Element = null then
289          raise Program_Error with "Right cursor is bad";
290       end if;
291
292       pragma Assert (Vet (Right.Container.Tree, Right.Node),
293                      "bad Right cursor in "">""");
294
295       return Right.Node.Element.all < Left;
296    end ">";
297
298    ------------
299    -- Adjust --
300    ------------
301
302    procedure Adjust is
303       new Tree_Operations.Generic_Adjust (Copy_Tree);
304
305    procedure Adjust (Container : in out Set) is
306    begin
307       Adjust (Container.Tree);
308    end Adjust;
309
310    -------------
311    -- Ceiling --
312    -------------
313
314    function Ceiling (Container : Set; Item : Element_Type) return Cursor is
315       Node : constant Node_Access :=
316                Element_Keys.Ceiling (Container.Tree, Item);
317
318    begin
319       if Node = null then
320          return No_Element;
321       end if;
322
323       return Cursor'(Container'Unrestricted_Access, Node);
324    end Ceiling;
325
326    -----------
327    -- Clear --
328    -----------
329
330    procedure Clear is
331       new Tree_Operations.Generic_Clear (Delete_Tree);
332
333    procedure Clear (Container : in out Set) is
334    begin
335       Clear (Container.Tree);
336    end Clear;
337
338    -----------
339    -- Color --
340    -----------
341
342    function Color (Node : Node_Access) return Color_Type is
343    begin
344       return Node.Color;
345    end Color;
346
347    --------------
348    -- Contains --
349    --------------
350
351    function Contains (Container : Set; Item : Element_Type) return Boolean is
352    begin
353       return Find (Container, Item) /= No_Element;
354    end Contains;
355
356    ---------------
357    -- Copy_Node --
358    ---------------
359
360    function Copy_Node (Source : Node_Access) return Node_Access is
361       Element : Element_Access := new Element_Type'(Source.Element.all);
362
363    begin
364       return new Node_Type'(Parent  => null,
365                             Left    => null,
366                             Right   => null,
367                             Color   => Source.Color,
368                             Element => Element);
369    exception
370       when others =>
371          Free_Element (Element);
372          raise;
373    end Copy_Node;
374
375    ------------
376    -- Delete --
377    ------------
378
379    procedure Delete (Container : in out Set; Position : in out Cursor) is
380    begin
381       if Position.Node = null then
382          raise Constraint_Error with "Position cursor equals No_Element";
383       end if;
384
385       if Position.Node.Element = null then
386          raise Program_Error with "Position cursor is bad";
387       end if;
388
389       if Position.Container /= Container'Unrestricted_Access then
390          raise Program_Error with "Position cursor designates wrong set";
391       end if;
392
393       pragma Assert (Vet (Container.Tree, Position.Node),
394                      "bad cursor in Delete");
395
396       Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
397       Free (Position.Node);
398       Position.Container := null;
399    end Delete;
400
401    procedure Delete (Container : in out Set; Item : Element_Type) is
402       X : Node_Access :=
403             Element_Keys.Find (Container.Tree, Item);
404
405    begin
406       if X = null then
407          raise Constraint_Error with "attempt to delete element not in set";
408       end if;
409
410       Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
411       Free (X);
412    end Delete;
413
414    ------------------
415    -- Delete_First --
416    ------------------
417
418    procedure Delete_First (Container : in out Set) is
419       Tree : Tree_Type renames Container.Tree;
420       X    : Node_Access := Tree.First;
421
422    begin
423       if X /= null then
424          Tree_Operations.Delete_Node_Sans_Free (Tree, X);
425          Free (X);
426       end if;
427    end Delete_First;
428
429    -----------------
430    -- Delete_Last --
431    -----------------
432
433    procedure Delete_Last (Container : in out Set) is
434       Tree : Tree_Type renames Container.Tree;
435       X    : Node_Access := Tree.Last;
436
437    begin
438       if X /= null then
439          Tree_Operations.Delete_Node_Sans_Free (Tree, X);
440          Free (X);
441       end if;
442    end Delete_Last;
443
444    ----------------
445    -- Difference --
446    ----------------
447
448    procedure Difference (Target : in out Set; Source : Set) is
449    begin
450       Set_Ops.Difference (Target.Tree, Source.Tree);
451    end Difference;
452
453    function Difference (Left, Right : Set) return Set is
454       Tree : constant Tree_Type :=
455                Set_Ops.Difference (Left.Tree, Right.Tree);
456    begin
457       return Set'(Controlled with Tree);
458    end Difference;
459
460    -------------
461    -- Element --
462    -------------
463
464    function Element (Position : Cursor) return Element_Type is
465    begin
466       if Position.Node = null then
467          raise Constraint_Error with "Position cursor equals No_Element";
468       end if;
469
470       if Position.Node.Element = null then
471          raise Program_Error with "Position cursor is bad";
472       end if;
473
474       pragma Assert (Vet (Position.Container.Tree, Position.Node),
475                      "bad cursor in Element");
476
477       return Position.Node.Element.all;
478    end Element;
479
480    -------------------------
481    -- Equivalent_Elements --
482    -------------------------
483
484    function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
485    begin
486       if Left < Right
487         or else Right < Left
488       then
489          return False;
490       else
491          return True;
492       end if;
493    end Equivalent_Elements;
494
495    ---------------------
496    -- Equivalent_Sets --
497    ---------------------
498
499    function Equivalent_Sets (Left, Right : Set) return Boolean is
500
501       function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
502       pragma Inline (Is_Equivalent_Node_Node);
503
504       function Is_Equivalent is
505          new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
506
507       -----------------------------
508       -- Is_Equivalent_Node_Node --
509       -----------------------------
510
511       function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
512       begin
513          if L.Element.all < R.Element.all then
514             return False;
515          elsif R.Element.all < L.Element.all then
516             return False;
517          else
518             return True;
519          end if;
520       end Is_Equivalent_Node_Node;
521
522    --  Start of processing for Equivalent_Sets
523
524    begin
525       return Is_Equivalent (Left.Tree, Right.Tree);
526    end Equivalent_Sets;
527
528    -------------
529    -- Exclude --
530    -------------
531
532    procedure Exclude (Container : in out Set; Item : Element_Type) is
533       X : Node_Access :=
534             Element_Keys.Find (Container.Tree, Item);
535
536    begin
537       if X /= null then
538          Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
539          Free (X);
540       end if;
541    end Exclude;
542
543    ----------
544    -- Find --
545    ----------
546
547    function Find (Container : Set; Item : Element_Type) return Cursor is
548       Node : constant Node_Access :=
549                Element_Keys.Find (Container.Tree, Item);
550
551    begin
552       if Node = null then
553          return No_Element;
554       end if;
555
556       return Cursor'(Container'Unrestricted_Access, Node);
557    end Find;
558
559    -----------
560    -- First --
561    -----------
562
563    function First (Container : Set) return Cursor is
564    begin
565       if Container.Tree.First = null then
566          return No_Element;
567       end if;
568
569       return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
570    end First;
571
572    -------------------
573    -- First_Element --
574    -------------------
575
576    function First_Element (Container : Set) return Element_Type is
577    begin
578       if Container.Tree.First = null then
579          raise Constraint_Error with "set is empty";
580       end if;
581
582       return Container.Tree.First.Element.all;
583    end First_Element;
584
585    -----------
586    -- Floor --
587    -----------
588
589    function Floor (Container : Set; Item : Element_Type) return Cursor is
590       Node : constant Node_Access :=
591                Element_Keys.Floor (Container.Tree, Item);
592
593    begin
594       if Node = null then
595          return No_Element;
596       end if;
597
598       return Cursor'(Container'Unrestricted_Access, Node);
599    end Floor;
600
601    ----------
602    -- Free --
603    ----------
604
605    procedure Free (X : in out Node_Access) is
606       procedure Deallocate is
607         new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
608
609    begin
610       if X = null then
611          return;
612       end if;
613
614       X.Parent := X;
615       X.Left := X;
616       X.Right := X;
617
618       begin
619          Free_Element (X.Element);
620       exception
621          when others =>
622             X.Element := null;
623             Deallocate (X);
624             raise;
625       end;
626
627       Deallocate (X);
628    end Free;
629
630    ------------------
631    -- Generic_Keys --
632    ------------------
633
634    package body Generic_Keys is
635
636       -----------------------
637       -- Local Subprograms --
638       -----------------------
639
640       function Is_Greater_Key_Node
641         (Left  : Key_Type;
642          Right : Node_Access) return Boolean;
643       pragma Inline (Is_Greater_Key_Node);
644
645       function Is_Less_Key_Node
646         (Left  : Key_Type;
647          Right : Node_Access) return Boolean;
648       pragma Inline (Is_Less_Key_Node);
649
650       --------------------------
651       -- Local Instantiations --
652       --------------------------
653
654       package Key_Keys is
655         new Red_Black_Trees.Generic_Keys
656           (Tree_Operations     => Tree_Operations,
657            Key_Type            => Key_Type,
658            Is_Less_Key_Node    => Is_Less_Key_Node,
659            Is_Greater_Key_Node => Is_Greater_Key_Node);
660
661       -------------
662       -- Ceiling --
663       -------------
664
665       function Ceiling (Container : Set; Key : Key_Type) return Cursor is
666          Node : constant Node_Access :=
667                   Key_Keys.Ceiling (Container.Tree, Key);
668
669       begin
670          if Node = null then
671             return No_Element;
672          end if;
673
674          return Cursor'(Container'Unrestricted_Access, Node);
675       end Ceiling;
676
677       --------------
678       -- Contains --
679       --------------
680
681       function Contains (Container : Set; Key : Key_Type) return Boolean is
682       begin
683          return Find (Container, Key) /= No_Element;
684       end Contains;
685
686       ------------
687       -- Delete --
688       ------------
689
690       procedure Delete (Container : in out Set; Key : Key_Type) is
691          X : Node_Access := Key_Keys.Find (Container.Tree, Key);
692
693       begin
694          if X = null then
695             raise Constraint_Error with "attempt to delete key not in set";
696          end if;
697
698          Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
699          Free (X);
700       end Delete;
701
702       -------------
703       -- Element --
704       -------------
705
706       function Element (Container : Set; Key : Key_Type) return Element_Type is
707          Node : constant Node_Access :=
708                   Key_Keys.Find (Container.Tree, Key);
709
710       begin
711          if Node = null then
712             raise Constraint_Error with "key not in set";
713          end if;
714
715          return Node.Element.all;
716       end Element;
717
718       ---------------------
719       -- Equivalent_Keys --
720       ---------------------
721
722       function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
723       begin
724          if Left < Right
725            or else Right < Left
726          then
727             return False;
728          else
729             return True;
730          end if;
731       end Equivalent_Keys;
732
733       -------------
734       -- Exclude --
735       -------------
736
737       procedure Exclude (Container : in out Set; Key : Key_Type) is
738          X : Node_Access := Key_Keys.Find (Container.Tree, Key);
739
740       begin
741          if X /= null then
742             Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
743             Free (X);
744          end if;
745       end Exclude;
746
747       ----------
748       -- Find --
749       ----------
750
751       function Find (Container : Set; Key : Key_Type) return Cursor is
752          Node : constant Node_Access :=
753                   Key_Keys.Find (Container.Tree, Key);
754
755       begin
756          if Node = null then
757             return No_Element;
758          end if;
759
760          return Cursor'(Container'Unrestricted_Access, Node);
761       end Find;
762
763       -----------
764       -- Floor --
765       -----------
766
767       function Floor (Container : Set; Key : Key_Type) return Cursor is
768          Node : constant Node_Access :=
769                   Key_Keys.Floor (Container.Tree, Key);
770
771       begin
772          if Node = null then
773             return No_Element;
774          end if;
775
776          return Cursor'(Container'Unrestricted_Access, Node);
777       end Floor;
778
779       -------------------------
780       -- Is_Greater_Key_Node --
781       -------------------------
782
783       function Is_Greater_Key_Node
784         (Left  : Key_Type;
785          Right : Node_Access) return Boolean is
786       begin
787          return Key (Right.Element.all) < Left;
788       end Is_Greater_Key_Node;
789
790       ----------------------
791       -- Is_Less_Key_Node --
792       ----------------------
793
794       function Is_Less_Key_Node
795         (Left  : Key_Type;
796          Right : Node_Access) return Boolean is
797       begin
798          return Left < Key (Right.Element.all);
799       end Is_Less_Key_Node;
800
801       ---------
802       -- Key --
803       ---------
804
805       function Key (Position : Cursor) return Key_Type is
806       begin
807          if Position.Node = null then
808             raise Constraint_Error with
809               "Position cursor equals No_Element";
810          end if;
811
812          if Position.Node.Element = null then
813             raise Program_Error with
814               "Position cursor is bad";
815          end if;
816
817          pragma Assert (Vet (Position.Container.Tree, Position.Node),
818                         "bad cursor in Key");
819
820          return Key (Position.Node.Element.all);
821       end Key;
822
823       -------------
824       -- Replace --
825       -------------
826
827       procedure Replace
828         (Container : in out Set;
829          Key       : Key_Type;
830          New_Item  : Element_Type)
831       is
832          Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
833
834       begin
835          if Node = null then
836             raise Constraint_Error with
837               "attempt to replace key not in set";
838          end if;
839
840          Replace_Element (Container.Tree, Node, New_Item);
841       end Replace;
842
843       -----------------------------------
844       -- Update_Element_Preserving_Key --
845       -----------------------------------
846
847       procedure Update_Element_Preserving_Key
848         (Container : in out Set;
849          Position  : Cursor;
850          Process   : not null access
851                         procedure (Element : in out Element_Type))
852       is
853          Tree : Tree_Type renames Container.Tree;
854
855       begin
856          if Position.Node = null then
857             raise Constraint_Error with "Position cursor equals No_Element";
858          end if;
859
860          if Position.Node.Element = null then
861             raise Program_Error with "Position cursor is bad";
862          end if;
863
864          if Position.Container /= Container'Unrestricted_Access then
865             raise Program_Error with "Position cursor designates wrong set";
866          end if;
867
868          pragma Assert (Vet (Container.Tree, Position.Node),
869                         "bad cursor in Update_Element_Preserving_Key");
870
871          declare
872             E : Element_Type renames Position.Node.Element.all;
873             K : constant Key_Type := Key (E);
874
875             B : Natural renames Tree.Busy;
876             L : Natural renames Tree.Lock;
877
878          begin
879             B := B + 1;
880             L := L + 1;
881
882             begin
883                Process (E);
884             exception
885                when others =>
886                   L := L - 1;
887                   B := B - 1;
888                   raise;
889             end;
890
891             L := L - 1;
892             B := B - 1;
893
894             if Equivalent_Keys (K, Key (E)) then
895                return;
896             end if;
897          end;
898
899          declare
900             X : Node_Access := Position.Node;
901          begin
902             Tree_Operations.Delete_Node_Sans_Free (Tree, X);
903             Free (X);
904          end;
905
906          raise Program_Error with "key was modified";
907       end Update_Element_Preserving_Key;
908
909    end Generic_Keys;
910
911    -----------------
912    -- Has_Element --
913    -----------------
914
915    function Has_Element (Position : Cursor) return Boolean is
916    begin
917       return Position /= No_Element;
918    end Has_Element;
919
920    -------------
921    -- Include --
922    -------------
923
924    procedure Include (Container : in out Set; New_Item  : Element_Type) is
925       Position : Cursor;
926       Inserted : Boolean;
927
928       X : Element_Access;
929
930    begin
931       Insert (Container, New_Item, Position, Inserted);
932
933       if not Inserted then
934          if Container.Tree.Lock > 0 then
935             raise Program_Error with
936               "attempt to tamper with cursors (set is locked)";
937          end if;
938
939          X := Position.Node.Element;
940          Position.Node.Element := new Element_Type'(New_Item);
941          Free_Element (X);
942       end if;
943    end Include;
944
945    ------------
946    -- Insert --
947    ------------
948
949    procedure Insert
950      (Container : in out Set;
951       New_Item  : Element_Type;
952       Position  : out Cursor;
953       Inserted  : out Boolean)
954    is
955    begin
956       Insert_Sans_Hint
957         (Container.Tree,
958          New_Item,
959          Position.Node,
960          Inserted);
961
962       Position.Container := Container'Unrestricted_Access;
963    end Insert;
964
965    procedure Insert (Container : in out Set; New_Item  : Element_Type) is
966       Position : Cursor;
967       Inserted : Boolean;
968    begin
969       Insert (Container, New_Item, Position, Inserted);
970
971       if not Inserted then
972          raise Constraint_Error with
973            "attempt to insert element already in set";
974       end if;
975    end Insert;
976
977    ----------------------
978    -- Insert_Sans_Hint --
979    ----------------------
980
981    procedure Insert_Sans_Hint
982      (Tree     : in out Tree_Type;
983       New_Item : Element_Type;
984       Node     : out Node_Access;
985       Inserted : out Boolean)
986    is
987       function New_Node return Node_Access;
988       pragma Inline (New_Node);
989
990       procedure Insert_Post is
991         new Element_Keys.Generic_Insert_Post (New_Node);
992
993       procedure Conditional_Insert_Sans_Hint is
994         new Element_Keys.Generic_Conditional_Insert (Insert_Post);
995
996       --------------
997       -- New_Node --
998       --------------
999
1000       function New_Node return Node_Access is
1001          Element : Element_Access := new Element_Type'(New_Item);
1002
1003       begin
1004          return new Node_Type'(Parent  => null,
1005                                Left    => null,
1006                                Right   => null,
1007                                Color   => Red_Black_Trees.Red,
1008                                Element => Element);
1009       exception
1010          when others =>
1011             Free_Element (Element);
1012             raise;
1013       end New_Node;
1014
1015    --  Start of processing for Insert_Sans_Hint
1016
1017    begin
1018       Conditional_Insert_Sans_Hint
1019         (Tree,
1020          New_Item,
1021          Node,
1022          Inserted);
1023    end Insert_Sans_Hint;
1024
1025    ----------------------
1026    -- Insert_With_Hint --
1027    ----------------------
1028
1029    procedure Insert_With_Hint
1030      (Dst_Tree : in out Tree_Type;
1031       Dst_Hint : Node_Access;
1032       Src_Node : Node_Access;
1033       Dst_Node : out Node_Access)
1034    is
1035       Success  : Boolean;
1036
1037       function New_Node return Node_Access;
1038
1039       procedure Insert_Post is
1040         new Element_Keys.Generic_Insert_Post (New_Node);
1041
1042       procedure Insert_Sans_Hint is
1043         new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1044
1045       procedure Insert_With_Hint is
1046          new Element_Keys.Generic_Conditional_Insert_With_Hint
1047             (Insert_Post,
1048              Insert_Sans_Hint);
1049
1050       --------------
1051       -- New_Node --
1052       --------------
1053
1054       function New_Node return Node_Access is
1055          Element : Element_Access :=
1056                      new Element_Type'(Src_Node.Element.all);
1057          Node    : Node_Access;
1058
1059       begin
1060          begin
1061             Node := new Node_Type;
1062          exception
1063             when others =>
1064                Free_Element (Element);
1065                raise;
1066          end;
1067
1068          Node.Element := Element;
1069          return Node;
1070       end New_Node;
1071
1072    --  Start of processing for Insert_With_Hint
1073
1074    begin
1075       Insert_With_Hint
1076         (Dst_Tree,
1077          Dst_Hint,
1078          Src_Node.Element.all,
1079          Dst_Node,
1080          Success);
1081    end Insert_With_Hint;
1082
1083    ------------------
1084    -- Intersection --
1085    ------------------
1086
1087    procedure Intersection (Target : in out Set; Source : Set) is
1088    begin
1089       Set_Ops.Intersection (Target.Tree, Source.Tree);
1090    end Intersection;
1091
1092    function Intersection (Left, Right : Set) return Set is
1093       Tree : constant Tree_Type :=
1094                Set_Ops.Intersection (Left.Tree, Right.Tree);
1095    begin
1096       return Set'(Controlled with Tree);
1097    end Intersection;
1098
1099    --------------
1100    -- Is_Empty --
1101    --------------
1102
1103    function Is_Empty (Container : Set) return Boolean is
1104    begin
1105       return Container.Tree.Length = 0;
1106    end Is_Empty;
1107
1108    -----------------------------
1109    -- Is_Greater_Element_Node --
1110    -----------------------------
1111
1112    function Is_Greater_Element_Node
1113      (Left  : Element_Type;
1114       Right : Node_Access) return Boolean is
1115    begin
1116       --  e > node same as node < e
1117
1118       return Right.Element.all < Left;
1119    end Is_Greater_Element_Node;
1120
1121    --------------------------
1122    -- Is_Less_Element_Node --
1123    --------------------------
1124
1125    function Is_Less_Element_Node
1126      (Left  : Element_Type;
1127       Right : Node_Access) return Boolean is
1128    begin
1129       return Left < Right.Element.all;
1130    end Is_Less_Element_Node;
1131
1132    -----------------------
1133    -- Is_Less_Node_Node --
1134    -----------------------
1135
1136    function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1137    begin
1138       return L.Element.all < R.Element.all;
1139    end Is_Less_Node_Node;
1140
1141    ---------------
1142    -- Is_Subset --
1143    ---------------
1144
1145    function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1146    begin
1147       return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1148    end Is_Subset;
1149
1150    -------------
1151    -- Iterate --
1152    -------------
1153
1154    procedure Iterate
1155      (Container : Set;
1156       Process   : not null access procedure (Position : Cursor))
1157    is
1158       procedure Process_Node (Node : Node_Access);
1159       pragma Inline (Process_Node);
1160
1161       procedure Local_Iterate is
1162         new Tree_Operations.Generic_Iteration (Process_Node);
1163
1164       ------------------
1165       -- Process_Node --
1166       ------------------
1167
1168       procedure Process_Node (Node : Node_Access) is
1169       begin
1170          Process (Cursor'(Container'Unrestricted_Access, Node));
1171       end Process_Node;
1172
1173       T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1174       B : Natural renames T.Busy;
1175
1176    --  Start of prccessing for Iterate
1177
1178    begin
1179       B := B + 1;
1180
1181       begin
1182          Local_Iterate (T);
1183       exception
1184          when others =>
1185             B := B - 1;
1186             raise;
1187       end;
1188
1189       B := B - 1;
1190    end Iterate;
1191
1192    ----------
1193    -- Last --
1194    ----------
1195
1196    function Last (Container : Set) return Cursor is
1197    begin
1198       if Container.Tree.Last = null then
1199          return No_Element;
1200       end if;
1201
1202       return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
1203    end Last;
1204
1205    ------------------
1206    -- Last_Element --
1207    ------------------
1208
1209    function Last_Element (Container : Set) return Element_Type is
1210    begin
1211       if Container.Tree.Last = null then
1212          raise Constraint_Error with "set is empty";
1213       end if;
1214
1215       return Container.Tree.Last.Element.all;
1216    end Last_Element;
1217
1218    ----------
1219    -- Left --
1220    ----------
1221
1222    function Left (Node : Node_Access) return Node_Access is
1223    begin
1224       return Node.Left;
1225    end Left;
1226
1227    ------------
1228    -- Length --
1229    ------------
1230
1231    function Length (Container : Set) return Count_Type is
1232    begin
1233       return Container.Tree.Length;
1234    end Length;
1235
1236    ----------
1237    -- Move --
1238    ----------
1239
1240    procedure Move is
1241       new Tree_Operations.Generic_Move (Clear);
1242
1243    procedure Move (Target : in out Set; Source : in out Set) is
1244    begin
1245       Move (Target => Target.Tree, Source => Source.Tree);
1246    end Move;
1247
1248    ----------
1249    -- Next --
1250    ----------
1251
1252    procedure Next (Position : in out Cursor) is
1253    begin
1254       Position := Next (Position);
1255    end Next;
1256
1257    function Next (Position : Cursor) return Cursor is
1258    begin
1259       if Position = No_Element then
1260          return No_Element;
1261       end if;
1262
1263       if Position.Node.Element = null then
1264          raise Program_Error with "Position cursor is bad";
1265       end if;
1266
1267       pragma Assert (Vet (Position.Container.Tree, Position.Node),
1268                      "bad cursor in Next");
1269
1270       declare
1271          Node : constant Node_Access :=
1272                   Tree_Operations.Next (Position.Node);
1273
1274       begin
1275          if Node = null then
1276             return No_Element;
1277          end if;
1278
1279          return Cursor'(Position.Container, Node);
1280       end;
1281    end Next;
1282
1283    -------------
1284    -- Overlap --
1285    -------------
1286
1287    function Overlap (Left, Right : Set) return Boolean is
1288    begin
1289       return Set_Ops.Overlap (Left.Tree, Right.Tree);
1290    end Overlap;
1291
1292    ------------
1293    -- Parent --
1294    ------------
1295
1296    function Parent (Node : Node_Access) return Node_Access is
1297    begin
1298       return Node.Parent;
1299    end Parent;
1300
1301    --------------
1302    -- Previous --
1303    --------------
1304
1305    procedure Previous (Position : in out Cursor) is
1306    begin
1307       Position := Previous (Position);
1308    end Previous;
1309
1310    function Previous (Position : Cursor) return Cursor is
1311    begin
1312       if Position = No_Element then
1313          return No_Element;
1314       end if;
1315
1316       if Position.Node.Element = null then
1317          raise Program_Error with "Position cursor is bad";
1318       end if;
1319
1320       pragma Assert (Vet (Position.Container.Tree, Position.Node),
1321                      "bad cursor in Previous");
1322
1323       declare
1324          Node : constant Node_Access :=
1325                   Tree_Operations.Previous (Position.Node);
1326
1327       begin
1328          if Node = null then
1329             return No_Element;
1330          end if;
1331
1332          return Cursor'(Position.Container, Node);
1333       end;
1334    end Previous;
1335
1336    -------------------
1337    -- Query_Element --
1338    -------------------
1339
1340    procedure Query_Element
1341      (Position  : Cursor;
1342       Process   : not null access procedure (Element : Element_Type))
1343    is
1344    begin
1345       if Position.Node = null then
1346          raise Constraint_Error with "Position cursor equals No_Element";
1347       end if;
1348
1349       if Position.Node.Element = null then
1350          raise Program_Error with "Position cursor is bad";
1351       end if;
1352
1353       pragma Assert (Vet (Position.Container.Tree, Position.Node),
1354                      "bad cursor in Query_Element");
1355
1356       declare
1357          T : Tree_Type renames Position.Container.Tree;
1358
1359          B : Natural renames T.Busy;
1360          L : Natural renames T.Lock;
1361
1362       begin
1363          B := B + 1;
1364          L := L + 1;
1365
1366          begin
1367             Process (Position.Node.Element.all);
1368          exception
1369             when others =>
1370                L := L - 1;
1371                B := B - 1;
1372                raise;
1373          end;
1374
1375          L := L - 1;
1376          B := B - 1;
1377       end;
1378    end Query_Element;
1379
1380    ----------
1381    -- Read --
1382    ----------
1383
1384    procedure Read
1385      (Stream    : not null access Root_Stream_Type'Class;
1386       Container : out Set)
1387    is
1388       function Read_Node
1389         (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1390       pragma Inline (Read_Node);
1391
1392       procedure Read is
1393          new Tree_Operations.Generic_Read (Clear, Read_Node);
1394
1395       ---------------
1396       -- Read_Node --
1397       ---------------
1398
1399       function Read_Node
1400         (Stream : not null access Root_Stream_Type'Class) return Node_Access
1401       is
1402          Node : Node_Access := new Node_Type;
1403
1404       begin
1405          Node.Element := new Element_Type'(Element_Type'Input (Stream));
1406          return Node;
1407
1408       exception
1409          when others =>
1410             Free (Node);  --  Note that Free deallocates elem too
1411             raise;
1412       end Read_Node;
1413
1414    --  Start of processing for Read
1415
1416    begin
1417       Read (Stream, Container.Tree);
1418    end Read;
1419
1420    procedure Read
1421      (Stream : not null access Root_Stream_Type'Class;
1422       Item   : out Cursor)
1423    is
1424    begin
1425       raise Program_Error with "attempt to stream set cursor";
1426    end Read;
1427
1428    -------------
1429    -- Replace --
1430    -------------
1431
1432    procedure Replace (Container : in out Set; New_Item : Element_Type) is
1433       Node : constant Node_Access :=
1434                Element_Keys.Find (Container.Tree, New_Item);
1435
1436       X : Element_Access;
1437
1438    begin
1439       if Node = null then
1440          raise Constraint_Error with "attempt to replace element not in set";
1441       end if;
1442
1443       if Container.Tree.Lock > 0 then
1444          raise Program_Error with
1445            "attempt to tamper with cursors (set is locked)";
1446       end if;
1447
1448       X := Node.Element;
1449       Node.Element := new Element_Type'(New_Item);
1450       Free_Element (X);
1451    end Replace;
1452
1453    ---------------------
1454    -- Replace_Element --
1455    ---------------------
1456
1457    procedure Replace_Element
1458      (Tree : in out Tree_Type;
1459       Node : Node_Access;
1460       Item : Element_Type)
1461    is
1462       pragma Assert (Node /= null);
1463       pragma Assert (Node.Element /= null);
1464
1465       function New_Node return Node_Access;
1466       pragma Inline (New_Node);
1467
1468       procedure Local_Insert_Post is
1469          new Element_Keys.Generic_Insert_Post (New_Node);
1470
1471       procedure Local_Insert_Sans_Hint is
1472          new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
1473
1474       procedure Local_Insert_With_Hint is
1475          new Element_Keys.Generic_Conditional_Insert_With_Hint
1476         (Local_Insert_Post,
1477          Local_Insert_Sans_Hint);
1478
1479       --------------
1480       -- New_Node --
1481       --------------
1482
1483       function New_Node return Node_Access is
1484       begin
1485          Node.Element := new Element_Type'(Item);  -- OK if fails
1486          Node.Color := Red;
1487          Node.Parent := null;
1488          Node.Right := null;
1489          Node.Left := null;
1490
1491          return Node;
1492       end New_Node;
1493
1494       Hint     : Node_Access;
1495       Result   : Node_Access;
1496       Inserted : Boolean;
1497
1498       X : Element_Access := Node.Element;
1499
1500       --  Start of processing for Insert
1501
1502    begin
1503       if Item < Node.Element.all
1504         or else Node.Element.all < Item
1505       then
1506          null;
1507
1508       else
1509          if Tree.Lock > 0 then
1510             raise Program_Error with
1511               "attempt to tamper with cursors (set is locked)";
1512          end if;
1513
1514          Node.Element := new Element_Type'(Item);
1515          Free_Element (X);
1516
1517          return;
1518       end if;
1519
1520       Hint := Element_Keys.Ceiling (Tree, Item);
1521
1522       if Hint = null then
1523          null;
1524
1525       elsif Item < Hint.Element.all then
1526          if Hint = Node then
1527             if Tree.Lock > 0 then
1528                raise Program_Error with
1529                  "attempt to tamper with cursors (set is locked)";
1530             end if;
1531
1532             Node.Element := new Element_Type'(Item);
1533             Free_Element (X);
1534
1535             return;
1536          end if;
1537
1538       else
1539          pragma Assert (not (Hint.Element.all < Item));
1540          raise Program_Error with "attempt to replace existing element";
1541       end if;
1542
1543       Tree_Operations.Delete_Node_Sans_Free (Tree, Node);  -- Checks busy-bit
1544
1545       Local_Insert_With_Hint
1546         (Tree     => Tree,
1547          Position => Hint,
1548          Key      => Item,
1549          Node     => Result,
1550          Inserted => Inserted);
1551
1552       pragma Assert (Inserted);
1553       pragma Assert (Result = Node);
1554
1555       Free_Element (X);
1556    end Replace_Element;
1557
1558    procedure Replace_Element
1559     (Container : in out Set;
1560      Position  : Cursor;
1561      New_Item  : Element_Type)
1562    is
1563    begin
1564       if Position.Node = null then
1565          raise Constraint_Error with "Position cursor equals No_Element";
1566       end if;
1567
1568       if Position.Node.Element = null then
1569          raise Program_Error with "Position cursor is bad";
1570       end if;
1571
1572       if Position.Container /= Container'Unrestricted_Access then
1573          raise Program_Error with "Position cursor designates wrong set";
1574       end if;
1575
1576       pragma Assert (Vet (Container.Tree, Position.Node),
1577                      "bad cursor in Replace_Element");
1578
1579       Replace_Element (Container.Tree, Position.Node, New_Item);
1580    end Replace_Element;
1581
1582    ---------------------
1583    -- Reverse_Iterate --
1584    ---------------------
1585
1586    procedure Reverse_Iterate
1587      (Container : Set;
1588       Process   : not null access procedure (Position : Cursor))
1589    is
1590       procedure Process_Node (Node : Node_Access);
1591       pragma Inline (Process_Node);
1592
1593       procedure Local_Reverse_Iterate is
1594          new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1595
1596       ------------------
1597       -- Process_Node --
1598       ------------------
1599
1600       procedure Process_Node (Node : Node_Access) is
1601       begin
1602          Process (Cursor'(Container'Unrestricted_Access, Node));
1603       end Process_Node;
1604
1605       T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1606       B : Natural renames T.Busy;
1607
1608    --  Start of processing for Reverse_Iterate
1609
1610    begin
1611       B := B + 1;
1612
1613       begin
1614          Local_Reverse_Iterate (T);
1615       exception
1616          when others =>
1617             B := B - 1;
1618             raise;
1619       end;
1620
1621       B := B - 1;
1622    end Reverse_Iterate;
1623
1624    -----------
1625    -- Right --
1626    -----------
1627
1628    function Right (Node : Node_Access) return Node_Access is
1629    begin
1630       return Node.Right;
1631    end Right;
1632
1633    ---------------
1634    -- Set_Color --
1635    ---------------
1636
1637    procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1638    begin
1639       Node.Color := Color;
1640    end Set_Color;
1641
1642    --------------
1643    -- Set_Left --
1644    --------------
1645
1646    procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1647    begin
1648       Node.Left := Left;
1649    end Set_Left;
1650
1651    ----------------
1652    -- Set_Parent --
1653    ----------------
1654
1655    procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1656    begin
1657       Node.Parent := Parent;
1658    end Set_Parent;
1659
1660    ---------------
1661    -- Set_Right --
1662    ---------------
1663
1664    procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1665    begin
1666       Node.Right := Right;
1667    end Set_Right;
1668
1669    --------------------------
1670    -- Symmetric_Difference --
1671    --------------------------
1672
1673    procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1674    begin
1675       Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1676    end Symmetric_Difference;
1677
1678    function Symmetric_Difference (Left, Right : Set) return Set is
1679       Tree : constant Tree_Type :=
1680                Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1681    begin
1682       return Set'(Controlled with Tree);
1683    end Symmetric_Difference;
1684
1685    ------------
1686    -- To_Set --
1687    ------------
1688
1689    function To_Set (New_Item : Element_Type) return Set is
1690       Tree     : Tree_Type;
1691       Node     : Node_Access;
1692       Inserted : Boolean;
1693
1694    begin
1695       Insert_Sans_Hint (Tree, New_Item, Node, Inserted);
1696       return Set'(Controlled with Tree);
1697    end To_Set;
1698
1699    -----------
1700    -- Union --
1701    -----------
1702
1703    procedure Union (Target : in out Set; Source : Set) is
1704    begin
1705       Set_Ops.Union (Target.Tree, Source.Tree);
1706    end Union;
1707
1708    function Union (Left, Right : Set) return Set is
1709       Tree : constant Tree_Type :=
1710                Set_Ops.Union (Left.Tree, Right.Tree);
1711    begin
1712       return Set'(Controlled with Tree);
1713    end Union;
1714
1715    -----------
1716    -- Write --
1717    -----------
1718
1719    procedure Write
1720      (Stream    : not null access Root_Stream_Type'Class;
1721       Container : Set)
1722    is
1723       procedure Write_Node
1724         (Stream : not null access Root_Stream_Type'Class;
1725          Node   : Node_Access);
1726       pragma Inline (Write_Node);
1727
1728       procedure Write is
1729          new Tree_Operations.Generic_Write (Write_Node);
1730
1731       ----------------
1732       -- Write_Node --
1733       ----------------
1734
1735       procedure Write_Node
1736         (Stream : not null access Root_Stream_Type'Class;
1737          Node   : Node_Access)
1738       is
1739       begin
1740          Element_Type'Output (Stream, Node.Element.all);
1741       end Write_Node;
1742
1743    --  Start of processing for Write
1744
1745    begin
1746       Write (Stream, Container.Tree);
1747    end Write;
1748
1749    procedure Write
1750      (Stream : not null access Root_Stream_Type'Class;
1751       Item   : Cursor)
1752    is
1753    begin
1754       raise Program_Error with "attempt to stream set cursor";
1755    end Write;
1756
1757 end Ada.Containers.Indefinite_Ordered_Sets;