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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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