2010-07-27 Paolo Carlini <paolo.carlini@oracle.com>
[official-gcc/alias-decl.git] / gcc / ada / a-stwise.adb
blob0e22f64bec7969681eb1aef66372393b48ba9f45
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT RUN-TIME COMPONENTS --
4 -- --
5 -- A D A . S T R I N G S . W I D E _ S E A R C H --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-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 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
29 -- --
30 ------------------------------------------------------------------------------
32 with Ada.Strings.Wide_Maps; use Ada.Strings.Wide_Maps;
33 with System; use System;
35 package body Ada.Strings.Wide_Search is
37 -----------------------
38 -- Local Subprograms --
39 -----------------------
41 function Belongs
42 (Element : Wide_Character;
43 Set : Wide_Maps.Wide_Character_Set;
44 Test : Membership) return Boolean;
45 pragma Inline (Belongs);
46 -- Determines if the given element is in (Test = Inside) or not in
47 -- (Test = Outside) the given character set.
49 -------------
50 -- Belongs --
51 -------------
53 function Belongs
54 (Element : Wide_Character;
55 Set : Wide_Maps.Wide_Character_Set;
56 Test : Membership) return Boolean
58 begin
59 if Test = Inside then
60 return Is_In (Element, Set);
61 else
62 return not Is_In (Element, Set);
63 end if;
64 end Belongs;
66 -----------
67 -- Count --
68 -----------
70 function Count
71 (Source : Wide_String;
72 Pattern : Wide_String;
73 Mapping : Wide_Maps.Wide_Character_Mapping := Wide_Maps.Identity)
74 return Natural
76 PL1 : constant Integer := Pattern'Length - 1;
77 Num : Natural;
78 Ind : Natural;
79 Cur : Natural;
81 begin
82 if Pattern = "" then
83 raise Pattern_Error;
84 end if;
86 Num := 0;
87 Ind := Source'First;
89 -- Unmapped case
91 if Mapping'Address = Wide_Maps.Identity'Address then
92 while Ind <= Source'Last - PL1 loop
93 if Pattern = Source (Ind .. Ind + PL1) then
94 Num := Num + 1;
95 Ind := Ind + Pattern'Length;
96 else
97 Ind := Ind + 1;
98 end if;
99 end loop;
101 -- Mapped case
103 else
104 while Ind <= Source'Last - PL1 loop
105 Cur := Ind;
106 for K in Pattern'Range loop
107 if Pattern (K) /= Value (Mapping, Source (Cur)) then
108 Ind := Ind + 1;
109 goto Cont;
110 else
111 Cur := Cur + 1;
112 end if;
113 end loop;
115 Num := Num + 1;
116 Ind := Ind + Pattern'Length;
118 <<Cont>>
119 null;
120 end loop;
121 end if;
123 -- Return result
125 return Num;
126 end Count;
128 function Count
129 (Source : Wide_String;
130 Pattern : Wide_String;
131 Mapping : Wide_Maps.Wide_Character_Mapping_Function) return Natural
133 PL1 : constant Integer := Pattern'Length - 1;
134 Num : Natural;
135 Ind : Natural;
136 Cur : Natural;
138 begin
139 if Pattern = "" then
140 raise Pattern_Error;
141 end if;
143 -- Check for null pointer in case checks are off
145 if Mapping = null then
146 raise Constraint_Error;
147 end if;
149 Num := 0;
150 Ind := Source'First;
151 while Ind <= Source'Last - PL1 loop
152 Cur := Ind;
153 for K in Pattern'Range loop
154 if Pattern (K) /= Mapping (Source (Cur)) then
155 Ind := Ind + 1;
156 goto Cont;
157 else
158 Cur := Cur + 1;
159 end if;
160 end loop;
162 Num := Num + 1;
163 Ind := Ind + Pattern'Length;
165 <<Cont>>
166 null;
167 end loop;
169 return Num;
170 end Count;
172 function Count
173 (Source : Wide_String;
174 Set : Wide_Maps.Wide_Character_Set) return Natural
176 N : Natural := 0;
178 begin
179 for J in Source'Range loop
180 if Is_In (Source (J), Set) then
181 N := N + 1;
182 end if;
183 end loop;
185 return N;
186 end Count;
188 ----------------
189 -- Find_Token --
190 ----------------
192 procedure Find_Token
193 (Source : Wide_String;
194 Set : Wide_Maps.Wide_Character_Set;
195 Test : Membership;
196 First : out Positive;
197 Last : out Natural)
199 begin
200 for J in Source'Range loop
201 if Belongs (Source (J), Set, Test) then
202 First := J;
204 for K in J + 1 .. Source'Last loop
205 if not Belongs (Source (K), Set, Test) then
206 Last := K - 1;
207 return;
208 end if;
209 end loop;
211 -- Here if J indexes first char of token, and all chars after J
212 -- are in the token.
214 Last := Source'Last;
215 return;
216 end if;
217 end loop;
219 -- Here if no token found
221 First := Source'First;
222 Last := 0;
223 end Find_Token;
225 -----------
226 -- Index --
227 -----------
229 function Index
230 (Source : Wide_String;
231 Pattern : Wide_String;
232 Going : Direction := Forward;
233 Mapping : Wide_Maps.Wide_Character_Mapping := Wide_Maps.Identity)
234 return Natural
236 PL1 : constant Integer := Pattern'Length - 1;
237 Cur : Natural;
239 Ind : Integer;
240 -- Index for start of match check. This can be negative if the pattern
241 -- length is greater than the string length, which is why this variable
242 -- is Integer instead of Natural. In this case, the search loops do not
243 -- execute at all, so this Ind value is never used.
245 begin
246 if Pattern = "" then
247 raise Pattern_Error;
248 end if;
250 -- Forwards case
252 if Going = Forward then
253 Ind := Source'First;
255 -- Unmapped forward case
257 if Mapping'Address = Wide_Maps.Identity'Address then
258 for J in 1 .. Source'Length - PL1 loop
259 if Pattern = Source (Ind .. Ind + PL1) then
260 return Ind;
261 else
262 Ind := Ind + 1;
263 end if;
264 end loop;
266 -- Mapped forward case
268 else
269 for J in 1 .. Source'Length - PL1 loop
270 Cur := Ind;
272 for K in Pattern'Range loop
273 if Pattern (K) /= Value (Mapping, Source (Cur)) then
274 goto Cont1;
275 else
276 Cur := Cur + 1;
277 end if;
278 end loop;
280 return Ind;
282 <<Cont1>>
283 Ind := Ind + 1;
284 end loop;
285 end if;
287 -- Backwards case
289 else
290 -- Unmapped backward case
292 Ind := Source'Last - PL1;
294 if Mapping'Address = Wide_Maps.Identity'Address then
295 for J in reverse 1 .. Source'Length - PL1 loop
296 if Pattern = Source (Ind .. Ind + PL1) then
297 return Ind;
298 else
299 Ind := Ind - 1;
300 end if;
301 end loop;
303 -- Mapped backward case
305 else
306 for J in reverse 1 .. Source'Length - PL1 loop
307 Cur := Ind;
309 for K in Pattern'Range loop
310 if Pattern (K) /= Value (Mapping, Source (Cur)) then
311 goto Cont2;
312 else
313 Cur := Cur + 1;
314 end if;
315 end loop;
317 return Ind;
319 <<Cont2>>
320 Ind := Ind - 1;
321 end loop;
322 end if;
323 end if;
325 -- Fall through if no match found. Note that the loops are skipped
326 -- completely in the case of the pattern being longer than the source.
328 return 0;
329 end Index;
331 function Index
332 (Source : Wide_String;
333 Pattern : Wide_String;
334 Going : Direction := Forward;
335 Mapping : Wide_Maps.Wide_Character_Mapping_Function) return Natural
337 PL1 : constant Integer := Pattern'Length - 1;
338 Ind : Natural;
339 Cur : Natural;
341 begin
342 if Pattern = "" then
343 raise Pattern_Error;
344 end if;
346 -- Check for null pointer in case checks are off
348 if Mapping = null then
349 raise Constraint_Error;
350 end if;
352 -- If Pattern longer than Source it can't be found
354 if Pattern'Length > Source'Length then
355 return 0;
356 end if;
358 -- Forwards case
360 if Going = Forward then
361 Ind := Source'First;
362 for J in 1 .. Source'Length - PL1 loop
363 Cur := Ind;
365 for K in Pattern'Range loop
366 if Pattern (K) /= Mapping.all (Source (Cur)) then
367 goto Cont1;
368 else
369 Cur := Cur + 1;
370 end if;
371 end loop;
373 return Ind;
375 <<Cont1>>
376 Ind := Ind + 1;
377 end loop;
379 -- Backwards case
381 else
382 Ind := Source'Last - PL1;
383 for J in reverse 1 .. Source'Length - PL1 loop
384 Cur := Ind;
386 for K in Pattern'Range loop
387 if Pattern (K) /= Mapping.all (Source (Cur)) then
388 goto Cont2;
389 else
390 Cur := Cur + 1;
391 end if;
392 end loop;
394 return Ind;
396 <<Cont2>>
397 Ind := Ind - 1;
398 end loop;
399 end if;
401 -- Fall through if no match found. Note that the loops are skipped
402 -- completely in the case of the pattern being longer than the source.
404 return 0;
405 end Index;
407 function Index
408 (Source : Wide_String;
409 Set : Wide_Maps.Wide_Character_Set;
410 Test : Membership := Inside;
411 Going : Direction := Forward) return Natural
413 begin
414 -- Forwards case
416 if Going = Forward then
417 for J in Source'Range loop
418 if Belongs (Source (J), Set, Test) then
419 return J;
420 end if;
421 end loop;
423 -- Backwards case
425 else
426 for J in reverse Source'Range loop
427 if Belongs (Source (J), Set, Test) then
428 return J;
429 end if;
430 end loop;
431 end if;
433 -- Fall through if no match
435 return 0;
436 end Index;
438 function Index
439 (Source : Wide_String;
440 Pattern : Wide_String;
441 From : Positive;
442 Going : Direction := Forward;
443 Mapping : Wide_Maps.Wide_Character_Mapping := Wide_Maps.Identity)
444 return Natural
446 begin
447 if Going = Forward then
448 if From < Source'First then
449 raise Index_Error;
450 end if;
452 return
453 Index (Source (From .. Source'Last), Pattern, Forward, Mapping);
455 else
456 if From > Source'Last then
457 raise Index_Error;
458 end if;
460 return
461 Index (Source (Source'First .. From), Pattern, Backward, Mapping);
462 end if;
463 end Index;
465 function Index
466 (Source : Wide_String;
467 Pattern : Wide_String;
468 From : Positive;
469 Going : Direction := Forward;
470 Mapping : Wide_Maps.Wide_Character_Mapping_Function) return Natural
472 begin
473 if Going = Forward then
474 if From < Source'First then
475 raise Index_Error;
476 end if;
478 return Index
479 (Source (From .. Source'Last), Pattern, Forward, Mapping);
481 else
482 if From > Source'Last then
483 raise Index_Error;
484 end if;
486 return Index
487 (Source (Source'First .. From), Pattern, Backward, Mapping);
488 end if;
489 end Index;
491 function Index
492 (Source : Wide_String;
493 Set : Wide_Maps.Wide_Character_Set;
494 From : Positive;
495 Test : Membership := Inside;
496 Going : Direction := Forward) return Natural
498 begin
499 if Going = Forward then
500 if From < Source'First then
501 raise Index_Error;
502 end if;
504 return
505 Index (Source (From .. Source'Last), Set, Test, Forward);
507 else
508 if From > Source'Last then
509 raise Index_Error;
510 end if;
512 return
513 Index (Source (Source'First .. From), Set, Test, Backward);
514 end if;
515 end Index;
517 ---------------------
518 -- Index_Non_Blank --
519 ---------------------
521 function Index_Non_Blank
522 (Source : Wide_String;
523 Going : Direction := Forward) return Natural
525 begin
526 if Going = Forward then
527 for J in Source'Range loop
528 if Source (J) /= Wide_Space then
529 return J;
530 end if;
531 end loop;
533 else -- Going = Backward
534 for J in reverse Source'Range loop
535 if Source (J) /= Wide_Space then
536 return J;
537 end if;
538 end loop;
539 end if;
541 -- Fall through if no match
543 return 0;
544 end Index_Non_Blank;
546 function Index_Non_Blank
547 (Source : Wide_String;
548 From : Positive;
549 Going : Direction := Forward) return Natural
551 begin
552 if Going = Forward then
553 if From < Source'First then
554 raise Index_Error;
555 end if;
557 return
558 Index_Non_Blank (Source (From .. Source'Last), Forward);
560 else
561 if From > Source'Last then
562 raise Index_Error;
563 end if;
565 return
566 Index_Non_Blank (Source (Source'First .. From), Backward);
567 end if;
568 end Index_Non_Blank;
570 end Ada.Strings.Wide_Search;