1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- A D A . S T R I N G S . W I D E _ W I D E _ S E A R C H --
9 -- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
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 2, 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. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
34 with Ada.Strings.Wide_Wide_Maps; use Ada.Strings.Wide_Wide_Maps;
36 package body Ada.Strings.Wide_Wide_Search is
38 -----------------------
39 -- Local Subprograms --
40 -----------------------
43 (Element : Wide_Wide_Character;
44 Set : Wide_Wide_Maps.Wide_Wide_Character_Set;
45 Test : Membership) return Boolean;
46 pragma Inline (Belongs);
47 -- Determines if the given element is in (Test = Inside) or not in
48 -- (Test = Outside) the given character set.
55 (Element : Wide_Wide_Character;
56 Set : Wide_Wide_Maps.Wide_Wide_Character_Set;
57 Test : Membership) return Boolean
61 return Is_In (Element, Set);
63 return not Is_In (Element, Set);
72 (Source : Wide_Wide_String;
73 Pattern : Wide_Wide_String;
74 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping :=
75 Wide_Wide_Maps.Identity)
86 -- Handle the case of non-identity mappings by creating a mapped
87 -- string and making a recursive call using the identity mapping
88 -- on this mapped string.
90 if Mapping /= Wide_Wide_Maps.Identity then
92 Mapped_Source : Wide_Wide_String (Source'Range);
95 for J in Source'Range loop
96 Mapped_Source (J) := Value (Mapping, Source (J));
99 return Count (Mapped_Source, Pattern);
106 while J <= Source'Last - (Pattern'Length - 1) loop
107 if Source (J .. J + (Pattern'Length - 1)) = Pattern then
109 J := J + Pattern'Length;
119 (Source : Wide_Wide_String;
120 Pattern : Wide_Wide_String;
121 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping_Function)
124 Mapped_Source : Wide_Wide_String (Source'Range);
127 for J in Source'Range loop
128 Mapped_Source (J) := Mapping (Source (J));
131 return Count (Mapped_Source, Pattern);
135 (Source : Wide_Wide_String;
136 Set : Wide_Wide_Maps.Wide_Wide_Character_Set) return Natural
141 for J in Source'Range loop
142 if Is_In (Source (J), Set) then
155 (Source : Wide_Wide_String;
156 Set : Wide_Wide_Maps.Wide_Wide_Character_Set;
158 First : out Positive;
162 for J in Source'Range loop
163 if Belongs (Source (J), Set, Test) then
166 for K in J + 1 .. Source'Last loop
167 if not Belongs (Source (K), Set, Test) then
173 -- Here if J indexes 1st char of token, and all chars
174 -- after J are in the token
181 -- Here if no token found
183 First := Source'First;
192 (Source : Wide_Wide_String;
193 Pattern : Wide_Wide_String;
194 Going : Direction := Forward;
195 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping :=
196 Wide_Wide_Maps.Identity)
204 -- Handle the case of non-identity mappings by creating a mapped
205 -- string and making a recursive call using the identity mapping
206 -- on this mapped string.
208 if Mapping /= Identity then
210 Mapped_Source : Wide_Wide_String (Source'Range);
213 for J in Source'Range loop
214 Mapped_Source (J) := Value (Mapping, Source (J));
217 return Index (Mapped_Source, Pattern, Going);
221 if Going = Forward then
222 for J in Source'First .. Source'Last - Pattern'Length + 1 loop
223 if Pattern = Source (J .. J + Pattern'Length - 1) then
228 else -- Going = Backward
229 for J in reverse Source'First .. Source'Last - Pattern'Length + 1 loop
230 if Pattern = Source (J .. J + Pattern'Length - 1) then
236 -- Fall through if no match found. Note that the loops are skipped
237 -- completely in the case of the pattern being longer than the source.
243 (Source : Wide_Wide_String;
244 Pattern : Wide_Wide_String;
245 Going : Direction := Forward;
246 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping_Function)
249 Mapped_Source : Wide_Wide_String (Source'Range);
252 for J in Source'Range loop
253 Mapped_Source (J) := Mapping (Source (J));
256 return Index (Mapped_Source, Pattern, Going);
260 (Source : Wide_Wide_String;
261 Set : Wide_Wide_Maps.Wide_Wide_Character_Set;
262 Test : Membership := Inside;
263 Going : Direction := Forward) return Natural
266 if Going = Forward then
267 for J in Source'Range loop
268 if Belongs (Source (J), Set, Test) then
273 else -- Going = Backward
274 for J in reverse Source'Range loop
275 if Belongs (Source (J), Set, Test) then
281 -- Fall through if no match
287 (Source : Wide_Wide_String;
288 Pattern : Wide_Wide_String;
290 Going : Direction := Forward;
291 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping :=
292 Wide_Wide_Maps.Identity)
296 if Going = Forward then
297 if From < Source'First then
302 Index (Source (From .. Source'Last), Pattern, Forward, Mapping);
305 if From > Source'Last then
310 Index (Source (Source'First .. From), Pattern, Backward, Mapping);
315 (Source : Wide_Wide_String;
316 Pattern : Wide_Wide_String;
318 Going : Direction := Forward;
319 Mapping : Wide_Wide_Maps.Wide_Wide_Character_Mapping_Function)
323 if Going = Forward then
324 if From < Source'First then
329 (Source (From .. Source'Last), Pattern, Forward, Mapping);
332 if From > Source'Last then
337 (Source (Source'First .. From), Pattern, Backward, Mapping);
342 (Source : Wide_Wide_String;
343 Set : Wide_Wide_Maps.Wide_Wide_Character_Set;
345 Test : Membership := Inside;
346 Going : Direction := Forward) return Natural
349 if Going = Forward then
350 if From < Source'First then
355 Index (Source (From .. Source'Last), Set, Test, Forward);
358 if From > Source'Last then
363 Index (Source (Source'First .. From), Set, Test, Backward);
367 ---------------------
368 -- Index_Non_Blank --
369 ---------------------
371 function Index_Non_Blank
372 (Source : Wide_Wide_String;
373 Going : Direction := Forward) return Natural
376 if Going = Forward then
377 for J in Source'Range loop
378 if Source (J) /= Wide_Wide_Space then
383 else -- Going = Backward
384 for J in reverse Source'Range loop
385 if Source (J) /= Wide_Wide_Space then
391 -- Fall through if no match
396 function Index_Non_Blank
397 (Source : Wide_Wide_String;
399 Going : Direction := Forward) return Natural
402 if Going = Forward then
403 if From < Source'First then
408 Index_Non_Blank (Source (From .. Source'Last), Forward);
411 if From > Source'Last then
416 Index_Non_Blank (Source (Source'First .. From), Backward);
420 end Ada.Strings.Wide_Wide_Search;