1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- A D A . S T R I N G S . U N B O U N D E D --
9 -- Copyright (C) 1992-2023, Free Software Foundation, Inc. --
11 -- This specification is derived from the Ada Reference Manual for use with --
12 -- GNAT. The copyright notice above, and the license provisions that follow --
13 -- apply solely to the contents of the part following the private keyword. --
15 -- GNAT is free software; you can redistribute it and/or modify it under --
16 -- terms of the GNU General Public License as published by the Free Soft- --
17 -- ware Foundation; either version 3, or (at your option) any later ver- --
18 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
19 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
20 -- or FITNESS FOR A PARTICULAR PURPOSE. --
22 -- As a special exception under Section 7 of GPL version 3, you are granted --
23 -- additional permissions described in the GCC Runtime Library Exception, --
24 -- version 3.1, as published by the Free Software Foundation. --
26 -- You should have received a copy of the GNU General Public License and --
27 -- a copy of the GCC Runtime Library Exception along with this program; --
28 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
29 -- <http://www.gnu.org/licenses/>. --
31 -- GNAT was originally developed by the GNAT team at New York University. --
32 -- Extensive contributions were provided by Ada Core Technologies Inc. --
34 ------------------------------------------------------------------------------
36 -- Preconditions in this unit are meant for analysis only, not for run-time
37 -- checking, so that the expected exceptions are raised. This is enforced by
38 -- setting the corresponding assertion policy to Ignore.
40 pragma Assertion_Policy
(Pre
=> Ignore
);
42 with Ada
.Strings
.Maps
;
43 with Ada
.Finalization
;
44 private with Ada
.Strings
.Text_Buffers
;
46 -- The language-defined package Strings.Unbounded provides a private type
47 -- Unbounded_String and a set of operations. An object of type
48 -- Unbounded_String represents a String whose low bound is 1 and whose length
49 -- can vary conceptually between 0 and Natural'Last. The subprograms for
50 -- fixed-length string handling are either overloaded directly for
51 -- Unbounded_String, or are modified as needed to reflect the flexibility in
52 -- length. Since the Unbounded_String type is private, relevant constructor
53 -- and selector operations are provided.
55 package Ada
.Strings
.Unbounded
with
57 Initial_Condition
=> Length
(Null_Unbounded_String
) = 0
60 pragma Annotate
(GNATprove
, Always_Return
, Unbounded
);
62 type Unbounded_String
is private with
63 Default_Initial_Condition
=> Length
(Unbounded_String
) = 0;
64 pragma Preelaborable_Initialization
(Unbounded_String
);
66 Null_Unbounded_String
: constant Unbounded_String
;
67 -- Represents the null String. If an object of type Unbounded_String is not
68 -- otherwise initialized, it will be initialized to the same value as
69 -- Null_Unbounded_String.
71 function Length
(Source
: Unbounded_String
) return Natural with
73 -- Returns the length of the String represented by Source
75 type String_Access
is access all String;
76 -- Provides a (nonprivate) access type for explicit processing of
77 -- unbounded-length strings.
79 procedure Free
(X
: in out String_Access
) with SPARK_Mode
=> Off
;
80 -- Performs an unchecked deallocation of an object of type String_Access
82 --------------------------------------------------------
83 -- Conversion, Concatenation, and Selection Functions --
84 --------------------------------------------------------
86 function To_Unbounded_String
87 (Source
: String) return Unbounded_String
89 Post
=> Length
(To_Unbounded_String
'Result) = Source
'Length,
91 -- Returns an Unbounded_String that represents Source
93 function To_Unbounded_String
94 (Length
: Natural) return Unbounded_String
97 Ada
.Strings
.Unbounded
.Length
(To_Unbounded_String
'Result) = Length
,
99 -- Returns an Unbounded_String that represents an uninitialized String
100 -- whose length is Length.
102 function To_String
(Source
: Unbounded_String
) return String with
103 Post
=> To_String
'Result'Length = Length (Source),
105 -- Returns the String with lower bound 1 represented by Source
107 -- To_String and To_Unbounded_String are related as follows:
109 -- * If S is a String, then To_String (To_Unbounded_String (S)) = S.
111 -- * If U is an Unbounded_String, then
112 -- To_Unbounded_String (To_String (U)) = U.
114 procedure Set_Unbounded_String
115 (Target : out Unbounded_String;
119 pragma Ada_05 (Set_Unbounded_String);
120 -- Sets Target to an Unbounded_String that represents Source
123 (Source : in out Unbounded_String;
124 New_Item : Unbounded_String)
126 Pre => Length (New_Item) <= Natural'Last - Length (Source),
127 Post => Length (Source) = Length (Source)'Old + Length (New_Item),
131 (Source : in out Unbounded_String;
134 Pre => New_Item'Length <= Natural'Last - Length (Source),
135 Post => Length (Source) = Length (Source)'Old + New_Item'Length,
139 (Source : in out Unbounded_String;
140 New_Item : Character)
142 Pre => Length (Source) < Natural'Last,
143 Post => Length (Source) = Length (Source)'Old + 1,
146 -- For each of the Append procedures, the resulting string represented by
147 -- the Source parameter is given by the concatenation of the original value
148 -- of Source and the value of New_Item.
151 (Left : Unbounded_String;
152 Right : Unbounded_String) return Unbounded_String
154 Pre => Length (Right) <= Natural'Last - Length (Left),
155 Post => Length ("&"'Result
) = Length
(Left
) + Length
(Right
),
159 (Left
: Unbounded_String
;
160 Right
: String) return Unbounded_String
162 Pre
=> Right
'Length <= Natural'Last - Length
(Left
),
163 Post
=> Length
("&"'Result) = Length (Left) + Right'Length,
168 Right : Unbounded_String) return Unbounded_String
170 Pre => Left'Length <= Natural'Last - Length (Right),
171 Post => Length ("&"'Result
) = Left
'Length + Length
(Right
),
175 (Left
: Unbounded_String
;
176 Right
: Character) return Unbounded_String
178 Pre
=> Length
(Left
) < Natural'Last,
179 Post
=> Length
("&"'Result) = Length (Left) + 1,
184 Right : Unbounded_String) return Unbounded_String
186 Pre => Length (Right) < Natural'Last,
187 Post => Length ("&"'Result
) = Length
(Right
) + 1,
190 -- Each of the "&" functions returns an Unbounded_String obtained by
191 -- concatenating the string or character given or represented by one of the
192 -- parameters, with the string or character given or represented by the
193 -- other parameter, and applying To_Unbounded_String to the concatenation
197 (Source
: Unbounded_String
;
198 Index
: Positive) return Character
200 Pre
=> Index
<= Length
(Source
),
202 -- Returns the character at position Index in the string represented by
203 -- Source; propagates Index_Error if Index > Length (Source).
205 procedure Replace_Element
206 (Source
: in out Unbounded_String
;
210 Pre
=> Index
<= Length
(Source
),
211 Post
=> Length
(Source
) = Length
(Source
)'Old,
213 -- Updates Source such that the character at position Index in the string
214 -- represented by Source is By; propagates Index_Error if
215 -- Index > Length (Source).
218 (Source
: Unbounded_String
;
220 High
: Natural) return String
222 Pre
=> Low
- 1 <= Length
(Source
) and then High
<= Length
(Source
),
223 Post
=> Slice
'Result'Length = Natural'Max (0, High - Low + 1),
225 -- Returns the slice at positions Low through High in the string
226 -- represented by Source; propagates Index_Error if
227 -- Low > Length (Source) + 1 or High > Length (Source). The bounds of the
228 -- returned string are Low and High.
230 function Unbounded_Slice
231 (Source : Unbounded_String;
233 High : Natural) return Unbounded_String
235 Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
237 Length (Unbounded_Slice'Result) = Natural'Max (0, High - Low + 1),
239 pragma Ada_05 (Unbounded_Slice);
240 -- Returns the slice at positions Low through High in the string
241 -- represented by Source as an Unbounded_String. This propagates
242 -- Index_Error if Low > Length(Source) + 1 or High > Length (Source).
244 procedure Unbounded_Slice
245 (Source : Unbounded_String;
246 Target : out Unbounded_String;
250 Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
251 Post => Length (Target) = Natural'Max (0, High - Low + 1),
253 pragma Ada_05 (Unbounded_Slice);
254 -- Sets Target to the Unbounded_String representing the slice at positions
255 -- Low through High in the string represented by Source. This propagates
256 -- Index_Error if Low > Length(Source) + 1 or High > Length (Source).
259 (Left : Unbounded_String;
260 Right : Unbounded_String) return Boolean
265 (Left : Unbounded_String;
266 Right : String) return Boolean
272 Right : Unbounded_String) return Boolean
277 (Left : Unbounded_String;
278 Right : Unbounded_String) return Boolean
283 (Left : Unbounded_String;
284 Right : String) return Boolean
290 Right : Unbounded_String) return Boolean
295 (Left : Unbounded_String;
296 Right : Unbounded_String) return Boolean
301 (Left : Unbounded_String;
302 Right : String) return Boolean
308 Right : Unbounded_String) return Boolean
313 (Left : Unbounded_String;
314 Right : Unbounded_String) return Boolean
319 (Left : Unbounded_String;
320 Right : String) return Boolean
326 Right : Unbounded_String) return Boolean
331 (Left : Unbounded_String;
332 Right : Unbounded_String) return Boolean
337 (Left : Unbounded_String;
338 Right : String) return Boolean
344 Right : Unbounded_String) return Boolean
348 -- Each of the functions "=", "<", ">", "<=", and ">=" returns the same
349 -- result as the corresponding String operation applied to the String
350 -- values given or represented by Left and Right.
352 ------------------------
353 -- Search Subprograms --
354 ------------------------
357 (Source : Unbounded_String;
359 Going : Direction := Forward;
360 Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
362 Pre => Pattern'Length /= 0,
366 (Source : Unbounded_String;
368 Going : Direction := Forward;
369 Mapping : Maps.Character_Mapping_Function) return Natural
371 Pre => Pattern'Length /= 0,
375 (Source : Unbounded_String;
376 Set : Maps.Character_Set;
377 Test : Membership := Inside;
378 Going : Direction := Forward) return Natural
383 (Source : Unbounded_String;
386 Going : Direction := Forward;
387 Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
389 Pre => (if Length (Source) /= 0 then From <= Length (Source))
390 and then Pattern'Length /= 0,
392 pragma Ada_05 (Index);
395 (Source : Unbounded_String;
398 Going : Direction := Forward;
399 Mapping : Maps.Character_Mapping_Function) return Natural
401 Pre => (if Length (Source) /= 0 then From <= Length (Source))
402 and then Pattern'Length /= 0,
404 pragma Ada_05 (Index);
407 (Source : Unbounded_String;
408 Set : Maps.Character_Set;
410 Test : Membership := Inside;
411 Going : Direction := Forward) return Natural
413 Pre => (if Length (Source) /= 0 then From <= Length (Source)),
415 pragma Ada_05 (Index);
417 function Index_Non_Blank
418 (Source : Unbounded_String;
419 Going : Direction := Forward) return Natural
423 function Index_Non_Blank
424 (Source : Unbounded_String;
426 Going : Direction := Forward) return Natural
428 Pre => (if Length (Source) /= 0 then From <= Length (Source)),
430 pragma Ada_05 (Index_Non_Blank);
433 (Source : Unbounded_String;
435 Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
437 Pre => Pattern'Length /= 0,
441 (Source : Unbounded_String;
443 Mapping : Maps.Character_Mapping_Function) return Natural
445 Pre => Pattern'Length /= 0,
449 (Source : Unbounded_String;
450 Set : Maps.Character_Set) return Natural
455 (Source : Unbounded_String;
456 Set : Maps.Character_Set;
459 First : out Positive;
462 Pre => (if Length (Source) /= 0 then From <= Length (Source)),
464 pragma Ada_2012 (Find_Token);
467 (Source : Unbounded_String;
468 Set : Maps.Character_Set;
470 First : out Positive;
475 -- Each of the search subprograms (Index, Index_Non_Blank, Count,
476 -- Find_Token) has the same effect as the corresponding subprogram in
477 -- Strings.Fixed applied to the string represented by the Unbounded_String
480 ------------------------------------
481 -- String Translation Subprograms --
482 ------------------------------------
485 (Source : Unbounded_String;
486 Mapping : Maps.Character_Mapping) return Unbounded_String
488 Post => Length (Translate'Result) = Length (Source),
492 (Source : in out Unbounded_String;
493 Mapping : Maps.Character_Mapping)
495 Post => Length (Source) = Length (Source)'Old,
499 (Source : Unbounded_String;
500 Mapping : Maps.Character_Mapping_Function) return Unbounded_String
502 Post => Length (Translate'Result) = Length (Source),
506 (Source : in out Unbounded_String;
507 Mapping : Maps.Character_Mapping_Function)
509 Post => Length (Source) = Length (Source)'Old,
512 -- The Translate function has an analogous effect to the corresponding
513 -- subprogram in Strings.Fixed. The translation is applied to the string
514 -- represented by the Unbounded_String parameter, and the result is
515 -- converted (via To_Unbounded_String) to an Unbounded_String.
517 ---------------------------------------
518 -- String Transformation Subprograms --
519 ---------------------------------------
521 function Replace_Slice
522 (Source : Unbounded_String;
525 By : String) return Unbounded_String
528 Low - 1 <= Length (Source)
529 and then (if High >= Low
531 <= Natural'Last - By'Length
532 - Natural'Max (Length (Source) - High, 0)
533 else Length (Source) <= Natural'Last - By'Length),
536 Length (Replace_Slice'Result)
537 = Low - 1 + By'Length + Natural'Max (Length (Source)'Old - High, 0),
539 Length (Replace_Slice'Result) = Length (Source)'Old + By'Length),
542 procedure Replace_Slice
543 (Source : in out Unbounded_String;
549 Low - 1 <= Length (Source)
550 and then (if High >= Low
552 <= Natural'Last - By'Length
553 - Natural'Max (Length (Source) - High, 0)
554 else Length (Source) <= Natural'Last - By'Length),
558 = Low - 1 + By'Length + Natural'Max (Length (Source)'Old - High, 0),
560 Length (Source) = Length (Source)'Old + By'Length),
564 (Source : Unbounded_String;
566 New_Item : String) return Unbounded_String
568 Pre => Before - 1 <= Length (Source)
569 and then New_Item'Length <= Natural'Last - Length (Source),
570 Post => Length (Insert'Result) = Length (Source) + New_Item'Length,
574 (Source : in out Unbounded_String;
578 Pre => Before - 1 <= Length (Source)
579 and then New_Item'Length <= Natural'Last - Length (Source),
580 Post => Length (Source) = Length (Source)'Old + New_Item'Length,
584 (Source : Unbounded_String;
586 New_Item : String) return Unbounded_String
588 Pre => Position - 1 <= Length (Source)
589 and then (if New_Item'Length /= 0
591 New_Item'Length <= Natural'Last - (Position - 1)),
593 Length (Overwrite'Result)
594 = Natural'Max (Length (Source), Position - 1 + New_Item'Length),
598 (Source : in out Unbounded_String;
602 Pre => Position - 1 <= Length (Source)
603 and then (if New_Item'Length /= 0
605 New_Item'Length <= Natural'Last - (Position - 1)),
608 = Natural'Max (Length (Source)'Old, Position - 1 + New_Item'Length),
613 (Source : Unbounded_String;
615 Through : Natural) return Unbounded_String
617 Pre => (if Through <= From then From - 1 <= Length (Source)),
620 Length (Delete'Result) = Length (Source) - (Through - From + 1),
622 Length (Delete'Result) = Length (Source)),
626 (Source : in out Unbounded_String;
630 Pre => (if Through <= From then From - 1 <= Length (Source)),
633 Length (Source) = Length (Source)'Old - (Through - From + 1),
635 Length (Source) = Length (Source)'Old),
639 (Source : Unbounded_String;
640 Side : Trim_End) return Unbounded_String
642 Post => Length (Trim'Result) <= Length (Source),
646 (Source : in out Unbounded_String;
649 Post => Length (Source) <= Length (Source)'Old,
653 (Source : Unbounded_String;
654 Left : Maps.Character_Set;
655 Right : Maps.Character_Set) return Unbounded_String
657 Post => Length (Trim'Result) <= Length (Source),
661 (Source : in out Unbounded_String;
662 Left : Maps.Character_Set;
663 Right : Maps.Character_Set)
665 Post => Length (Source) <= Length (Source)'Old,
669 (Source : Unbounded_String;
671 Pad : Character := Space) return Unbounded_String
673 Post => Length (Head'Result) = Count,
677 (Source : in out Unbounded_String;
679 Pad : Character := Space)
681 Post => Length (Source) = Count,
685 (Source : Unbounded_String;
687 Pad : Character := Space) return Unbounded_String
689 Post => Length (Tail'Result) = Count,
693 (Source : in out Unbounded_String;
695 Pad : Character := Space)
697 Post => Length (Source) = Count,
702 Right : Character) return Unbounded_String
704 Pre => Left <= Natural'Last,
705 Post => Length ("*"'Result
) = Left
,
710 Right
: String) return Unbounded_String
712 Pre
=> (if Left
/= 0 then Right
'Length <= Natural'Last / Left
),
713 Post
=> Length
("*"'Result) = Left * Right'Length,
718 Right : Unbounded_String) return Unbounded_String
720 Pre => (if Left /= 0 then Length (Right) <= Natural'Last / Left),
721 Post => Length ("*"'Result
) = Left
* Length
(Right
),
724 -- Each of the transformation functions (Replace_Slice, Insert, Overwrite,
725 -- Delete), selector functions (Trim, Head, Tail), and constructor
726 -- functions ("*") is likewise analogous to its corresponding subprogram in
727 -- Strings.Fixed. For each of the subprograms, the corresponding
728 -- fixed-length string subprogram is applied to the string represented by
729 -- the Unbounded_String parameter, and To_Unbounded_String is applied the
732 -- For each of the procedures Translate, Replace_Slice, Insert, Overwrite,
733 -- Delete, Trim, Head, and Tail, the resulting string represented by the
734 -- Source parameter is given by the corresponding function for fixed-length
735 -- strings applied to the string represented by Source's original value.
738 pragma SPARK_Mode
(Off
); -- Controlled types are not in SPARK
740 pragma Inline
(Length
);
742 package AF
renames Ada
.Finalization
;
744 Null_String
: aliased String := "";
746 function To_Unbounded
(S
: String) return Unbounded_String
747 renames To_Unbounded_String
;
749 type Unbounded_String
is new AF
.Controlled
with record
750 Reference
: not null String_Access
:= Null_String
'Access;
752 end record with Put_Image
=> Put_Image
;
755 (S
: in out Ada
.Strings
.Text_Buffers
.Root_Buffer_Type
'Class;
756 V
: Unbounded_String
);
758 -- The Unbounded_String is using a buffered implementation to increase
759 -- speed of the Append/Delete/Insert procedures. The Reference string
760 -- pointer above contains the current string value and extra room at the
761 -- end to be used by the next Append routine. Last is the index of the
762 -- string ending character. So the current string value is really
763 -- Reference (1 .. Last).
765 pragma Stream_Convert
(Unbounded_String
, To_Unbounded
, To_String
);
766 -- Provide stream routines without dragging in Ada.Streams
768 pragma Finalize_Storage_Only
(Unbounded_String
);
769 -- Finalization is required only for freeing storage
771 procedure Initialize
(Object
: in out Unbounded_String
);
772 procedure Adjust
(Object
: in out Unbounded_String
);
773 procedure Finalize
(Object
: in out Unbounded_String
);
775 procedure Realloc_For_Chunk
776 (Source
: in out Unbounded_String
;
777 Chunk_Size
: Natural);
778 pragma Inline
(Realloc_For_Chunk
);
779 -- Adjust the size allocated for the string. Add at least Chunk_Size so it
780 -- is safe to add a string of this size at the end of the current content.
781 -- The real size allocated for the string is Chunk_Size + x of the current
782 -- string size. This buffered handling makes the Append unbounded string
783 -- routines very fast. This spec is in the private part so that it can be
784 -- accessed from children (e.g. from Unbounded.Text_IO).
786 Null_Unbounded_String
: constant Unbounded_String
:=
788 Reference
=> Null_String
'Access,
790 end Ada
.Strings
.Unbounded
;