]>
Commit | Line | Data |
---|---|---|
d23b8f57 RK |
1 | ------------------------------------------------------------------------------ |
2 | -- -- | |
3084fecd | 3 | -- GNAT RUN-TIME COMPONENTS -- |
d23b8f57 RK |
4 | -- -- |
5 | -- A D A . S T R I N G S . F I X E D -- | |
6 | -- -- | |
7 | -- B o d y -- | |
8 | -- -- | |
1d005acc | 9 | -- Copyright (C) 1992-2019, Free Software Foundation, Inc. -- |
d23b8f57 RK |
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- -- | |
748086b7 | 13 | -- ware Foundation; either version 3, or (at your option) any later ver- -- |
d23b8f57 RK |
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 -- | |
748086b7 | 16 | -- or FITNESS FOR A PARTICULAR PURPOSE. -- |
d23b8f57 | 17 | -- -- |
748086b7 JJ |
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/>. -- | |
d23b8f57 RK |
26 | -- -- |
27 | -- GNAT was originally developed by the GNAT team at New York University. -- | |
71ff80dc | 28 | -- Extensive contributions were provided by Ada Core Technologies Inc. -- |
d23b8f57 RK |
29 | -- -- |
30 | ------------------------------------------------------------------------------ | |
31 | ||
9de61fcb RD |
32 | -- Note: This code is derived from the ADAR.CSH public domain Ada 83 versions |
33 | -- of the Appendix C string handling packages. One change is to avoid the use | |
34 | -- of Is_In, so that we are not dependent on inlining. Note that the search | |
35 | -- function implementations are to be found in the auxiliary package | |
36 | -- Ada.Strings.Search. Also the Move procedure is directly incorporated (ADAR | |
8fc789c8 | 37 | -- used a subunit for this procedure). The number of errors having to do with |
9de61fcb RD |
38 | -- bounds of function return results were also fixed, and use of & removed for |
39 | -- efficiency reasons. | |
d23b8f57 RK |
40 | |
41 | with Ada.Strings.Maps; use Ada.Strings.Maps; | |
42 | with Ada.Strings.Search; | |
43 | ||
44 | package body Ada.Strings.Fixed is | |
45 | ||
46 | ------------------------ | |
47 | -- Search Subprograms -- | |
48 | ------------------------ | |
49 | ||
50 | function Index | |
4e45e7a9 RD |
51 | (Source : String; |
52 | Pattern : String; | |
53 | Going : Direction := Forward; | |
54 | Mapping : Maps.Character_Mapping := Maps.Identity) return Natural | |
d23b8f57 RK |
55 | renames Ada.Strings.Search.Index; |
56 | ||
57 | function Index | |
4e45e7a9 RD |
58 | (Source : String; |
59 | Pattern : String; | |
60 | Going : Direction := Forward; | |
61 | Mapping : Maps.Character_Mapping_Function) return Natural | |
d23b8f57 RK |
62 | renames Ada.Strings.Search.Index; |
63 | ||
64 | function Index | |
4e45e7a9 RD |
65 | (Source : String; |
66 | Set : Maps.Character_Set; | |
67 | Test : Membership := Inside; | |
68 | Going : Direction := Forward) return Natural | |
d23b8f57 RK |
69 | renames Ada.Strings.Search.Index; |
70 | ||
4e45e7a9 RD |
71 | function Index |
72 | (Source : String; | |
73 | Pattern : String; | |
74 | From : Positive; | |
75 | Going : Direction := Forward; | |
76 | Mapping : Maps.Character_Mapping := Maps.Identity) return Natural | |
77 | renames Ada.Strings.Search.Index; | |
78 | ||
79 | function Index | |
80 | (Source : String; | |
81 | Pattern : String; | |
82 | From : Positive; | |
83 | Going : Direction := Forward; | |
84 | Mapping : Maps.Character_Mapping_Function) return Natural | |
85 | renames Ada.Strings.Search.Index; | |
86 | ||
87 | function Index | |
88 | (Source : String; | |
89 | Set : Maps.Character_Set; | |
90 | From : Positive; | |
91 | Test : Membership := Inside; | |
92 | Going : Direction := Forward) return Natural | |
93 | renames Ada.Strings.Search.Index; | |
94 | ||
95 | function Index_Non_Blank | |
96 | (Source : String; | |
97 | Going : Direction := Forward) return Natural | |
98 | renames Ada.Strings.Search.Index_Non_Blank; | |
99 | ||
d23b8f57 | 100 | function Index_Non_Blank |
4e45e7a9 RD |
101 | (Source : String; |
102 | From : Positive; | |
103 | Going : Direction := Forward) return Natural | |
d23b8f57 RK |
104 | renames Ada.Strings.Search.Index_Non_Blank; |
105 | ||
106 | function Count | |
4e45e7a9 RD |
107 | (Source : String; |
108 | Pattern : String; | |
109 | Mapping : Maps.Character_Mapping := Maps.Identity) return Natural | |
d23b8f57 RK |
110 | renames Ada.Strings.Search.Count; |
111 | ||
112 | function Count | |
4e45e7a9 RD |
113 | (Source : String; |
114 | Pattern : String; | |
115 | Mapping : Maps.Character_Mapping_Function) return Natural | |
d23b8f57 RK |
116 | renames Ada.Strings.Search.Count; |
117 | ||
118 | function Count | |
4e45e7a9 RD |
119 | (Source : String; |
120 | Set : Maps.Character_Set) return Natural | |
d23b8f57 RK |
121 | renames Ada.Strings.Search.Count; |
122 | ||
af31bffb AC |
123 | procedure Find_Token |
124 | (Source : String; | |
125 | Set : Maps.Character_Set; | |
126 | From : Positive; | |
127 | Test : Membership; | |
128 | First : out Positive; | |
129 | Last : out Natural) | |
130 | renames Ada.Strings.Search.Find_Token; | |
131 | ||
d23b8f57 | 132 | procedure Find_Token |
4e45e7a9 RD |
133 | (Source : String; |
134 | Set : Maps.Character_Set; | |
135 | Test : Membership; | |
d23b8f57 RK |
136 | First : out Positive; |
137 | Last : out Natural) | |
138 | renames Ada.Strings.Search.Find_Token; | |
139 | ||
140 | --------- | |
141 | -- "*" -- | |
142 | --------- | |
143 | ||
144 | function "*" | |
4e45e7a9 RD |
145 | (Left : Natural; |
146 | Right : Character) return String | |
d23b8f57 RK |
147 | is |
148 | Result : String (1 .. Left); | |
149 | ||
150 | begin | |
151 | for J in Result'Range loop | |
152 | Result (J) := Right; | |
153 | end loop; | |
154 | ||
155 | return Result; | |
156 | end "*"; | |
157 | ||
158 | function "*" | |
4e45e7a9 RD |
159 | (Left : Natural; |
160 | Right : String) return String | |
d23b8f57 RK |
161 | is |
162 | Result : String (1 .. Left * Right'Length); | |
163 | Ptr : Integer := 1; | |
164 | ||
165 | begin | |
166 | for J in 1 .. Left loop | |
167 | Result (Ptr .. Ptr + Right'Length - 1) := Right; | |
168 | Ptr := Ptr + Right'Length; | |
169 | end loop; | |
170 | ||
171 | return Result; | |
172 | end "*"; | |
173 | ||
174 | ------------ | |
175 | -- Delete -- | |
176 | ------------ | |
177 | ||
178 | function Delete | |
4e45e7a9 RD |
179 | (Source : String; |
180 | From : Positive; | |
181 | Through : Natural) return String | |
d23b8f57 RK |
182 | is |
183 | begin | |
184 | if From > Through then | |
185 | declare | |
186 | subtype Result_Type is String (1 .. Source'Length); | |
187 | ||
188 | begin | |
189 | return Result_Type (Source); | |
190 | end; | |
191 | ||
192 | elsif From not in Source'Range | |
193 | or else Through > Source'Last | |
194 | then | |
a6b13d32 AC |
195 | pragma Annotate |
196 | (CodePeer, False_Positive, | |
197 | "test always false", "self fullfilling prophecy"); | |
198 | ||
4962dc44 ES |
199 | -- In most cases this raises an exception, but the case of deleting |
200 | -- a null string at the end of the current one is a special-case, and | |
201 | -- reflects the equivalence with Replace_String (RM A.4.3 (86/3)). | |
202 | ||
203 | if From = Source'Last + 1 and then From = Through then | |
204 | return Source; | |
205 | else | |
206 | raise Index_Error; | |
207 | end if; | |
d23b8f57 RK |
208 | |
209 | else | |
210 | declare | |
211 | Front : constant Integer := From - Source'First; | |
212 | Result : String (1 .. Source'Length - (Through - From + 1)); | |
213 | ||
214 | begin | |
215 | Result (1 .. Front) := | |
216 | Source (Source'First .. From - 1); | |
217 | Result (Front + 1 .. Result'Last) := | |
218 | Source (Through + 1 .. Source'Last); | |
219 | ||
220 | return Result; | |
221 | end; | |
222 | end if; | |
223 | end Delete; | |
224 | ||
225 | procedure Delete | |
226 | (Source : in out String; | |
4e45e7a9 RD |
227 | From : Positive; |
228 | Through : Natural; | |
229 | Justify : Alignment := Left; | |
230 | Pad : Character := Space) | |
d23b8f57 RK |
231 | is |
232 | begin | |
233 | Move (Source => Delete (Source, From, Through), | |
234 | Target => Source, | |
235 | Justify => Justify, | |
236 | Pad => Pad); | |
237 | end Delete; | |
238 | ||
239 | ---------- | |
240 | -- Head -- | |
241 | ---------- | |
242 | ||
243 | function Head | |
4e45e7a9 RD |
244 | (Source : String; |
245 | Count : Natural; | |
246 | Pad : Character := Space) return String | |
d23b8f57 RK |
247 | is |
248 | subtype Result_Type is String (1 .. Count); | |
249 | ||
250 | begin | |
251 | if Count < Source'Length then | |
252 | return | |
253 | Result_Type (Source (Source'First .. Source'First + Count - 1)); | |
254 | ||
255 | else | |
256 | declare | |
257 | Result : Result_Type; | |
258 | ||
259 | begin | |
260 | Result (1 .. Source'Length) := Source; | |
261 | ||
262 | for J in Source'Length + 1 .. Count loop | |
263 | Result (J) := Pad; | |
264 | end loop; | |
265 | ||
266 | return Result; | |
267 | end; | |
268 | end if; | |
269 | end Head; | |
270 | ||
271 | procedure Head | |
272 | (Source : in out String; | |
4e45e7a9 RD |
273 | Count : Natural; |
274 | Justify : Alignment := Left; | |
275 | Pad : Character := Space) | |
d23b8f57 RK |
276 | is |
277 | begin | |
278 | Move (Source => Head (Source, Count, Pad), | |
279 | Target => Source, | |
280 | Drop => Error, | |
281 | Justify => Justify, | |
282 | Pad => Pad); | |
283 | end Head; | |
284 | ||
285 | ------------ | |
286 | -- Insert -- | |
287 | ------------ | |
288 | ||
289 | function Insert | |
4e45e7a9 RD |
290 | (Source : String; |
291 | Before : Positive; | |
292 | New_Item : String) return String | |
d23b8f57 RK |
293 | is |
294 | Result : String (1 .. Source'Length + New_Item'Length); | |
295 | Front : constant Integer := Before - Source'First; | |
296 | ||
297 | begin | |
298 | if Before not in Source'First .. Source'Last + 1 then | |
299 | raise Index_Error; | |
300 | end if; | |
301 | ||
302 | Result (1 .. Front) := | |
303 | Source (Source'First .. Before - 1); | |
304 | Result (Front + 1 .. Front + New_Item'Length) := | |
305 | New_Item; | |
306 | Result (Front + New_Item'Length + 1 .. Result'Last) := | |
307 | Source (Before .. Source'Last); | |
308 | ||
309 | return Result; | |
310 | end Insert; | |
311 | ||
312 | procedure Insert | |
313 | (Source : in out String; | |
4e45e7a9 RD |
314 | Before : Positive; |
315 | New_Item : String; | |
316 | Drop : Truncation := Error) | |
d23b8f57 RK |
317 | is |
318 | begin | |
319 | Move (Source => Insert (Source, Before, New_Item), | |
320 | Target => Source, | |
321 | Drop => Drop); | |
322 | end Insert; | |
323 | ||
324 | ---------- | |
325 | -- Move -- | |
326 | ---------- | |
327 | ||
328 | procedure Move | |
4e45e7a9 | 329 | (Source : String; |
d23b8f57 | 330 | Target : out String; |
4e45e7a9 RD |
331 | Drop : Truncation := Error; |
332 | Justify : Alignment := Left; | |
333 | Pad : Character := Space) | |
d23b8f57 RK |
334 | is |
335 | Sfirst : constant Integer := Source'First; | |
336 | Slast : constant Integer := Source'Last; | |
337 | Slength : constant Integer := Source'Length; | |
338 | ||
339 | Tfirst : constant Integer := Target'First; | |
340 | Tlast : constant Integer := Target'Last; | |
341 | Tlength : constant Integer := Target'Length; | |
342 | ||
343 | function Is_Padding (Item : String) return Boolean; | |
344 | -- Check if Item is all Pad characters, return True if so, False if not | |
345 | ||
346 | function Is_Padding (Item : String) return Boolean is | |
347 | begin | |
348 | for J in Item'Range loop | |
349 | if Item (J) /= Pad then | |
350 | return False; | |
351 | end if; | |
352 | end loop; | |
353 | ||
354 | return True; | |
355 | end Is_Padding; | |
356 | ||
357 | -- Start of processing for Move | |
358 | ||
359 | begin | |
360 | if Slength = Tlength then | |
361 | Target := Source; | |
362 | ||
363 | elsif Slength > Tlength then | |
d23b8f57 RK |
364 | case Drop is |
365 | when Left => | |
366 | Target := Source (Slast - Tlength + 1 .. Slast); | |
367 | ||
368 | when Right => | |
369 | Target := Source (Sfirst .. Sfirst + Tlength - 1); | |
370 | ||
371 | when Error => | |
372 | case Justify is | |
373 | when Left => | |
374 | if Is_Padding (Source (Sfirst + Tlength .. Slast)) then | |
375 | Target := | |
376 | Source (Sfirst .. Sfirst + Target'Length - 1); | |
377 | else | |
378 | raise Length_Error; | |
379 | end if; | |
380 | ||
381 | when Right => | |
382 | if Is_Padding (Source (Sfirst .. Slast - Tlength)) then | |
383 | Target := Source (Slast - Tlength + 1 .. Slast); | |
384 | else | |
385 | raise Length_Error; | |
386 | end if; | |
387 | ||
388 | when Center => | |
389 | raise Length_Error; | |
390 | end case; | |
d23b8f57 RK |
391 | end case; |
392 | ||
393 | -- Source'Length < Target'Length | |
394 | ||
395 | else | |
396 | case Justify is | |
397 | when Left => | |
398 | Target (Tfirst .. Tfirst + Slength - 1) := Source; | |
399 | ||
400 | for I in Tfirst + Slength .. Tlast loop | |
401 | Target (I) := Pad; | |
402 | end loop; | |
403 | ||
404 | when Right => | |
405 | for I in Tfirst .. Tlast - Slength loop | |
406 | Target (I) := Pad; | |
407 | end loop; | |
408 | ||
409 | Target (Tlast - Slength + 1 .. Tlast) := Source; | |
410 | ||
411 | when Center => | |
412 | declare | |
413 | Front_Pad : constant Integer := (Tlength - Slength) / 2; | |
414 | Tfirst_Fpad : constant Integer := Tfirst + Front_Pad; | |
415 | ||
416 | begin | |
417 | for I in Tfirst .. Tfirst_Fpad - 1 loop | |
418 | Target (I) := Pad; | |
419 | end loop; | |
420 | ||
421 | Target (Tfirst_Fpad .. Tfirst_Fpad + Slength - 1) := Source; | |
422 | ||
423 | for I in Tfirst_Fpad + Slength .. Tlast loop | |
424 | Target (I) := Pad; | |
425 | end loop; | |
426 | end; | |
427 | end case; | |
428 | end if; | |
429 | end Move; | |
430 | ||
431 | --------------- | |
432 | -- Overwrite -- | |
433 | --------------- | |
434 | ||
435 | function Overwrite | |
4e45e7a9 RD |
436 | (Source : String; |
437 | Position : Positive; | |
438 | New_Item : String) return String | |
d23b8f57 RK |
439 | is |
440 | begin | |
441 | if Position not in Source'First .. Source'Last + 1 then | |
442 | raise Index_Error; | |
443 | end if; | |
444 | ||
445 | declare | |
fbf5a39b | 446 | Result_Length : constant Natural := |
15f0f591 AC |
447 | Integer'Max |
448 | (Source'Length, | |
449 | Position - Source'First + New_Item'Length); | |
d23b8f57 RK |
450 | |
451 | Result : String (1 .. Result_Length); | |
452 | Front : constant Integer := Position - Source'First; | |
453 | ||
454 | begin | |
455 | Result (1 .. Front) := | |
456 | Source (Source'First .. Position - 1); | |
457 | Result (Front + 1 .. Front + New_Item'Length) := | |
458 | New_Item; | |
459 | Result (Front + New_Item'Length + 1 .. Result'Length) := | |
460 | Source (Position + New_Item'Length .. Source'Last); | |
461 | return Result; | |
462 | end; | |
463 | end Overwrite; | |
464 | ||
465 | procedure Overwrite | |
466 | (Source : in out String; | |
4e45e7a9 RD |
467 | Position : Positive; |
468 | New_Item : String; | |
469 | Drop : Truncation := Right) | |
d23b8f57 RK |
470 | is |
471 | begin | |
472 | Move (Source => Overwrite (Source, Position, New_Item), | |
473 | Target => Source, | |
474 | Drop => Drop); | |
475 | end Overwrite; | |
476 | ||
477 | ------------------- | |
478 | -- Replace_Slice -- | |
479 | ------------------- | |
480 | ||
481 | function Replace_Slice | |
4e45e7a9 RD |
482 | (Source : String; |
483 | Low : Positive; | |
484 | High : Natural; | |
485 | By : String) return String | |
d23b8f57 RK |
486 | is |
487 | begin | |
d1ced162 | 488 | if Low > Source'Last + 1 or else High < Source'First - 1 then |
d23b8f57 RK |
489 | raise Index_Error; |
490 | end if; | |
491 | ||
492 | if High >= Low then | |
493 | declare | |
494 | Front_Len : constant Integer := | |
15f0f591 | 495 | Integer'Max (0, Low - Source'First); |
d23b8f57 RK |
496 | -- Length of prefix of Source copied to result |
497 | ||
47e11d08 | 498 | Back_Len : constant Integer := |
15f0f591 | 499 | Integer'Max (0, Source'Last - High); |
d23b8f57 RK |
500 | -- Length of suffix of Source copied to result |
501 | ||
502 | Result_Length : constant Integer := | |
15f0f591 | 503 | Front_Len + By'Length + Back_Len; |
d23b8f57 RK |
504 | -- Length of result |
505 | ||
506 | Result : String (1 .. Result_Length); | |
507 | ||
508 | begin | |
47e11d08 AC |
509 | Result (1 .. Front_Len) := Source (Source'First .. Low - 1); |
510 | Result (Front_Len + 1 .. Front_Len + By'Length) := By; | |
d23b8f57 RK |
511 | Result (Front_Len + By'Length + 1 .. Result'Length) := |
512 | Source (High + 1 .. Source'Last); | |
d23b8f57 RK |
513 | return Result; |
514 | end; | |
515 | ||
516 | else | |
517 | return Insert (Source, Before => Low, New_Item => By); | |
518 | end if; | |
519 | end Replace_Slice; | |
520 | ||
521 | procedure Replace_Slice | |
522 | (Source : in out String; | |
4e45e7a9 RD |
523 | Low : Positive; |
524 | High : Natural; | |
525 | By : String; | |
526 | Drop : Truncation := Error; | |
527 | Justify : Alignment := Left; | |
528 | Pad : Character := Space) | |
d23b8f57 RK |
529 | is |
530 | begin | |
531 | Move (Replace_Slice (Source, Low, High, By), Source, Drop, Justify, Pad); | |
532 | end Replace_Slice; | |
533 | ||
534 | ---------- | |
535 | -- Tail -- | |
536 | ---------- | |
537 | ||
538 | function Tail | |
4e45e7a9 RD |
539 | (Source : String; |
540 | Count : Natural; | |
541 | Pad : Character := Space) return String | |
d23b8f57 RK |
542 | is |
543 | subtype Result_Type is String (1 .. Count); | |
544 | ||
545 | begin | |
546 | if Count < Source'Length then | |
547 | return Result_Type (Source (Source'Last - Count + 1 .. Source'Last)); | |
548 | ||
549 | -- Pad on left | |
550 | ||
551 | else | |
552 | declare | |
553 | Result : Result_Type; | |
554 | ||
555 | begin | |
556 | for J in 1 .. Count - Source'Length loop | |
557 | Result (J) := Pad; | |
558 | end loop; | |
559 | ||
560 | Result (Count - Source'Length + 1 .. Count) := Source; | |
561 | return Result; | |
562 | end; | |
563 | end if; | |
564 | end Tail; | |
565 | ||
566 | procedure Tail | |
567 | (Source : in out String; | |
4e45e7a9 RD |
568 | Count : Natural; |
569 | Justify : Alignment := Left; | |
570 | Pad : Character := Space) | |
d23b8f57 RK |
571 | is |
572 | begin | |
573 | Move (Source => Tail (Source, Count, Pad), | |
574 | Target => Source, | |
575 | Drop => Error, | |
576 | Justify => Justify, | |
577 | Pad => Pad); | |
578 | end Tail; | |
579 | ||
580 | --------------- | |
581 | -- Translate -- | |
582 | --------------- | |
583 | ||
584 | function Translate | |
4e45e7a9 RD |
585 | (Source : String; |
586 | Mapping : Maps.Character_Mapping) return String | |
d23b8f57 RK |
587 | is |
588 | Result : String (1 .. Source'Length); | |
589 | ||
590 | begin | |
591 | for J in Source'Range loop | |
592 | Result (J - (Source'First - 1)) := Value (Mapping, Source (J)); | |
593 | end loop; | |
594 | ||
595 | return Result; | |
596 | end Translate; | |
597 | ||
598 | procedure Translate | |
599 | (Source : in out String; | |
4e45e7a9 | 600 | Mapping : Maps.Character_Mapping) |
d23b8f57 RK |
601 | is |
602 | begin | |
603 | for J in Source'Range loop | |
604 | Source (J) := Value (Mapping, Source (J)); | |
605 | end loop; | |
606 | end Translate; | |
607 | ||
608 | function Translate | |
4e45e7a9 RD |
609 | (Source : String; |
610 | Mapping : Maps.Character_Mapping_Function) return String | |
d23b8f57 RK |
611 | is |
612 | Result : String (1 .. Source'Length); | |
613 | pragma Unsuppress (Access_Check); | |
614 | ||
615 | begin | |
616 | for J in Source'Range loop | |
617 | Result (J - (Source'First - 1)) := Mapping.all (Source (J)); | |
618 | end loop; | |
619 | ||
620 | return Result; | |
621 | end Translate; | |
622 | ||
623 | procedure Translate | |
624 | (Source : in out String; | |
4e45e7a9 | 625 | Mapping : Maps.Character_Mapping_Function) |
d23b8f57 RK |
626 | is |
627 | pragma Unsuppress (Access_Check); | |
628 | begin | |
629 | for J in Source'Range loop | |
630 | Source (J) := Mapping.all (Source (J)); | |
631 | end loop; | |
632 | end Translate; | |
633 | ||
634 | ---------- | |
635 | -- Trim -- | |
636 | ---------- | |
637 | ||
638 | function Trim | |
4e45e7a9 RD |
639 | (Source : String; |
640 | Side : Trim_End) return String | |
d23b8f57 | 641 | is |
d23b8f57 | 642 | begin |
3815f967 AC |
643 | case Side is |
644 | when Strings.Left => | |
645 | declare | |
646 | Low : constant Natural := Index_Non_Blank (Source, Forward); | |
647 | begin | |
648 | -- All blanks case | |
d23b8f57 | 649 | |
3815f967 AC |
650 | if Low = 0 then |
651 | return ""; | |
652 | end if; | |
d23b8f57 | 653 | |
d23b8f57 RK |
654 | declare |
655 | subtype Result_Type is String (1 .. Source'Last - Low + 1); | |
d23b8f57 RK |
656 | begin |
657 | return Result_Type (Source (Low .. Source'Last)); | |
658 | end; | |
3815f967 AC |
659 | end; |
660 | ||
661 | when Strings.Right => | |
662 | declare | |
663 | High : constant Natural := Index_Non_Blank (Source, Backward); | |
664 | begin | |
665 | -- All blanks case | |
666 | ||
667 | if High = 0 then | |
668 | return ""; | |
669 | end if; | |
d23b8f57 | 670 | |
d23b8f57 RK |
671 | declare |
672 | subtype Result_Type is String (1 .. High - Source'First + 1); | |
d23b8f57 RK |
673 | begin |
674 | return Result_Type (Source (Source'First .. High)); | |
675 | end; | |
3815f967 AC |
676 | end; |
677 | ||
678 | when Strings.Both => | |
679 | declare | |
680 | Low : constant Natural := Index_Non_Blank (Source, Forward); | |
681 | begin | |
682 | -- All blanks case | |
683 | ||
684 | if Low = 0 then | |
685 | return ""; | |
686 | end if; | |
d23b8f57 | 687 | |
d23b8f57 | 688 | declare |
3815f967 AC |
689 | High : constant Natural := |
690 | Index_Non_Blank (Source, Backward); | |
d23b8f57 | 691 | subtype Result_Type is String (1 .. High - Low + 1); |
d23b8f57 RK |
692 | begin |
693 | return Result_Type (Source (Low .. High)); | |
694 | end; | |
3815f967 AC |
695 | end; |
696 | end case; | |
d23b8f57 RK |
697 | end Trim; |
698 | ||
699 | procedure Trim | |
700 | (Source : in out String; | |
4e45e7a9 RD |
701 | Side : Trim_End; |
702 | Justify : Alignment := Left; | |
703 | Pad : Character := Space) | |
d23b8f57 RK |
704 | is |
705 | begin | |
706 | Move (Trim (Source, Side), | |
707 | Source, | |
708 | Justify => Justify, | |
709 | Pad => Pad); | |
710 | end Trim; | |
711 | ||
712 | function Trim | |
4e45e7a9 RD |
713 | (Source : String; |
714 | Left : Maps.Character_Set; | |
715 | Right : Maps.Character_Set) return String | |
d23b8f57 RK |
716 | is |
717 | High, Low : Integer; | |
718 | ||
719 | begin | |
720 | Low := Index (Source, Set => Left, Test => Outside, Going => Forward); | |
721 | ||
722 | -- Case where source comprises only characters in Left | |
723 | ||
724 | if Low = 0 then | |
725 | return ""; | |
726 | end if; | |
727 | ||
728 | High := | |
729 | Index (Source, Set => Right, Test => Outside, Going => Backward); | |
730 | ||
731 | -- Case where source comprises only characters in Right | |
732 | ||
733 | if High = 0 then | |
734 | return ""; | |
735 | end if; | |
736 | ||
737 | declare | |
738 | subtype Result_Type is String (1 .. High - Low + 1); | |
739 | ||
740 | begin | |
741 | return Result_Type (Source (Low .. High)); | |
742 | end; | |
743 | end Trim; | |
744 | ||
745 | procedure Trim | |
746 | (Source : in out String; | |
4e45e7a9 RD |
747 | Left : Maps.Character_Set; |
748 | Right : Maps.Character_Set; | |
749 | Justify : Alignment := Strings.Left; | |
750 | Pad : Character := Space) | |
d23b8f57 RK |
751 | is |
752 | begin | |
753 | Move (Source => Trim (Source, Left, Right), | |
754 | Target => Source, | |
755 | Justify => Justify, | |
756 | Pad => Pad); | |
757 | end Trim; | |
758 | ||
759 | end Ada.Strings.Fixed; |