PR testsuite/44195
[official-gcc.git] / gcc / ada / a-stwifi.adb
blob14fd52f107c8aadc87298214faadfc750578e8f7
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT RUN-TIME COMPONENTS --
4 -- --
5 -- A D A . S T R I N G S . W I D E _ F I X E D --
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 Ada.Strings.Wide_Search;
35 package body Ada.Strings.Wide_Fixed is
37 ------------------------
38 -- Search Subprograms --
39 ------------------------
41 function Index
42 (Source : Wide_String;
43 Pattern : Wide_String;
44 Going : Direction := Forward;
45 Mapping : Wide_Maps.Wide_Character_Mapping := Wide_Maps.Identity)
46 return Natural
47 renames Ada.Strings.Wide_Search.Index;
49 function Index
50 (Source : Wide_String;
51 Pattern : Wide_String;
52 Going : Direction := Forward;
53 Mapping : Wide_Maps.Wide_Character_Mapping_Function) return Natural
54 renames Ada.Strings.Wide_Search.Index;
56 function Index
57 (Source : Wide_String;
58 Set : Wide_Maps.Wide_Character_Set;
59 Test : Membership := Inside;
60 Going : Direction := Forward) return Natural
61 renames Ada.Strings.Wide_Search.Index;
63 function Index
64 (Source : Wide_String;
65 Pattern : Wide_String;
66 From : Positive;
67 Going : Direction := Forward;
68 Mapping : Wide_Maps.Wide_Character_Mapping := Wide_Maps.Identity)
69 return Natural
70 renames Ada.Strings.Wide_Search.Index;
72 function Index
73 (Source : Wide_String;
74 Pattern : Wide_String;
75 From : Positive;
76 Going : Direction := Forward;
77 Mapping : Wide_Maps.Wide_Character_Mapping_Function) return Natural
78 renames Ada.Strings.Wide_Search.Index;
80 function Index
81 (Source : Wide_String;
82 Set : Wide_Maps.Wide_Character_Set;
83 From : Positive;
84 Test : Membership := Inside;
85 Going : Direction := Forward) return Natural
86 renames Ada.Strings.Wide_Search.Index;
88 function Index_Non_Blank
89 (Source : Wide_String;
90 Going : Direction := Forward) return Natural
91 renames Ada.Strings.Wide_Search.Index_Non_Blank;
93 function Index_Non_Blank
94 (Source : Wide_String;
95 From : Positive;
96 Going : Direction := Forward) return Natural
97 renames Ada.Strings.Wide_Search.Index_Non_Blank;
99 function Count
100 (Source : Wide_String;
101 Pattern : Wide_String;
102 Mapping : Wide_Maps.Wide_Character_Mapping := Wide_Maps.Identity)
103 return Natural
104 renames Ada.Strings.Wide_Search.Count;
106 function Count
107 (Source : Wide_String;
108 Pattern : Wide_String;
109 Mapping : Wide_Maps.Wide_Character_Mapping_Function) return Natural
110 renames Ada.Strings.Wide_Search.Count;
112 function Count
113 (Source : Wide_String;
114 Set : Wide_Maps.Wide_Character_Set) return Natural
115 renames Ada.Strings.Wide_Search.Count;
117 procedure Find_Token
118 (Source : Wide_String;
119 Set : Wide_Maps.Wide_Character_Set;
120 Test : Membership;
121 First : out Positive;
122 Last : out Natural)
123 renames Ada.Strings.Wide_Search.Find_Token;
125 ---------
126 -- "*" --
127 ---------
129 function "*"
130 (Left : Natural;
131 Right : Wide_Character) return Wide_String
133 Result : Wide_String (1 .. Left);
135 begin
136 for J in Result'Range loop
137 Result (J) := Right;
138 end loop;
140 return Result;
141 end "*";
143 function "*"
144 (Left : Natural;
145 Right : Wide_String) return Wide_String
147 Result : Wide_String (1 .. Left * Right'Length);
148 Ptr : Integer := 1;
150 begin
151 for J in 1 .. Left loop
152 Result (Ptr .. Ptr + Right'Length - 1) := Right;
153 Ptr := Ptr + Right'Length;
154 end loop;
156 return Result;
157 end "*";
159 ------------
160 -- Delete --
161 ------------
163 function Delete
164 (Source : Wide_String;
165 From : Positive;
166 Through : Natural) return Wide_String
168 begin
169 if From not in Source'Range
170 or else Through > Source'Last
171 then
172 raise Index_Error;
174 elsif From > Through then
175 return Source;
177 else
178 declare
179 Len : constant Integer := Source'Length - (Through - From + 1);
180 Result : constant
181 Wide_String (Source'First .. Source'First + Len - 1) :=
182 Source (Source'First .. From - 1) &
183 Source (Through + 1 .. Source'Last);
184 begin
185 return Result;
186 end;
187 end if;
188 end Delete;
190 procedure Delete
191 (Source : in out Wide_String;
192 From : Positive;
193 Through : Natural;
194 Justify : Alignment := Left;
195 Pad : Wide_Character := Wide_Space)
197 begin
198 Move (Source => Delete (Source, From, Through),
199 Target => Source,
200 Justify => Justify,
201 Pad => Pad);
202 end Delete;
204 ----------
205 -- Head --
206 ----------
208 function Head
209 (Source : Wide_String;
210 Count : Natural;
211 Pad : Wide_Character := Wide_Space) return Wide_String
213 Result : Wide_String (1 .. Count);
215 begin
216 if Count <= Source'Length then
217 Result := Source (Source'First .. Source'First + Count - 1);
219 else
220 Result (1 .. Source'Length) := Source;
222 for J in Source'Length + 1 .. Count loop
223 Result (J) := Pad;
224 end loop;
225 end if;
227 return Result;
228 end Head;
230 procedure Head
231 (Source : in out Wide_String;
232 Count : Natural;
233 Justify : Alignment := Left;
234 Pad : Wide_Character := Ada.Strings.Wide_Space)
236 begin
237 Move (Source => Head (Source, Count, Pad),
238 Target => Source,
239 Drop => Error,
240 Justify => Justify,
241 Pad => Pad);
242 end Head;
244 ------------
245 -- Insert --
246 ------------
248 function Insert
249 (Source : Wide_String;
250 Before : Positive;
251 New_Item : Wide_String) return Wide_String
253 Result : Wide_String (1 .. Source'Length + New_Item'Length);
255 begin
256 if Before < Source'First or else Before > Source'Last + 1 then
257 raise Index_Error;
258 end if;
260 Result := Source (Source'First .. Before - 1) & New_Item &
261 Source (Before .. Source'Last);
262 return Result;
263 end Insert;
265 procedure Insert
266 (Source : in out Wide_String;
267 Before : Positive;
268 New_Item : Wide_String;
269 Drop : Truncation := Error)
271 begin
272 Move (Source => Insert (Source, Before, New_Item),
273 Target => Source,
274 Drop => Drop);
275 end Insert;
277 ----------
278 -- Move --
279 ----------
281 procedure Move
282 (Source : Wide_String;
283 Target : out Wide_String;
284 Drop : Truncation := Error;
285 Justify : Alignment := Left;
286 Pad : Wide_Character := Wide_Space)
288 Sfirst : constant Integer := Source'First;
289 Slast : constant Integer := Source'Last;
290 Slength : constant Integer := Source'Length;
292 Tfirst : constant Integer := Target'First;
293 Tlast : constant Integer := Target'Last;
294 Tlength : constant Integer := Target'Length;
296 function Is_Padding (Item : Wide_String) return Boolean;
297 -- Determine if all characters in Item are pad characters
299 ----------------
300 -- Is_Padding --
301 ----------------
303 function Is_Padding (Item : Wide_String) return Boolean is
304 begin
305 for J in Item'Range loop
306 if Item (J) /= Pad then
307 return False;
308 end if;
309 end loop;
311 return True;
312 end Is_Padding;
314 -- Start of processing for Move
316 begin
317 if Slength = Tlength then
318 Target := Source;
320 elsif Slength > Tlength then
322 case Drop is
323 when Left =>
324 Target := Source (Slast - Tlength + 1 .. Slast);
326 when Right =>
327 Target := Source (Sfirst .. Sfirst + Tlength - 1);
329 when Error =>
330 case Justify is
331 when Left =>
332 if Is_Padding (Source (Sfirst + Tlength .. Slast)) then
333 Target :=
334 Source (Sfirst .. Sfirst + Target'Length - 1);
335 else
336 raise Length_Error;
337 end if;
339 when Right =>
340 if Is_Padding (Source (Sfirst .. Slast - Tlength)) then
341 Target := Source (Slast - Tlength + 1 .. Slast);
342 else
343 raise Length_Error;
344 end if;
346 when Center =>
347 raise Length_Error;
348 end case;
350 end case;
352 -- Source'Length < Target'Length
354 else
355 case Justify is
356 when Left =>
357 Target (Tfirst .. Tfirst + Slength - 1) := Source;
359 for J in Tfirst + Slength .. Tlast loop
360 Target (J) := Pad;
361 end loop;
363 when Right =>
364 for J in Tfirst .. Tlast - Slength loop
365 Target (J) := Pad;
366 end loop;
368 Target (Tlast - Slength + 1 .. Tlast) := Source;
370 when Center =>
371 declare
372 Front_Pad : constant Integer := (Tlength - Slength) / 2;
373 Tfirst_Fpad : constant Integer := Tfirst + Front_Pad;
375 begin
376 for J in Tfirst .. Tfirst_Fpad - 1 loop
377 Target (J) := Pad;
378 end loop;
380 Target (Tfirst_Fpad .. Tfirst_Fpad + Slength - 1) := Source;
382 for J in Tfirst_Fpad + Slength .. Tlast loop
383 Target (J) := Pad;
384 end loop;
385 end;
386 end case;
387 end if;
388 end Move;
390 ---------------
391 -- Overwrite --
392 ---------------
394 function Overwrite
395 (Source : Wide_String;
396 Position : Positive;
397 New_Item : Wide_String) return Wide_String
399 begin
400 if Position not in Source'First .. Source'Last + 1 then
401 raise Index_Error;
402 else
403 declare
404 Result_Length : constant Natural :=
405 Natural'Max
406 (Source'Length,
407 Position - Source'First + New_Item'Length);
409 Result : Wide_String (1 .. Result_Length);
411 begin
412 Result := Source (Source'First .. Position - 1) & New_Item &
413 Source (Position + New_Item'Length .. Source'Last);
414 return Result;
415 end;
416 end if;
417 end Overwrite;
419 procedure Overwrite
420 (Source : in out Wide_String;
421 Position : Positive;
422 New_Item : Wide_String;
423 Drop : Truncation := Right)
425 begin
426 Move (Source => Overwrite (Source, Position, New_Item),
427 Target => Source,
428 Drop => Drop);
429 end Overwrite;
431 -------------------
432 -- Replace_Slice --
433 -------------------
435 function Replace_Slice
436 (Source : Wide_String;
437 Low : Positive;
438 High : Natural;
439 By : Wide_String) return Wide_String
441 Result_Length : Natural;
443 begin
444 if Low > Source'Last + 1 or else High < Source'First - 1 then
445 raise Index_Error;
446 else
447 Result_Length :=
448 Source'Length - Natural'Max (High - Low + 1, 0) + By'Length;
450 declare
451 Result : Wide_String (1 .. Result_Length);
453 begin
454 if High >= Low then
455 Result :=
456 Source (Source'First .. Low - 1) & By &
457 Source (High + 1 .. Source'Last);
458 else
459 Result := Source (Source'First .. Low - 1) & By &
460 Source (Low .. Source'Last);
461 end if;
463 return Result;
464 end;
465 end if;
466 end Replace_Slice;
468 procedure Replace_Slice
469 (Source : in out Wide_String;
470 Low : Positive;
471 High : Natural;
472 By : Wide_String;
473 Drop : Truncation := Error;
474 Justify : Alignment := Left;
475 Pad : Wide_Character := Wide_Space)
477 begin
478 Move (Replace_Slice (Source, Low, High, By), Source, Drop, Justify, Pad);
479 end Replace_Slice;
481 ----------
482 -- Tail --
483 ----------
485 function Tail
486 (Source : Wide_String;
487 Count : Natural;
488 Pad : Wide_Character := Wide_Space) return Wide_String
490 Result : Wide_String (1 .. Count);
492 begin
493 if Count < Source'Length then
494 Result := Source (Source'Last - Count + 1 .. Source'Last);
496 -- Pad on left
498 else
499 for J in 1 .. Count - Source'Length loop
500 Result (J) := Pad;
501 end loop;
503 Result (Count - Source'Length + 1 .. Count) := Source;
504 end if;
506 return Result;
507 end Tail;
509 procedure Tail
510 (Source : in out Wide_String;
511 Count : Natural;
512 Justify : Alignment := Left;
513 Pad : Wide_Character := Ada.Strings.Wide_Space)
515 begin
516 Move (Source => Tail (Source, Count, Pad),
517 Target => Source,
518 Drop => Error,
519 Justify => Justify,
520 Pad => Pad);
521 end Tail;
523 ---------------
524 -- Translate --
525 ---------------
527 function Translate
528 (Source : Wide_String;
529 Mapping : Wide_Maps.Wide_Character_Mapping) return Wide_String
531 Result : Wide_String (1 .. Source'Length);
533 begin
534 for J in Source'Range loop
535 Result (J - (Source'First - 1)) := Value (Mapping, Source (J));
536 end loop;
538 return Result;
539 end Translate;
541 procedure Translate
542 (Source : in out Wide_String;
543 Mapping : Wide_Maps.Wide_Character_Mapping)
545 begin
546 for J in Source'Range loop
547 Source (J) := Value (Mapping, Source (J));
548 end loop;
549 end Translate;
551 function Translate
552 (Source : Wide_String;
553 Mapping : Wide_Maps.Wide_Character_Mapping_Function) return Wide_String
555 Result : Wide_String (1 .. Source'Length);
557 begin
558 for J in Source'Range loop
559 Result (J - (Source'First - 1)) := Mapping (Source (J));
560 end loop;
562 return Result;
563 end Translate;
565 procedure Translate
566 (Source : in out Wide_String;
567 Mapping : Wide_Maps.Wide_Character_Mapping_Function)
569 begin
570 for J in Source'Range loop
571 Source (J) := Mapping (Source (J));
572 end loop;
573 end Translate;
575 ----------
576 -- Trim --
577 ----------
579 function Trim
580 (Source : Wide_String;
581 Side : Trim_End) return Wide_String
583 Low : Natural := Source'First;
584 High : Natural := Source'Last;
586 begin
587 if Side = Left or else Side = Both then
588 while Low <= High and then Source (Low) = Wide_Space loop
589 Low := Low + 1;
590 end loop;
591 end if;
593 if Side = Right or else Side = Both then
594 while High >= Low and then Source (High) = Wide_Space loop
595 High := High - 1;
596 end loop;
597 end if;
599 -- All blanks case
601 if Low > High then
602 return "";
604 -- At least one non-blank
606 else
607 declare
608 Result : constant Wide_String (1 .. High - Low + 1) :=
609 Source (Low .. High);
611 begin
612 return Result;
613 end;
614 end if;
615 end Trim;
617 procedure Trim
618 (Source : in out Wide_String;
619 Side : Trim_End;
620 Justify : Alignment := Left;
621 Pad : Wide_Character := Wide_Space)
623 begin
624 Move (Source => Trim (Source, Side),
625 Target => Source,
626 Justify => Justify,
627 Pad => Pad);
628 end Trim;
630 function Trim
631 (Source : Wide_String;
632 Left : Wide_Maps.Wide_Character_Set;
633 Right : Wide_Maps.Wide_Character_Set) return Wide_String
635 Low : Natural := Source'First;
636 High : Natural := Source'Last;
638 begin
639 while Low <= High and then Is_In (Source (Low), Left) loop
640 Low := Low + 1;
641 end loop;
643 while High >= Low and then Is_In (Source (High), Right) loop
644 High := High - 1;
645 end loop;
647 -- Case where source comprises only characters in the sets
649 if Low > High then
650 return "";
651 else
652 declare
653 subtype WS is Wide_String (1 .. High - Low + 1);
655 begin
656 return WS (Source (Low .. High));
657 end;
658 end if;
659 end Trim;
661 procedure Trim
662 (Source : in out Wide_String;
663 Left : Wide_Maps.Wide_Character_Set;
664 Right : Wide_Maps.Wide_Character_Set;
665 Justify : Alignment := Strings.Left;
666 Pad : Wide_Character := Wide_Space)
668 begin
669 Move (Source => Trim (Source, Left, Right),
670 Target => Source,
671 Justify => Justify,
672 Pad => Pad);
673 end Trim;
675 end Ada.Strings.Wide_Fixed;