[gcc/]
[official-gcc.git] / gcc / ada / a-cborse.adb
blobea6a6d06af16d340ec1451cc427f50fb957f21b6
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- A D A . C O N T A I N E R S . B O U N D E D _ O R D E R E D _ S E T S --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004-2014, 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 ------------------------------------------------------------------------------
30 with Ada.Containers.Red_Black_Trees.Generic_Bounded_Operations;
31 pragma Elaborate_All
32 (Ada.Containers.Red_Black_Trees.Generic_Bounded_Operations);
34 with Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys;
35 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys);
37 with Ada.Containers.Red_Black_Trees.Generic_Bounded_Set_Operations;
38 pragma Elaborate_All
39 (Ada.Containers.Red_Black_Trees.Generic_Bounded_Set_Operations);
41 with System; use type System.Address;
43 package body Ada.Containers.Bounded_Ordered_Sets is
45 ------------------------------
46 -- Access to Fields of Node --
47 ------------------------------
49 -- These subprograms provide functional notation for access to fields
50 -- of a node, and procedural notation for modifying these fields.
52 function Color (Node : Node_Type) return Red_Black_Trees.Color_Type;
53 pragma Inline (Color);
55 function Left (Node : Node_Type) return Count_Type;
56 pragma Inline (Left);
58 function Parent (Node : Node_Type) return Count_Type;
59 pragma Inline (Parent);
61 function Right (Node : Node_Type) return Count_Type;
62 pragma Inline (Right);
64 procedure Set_Color
65 (Node : in out Node_Type;
66 Color : Red_Black_Trees.Color_Type);
67 pragma Inline (Set_Color);
69 procedure Set_Left (Node : in out Node_Type; Left : Count_Type);
70 pragma Inline (Set_Left);
72 procedure Set_Right (Node : in out Node_Type; Right : Count_Type);
73 pragma Inline (Set_Right);
75 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type);
76 pragma Inline (Set_Parent);
78 -----------------------
79 -- Local Subprograms --
80 -----------------------
82 procedure Insert_Sans_Hint
83 (Container : in out Set;
84 New_Item : Element_Type;
85 Node : out Count_Type;
86 Inserted : out Boolean);
88 procedure Insert_With_Hint
89 (Dst_Set : in out Set;
90 Dst_Hint : Count_Type;
91 Src_Node : Node_Type;
92 Dst_Node : out Count_Type);
94 function Is_Greater_Element_Node
95 (Left : Element_Type;
96 Right : Node_Type) return Boolean;
97 pragma Inline (Is_Greater_Element_Node);
99 function Is_Less_Element_Node
100 (Left : Element_Type;
101 Right : Node_Type) return Boolean;
102 pragma Inline (Is_Less_Element_Node);
104 function Is_Less_Node_Node (L, R : Node_Type) return Boolean;
105 pragma Inline (Is_Less_Node_Node);
107 procedure Replace_Element
108 (Container : in out Set;
109 Index : Count_Type;
110 Item : Element_Type);
112 --------------------------
113 -- Local Instantiations --
114 --------------------------
116 package Tree_Operations is
117 new Red_Black_Trees.Generic_Bounded_Operations (Tree_Types);
119 use Tree_Operations;
121 package Element_Keys is
122 new Red_Black_Trees.Generic_Bounded_Keys
123 (Tree_Operations => Tree_Operations,
124 Key_Type => Element_Type,
125 Is_Less_Key_Node => Is_Less_Element_Node,
126 Is_Greater_Key_Node => Is_Greater_Element_Node);
128 package Set_Ops is
129 new Red_Black_Trees.Generic_Bounded_Set_Operations
130 (Tree_Operations => Tree_Operations,
131 Set_Type => Set,
132 Assign => Assign,
133 Insert_With_Hint => Insert_With_Hint,
134 Is_Less => Is_Less_Node_Node);
136 ---------
137 -- "<" --
138 ---------
140 function "<" (Left, Right : Cursor) return Boolean is
141 begin
142 if Left.Node = 0 then
143 raise Constraint_Error with "Left cursor equals No_Element";
144 end if;
146 if Right.Node = 0 then
147 raise Constraint_Error with "Right cursor equals No_Element";
148 end if;
150 pragma Assert (Vet (Left.Container.all, Left.Node),
151 "bad Left cursor in ""<""");
153 pragma Assert (Vet (Right.Container.all, Right.Node),
154 "bad Right cursor in ""<""");
156 declare
157 LN : Nodes_Type renames Left.Container.Nodes;
158 RN : Nodes_Type renames Right.Container.Nodes;
159 begin
160 return LN (Left.Node).Element < RN (Right.Node).Element;
161 end;
162 end "<";
164 function "<" (Left : Cursor; Right : Element_Type) return Boolean is
165 begin
166 if Left.Node = 0 then
167 raise Constraint_Error with "Left cursor equals No_Element";
168 end if;
170 pragma Assert (Vet (Left.Container.all, Left.Node),
171 "bad Left cursor in ""<""");
173 return Left.Container.Nodes (Left.Node).Element < Right;
174 end "<";
176 function "<" (Left : Element_Type; Right : Cursor) return Boolean is
177 begin
178 if Right.Node = 0 then
179 raise Constraint_Error with "Right cursor equals No_Element";
180 end if;
182 pragma Assert (Vet (Right.Container.all, Right.Node),
183 "bad Right cursor in ""<""");
185 return Left < Right.Container.Nodes (Right.Node).Element;
186 end "<";
188 ---------
189 -- "=" --
190 ---------
192 function "=" (Left, Right : Set) return Boolean is
193 function Is_Equal_Node_Node (L, R : Node_Type) return Boolean;
194 pragma Inline (Is_Equal_Node_Node);
196 function Is_Equal is
197 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
199 ------------------------
200 -- Is_Equal_Node_Node --
201 ------------------------
203 function Is_Equal_Node_Node (L, R : Node_Type) return Boolean is
204 begin
205 return L.Element = R.Element;
206 end Is_Equal_Node_Node;
208 -- Start of processing for Is_Equal
210 begin
211 return Is_Equal (Left, Right);
212 end "=";
214 ---------
215 -- ">" --
216 ---------
218 function ">" (Left, Right : Cursor) return Boolean is
219 begin
220 if Left.Node = 0 then
221 raise Constraint_Error with "Left cursor equals No_Element";
222 end if;
224 if Right.Node = 0 then
225 raise Constraint_Error with "Right cursor equals No_Element";
226 end if;
228 pragma Assert (Vet (Left.Container.all, Left.Node),
229 "bad Left cursor in "">""");
231 pragma Assert (Vet (Right.Container.all, Right.Node),
232 "bad Right cursor in "">""");
234 -- L > R same as R < L
236 declare
237 LN : Nodes_Type renames Left.Container.Nodes;
238 RN : Nodes_Type renames Right.Container.Nodes;
239 begin
240 return RN (Right.Node).Element < LN (Left.Node).Element;
241 end;
242 end ">";
244 function ">" (Left : Element_Type; Right : Cursor) return Boolean is
245 begin
246 if Right.Node = 0 then
247 raise Constraint_Error with "Right cursor equals No_Element";
248 end if;
250 pragma Assert (Vet (Right.Container.all, Right.Node),
251 "bad Right cursor in "">""");
253 return Right.Container.Nodes (Right.Node).Element < Left;
254 end ">";
256 function ">" (Left : Cursor; Right : Element_Type) return Boolean is
257 begin
258 if Left.Node = 0 then
259 raise Constraint_Error with "Left cursor equals No_Element";
260 end if;
262 pragma Assert (Vet (Left.Container.all, Left.Node),
263 "bad Left cursor in "">""");
265 return Right < Left.Container.Nodes (Left.Node).Element;
266 end ">";
268 ------------
269 -- Adjust --
270 ------------
272 procedure Adjust (Control : in out Reference_Control_Type) is
273 begin
274 if Control.Container /= null then
275 declare
276 C : Set renames Control.Container.all;
277 B : Natural renames C.Busy;
278 L : Natural renames C.Lock;
279 begin
280 B := B + 1;
281 L := L + 1;
282 end;
283 end if;
284 end Adjust;
286 ------------
287 -- Assign --
288 ------------
290 procedure Assign (Target : in out Set; Source : Set) is
291 procedure Append_Element (Source_Node : Count_Type);
293 procedure Append_Elements is
294 new Tree_Operations.Generic_Iteration (Append_Element);
296 --------------------
297 -- Append_Element --
298 --------------------
300 procedure Append_Element (Source_Node : Count_Type) is
301 SN : Node_Type renames Source.Nodes (Source_Node);
303 procedure Set_Element (Node : in out Node_Type);
304 pragma Inline (Set_Element);
306 function New_Node return Count_Type;
307 pragma Inline (New_Node);
309 procedure Insert_Post is
310 new Element_Keys.Generic_Insert_Post (New_Node);
312 procedure Unconditional_Insert_Sans_Hint is
313 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
315 procedure Unconditional_Insert_Avec_Hint is
316 new Element_Keys.Generic_Unconditional_Insert_With_Hint
317 (Insert_Post,
318 Unconditional_Insert_Sans_Hint);
320 procedure Allocate is
321 new Tree_Operations.Generic_Allocate (Set_Element);
323 --------------
324 -- New_Node --
325 --------------
327 function New_Node return Count_Type is
328 Result : Count_Type;
329 begin
330 Allocate (Target, Result);
331 return Result;
332 end New_Node;
334 -----------------
335 -- Set_Element --
336 -----------------
338 procedure Set_Element (Node : in out Node_Type) is
339 begin
340 Node.Element := SN.Element;
341 end Set_Element;
343 Target_Node : Count_Type;
345 -- Start of processing for Append_Element
347 begin
348 Unconditional_Insert_Avec_Hint
349 (Tree => Target,
350 Hint => 0,
351 Key => SN.Element,
352 Node => Target_Node);
353 end Append_Element;
355 -- Start of processing for Assign
357 begin
358 if Target'Address = Source'Address then
359 return;
360 end if;
362 if Target.Capacity < Source.Length then
363 raise Capacity_Error
364 with "Target capacity is less than Source length";
365 end if;
367 Target.Clear;
368 Append_Elements (Source);
369 end Assign;
371 -------------
372 -- Ceiling --
373 -------------
375 function Ceiling (Container : Set; Item : Element_Type) return Cursor is
376 Node : constant Count_Type :=
377 Element_Keys.Ceiling (Container, Item);
378 begin
379 return (if Node = 0 then No_Element
380 else Cursor'(Container'Unrestricted_Access, Node));
381 end Ceiling;
383 -----------
384 -- Clear --
385 -----------
387 procedure Clear (Container : in out Set) is
388 begin
389 Tree_Operations.Clear_Tree (Container);
390 end Clear;
392 -----------
393 -- Color --
394 -----------
396 function Color (Node : Node_Type) return Red_Black_Trees.Color_Type is
397 begin
398 return Node.Color;
399 end Color;
401 ------------------------
402 -- Constant_Reference --
403 ------------------------
405 function Constant_Reference
406 (Container : aliased Set;
407 Position : Cursor) return Constant_Reference_Type
409 begin
410 if Position.Container = null then
411 raise Constraint_Error with "Position cursor has no element";
412 end if;
414 if Position.Container /= Container'Unrestricted_Access then
415 raise Program_Error with
416 "Position cursor designates wrong container";
417 end if;
419 pragma Assert
420 (Vet (Container, Position.Node),
421 "bad cursor in Constant_Reference");
423 declare
424 N : Node_Type renames Container.Nodes (Position.Node);
425 B : Natural renames Position.Container.Busy;
426 L : Natural renames Position.Container.Lock;
427 begin
428 return R : constant Constant_Reference_Type :=
429 (Element => N.Element'Access,
430 Control => (Controlled with Container'Unrestricted_Access))
432 B := B + 1;
433 L := L + 1;
434 end return;
435 end;
436 end Constant_Reference;
438 --------------
439 -- Contains --
440 --------------
442 function Contains
443 (Container : Set;
444 Item : Element_Type) return Boolean
446 begin
447 return Find (Container, Item) /= No_Element;
448 end Contains;
450 ----------
451 -- Copy --
452 ----------
454 function Copy (Source : Set; Capacity : Count_Type := 0) return Set is
455 C : Count_Type;
457 begin
458 if Capacity = 0 then
459 C := Source.Length;
460 elsif Capacity >= Source.Length then
461 C := Capacity;
462 else
463 raise Capacity_Error with "Capacity value too small";
464 end if;
466 return Target : Set (Capacity => C) do
467 Assign (Target => Target, Source => Source);
468 end return;
469 end Copy;
471 ------------
472 -- Delete --
473 ------------
475 procedure Delete (Container : in out Set; Position : in out Cursor) is
476 begin
477 if Position.Node = 0 then
478 raise Constraint_Error with "Position cursor equals No_Element";
479 end if;
481 if Position.Container /= Container'Unrestricted_Access then
482 raise Program_Error with "Position cursor designates wrong set";
483 end if;
485 pragma Assert (Vet (Container, Position.Node),
486 "bad cursor in Delete");
488 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
489 Tree_Operations.Free (Container, Position.Node);
491 Position := No_Element;
492 end Delete;
494 procedure Delete (Container : in out Set; Item : Element_Type) is
495 X : constant Count_Type := Element_Keys.Find (Container, Item);
497 begin
498 if X = 0 then
499 raise Constraint_Error with "attempt to delete element not in set";
500 end if;
502 Tree_Operations.Delete_Node_Sans_Free (Container, X);
503 Tree_Operations.Free (Container, X);
504 end Delete;
506 ------------------
507 -- Delete_First --
508 ------------------
510 procedure Delete_First (Container : in out Set) is
511 X : constant Count_Type := Container.First;
512 begin
513 if X /= 0 then
514 Tree_Operations.Delete_Node_Sans_Free (Container, X);
515 Tree_Operations.Free (Container, X);
516 end if;
517 end Delete_First;
519 -----------------
520 -- Delete_Last --
521 -----------------
523 procedure Delete_Last (Container : in out Set) is
524 X : constant Count_Type := Container.Last;
525 begin
526 if X /= 0 then
527 Tree_Operations.Delete_Node_Sans_Free (Container, X);
528 Tree_Operations.Free (Container, X);
529 end if;
530 end Delete_Last;
532 ----------------
533 -- Difference --
534 ----------------
536 procedure Difference (Target : in out Set; Source : Set)
537 renames Set_Ops.Set_Difference;
539 function Difference (Left, Right : Set) return Set
540 renames Set_Ops.Set_Difference;
542 -------------
543 -- Element --
544 -------------
546 function Element (Position : Cursor) return Element_Type is
547 begin
548 if Position.Node = 0 then
549 raise Constraint_Error with "Position cursor equals No_Element";
550 end if;
552 pragma Assert (Vet (Position.Container.all, Position.Node),
553 "bad cursor in Element");
555 return Position.Container.Nodes (Position.Node).Element;
556 end Element;
558 -------------------------
559 -- Equivalent_Elements --
560 -------------------------
562 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
563 begin
564 return (if Left < Right or else Right < Left then False else True);
565 end Equivalent_Elements;
567 ---------------------
568 -- Equivalent_Sets --
569 ---------------------
571 function Equivalent_Sets (Left, Right : Set) return Boolean is
572 function Is_Equivalent_Node_Node (L, R : Node_Type) return Boolean;
573 pragma Inline (Is_Equivalent_Node_Node);
575 function Is_Equivalent is
576 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
578 -----------------------------
579 -- Is_Equivalent_Node_Node --
580 -----------------------------
582 function Is_Equivalent_Node_Node (L, R : Node_Type) return Boolean is
583 begin
584 return (if L.Element < R.Element then False
585 elsif R.Element < L.Element then False
586 else True);
587 end Is_Equivalent_Node_Node;
589 -- Start of processing for Equivalent_Sets
591 begin
592 return Is_Equivalent (Left, Right);
593 end Equivalent_Sets;
595 -------------
596 -- Exclude --
597 -------------
599 procedure Exclude (Container : in out Set; Item : Element_Type) is
600 X : constant Count_Type := Element_Keys.Find (Container, Item);
601 begin
602 if X /= 0 then
603 Tree_Operations.Delete_Node_Sans_Free (Container, X);
604 Tree_Operations.Free (Container, X);
605 end if;
606 end Exclude;
608 --------------
609 -- Finalize --
610 --------------
612 procedure Finalize (Object : in out Iterator) is
613 begin
614 if Object.Container /= null then
615 declare
616 B : Natural renames Object.Container.all.Busy;
617 begin
618 B := B - 1;
619 end;
620 end if;
621 end Finalize;
623 procedure Finalize (Control : in out Reference_Control_Type) is
624 begin
625 if Control.Container /= null then
626 declare
627 C : Set renames Control.Container.all;
628 B : Natural renames C.Busy;
629 L : Natural renames C.Lock;
630 begin
631 B := B - 1;
632 L := L - 1;
633 end;
635 Control.Container := null;
636 end if;
637 end Finalize;
639 ----------
640 -- Find --
641 ----------
643 function Find (Container : Set; Item : Element_Type) return Cursor is
644 Node : constant Count_Type := Element_Keys.Find (Container, Item);
645 begin
646 return (if Node = 0 then No_Element
647 else Cursor'(Container'Unrestricted_Access, Node));
648 end Find;
650 -----------
651 -- First --
652 -----------
654 function First (Container : Set) return Cursor is
655 begin
656 return (if Container.First = 0 then No_Element
657 else Cursor'(Container'Unrestricted_Access, Container.First));
658 end First;
660 function First (Object : Iterator) return Cursor is
661 begin
662 -- The value of the iterator object's Node component influences the
663 -- behavior of the First (and Last) selector function.
665 -- When the Node component is 0, this means the iterator object was
666 -- constructed without a start expression, in which case the (forward)
667 -- iteration starts from the (logical) beginning of the entire sequence
668 -- of items (corresponding to Container.First, for a forward iterator).
670 -- Otherwise, this is iteration over a partial sequence of items. When
671 -- the Node component is positive, the iterator object was constructed
672 -- with a start expression, that specifies the position from which the
673 -- (forward) partial iteration begins.
675 if Object.Node = 0 then
676 return Bounded_Ordered_Sets.First (Object.Container.all);
677 else
678 return Cursor'(Object.Container, Object.Node);
679 end if;
680 end First;
682 -------------------
683 -- First_Element --
684 -------------------
686 function First_Element (Container : Set) return Element_Type is
687 begin
688 if Container.First = 0 then
689 raise Constraint_Error with "set is empty";
690 end if;
692 return Container.Nodes (Container.First).Element;
693 end First_Element;
695 -----------
696 -- Floor --
697 -----------
699 function Floor (Container : Set; Item : Element_Type) return Cursor is
700 Node : constant Count_Type := Element_Keys.Floor (Container, Item);
701 begin
702 return (if Node = 0 then No_Element
703 else Cursor'(Container'Unrestricted_Access, Node));
704 end Floor;
706 ------------------
707 -- Generic_Keys --
708 ------------------
710 package body Generic_Keys is
712 -----------------------
713 -- Local Subprograms --
714 -----------------------
716 function Is_Greater_Key_Node
717 (Left : Key_Type;
718 Right : Node_Type) return Boolean;
719 pragma Inline (Is_Greater_Key_Node);
721 function Is_Less_Key_Node
722 (Left : Key_Type;
723 Right : Node_Type) return Boolean;
724 pragma Inline (Is_Less_Key_Node);
726 --------------------------
727 -- Local Instantiations --
728 --------------------------
730 package Key_Keys is
731 new Red_Black_Trees.Generic_Bounded_Keys
732 (Tree_Operations => Tree_Operations,
733 Key_Type => Key_Type,
734 Is_Less_Key_Node => Is_Less_Key_Node,
735 Is_Greater_Key_Node => Is_Greater_Key_Node);
737 -------------
738 -- Ceiling --
739 -------------
741 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
742 Node : constant Count_Type :=
743 Key_Keys.Ceiling (Container, Key);
744 begin
745 return (if Node = 0 then No_Element
746 else Cursor'(Container'Unrestricted_Access, Node));
747 end Ceiling;
749 ------------------------
750 -- Constant_Reference --
751 ------------------------
753 function Constant_Reference
754 (Container : aliased Set;
755 Key : Key_Type) return Constant_Reference_Type
757 Node : constant Count_Type := Key_Keys.Find (Container, Key);
759 begin
760 if Node = 0 then
761 raise Constraint_Error with "key not in set";
762 end if;
764 declare
765 Cur : Cursor := Find (Container, Key);
766 pragma Unmodified (Cur);
768 N : Node_Type renames Container.Nodes (Node);
769 B : Natural renames Cur.Container.Busy;
770 L : Natural renames Cur.Container.Lock;
772 begin
773 return R : constant Constant_Reference_Type :=
774 (Element => N.Element'Access,
775 Control => (Controlled with Container'Unrestricted_Access))
777 B := B + 1;
778 L := L + 1;
779 end return;
780 end;
781 end Constant_Reference;
783 --------------
784 -- Contains --
785 --------------
787 function Contains (Container : Set; Key : Key_Type) return Boolean is
788 begin
789 return Find (Container, Key) /= No_Element;
790 end Contains;
792 ------------
793 -- Delete --
794 ------------
796 procedure Delete (Container : in out Set; Key : Key_Type) is
797 X : constant Count_Type := Key_Keys.Find (Container, Key);
799 begin
800 if X = 0 then
801 raise Constraint_Error with "attempt to delete key not in set";
802 end if;
804 Tree_Operations.Delete_Node_Sans_Free (Container, X);
805 Tree_Operations.Free (Container, X);
806 end Delete;
808 -------------
809 -- Element --
810 -------------
812 function Element (Container : Set; Key : Key_Type) return Element_Type is
813 Node : constant Count_Type := Key_Keys.Find (Container, Key);
815 begin
816 if Node = 0 then
817 raise Constraint_Error with "key not in set";
818 end if;
820 return Container.Nodes (Node).Element;
821 end Element;
823 ---------------------
824 -- Equivalent_Keys --
825 ---------------------
827 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
828 begin
829 return (if Left < Right or else Right < Left then False else True);
830 end Equivalent_Keys;
832 -------------
833 -- Exclude --
834 -------------
836 procedure Exclude (Container : in out Set; Key : Key_Type) is
837 X : constant Count_Type := Key_Keys.Find (Container, Key);
838 begin
839 if X /= 0 then
840 Tree_Operations.Delete_Node_Sans_Free (Container, X);
841 Tree_Operations.Free (Container, X);
842 end if;
843 end Exclude;
845 ----------
846 -- Find --
847 ----------
849 function Find (Container : Set; Key : Key_Type) return Cursor is
850 Node : constant Count_Type := Key_Keys.Find (Container, Key);
851 begin
852 return (if Node = 0 then No_Element
853 else Cursor'(Container'Unrestricted_Access, Node));
854 end Find;
856 -----------
857 -- Floor --
858 -----------
860 function Floor (Container : Set; Key : Key_Type) return Cursor is
861 Node : constant Count_Type := Key_Keys.Floor (Container, Key);
862 begin
863 return (if Node = 0 then No_Element
864 else Cursor'(Container'Unrestricted_Access, Node));
865 end Floor;
867 -------------------------
868 -- Is_Greater_Key_Node --
869 -------------------------
871 function Is_Greater_Key_Node
872 (Left : Key_Type;
873 Right : Node_Type) return Boolean
875 begin
876 return Key (Right.Element) < Left;
877 end Is_Greater_Key_Node;
879 ----------------------
880 -- Is_Less_Key_Node --
881 ----------------------
883 function Is_Less_Key_Node
884 (Left : Key_Type;
885 Right : Node_Type) return Boolean
887 begin
888 return Left < Key (Right.Element);
889 end Is_Less_Key_Node;
891 ---------
892 -- Key --
893 ---------
895 function Key (Position : Cursor) return Key_Type is
896 begin
897 if Position.Node = 0 then
898 raise Constraint_Error with
899 "Position cursor equals No_Element";
900 end if;
902 pragma Assert (Vet (Position.Container.all, Position.Node),
903 "bad cursor in Key");
905 return Key (Position.Container.Nodes (Position.Node).Element);
906 end Key;
908 ----------
909 -- Read --
910 ----------
912 procedure Read
913 (Stream : not null access Root_Stream_Type'Class;
914 Item : out Reference_Type)
916 begin
917 raise Program_Error with "attempt to stream reference";
918 end Read;
920 ------------------------------
921 -- Reference_Preserving_Key --
922 ------------------------------
924 function Reference_Preserving_Key
925 (Container : aliased in out Set;
926 Position : Cursor) return Reference_Type
928 begin
929 if Position.Container = null then
930 raise Constraint_Error with "Position cursor has no element";
931 end if;
933 if Position.Container /= Container'Unrestricted_Access then
934 raise Program_Error with
935 "Position cursor designates wrong container";
936 end if;
938 pragma Assert
939 (Vet (Container, Position.Node),
940 "bad cursor in function Reference_Preserving_Key");
942 -- Some form of finalization will be required in order to actually
943 -- check that the key-part of the element designated by Position has
944 -- not changed. ???
946 declare
947 N : Node_Type renames Container.Nodes (Position.Node);
948 begin
949 return (Element => N.Element'Access);
950 end;
951 end Reference_Preserving_Key;
953 function Reference_Preserving_Key
954 (Container : aliased in out Set;
955 Key : Key_Type) return Reference_Type
957 Node : constant Count_Type := Key_Keys.Find (Container, Key);
959 begin
960 if Node = 0 then
961 raise Constraint_Error with "key not in set";
962 end if;
964 declare
965 N : Node_Type renames Container.Nodes (Node);
966 begin
967 return (Element => N.Element'Access);
968 end;
969 end Reference_Preserving_Key;
971 -------------
972 -- Replace --
973 -------------
975 procedure Replace
976 (Container : in out Set;
977 Key : Key_Type;
978 New_Item : Element_Type)
980 Node : constant Count_Type := Key_Keys.Find (Container, Key);
982 begin
983 if Node = 0 then
984 raise Constraint_Error with
985 "attempt to replace key not in set";
986 end if;
988 Replace_Element (Container, Node, New_Item);
989 end Replace;
991 -----------------------------------
992 -- Update_Element_Preserving_Key --
993 -----------------------------------
995 procedure Update_Element_Preserving_Key
996 (Container : in out Set;
997 Position : Cursor;
998 Process : not null access procedure (Element : in out Element_Type))
1000 begin
1001 if Position.Node = 0 then
1002 raise Constraint_Error with
1003 "Position cursor equals No_Element";
1004 end if;
1006 if Position.Container /= Container'Unrestricted_Access then
1007 raise Program_Error with
1008 "Position cursor designates wrong set";
1009 end if;
1011 pragma Assert (Vet (Container, Position.Node),
1012 "bad cursor in Update_Element_Preserving_Key");
1014 -- Per AI05-0022, the container implementation is required to detect
1015 -- element tampering by a generic actual subprogram.
1017 declare
1018 N : Node_Type renames Container.Nodes (Position.Node);
1019 E : Element_Type renames N.Element;
1020 K : constant Key_Type := Key (E);
1022 B : Natural renames Container.Busy;
1023 L : Natural renames Container.Lock;
1025 Eq : Boolean;
1027 begin
1028 B := B + 1;
1029 L := L + 1;
1031 begin
1032 Process (E);
1033 Eq := Equivalent_Keys (K, Key (E));
1034 exception
1035 when others =>
1036 L := L - 1;
1037 B := B - 1;
1038 raise;
1039 end;
1041 L := L - 1;
1042 B := B - 1;
1044 if Eq then
1045 return;
1046 end if;
1047 end;
1049 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
1050 Tree_Operations.Free (Container, Position.Node);
1052 raise Program_Error with "key was modified";
1053 end Update_Element_Preserving_Key;
1055 -----------
1056 -- Write --
1057 -----------
1059 procedure Write
1060 (Stream : not null access Root_Stream_Type'Class;
1061 Item : Reference_Type)
1063 begin
1064 raise Program_Error with "attempt to stream reference";
1065 end Write;
1066 end Generic_Keys;
1068 -----------------
1069 -- Has_Element --
1070 -----------------
1072 function Has_Element (Position : Cursor) return Boolean is
1073 begin
1074 return Position /= No_Element;
1075 end Has_Element;
1077 -------------
1078 -- Include --
1079 -------------
1081 procedure Include (Container : in out Set; New_Item : Element_Type) is
1082 Position : Cursor;
1083 Inserted : Boolean;
1085 begin
1086 Insert (Container, New_Item, Position, Inserted);
1088 if not Inserted then
1089 if Container.Lock > 0 then
1090 raise Program_Error with
1091 "attempt to tamper with elements (set is locked)";
1092 end if;
1094 Container.Nodes (Position.Node).Element := New_Item;
1095 end if;
1096 end Include;
1098 ------------
1099 -- Insert --
1100 ------------
1102 procedure Insert
1103 (Container : in out Set;
1104 New_Item : Element_Type;
1105 Position : out Cursor;
1106 Inserted : out Boolean)
1108 begin
1109 Insert_Sans_Hint
1110 (Container,
1111 New_Item,
1112 Position.Node,
1113 Inserted);
1115 Position.Container := Container'Unrestricted_Access;
1116 end Insert;
1118 procedure Insert
1119 (Container : in out Set;
1120 New_Item : Element_Type)
1122 Position : Cursor;
1123 pragma Unreferenced (Position);
1125 Inserted : Boolean;
1127 begin
1128 Insert (Container, New_Item, Position, Inserted);
1130 if not Inserted then
1131 raise Constraint_Error with
1132 "attempt to insert element already in set";
1133 end if;
1134 end Insert;
1136 ----------------------
1137 -- Insert_Sans_Hint --
1138 ----------------------
1140 procedure Insert_Sans_Hint
1141 (Container : in out Set;
1142 New_Item : Element_Type;
1143 Node : out Count_Type;
1144 Inserted : out Boolean)
1146 procedure Set_Element (Node : in out Node_Type);
1147 pragma Inline (Set_Element);
1149 function New_Node return Count_Type;
1150 pragma Inline (New_Node);
1152 procedure Insert_Post is
1153 new Element_Keys.Generic_Insert_Post (New_Node);
1155 procedure Conditional_Insert_Sans_Hint is
1156 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1158 procedure Allocate is
1159 new Tree_Operations.Generic_Allocate (Set_Element);
1161 --------------
1162 -- New_Node --
1163 --------------
1165 function New_Node return Count_Type is
1166 Result : Count_Type;
1167 begin
1168 Allocate (Container, Result);
1169 return Result;
1170 end New_Node;
1172 -----------------
1173 -- Set_Element --
1174 -----------------
1176 procedure Set_Element (Node : in out Node_Type) is
1177 begin
1178 Node.Element := New_Item;
1179 end Set_Element;
1181 -- Start of processing for Insert_Sans_Hint
1183 begin
1184 Conditional_Insert_Sans_Hint
1185 (Container,
1186 New_Item,
1187 Node,
1188 Inserted);
1189 end Insert_Sans_Hint;
1191 ----------------------
1192 -- Insert_With_Hint --
1193 ----------------------
1195 procedure Insert_With_Hint
1196 (Dst_Set : in out Set;
1197 Dst_Hint : Count_Type;
1198 Src_Node : Node_Type;
1199 Dst_Node : out Count_Type)
1201 Success : Boolean;
1202 pragma Unreferenced (Success);
1204 procedure Set_Element (Node : in out Node_Type);
1205 pragma Inline (Set_Element);
1207 function New_Node return Count_Type;
1208 pragma Inline (New_Node);
1210 procedure Insert_Post is
1211 new Element_Keys.Generic_Insert_Post (New_Node);
1213 procedure Insert_Sans_Hint is
1214 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1216 procedure Local_Insert_With_Hint is
1217 new Element_Keys.Generic_Conditional_Insert_With_Hint
1218 (Insert_Post,
1219 Insert_Sans_Hint);
1221 procedure Allocate is
1222 new Tree_Operations.Generic_Allocate (Set_Element);
1224 --------------
1225 -- New_Node --
1226 --------------
1228 function New_Node return Count_Type is
1229 Result : Count_Type;
1230 begin
1231 Allocate (Dst_Set, Result);
1232 return Result;
1233 end New_Node;
1235 -----------------
1236 -- Set_Element --
1237 -----------------
1239 procedure Set_Element (Node : in out Node_Type) is
1240 begin
1241 Node.Element := Src_Node.Element;
1242 end Set_Element;
1244 -- Start of processing for Insert_With_Hint
1246 begin
1247 Local_Insert_With_Hint
1248 (Dst_Set,
1249 Dst_Hint,
1250 Src_Node.Element,
1251 Dst_Node,
1252 Success);
1253 end Insert_With_Hint;
1255 ------------------
1256 -- Intersection --
1257 ------------------
1259 procedure Intersection (Target : in out Set; Source : Set)
1260 renames Set_Ops.Set_Intersection;
1262 function Intersection (Left, Right : Set) return Set
1263 renames Set_Ops.Set_Intersection;
1265 --------------
1266 -- Is_Empty --
1267 --------------
1269 function Is_Empty (Container : Set) return Boolean is
1270 begin
1271 return Container.Length = 0;
1272 end Is_Empty;
1274 -----------------------------
1275 -- Is_Greater_Element_Node --
1276 -----------------------------
1278 function Is_Greater_Element_Node
1279 (Left : Element_Type;
1280 Right : Node_Type) return Boolean
1282 begin
1283 -- Compute e > node same as node < e
1285 return Right.Element < Left;
1286 end Is_Greater_Element_Node;
1288 --------------------------
1289 -- Is_Less_Element_Node --
1290 --------------------------
1292 function Is_Less_Element_Node
1293 (Left : Element_Type;
1294 Right : Node_Type) return Boolean
1296 begin
1297 return Left < Right.Element;
1298 end Is_Less_Element_Node;
1300 -----------------------
1301 -- Is_Less_Node_Node --
1302 -----------------------
1304 function Is_Less_Node_Node (L, R : Node_Type) return Boolean is
1305 begin
1306 return L.Element < R.Element;
1307 end Is_Less_Node_Node;
1309 ---------------
1310 -- Is_Subset --
1311 ---------------
1313 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean
1314 renames Set_Ops.Set_Subset;
1316 -------------
1317 -- Iterate --
1318 -------------
1320 procedure Iterate
1321 (Container : Set;
1322 Process : not null access procedure (Position : Cursor))
1324 procedure Process_Node (Node : Count_Type);
1325 pragma Inline (Process_Node);
1327 procedure Local_Iterate is
1328 new Tree_Operations.Generic_Iteration (Process_Node);
1330 ------------------
1331 -- Process_Node --
1332 ------------------
1334 procedure Process_Node (Node : Count_Type) is
1335 begin
1336 Process (Cursor'(Container'Unrestricted_Access, Node));
1337 end Process_Node;
1339 S : Set renames Container'Unrestricted_Access.all;
1340 B : Natural renames S.Busy;
1342 -- Start of processing for Iterate
1344 begin
1345 B := B + 1;
1347 begin
1348 Local_Iterate (S);
1349 exception
1350 when others =>
1351 B := B - 1;
1352 raise;
1353 end;
1355 B := B - 1;
1356 end Iterate;
1358 function Iterate (Container : Set)
1359 return Set_Iterator_Interfaces.Reversible_Iterator'class
1361 B : Natural renames Container'Unrestricted_Access.all.Busy;
1363 begin
1364 -- The value of the Node component influences the behavior of the First
1365 -- and Last selector functions of the iterator object. When the Node
1366 -- component is 0 (as is the case here), this means the iterator object
1367 -- was constructed without a start expression. This is a complete
1368 -- iterator, meaning that the iteration starts from the (logical)
1369 -- beginning of the sequence of items.
1371 -- Note: For a forward iterator, Container.First is the beginning, and
1372 -- for a reverse iterator, Container.Last is the beginning.
1374 return It : constant Iterator :=
1375 Iterator'(Limited_Controlled with
1376 Container => Container'Unrestricted_Access,
1377 Node => 0)
1379 B := B + 1;
1380 end return;
1381 end Iterate;
1383 function Iterate (Container : Set; Start : Cursor)
1384 return Set_Iterator_Interfaces.Reversible_Iterator'class
1386 B : Natural renames Container'Unrestricted_Access.all.Busy;
1388 begin
1389 -- It was formerly the case that when Start = No_Element, the partial
1390 -- iterator was defined to behave the same as for a complete iterator,
1391 -- and iterate over the entire sequence of items. However, those
1392 -- semantics were unintuitive and arguably error-prone (it is too easy
1393 -- to accidentally create an endless loop), and so they were changed,
1394 -- per the ARG meeting in Denver on 2011/11. However, there was no
1395 -- consensus about what positive meaning this corner case should have,
1396 -- and so it was decided to simply raise an exception. This does imply,
1397 -- however, that it is not possible to use a partial iterator to specify
1398 -- an empty sequence of items.
1400 if Start = No_Element then
1401 raise Constraint_Error with
1402 "Start position for iterator equals No_Element";
1403 end if;
1405 if Start.Container /= Container'Unrestricted_Access then
1406 raise Program_Error with
1407 "Start cursor of Iterate designates wrong set";
1408 end if;
1410 pragma Assert (Vet (Container, Start.Node),
1411 "Start cursor of Iterate is bad");
1413 -- The value of the Node component influences the behavior of the First
1414 -- and Last selector functions of the iterator object. When the Node
1415 -- component is positive (as is the case here), it means that this
1416 -- is a partial iteration, over a subset of the complete sequence of
1417 -- items. The iterator object was constructed with a start expression,
1418 -- indicating the position from which the iteration begins. (Note that
1419 -- the start position has the same value irrespective of whether this
1420 -- is a forward or reverse iteration.)
1422 return It : constant Iterator :=
1423 Iterator'(Limited_Controlled with
1424 Container => Container'Unrestricted_Access,
1425 Node => Start.Node)
1427 B := B + 1;
1428 end return;
1429 end Iterate;
1431 ----------
1432 -- Last --
1433 ----------
1435 function Last (Container : Set) return Cursor is
1436 begin
1437 return (if Container.Last = 0 then No_Element
1438 else Cursor'(Container'Unrestricted_Access, Container.Last));
1439 end Last;
1441 function Last (Object : Iterator) return Cursor is
1442 begin
1443 -- The value of the iterator object's Node component influences the
1444 -- behavior of the Last (and First) selector function.
1446 -- When the Node component is 0, this means the iterator object was
1447 -- constructed without a start expression, in which case the (reverse)
1448 -- iteration starts from the (logical) beginning of the entire sequence
1449 -- (corresponding to Container.Last, for a reverse iterator).
1451 -- Otherwise, this is iteration over a partial sequence of items. When
1452 -- the Node component is positive, the iterator object was constructed
1453 -- with a start expression, that specifies the position from which the
1454 -- (reverse) partial iteration begins.
1456 if Object.Node = 0 then
1457 return Bounded_Ordered_Sets.Last (Object.Container.all);
1458 else
1459 return Cursor'(Object.Container, Object.Node);
1460 end if;
1461 end Last;
1463 ------------------
1464 -- Last_Element --
1465 ------------------
1467 function Last_Element (Container : Set) return Element_Type is
1468 begin
1469 if Container.Last = 0 then
1470 raise Constraint_Error with "set is empty";
1471 end if;
1473 return Container.Nodes (Container.Last).Element;
1474 end Last_Element;
1476 ----------
1477 -- Left --
1478 ----------
1480 function Left (Node : Node_Type) return Count_Type is
1481 begin
1482 return Node.Left;
1483 end Left;
1485 ------------
1486 -- Length --
1487 ------------
1489 function Length (Container : Set) return Count_Type is
1490 begin
1491 return Container.Length;
1492 end Length;
1494 ----------
1495 -- Move --
1496 ----------
1498 procedure Move (Target : in out Set; Source : in out Set) is
1499 begin
1500 if Target'Address = Source'Address then
1501 return;
1502 end if;
1504 if Source.Busy > 0 then
1505 raise Program_Error with
1506 "attempt to tamper with cursors (container is busy)";
1507 end if;
1509 Target.Assign (Source);
1510 Source.Clear;
1511 end Move;
1513 ----------
1514 -- Next --
1515 ----------
1517 function Next (Position : Cursor) return Cursor is
1518 begin
1519 if Position = No_Element then
1520 return No_Element;
1521 end if;
1523 pragma Assert (Vet (Position.Container.all, Position.Node),
1524 "bad cursor in Next");
1526 declare
1527 Node : constant Count_Type :=
1528 Tree_Operations.Next (Position.Container.all, Position.Node);
1530 begin
1531 if Node = 0 then
1532 return No_Element;
1533 end if;
1535 return Cursor'(Position.Container, Node);
1536 end;
1537 end Next;
1539 procedure Next (Position : in out Cursor) is
1540 begin
1541 Position := Next (Position);
1542 end Next;
1544 function Next (Object : Iterator; Position : Cursor) return Cursor is
1545 begin
1546 if Position.Container = null then
1547 return No_Element;
1548 end if;
1550 if Position.Container /= Object.Container then
1551 raise Program_Error with
1552 "Position cursor of Next designates wrong set";
1553 end if;
1555 return Next (Position);
1556 end Next;
1558 -------------
1559 -- Overlap --
1560 -------------
1562 function Overlap (Left, Right : Set) return Boolean
1563 renames Set_Ops.Set_Overlap;
1565 ------------
1566 -- Parent --
1567 ------------
1569 function Parent (Node : Node_Type) return Count_Type is
1570 begin
1571 return Node.Parent;
1572 end Parent;
1574 --------------
1575 -- Previous --
1576 --------------
1578 function Previous (Position : Cursor) return Cursor is
1579 begin
1580 if Position = No_Element then
1581 return No_Element;
1582 end if;
1584 pragma Assert (Vet (Position.Container.all, Position.Node),
1585 "bad cursor in Previous");
1587 declare
1588 Node : constant Count_Type :=
1589 Tree_Operations.Previous (Position.Container.all, Position.Node);
1590 begin
1591 return (if Node = 0 then No_Element
1592 else Cursor'(Position.Container, Node));
1593 end;
1594 end Previous;
1596 procedure Previous (Position : in out Cursor) is
1597 begin
1598 Position := Previous (Position);
1599 end Previous;
1601 function Previous (Object : Iterator; Position : Cursor) return Cursor is
1602 begin
1603 if Position.Container = null then
1604 return No_Element;
1605 end if;
1607 if Position.Container /= Object.Container then
1608 raise Program_Error with
1609 "Position cursor of Previous designates wrong set";
1610 end if;
1612 return Previous (Position);
1613 end Previous;
1615 -------------------
1616 -- Query_Element --
1617 -------------------
1619 procedure Query_Element
1620 (Position : Cursor;
1621 Process : not null access procedure (Element : Element_Type))
1623 begin
1624 if Position.Node = 0 then
1625 raise Constraint_Error with "Position cursor equals No_Element";
1626 end if;
1628 pragma Assert (Vet (Position.Container.all, Position.Node),
1629 "bad cursor in Query_Element");
1631 declare
1632 S : Set renames Position.Container.all;
1633 B : Natural renames S.Busy;
1634 L : Natural renames S.Lock;
1636 begin
1637 B := B + 1;
1638 L := L + 1;
1640 begin
1641 Process (S.Nodes (Position.Node).Element);
1642 exception
1643 when others =>
1644 L := L - 1;
1645 B := B - 1;
1646 raise;
1647 end;
1649 L := L - 1;
1650 B := B - 1;
1651 end;
1652 end Query_Element;
1654 ----------
1655 -- Read --
1656 ----------
1658 procedure Read
1659 (Stream : not null access Root_Stream_Type'Class;
1660 Container : out Set)
1662 procedure Read_Element (Node : in out Node_Type);
1663 pragma Inline (Read_Element);
1665 procedure Allocate is
1666 new Tree_Operations.Generic_Allocate (Read_Element);
1668 procedure Read_Elements is
1669 new Tree_Operations.Generic_Read (Allocate);
1671 ------------------
1672 -- Read_Element --
1673 ------------------
1675 procedure Read_Element (Node : in out Node_Type) is
1676 begin
1677 Element_Type'Read (Stream, Node.Element);
1678 end Read_Element;
1680 -- Start of processing for Read
1682 begin
1683 Read_Elements (Stream, Container);
1684 end Read;
1686 procedure Read
1687 (Stream : not null access Root_Stream_Type'Class;
1688 Item : out Cursor)
1690 begin
1691 raise Program_Error with "attempt to stream set cursor";
1692 end Read;
1694 procedure Read
1695 (Stream : not null access Root_Stream_Type'Class;
1696 Item : out Constant_Reference_Type)
1698 begin
1699 raise Program_Error with "attempt to stream reference";
1700 end Read;
1702 -------------
1703 -- Replace --
1704 -------------
1706 procedure Replace (Container : in out Set; New_Item : Element_Type) is
1707 Node : constant Count_Type := Element_Keys.Find (Container, New_Item);
1709 begin
1710 if Node = 0 then
1711 raise Constraint_Error with
1712 "attempt to replace element not in set";
1713 end if;
1715 if Container.Lock > 0 then
1716 raise Program_Error with
1717 "attempt to tamper with elements (set is locked)";
1718 end if;
1720 Container.Nodes (Node).Element := New_Item;
1721 end Replace;
1723 ---------------------
1724 -- Replace_Element --
1725 ---------------------
1727 procedure Replace_Element
1728 (Container : in out Set;
1729 Index : Count_Type;
1730 Item : Element_Type)
1732 pragma Assert (Index /= 0);
1734 function New_Node return Count_Type;
1735 pragma Inline (New_Node);
1737 procedure Local_Insert_Post is
1738 new Element_Keys.Generic_Insert_Post (New_Node);
1740 procedure Local_Insert_Sans_Hint is
1741 new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
1743 procedure Local_Insert_With_Hint is
1744 new Element_Keys.Generic_Conditional_Insert_With_Hint
1745 (Local_Insert_Post,
1746 Local_Insert_Sans_Hint);
1748 Nodes : Nodes_Type renames Container.Nodes;
1749 Node : Node_Type renames Nodes (Index);
1751 --------------
1752 -- New_Node --
1753 --------------
1755 function New_Node return Count_Type is
1756 begin
1757 Node.Element := Item;
1758 Node.Color := Red_Black_Trees.Red;
1759 Node.Parent := 0;
1760 Node.Right := 0;
1761 Node.Left := 0;
1762 return Index;
1763 end New_Node;
1765 Hint : Count_Type;
1766 Result : Count_Type;
1767 Inserted : Boolean;
1768 Compare : Boolean;
1770 -- Per AI05-0022, the container implementation is required to detect
1771 -- element tampering by a generic actual subprogram.
1773 B : Natural renames Container.Busy;
1774 L : Natural renames Container.Lock;
1776 -- Start of processing for Replace_Element
1778 begin
1779 -- Replace_Element assigns value Item to the element designated by Node,
1780 -- per certain semantic constraints, described as follows.
1782 -- If Item is equivalent to the element, then element is replaced and
1783 -- there's nothing else to do. This is the easy case.
1785 -- If Item is not equivalent, then the node will (possibly) have to move
1786 -- to some other place in the tree. This is slighly more complicated,
1787 -- because we must ensure that Item is not equivalent to some other
1788 -- element in the tree (in which case, the replacement is not allowed).
1790 -- Determine whether Item is equivalent to element on the specified
1791 -- node.
1793 begin
1794 B := B + 1;
1795 L := L + 1;
1797 Compare := (if Item < Node.Element then False
1798 elsif Node.Element < Item then False
1799 else True);
1801 L := L - 1;
1802 B := B - 1;
1804 exception
1805 when others =>
1806 L := L - 1;
1807 B := B - 1;
1808 raise;
1809 end;
1811 if Compare then
1813 -- Item is equivalent to the node's element, so we will not have to
1814 -- move the node.
1816 if Container.Lock > 0 then
1817 raise Program_Error with
1818 "attempt to tamper with elements (set is locked)";
1819 end if;
1821 Node.Element := Item;
1822 return;
1823 end if;
1825 -- The replacement Item is not equivalent to the element on the
1826 -- specified node, which means that it will need to be re-inserted in a
1827 -- different position in the tree. We must now determine whether Item is
1828 -- equivalent to some other element in the tree (which would prohibit
1829 -- the assignment and hence the move).
1831 -- Ceiling returns the smallest element equivalent or greater than the
1832 -- specified Item; if there is no such element, then it returns 0.
1834 Hint := Element_Keys.Ceiling (Container, Item);
1836 if Hint /= 0 then -- Item <= Nodes (Hint).Element
1837 begin
1838 B := B + 1;
1839 L := L + 1;
1841 Compare := Item < Nodes (Hint).Element;
1843 L := L - 1;
1844 B := B - 1;
1846 exception
1847 when others =>
1848 L := L - 1;
1849 B := B - 1;
1850 raise;
1851 end;
1853 -- Item is equivalent to Nodes (Hint).Element
1855 if not Compare then
1857 -- Ceiling returns an element that is equivalent or greater than
1858 -- Item. If Item is "not less than" the element, then by
1859 -- elimination we know that Item is equivalent to the element.
1861 -- But this means that it is not possible to assign the value of
1862 -- Item to the specified element (on Node), because a different
1863 -- element (on Hint) equivalent to Item already exsits. (Were we
1864 -- to change Node's element value, we would have to move Node, but
1865 -- we would be unable to move the Node, because its new position
1866 -- in the tree is already occupied by an equivalent element.)
1868 raise Program_Error with "attempt to replace existing element";
1869 end if;
1871 -- Item is not equivalent to any other element in the tree
1872 -- (specifically, it is less than Nodes (Hint).Element), so it is
1873 -- safe to assign the value of Item to Node.Element. This means that
1874 -- the node will have to move to a different position in the tree
1875 -- (because its element will have a different value).
1877 -- The nearest (greater) neighbor of Item is Hint. This will be the
1878 -- insertion position of Node (because its element will have Item as
1879 -- its new value).
1881 -- If Node equals Hint, the relative position of Node does not
1882 -- change. This allows us to perform an optimization: we need not
1883 -- remove Node from the tree and then reinsert it with its new value,
1884 -- because it would only be placed in the exact same position.
1886 if Hint = Index then
1887 if Container.Lock > 0 then
1888 raise Program_Error with
1889 "attempt to tamper with elements (set is locked)";
1890 end if;
1892 Node.Element := Item;
1893 return;
1894 end if;
1895 end if;
1897 -- If we get here, it is because Item was greater than all elements in
1898 -- the tree (Hint = 0), or because Item was less than some element at a
1899 -- different place in the tree (Item < Nodes (Hint).Element and Hint /=
1900 -- Index). In either case, we remove Node from the tree and then insert
1901 -- Item into the tree, onto the same Node.
1903 Tree_Operations.Delete_Node_Sans_Free (Container, Index);
1905 Local_Insert_With_Hint
1906 (Tree => Container,
1907 Position => Hint,
1908 Key => Item,
1909 Node => Result,
1910 Inserted => Inserted);
1912 pragma Assert (Inserted);
1913 pragma Assert (Result = Index);
1914 end Replace_Element;
1916 procedure Replace_Element
1917 (Container : in out Set;
1918 Position : Cursor;
1919 New_Item : Element_Type)
1921 begin
1922 if Position.Node = 0 then
1923 raise Constraint_Error with
1924 "Position cursor equals No_Element";
1925 end if;
1927 if Position.Container /= Container'Unrestricted_Access then
1928 raise Program_Error with
1929 "Position cursor designates wrong set";
1930 end if;
1932 pragma Assert (Vet (Container, Position.Node),
1933 "bad cursor in Replace_Element");
1935 Replace_Element (Container, Position.Node, New_Item);
1936 end Replace_Element;
1938 ---------------------
1939 -- Reverse_Iterate --
1940 ---------------------
1942 procedure Reverse_Iterate
1943 (Container : Set;
1944 Process : not null access procedure (Position : Cursor))
1946 procedure Process_Node (Node : Count_Type);
1947 pragma Inline (Process_Node);
1949 procedure Local_Reverse_Iterate is
1950 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1952 ------------------
1953 -- Process_Node --
1954 ------------------
1956 procedure Process_Node (Node : Count_Type) is
1957 begin
1958 Process (Cursor'(Container'Unrestricted_Access, Node));
1959 end Process_Node;
1961 S : Set renames Container'Unrestricted_Access.all;
1962 B : Natural renames S.Busy;
1964 -- Start of processing for Reverse_Iterate
1966 begin
1967 B := B + 1;
1969 begin
1970 Local_Reverse_Iterate (S);
1971 exception
1972 when others =>
1973 B := B - 1;
1974 raise;
1975 end;
1977 B := B - 1;
1978 end Reverse_Iterate;
1980 -----------
1981 -- Right --
1982 -----------
1984 function Right (Node : Node_Type) return Count_Type is
1985 begin
1986 return Node.Right;
1987 end Right;
1989 ---------------
1990 -- Set_Color --
1991 ---------------
1993 procedure Set_Color
1994 (Node : in out Node_Type;
1995 Color : Red_Black_Trees.Color_Type)
1997 begin
1998 Node.Color := Color;
1999 end Set_Color;
2001 --------------
2002 -- Set_Left --
2003 --------------
2005 procedure Set_Left (Node : in out Node_Type; Left : Count_Type) is
2006 begin
2007 Node.Left := Left;
2008 end Set_Left;
2010 ----------------
2011 -- Set_Parent --
2012 ----------------
2014 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type) is
2015 begin
2016 Node.Parent := Parent;
2017 end Set_Parent;
2019 ---------------
2020 -- Set_Right --
2021 ---------------
2023 procedure Set_Right (Node : in out Node_Type; Right : Count_Type) is
2024 begin
2025 Node.Right := Right;
2026 end Set_Right;
2028 --------------------------
2029 -- Symmetric_Difference --
2030 --------------------------
2032 procedure Symmetric_Difference (Target : in out Set; Source : Set)
2033 renames Set_Ops.Set_Symmetric_Difference;
2035 function Symmetric_Difference (Left, Right : Set) return Set
2036 renames Set_Ops.Set_Symmetric_Difference;
2038 ------------
2039 -- To_Set --
2040 ------------
2042 function To_Set (New_Item : Element_Type) return Set is
2043 Node : Count_Type;
2044 Inserted : Boolean;
2045 begin
2046 return S : Set (1) do
2047 Insert_Sans_Hint (S, New_Item, Node, Inserted);
2048 pragma Assert (Inserted);
2049 end return;
2050 end To_Set;
2052 -----------
2053 -- Union --
2054 -----------
2056 procedure Union (Target : in out Set; Source : Set)
2057 renames Set_Ops.Set_Union;
2059 function Union (Left, Right : Set) return Set
2060 renames Set_Ops.Set_Union;
2062 -----------
2063 -- Write --
2064 -----------
2066 procedure Write
2067 (Stream : not null access Root_Stream_Type'Class;
2068 Container : Set)
2070 procedure Write_Element
2071 (Stream : not null access Root_Stream_Type'Class;
2072 Node : Node_Type);
2073 pragma Inline (Write_Element);
2075 procedure Write_Elements is
2076 new Tree_Operations.Generic_Write (Write_Element);
2078 -------------------
2079 -- Write_Element --
2080 -------------------
2082 procedure Write_Element
2083 (Stream : not null access Root_Stream_Type'Class;
2084 Node : Node_Type)
2086 begin
2087 Element_Type'Write (Stream, Node.Element);
2088 end Write_Element;
2090 -- Start of processing for Write
2092 begin
2093 Write_Elements (Stream, Container);
2094 end Write;
2096 procedure Write
2097 (Stream : not null access Root_Stream_Type'Class;
2098 Item : Cursor)
2100 begin
2101 raise Program_Error with "attempt to stream set cursor";
2102 end Write;
2104 procedure Write
2105 (Stream : not null access Root_Stream_Type'Class;
2106 Item : Constant_Reference_Type)
2108 begin
2109 raise Program_Error with "attempt to stream reference";
2110 end Write;
2112 end Ada.Containers.Bounded_Ordered_Sets;