diff options
Diffstat (limited to 'gcc/ada/a-stwise.adb')
-rw-r--r-- | gcc/ada/a-stwise.adb | 270 |
1 files changed, 208 insertions, 62 deletions
diff --git a/gcc/ada/a-stwise.adb b/gcc/ada/a-stwise.adb index d522315831c..3add82b6d1e 100644 --- a/gcc/ada/a-stwise.adb +++ b/gcc/ada/a-stwise.adb @@ -30,6 +30,7 @@ ------------------------------------------------------------------------------ with Ada.Strings.Wide_Maps; use Ada.Strings.Wide_Maps; +with System; use System; package body Ada.Strings.Wide_Search is @@ -72,44 +73,55 @@ package body Ada.Strings.Wide_Search is Mapping : Wide_Maps.Wide_Character_Mapping := Wide_Maps.Identity) return Natural is - N : Natural; - J : Natural; - + PL1 : constant Integer := Pattern'Length - 1; + Num : Natural; + Ind : Natural; + Cur : Natural; begin if Pattern = "" then raise Pattern_Error; end if; - -- Handle the case of non-identity mappings by creating a mapped - -- string and making a recursive call using the identity mapping - -- on this mapped string. + Num := 0; + Ind := Source'First; + + -- Unmapped case + + if Mapping'Address = Wide_Maps.Identity'Address then + while Ind <= Source'Last - PL1 loop + if Pattern = Source (Ind .. Ind + PL1) then + Num := Num + 1; + Ind := Ind + Pattern'Length; + else + Ind := Ind + 1; + end if; + end loop; - if Mapping /= Wide_Maps.Identity then - declare - Mapped_Source : Wide_String (Source'Range); + -- Mapped case - begin - for J in Source'Range loop - Mapped_Source (J) := Value (Mapping, Source (J)); + else + while Ind <= Source'Last - PL1 loop + Cur := Ind; + for K in Pattern'Range loop + if Pattern (K) /= Value (Mapping, Source (Cur)) then + Ind := Ind + 1; + goto Cont; + else + Cur := Cur + 1; + end if; end loop; - return Count (Mapped_Source, Pattern); - end; - end if; + Num := Num + 1; + Ind := Ind + Pattern'Length; - N := 0; - J := Source'First; + <<Cont>> + null; + end loop; + end if; - while J <= Source'Last - (Pattern'Length - 1) loop - if Source (J .. J + (Pattern'Length - 1)) = Pattern then - N := N + 1; - J := J + Pattern'Length; - else - J := J + 1; - end if; - end loop; + -- Return result - return N; + return Num; end Count; function Count @@ -117,14 +129,43 @@ package body Ada.Strings.Wide_Search is Pattern : Wide_String; Mapping : Wide_Maps.Wide_Character_Mapping_Function) return Natural is - Mapped_Source : Wide_String (Source'Range); + PL1 : constant Integer := Pattern'Length - 1; + Num : Natural; + Ind : Natural; + Cur : Natural; begin - for J in Source'Range loop - Mapped_Source (J) := Mapping (Source (J)); + if Pattern = "" then + raise Pattern_Error; + end if; + + -- Check for null pointer in case checks are off + + if Mapping = null then + raise Constraint_Error; + end if; + + Num := 0; + Ind := Source'First; + while Ind <= Source'Last - PL1 loop + Cur := Ind; + for K in Pattern'Range loop + if Pattern (K) /= Mapping (Source (Cur)) then + Ind := Ind + 1; + goto Cont; + else + Cur := Cur + 1; + end if; + end loop; + + Num := Num + 1; + Ind := Ind + Pattern'Length; + + <<Cont>> + null; end loop; - return Count (Mapped_Source, Pattern); + return Num; end Count; function Count @@ -166,8 +207,8 @@ package body Ada.Strings.Wide_Search is end if; end loop; - -- Here if J indexes 1st char of token, and all chars - -- after J are in the token + -- Here if J indexes first char of token, and all chars after J + -- are in the token. Last := Source'Last; return; @@ -191,41 +232,88 @@ package body Ada.Strings.Wide_Search is Mapping : Wide_Maps.Wide_Character_Mapping := Wide_Maps.Identity) return Natural is + PL1 : constant Integer := Pattern'Length - 1; + Ind : Natural; + Cur : Natural; + begin if Pattern = "" then raise Pattern_Error; end if; - -- Handle the case of non-identity mappings by creating a mapped - -- string and making a recursive call using the identity mapping - -- on this mapped string. + -- Forwards case + + if Going = Forward then + Ind := Source'First; - if Mapping /= Identity then - declare - Mapped_Source : Wide_String (Source'Range); + -- Unmapped forward case - begin - for J in Source'Range loop - Mapped_Source (J) := Value (Mapping, Source (J)); + if Mapping'Address = Wide_Maps.Identity'Address then + for J in 1 .. Source'Length - PL1 loop + if Pattern = Source (Ind .. Ind + PL1) then + return Ind; + else + Ind := Ind + 1; + end if; end loop; - return Index (Mapped_Source, Pattern, Going); - end; - end if; + -- Mapped forward case - if Going = Forward then - for J in Source'First .. Source'Last - Pattern'Length + 1 loop - if Pattern = Source (J .. J + Pattern'Length - 1) then - return J; - end if; - end loop; + else + for J in 1 .. Source'Length - PL1 loop + Cur := Ind; - else -- Going = Backward - for J in reverse Source'First .. Source'Last - Pattern'Length + 1 loop - if Pattern = Source (J .. J + Pattern'Length - 1) then - return J; - end if; - end loop; + for K in Pattern'Range loop + if Pattern (K) /= Value (Mapping, Source (Cur)) then + goto Cont1; + else + Cur := Cur + 1; + end if; + end loop; + + return Ind; + + <<Cont1>> + Ind := Ind + 1; + end loop; + end if; + + -- Backwards case + + else + -- Unmapped backward case + + Ind := Source'Last - PL1; + + if Mapping'Address = Wide_Maps.Identity'Address then + for J in reverse 1 .. Source'Length - PL1 loop + if Pattern = Source (Ind .. Ind + PL1) then + return Ind; + else + Ind := Ind - 1; + end if; + end loop; + + -- Mapped backward case + + else + for J in reverse 1 .. Source'Length - PL1 loop + Cur := Ind; + + for K in Pattern'Range loop + if Pattern (K) /= Value (Mapping, Source (Cur)) then + goto Cont2; + else + Cur := Cur + 1; + end if; + end loop; + + return Ind; + + <<Cont2>> + Ind := Ind - 1; + end loop; + end if; end if; -- Fall through if no match found. Note that the loops are skipped @@ -240,14 +328,68 @@ package body Ada.Strings.Wide_Search is Going : Direction := Forward; Mapping : Wide_Maps.Wide_Character_Mapping_Function) return Natural is - Mapped_Source : Wide_String (Source'Range); + PL1 : constant Integer := Pattern'Length - 1; + Ind : Natural; + Cur : Natural; begin - for J in Source'Range loop - Mapped_Source (J) := Mapping (Source (J)); - end loop; + if Pattern = "" then + raise Pattern_Error; + end if; + + -- Check for null pointer in case checks are off + + if Mapping = null then + raise Constraint_Error; + end if; + + -- Forwards case + + if Going = Forward then + Ind := Source'First; + for J in 1 .. Source'Length - PL1 loop + Cur := Ind; + + for K in Pattern'Range loop + if Pattern (K) /= Mapping.all (Source (Cur)) then + goto Cont1; + else + Cur := Cur + 1; + end if; + end loop; + + return Ind; + + <<Cont1>> + Ind := Ind + 1; + end loop; + + -- Backwards case + + else + Ind := Source'Last - PL1; + for J in reverse 1 .. Source'Length - PL1 loop + Cur := Ind; + + for K in Pattern'Range loop + if Pattern (K) /= Mapping.all (Source (Cur)) then + goto Cont2; + else + Cur := Cur + 1; + end if; + end loop; + + return Ind; - return Index (Mapped_Source, Pattern, Going); + <<Cont2>> + Ind := Ind - 1; + end loop; + end if; + + -- Fall through if no match found. Note that the loops are skipped + -- completely in the case of the pattern being longer than the source. + + return 0; end Index; function Index @@ -257,6 +399,8 @@ package body Ada.Strings.Wide_Search is Going : Direction := Forward) return Natural is begin + -- Forwards case + if Going = Forward then for J in Source'Range loop if Belongs (Source (J), Set, Test) then @@ -264,7 +408,9 @@ package body Ada.Strings.Wide_Search is end if; end loop; - else -- Going = Backward + -- Backwards case + + else for J in reverse Source'Range loop if Belongs (Source (J), Set, Test) then return J; |