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