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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [a-convec.adb] - Blame information for rev 414

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

Line No. Rev Author Line
1 281 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT LIBRARY COMPONENTS                          --
4
--                                                                          --
5
--                A D A . C O N T A I N E R S . V E C T O R S               --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 2004-2009, Free Software Foundation, Inc.         --
10
--                                                                          --
11
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
12
-- terms of the  GNU General Public License as published  by the Free Soft- --
13
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
14
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16
-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
17
--                                                                          --
18
-- As a special exception under Section 7 of GPL version 3, you are granted --
19
-- additional permissions described in the GCC Runtime Library Exception,   --
20
-- version 3.1, as published by the Free Software Foundation.               --
21
--                                                                          --
22
-- You should have received a copy of the GNU General Public License and    --
23
-- a copy of the GCC Runtime Library Exception along with this program;     --
24
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
25
-- <http://www.gnu.org/licenses/>.                                          --
26
--                                                                          --
27
-- This unit was originally developed by Matthew J Heaney.                  --
28
------------------------------------------------------------------------------
29
 
30
with Ada.Containers.Generic_Array_Sort;
31
with Ada.Unchecked_Deallocation;
32
 
33
with System; use type System.Address;
34
 
35
package body Ada.Containers.Vectors is
36
 
37
   type Int is range System.Min_Int .. System.Max_Int;
38
   type UInt is mod System.Max_Binary_Modulus;
39
 
40
   procedure Free is
41
     new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
42
 
43
   ---------
44
   -- "&" --
45
   ---------
46
 
47
   function "&" (Left, Right : Vector) return Vector is
48
      LN : constant Count_Type := Length (Left);
49
      RN : constant Count_Type := Length (Right);
50
 
51
   begin
52
      if LN = 0 then
53
         if RN = 0 then
54
            return Empty_Vector;
55
         end if;
56
 
57
         declare
58
            RE : Elements_Array renames
59
                   Right.Elements.EA (Index_Type'First .. Right.Last);
60
 
61
            Elements : constant Elements_Access :=
62
                         new Elements_Type'(Right.Last, RE);
63
 
64
         begin
65
            return (Controlled with Elements, Right.Last, 0, 0);
66
         end;
67
      end if;
68
 
69
      if RN = 0 then
70
         declare
71
            LE : Elements_Array renames
72
                   Left.Elements.EA (Index_Type'First .. Left.Last);
73
 
74
            Elements : constant Elements_Access :=
75
                         new Elements_Type'(Left.Last, LE);
76
 
77
         begin
78
            return (Controlled with Elements, Left.Last, 0, 0);
79
         end;
80
 
81
      end if;
82
 
83
      declare
84
         N           : constant Int'Base := Int (LN) + Int (RN);
85
         Last_As_Int : Int'Base;
86
 
87
      begin
88
         if Int (No_Index) > Int'Last - N then
89
            raise Constraint_Error with "new length is out of range";
90
         end if;
91
 
92
         Last_As_Int := Int (No_Index) + N;
93
 
94
         if Last_As_Int > Int (Index_Type'Last) then
95
            raise Constraint_Error with "new length is out of range";
96
         end if;
97
 
98
         declare
99
            Last : constant Index_Type := Index_Type (Last_As_Int);
100
 
101
            LE : Elements_Array renames
102
                   Left.Elements.EA (Index_Type'First .. Left.Last);
103
 
104
            RE : Elements_Array renames
105
                   Right.Elements.EA (Index_Type'First .. Right.Last);
106
 
107
            Elements : constant Elements_Access :=
108
                         new Elements_Type'(Last, LE & RE);
109
 
110
         begin
111
            return (Controlled with Elements, Last, 0, 0);
112
         end;
113
      end;
114
   end "&";
115
 
116
   function "&" (Left  : Vector; Right : Element_Type) return Vector is
117
      LN : constant Count_Type := Length (Left);
118
 
119
   begin
120
      if LN = 0 then
121
         declare
122
            Elements : constant Elements_Access :=
123
                         new Elements_Type'
124
                               (Last => Index_Type'First,
125
                                EA   => (others => Right));
126
 
127
         begin
128
            return (Controlled with Elements, Index_Type'First, 0, 0);
129
         end;
130
      end if;
131
 
132
      declare
133
         Last_As_Int : Int'Base;
134
 
135
      begin
136
         if Int (Index_Type'First) > Int'Last - Int (LN) then
137
            raise Constraint_Error with "new length is out of range";
138
         end if;
139
 
140
         Last_As_Int := Int (Index_Type'First) + Int (LN);
141
 
142
         if Last_As_Int > Int (Index_Type'Last) then
143
            raise Constraint_Error with "new length is out of range";
144
         end if;
145
 
146
         declare
147
            Last : constant Index_Type := Index_Type (Last_As_Int);
148
 
149
            LE : Elements_Array renames
150
                   Left.Elements.EA (Index_Type'First .. Left.Last);
151
 
152
            Elements : constant Elements_Access :=
153
                         new Elements_Type'
154
                               (Last => Last,
155
                                EA   => LE & Right);
156
 
157
         begin
158
            return (Controlled with Elements, Last, 0, 0);
159
         end;
160
      end;
161
   end "&";
162
 
163
   function "&" (Left  : Element_Type; Right : Vector) return Vector is
164
      RN : constant Count_Type := Length (Right);
165
 
166
   begin
167
      if RN = 0 then
168
         declare
169
            Elements : constant Elements_Access :=
170
                         new Elements_Type'
171
                               (Last => Index_Type'First,
172
                                EA   => (others => Left));
173
 
174
         begin
175
            return (Controlled with Elements, Index_Type'First, 0, 0);
176
         end;
177
      end if;
178
 
179
      declare
180
         Last_As_Int : Int'Base;
181
 
182
      begin
183
         if Int (Index_Type'First) > Int'Last - Int (RN) then
184
            raise Constraint_Error with "new length is out of range";
185
         end if;
186
 
187
         Last_As_Int := Int (Index_Type'First) + Int (RN);
188
 
189
         if Last_As_Int > Int (Index_Type'Last) then
190
            raise Constraint_Error with "new length is out of range";
191
         end if;
192
 
193
         declare
194
            Last : constant Index_Type := Index_Type (Last_As_Int);
195
 
196
            RE : Elements_Array renames
197
                   Right.Elements.EA (Index_Type'First .. Right.Last);
198
 
199
            Elements : constant Elements_Access :=
200
                         new Elements_Type'
201
                               (Last => Last,
202
                                EA   => Left & RE);
203
 
204
         begin
205
            return (Controlled with Elements, Last, 0, 0);
206
         end;
207
      end;
208
   end "&";
209
 
210
   function "&" (Left, Right : Element_Type) return Vector is
211
   begin
212
      if Index_Type'First >= Index_Type'Last then
213
         raise Constraint_Error with "new length is out of range";
214
      end if;
215
 
216
      declare
217
         Last : constant Index_Type := Index_Type'First + 1;
218
 
219
         Elements : constant Elements_Access :=
220
                      new Elements_Type'
221
                            (Last => Last,
222
                             EA   => (Left, Right));
223
 
224
      begin
225
         return (Controlled with Elements, Last, 0, 0);
226
      end;
227
   end "&";
228
 
229
   ---------
230
   -- "=" --
231
   ---------
232
 
233
   overriding function "=" (Left, Right : Vector) return Boolean is
234
   begin
235
      if Left'Address = Right'Address then
236
         return True;
237
      end if;
238
 
239
      if Left.Last /= Right.Last then
240
         return False;
241
      end if;
242
 
243
      for J in Index_Type range Index_Type'First .. Left.Last loop
244
         if Left.Elements.EA (J) /= Right.Elements.EA (J) then
245
            return False;
246
         end if;
247
      end loop;
248
 
249
      return True;
250
   end "=";
251
 
252
   ------------
253
   -- Adjust --
254
   ------------
255
 
256
   procedure Adjust (Container : in out Vector) is
257
   begin
258
      if Container.Last = No_Index then
259
         Container.Elements := null;
260
         return;
261
      end if;
262
 
263
      declare
264
         L  : constant Index_Type := Container.Last;
265
         EA : Elements_Array renames
266
                Container.Elements.EA (Index_Type'First .. L);
267
 
268
      begin
269
         Container.Elements := null;
270
         Container.Busy := 0;
271
         Container.Lock := 0;
272
 
273
         --  Note: it may seem that the following assignment to Container.Last
274
         --  is useless, since we assign it to L below. However this code is
275
         --  used in case 'new Elements_Type' below raises an exception, to
276
         --  keep Container in a consistent state.
277
 
278
         Container.Last := No_Index;
279
         Container.Elements := new Elements_Type'(L, EA);
280
         Container.Last := L;
281
      end;
282
   end Adjust;
283
 
284
   ------------
285
   -- Append --
286
   ------------
287
 
288
   procedure Append (Container : in out Vector; New_Item : Vector) is
289
   begin
290
      if Is_Empty (New_Item) then
291
         return;
292
      end if;
293
 
294
      if Container.Last = Index_Type'Last then
295
         raise Constraint_Error with "vector is already at its maximum length";
296
      end if;
297
 
298
      Insert
299
        (Container,
300
         Container.Last + 1,
301
         New_Item);
302
   end Append;
303
 
304
   procedure Append
305
     (Container : in out Vector;
306
      New_Item  : Element_Type;
307
      Count     : Count_Type := 1)
308
   is
309
   begin
310
      if Count = 0 then
311
         return;
312
      end if;
313
 
314
      if Container.Last = Index_Type'Last then
315
         raise Constraint_Error with "vector is already at its maximum length";
316
      end if;
317
 
318
      Insert
319
        (Container,
320
         Container.Last + 1,
321
         New_Item,
322
         Count);
323
   end Append;
324
 
325
   --------------
326
   -- Capacity --
327
   --------------
328
 
329
   function Capacity (Container : Vector) return Count_Type is
330
   begin
331
      if Container.Elements = null then
332
         return 0;
333
      end if;
334
 
335
      return Container.Elements.EA'Length;
336
   end Capacity;
337
 
338
   -----------
339
   -- Clear --
340
   -----------
341
 
342
   procedure Clear (Container : in out Vector) is
343
   begin
344
      if Container.Busy > 0 then
345
         raise Program_Error with
346
           "attempt to tamper with elements (vector is busy)";
347
      end if;
348
 
349
      Container.Last := No_Index;
350
   end Clear;
351
 
352
   --------------
353
   -- Contains --
354
   --------------
355
 
356
   function Contains
357
     (Container : Vector;
358
      Item      : Element_Type) return Boolean
359
   is
360
   begin
361
      return Find_Index (Container, Item) /= No_Index;
362
   end Contains;
363
 
364
   ------------
365
   -- Delete --
366
   ------------
367
 
368
   procedure Delete
369
     (Container : in out Vector;
370
      Index     : Extended_Index;
371
      Count     : Count_Type := 1)
372
   is
373
   begin
374
      if Index < Index_Type'First then
375
         raise Constraint_Error with "Index is out of range (too small)";
376
      end if;
377
 
378
      if Index > Container.Last then
379
         if Index > Container.Last + 1 then
380
            raise Constraint_Error with "Index is out of range (too large)";
381
         end if;
382
 
383
         return;
384
      end if;
385
 
386
      if Count = 0 then
387
         return;
388
      end if;
389
 
390
      if Container.Busy > 0 then
391
         raise Program_Error with
392
           "attempt to tamper with elements (vector is busy)";
393
      end if;
394
 
395
      declare
396
         I_As_Int        : constant Int := Int (Index);
397
         Old_Last_As_Int : constant Int := Index_Type'Pos (Container.Last);
398
 
399
         Count1 : constant Int'Base := Count_Type'Pos (Count);
400
         Count2 : constant Int'Base := Old_Last_As_Int - I_As_Int + 1;
401
         N      : constant Int'Base := Int'Min (Count1, Count2);
402
 
403
         J_As_Int : constant Int'Base := I_As_Int + N;
404
 
405
      begin
406
         if J_As_Int > Old_Last_As_Int then
407
            Container.Last := Index - 1;
408
 
409
         else
410
            declare
411
               J  : constant Index_Type := Index_Type (J_As_Int);
412
               EA : Elements_Array renames Container.Elements.EA;
413
 
414
               New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
415
               New_Last        : constant Index_Type :=
416
                                   Index_Type (New_Last_As_Int);
417
 
418
            begin
419
               EA (Index .. New_Last) := EA (J .. Container.Last);
420
               Container.Last := New_Last;
421
            end;
422
         end if;
423
      end;
424
   end Delete;
425
 
426
   procedure Delete
427
     (Container : in out Vector;
428
      Position  : in out Cursor;
429
      Count     : Count_Type := 1)
430
   is
431
      pragma Warnings (Off, Position);
432
 
433
   begin
434
      if Position.Container = null then
435
         raise Constraint_Error with "Position cursor has no element";
436
      end if;
437
 
438
      if Position.Container /= Container'Unrestricted_Access then
439
         raise Program_Error with "Position cursor denotes wrong container";
440
      end if;
441
 
442
      if Position.Index > Container.Last then
443
         raise Program_Error with "Position index is out of range";
444
      end if;
445
 
446
      Delete (Container, Position.Index, Count);
447
      Position := No_Element;
448
   end Delete;
449
 
450
   ------------------
451
   -- Delete_First --
452
   ------------------
453
 
454
   procedure Delete_First
455
     (Container : in out Vector;
456
      Count     : Count_Type := 1)
457
   is
458
   begin
459
      if Count = 0 then
460
         return;
461
      end if;
462
 
463
      if Count >= Length (Container) then
464
         Clear (Container);
465
         return;
466
      end if;
467
 
468
      Delete (Container, Index_Type'First, Count);
469
   end Delete_First;
470
 
471
   -----------------
472
   -- Delete_Last --
473
   -----------------
474
 
475
   procedure Delete_Last
476
     (Container : in out Vector;
477
      Count     : Count_Type := 1)
478
   is
479
      Index : Int'Base;
480
 
481
   begin
482
      if Count = 0 then
483
         return;
484
      end if;
485
 
486
      if Container.Busy > 0 then
487
         raise Program_Error with
488
           "attempt to tamper with elements (vector is busy)";
489
      end if;
490
 
491
      Index := Int'Base (Container.Last) - Int'Base (Count);
492
 
493
      Container.Last :=
494
         (if Index < Index_Type'Pos (Index_Type'First)
495
          then No_Index
496
          else Index_Type (Index));
497
   end Delete_Last;
498
 
499
   -------------
500
   -- Element --
501
   -------------
502
 
503
   function Element
504
     (Container : Vector;
505
      Index     : Index_Type) return Element_Type
506
   is
507
   begin
508
      if Index > Container.Last then
509
         raise Constraint_Error with "Index is out of range";
510
      end if;
511
 
512
      return Container.Elements.EA (Index);
513
   end Element;
514
 
515
   function Element (Position : Cursor) return Element_Type is
516
   begin
517
      if Position.Container = null then
518
         raise Constraint_Error with "Position cursor has no element";
519
      end if;
520
 
521
      if Position.Index > Position.Container.Last then
522
         raise Constraint_Error with "Position cursor is out of range";
523
      end if;
524
 
525
      return Position.Container.Elements.EA (Position.Index);
526
   end Element;
527
 
528
   --------------
529
   -- Finalize --
530
   --------------
531
 
532
   procedure Finalize (Container : in out Vector) is
533
      X : Elements_Access := Container.Elements;
534
 
535
   begin
536
      if Container.Busy > 0 then
537
         raise Program_Error with
538
           "attempt to tamper with elements (vector is busy)";
539
      end if;
540
 
541
      Container.Elements := null;
542
      Container.Last := No_Index;
543
      Free (X);
544
   end Finalize;
545
 
546
   ----------
547
   -- Find --
548
   ----------
549
 
550
   function Find
551
     (Container : Vector;
552
      Item      : Element_Type;
553
      Position  : Cursor := No_Element) return Cursor
554
   is
555
   begin
556
      if Position.Container /= null then
557
         if Position.Container /= Container'Unrestricted_Access then
558
            raise Program_Error with "Position cursor denotes wrong container";
559
         end if;
560
 
561
         if Position.Index > Container.Last then
562
            raise Program_Error with "Position index is out of range";
563
         end if;
564
      end if;
565
 
566
      for J in Position.Index .. Container.Last loop
567
         if Container.Elements.EA (J) = Item then
568
            return (Container'Unchecked_Access, J);
569
         end if;
570
      end loop;
571
 
572
      return No_Element;
573
   end Find;
574
 
575
   ----------------
576
   -- Find_Index --
577
   ----------------
578
 
579
   function Find_Index
580
     (Container : Vector;
581
      Item      : Element_Type;
582
      Index     : Index_Type := Index_Type'First) return Extended_Index
583
   is
584
   begin
585
      for Indx in Index .. Container.Last loop
586
         if Container.Elements.EA (Indx) = Item then
587
            return Indx;
588
         end if;
589
      end loop;
590
 
591
      return No_Index;
592
   end Find_Index;
593
 
594
   -----------
595
   -- First --
596
   -----------
597
 
598
   function First (Container : Vector) return Cursor is
599
   begin
600
      if Is_Empty (Container) then
601
         return No_Element;
602
      end if;
603
 
604
      return (Container'Unchecked_Access, Index_Type'First);
605
   end First;
606
 
607
   -------------------
608
   -- First_Element --
609
   -------------------
610
 
611
   function First_Element (Container : Vector) return Element_Type is
612
   begin
613
      if Container.Last = No_Index then
614
         raise Constraint_Error with "Container is empty";
615
      end if;
616
 
617
      return Container.Elements.EA (Index_Type'First);
618
   end First_Element;
619
 
620
   -----------------
621
   -- First_Index --
622
   -----------------
623
 
624
   function First_Index (Container : Vector) return Index_Type is
625
      pragma Unreferenced (Container);
626
   begin
627
      return Index_Type'First;
628
   end First_Index;
629
 
630
   ---------------------
631
   -- Generic_Sorting --
632
   ---------------------
633
 
634
   package body Generic_Sorting is
635
 
636
      ---------------
637
      -- Is_Sorted --
638
      ---------------
639
 
640
      function Is_Sorted (Container : Vector) return Boolean is
641
      begin
642
         if Container.Last <= Index_Type'First then
643
            return True;
644
         end if;
645
 
646
         declare
647
            EA : Elements_Array renames Container.Elements.EA;
648
         begin
649
            for I in Index_Type'First .. Container.Last - 1 loop
650
               if EA (I + 1) < EA (I) then
651
                  return False;
652
               end if;
653
            end loop;
654
         end;
655
 
656
         return True;
657
      end Is_Sorted;
658
 
659
      -----------
660
      -- Merge --
661
      -----------
662
 
663
      procedure Merge (Target, Source : in out Vector) is
664
         I : Index_Type'Base := Target.Last;
665
         J : Index_Type'Base;
666
 
667
      begin
668
         if Target.Last < Index_Type'First then
669
            Move (Target => Target, Source => Source);
670
            return;
671
         end if;
672
 
673
         if Target'Address = Source'Address then
674
            return;
675
         end if;
676
 
677
         if Source.Last < Index_Type'First then
678
            return;
679
         end if;
680
 
681
         if Source.Busy > 0 then
682
            raise Program_Error with
683
              "attempt to tamper with elements (vector is busy)";
684
         end if;
685
 
686
         Target.Set_Length (Length (Target) + Length (Source));
687
 
688
         declare
689
            TA : Elements_Array renames Target.Elements.EA;
690
            SA : Elements_Array renames Source.Elements.EA;
691
 
692
         begin
693
            J := Target.Last;
694
            while Source.Last >= Index_Type'First loop
695
               pragma Assert (Source.Last <= Index_Type'First
696
                                or else not (SA (Source.Last) <
697
                                             SA (Source.Last - 1)));
698
 
699
               if I < Index_Type'First then
700
                  TA (Index_Type'First .. J) :=
701
                    SA (Index_Type'First .. Source.Last);
702
 
703
                  Source.Last := No_Index;
704
                  return;
705
               end if;
706
 
707
               pragma Assert (I <= Index_Type'First
708
                                or else not (TA (I) < TA (I - 1)));
709
 
710
               if SA (Source.Last) < TA (I) then
711
                  TA (J) := TA (I);
712
                  I := I - 1;
713
 
714
               else
715
                  TA (J) := SA (Source.Last);
716
                  Source.Last := Source.Last - 1;
717
               end if;
718
 
719
               J := J - 1;
720
            end loop;
721
         end;
722
      end Merge;
723
 
724
      ----------
725
      -- Sort --
726
      ----------
727
 
728
      procedure Sort (Container : in out Vector)
729
      is
730
         procedure Sort is
731
            new Generic_Array_Sort
732
             (Index_Type   => Index_Type,
733
              Element_Type => Element_Type,
734
              Array_Type   => Elements_Array,
735
              "<"          => "<");
736
 
737
      begin
738
         if Container.Last <= Index_Type'First then
739
            return;
740
         end if;
741
 
742
         if Container.Lock > 0 then
743
            raise Program_Error with
744
              "attempt to tamper with cursors (vector is locked)";
745
         end if;
746
 
747
         Sort (Container.Elements.EA (Index_Type'First .. Container.Last));
748
      end Sort;
749
 
750
   end Generic_Sorting;
751
 
752
   -----------------
753
   -- Has_Element --
754
   -----------------
755
 
756
   function Has_Element (Position : Cursor) return Boolean is
757
   begin
758
      if Position.Container = null then
759
         return False;
760
      end if;
761
 
762
      return Position.Index <= Position.Container.Last;
763
   end Has_Element;
764
 
765
   ------------
766
   -- Insert --
767
   ------------
768
 
769
   procedure Insert
770
     (Container : in out Vector;
771
      Before    : Extended_Index;
772
      New_Item  : Element_Type;
773
      Count     : Count_Type := 1)
774
   is
775
      N : constant Int := Count_Type'Pos (Count);
776
 
777
      First           : constant Int := Int (Index_Type'First);
778
      New_Last_As_Int : Int'Base;
779
      New_Last        : Index_Type;
780
      New_Length      : UInt;
781
      Max_Length      : constant UInt := UInt (Count_Type'Last);
782
 
783
      Dst : Elements_Access;
784
 
785
   begin
786
      if Before < Index_Type'First then
787
         raise Constraint_Error with
788
           "Before index is out of range (too small)";
789
      end if;
790
 
791
      if Before > Container.Last
792
        and then Before > Container.Last + 1
793
      then
794
         raise Constraint_Error with
795
           "Before index is out of range (too large)";
796
      end if;
797
 
798
      if Count = 0 then
799
         return;
800
      end if;
801
 
802
      declare
803
         Old_Last_As_Int : constant Int := Int (Container.Last);
804
 
805
      begin
806
         if Old_Last_As_Int > Int'Last - N then
807
            raise Constraint_Error with "new length is out of range";
808
         end if;
809
 
810
         New_Last_As_Int := Old_Last_As_Int + N;
811
 
812
         if New_Last_As_Int > Int (Index_Type'Last) then
813
            raise Constraint_Error with "new length is out of range";
814
         end if;
815
 
816
         New_Length := UInt (New_Last_As_Int - First + Int'(1));
817
 
818
         if New_Length > Max_Length then
819
            raise Constraint_Error with "new length is out of range";
820
         end if;
821
 
822
         New_Last := Index_Type (New_Last_As_Int);
823
      end;
824
 
825
      if Container.Busy > 0 then
826
         raise Program_Error with
827
           "attempt to tamper with elements (vector is busy)";
828
      end if;
829
 
830
      if Container.Elements = null then
831
         Container.Elements := new Elements_Type'
832
                                     (Last => New_Last,
833
                                      EA   => (others => New_Item));
834
         Container.Last := New_Last;
835
         return;
836
      end if;
837
 
838
      if New_Last <= Container.Elements.Last then
839
         declare
840
            EA : Elements_Array renames Container.Elements.EA;
841
 
842
         begin
843
            if Before <= Container.Last then
844
               declare
845
                  Index_As_Int : constant Int'Base :=
846
                                   Index_Type'Pos (Before) + N;
847
 
848
                  Index : constant Index_Type := Index_Type (Index_As_Int);
849
 
850
               begin
851
                  EA (Index .. New_Last) := EA (Before .. Container.Last);
852
 
853
                  EA (Before .. Index_Type'Pred (Index)) :=
854
                      (others => New_Item);
855
               end;
856
 
857
            else
858
               EA (Before .. New_Last) := (others => New_Item);
859
            end if;
860
         end;
861
 
862
         Container.Last := New_Last;
863
         return;
864
      end if;
865
 
866
      declare
867
         C, CC : UInt;
868
 
869
      begin
870
         C := UInt'Max (1, Container.Elements.EA'Length);  -- ???
871
         while C < New_Length loop
872
            if C > UInt'Last / 2 then
873
               C := UInt'Last;
874
               exit;
875
            end if;
876
 
877
            C := 2 * C;
878
         end loop;
879
 
880
         if C > Max_Length then
881
            C := Max_Length;
882
         end if;
883
 
884
         if Index_Type'First <= 0
885
           and then Index_Type'Last >= 0
886
         then
887
            CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
888
         else
889
            CC := UInt (Int (Index_Type'Last) - First + 1);
890
         end if;
891
 
892
         if C > CC then
893
            C := CC;
894
         end if;
895
 
896
         declare
897
            Dst_Last : constant Index_Type :=
898
                         Index_Type (First + UInt'Pos (C) - 1);
899
 
900
         begin
901
            Dst := new Elements_Type (Dst_Last);
902
         end;
903
      end;
904
 
905
      declare
906
         SA : Elements_Array renames Container.Elements.EA;
907
         DA : Elements_Array renames Dst.EA;
908
 
909
      begin
910
         DA (Index_Type'First .. Index_Type'Pred (Before)) :=
911
           SA (Index_Type'First .. Index_Type'Pred (Before));
912
 
913
         if Before <= Container.Last then
914
            declare
915
               Index_As_Int : constant Int'Base :=
916
                                Index_Type'Pos (Before) + N;
917
 
918
               Index : constant Index_Type := Index_Type (Index_As_Int);
919
 
920
            begin
921
               DA (Before .. Index_Type'Pred (Index)) := (others => New_Item);
922
               DA (Index .. New_Last) := SA (Before .. Container.Last);
923
            end;
924
 
925
         else
926
            DA (Before .. New_Last) := (others => New_Item);
927
         end if;
928
      exception
929
         when others =>
930
            Free (Dst);
931
            raise;
932
      end;
933
 
934
      declare
935
         X : Elements_Access := Container.Elements;
936
      begin
937
         Container.Elements := Dst;
938
         Container.Last := New_Last;
939
         Free (X);
940
      end;
941
   end Insert;
942
 
943
   procedure Insert
944
     (Container : in out Vector;
945
      Before    : Extended_Index;
946
      New_Item  : Vector)
947
   is
948
      N : constant Count_Type := Length (New_Item);
949
 
950
   begin
951
      if Before < Index_Type'First then
952
         raise Constraint_Error with
953
           "Before index is out of range (too small)";
954
      end if;
955
 
956
      if Before > Container.Last
957
        and then Before > Container.Last + 1
958
      then
959
         raise Constraint_Error with
960
           "Before index is out of range (too large)";
961
      end if;
962
 
963
      if N = 0 then
964
         return;
965
      end if;
966
 
967
      Insert_Space (Container, Before, Count => N);
968
 
969
      declare
970
         Dst_Last_As_Int : constant Int'Base :=
971
                             Int'Base (Before) + Int'Base (N) - 1;
972
 
973
         Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
974
 
975
      begin
976
         if Container'Address /= New_Item'Address then
977
            Container.Elements.EA (Before .. Dst_Last) :=
978
              New_Item.Elements.EA (Index_Type'First .. New_Item.Last);
979
 
980
            return;
981
         end if;
982
 
983
         declare
984
            subtype Src_Index_Subtype is Index_Type'Base range
985
              Index_Type'First .. Before - 1;
986
 
987
            Src : Elements_Array renames
988
                    Container.Elements.EA (Src_Index_Subtype);
989
 
990
            Index_As_Int : constant Int'Base :=
991
                             Int (Before) + Src'Length - 1;
992
 
993
            Index : constant Index_Type'Base :=
994
                      Index_Type'Base (Index_As_Int);
995
 
996
            Dst : Elements_Array renames
997
                    Container.Elements.EA (Before .. Index);
998
 
999
         begin
1000
            Dst := Src;
1001
         end;
1002
 
1003
         if Dst_Last = Container.Last then
1004
            return;
1005
         end if;
1006
 
1007
         declare
1008
            subtype Src_Index_Subtype is Index_Type'Base range
1009
              Dst_Last + 1 .. Container.Last;
1010
 
1011
            Src : Elements_Array renames
1012
                    Container.Elements.EA (Src_Index_Subtype);
1013
 
1014
            Index_As_Int : constant Int'Base :=
1015
                             Dst_Last_As_Int - Src'Length + 1;
1016
 
1017
            Index : constant Index_Type :=
1018
                      Index_Type (Index_As_Int);
1019
 
1020
            Dst : Elements_Array renames
1021
                    Container.Elements.EA (Index .. Dst_Last);
1022
 
1023
         begin
1024
            Dst := Src;
1025
         end;
1026
      end;
1027
   end Insert;
1028
 
1029
   procedure Insert
1030
     (Container : in out Vector;
1031
      Before    : Cursor;
1032
      New_Item  : Vector)
1033
   is
1034
      Index : Index_Type'Base;
1035
 
1036
   begin
1037
      if Before.Container /= null
1038
        and then Before.Container /= Container'Unchecked_Access
1039
      then
1040
         raise Program_Error with "Before cursor denotes wrong container";
1041
      end if;
1042
 
1043
      if Is_Empty (New_Item) then
1044
         return;
1045
      end if;
1046
 
1047
      if Before.Container = null
1048
        or else Before.Index > Container.Last
1049
      then
1050
         if Container.Last = Index_Type'Last then
1051
            raise Constraint_Error with
1052
              "vector is already at its maximum length";
1053
         end if;
1054
 
1055
         Index := Container.Last + 1;
1056
 
1057
      else
1058
         Index := Before.Index;
1059
      end if;
1060
 
1061
      Insert (Container, Index, New_Item);
1062
   end Insert;
1063
 
1064
   procedure Insert
1065
     (Container : in out Vector;
1066
      Before    : Cursor;
1067
      New_Item  : Vector;
1068
      Position  : out Cursor)
1069
   is
1070
      Index : Index_Type'Base;
1071
 
1072
   begin
1073
      if Before.Container /= null
1074
        and then Before.Container /= Container'Unchecked_Access
1075
      then
1076
         raise Program_Error with "Before cursor denotes wrong container";
1077
      end if;
1078
 
1079
      if Is_Empty (New_Item) then
1080
         if Before.Container = null
1081
           or else Before.Index > Container.Last
1082
         then
1083
            Position := No_Element;
1084
         else
1085
            Position := (Container'Unchecked_Access, Before.Index);
1086
         end if;
1087
 
1088
         return;
1089
      end if;
1090
 
1091
      if Before.Container = null
1092
        or else Before.Index > Container.Last
1093
      then
1094
         if Container.Last = Index_Type'Last then
1095
            raise Constraint_Error with
1096
              "vector is already at its maximum length";
1097
         end if;
1098
 
1099
         Index := Container.Last + 1;
1100
 
1101
      else
1102
         Index := Before.Index;
1103
      end if;
1104
 
1105
      Insert (Container, Index, New_Item);
1106
 
1107
      Position := Cursor'(Container'Unchecked_Access, Index);
1108
   end Insert;
1109
 
1110
   procedure Insert
1111
     (Container : in out Vector;
1112
      Before    : Cursor;
1113
      New_Item  : Element_Type;
1114
      Count     : Count_Type := 1)
1115
   is
1116
      Index : Index_Type'Base;
1117
 
1118
   begin
1119
      if Before.Container /= null
1120
        and then Before.Container /= Container'Unchecked_Access
1121
      then
1122
         raise Program_Error with "Before cursor denotes wrong container";
1123
      end if;
1124
 
1125
      if Count = 0 then
1126
         return;
1127
      end if;
1128
 
1129
      if Before.Container = null
1130
        or else Before.Index > Container.Last
1131
      then
1132
         if Container.Last = Index_Type'Last then
1133
            raise Constraint_Error with
1134
              "vector is already at its maximum length";
1135
         end if;
1136
 
1137
         Index := Container.Last + 1;
1138
 
1139
      else
1140
         Index := Before.Index;
1141
      end if;
1142
 
1143
      Insert (Container, Index, New_Item, Count);
1144
   end Insert;
1145
 
1146
   procedure Insert
1147
     (Container : in out Vector;
1148
      Before    : Cursor;
1149
      New_Item  : Element_Type;
1150
      Position  : out Cursor;
1151
      Count     : Count_Type := 1)
1152
   is
1153
      Index : Index_Type'Base;
1154
 
1155
   begin
1156
      if Before.Container /= null
1157
        and then Before.Container /= Container'Unchecked_Access
1158
      then
1159
         raise Program_Error with "Before cursor denotes wrong container";
1160
      end if;
1161
 
1162
      if Count = 0 then
1163
         if Before.Container = null
1164
           or else Before.Index > Container.Last
1165
         then
1166
            Position := No_Element;
1167
         else
1168
            Position := (Container'Unchecked_Access, Before.Index);
1169
         end if;
1170
 
1171
         return;
1172
      end if;
1173
 
1174
      if Before.Container = null
1175
        or else Before.Index > Container.Last
1176
      then
1177
         if Container.Last = Index_Type'Last then
1178
            raise Constraint_Error with
1179
              "vector is already at its maximum length";
1180
         end if;
1181
 
1182
         Index := Container.Last + 1;
1183
 
1184
      else
1185
         Index := Before.Index;
1186
      end if;
1187
 
1188
      Insert (Container, Index, New_Item, Count);
1189
 
1190
      Position := Cursor'(Container'Unchecked_Access, Index);
1191
   end Insert;
1192
 
1193
   procedure Insert
1194
     (Container : in out Vector;
1195
      Before    : Extended_Index;
1196
      Count     : Count_Type := 1)
1197
   is
1198
      New_Item : Element_Type;  -- Default-initialized value
1199
      pragma Warnings (Off, New_Item);
1200
 
1201
   begin
1202
      Insert (Container, Before, New_Item, Count);
1203
   end Insert;
1204
 
1205
   procedure Insert
1206
     (Container : in out Vector;
1207
      Before    : Cursor;
1208
      Position  : out Cursor;
1209
      Count     : Count_Type := 1)
1210
   is
1211
      New_Item : Element_Type;  -- Default-initialized value
1212
      pragma Warnings (Off, New_Item);
1213
 
1214
   begin
1215
      Insert (Container, Before, New_Item, Position, Count);
1216
   end Insert;
1217
 
1218
   ------------------
1219
   -- Insert_Space --
1220
   ------------------
1221
 
1222
   procedure Insert_Space
1223
     (Container : in out Vector;
1224
      Before    : Extended_Index;
1225
      Count     : Count_Type := 1)
1226
   is
1227
      N : constant Int := Count_Type'Pos (Count);
1228
 
1229
      First           : constant Int := Int (Index_Type'First);
1230
      New_Last_As_Int : Int'Base;
1231
      New_Last        : Index_Type;
1232
      New_Length      : UInt;
1233
      Max_Length      : constant UInt := UInt (Count_Type'Last);
1234
 
1235
      Dst : Elements_Access;
1236
 
1237
   begin
1238
      if Before < Index_Type'First then
1239
         raise Constraint_Error with
1240
           "Before index is out of range (too small)";
1241
      end if;
1242
 
1243
      if Before > Container.Last
1244
        and then Before > Container.Last + 1
1245
      then
1246
         raise Constraint_Error with
1247
           "Before index is out of range (too large)";
1248
      end if;
1249
 
1250
      if Count = 0 then
1251
         return;
1252
      end if;
1253
 
1254
      declare
1255
         Old_Last_As_Int : constant Int := Int (Container.Last);
1256
 
1257
      begin
1258
         if Old_Last_As_Int > Int'Last - N then
1259
            raise Constraint_Error with "new length is out of range";
1260
         end if;
1261
 
1262
         New_Last_As_Int := Old_Last_As_Int + N;
1263
 
1264
         if New_Last_As_Int > Int (Index_Type'Last) then
1265
            raise Constraint_Error with "new length is out of range";
1266
         end if;
1267
 
1268
         New_Length := UInt (New_Last_As_Int - First + Int'(1));
1269
 
1270
         if New_Length > Max_Length then
1271
            raise Constraint_Error with "new length is out of range";
1272
         end if;
1273
 
1274
         New_Last := Index_Type (New_Last_As_Int);
1275
      end;
1276
 
1277
      if Container.Busy > 0 then
1278
         raise Program_Error with
1279
           "attempt to tamper with elements (vector is busy)";
1280
      end if;
1281
 
1282
      if Container.Elements = null then
1283
         Container.Elements := new Elements_Type (New_Last);
1284
         Container.Last := New_Last;
1285
         return;
1286
      end if;
1287
 
1288
      if New_Last <= Container.Elements.Last then
1289
         declare
1290
            EA : Elements_Array renames Container.Elements.EA;
1291
         begin
1292
            if Before <= Container.Last then
1293
               declare
1294
                  Index_As_Int : constant Int'Base :=
1295
                                   Index_Type'Pos (Before) + N;
1296
 
1297
                  Index : constant Index_Type := Index_Type (Index_As_Int);
1298
 
1299
               begin
1300
                  EA (Index .. New_Last) := EA (Before .. Container.Last);
1301
               end;
1302
            end if;
1303
         end;
1304
 
1305
         Container.Last := New_Last;
1306
         return;
1307
      end if;
1308
 
1309
      declare
1310
         C, CC : UInt;
1311
 
1312
      begin
1313
         C := UInt'Max (1, Container.Elements.EA'Length);  -- ???
1314
         while C < New_Length loop
1315
            if C > UInt'Last / 2 then
1316
               C := UInt'Last;
1317
               exit;
1318
            end if;
1319
 
1320
            C := 2 * C;
1321
         end loop;
1322
 
1323
         if C > Max_Length then
1324
            C := Max_Length;
1325
         end if;
1326
 
1327
         if Index_Type'First <= 0
1328
           and then Index_Type'Last >= 0
1329
         then
1330
            CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
1331
         else
1332
            CC := UInt (Int (Index_Type'Last) - First + 1);
1333
         end if;
1334
 
1335
         if C > CC then
1336
            C := CC;
1337
         end if;
1338
 
1339
         declare
1340
            Dst_Last : constant Index_Type :=
1341
                         Index_Type (First + UInt'Pos (C) - 1);
1342
 
1343
         begin
1344
            Dst := new Elements_Type (Dst_Last);
1345
         end;
1346
      end;
1347
 
1348
      declare
1349
         SA : Elements_Array renames Container.Elements.EA;
1350
         DA : Elements_Array renames Dst.EA;
1351
 
1352
      begin
1353
         DA (Index_Type'First .. Index_Type'Pred (Before)) :=
1354
           SA (Index_Type'First .. Index_Type'Pred (Before));
1355
 
1356
         if Before <= Container.Last then
1357
            declare
1358
               Index_As_Int : constant Int'Base :=
1359
                                Index_Type'Pos (Before) + N;
1360
 
1361
               Index : constant Index_Type := Index_Type (Index_As_Int);
1362
 
1363
            begin
1364
               DA (Index .. New_Last) := SA (Before .. Container.Last);
1365
            end;
1366
         end if;
1367
      exception
1368
         when others =>
1369
            Free (Dst);
1370
            raise;
1371
      end;
1372
 
1373
      declare
1374
         X : Elements_Access := Container.Elements;
1375
      begin
1376
         Container.Elements := Dst;
1377
         Container.Last := New_Last;
1378
         Free (X);
1379
      end;
1380
   end Insert_Space;
1381
 
1382
   procedure Insert_Space
1383
     (Container : in out Vector;
1384
      Before    : Cursor;
1385
      Position  : out Cursor;
1386
      Count     : Count_Type := 1)
1387
   is
1388
      Index : Index_Type'Base;
1389
 
1390
   begin
1391
      if Before.Container /= null
1392
        and then Before.Container /= Container'Unchecked_Access
1393
      then
1394
         raise Program_Error with "Before cursor denotes wrong container";
1395
      end if;
1396
 
1397
      if Count = 0 then
1398
         if Before.Container = null
1399
           or else Before.Index > Container.Last
1400
         then
1401
            Position := No_Element;
1402
         else
1403
            Position := (Container'Unchecked_Access, Before.Index);
1404
         end if;
1405
 
1406
         return;
1407
      end if;
1408
 
1409
      if Before.Container = null
1410
        or else Before.Index > Container.Last
1411
      then
1412
         if Container.Last = Index_Type'Last then
1413
            raise Constraint_Error with
1414
              "vector is already at its maximum length";
1415
         end if;
1416
 
1417
         Index := Container.Last + 1;
1418
 
1419
      else
1420
         Index := Before.Index;
1421
      end if;
1422
 
1423
      Insert_Space (Container, Index, Count => Count);
1424
 
1425
      Position := Cursor'(Container'Unchecked_Access, Index);
1426
   end Insert_Space;
1427
 
1428
   --------------
1429
   -- Is_Empty --
1430
   --------------
1431
 
1432
   function Is_Empty (Container : Vector) return Boolean is
1433
   begin
1434
      return Container.Last < Index_Type'First;
1435
   end Is_Empty;
1436
 
1437
   -------------
1438
   -- Iterate --
1439
   -------------
1440
 
1441
   procedure Iterate
1442
     (Container : Vector;
1443
      Process   : not null access procedure (Position : Cursor))
1444
   is
1445
      V : Vector renames Container'Unrestricted_Access.all;
1446
      B : Natural renames V.Busy;
1447
 
1448
   begin
1449
      B := B + 1;
1450
 
1451
      begin
1452
         for Indx in Index_Type'First .. Container.Last loop
1453
            Process (Cursor'(Container'Unchecked_Access, Indx));
1454
         end loop;
1455
      exception
1456
         when others =>
1457
            B := B - 1;
1458
            raise;
1459
      end;
1460
 
1461
      B := B - 1;
1462
   end Iterate;
1463
 
1464
   ----------
1465
   -- Last --
1466
   ----------
1467
 
1468
   function Last (Container : Vector) return Cursor is
1469
   begin
1470
      if Is_Empty (Container) then
1471
         return No_Element;
1472
      end if;
1473
 
1474
      return (Container'Unchecked_Access, Container.Last);
1475
   end Last;
1476
 
1477
   ------------------
1478
   -- Last_Element --
1479
   ------------------
1480
 
1481
   function Last_Element (Container : Vector) return Element_Type is
1482
   begin
1483
      if Container.Last = No_Index then
1484
         raise Constraint_Error with "Container is empty";
1485
      end if;
1486
 
1487
      return Container.Elements.EA (Container.Last);
1488
   end Last_Element;
1489
 
1490
   ----------------
1491
   -- Last_Index --
1492
   ----------------
1493
 
1494
   function Last_Index (Container : Vector) return Extended_Index is
1495
   begin
1496
      return Container.Last;
1497
   end Last_Index;
1498
 
1499
   ------------
1500
   -- Length --
1501
   ------------
1502
 
1503
   function Length (Container : Vector) return Count_Type is
1504
      L : constant Int := Int (Container.Last);
1505
      F : constant Int := Int (Index_Type'First);
1506
      N : constant Int'Base := L - F + 1;
1507
 
1508
   begin
1509
      return Count_Type (N);
1510
   end Length;
1511
 
1512
   ----------
1513
   -- Move --
1514
   ----------
1515
 
1516
   procedure Move
1517
     (Target : in out Vector;
1518
      Source : in out Vector)
1519
   is
1520
   begin
1521
      if Target'Address = Source'Address then
1522
         return;
1523
      end if;
1524
 
1525
      if Target.Busy > 0 then
1526
         raise Program_Error with
1527
           "attempt to tamper with elements (Target is busy)";
1528
      end if;
1529
 
1530
      if Source.Busy > 0 then
1531
         raise Program_Error with
1532
           "attempt to tamper with elements (Source is busy)";
1533
      end if;
1534
 
1535
      declare
1536
         Target_Elements : constant Elements_Access := Target.Elements;
1537
      begin
1538
         Target.Elements := Source.Elements;
1539
         Source.Elements := Target_Elements;
1540
      end;
1541
 
1542
      Target.Last := Source.Last;
1543
      Source.Last := No_Index;
1544
   end Move;
1545
 
1546
   ----------
1547
   -- Next --
1548
   ----------
1549
 
1550
   function Next (Position : Cursor) return Cursor is
1551
   begin
1552
      if Position.Container = null then
1553
         return No_Element;
1554
      end if;
1555
 
1556
      if Position.Index < Position.Container.Last then
1557
         return (Position.Container, Position.Index + 1);
1558
      end if;
1559
 
1560
      return No_Element;
1561
   end Next;
1562
 
1563
   ----------
1564
   -- Next --
1565
   ----------
1566
 
1567
   procedure Next (Position : in out Cursor) is
1568
   begin
1569
      if Position.Container = null then
1570
         return;
1571
      end if;
1572
 
1573
      if Position.Index < Position.Container.Last then
1574
         Position.Index := Position.Index + 1;
1575
      else
1576
         Position := No_Element;
1577
      end if;
1578
   end Next;
1579
 
1580
   -------------
1581
   -- Prepend --
1582
   -------------
1583
 
1584
   procedure Prepend (Container : in out Vector; New_Item : Vector) is
1585
   begin
1586
      Insert (Container, Index_Type'First, New_Item);
1587
   end Prepend;
1588
 
1589
   procedure Prepend
1590
     (Container : in out Vector;
1591
      New_Item  : Element_Type;
1592
      Count     : Count_Type := 1)
1593
   is
1594
   begin
1595
      Insert (Container,
1596
              Index_Type'First,
1597
              New_Item,
1598
              Count);
1599
   end Prepend;
1600
 
1601
   --------------
1602
   -- Previous --
1603
   --------------
1604
 
1605
   procedure Previous (Position : in out Cursor) is
1606
   begin
1607
      if Position.Container = null then
1608
         return;
1609
      end if;
1610
 
1611
      if Position.Index > Index_Type'First then
1612
         Position.Index := Position.Index - 1;
1613
      else
1614
         Position := No_Element;
1615
      end if;
1616
   end Previous;
1617
 
1618
   function Previous (Position : Cursor) return Cursor is
1619
   begin
1620
      if Position.Container = null then
1621
         return No_Element;
1622
      end if;
1623
 
1624
      if Position.Index > Index_Type'First then
1625
         return (Position.Container, Position.Index - 1);
1626
      end if;
1627
 
1628
      return No_Element;
1629
   end Previous;
1630
 
1631
   -------------------
1632
   -- Query_Element --
1633
   -------------------
1634
 
1635
   procedure Query_Element
1636
     (Container : Vector;
1637
      Index     : Index_Type;
1638
      Process   : not null access procedure (Element : Element_Type))
1639
   is
1640
      V : Vector renames Container'Unrestricted_Access.all;
1641
      B : Natural renames V.Busy;
1642
      L : Natural renames V.Lock;
1643
 
1644
   begin
1645
      if Index > Container.Last then
1646
         raise Constraint_Error with "Index is out of range";
1647
      end if;
1648
 
1649
      B := B + 1;
1650
      L := L + 1;
1651
 
1652
      begin
1653
         Process (V.Elements.EA (Index));
1654
      exception
1655
         when others =>
1656
            L := L - 1;
1657
            B := B - 1;
1658
            raise;
1659
      end;
1660
 
1661
      L := L - 1;
1662
      B := B - 1;
1663
   end Query_Element;
1664
 
1665
   procedure Query_Element
1666
     (Position : Cursor;
1667
      Process  : not null access procedure (Element : Element_Type))
1668
   is
1669
   begin
1670
      if Position.Container = null then
1671
         raise Constraint_Error with "Position cursor has no element";
1672
      end if;
1673
 
1674
      Query_Element (Position.Container.all, Position.Index, Process);
1675
   end Query_Element;
1676
 
1677
   ----------
1678
   -- Read --
1679
   ----------
1680
 
1681
   procedure Read
1682
     (Stream    : not null access Root_Stream_Type'Class;
1683
      Container : out Vector)
1684
   is
1685
      Length : Count_Type'Base;
1686
      Last   : Index_Type'Base := No_Index;
1687
 
1688
   begin
1689
      Clear (Container);
1690
 
1691
      Count_Type'Base'Read (Stream, Length);
1692
 
1693
      if Length > Capacity (Container) then
1694
         Reserve_Capacity (Container, Capacity => Length);
1695
      end if;
1696
 
1697
      for J in Count_Type range 1 .. Length loop
1698
         Last := Last + 1;
1699
         Element_Type'Read (Stream, Container.Elements.EA (Last));
1700
         Container.Last := Last;
1701
      end loop;
1702
   end Read;
1703
 
1704
   procedure Read
1705
     (Stream   : not null access Root_Stream_Type'Class;
1706
      Position : out Cursor)
1707
   is
1708
   begin
1709
      raise Program_Error with "attempt to stream vector cursor";
1710
   end Read;
1711
 
1712
   ---------------------
1713
   -- Replace_Element --
1714
   ---------------------
1715
 
1716
   procedure Replace_Element
1717
     (Container : in out Vector;
1718
      Index     : Index_Type;
1719
      New_Item  : Element_Type)
1720
   is
1721
   begin
1722
      if Index > Container.Last then
1723
         raise Constraint_Error with "Index is out of range";
1724
      end if;
1725
 
1726
      if Container.Lock > 0 then
1727
         raise Program_Error with
1728
           "attempt to tamper with cursors (vector is locked)";
1729
      end if;
1730
 
1731
      Container.Elements.EA (Index) := New_Item;
1732
   end Replace_Element;
1733
 
1734
   procedure Replace_Element
1735
     (Container : in out Vector;
1736
      Position  : Cursor;
1737
      New_Item  : Element_Type)
1738
   is
1739
   begin
1740
      if Position.Container = null then
1741
         raise Constraint_Error with "Position cursor has no element";
1742
      end if;
1743
 
1744
      if Position.Container /= Container'Unrestricted_Access then
1745
         raise Program_Error with "Position cursor denotes wrong container";
1746
      end if;
1747
 
1748
      if Position.Index > Container.Last then
1749
         raise Constraint_Error with "Position cursor is out of range";
1750
      end if;
1751
 
1752
      if Container.Lock > 0 then
1753
         raise Program_Error with
1754
           "attempt to tamper with cursors (vector is locked)";
1755
      end if;
1756
 
1757
      Container.Elements.EA (Position.Index) := New_Item;
1758
   end Replace_Element;
1759
 
1760
   ----------------------
1761
   -- Reserve_Capacity --
1762
   ----------------------
1763
 
1764
   procedure Reserve_Capacity
1765
     (Container : in out Vector;
1766
      Capacity  : Count_Type)
1767
   is
1768
      N : constant Count_Type := Length (Container);
1769
 
1770
   begin
1771
      if Capacity = 0 then
1772
         if N = 0 then
1773
            declare
1774
               X : Elements_Access := Container.Elements;
1775
            begin
1776
               Container.Elements := null;
1777
               Free (X);
1778
            end;
1779
 
1780
         elsif N < Container.Elements.EA'Length then
1781
            if Container.Busy > 0 then
1782
               raise Program_Error with
1783
                 "attempt to tamper with elements (vector is busy)";
1784
            end if;
1785
 
1786
            declare
1787
               subtype Src_Index_Subtype is Index_Type'Base range
1788
                 Index_Type'First .. Container.Last;
1789
 
1790
               Src : Elements_Array renames
1791
                       Container.Elements.EA (Src_Index_Subtype);
1792
 
1793
               X : Elements_Access := Container.Elements;
1794
 
1795
            begin
1796
               Container.Elements := new Elements_Type'(Container.Last, Src);
1797
               Free (X);
1798
            end;
1799
         end if;
1800
 
1801
         return;
1802
      end if;
1803
 
1804
      if Container.Elements = null then
1805
         declare
1806
            Last_As_Int : constant Int'Base :=
1807
                            Int (Index_Type'First) + Int (Capacity) - 1;
1808
 
1809
         begin
1810
            if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1811
               raise Constraint_Error with "new length is out of range";
1812
            end if;
1813
 
1814
            declare
1815
               Last : constant Index_Type := Index_Type (Last_As_Int);
1816
 
1817
            begin
1818
               Container.Elements := new Elements_Type (Last);
1819
            end;
1820
         end;
1821
 
1822
         return;
1823
      end if;
1824
 
1825
      if Capacity <= N then
1826
         if N < Container.Elements.EA'Length then
1827
            if Container.Busy > 0 then
1828
               raise Program_Error with
1829
                 "attempt to tamper with elements (vector is busy)";
1830
            end if;
1831
 
1832
            declare
1833
               subtype Src_Index_Subtype is Index_Type'Base range
1834
                 Index_Type'First .. Container.Last;
1835
 
1836
               Src : Elements_Array renames
1837
                       Container.Elements.EA (Src_Index_Subtype);
1838
 
1839
               X : Elements_Access := Container.Elements;
1840
 
1841
            begin
1842
               Container.Elements := new Elements_Type'(Container.Last, Src);
1843
               Free (X);
1844
            end;
1845
 
1846
         end if;
1847
 
1848
         return;
1849
      end if;
1850
 
1851
      if Capacity = Container.Elements.EA'Length then
1852
         return;
1853
      end if;
1854
 
1855
      if Container.Busy > 0 then
1856
         raise Program_Error with
1857
           "attempt to tamper with elements (vector is busy)";
1858
      end if;
1859
 
1860
      declare
1861
         Last_As_Int : constant Int'Base :=
1862
                         Int (Index_Type'First) + Int (Capacity) - 1;
1863
 
1864
      begin
1865
         if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1866
            raise Constraint_Error with "new length is out of range";
1867
         end if;
1868
 
1869
         declare
1870
            Last : constant Index_Type := Index_Type (Last_As_Int);
1871
 
1872
            E : Elements_Access := new Elements_Type (Last);
1873
 
1874
         begin
1875
            declare
1876
               subtype Index_Subtype is Index_Type'Base range
1877
                 Index_Type'First .. Container.Last;
1878
 
1879
               Src : Elements_Array renames
1880
                       Container.Elements.EA (Index_Subtype);
1881
 
1882
               Tgt : Elements_Array renames E.EA (Index_Subtype);
1883
 
1884
            begin
1885
               Tgt := Src;
1886
 
1887
            exception
1888
               when others =>
1889
                  Free (E);
1890
                  raise;
1891
            end;
1892
 
1893
            declare
1894
               X : Elements_Access := Container.Elements;
1895
            begin
1896
               Container.Elements := E;
1897
               Free (X);
1898
            end;
1899
         end;
1900
      end;
1901
   end Reserve_Capacity;
1902
 
1903
   ----------------------
1904
   -- Reverse_Elements --
1905
   ----------------------
1906
 
1907
   procedure Reverse_Elements (Container : in out Vector) is
1908
   begin
1909
      if Container.Length <= 1 then
1910
         return;
1911
      end if;
1912
 
1913
      if Container.Lock > 0 then
1914
         raise Program_Error with
1915
           "attempt to tamper with cursors (vector is locked)";
1916
      end if;
1917
 
1918
      declare
1919
         I, J : Index_Type;
1920
         E    : Elements_Type renames Container.Elements.all;
1921
 
1922
      begin
1923
         I := Index_Type'First;
1924
         J := Container.Last;
1925
         while I < J loop
1926
            declare
1927
               EI : constant Element_Type := E.EA (I);
1928
 
1929
            begin
1930
               E.EA (I) := E.EA (J);
1931
               E.EA (J) := EI;
1932
            end;
1933
 
1934
            I := I + 1;
1935
            J := J - 1;
1936
         end loop;
1937
      end;
1938
   end Reverse_Elements;
1939
 
1940
   ------------------
1941
   -- Reverse_Find --
1942
   ------------------
1943
 
1944
   function Reverse_Find
1945
     (Container : Vector;
1946
      Item      : Element_Type;
1947
      Position  : Cursor := No_Element) return Cursor
1948
   is
1949
      Last : Index_Type'Base;
1950
 
1951
   begin
1952
      if Position.Container /= null
1953
        and then Position.Container /= Container'Unchecked_Access
1954
      then
1955
         raise Program_Error with "Position cursor denotes wrong container";
1956
      end if;
1957
 
1958
      Last :=
1959
        (if Position.Container = null or else Position.Index > Container.Last
1960
         then Container.Last
1961
         else Position.Index);
1962
 
1963
      for Indx in reverse Index_Type'First .. Last loop
1964
         if Container.Elements.EA (Indx) = Item then
1965
            return (Container'Unchecked_Access, Indx);
1966
         end if;
1967
      end loop;
1968
 
1969
      return No_Element;
1970
   end Reverse_Find;
1971
 
1972
   ------------------------
1973
   -- Reverse_Find_Index --
1974
   ------------------------
1975
 
1976
   function Reverse_Find_Index
1977
     (Container : Vector;
1978
      Item      : Element_Type;
1979
      Index     : Index_Type := Index_Type'Last) return Extended_Index
1980
   is
1981
      Last : constant Index_Type'Base :=
1982
               Index_Type'Min (Container.Last, Index);
1983
 
1984
   begin
1985
      for Indx in reverse Index_Type'First .. Last loop
1986
         if Container.Elements.EA (Indx) = Item then
1987
            return Indx;
1988
         end if;
1989
      end loop;
1990
 
1991
      return No_Index;
1992
   end Reverse_Find_Index;
1993
 
1994
   ---------------------
1995
   -- Reverse_Iterate --
1996
   ---------------------
1997
 
1998
   procedure Reverse_Iterate
1999
     (Container : Vector;
2000
      Process   : not null access procedure (Position : Cursor))
2001
   is
2002
      V : Vector renames Container'Unrestricted_Access.all;
2003
      B : Natural renames V.Busy;
2004
 
2005
   begin
2006
      B := B + 1;
2007
 
2008
      begin
2009
         for Indx in reverse Index_Type'First .. Container.Last loop
2010
            Process (Cursor'(Container'Unchecked_Access, Indx));
2011
         end loop;
2012
      exception
2013
         when others =>
2014
            B := B - 1;
2015
            raise;
2016
      end;
2017
 
2018
      B := B - 1;
2019
   end Reverse_Iterate;
2020
 
2021
   ----------------
2022
   -- Set_Length --
2023
   ----------------
2024
 
2025
   procedure Set_Length (Container : in out Vector; Length : Count_Type) is
2026
   begin
2027
      if Length = Vectors.Length (Container) then
2028
         return;
2029
      end if;
2030
 
2031
      if Container.Busy > 0 then
2032
         raise Program_Error with
2033
           "attempt to tamper with elements (vector is busy)";
2034
      end if;
2035
 
2036
      if Length > Capacity (Container) then
2037
         Reserve_Capacity (Container, Capacity => Length);
2038
      end if;
2039
 
2040
      declare
2041
         Last_As_Int : constant Int'Base :=
2042
                         Int (Index_Type'First) + Int (Length) - 1;
2043
      begin
2044
         Container.Last := Index_Type'Base (Last_As_Int);
2045
      end;
2046
   end Set_Length;
2047
 
2048
   ----------
2049
   -- Swap --
2050
   ----------
2051
 
2052
   procedure Swap (Container : in out Vector; I, J : Index_Type) is
2053
   begin
2054
      if I > Container.Last then
2055
         raise Constraint_Error with "I index is out of range";
2056
      end if;
2057
 
2058
      if J > Container.Last then
2059
         raise Constraint_Error with "J index is out of range";
2060
      end if;
2061
 
2062
      if I = J then
2063
         return;
2064
      end if;
2065
 
2066
      if Container.Lock > 0 then
2067
         raise Program_Error with
2068
           "attempt to tamper with cursors (vector is locked)";
2069
      end if;
2070
 
2071
      declare
2072
         EI_Copy : constant Element_Type := Container.Elements.EA (I);
2073
      begin
2074
         Container.Elements.EA (I) := Container.Elements.EA (J);
2075
         Container.Elements.EA (J) := EI_Copy;
2076
      end;
2077
   end Swap;
2078
 
2079
   procedure Swap (Container : in out Vector; I, J : Cursor) is
2080
   begin
2081
      if I.Container = null then
2082
         raise Constraint_Error with "I cursor has no element";
2083
      end if;
2084
 
2085
      if J.Container = null then
2086
         raise Constraint_Error with "J cursor has no element";
2087
      end if;
2088
 
2089
      if I.Container /= Container'Unrestricted_Access then
2090
         raise Program_Error with "I cursor denotes wrong container";
2091
      end if;
2092
 
2093
      if J.Container /= Container'Unrestricted_Access then
2094
         raise Program_Error with "J cursor denotes wrong container";
2095
      end if;
2096
 
2097
      Swap (Container, I.Index, J.Index);
2098
   end Swap;
2099
 
2100
   ---------------
2101
   -- To_Cursor --
2102
   ---------------
2103
 
2104
   function To_Cursor
2105
     (Container : Vector;
2106
      Index     : Extended_Index) return Cursor
2107
   is
2108
   begin
2109
      if Index not in Index_Type'First .. Container.Last then
2110
         return No_Element;
2111
      end if;
2112
 
2113
      return Cursor'(Container'Unchecked_Access, Index);
2114
   end To_Cursor;
2115
 
2116
   --------------
2117
   -- To_Index --
2118
   --------------
2119
 
2120
   function To_Index (Position : Cursor) return Extended_Index is
2121
   begin
2122
      if Position.Container = null then
2123
         return No_Index;
2124
      end if;
2125
 
2126
      if Position.Index <= Position.Container.Last then
2127
         return Position.Index;
2128
      end if;
2129
 
2130
      return No_Index;
2131
   end To_Index;
2132
 
2133
   ---------------
2134
   -- To_Vector --
2135
   ---------------
2136
 
2137
   function To_Vector (Length : Count_Type) return Vector is
2138
   begin
2139
      if Length = 0 then
2140
         return Empty_Vector;
2141
      end if;
2142
 
2143
      declare
2144
         First       : constant Int := Int (Index_Type'First);
2145
         Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2146
         Last        : Index_Type;
2147
         Elements    : Elements_Access;
2148
 
2149
      begin
2150
         if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2151
            raise Constraint_Error with "Length is out of range";
2152
         end if;
2153
 
2154
         Last := Index_Type (Last_As_Int);
2155
         Elements := new Elements_Type (Last);
2156
 
2157
         return Vector'(Controlled with Elements, Last, 0, 0);
2158
      end;
2159
   end To_Vector;
2160
 
2161
   function To_Vector
2162
     (New_Item : Element_Type;
2163
      Length   : Count_Type) return Vector
2164
   is
2165
   begin
2166
      if Length = 0 then
2167
         return Empty_Vector;
2168
      end if;
2169
 
2170
      declare
2171
         First       : constant Int := Int (Index_Type'First);
2172
         Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2173
         Last        : Index_Type;
2174
         Elements    : Elements_Access;
2175
 
2176
      begin
2177
         if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2178
            raise Constraint_Error with "Length is out of range";
2179
         end if;
2180
 
2181
         Last := Index_Type (Last_As_Int);
2182
         Elements := new Elements_Type'(Last, EA => (others => New_Item));
2183
 
2184
         return Vector'(Controlled with Elements, Last, 0, 0);
2185
      end;
2186
   end To_Vector;
2187
 
2188
   --------------------
2189
   -- Update_Element --
2190
   --------------------
2191
 
2192
   procedure Update_Element
2193
     (Container : in out Vector;
2194
      Index     : Index_Type;
2195
      Process   : not null access procedure (Element : in out Element_Type))
2196
   is
2197
      B : Natural renames Container.Busy;
2198
      L : Natural renames Container.Lock;
2199
 
2200
   begin
2201
      if Index > Container.Last then
2202
         raise Constraint_Error with "Index is out of range";
2203
      end if;
2204
 
2205
      B := B + 1;
2206
      L := L + 1;
2207
 
2208
      begin
2209
         Process (Container.Elements.EA (Index));
2210
      exception
2211
         when others =>
2212
            L := L - 1;
2213
            B := B - 1;
2214
            raise;
2215
      end;
2216
 
2217
      L := L - 1;
2218
      B := B - 1;
2219
   end Update_Element;
2220
 
2221
   procedure Update_Element
2222
     (Container : in out Vector;
2223
      Position  : Cursor;
2224
      Process   : not null access procedure (Element : in out Element_Type))
2225
   is
2226
   begin
2227
      if Position.Container = null then
2228
         raise Constraint_Error with "Position cursor has no element";
2229
      end if;
2230
 
2231
      if Position.Container /= Container'Unrestricted_Access then
2232
         raise Program_Error with "Position cursor denotes wrong container";
2233
      end if;
2234
 
2235
      Update_Element (Container, Position.Index, Process);
2236
   end Update_Element;
2237
 
2238
   -----------
2239
   -- Write --
2240
   -----------
2241
 
2242
   procedure Write
2243
     (Stream    : not null access Root_Stream_Type'Class;
2244
      Container : Vector)
2245
   is
2246
   begin
2247
      Count_Type'Base'Write (Stream, Length (Container));
2248
 
2249
      for J in Index_Type'First .. Container.Last loop
2250
         Element_Type'Write (Stream, Container.Elements.EA (J));
2251
      end loop;
2252
   end Write;
2253
 
2254
   procedure Write
2255
     (Stream   : not null access Root_Stream_Type'Class;
2256
      Position : Cursor)
2257
   is
2258
   begin
2259
      raise Program_Error with "attempt to stream vector cursor";
2260
   end Write;
2261
 
2262
end Ada.Containers.Vectors;

powered by: WebSVN 2.1.0

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