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

Subversion Repositories openrisc

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

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

Line No. Rev Author Line
1 706 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT LIBRARY COMPONENTS                          --
4
--                                                                          --
5
--    A D A . C O N T A I N E R S . F O R M A L _ H A S H E D _ M A P S     --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 2010-2011, Free Software Foundation, Inc.         --
10
--                                                                          --
11
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
12
-- terms of the  GNU General Public License as published  by the Free Soft- --
13
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
14
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16
-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
17
--                                                                          --
18
-- As a special exception under Section 7 of GPL version 3, you are granted --
19
-- additional permissions described in the GCC Runtime Library Exception,   --
20
-- version 3.1, as published by the Free Software Foundation.               --
21
--                                                                          --
22
-- You should have received a copy of the GNU General Public License and    --
23
-- a copy of the GCC Runtime Library Exception along with this program;     --
24
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
25
-- <http://www.gnu.org/licenses/>.                                          --
26
------------------------------------------------------------------------------
27
 
28
with Ada.Containers.Hash_Tables.Generic_Bounded_Operations;
29
pragma Elaborate_All (Ada.Containers.Hash_Tables.Generic_Bounded_Operations);
30
 
31
with Ada.Containers.Hash_Tables.Generic_Bounded_Keys;
32
pragma Elaborate_All (Ada.Containers.Hash_Tables.Generic_Bounded_Keys);
33
 
34
with Ada.Containers.Prime_Numbers; use Ada.Containers.Prime_Numbers;
35
 
36
with System;  use type System.Address;
37
 
38
package body Ada.Containers.Formal_Hashed_Maps is
39
 
40
   -----------------------
41
   -- Local Subprograms --
42
   -----------------------
43
 
44
   --  All local subprograms require comments ???
45
 
46
   function Equivalent_Keys
47
     (Key  : Key_Type;
48
      Node : Node_Type) return Boolean;
49
   pragma Inline (Equivalent_Keys);
50
 
51
   procedure Free
52
     (HT : in out Map;
53
      X  : Count_Type);
54
 
55
   generic
56
      with procedure Set_Element (Node : in out Node_Type);
57
   procedure Generic_Allocate
58
     (HT   : in out Map;
59
      Node : out Count_Type);
60
 
61
   function Hash_Node (Node : Node_Type) return Hash_Type;
62
   pragma Inline (Hash_Node);
63
 
64
   function Next (Node : Node_Type) return Count_Type;
65
   pragma Inline (Next);
66
 
67
   procedure Set_Next (Node : in out Node_Type; Next : Count_Type);
68
   pragma Inline (Set_Next);
69
 
70
   function Vet (Container : Map; Position : Cursor) return Boolean;
71
 
72
   --------------------------
73
   -- Local Instantiations --
74
   --------------------------
75
 
76
   package HT_Ops is
77
     new Hash_Tables.Generic_Bounded_Operations
78
       (HT_Types  => HT_Types,
79
        Hash_Node => Hash_Node,
80
        Next      => Next,
81
        Set_Next  => Set_Next);
82
 
83
   package Key_Ops is
84
     new Hash_Tables.Generic_Bounded_Keys
85
       (HT_Types        => HT_Types,
86
        Next            => Next,
87
        Set_Next        => Set_Next,
88
        Key_Type        => Key_Type,
89
        Hash            => Hash,
90
        Equivalent_Keys => Equivalent_Keys);
91
 
92
   ---------
93
   -- "=" --
94
   ---------
95
 
96
   function "=" (Left, Right : Map) return Boolean is
97
   begin
98
      if Length (Left) /= Length (Right) then
99
         return False;
100
      end if;
101
 
102
      if Length (Left) = 0 then
103
         return True;
104
      end if;
105
 
106
      declare
107
         Node  : Count_Type;
108
         ENode : Count_Type;
109
 
110
      begin
111
         Node := Left.First.Node;
112
         while Node /= 0 loop
113
            ENode := Find (Container => Right,
114
                           Key       => Left.Nodes (Node).Key).Node;
115
 
116
            if ENode = 0 or else
117
              Right.Nodes (ENode).Element /= Left.Nodes (Node).Element
118
            then
119
               return False;
120
            end if;
121
 
122
            Node := HT_Ops.Next (Left, Node);
123
         end loop;
124
 
125
         return True;
126
      end;
127
   end "=";
128
 
129
   ------------
130
   -- Assign --
131
   ------------
132
 
133
   procedure Assign (Target : in out Map; Source : Map) is
134
      procedure Insert_Element (Source_Node : Count_Type);
135
      pragma Inline (Insert_Element);
136
 
137
      procedure Insert_Elements is
138
        new HT_Ops.Generic_Iteration (Insert_Element);
139
 
140
      --------------------
141
      -- Insert_Element --
142
      --------------------
143
 
144
      procedure Insert_Element (Source_Node : Count_Type) is
145
         N : Node_Type renames Source.Nodes (Source_Node);
146
      begin
147
         Target.Insert (N.Key, N.Element);
148
      end Insert_Element;
149
 
150
      --  Start of processing for Assign
151
 
152
   begin
153
      if Target'Address = Source'Address then
154
         return;
155
      end if;
156
 
157
      if Target.Capacity < Length (Source) then
158
         raise Constraint_Error with  -- correct exception ???
159
           "Source length exceeds Target capacity";
160
      end if;
161
 
162
      --  Check busy bits
163
 
164
      Clear (Target);
165
 
166
      Insert_Elements (Source);
167
   end Assign;
168
 
169
   --------------
170
   -- Capacity --
171
   --------------
172
 
173
   function Capacity (Container : Map) return Count_Type is
174
   begin
175
      return Container.Nodes'Length;
176
   end Capacity;
177
 
178
   -----------
179
   -- Clear --
180
   -----------
181
 
182
   procedure Clear (Container : in out Map) is
183
   begin
184
      HT_Ops.Clear (Container);
185
   end Clear;
186
 
187
   --------------
188
   -- Contains --
189
   --------------
190
 
191
   function Contains (Container : Map; Key : Key_Type) return Boolean is
192
   begin
193
      return Find (Container, Key) /= No_Element;
194
   end Contains;
195
 
196
   ----------
197
   -- Copy --
198
   ----------
199
 
200
   function Copy
201
     (Source   : Map;
202
      Capacity : Count_Type := 0) return Map
203
   is
204
      C      : constant Count_Type :=
205
                 Count_Type'Max (Capacity, Source.Capacity);
206
      H      : Hash_Type;
207
      N      : Count_Type;
208
      Target : Map (C, Source.Modulus);
209
      Cu     : Cursor;
210
 
211
   begin
212
      Target.Length := Source.Length;
213
      Target.Free := Source.Free;
214
 
215
      H := 1;
216
      while H <= Source.Modulus loop
217
         Target.Buckets (H) := Source.Buckets (H);
218
         H := H + 1;
219
      end loop;
220
 
221
      N := 1;
222
      while N <= Source.Capacity loop
223
         Target.Nodes (N) := Source.Nodes (N);
224
         N := N + 1;
225
      end loop;
226
 
227
      while N <= C loop
228
         Cu := (Node => N);
229
         Free (Target, Cu.Node);
230
         N := N + 1;
231
      end loop;
232
 
233
      return Target;
234
   end Copy;
235
 
236
   ---------------------
237
   -- Default_Modulus --
238
   ---------------------
239
 
240
   function Default_Modulus (Capacity : Count_Type) return Hash_Type is
241
   begin
242
      return To_Prime (Capacity);
243
   end Default_Modulus;
244
 
245
   ------------
246
   -- Delete --
247
   ------------
248
 
249
   procedure Delete (Container : in out Map; Key : Key_Type) is
250
      X : Count_Type;
251
 
252
   begin
253
      Key_Ops.Delete_Key_Sans_Free (Container, Key, X);
254
 
255
      if X = 0 then
256
         raise Constraint_Error with "attempt to delete key not in map";
257
      end if;
258
 
259
      Free (Container, X);
260
   end Delete;
261
 
262
   procedure Delete (Container : in out Map; Position : in out Cursor) is
263
   begin
264
      if not Has_Element (Container, Position) then
265
         raise Constraint_Error with
266
           "Position cursor of Delete has no element";
267
      end if;
268
 
269
      if Container.Busy > 0 then
270
         raise Program_Error with
271
           "Delete attempted to tamper with elements (map is busy)";
272
      end if;
273
 
274
      pragma Assert (Vet (Container, Position), "bad cursor in Delete");
275
 
276
      HT_Ops.Delete_Node_Sans_Free (Container, Position.Node);
277
 
278
      Free (Container, Position.Node);
279
   end Delete;
280
 
281
   -------------
282
   -- Element --
283
   -------------
284
 
285
   function Element (Container : Map; Key : Key_Type) return Element_Type is
286
      Node : constant Count_Type := Find (Container, Key).Node;
287
 
288
   begin
289
      if Node = 0 then
290
         raise Constraint_Error with
291
           "no element available because key not in map";
292
      end if;
293
 
294
      return Container.Nodes (Node).Element;
295
   end Element;
296
 
297
   function Element (Container : Map; Position : Cursor) return Element_Type is
298
   begin
299
      if not Has_Element (Container, Position) then
300
         raise Constraint_Error with "Position cursor equals No_Element";
301
      end if;
302
 
303
      pragma Assert (Vet (Container, Position),
304
                     "bad cursor in function Element");
305
 
306
      return Container.Nodes (Position.Node).Element;
307
   end Element;
308
 
309
   ---------------------
310
   -- Equivalent_Keys --
311
   ---------------------
312
 
313
   function Equivalent_Keys
314
     (Key  : Key_Type;
315
      Node : Node_Type) return Boolean
316
   is
317
   begin
318
      return Equivalent_Keys (Key, Node.Key);
319
   end Equivalent_Keys;
320
 
321
   function Equivalent_Keys
322
     (Left   : Map;
323
      CLeft  : Cursor;
324
      Right  : Map;
325
      CRight : Cursor) return Boolean
326
   is
327
   begin
328
      if not Has_Element (Left, CLeft) then
329
         raise Constraint_Error with
330
           "Left cursor of Equivalent_Keys has no element";
331
      end if;
332
 
333
      if not Has_Element (Right, CRight) then
334
         raise Constraint_Error with
335
           "Right cursor of Equivalent_Keys has no element";
336
      end if;
337
 
338
      pragma Assert (Vet (Left, CLeft),
339
                     "Left cursor of Equivalent_Keys is bad");
340
      pragma Assert (Vet (Right, CRight),
341
                     "Right cursor of Equivalent_Keys is bad");
342
 
343
      declare
344
         LN : Node_Type renames Left.Nodes (CLeft.Node);
345
         RN : Node_Type renames Right.Nodes (CRight.Node);
346
      begin
347
         return Equivalent_Keys (LN.Key, RN.Key);
348
      end;
349
   end Equivalent_Keys;
350
 
351
   function Equivalent_Keys
352
     (Left  : Map;
353
      CLeft : Cursor;
354
      Right : Key_Type) return Boolean
355
   is
356
   begin
357
      if not Has_Element (Left, CLeft) then
358
         raise Constraint_Error with
359
           "Left cursor of Equivalent_Keys has no element";
360
      end if;
361
 
362
      pragma Assert (Vet (Left, CLeft),
363
                     "Left cursor in Equivalent_Keys is bad");
364
 
365
      declare
366
         LN : Node_Type renames Left.Nodes (CLeft.Node);
367
      begin
368
         return Equivalent_Keys (LN.Key, Right);
369
      end;
370
   end Equivalent_Keys;
371
 
372
   function Equivalent_Keys
373
     (Left   : Key_Type;
374
      Right  : Map;
375
      CRight : Cursor) return Boolean
376
   is
377
   begin
378
      if Has_Element (Right, CRight) then
379
         raise Constraint_Error with
380
           "Right cursor of Equivalent_Keys has no element";
381
      end if;
382
 
383
      pragma Assert (Vet (Right, CRight),
384
                     "Right cursor of Equivalent_Keys is bad");
385
 
386
      declare
387
         RN : Node_Type renames Right.Nodes (CRight.Node);
388
 
389
      begin
390
         return Equivalent_Keys (Left, RN.Key);
391
      end;
392
   end Equivalent_Keys;
393
 
394
   -------------
395
   -- Exclude --
396
   -------------
397
 
398
   procedure Exclude (Container : in out Map; Key : Key_Type) is
399
      X : Count_Type;
400
   begin
401
      Key_Ops.Delete_Key_Sans_Free (Container, Key, X);
402
      Free (Container, X);
403
   end Exclude;
404
 
405
   ----------
406
   -- Find --
407
   ----------
408
 
409
   function Find (Container : Map; Key : Key_Type) return Cursor is
410
      Node : constant Count_Type :=
411
               Key_Ops.Find (Container, Key);
412
 
413
   begin
414
      if Node = 0 then
415
         return No_Element;
416
      end if;
417
 
418
      return (Node => Node);
419
   end Find;
420
 
421
   -----------
422
   -- First --
423
   -----------
424
 
425
   function First (Container : Map) return Cursor is
426
      Node : constant Count_Type := HT_Ops.First (Container);
427
 
428
   begin
429
      if Node = 0 then
430
         return No_Element;
431
      end if;
432
 
433
      return (Node => Node);
434
   end First;
435
 
436
   ----------
437
   -- Free --
438
   ----------
439
 
440
   procedure Free (HT : in out Map; X : Count_Type) is
441
   begin
442
      HT.Nodes (X).Has_Element := False;
443
      HT_Ops.Free (HT, X);
444
   end Free;
445
 
446
   ----------------------
447
   -- Generic_Allocate --
448
   ----------------------
449
 
450
   procedure Generic_Allocate (HT : in out Map; Node : out Count_Type) is
451
 
452
      procedure Allocate is
453
        new HT_Ops.Generic_Allocate (Set_Element);
454
 
455
   begin
456
      Allocate (HT, Node);
457
      HT.Nodes (Node).Has_Element := True;
458
   end Generic_Allocate;
459
 
460
   -----------------
461
   -- Has_Element --
462
   -----------------
463
 
464
   function Has_Element (Container : Map; Position : Cursor) return Boolean is
465
   begin
466
      if Position.Node = 0 or else
467
        not Container.Nodes (Position.Node).Has_Element then
468
         return False;
469
      end if;
470
 
471
      return True;
472
   end Has_Element;
473
 
474
   ---------------
475
   -- Hash_Node --
476
   ---------------
477
 
478
   function Hash_Node (Node : Node_Type) return Hash_Type is
479
   begin
480
      return Hash (Node.Key);
481
   end Hash_Node;
482
 
483
   -------------
484
   -- Include --
485
   -------------
486
 
487
   procedure Include
488
     (Container : in out Map;
489
      Key       : Key_Type;
490
      New_Item  : Element_Type)
491
   is
492
      Position : Cursor;
493
      Inserted : Boolean;
494
 
495
   begin
496
      Insert (Container, Key, New_Item, Position, Inserted);
497
 
498
      if not Inserted then
499
         if Container.Lock > 0 then
500
            raise Program_Error with
501
              "Include attempted to tamper with cursors (map is locked)";
502
         end if;
503
 
504
         declare
505
            N : Node_Type renames Container.Nodes (Position.Node);
506
         begin
507
            N.Key := Key;
508
            N.Element := New_Item;
509
         end;
510
      end if;
511
   end Include;
512
 
513
   ------------
514
   -- Insert --
515
   ------------
516
 
517
   procedure Insert
518
     (Container : in out Map;
519
      Key       : Key_Type;
520
      Position  : out Cursor;
521
      Inserted  : out Boolean)
522
   is
523
      procedure Assign_Key (Node : in out Node_Type);
524
      pragma Inline (Assign_Key);
525
 
526
      function New_Node return Count_Type;
527
      pragma Inline (New_Node);
528
 
529
      procedure Local_Insert is
530
        new Key_Ops.Generic_Conditional_Insert (New_Node);
531
 
532
      procedure Allocate is
533
        new Generic_Allocate (Assign_Key);
534
 
535
      -----------------
536
      --  Assign_Key --
537
      -----------------
538
 
539
      procedure Assign_Key (Node : in out Node_Type) is
540
      begin
541
         Node.Key := Key;
542
 
543
         --  What is following commented out line doing here ???
544
         --  Node.Element := New_Item;
545
      end Assign_Key;
546
 
547
      --------------
548
      -- New_Node --
549
      --------------
550
 
551
      function New_Node return Count_Type is
552
         Result : Count_Type;
553
      begin
554
         Allocate (Container, Result);
555
         return Result;
556
      end New_Node;
557
 
558
   --  Start of processing for Insert
559
 
560
   begin
561
 
562
      Local_Insert (Container, Key, Position.Node, Inserted);
563
   end Insert;
564
 
565
   procedure Insert
566
     (Container : in out Map;
567
      Key       : Key_Type;
568
      New_Item  : Element_Type;
569
      Position  : out Cursor;
570
      Inserted  : out Boolean)
571
   is
572
      procedure Assign_Key (Node : in out Node_Type);
573
      pragma Inline (Assign_Key);
574
 
575
      function New_Node return Count_Type;
576
      pragma Inline (New_Node);
577
 
578
      procedure Local_Insert is
579
        new Key_Ops.Generic_Conditional_Insert (New_Node);
580
 
581
      procedure Allocate is
582
        new Generic_Allocate (Assign_Key);
583
 
584
      -----------------
585
      --  Assign_Key --
586
      -----------------
587
 
588
      procedure Assign_Key (Node : in out Node_Type) is
589
      begin
590
         Node.Key := Key;
591
         Node.Element := New_Item;
592
      end Assign_Key;
593
 
594
      --------------
595
      -- New_Node --
596
      --------------
597
 
598
      function New_Node return Count_Type is
599
         Result : Count_Type;
600
      begin
601
         Allocate (Container, Result);
602
         return Result;
603
      end New_Node;
604
 
605
   --  Start of processing for Insert
606
 
607
   begin
608
      Local_Insert (Container, Key, Position.Node, Inserted);
609
   end Insert;
610
 
611
   procedure Insert
612
     (Container : in out Map;
613
      Key       : Key_Type;
614
      New_Item  : Element_Type)
615
   is
616
      Position : Cursor;
617
      pragma Unreferenced (Position);
618
 
619
      Inserted : Boolean;
620
 
621
   begin
622
      Insert (Container, Key, New_Item, Position, Inserted);
623
 
624
      if not Inserted then
625
         raise Constraint_Error with
626
           "attempt to insert key already in map";
627
      end if;
628
   end Insert;
629
 
630
   --------------
631
   -- Is_Empty --
632
   --------------
633
 
634
   function Is_Empty (Container : Map) return Boolean is
635
   begin
636
      return Length (Container) = 0;
637
   end Is_Empty;
638
 
639
   -------------
640
   -- Iterate --
641
   -------------
642
 
643
   procedure Iterate
644
     (Container : Map;
645
      Process   : not null
646
                    access procedure (Container : Map; Position : Cursor))
647
   is
648
      procedure Process_Node (Node : Count_Type);
649
      pragma Inline (Process_Node);
650
 
651
      procedure Local_Iterate is new HT_Ops.Generic_Iteration (Process_Node);
652
 
653
      ------------------
654
      -- Process_Node --
655
      ------------------
656
 
657
      procedure Process_Node (Node : Count_Type) is
658
      begin
659
         Process (Container, (Node => Node));
660
      end Process_Node;
661
 
662
      B : Natural renames Container'Unrestricted_Access.Busy;
663
 
664
   --  Start of processing for Iterate
665
 
666
   begin
667
      B := B + 1;
668
 
669
      begin
670
         Local_Iterate (Container);
671
      exception
672
         when others =>
673
            B := B - 1;
674
            raise;
675
      end;
676
 
677
      B := B - 1;
678
   end Iterate;
679
 
680
   ---------
681
   -- Key --
682
   ---------
683
 
684
   function Key (Container : Map; Position : Cursor) return Key_Type is
685
   begin
686
      if not Has_Element (Container, Position) then
687
         raise Constraint_Error with
688
           "Position cursor of function Key has no element";
689
      end if;
690
 
691
      pragma Assert (Vet (Container, Position), "bad cursor in function Key");
692
 
693
      return Container.Nodes (Position.Node).Key;
694
   end Key;
695
 
696
   ----------
697
   -- Left --
698
   ----------
699
 
700
   function Left (Container : Map; Position : Cursor) return Map is
701
      Curs : Cursor;
702
      C    : Map (Container.Capacity, Container.Modulus) :=
703
               Copy (Container, Container.Capacity);
704
      Node : Count_Type;
705
 
706
   begin
707
      Curs := Position;
708
 
709
      if Curs = No_Element then
710
         return C;
711
      end if;
712
 
713
      if not Has_Element (Container, Curs) then
714
         raise Constraint_Error;
715
      end if;
716
 
717
      while Curs.Node /= 0 loop
718
         Node := Curs.Node;
719
         Delete (C, Curs);
720
         Curs := Next (Container, (Node => Node));
721
      end loop;
722
 
723
      return C;
724
   end Left;
725
 
726
   ------------
727
   -- Length --
728
   ------------
729
 
730
   function Length (Container : Map) return Count_Type is
731
   begin
732
      return Container.Length;
733
   end Length;
734
 
735
   ----------
736
   -- Move --
737
   ----------
738
 
739
   procedure Move
740
     (Target : in out Map;
741
      Source : in out Map)
742
   is
743
      NN   : HT_Types.Nodes_Type renames Source.Nodes;
744
      X, Y : Count_Type;
745
 
746
   begin
747
      if Target'Address = Source'Address then
748
         return;
749
      end if;
750
 
751
      if Target.Capacity < Length (Source) then
752
         raise Constraint_Error with  -- ???
753
           "Source length exceeds Target capacity";
754
      end if;
755
 
756
      if Source.Busy > 0 then
757
         raise Program_Error with
758
           "attempt to tamper with cursors of Source (list is busy)";
759
      end if;
760
 
761
      Clear (Target);
762
 
763
      if Source.Length = 0 then
764
         return;
765
      end if;
766
 
767
      X := HT_Ops.First (Source);
768
      while X /= 0 loop
769
         Insert (Target, NN (X).Key, NN (X).Element);  -- optimize???
770
 
771
         Y := HT_Ops.Next (Source, X);
772
 
773
         HT_Ops.Delete_Node_Sans_Free (Source, X);
774
         Free (Source, X);
775
 
776
         X := Y;
777
      end loop;
778
   end Move;
779
 
780
   ----------
781
   -- Next --
782
   ----------
783
 
784
   function Next (Node : Node_Type) return Count_Type is
785
   begin
786
      return Node.Next;
787
   end Next;
788
 
789
   function Next (Container : Map; Position : Cursor) return Cursor is
790
   begin
791
      if Position.Node = 0 then
792
         return No_Element;
793
      end if;
794
 
795
      if not Has_Element (Container, Position) then
796
         raise Constraint_Error
797
           with "Position has no element";
798
      end if;
799
 
800
      pragma Assert (Vet (Container, Position), "bad cursor in function Next");
801
 
802
      declare
803
         Node : constant Count_Type := HT_Ops.Next (Container, Position.Node);
804
 
805
      begin
806
         if Node = 0 then
807
            return No_Element;
808
         end if;
809
 
810
         return (Node => Node);
811
      end;
812
   end Next;
813
 
814
   procedure Next (Container : Map; Position : in out Cursor) is
815
   begin
816
      Position := Next (Container, Position);
817
   end Next;
818
 
819
   -------------
820
   -- Overlap --
821
   -------------
822
 
823
   function Overlap (Left, Right : Map) return Boolean is
824
      Left_Node  : Count_Type;
825
      Left_Nodes : Nodes_Type renames Left.Nodes;
826
 
827
   begin
828
      if Length (Right) = 0 or Length (Left) = 0 then
829
         return False;
830
      end if;
831
 
832
      if Left'Address = Right'Address then
833
         return True;
834
      end if;
835
 
836
      Left_Node := First (Left).Node;
837
      while Left_Node /= 0 loop
838
         declare
839
            N : Node_Type renames Left_Nodes (Left_Node);
840
            E : Key_Type renames N.Key;
841
         begin
842
            if Find (Right, E).Node /= 0 then
843
               return True;
844
            end if;
845
         end;
846
 
847
         Left_Node := HT_Ops.Next (Left, Left_Node);
848
      end loop;
849
 
850
      return False;
851
   end Overlap;
852
 
853
   -------------------
854
   -- Query_Element --
855
   -------------------
856
 
857
   procedure Query_Element
858
     (Container : in out Map;
859
      Position  : Cursor;
860
      Process   : not null access
861
                    procedure (Key : Key_Type; Element : Element_Type))
862
   is
863
   begin
864
      if not Has_Element (Container, Position) then
865
         raise Constraint_Error with
866
           "Position cursor of Query_Element has no element";
867
      end if;
868
 
869
      pragma Assert (Vet (Container, Position), "bad cursor in Query_Element");
870
 
871
      declare
872
         N : Node_Type renames Container.Nodes (Position.Node);
873
         B : Natural renames Container.Busy;
874
         L : Natural renames Container.Lock;
875
 
876
      begin
877
         B := B + 1;
878
         L := L + 1;
879
 
880
         declare
881
            K : Key_Type renames N.Key;
882
            E : Element_Type renames N.Element;
883
         begin
884
            Process (K, E);
885
         exception
886
            when others =>
887
               L := L - 1;
888
               B := B - 1;
889
               raise;
890
         end;
891
 
892
         L := L - 1;
893
         B := B - 1;
894
      end;
895
   end Query_Element;
896
 
897
   ----------
898
   -- Read --
899
   ----------
900
 
901
   procedure Read
902
     (Stream    : not null access Root_Stream_Type'Class;
903
      Container : out Map)
904
   is
905
      function Read_Node (Stream : not null access Root_Stream_Type'Class)
906
                          return Count_Type;
907
 
908
      procedure Read_Nodes is
909
        new HT_Ops.Generic_Read (Read_Node);
910
 
911
      ---------------
912
      -- Read_Node --
913
      ---------------
914
 
915
      function Read_Node
916
        (Stream : not null access Root_Stream_Type'Class) return Count_Type
917
      is
918
         procedure Read_Element (Node : in out Node_Type);
919
         pragma Inline (Read_Element);
920
 
921
         procedure Allocate is
922
           new Generic_Allocate (Read_Element);
923
 
924
         procedure Read_Element (Node : in out Node_Type) is
925
         begin
926
            Element_Type'Read (Stream, Node.Element);
927
         end Read_Element;
928
 
929
         Node : Count_Type;
930
 
931
      --  Start of processing for Read_Node
932
 
933
      begin
934
         Allocate (Container, Node);
935
         return Node;
936
      end Read_Node;
937
 
938
   --  Start of processing for Read
939
 
940
   begin
941
      Read_Nodes (Stream, Container);
942
   end Read;
943
 
944
   procedure Read
945
     (Stream : not null access Root_Stream_Type'Class;
946
      Item   : out Cursor)
947
   is
948
   begin
949
      raise Program_Error with "attempt to stream set cursor";
950
   end Read;
951
 
952
   -------------
953
   -- Replace --
954
   -------------
955
 
956
   procedure Replace
957
     (Container : in out Map;
958
      Key       : Key_Type;
959
      New_Item  : Element_Type)
960
   is
961
      Node : constant Count_Type := Key_Ops.Find (Container, Key);
962
 
963
   begin
964
      if Node = 0 then
965
         raise Constraint_Error with
966
           "attempt to replace key not in map";
967
      end if;
968
 
969
      if Container.Lock > 0 then
970
         raise Program_Error with
971
           "Replace attempted to tamper with cursors (map is locked)";
972
      end if;
973
 
974
      declare
975
         N : Node_Type renames Container.Nodes (Node);
976
      begin
977
         N.Key := Key;
978
         N.Element := New_Item;
979
      end;
980
   end Replace;
981
 
982
   ---------------------
983
   -- Replace_Element --
984
   ---------------------
985
 
986
   procedure Replace_Element
987
     (Container : in out Map;
988
      Position  : Cursor;
989
      New_Item  : Element_Type)
990
   is
991
   begin
992
      if not Has_Element (Container, Position) then
993
         raise Constraint_Error with
994
           "Position cursor of Replace_Element has no element";
995
      end if;
996
 
997
      if Container.Lock > 0 then
998
         raise Program_Error with
999
           "Replace_Element attempted to tamper with cursors (map is locked)";
1000
      end if;
1001
 
1002
      pragma Assert (Vet (Container, Position),
1003
                     "bad cursor in Replace_Element");
1004
 
1005
      Container.Nodes (Position.Node).Element := New_Item;
1006
   end Replace_Element;
1007
 
1008
   ----------------------
1009
   -- Reserve_Capacity --
1010
   ----------------------
1011
 
1012
   procedure Reserve_Capacity
1013
     (Container : in out Map;
1014
      Capacity  : Count_Type)
1015
   is
1016
   begin
1017
      if Capacity > Container.Capacity then
1018
         raise Capacity_Error with "requested capacity is too large";
1019
      end if;
1020
   end Reserve_Capacity;
1021
 
1022
   -----------
1023
   -- Right --
1024
   -----------
1025
 
1026
   function Right (Container : Map; Position : Cursor) return Map is
1027
      Curs : Cursor := First (Container);
1028
      C    : Map (Container.Capacity, Container.Modulus) :=
1029
               Copy (Container, Container.Capacity);
1030
      Node : Count_Type;
1031
 
1032
   begin
1033
      if Curs = No_Element then
1034
         Clear (C);
1035
         return C;
1036
      end if;
1037
 
1038
      if Position /= No_Element and not Has_Element (Container, Position) then
1039
         raise Constraint_Error;
1040
      end if;
1041
 
1042
      while Curs.Node /= Position.Node loop
1043
         Node := Curs.Node;
1044
         Delete (C, Curs);
1045
         Curs := Next (Container, (Node => Node));
1046
      end loop;
1047
 
1048
      return C;
1049
   end Right;
1050
 
1051
   --------------
1052
   -- Set_Next --
1053
   --------------
1054
 
1055
   procedure Set_Next (Node : in out Node_Type; Next : Count_Type) is
1056
   begin
1057
      Node.Next := Next;
1058
   end Set_Next;
1059
 
1060
   ------------------
1061
   -- Strict_Equal --
1062
   ------------------
1063
 
1064
   function Strict_Equal (Left, Right : Map) return Boolean is
1065
      CuL : Cursor := First (Left);
1066
      CuR : Cursor := First (Right);
1067
 
1068
   begin
1069
      if Length (Left) /= Length (Right) then
1070
         return False;
1071
      end if;
1072
 
1073
      while CuL.Node /= 0 or CuR.Node /= 0 loop
1074
         if CuL.Node /= CuR.Node or else
1075
           (Left.Nodes (CuL.Node).Element /=
1076
              Right.Nodes (CuR.Node).Element or
1077
              Left.Nodes (CuL.Node).Key /=
1078
              Right.Nodes (CuR.Node).Key) then
1079
            return False;
1080
         end if;
1081
 
1082
         CuL := Next (Left, CuL);
1083
         CuR := Next (Right, CuR);
1084
      end loop;
1085
 
1086
      return True;
1087
   end Strict_Equal;
1088
 
1089
   --------------------
1090
   -- Update_Element --
1091
   --------------------
1092
 
1093
   procedure Update_Element
1094
     (Container : in out Map;
1095
      Position  : Cursor;
1096
      Process   : not null access procedure (Key     : Key_Type;
1097
                                             Element : in out Element_Type))
1098
   is
1099
   begin
1100
      if not Has_Element (Container, Position) then
1101
         raise Constraint_Error with
1102
           "Position cursor of Update_Element has no element";
1103
      end if;
1104
 
1105
      pragma Assert (Vet (Container, Position),
1106
                     "bad cursor in Update_Element");
1107
 
1108
      declare
1109
         B  : Natural renames Container.Busy;
1110
         L  : Natural renames Container.Lock;
1111
 
1112
      begin
1113
         B := B + 1;
1114
         L := L + 1;
1115
 
1116
         declare
1117
            N : Node_Type renames Container.Nodes (Position.Node);
1118
            K : Key_Type renames N.Key;
1119
            E : Element_Type renames N.Element;
1120
 
1121
         begin
1122
            Process (K, E);
1123
         exception
1124
            when others =>
1125
               L := L - 1;
1126
               B := B - 1;
1127
               raise;
1128
         end;
1129
 
1130
         L := L - 1;
1131
         B := B - 1;
1132
      end;
1133
   end Update_Element;
1134
 
1135
   ---------
1136
   -- Vet --
1137
   ---------
1138
 
1139
   function Vet (Container : Map; Position : Cursor) return Boolean is
1140
   begin
1141
      if Position.Node = 0 then
1142
         return True;
1143
      end if;
1144
 
1145
      declare
1146
         X : Count_Type;
1147
 
1148
      begin
1149
         if Container.Length = 0 then
1150
            return False;
1151
         end if;
1152
 
1153
         if Container.Capacity = 0 then
1154
            return False;
1155
         end if;
1156
 
1157
         if Container.Buckets'Length = 0 then
1158
            return False;
1159
         end if;
1160
 
1161
         if Position.Node > Container.Capacity then
1162
            return False;
1163
         end if;
1164
 
1165
         if Container.Nodes (Position.Node).Next = Position.Node then
1166
            return False;
1167
         end if;
1168
 
1169
         X := Container.Buckets
1170
           (Key_Ops.Index (Container, Container.Nodes (Position.Node).Key));
1171
 
1172
         for J in 1 .. Container.Length loop
1173
            if X = Position.Node then
1174
               return True;
1175
            end if;
1176
 
1177
            if X = 0 then
1178
               return False;
1179
            end if;
1180
 
1181
            if X = Container.Nodes (X).Next then
1182
 
1183
               --  Prevent unnecessary looping
1184
 
1185
               return False;
1186
            end if;
1187
 
1188
            X := Container.Nodes (X).Next;
1189
         end loop;
1190
 
1191
         return False;
1192
      end;
1193
   end Vet;
1194
 
1195
   -----------
1196
   -- Write --
1197
   -----------
1198
 
1199
   procedure Write
1200
     (Stream    : not null access Root_Stream_Type'Class;
1201
      Container : Map)
1202
   is
1203
      procedure Write_Node
1204
        (Stream : not null access Root_Stream_Type'Class;
1205
         Node   : Node_Type);
1206
      pragma Inline (Write_Node);
1207
 
1208
      procedure Write_Nodes is new HT_Ops.Generic_Write (Write_Node);
1209
 
1210
      ----------------
1211
      -- Write_Node --
1212
      ----------------
1213
 
1214
      procedure Write_Node
1215
        (Stream : not null access Root_Stream_Type'Class;
1216
         Node   : Node_Type)
1217
      is
1218
      begin
1219
         Key_Type'Write (Stream, Node.Key);
1220
         Element_Type'Write (Stream, Node.Element);
1221
      end Write_Node;
1222
 
1223
   --  Start of processing for Write
1224
 
1225
   begin
1226
      Write_Nodes (Stream, Container);
1227
   end Write;
1228
 
1229
   procedure Write
1230
     (Stream : not null access Root_Stream_Type'Class;
1231
      Item   : Cursor)
1232
   is
1233
   begin
1234
      raise Program_Error with "attempt to stream map cursor";
1235
   end Write;
1236
 
1237
end Ada.Containers.Formal_Hashed_Maps;

powered by: WebSVN 2.1.0

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