diff options
author | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-04 13:31:24 +0000 |
---|---|---|
committer | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-04 13:31:24 +0000 |
commit | 8e9d12597759d6626335764fac82795cef78f7be (patch) | |
tree | 44bfd5c7d3bbfa64205b95de570d167845fe6f12 /gcc/ada/a-coinve.adb | |
parent | 210a164419cbbf31544e375344036f30f891dea2 (diff) | |
download | gcc-8e9d12597759d6626335764fac82795cef78f7be.tar.gz |
2005-07-04 Matthew Heaney <heaney@adacore.com>
* a-convec.ads, a-coinve.ads: Declaration of subtype Extended_Index
was changed.
* a-coinve.adb: Perform constraint checks explicitly.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@101597 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/a-coinve.adb')
-rw-r--r-- | gcc/ada/a-coinve.adb | 1075 |
1 files changed, 600 insertions, 475 deletions
diff --git a/gcc/ada/a-coinve.adb b/gcc/ada/a-coinve.adb index ac6a91b4308..be49e39be7f 100644 --- a/gcc/ada/a-coinve.adb +++ b/gcc/ada/a-coinve.adb @@ -76,7 +76,7 @@ package body Ada.Containers.Indefinite_Vectors is end if; exception when others => - for J in Index_Type'First .. Index_Type'Pred (I) loop + for J in Index_Type'First .. I - 1 loop Free (Elements (J)); end loop; @@ -106,7 +106,7 @@ package body Ada.Containers.Indefinite_Vectors is end if; exception when others => - for J in Index_Type'First .. Index_Type'Pred (I) loop + for J in Index_Type'First .. I - 1 loop Free (Elements (J)); end loop; @@ -120,60 +120,67 @@ package body Ada.Containers.Indefinite_Vectors is end if; declare - Last_As_Int : constant Int'Base := + Last_As_Int : constant Int'Base := -- TODO: handle overflow Int (Index_Type'First) + Int (LN) + Int (RN) - 1; - Last : constant Index_Type := Index_Type (Last_As_Int); + begin + if Last_As_Int > Index_Type'Pos (Index_Type'Last) then + raise Constraint_Error; + end if; - LE : Elements_Type renames - Left.Elements (Index_Type'First .. Left.Last); + declare + Last : constant Index_Type := Index_Type (Last_As_Int); - RE : Elements_Type renames - Right.Elements (Index_Type'First .. Right.Last); + LE : Elements_Type renames + Left.Elements (Index_Type'First .. Left.Last); - Elements : Elements_Access := - new Elements_Type (Index_Type'First .. Last); + RE : Elements_Type renames + Right.Elements (Index_Type'First .. Right.Last); - I : Index_Type'Base := Index_Type'Pred (Index_Type'First); + Elements : Elements_Access := + new Elements_Type (Index_Type'First .. Last); - begin - for LI in LE'Range loop - I := Index_Type'Succ (I); + I : Index_Type'Base := No_Index; - begin - if LE (LI) /= null then - Elements (I) := new Element_Type'(LE (LI).all); - end if; - exception - when others => - for J in Index_Type'First .. Index_Type'Pred (I) loop - Free (Elements (J)); - end loop; + begin + for LI in LE'Range loop + I := I + 1; - Free (Elements); - raise; - end; - end loop; + begin + if LE (LI) /= null then + Elements (I) := new Element_Type'(LE (LI).all); + end if; + exception + when others => + for J in Index_Type'First .. I - 1 loop + Free (Elements (J)); + end loop; - for RI in RE'Range loop - I := Index_Type'Succ (I); + Free (Elements); + raise; + end; + end loop; - begin - if RE (RI) /= null then - Elements (I) := new Element_Type'(RE (RI).all); - end if; - exception - when others => - for J in Index_Type'First .. Index_Type'Pred (I) loop - Free (Elements (J)); - end loop; + for RI in RE'Range loop + I := I + 1; - Free (Elements); - raise; - end; - end loop; + begin + if RE (RI) /= null then + Elements (I) := new Element_Type'(RE (RI).all); + end if; + exception + when others => + for J in Index_Type'First .. I - 1 loop + Free (Elements (J)); + end loop; - return (Controlled with Elements, Last, 0, 0); + Free (Elements); + raise; + end; + end loop; + + return (Controlled with Elements, Last, 0, 0); + end; end; end "&"; @@ -205,49 +212,51 @@ package body Ada.Containers.Indefinite_Vectors is Last_As_Int : constant Int'Base := Int (Index_Type'First) + Int (LN); - Last : constant Index_Type := Index_Type (Last_As_Int); + begin + if Last_As_Int > Index_Type'Pos (Index_Type'Last) then + raise Constraint_Error; + end if; - LE : Elements_Type renames - Left.Elements (Index_Type'First .. Left.Last); + declare + Last : constant Index_Type := Index_Type (Last_As_Int); - Elements : Elements_Access := - new Elements_Type (Index_Type'First .. Last); + LE : Elements_Type renames + Left.Elements (Index_Type'First .. Left.Last); + + Elements : Elements_Access := + new Elements_Type (Index_Type'First .. Last); + + begin + for I in LE'Range loop + begin + if LE (I) /= null then + Elements (I) := new Element_Type'(LE (I).all); + end if; + exception + when others => + for J in Index_Type'First .. I - 1 loop + Free (Elements (J)); + end loop; + + Free (Elements); + raise; + end; + end loop; - begin - for I in LE'Range loop begin - if LE (I) /= null then - Elements (I) := new Element_Type'(LE (I).all); - end if; + Elements (Elements'Last) := new Element_Type'(Right); exception when others => - for J in Index_Type'First .. Index_Type'Pred (I) loop + for J in Index_Type'First .. Elements'Last - 1 loop Free (Elements (J)); end loop; Free (Elements); raise; end; - end loop; - - begin - Elements (Elements'Last) := new Element_Type'(Right); - exception - when others => - declare - subtype J_Subtype is Index_Type'Base range - Index_Type'First .. Index_Type'Pred (Elements'Last); - begin - for J in J_Subtype loop - Free (Elements (J)); - end loop; - end; - Free (Elements); - raise; + return (Controlled with Elements, Last, 0, 0); end; - - return (Controlled with Elements, Last, 0, 0); end; end "&"; @@ -279,72 +288,86 @@ package body Ada.Containers.Indefinite_Vectors is Last_As_Int : constant Int'Base := Int (Index_Type'First) + Int (RN); - Last : constant Index_Type := Index_Type (Last_As_Int); - - RE : Elements_Type renames - Right.Elements (Index_Type'First .. Right.Last); + begin + if Last_As_Int > Index_Type'Pos (Index_Type'Last) then + raise Constraint_Error; + end if; - Elements : Elements_Access := - new Elements_Type (Index_Type'First .. Last); + declare + Last : constant Index_Type := Index_Type (Last_As_Int); - I : Index_Type'Base := Index_Type'First; + RE : Elements_Type renames + Right.Elements (Index_Type'First .. Right.Last); - begin - begin - Elements (I) := new Element_Type'(Left); - exception - when others => - Free (Elements); - raise; - end; + Elements : Elements_Access := + new Elements_Type (Index_Type'First .. Last); - for RI in RE'Range loop - I := Index_Type'Succ (I); + I : Index_Type'Base := Index_Type'First; + begin begin - if RE (RI) /= null then - Elements (I) := new Element_Type'(RE (RI).all); - end if; + Elements (I) := new Element_Type'(Left); exception when others => - for J in Index_Type'First .. Index_Type'Pred (I) loop - Free (Elements (J)); - end loop; - Free (Elements); raise; end; - end loop; - return (Controlled with Elements, Last, 0, 0); + for RI in RE'Range loop + I := I + 1; + + begin + if RE (RI) /= null then + Elements (I) := new Element_Type'(RE (RI).all); + end if; + exception + when others => + for J in Index_Type'First .. I - 1 loop + Free (Elements (J)); + end loop; + + Free (Elements); + raise; + end; + end loop; + + return (Controlled with Elements, Last, 0, 0); + end; end; end "&"; function "&" (Left, Right : Element_Type) return Vector is - subtype IT is Index_Type'Base range - Index_Type'First .. Index_Type'Succ (Index_Type'First); + begin + if Index_Type'First >= Index_Type'Last then + raise Constraint_Error; + end if; + + declare + Last : constant Index_Type := Index_Type'First + 1; - Elements : Elements_Access := new Elements_Type (IT); + subtype ET is Elements_Type (Index_Type'First .. Last); - begin + Elements : Elements_Access := new ET; begin - Elements (Elements'First) := new Element_Type'(Left); - exception - when others => - Free (Elements); - raise; - end; + begin + Elements (Elements'First) := new Element_Type'(Left); + exception + when others => + Free (Elements); + raise; + end; - begin - Elements (Elements'Last) := new Element_Type'(Right); - exception - when others => - Free (Elements (Elements'First)); - Free (Elements); - raise; - end; + begin + Elements (Elements'Last) := new Element_Type'(Right); + exception + when others => + Free (Elements (Elements'First)); + Free (Elements); + raise; + end; - return (Controlled with Elements, Elements'Last, 0, 0); + return (Controlled with Elements, Elements'Last, 0, 0); + end; end "&"; --------- @@ -362,17 +385,6 @@ package body Ada.Containers.Indefinite_Vectors is end if; for J in Index_Type'First .. Left.Last loop - -- NOTE: - -- I think it's a bounded error to read or otherwise manipulate - -- an "empty" element, which here means that it has the value - -- null. If it's a bounded error then an exception might - -- propagate, or it might not. We take advantage of that - -- permission here to allow empty elements to be compared. - -- - -- Whether this is the right decision I'm not really sure. If - -- you have a contrary argument then let me know. - -- END NOTE. - if Left.Elements (J) = null then if Right.Elements (J) /= null then return False; @@ -383,7 +395,6 @@ package body Ada.Containers.Indefinite_Vectors is elsif Left.Elements (J).all /= Right.Elements (J).all then return False; - end if; end loop; @@ -396,13 +407,7 @@ package body Ada.Containers.Indefinite_Vectors is procedure Adjust (Container : in out Vector) is begin - if Container.Elements = null then - return; - end if; - - if Container.Elements'Length = 0 - or else Container.Last < Index_Type'First - then + if Container.Last = No_Index then Container.Elements := null; return; end if; @@ -410,6 +415,7 @@ package body Ada.Containers.Indefinite_Vectors is declare E : Elements_Type renames Container.Elements.all; L : constant Index_Type := Container.Last; + begin Container.Elements := null; Container.Last := No_Index; @@ -438,9 +444,13 @@ package body Ada.Containers.Indefinite_Vectors is return; end if; + if Container.Last = Index_Type'Last then + raise Constraint_Error; + end if; + Insert (Container, - Index_Type'Succ (Container.Last), + Container.Last + 1, New_Item); end Append; @@ -454,9 +464,13 @@ package body Ada.Containers.Indefinite_Vectors is return; end if; + if Container.Last = Index_Type'Last then + raise Constraint_Error; + end if; + Insert (Container, - Index_Type'Succ (Container.Last), + Container.Last + 1, New_Item, Count); end Append; @@ -522,12 +536,12 @@ package body Ada.Containers.Indefinite_Vectors is raise Program_Error; end if; - for J in reverse Index_Type'First .. Container.Last loop + while Container.Last >= Index_Type'First loop declare - X : Element_Access := Container.Elements (J); + X : Element_Access := Container.Elements (Container.Last); begin - Container.Elements (J) := null; - Container.Last := Index_Type'Pred (J); + Container.Elements (Container.Last) := null; + Container.Last := Container.Last - 1; Free (X); end; end loop; @@ -575,37 +589,53 @@ package body Ada.Containers.Indefinite_Vectors is end if; declare - I_As_Int : constant Int := Int (Index); - + Index_As_Int : constant Int := Int (Index); Old_Last_As_Int : constant Int := Int (Container.Last); + -- TODO: somewhat vestigial...fix. Count1 : constant Int'Base := Int (Count); - Count2 : constant Int'Base := Old_Last_As_Int - I_As_Int + 1; + Count2 : constant Int'Base := Old_Last_As_Int - Index_As_Int + 1; + N : constant Int'Base := Int'Min (Count1, Count2); - N : constant Int'Base := Int'Min (Count1, Count2); + J_As_Int : constant Int'Base := Index_As_Int + N; + E : Elements_Type renames Container.Elements.all; - J_As_Int : constant Int'Base := I_As_Int + N; - J : constant Index_Type'Base := Index_Type'Base (J_As_Int); + begin + if J_As_Int > Old_Last_As_Int then + while Container.Last >= Index loop + declare + K : constant Index_Type := Container.Last; + X : Element_Access := E (K); - E : Elements_Type renames Container.Elements.all; + begin + E (K) := null; + Container.Last := K - 1; + Free (X); + end; + end loop; - New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N; + else + declare + J : constant Index_Type := Index_Type (J_As_Int); - New_Last : constant Extended_Index := - Extended_Index (New_Last_As_Int); + New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N; + New_Last : constant Index_Type := + Index_Type (New_Last_As_Int); - begin - for K in Index .. Index_Type'Pred (J) loop - declare - X : Element_Access := E (K); begin - E (K) := null; - Free (X); - end; - end loop; + for K in Index .. J - 1 loop + declare + X : Element_Access := E (K); + begin + E (K) := null; + Free (X); + end; + end loop; - E (Index .. New_Last) := E (J .. Container.Last); - Container.Last := New_Last; + E (Index .. New_Last) := E (J .. Container.Last); + Container.Last := New_Last; + end; + end if; end; end Delete; @@ -664,21 +694,35 @@ package body Ada.Containers.Indefinite_Vectors is (Container : in out Vector; Count : Count_Type := 1) is - Index : Int'Base; + N : constant Count_Type := Length (Container); begin - if Count = 0 then + if Count = 0 + or else N = 0 + then return; end if; - if Count >= Length (Container) then - Clear (Container); - return; + if Container.Busy > 0 then + raise Program_Error; end if; - Index := Int'Base (Container.Last) - Int'Base (Count) + 1; + declare + E : Elements_Type renames Container.Elements.all; - Delete (Container, Index_Type'Base (Index), Count); + begin + for Indx in 1 .. Count_Type'Min (Count, N) loop + declare + J : constant Index_Type := Container.Last; + X : Element_Access := E (J); + + begin + E (J) := null; + Container.Last := J - 1; + Free (X); + end; + end loop; + end; end Delete_Last; ------------- @@ -689,14 +733,20 @@ package body Ada.Containers.Indefinite_Vectors is (Container : Vector; Index : Index_Type) return Element_Type is - subtype T is Index_Type'Base range - Index_Type'First .. Container.Last; begin - return Container.Elements (T'(Index)).all; + if Index > Container.Last then + raise Constraint_Error; + end if; + + return Container.Elements (Index).all; end Element; function Element (Position : Cursor) return Element_Type is begin + if Position.Container = null then + raise Constraint_Error; + end if; + return Element (Position.Container.all, Position.Index); end Element; @@ -970,10 +1020,7 @@ package body Ada.Containers.Indefinite_Vectors is New_Last_As_Int : Int'Base; New_Last : Index_Type; - Index : Extended_Index; -- TODO: see note in a-convec.adb. - - Dst_Last : Index_Type; - Dst : Elements_Access; + Dst : Elements_Access; begin if Before < Index_Type'First then @@ -995,6 +1042,11 @@ package body Ada.Containers.Indefinite_Vectors is begin New_Last_As_Int := Old_Last_As_Int + N; + + if New_Last_As_Int > Index_Type'Pos (Index_Type'Last) then + raise Constraint_Error; + end if; + New_Last := Index_Type (New_Last_As_Int); end; @@ -1002,28 +1054,16 @@ package body Ada.Containers.Indefinite_Vectors is raise Program_Error; end if; - declare - Old_First_As_Int : constant Int := Int (Before); - - New_First_As_Int : constant Int'Base := Old_First_As_Int + N; - - begin - Index := Extended_Index (New_First_As_Int); -- TODO - end; - if Container.Elements = null then - declare - subtype Elements_Subtype is - Elements_Type (Index_Type'First .. New_Last); - begin - Container.Elements := new Elements_Subtype; - Container.Last := Index_Type'Pred (Index_Type'First); + Container.Elements := + new Elements_Type (Index_Type'First .. New_Last); - for J in Container.Elements'Range loop - Container.Elements (J) := new Element_Type'(New_Item); - Container.Last := J; - end loop; - end; + Container.Last := No_Index; + + for J in Container.Elements'Range loop + Container.Elements (J) := new Element_Type'(New_Item); + Container.Last := J; + end loop; return; end if; @@ -1032,105 +1072,116 @@ package body Ada.Containers.Indefinite_Vectors is declare E : Elements_Type renames Container.Elements.all; begin - E (Index .. New_Last) := E (Before .. Container.Last); - Container.Last := New_Last; + if Before <= Container.Last then + declare + Index_As_Int : constant Int'Base := + Index_Type'Pos (Before) + N; + + Index : constant Index_Type := Index_Type (Index_As_Int); + + J : Index_Type'Base := Before; - -- NOTE: - -- Now we do the allocation. If it fails, we can propagate the - -- exception and invariants are more or less satisfied. The - -- issue is that we have some slots still null, and the client - -- has no way of detecting whether the slot is null (unless we - -- give him a way). - -- - -- Another way is to allocate a subarray on the stack, do the - -- allocation into that array, and if that success then do - -- the insertion proper. The issue there is that you have to - -- allocate the subarray on the stack, and that may fail if the - -- subarray is long. - -- - -- Or we could try to roll-back the changes: deallocate the - -- elements we have successfully deallocated, and then copy - -- the elements ptrs back to their original posns. - -- END NOTE. - - -- NOTE: I have written the loop manually here. I could - -- have done it this way too: - -- E (Before .. Index_Type'Pred (Index)) := - -- (others => new Element_Type'New_Item); - -- END NOTE. - - for J in Before .. Index_Type'Pred (Index) loop begin - E (J) := new Element_Type'(New_Item); + E (Index .. New_Last) := E (Before .. Container.Last); + Container.Last := New_Last; + + while J < Index loop + E (J) := new Element_Type'(New_Item); + J := J + 1; + end loop; exception when others => - E (J .. Index_Type'Pred (Index)) := (others => null); + E (J .. Index - 1) := (others => null); raise; end; - end loop; + + else + for J in Before .. New_Last loop + E (J) := new Element_Type'(New_Item); + Container.Last := J; + end loop; + end if; end; return; end if; declare - First : constant Int := Int (Index_Type'First); - + First : constant Int := Int (Index_Type'First); New_Size : constant Int'Base := New_Last_As_Int - First + 1; - Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1; - - Size, Dst_Last_As_Int : Int'Base; + Size : Int'Base := Int'Max (1, Container.Elements'Length); begin - if New_Size >= Max_Size / 2 then - Dst_Last := Index_Type'Last; + while Size < New_Size loop + if Size > Int'Last / 2 then + Size := Int'Last; + exit; + end if; - else - Size := Container.Elements'Length; + Size := 2 * Size; + end loop; - if Size = 0 then - Size := 1; - end if; + -- TODO: The following calculations aren't quite right, since + -- there will be overflow if Index_Type'Range is very large + -- (e.g. this package is instantiated with a 64-bit integer). + -- END TODO. - while Size < New_Size loop - Size := 2 * Size; - end loop; + declare + Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1; + begin + if Size > Max_Size then + Size := Max_Size; + end if; + end; - Dst_Last_As_Int := First + Size - 1; - Dst_Last := Index_Type (Dst_Last_As_Int); - end if; + declare + Dst_Last : constant Index_Type := Index_Type (First + Size - 1); + begin + Dst := new Elements_Type (Index_Type'First .. Dst_Last); + end; end; - Dst := new Elements_Type (Index_Type'First .. Dst_Last); + if Before <= Container.Last then + declare + Index_As_Int : constant Int'Base := + Index_Type'Pos (Before) + N; - declare - Src : Elements_Type renames Container.Elements.all; + Index : constant Index_Type := Index_Type (Index_As_Int); - begin - Dst (Index_Type'First .. Index_Type'Pred (Before)) := - Src (Index_Type'First .. Index_Type'Pred (Before)); + Src : Elements_Access := Container.Elements; - Dst (Index .. New_Last) := Src (Before .. Container.Last); - end; + begin + Dst (Index_Type'First .. Before - 1) := + Src (Index_Type'First .. Before - 1); - declare - X : Elements_Access := Container.Elements; - begin - Container.Elements := Dst; - Container.Last := New_Last; + Dst (Index .. New_Last) := Src (Before .. Container.Last); - Free (X); - end; + Container.Elements := Dst; + Container.Last := New_Last; + Free (Src); + + for J in Before .. Index - 1 loop + Dst (J) := new Element_Type'(New_Item); + end loop; + end; - -- NOTE: - -- Now do the allocation. If the allocation fails, - -- then the worst thing is that we have a few null slots. - -- Our invariants are otherwise satisfied. - -- END NOTE. + else + declare + Src : Elements_Access := Container.Elements; - for J in Before .. Index_Type'Pred (Index) loop - Dst (J) := new Element_Type'(New_Item); - end loop; + begin + Dst (Index_Type'First .. Container.Last) := + Src (Index_Type'First .. Container.Last); + + Container.Elements := Dst; + Free (Src); + + for J in Before .. New_Last loop + Dst (J) := new Element_Type'(New_Item); + Container.Last := J; + end loop; + end; + end if; end Insert; procedure Insert @@ -1157,29 +1208,26 @@ package body Ada.Containers.Indefinite_Vectors is Insert_Space (Container, Before, Count => N); - if Container'Address = New_Item'Address then - declare - Dst_Last_As_Int : constant Int'Base := - Int'Base (Before) + Int'Base (N) - 1; + declare + Dst_Last_As_Int : constant Int'Base := + Int'Base (Before) + Int'Base (N) - 1; - Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int); + Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int); - Dst_Index : Index_Type'Base := Index_Type'Pred (Before); + Dst : Elements_Type renames + Container.Elements (Before .. Dst_Last); - Dst : Elements_Type renames - Container.Elements (Before .. Dst_Last); + Dst_Index : Index_Type'Base := Before - 1; - begin + begin + if Container'Address /= New_Item'Address then declare - subtype Src_Index_Subtype is Index_Type'Base range - Index_Type'First .. Index_Type'Pred (Before); - Src : Elements_Type renames - Container.Elements (Src_Index_Subtype); + New_Item.Elements (Index_Type'First .. New_Item.Last); begin for Src_Index in Src'Range loop - Dst_Index := Index_Type'Succ (Dst_Index); + Dst_Index := Dst_Index + 1; if Src (Src_Index) /= null then Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all); @@ -1187,49 +1235,47 @@ package body Ada.Containers.Indefinite_Vectors is end loop; end; - declare - subtype Src_Index_Subtype is Index_Type'Base range - Index_Type'Succ (Dst_Last) .. Container.Last; + return; + end if; - Src : Elements_Type renames - Container.Elements (Src_Index_Subtype); + declare + subtype Src_Index_Subtype is Index_Type'Base range + Index_Type'First .. Before - 1; - begin - for Src_Index in Src'Range loop - Dst_Index := Index_Type'Succ (Dst_Index); + Src : Elements_Type renames + Container.Elements (Src_Index_Subtype); - if Src (Src_Index) /= null then - Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all); - end if; - end loop; - end; - end; + begin + for Src_Index in Src'Range loop + Dst_Index := Dst_Index + 1; - else - declare - Dst_Last_As_Int : constant Int'Base := - Int'Base (Before) + Int'Base (N) - 1; + if Src (Src_Index) /= null then + Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all); + end if; + end loop; + end; - Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int); + if Dst_Last = Container.Last then + return; + end if; - Dst_Index : Index_Type'Base := Index_Type'Pred (Before); + declare + subtype Src_Index_Subtype is Index_Type'Base range + Dst_Last + 1 .. Container.Last; Src : Elements_Type renames - New_Item.Elements (Index_Type'First .. New_Item.Last); + Container.Elements (Src_Index_Subtype); - Dst : Elements_Type renames - Container.Elements (Before .. Dst_Last); begin for Src_Index in Src'Range loop - Dst_Index := Index_Type'Succ (Dst_Index); + Dst_Index := Dst_Index + 1; if Src (Src_Index) /= null then Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all); end if; end loop; end; - - end if; + end; end Insert; procedure Insert @@ -1253,7 +1299,12 @@ package body Ada.Containers.Indefinite_Vectors is if Before.Container = null or else Before.Index > Container.Last then - Index := Index_Type'Succ (Container.Last); + if Container.Last = Index_Type'Last then + raise Constraint_Error; + end if; + + Index := Container.Last + 1; + else Index := Before.Index; end if; @@ -1291,7 +1342,12 @@ package body Ada.Containers.Indefinite_Vectors is if Before.Container = null or else Before.Index > Container.Last then - Index := Index_Type'Succ (Container.Last); + if Container.Last = Index_Type'Last then + raise Constraint_Error; + end if; + + Index := Container.Last + 1; + else Index := Before.Index; end if; @@ -1323,7 +1379,12 @@ package body Ada.Containers.Indefinite_Vectors is if Before.Container = null or else Before.Index > Container.Last then - Index := Index_Type'Succ (Container.Last); + if Container.Last = Index_Type'Last then + raise Constraint_Error; + end if; + + Index := Container.Last + 1; + else Index := Before.Index; end if; @@ -1362,7 +1423,12 @@ package body Ada.Containers.Indefinite_Vectors is if Before.Container = null or else Before.Index > Container.Last then - Index := Index_Type'Succ (Container.Last); + if Container.Last = Index_Type'Last then + raise Constraint_Error; + end if; + + Index := Container.Last + 1; + else Index := Before.Index; end if; @@ -1386,10 +1452,7 @@ package body Ada.Containers.Indefinite_Vectors is New_Last_As_Int : Int'Base; New_Last : Index_Type; - Index : Extended_Index; -- TODO: see a-convec.adb. - - Dst_Last : Index_Type; - Dst : Elements_Access; + Dst : Elements_Access; begin if Before < Index_Type'First then @@ -1411,6 +1474,11 @@ package body Ada.Containers.Indefinite_Vectors is begin New_Last_As_Int := Old_Last_As_Int + N; + + if New_Last_As_Int > Index_Type'Pos (Index_Type'Last) then + raise Constraint_Error; + end if; + New_Last := Index_Type (New_Last_As_Int); end; @@ -1418,90 +1486,98 @@ package body Ada.Containers.Indefinite_Vectors is raise Program_Error; end if; - declare - Old_First_As_Int : constant Int := Int (Before); - - New_First_As_Int : constant Int'Base := Old_First_As_Int + N; - - begin - Index := Extended_Index (New_First_As_Int); -- TODO - end; - if Container.Elements = null then - declare - subtype Elements_Subtype is - Elements_Type (Index_Type'First .. New_Last); - begin - Container.Elements := new Elements_Subtype; - Container.Last := New_Last; - end; + Container.Elements := + new Elements_Type (Index_Type'First .. New_Last); + Container.Last := New_Last; return; end if; if New_Last <= Container.Elements'Last then declare E : Elements_Type renames Container.Elements.all; + begin - E (Index .. New_Last) := E (Before .. Container.Last); - E (Before .. Index_Type'Pred (Index)) := (others => null); + if Before <= Container.Last then + declare + Index_As_Int : constant Int'Base := + Index_Type'Pos (Before) + N; - Container.Last := New_Last; + Index : constant Index_Type := Index_Type (Index_As_Int); + + begin + E (Index .. New_Last) := E (Before .. Container.Last); + E (Before .. Index - 1) := (others => null); + end; + end if; end; + Container.Last := New_Last; return; end if; declare - First : constant Int := Int (Index_Type'First); - - New_Size : constant Int'Base := - Int (New_Last_As_Int) - First + 1; - - Max_Size : constant Int'Base := - Int (Index_Type'Last) - First + 1; - - Size, Dst_Last_As_Int : Int'Base; + First : constant Int := Int (Index_Type'First); + New_Size : constant Int'Base := New_Last_As_Int - First + 1; + Size : Int'Base := Int'Max (1, Container.Elements'Length); begin - if New_Size >= Max_Size / 2 then - Dst_Last := Index_Type'Last; + while Size < New_Size loop + if Size > Int'Last / 2 then + Size := Int'Last; + exit; + end if; - else - Size := Container.Elements'Length; + Size := 2 * Size; + end loop; - if Size = 0 then - Size := 1; - end if; + -- TODO: The following calculations aren't quite right, since + -- there will be overflow if Index_Type'Range is very large + -- (e.g. this package is instantiated with a 64-bit integer). + -- END TODO. - while Size < New_Size loop - Size := 2 * Size; - end loop; + declare + Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1; + begin + if Size > Max_Size then + Size := Max_Size; + end if; + end; - Dst_Last_As_Int := First + Size - 1; - Dst_Last := Index_Type (Dst_Last_As_Int); - end if; + declare + Dst_Last : constant Index_Type := Index_Type (First + Size - 1); + begin + Dst := new Elements_Type (Index_Type'First .. Dst_Last); + end; end; - Dst := new Elements_Type (Index_Type'First .. Dst_Last); - declare - Src : Elements_Type renames Container.Elements.all; + Src : Elements_Access := Container.Elements; begin - Dst (Index_Type'First .. Index_Type'Pred (Before)) := - Src (Index_Type'First .. Index_Type'Pred (Before)); + if Before <= Container.Last then + declare + Index_As_Int : constant Int'Base := + Index_Type'Pos (Before) + N; - Dst (Index .. New_Last) := Src (Before .. Container.Last); - end; + Index : constant Index_Type := Index_Type (Index_As_Int); + + begin + Dst (Index_Type'First .. Before - 1) := + Src (Index_Type'First .. Before - 1); + + Dst (Index .. New_Last) := Src (Before .. Container.Last); + end; + + else + Dst (Index_Type'First .. Container.Last) := + Src (Index_Type'First .. Container.Last); + end if; - declare - X : Elements_Access := Container.Elements; - begin Container.Elements := Dst; Container.Last := New_Last; - - Free (X); + Free (Src); end; end Insert_Space; @@ -1535,7 +1611,12 @@ package body Ada.Containers.Indefinite_Vectors is if Before.Container = null or else Before.Index > Container.Last then - Index := Index_Type'Succ (Container.Last); + if Container.Last = Index_Type'Last then + raise Constraint_Error; + end if; + + Index := Container.Last + 1; + else Index := Before.Index; end if; @@ -1620,7 +1701,12 @@ package body Ada.Containers.Indefinite_Vectors is L : constant Int := Int (Container.Last); F : constant Int := Int (Index_Type'First); N : constant Int'Base := L - F + 1; + begin + if N > Count_Type'Pos (Count_Type'Last) then + raise Constraint_Error; + end if; + return Count_Type (N); end Length; @@ -1644,16 +1730,13 @@ package body Ada.Containers.Indefinite_Vectors is Clear (Target); declare - X : Elements_Access := Target.Elements; + Target_Elements : constant Elements_Access := Target.Elements; begin - Target.Elements := null; - Free (X); + Target.Elements := Source.Elements; + Source.Elements := Target_Elements; end; - Target.Elements := Source.Elements; Target.Last := Source.Last; - - Source.Elements := null; Source.Last := No_Index; end Move; @@ -1668,7 +1751,7 @@ package body Ada.Containers.Indefinite_Vectors is end if; if Position.Index < Position.Container.Last then - return (Position.Container, Index_Type'Succ (Position.Index)); + return (Position.Container, Position.Index + 1); end if; return No_Element; @@ -1685,7 +1768,7 @@ package body Ada.Containers.Indefinite_Vectors is end if; if Position.Index < Position.Container.Last then - Position.Index := Index_Type'Succ (Position.Index); + Position.Index := Position.Index + 1; else Position := No_Element; end if; @@ -1723,7 +1806,7 @@ package body Ada.Containers.Indefinite_Vectors is end if; if Position.Index > Index_Type'First then - Position.Index := Index_Type'Pred (Position.Index); + Position.Index := Position.Index - 1; else Position := No_Element; end if; @@ -1736,7 +1819,7 @@ package body Ada.Containers.Indefinite_Vectors is end if; if Position.Index > Index_Type'First then - return (Position.Container, Index_Type'Pred (Position.Index)); + return (Position.Container, Position.Index - 1); end if; return No_Element; @@ -1751,21 +1834,20 @@ package body Ada.Containers.Indefinite_Vectors is Index : Index_Type; Process : not null access procedure (Element : in Element_Type)) is - subtype T is Index_Type'Base range - Index_Type'First .. Container.Last; - - E : Element_Type renames Container.Elements (T'(Index)).all; - V : Vector renames Container'Unrestricted_Access.all; B : Natural renames V.Busy; L : Natural renames V.Lock; begin + if Index > Container.Last then + raise Constraint_Error; + end if; + B := B + 1; L := L + 1; begin - Process (E); + Process (V.Elements (Index).all); exception when others => L := L - 1; @@ -1782,6 +1864,10 @@ package body Ada.Containers.Indefinite_Vectors is Process : not null access procedure (Element : in Element_Type)) is begin + if Position.Container = null then + raise Constraint_Error; + end if; + Query_Element (Position.Container.all, Position.Index, Process); end Query_Element; @@ -1808,7 +1894,7 @@ package body Ada.Containers.Indefinite_Vectors is end if; for J in Count_Type range 1 .. Length loop - Last := Index_Type'Succ (Last); + Last := Last + 1; Boolean'Read (Stream, B); @@ -1830,22 +1916,29 @@ package body Ada.Containers.Indefinite_Vectors is Index : Index_Type; By : Element_Type) is - subtype T is Index_Type'Base range - Index_Type'First .. Container.Last; - - X : Element_Access := Container.Elements (T'(Index)); - begin + if Index > Container.Last then + raise Constraint_Error; + end if; + if Container.Lock > 0 then raise Program_Error; end if; - Container.Elements (T'(Index)) := new Element_Type'(By); - Free (X); + declare + X : Element_Access := Container.Elements (Index); + begin + Container.Elements (Index) := new Element_Type'(By); + Free (X); + end; end Replace_Element; procedure Replace_Element (Position : Cursor; By : Element_Type) is begin + if Position.Container = null then + raise Constraint_Error; + end if; + Replace_Element (Position.Container.all, Position.Index, By); end Replace_Element; @@ -1885,11 +1978,11 @@ package body Ada.Containers.Indefinite_Vectors is Elements_Type (Array_Index_Subtype); X : Elements_Access := Container.Elements; + begin Container.Elements := new Array_Subtype'(Src); Free (X); end; - end if; return; @@ -1900,14 +1993,20 @@ package body Ada.Containers.Indefinite_Vectors is Last_As_Int : constant Int'Base := Int (Index_Type'First) + Int (Capacity) - 1; - Last : constant Index_Type := - Index_Type (Last_As_Int); + begin + if Last_As_Int > Index_Type'Pos (Index_Type'Last) then + raise Constraint_Error; + end if; - subtype Array_Subtype is - Elements_Type (Index_Type'First .. Last); + declare + Last : constant Index_Type := Index_Type (Last_As_Int); - begin - Container.Elements := new Array_Subtype; + subtype Array_Subtype is + Elements_Type (Index_Type'First .. Last); + + begin + Container.Elements := new Array_Subtype; + end; end; return; @@ -1935,7 +2034,6 @@ package body Ada.Containers.Indefinite_Vectors is Container.Elements := new Array_Subtype'(Src); Free (X); end; - end if; return; @@ -1953,28 +2051,35 @@ package body Ada.Containers.Indefinite_Vectors is Last_As_Int : constant Int'Base := Int (Index_Type'First) + Int (Capacity) - 1; - Last : constant Index_Type := Index_Type (Last_As_Int); - - subtype Array_Subtype is - Elements_Type (Index_Type'First .. Last); - - X : Elements_Access := Container.Elements; - begin - Container.Elements := new Array_Subtype; + if Last_As_Int > Index_Type'Pos (Index_Type'Last) then + raise Constraint_Error; + end if; declare - Src : Elements_Type renames - X (Index_Type'First .. Container.Last); + Last : constant Index_Type := Index_Type (Last_As_Int); + + subtype Array_Subtype is + Elements_Type (Index_Type'First .. Last); - Tgt : Elements_Type renames - Container.Elements (Index_Type'First .. Container.Last); + X : Elements_Access := Container.Elements; begin - Tgt := Src; - end; + Container.Elements := new Array_Subtype; - Free (X); + declare + Src : Elements_Type renames + X (Index_Type'First .. Container.Last); + + Tgt : Elements_Type renames + Container.Elements (Index_Type'First .. Container.Last); + + begin + Tgt := Src; + end; + + Free (X); + end; end; end Reserve_Capacity; @@ -2087,42 +2192,36 @@ package body Ada.Containers.Indefinite_Vectors is return; end if; - if Length = 0 then - Clear (Container); - return; - end if; - if Container.Busy > 0 then raise Program_Error; end if; - declare - Last_As_Int : constant Int'Base := - Int (Index_Type'First) + Int (Length) - 1; - - Last : constant Index_Type := - Index_Type (Last_As_Int); - - begin - if Length > N then - if Length > Capacity (Container) then - Reserve_Capacity (Container, Capacity => Length); - end if; - - Container.Last := Last; - return; - end if; - - for Indx in reverse Index_Type'Succ (Last) .. Container.Last loop + if Length < N then + for Index in 1 .. N - Length loop declare - X : Element_Access := Container.Elements (Indx); + J : constant Index_Type := Container.Last; + X : Element_Access := Container.Elements (J); begin - Container.Elements (Indx) := null; - Container.Last := Index_Type'Pred (Container.Last); + Container.Elements (J) := null; + Container.Last := J - 1; Free (X); end; end loop; + + return; + end if; + + if Length > Capacity (Container) then + Reserve_Capacity (Container, Capacity => Length); + end if; + + declare + Last_As_Int : constant Int'Base := + Int (Index_Type'First) + Int (Length) - 1; + + begin + Container.Last := Index_Type (Last_As_Int); end; end Set_Length; @@ -2134,19 +2233,27 @@ package body Ada.Containers.Indefinite_Vectors is (Container : Vector; I, J : Index_Type) is - subtype T is Index_Type'Base range - Index_Type'First .. Container.Last; + begin + if I > Container.Last + or else J > Container.Last + then + raise Constraint_Error; + end if; - EI : Element_Type renames Container.Elements (T'(I)).all; - EJ : Element_Type renames Container.Elements (T'(J)).all; + if I = J then + return; + end if; - begin if Container.Lock > 0 then raise Program_Error; end if; declare - EI_Copy : constant Element_Type := EI; + EI : Element_Access renames Container.Elements (I); + EJ : Element_Access renames Container.Elements (J); + + EI_Copy : constant Element_Access := EI; + begin EI := EJ; EJ := EI_Copy; @@ -2215,10 +2322,17 @@ package body Ada.Containers.Indefinite_Vectors is declare First : constant Int := Int (Index_Type'First); Last_As_Int : constant Int'Base := First + Int (Length) - 1; - Last : constant Index_Type := Index_Type (Last_As_Int); - Elements : constant Elements_Access := - new Elements_Type (Index_Type'First .. Last); + Last : Index_Type; + Elements : Elements_Access; + begin + if Last_As_Int > Index_Type'Pos (Index_Type'Last) then + raise Constraint_Error; + end if; + + Last := Index_Type (Last_As_Int); + Elements := new Elements_Type (Index_Type'First .. Last); + return (Controlled with Elements, Last, 0, 0); end; end To_Vector; @@ -2235,24 +2349,34 @@ package body Ada.Containers.Indefinite_Vectors is declare First : constant Int := Int (Index_Type'First); Last_As_Int : constant Int'Base := First + Int (Length) - 1; - Last : constant Index_Type := Index_Type (Last_As_Int); - Elements : Elements_Access := - new Elements_Type (Index_Type'First .. Last); + Last : Index_Type'Base; + Elements : Elements_Access; + begin - for Indx in Elements'Range loop - begin - Elements (Indx) := new Element_Type'(New_Item); - exception - when others => - for J in Index_Type'First .. Index_Type'Pred (Indx) loop - Free (Elements (J)); - end loop; + if Last_As_Int > Index_Type'Pos (Index_Type'Last) then + raise Constraint_Error; + end if; - Free (Elements); - raise; - end; + Last := Index_Type (Last_As_Int); + Elements := new Elements_Type (Index_Type'First .. Last); - end loop; + Last := Index_Type'First; + + begin + loop + Elements (Last) := new Element_Type'(New_Item); + exit when Last = Elements'Last; + Last := Last + 1; + end loop; + exception + when others => + for J in Index_Type'First .. Last - 1 loop + Free (Elements (J)); + end loop; + + Free (Elements); + raise; + end; return (Controlled with Elements, Last, 0, 0); end; @@ -2267,21 +2391,20 @@ package body Ada.Containers.Indefinite_Vectors is Index : Index_Type; Process : not null access procedure (Element : in out Element_Type)) is - subtype T is Index_Type'Base range - Index_Type'First .. Container.Last; - - E : Element_Type renames Container.Elements (T'(Index)).all; - V : Vector renames Container'Unrestricted_Access.all; B : Natural renames V.Busy; L : Natural renames V.Lock; begin + if Index > Container.Last then + raise Constraint_Error; + end if; + B := B + 1; L := L + 1; begin - Process (E); + Process (V.Elements (Index).all); exception when others => L := L - 1; @@ -2298,6 +2421,10 @@ package body Ada.Containers.Indefinite_Vectors is Process : not null access procedure (Element : in out Element_Type)) is begin + if Position.Container = null then + raise Constraint_Error; + end if; + Update_Element (Position.Container.all, Position.Index, Process); end Update_Element; @@ -2327,9 +2454,7 @@ package body Ada.Containers.Indefinite_Vectors is -- There's another way to do this. Instead a separate -- Boolean for each element, you could write a Boolean -- followed by a count of how many nulls or non-nulls - -- follow in the array. Alternately you could use a - -- signed integer, and use the sign as the indicator - -- of null-ness. + -- follow in the array. if E (Indx) = null then Boolean'Write (Stream, False); |