OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ada/] [a-coormu.adb] - Blame information for rev 711

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.