1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- A D A . S T R I N G S . W I D E _ F I X E D --
9 -- Copyright (C) 1992-2016, 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 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. --
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. --
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/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 with Ada
.Strings
.Wide_Wide_Maps
; use Ada
.Strings
.Wide_Wide_Maps
;
33 with Ada
.Strings
.Wide_Wide_Search
;
35 package body Ada
.Strings
.Wide_Wide_Fixed
is
37 ------------------------
38 -- Search Subprograms --
39 ------------------------
42 (Source
: Wide_Wide_String
;
43 Pattern
: Wide_Wide_String
;
44 Going
: Direction
:= Forward
;
45 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping
:=
46 Wide_Wide_Maps
.Identity
)
48 renames Ada
.Strings
.Wide_Wide_Search
.Index
;
51 (Source
: Wide_Wide_String
;
52 Pattern
: Wide_Wide_String
;
53 Going
: Direction
:= Forward
;
54 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping_Function
)
56 renames Ada
.Strings
.Wide_Wide_Search
.Index
;
59 (Source
: Wide_Wide_String
;
60 Set
: Wide_Wide_Maps
.Wide_Wide_Character_Set
;
61 Test
: Membership
:= Inside
;
62 Going
: Direction
:= Forward
) return Natural
63 renames Ada
.Strings
.Wide_Wide_Search
.Index
;
66 (Source
: Wide_Wide_String
;
67 Pattern
: Wide_Wide_String
;
69 Going
: Direction
:= Forward
;
70 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping
:=
71 Wide_Wide_Maps
.Identity
)
73 renames Ada
.Strings
.Wide_Wide_Search
.Index
;
76 (Source
: Wide_Wide_String
;
77 Pattern
: Wide_Wide_String
;
79 Going
: Direction
:= Forward
;
80 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping_Function
)
82 renames Ada
.Strings
.Wide_Wide_Search
.Index
;
85 (Source
: Wide_Wide_String
;
86 Set
: Wide_Wide_Maps
.Wide_Wide_Character_Set
;
88 Test
: Membership
:= Inside
;
89 Going
: Direction
:= Forward
) return Natural
90 renames Ada
.Strings
.Wide_Wide_Search
.Index
;
92 function Index_Non_Blank
93 (Source
: Wide_Wide_String
;
94 Going
: Direction
:= Forward
) return Natural
95 renames Ada
.Strings
.Wide_Wide_Search
.Index_Non_Blank
;
97 function Index_Non_Blank
98 (Source
: Wide_Wide_String
;
100 Going
: Direction
:= Forward
) return Natural
101 renames Ada
.Strings
.Wide_Wide_Search
.Index_Non_Blank
;
104 (Source
: Wide_Wide_String
;
105 Pattern
: Wide_Wide_String
;
106 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping
:=
107 Wide_Wide_Maps
.Identity
)
109 renames Ada
.Strings
.Wide_Wide_Search
.Count
;
112 (Source
: Wide_Wide_String
;
113 Pattern
: Wide_Wide_String
;
114 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping_Function
)
116 renames Ada
.Strings
.Wide_Wide_Search
.Count
;
119 (Source
: Wide_Wide_String
;
120 Set
: Wide_Wide_Maps
.Wide_Wide_Character_Set
) return Natural
121 renames Ada
.Strings
.Wide_Wide_Search
.Count
;
124 (Source
: Wide_Wide_String
;
125 Set
: Wide_Wide_Maps
.Wide_Wide_Character_Set
;
128 First
: out Positive;
130 renames Ada
.Strings
.Wide_Wide_Search
.Find_Token
;
133 (Source
: Wide_Wide_String
;
134 Set
: Wide_Wide_Maps
.Wide_Wide_Character_Set
;
136 First
: out Positive;
138 renames Ada
.Strings
.Wide_Wide_Search
.Find_Token
;
146 Right
: Wide_Wide_Character
) return Wide_Wide_String
148 Result
: Wide_Wide_String
(1 .. Left
);
151 for J
in Result
'Range loop
160 Right
: Wide_Wide_String
) return Wide_Wide_String
162 Result
: Wide_Wide_String
(1 .. Left
* Right
'Length);
166 for J
in 1 .. Left
loop
167 Result
(Ptr
.. Ptr
+ Right
'Length - 1) := Right
;
168 Ptr
:= Ptr
+ Right
'Length;
179 (Source
: Wide_Wide_String
;
181 Through
: Natural) return Wide_Wide_String
184 if From
not in Source
'Range
185 or else Through
> Source
'Last
189 elsif From
> Through
then
194 Len
: constant Integer := Source
'Length - (Through
- From
+ 1);
195 Result
: constant Wide_Wide_String
196 (Source
'First .. Source
'First + Len
- 1) :=
197 Source
(Source
'First .. From
- 1) &
198 Source
(Through
+ 1 .. Source
'Last);
206 (Source
: in out Wide_Wide_String
;
209 Justify
: Alignment
:= Left
;
210 Pad
: Wide_Wide_Character
:= Wide_Wide_Space
)
213 Move
(Source
=> Delete
(Source
, From
, Through
),
224 (Source
: Wide_Wide_String
;
226 Pad
: Wide_Wide_Character
:= Wide_Wide_Space
) return Wide_Wide_String
228 Result
: Wide_Wide_String
(1 .. Count
);
231 if Count
<= Source
'Length then
232 Result
:= Source
(Source
'First .. Source
'First + Count
- 1);
235 Result
(1 .. Source
'Length) := Source
;
237 for J
in Source
'Length + 1 .. Count
loop
246 (Source
: in out Wide_Wide_String
;
248 Justify
: Alignment
:= Left
;
249 Pad
: Wide_Wide_Character
:= Ada
.Strings
.Wide_Wide_Space
)
252 Move
(Source
=> Head
(Source
, Count
, Pad
),
264 (Source
: Wide_Wide_String
;
266 New_Item
: Wide_Wide_String
) return Wide_Wide_String
268 Result
: Wide_Wide_String
(1 .. Source
'Length + New_Item
'Length);
271 if Before
< Source
'First or else Before
> Source
'Last + 1 then
275 Result
:= Source
(Source
'First .. Before
- 1) & New_Item
&
276 Source
(Before
.. Source
'Last);
281 (Source
: in out Wide_Wide_String
;
283 New_Item
: Wide_Wide_String
;
284 Drop
: Truncation
:= Error
)
287 Move
(Source
=> Insert
(Source
, Before
, New_Item
),
297 (Source
: Wide_Wide_String
;
298 Target
: out Wide_Wide_String
;
299 Drop
: Truncation
:= Error
;
300 Justify
: Alignment
:= Left
;
301 Pad
: Wide_Wide_Character
:= Wide_Wide_Space
)
303 Sfirst
: constant Integer := Source
'First;
304 Slast
: constant Integer := Source
'Last;
305 Slength
: constant Integer := Source
'Length;
307 Tfirst
: constant Integer := Target
'First;
308 Tlast
: constant Integer := Target
'Last;
309 Tlength
: constant Integer := Target
'Length;
311 function Is_Padding
(Item
: Wide_Wide_String
) return Boolean;
312 -- Determinbe if all characters in Item are pad characters
314 function Is_Padding
(Item
: Wide_Wide_String
) return Boolean is
316 for J
in Item
'Range loop
317 if Item
(J
) /= Pad
then
325 -- Start of processing for Move
328 if Slength
= Tlength
then
331 elsif Slength
> Tlength
then
334 Target
:= Source
(Slast
- Tlength
+ 1 .. Slast
);
337 Target
:= Source
(Sfirst
.. Sfirst
+ Tlength
- 1);
342 if Is_Padding
(Source
(Sfirst
+ Tlength
.. Slast
)) then
344 Source
(Sfirst
.. Sfirst
+ Target
'Length - 1);
350 if Is_Padding
(Source
(Sfirst
.. Slast
- Tlength
)) then
351 Target
:= Source
(Slast
- Tlength
+ 1 .. Slast
);
362 -- Source'Length < Target'Length
367 Target
(Tfirst
.. Tfirst
+ Slength
- 1) := Source
;
369 for J
in Tfirst
+ Slength
.. Tlast
loop
374 for J
in Tfirst
.. Tlast
- Slength
loop
378 Target
(Tlast
- Slength
+ 1 .. Tlast
) := Source
;
382 Front_Pad
: constant Integer := (Tlength
- Slength
) / 2;
383 Tfirst_Fpad
: constant Integer := Tfirst
+ Front_Pad
;
386 for J
in Tfirst
.. Tfirst_Fpad
- 1 loop
390 Target
(Tfirst_Fpad
.. Tfirst_Fpad
+ Slength
- 1) := Source
;
392 for J
in Tfirst_Fpad
+ Slength
.. Tlast
loop
405 (Source
: Wide_Wide_String
;
407 New_Item
: Wide_Wide_String
) return Wide_Wide_String
410 if Position
not in Source
'First .. Source
'Last + 1 then
414 Result_Length
: constant Natural :=
417 Position
- Source
'First + New_Item
'Length);
419 Result
: Wide_Wide_String
(1 .. Result_Length
);
422 Result
:= Source
(Source
'First .. Position
- 1) & New_Item
&
423 Source
(Position
+ New_Item
'Length .. Source
'Last);
430 (Source
: in out Wide_Wide_String
;
432 New_Item
: Wide_Wide_String
;
433 Drop
: Truncation
:= Right
)
436 Move
(Source
=> Overwrite
(Source
, Position
, New_Item
),
445 function Replace_Slice
446 (Source
: Wide_Wide_String
;
449 By
: Wide_Wide_String
) return Wide_Wide_String
452 if Low
> Source
'Last + 1 or else High
< Source
'First - 1 then
458 Front_Len
: constant Integer :=
459 Integer'Max (0, Low
- Source
'First);
460 -- Length of prefix of Source copied to result
462 Back_Len
: constant Integer :=
463 Integer'Max (0, Source
'Last - High
);
464 -- Length of suffix of Source copied to result
466 Result_Length
: constant Integer :=
467 Front_Len
+ By
'Length + Back_Len
;
470 Result
: Wide_Wide_String
(1 .. Result_Length
);
473 Result
(1 .. Front_Len
) := Source
(Source
'First .. Low
- 1);
474 Result
(Front_Len
+ 1 .. Front_Len
+ By
'Length) := By
;
475 Result
(Front_Len
+ By
'Length + 1 .. Result
'Length) :=
476 Source
(High
+ 1 .. Source
'Last);
481 return Insert
(Source
, Before
=> Low
, New_Item
=> By
);
485 procedure Replace_Slice
486 (Source
: in out Wide_Wide_String
;
489 By
: Wide_Wide_String
;
490 Drop
: Truncation
:= Error
;
491 Justify
: Alignment
:= Left
;
492 Pad
: Wide_Wide_Character
:= Wide_Wide_Space
)
495 Move
(Replace_Slice
(Source
, Low
, High
, By
), Source
, Drop
, Justify
, Pad
);
503 (Source
: Wide_Wide_String
;
505 Pad
: Wide_Wide_Character
:= Wide_Wide_Space
) return Wide_Wide_String
507 Result
: Wide_Wide_String
(1 .. Count
);
510 if Count
< Source
'Length then
511 Result
:= Source
(Source
'Last - Count
+ 1 .. Source
'Last);
516 for J
in 1 .. Count
- Source
'Length loop
520 Result
(Count
- Source
'Length + 1 .. Count
) := Source
;
527 (Source
: in out Wide_Wide_String
;
529 Justify
: Alignment
:= Left
;
530 Pad
: Wide_Wide_Character
:= Ada
.Strings
.Wide_Wide_Space
)
533 Move
(Source
=> Tail
(Source
, Count
, Pad
),
545 (Source
: Wide_Wide_String
;
546 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping
)
547 return Wide_Wide_String
549 Result
: Wide_Wide_String
(1 .. Source
'Length);
552 for J
in Source
'Range loop
553 Result
(J
- (Source
'First - 1)) := Value
(Mapping
, Source
(J
));
560 (Source
: in out Wide_Wide_String
;
561 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping
)
564 for J
in Source
'Range loop
565 Source
(J
) := Value
(Mapping
, Source
(J
));
570 (Source
: Wide_Wide_String
;
571 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping_Function
)
572 return Wide_Wide_String
574 Result
: Wide_Wide_String
(1 .. Source
'Length);
577 for J
in Source
'Range loop
578 Result
(J
- (Source
'First - 1)) := Mapping
(Source
(J
));
585 (Source
: in out Wide_Wide_String
;
586 Mapping
: Wide_Wide_Maps
.Wide_Wide_Character_Mapping_Function
)
589 for J
in Source
'Range loop
590 Source
(J
) := Mapping
(Source
(J
));
599 (Source
: Wide_Wide_String
;
600 Side
: Trim_End
) return Wide_Wide_String
602 Low
: Natural := Source
'First;
603 High
: Natural := Source
'Last;
606 if Side
= Left
or else Side
= Both
then
607 while Low
<= High
and then Source
(Low
) = Wide_Wide_Space
loop
612 if Side
= Right
or else Side
= Both
then
613 while High
>= Low
and then Source
(High
) = Wide_Wide_Space
loop
623 -- At least one non-blank
627 Result
: constant Wide_Wide_String
(1 .. High
- Low
+ 1) :=
628 Source
(Low
.. High
);
637 (Source
: in out Wide_Wide_String
;
639 Justify
: Alignment
:= Left
;
640 Pad
: Wide_Wide_Character
:= Wide_Wide_Space
)
643 Move
(Source
=> Trim
(Source
, Side
),
650 (Source
: Wide_Wide_String
;
651 Left
: Wide_Wide_Maps
.Wide_Wide_Character_Set
;
652 Right
: Wide_Wide_Maps
.Wide_Wide_Character_Set
) return Wide_Wide_String
654 Low
: Natural := Source
'First;
655 High
: Natural := Source
'Last;
658 while Low
<= High
and then Is_In
(Source
(Low
), Left
) loop
662 while High
>= Low
and then Is_In
(Source
(High
), Right
) loop
666 -- Case where source comprises only characters in the sets
672 subtype WS
is Wide_Wide_String
(1 .. High
- Low
+ 1);
675 return WS
(Source
(Low
.. High
));
681 (Source
: in out Wide_Wide_String
;
682 Left
: Wide_Wide_Maps
.Wide_Wide_Character_Set
;
683 Right
: Wide_Wide_Maps
.Wide_Wide_Character_Set
;
684 Justify
: Alignment
:= Strings
.Left
;
685 Pad
: Wide_Wide_Character
:= Wide_Wide_Space
)
688 Move
(Source
=> Trim
(Source
, Left
, Right
),
694 end Ada
.Strings
.Wide_Wide_Fixed
;