Remove some compile time warnings about duplicate definitions.
[official-gcc.git] / gcc / ada / a-strfix.adb
blob8c10dec654c66912e8d80d80659c92e87831b057
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT RUNTIME COMPONENTS --
4 -- --
5 -- A D A . S T R I N G S . F I X E D --
6 -- --
7 -- B o d y --
8 -- --
9 -- $Revision: 1.19 $
10 -- --
11 -- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
12 -- --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
23 -- --
24 -- As a special exception, if other files instantiate generics from this --
25 -- unit, or you link this unit with other files to produce an executable, --
26 -- this unit does not by itself cause the resulting executable to be --
27 -- covered by the GNU General Public License. This exception does not --
28 -- however invalidate any other reasons why the executable file might be --
29 -- covered by the GNU Public License. --
30 -- --
31 -- GNAT was originally developed by the GNAT team at New York University. --
32 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
33 -- --
34 ------------------------------------------------------------------------------
36 -- Note: This code is derived from the ADAR.CSH public domain Ada 83
37 -- versions of the Appendix C string handling packages. One change is
38 -- to avoid the use of Is_In, so that we are not dependent on inlining.
39 -- Note that the search function implementations are to be found in the
40 -- auxiliary package Ada.Strings.Search. Also the Move procedure is
41 -- directly incorporated (ADAR used a subunit for this procedure). A
42 -- number of errors having to do with bounds of function return results
43 -- were also fixed, and use of & removed for efficiency reasons.
45 with Ada.Strings.Maps; use Ada.Strings.Maps;
46 with Ada.Strings.Search;
48 package body Ada.Strings.Fixed is
50 ------------------------
51 -- Search Subprograms --
52 ------------------------
54 function Index
55 (Source : in String;
56 Pattern : in String;
57 Going : in Direction := Forward;
58 Mapping : in Maps.Character_Mapping := Maps.Identity)
59 return Natural
60 renames Ada.Strings.Search.Index;
62 function Index
63 (Source : in String;
64 Pattern : in String;
65 Going : in Direction := Forward;
66 Mapping : in Maps.Character_Mapping_Function)
67 return Natural
68 renames Ada.Strings.Search.Index;
70 function Index
71 (Source : in String;
72 Set : in Maps.Character_Set;
73 Test : in Membership := Inside;
74 Going : in Direction := Forward)
75 return Natural
76 renames Ada.Strings.Search.Index;
78 function Index_Non_Blank
79 (Source : in String;
80 Going : in Direction := Forward)
81 return Natural
82 renames Ada.Strings.Search.Index_Non_Blank;
84 function Count
85 (Source : in String;
86 Pattern : in String;
87 Mapping : in Maps.Character_Mapping := Maps.Identity)
88 return Natural
89 renames Ada.Strings.Search.Count;
91 function Count
92 (Source : in String;
93 Pattern : in String;
94 Mapping : in Maps.Character_Mapping_Function)
95 return Natural
96 renames Ada.Strings.Search.Count;
98 function Count
99 (Source : in String;
100 Set : in Maps.Character_Set)
101 return Natural
102 renames Ada.Strings.Search.Count;
104 procedure Find_Token
105 (Source : in String;
106 Set : in Maps.Character_Set;
107 Test : in Membership;
108 First : out Positive;
109 Last : out Natural)
110 renames Ada.Strings.Search.Find_Token;
112 ---------
113 -- "*" --
114 ---------
116 function "*"
117 (Left : in Natural;
118 Right : in Character)
119 return String
121 Result : String (1 .. Left);
123 begin
124 for J in Result'Range loop
125 Result (J) := Right;
126 end loop;
128 return Result;
129 end "*";
131 function "*"
132 (Left : in Natural;
133 Right : in String)
134 return String
136 Result : String (1 .. Left * Right'Length);
137 Ptr : Integer := 1;
139 begin
140 for J in 1 .. Left loop
141 Result (Ptr .. Ptr + Right'Length - 1) := Right;
142 Ptr := Ptr + Right'Length;
143 end loop;
145 return Result;
146 end "*";
148 ------------
149 -- Delete --
150 ------------
152 function Delete
153 (Source : in String;
154 From : in Positive;
155 Through : in Natural)
156 return String
158 begin
159 if From > Through then
160 declare
161 subtype Result_Type is String (1 .. Source'Length);
163 begin
164 return Result_Type (Source);
165 end;
167 elsif From not in Source'Range
168 or else Through > Source'Last
169 then
170 raise Index_Error;
172 else
173 declare
174 Front : constant Integer := From - Source'First;
175 Result : String (1 .. Source'Length - (Through - From + 1));
177 begin
178 Result (1 .. Front) :=
179 Source (Source'First .. From - 1);
180 Result (Front + 1 .. Result'Last) :=
181 Source (Through + 1 .. Source'Last);
183 return Result;
184 end;
185 end if;
186 end Delete;
188 procedure Delete
189 (Source : in out String;
190 From : in Positive;
191 Through : in Natural;
192 Justify : in Alignment := Left;
193 Pad : in Character := Space)
195 begin
196 Move (Source => Delete (Source, From, Through),
197 Target => Source,
198 Justify => Justify,
199 Pad => Pad);
200 end Delete;
202 ----------
203 -- Head --
204 ----------
206 function Head
207 (Source : in String;
208 Count : in Natural;
209 Pad : in Character := Space)
210 return String
212 subtype Result_Type is String (1 .. Count);
214 begin
215 if Count < Source'Length then
216 return
217 Result_Type (Source (Source'First .. Source'First + Count - 1));
219 else
220 declare
221 Result : Result_Type;
223 begin
224 Result (1 .. Source'Length) := Source;
226 for J in Source'Length + 1 .. Count loop
227 Result (J) := Pad;
228 end loop;
230 return Result;
231 end;
232 end if;
233 end Head;
235 procedure Head
236 (Source : in out String;
237 Count : in Natural;
238 Justify : in Alignment := Left;
239 Pad : in Character := Space)
241 begin
242 Move (Source => Head (Source, Count, Pad),
243 Target => Source,
244 Drop => Error,
245 Justify => Justify,
246 Pad => Pad);
247 end Head;
249 ------------
250 -- Insert --
251 ------------
253 function Insert
254 (Source : in String;
255 Before : in Positive;
256 New_Item : in String)
257 return String
259 Result : String (1 .. Source'Length + New_Item'Length);
260 Front : constant Integer := Before - Source'First;
262 begin
263 if Before not in Source'First .. Source'Last + 1 then
264 raise Index_Error;
265 end if;
267 Result (1 .. Front) :=
268 Source (Source'First .. Before - 1);
269 Result (Front + 1 .. Front + New_Item'Length) :=
270 New_Item;
271 Result (Front + New_Item'Length + 1 .. Result'Last) :=
272 Source (Before .. Source'Last);
274 return Result;
275 end Insert;
277 procedure Insert
278 (Source : in out String;
279 Before : in Positive;
280 New_Item : in String;
281 Drop : in Truncation := Error)
283 begin
284 Move (Source => Insert (Source, Before, New_Item),
285 Target => Source,
286 Drop => Drop);
287 end Insert;
289 ----------
290 -- Move --
291 ----------
293 procedure Move
294 (Source : in String;
295 Target : out String;
296 Drop : in Truncation := Error;
297 Justify : in Alignment := Left;
298 Pad : in Character := Space)
300 Sfirst : constant Integer := Source'First;
301 Slast : constant Integer := Source'Last;
302 Slength : constant Integer := Source'Length;
304 Tfirst : constant Integer := Target'First;
305 Tlast : constant Integer := Target'Last;
306 Tlength : constant Integer := Target'Length;
308 function Is_Padding (Item : String) return Boolean;
309 -- Check if Item is all Pad characters, return True if so, False if not
311 function Is_Padding (Item : String) return Boolean is
312 begin
313 for J in Item'Range loop
314 if Item (J) /= Pad then
315 return False;
316 end if;
317 end loop;
319 return True;
320 end Is_Padding;
322 -- Start of processing for Move
324 begin
325 if Slength = Tlength then
326 Target := Source;
328 elsif Slength > Tlength then
330 case Drop is
331 when Left =>
332 Target := Source (Slast - Tlength + 1 .. Slast);
334 when Right =>
335 Target := Source (Sfirst .. Sfirst + Tlength - 1);
337 when Error =>
338 case Justify is
339 when Left =>
340 if Is_Padding (Source (Sfirst + Tlength .. Slast)) then
341 Target :=
342 Source (Sfirst .. Sfirst + Target'Length - 1);
343 else
344 raise Length_Error;
345 end if;
347 when Right =>
348 if Is_Padding (Source (Sfirst .. Slast - Tlength)) then
349 Target := Source (Slast - Tlength + 1 .. Slast);
350 else
351 raise Length_Error;
352 end if;
354 when Center =>
355 raise Length_Error;
356 end case;
358 end case;
360 -- Source'Length < Target'Length
362 else
363 case Justify is
364 when Left =>
365 Target (Tfirst .. Tfirst + Slength - 1) := Source;
367 for I in Tfirst + Slength .. Tlast loop
368 Target (I) := Pad;
369 end loop;
371 when Right =>
372 for I in Tfirst .. Tlast - Slength loop
373 Target (I) := Pad;
374 end loop;
376 Target (Tlast - Slength + 1 .. Tlast) := Source;
378 when Center =>
379 declare
380 Front_Pad : constant Integer := (Tlength - Slength) / 2;
381 Tfirst_Fpad : constant Integer := Tfirst + Front_Pad;
383 begin
384 for I in Tfirst .. Tfirst_Fpad - 1 loop
385 Target (I) := Pad;
386 end loop;
388 Target (Tfirst_Fpad .. Tfirst_Fpad + Slength - 1) := Source;
390 for I in Tfirst_Fpad + Slength .. Tlast loop
391 Target (I) := Pad;
392 end loop;
393 end;
394 end case;
395 end if;
396 end Move;
398 ---------------
399 -- Overwrite --
400 ---------------
402 function Overwrite
403 (Source : in String;
404 Position : in Positive;
405 New_Item : in String)
406 return String
408 begin
409 if Position not in Source'First .. Source'Last + 1 then
410 raise Index_Error;
411 end if;
413 declare
414 Result_Length : Natural :=
415 Integer'Max
416 (Source'Length, Position - Source'First + New_Item'Length);
418 Result : String (1 .. Result_Length);
419 Front : constant Integer := Position - Source'First;
421 begin
422 Result (1 .. Front) :=
423 Source (Source'First .. Position - 1);
424 Result (Front + 1 .. Front + New_Item'Length) :=
425 New_Item;
426 Result (Front + New_Item'Length + 1 .. Result'Length) :=
427 Source (Position + New_Item'Length .. Source'Last);
428 return Result;
429 end;
430 end Overwrite;
432 procedure Overwrite
433 (Source : in out String;
434 Position : in Positive;
435 New_Item : in String;
436 Drop : in Truncation := Right)
438 begin
439 Move (Source => Overwrite (Source, Position, New_Item),
440 Target => Source,
441 Drop => Drop);
442 end Overwrite;
444 -------------------
445 -- Replace_Slice --
446 -------------------
448 function Replace_Slice
449 (Source : in String;
450 Low : in Positive;
451 High : in Natural;
452 By : in String)
453 return String
455 begin
456 if Low > Source'Last + 1 or High < Source'First - 1 then
457 raise Index_Error;
458 end if;
460 if High >= Low then
461 declare
462 Front_Len : constant Integer :=
463 Integer'Max (0, Low - Source'First);
464 -- Length of prefix of Source copied to result
466 Back_Len : constant Integer :=
467 Integer'Max (0, Source'Last - High);
468 -- Length of suffix of Source copied to result
470 Result_Length : constant Integer :=
471 Front_Len + By'Length + Back_Len;
472 -- Length of result
474 Result : String (1 .. Result_Length);
476 begin
477 Result (1 .. Front_Len) :=
478 Source (Source'First .. Low - 1);
479 Result (Front_Len + 1 .. Front_Len + By'Length) :=
481 Result (Front_Len + By'Length + 1 .. Result'Length) :=
482 Source (High + 1 .. Source'Last);
484 return Result;
485 end;
487 else
488 return Insert (Source, Before => Low, New_Item => By);
489 end if;
490 end Replace_Slice;
492 procedure Replace_Slice
493 (Source : in out String;
494 Low : in Positive;
495 High : in Natural;
496 By : in String;
497 Drop : in Truncation := Error;
498 Justify : in Alignment := Left;
499 Pad : in Character := Space)
501 begin
502 Move (Replace_Slice (Source, Low, High, By), Source, Drop, Justify, Pad);
503 end Replace_Slice;
505 ----------
506 -- Tail --
507 ----------
509 function Tail
510 (Source : in String;
511 Count : in Natural;
512 Pad : in Character := Space)
513 return String
515 subtype Result_Type is String (1 .. Count);
517 begin
518 if Count < Source'Length then
519 return Result_Type (Source (Source'Last - Count + 1 .. Source'Last));
521 -- Pad on left
523 else
524 declare
525 Result : Result_Type;
527 begin
528 for J in 1 .. Count - Source'Length loop
529 Result (J) := Pad;
530 end loop;
532 Result (Count - Source'Length + 1 .. Count) := Source;
533 return Result;
534 end;
535 end if;
536 end Tail;
538 procedure Tail
539 (Source : in out String;
540 Count : in Natural;
541 Justify : in Alignment := Left;
542 Pad : in Character := Space)
544 begin
545 Move (Source => Tail (Source, Count, Pad),
546 Target => Source,
547 Drop => Error,
548 Justify => Justify,
549 Pad => Pad);
550 end Tail;
552 ---------------
553 -- Translate --
554 ---------------
556 function Translate
557 (Source : in String;
558 Mapping : in Maps.Character_Mapping)
559 return String
561 Result : String (1 .. Source'Length);
563 begin
564 for J in Source'Range loop
565 Result (J - (Source'First - 1)) := Value (Mapping, Source (J));
566 end loop;
568 return Result;
569 end Translate;
571 procedure Translate
572 (Source : in out String;
573 Mapping : in Maps.Character_Mapping)
575 begin
576 for J in Source'Range loop
577 Source (J) := Value (Mapping, Source (J));
578 end loop;
579 end Translate;
581 function Translate
582 (Source : in String;
583 Mapping : in Maps.Character_Mapping_Function)
584 return String
586 Result : String (1 .. Source'Length);
587 pragma Unsuppress (Access_Check);
589 begin
590 for J in Source'Range loop
591 Result (J - (Source'First - 1)) := Mapping.all (Source (J));
592 end loop;
594 return Result;
595 end Translate;
597 procedure Translate
598 (Source : in out String;
599 Mapping : in Maps.Character_Mapping_Function)
601 pragma Unsuppress (Access_Check);
602 begin
603 for J in Source'Range loop
604 Source (J) := Mapping.all (Source (J));
605 end loop;
606 end Translate;
608 ----------
609 -- Trim --
610 ----------
612 function Trim
613 (Source : in String;
614 Side : in Trim_End)
615 return String
617 Low, High : Integer;
619 begin
620 Low := Index_Non_Blank (Source, Forward);
622 -- All blanks case
624 if Low = 0 then
625 return "";
627 -- At least one non-blank
629 else
630 High := Index_Non_Blank (Source, Backward);
632 case Side is
633 when Strings.Left =>
634 declare
635 subtype Result_Type is String (1 .. Source'Last - Low + 1);
637 begin
638 return Result_Type (Source (Low .. Source'Last));
639 end;
641 when Strings.Right =>
642 declare
643 subtype Result_Type is String (1 .. High - Source'First + 1);
645 begin
646 return Result_Type (Source (Source'First .. High));
647 end;
649 when Strings.Both =>
650 declare
651 subtype Result_Type is String (1 .. High - Low + 1);
653 begin
654 return Result_Type (Source (Low .. High));
655 end;
656 end case;
657 end if;
658 end Trim;
660 procedure Trim
661 (Source : in out String;
662 Side : in Trim_End;
663 Justify : in Alignment := Left;
664 Pad : in Character := Space)
666 begin
667 Move (Trim (Source, Side),
668 Source,
669 Justify => Justify,
670 Pad => Pad);
671 end Trim;
673 function Trim
674 (Source : in String;
675 Left : in Maps.Character_Set;
676 Right : in Maps.Character_Set)
677 return String
679 High, Low : Integer;
681 begin
682 Low := Index (Source, Set => Left, Test => Outside, Going => Forward);
684 -- Case where source comprises only characters in Left
686 if Low = 0 then
687 return "";
688 end if;
690 High :=
691 Index (Source, Set => Right, Test => Outside, Going => Backward);
693 -- Case where source comprises only characters in Right
695 if High = 0 then
696 return "";
697 end if;
699 declare
700 subtype Result_Type is String (1 .. High - Low + 1);
702 begin
703 return Result_Type (Source (Low .. High));
704 end;
705 end Trim;
707 procedure Trim
708 (Source : in out String;
709 Left : in Maps.Character_Set;
710 Right : in Maps.Character_Set;
711 Justify : in Alignment := Strings.Left;
712 Pad : in Character := Space)
714 begin
715 Move (Source => Trim (Source, Left, Right),
716 Target => Source,
717 Justify => Justify,
718 Pad => Pad);
719 end Trim;
721 end Ada.Strings.Fixed;