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-2020, 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;
45 -- The language-defined package Strings.Unbounded provides a private type
46 -- Unbounded_String and a set of operations. An object of type
47 -- Unbounded_String represents a String whose low bound is 1 and whose length
48 -- can vary conceptually between 0 and Natural'Last. The subprograms for
49 -- fixed-length string handling are either overloaded directly for
50 -- Unbounded_String, or are modified as needed to reflect the flexibility in
51 -- length. Since the Unbounded_String type is private, relevant constructor
52 -- and selector operations are provided.
54 package Ada.Strings.Unbounded with
55 Initial_Condition => Length (Null_Unbounded_String) = 0
59 type Unbounded_String is private;
60 pragma Preelaborable_Initialization (Unbounded_String);
62 Null_Unbounded_String : constant Unbounded_String;
63 -- Represents the null String. If an object of type Unbounded_String is not
64 -- otherwise initialized, it will be initialized to the same value as
65 -- Null_Unbounded_String.
67 function Length (Source : Unbounded_String) return Natural with
69 -- Returns the length of the String represented by Source
71 type String_Access is access all String;
72 -- Provides a (nonprivate) access type for explicit processing of
73 -- unbounded-length strings.
75 procedure Free (X : in out String_Access);
76 -- Performs an unchecked deallocation of an object of type String_Access
78 --------------------------------------------------------
79 -- Conversion, Concatenation, and Selection Functions --
80 --------------------------------------------------------
82 function To_Unbounded_String
83 (Source : String) return Unbounded_String
85 Post => Length (To_Unbounded_String'Result) = Source'Length,
87 -- Returns an Unbounded_String that represents Source
89 function To_Unbounded_String
90 (Length : Natural) return Unbounded_String
93 Ada.Strings.Unbounded.Length (To_Unbounded_String'Result)
96 -- Returns an Unbounded_String that represents an uninitialized String
97 -- whose length is Length.
99 function To_String (Source : Unbounded_String) return String with
100 Post => To_String'Result'Length = Length (Source),
102 -- Returns the String with lower bound 1 represented by Source
104 -- To_String and To_Unbounded_String are related as follows:
106 -- * If S is a String, then To_String (To_Unbounded_String (S)) = S.
108 -- * If U is an Unbounded_String, then
109 -- To_Unbounded_String (To_String (U)) = U.
111 procedure Set_Unbounded_String
112 (Target : out Unbounded_String;
116 pragma Ada_05 (Set_Unbounded_String);
117 -- Sets Target to an Unbounded_String that represents Source
120 (Source : in out Unbounded_String;
121 New_Item : Unbounded_String)
123 Pre => Length (New_Item) <= Natural'Last - Length (Source),
124 Post => Length (Source) = Length (Source)'Old + Length (New_Item),
128 (Source : in out Unbounded_String;
131 Pre => New_Item'Length <= Natural'Last - Length (Source),
132 Post => Length (Source) = Length (Source)'Old + New_Item'Length,
136 (Source : in out Unbounded_String;
137 New_Item : Character)
139 Pre => Length (Source) < Natural'Last,
140 Post => Length (Source) = Length (Source)'Old + 1,
143 -- For each of the Append procedures, the resulting string represented by
144 -- the Source parameter is given by the concatenation of the original value
145 -- of Source and the value of New_Item.
148 (Left : Unbounded_String;
149 Right : Unbounded_String) return Unbounded_String
151 Pre => Length (Right) <= Natural'Last - Length (Left),
152 Post => Length ("&"'Result) = Length (Left) + Length (Right),
156 (Left : Unbounded_String;
157 Right : String) return Unbounded_String
159 Pre => Right'Length <= Natural'Last - Length (Left),
160 Post => Length ("&"'Result) = Length (Left) + Right'Length,
165 Right : Unbounded_String) return Unbounded_String
167 Pre => Left'Length <= Natural'Last - Length (Right),
168 Post => Length ("&"'Result) = Left'Length + Length (Right),
172 (Left : Unbounded_String;
173 Right : Character) return Unbounded_String
175 Pre => Length (Left) < Natural'Last,
176 Post => Length ("&"'Result) = Length (Left) + 1,
181 Right : Unbounded_String) return Unbounded_String
183 Pre => Length (Right) < Natural'Last,
184 Post => Length ("&"'Result) = Length (Right) + 1,
187 -- Each of the "&" functions returns an Unbounded_String obtained by
188 -- concatenating the string or character given or represented by one of the
189 -- parameters, with the string or character given or represented by the
190 -- other parameter, and applying To_Unbounded_String to the concatenation
194 (Source : Unbounded_String;
195 Index : Positive) return Character
197 Pre => Index <= Length (Source),
199 -- Returns the character at position Index in the string represented by
200 -- Source; propagates Index_Error if Index > Length (Source).
202 procedure Replace_Element
203 (Source : in out Unbounded_String;
207 Pre => Index <= Length (Source),
208 Post => Length (Source) = Length (Source)'Old,
210 -- Updates Source such that the character at position Index in the string
211 -- represented by Source is By; propagates Index_Error if
212 -- Index > Length (Source).
215 (Source : Unbounded_String;
217 High : Natural) return String
219 Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
220 Post => Slice'Result'Length = Natural'Max (0, High - Low + 1),
222 -- Returns the slice at positions Low through High in the string
223 -- represented by Source; propagates Index_Error if
224 -- Low > Length (Source) + 1 or High > Length (Source). The bounds of the
225 -- returned string are Low and High.
227 function Unbounded_Slice
228 (Source : Unbounded_String;
230 High : Natural) return Unbounded_String
232 Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
234 Length (Unbounded_Slice'Result) = Natural'Max (0, High - Low + 1),
236 pragma Ada_05 (Unbounded_Slice);
237 -- Returns the slice at positions Low through High in the string
238 -- represented by Source as an Unbounded_String. This propagates
239 -- Index_Error if Low > Length(Source) + 1 or High > Length (Source).
241 procedure Unbounded_Slice
242 (Source : Unbounded_String;
243 Target : out Unbounded_String;
247 Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
248 Post => Length (Target) = Natural'Max (0, High - Low + 1),
250 pragma Ada_05 (Unbounded_Slice);
251 -- Sets Target to the Unbounded_String representing the slice at positions
252 -- Low through High in the string represented by Source. This propagates
253 -- Index_Error if Low > Length(Source) + 1 or High > Length (Source).
256 (Left : Unbounded_String;
257 Right : Unbounded_String) return Boolean
262 (Left : Unbounded_String;
263 Right : String) return Boolean
269 Right : Unbounded_String) return Boolean
274 (Left : Unbounded_String;
275 Right : Unbounded_String) return Boolean
280 (Left : Unbounded_String;
281 Right : String) return Boolean
287 Right : Unbounded_String) return Boolean
292 (Left : Unbounded_String;
293 Right : Unbounded_String) return Boolean
298 (Left : Unbounded_String;
299 Right : String) return Boolean
305 Right : Unbounded_String) return Boolean
310 (Left : Unbounded_String;
311 Right : Unbounded_String) return Boolean
316 (Left : Unbounded_String;
317 Right : String) return Boolean
323 Right : Unbounded_String) return Boolean
328 (Left : Unbounded_String;
329 Right : Unbounded_String) return Boolean
334 (Left : Unbounded_String;
335 Right : String) return Boolean
341 Right : Unbounded_String) return Boolean
345 -- Each of the functions "=", "<", ">", "<=", and ">=" returns the same
346 -- result as the corresponding String operation applied to the String
347 -- values given or represented by Left and Right.
349 ------------------------
350 -- Search Subprograms --
351 ------------------------
354 (Source : Unbounded_String;
356 Going : Direction := Forward;
357 Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
359 Pre => Pattern'Length /= 0,
363 (Source : Unbounded_String;
365 Going : Direction := Forward;
366 Mapping : Maps.Character_Mapping_Function) return Natural
368 Pre => Pattern'Length /= 0,
372 (Source : Unbounded_String;
373 Set : Maps.Character_Set;
374 Test : Membership := Inside;
375 Going : Direction := Forward) return Natural
380 (Source : Unbounded_String;
383 Going : Direction := Forward;
384 Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
386 Pre => (if Length (Source) /= 0 then From <= Length (Source))
387 and then Pattern'Length /= 0,
389 pragma Ada_05 (Index);
392 (Source : Unbounded_String;
395 Going : Direction := Forward;
396 Mapping : Maps.Character_Mapping_Function) return Natural
398 Pre => (if Length (Source) /= 0 then From <= Length (Source))
399 and then Pattern'Length /= 0,
401 pragma Ada_05 (Index);
404 (Source : Unbounded_String;
405 Set : Maps.Character_Set;
407 Test : Membership := Inside;
408 Going : Direction := Forward) return Natural
410 Pre => (if Length (Source) /= 0 then From <= Length (Source)),
412 pragma Ada_05 (Index);
414 function Index_Non_Blank
415 (Source : Unbounded_String;
416 Going : Direction := Forward) return Natural
420 function Index_Non_Blank
421 (Source : Unbounded_String;
423 Going : Direction := Forward) return Natural
425 Pre => (if Length (Source) /= 0 then From <= Length (Source)),
427 pragma Ada_05 (Index_Non_Blank);
430 (Source : Unbounded_String;
432 Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
434 Pre => Pattern'Length /= 0,
438 (Source : Unbounded_String;
440 Mapping : Maps.Character_Mapping_Function) return Natural
442 Pre => Pattern'Length /= 0,
446 (Source : Unbounded_String;
447 Set : Maps.Character_Set) return Natural
452 (Source : Unbounded_String;
453 Set : Maps.Character_Set;
456 First : out Positive;
459 Pre => (if Length (Source) /= 0 then From <= Length (Source)),
461 pragma Ada_2012 (Find_Token);
464 (Source : Unbounded_String;
465 Set : Maps.Character_Set;
467 First : out Positive;
472 -- Each of the search subprograms (Index, Index_Non_Blank, Count,
473 -- Find_Token) has the same effect as the corresponding subprogram in
474 -- Strings.Fixed applied to the string represented by the Unbounded_String
477 ------------------------------------
478 -- String Translation Subprograms --
479 ------------------------------------
482 (Source : Unbounded_String;
483 Mapping : Maps.Character_Mapping) return Unbounded_String
485 Post => Length (Translate'Result) = Length (Source),
489 (Source : in out Unbounded_String;
490 Mapping : Maps.Character_Mapping)
492 Post => Length (Source) = Length (Source)'Old,
496 (Source : Unbounded_String;
497 Mapping : Maps.Character_Mapping_Function) return Unbounded_String
499 Post => Length (Translate'Result) = Length (Source),
503 (Source : in out Unbounded_String;
504 Mapping : Maps.Character_Mapping_Function)
506 Post => Length (Source) = Length (Source)'Old,
509 -- The Translate function has an analogous effect to the corresponding
510 -- subprogram in Strings.Fixed. The translation is applied to the string
511 -- represented by the Unbounded_String parameter, and the result is
512 -- converted (via To_Unbounded_String) to an Unbounded_String.
514 ---------------------------------------
515 -- String Transformation Subprograms --
516 ---------------------------------------
518 function Replace_Slice
519 (Source : Unbounded_String;
522 By : String) return Unbounded_String
525 Low - 1 <= Length (Source)
526 and then (if High >= Low
528 <= Natural'Last - By'Length
529 - Natural'Max (Length (Source) - High, 0)
530 else Length (Source) <= Natural'Last - By'Length),
533 Length (Replace_Slice'Result)
534 = Low - 1 + By'Length + Natural'Max (Length (Source)'Old - High, 0),
536 Length (Replace_Slice'Result) = Length (Source)'Old + By'Length),
539 procedure Replace_Slice
540 (Source : in out Unbounded_String;
546 Low - 1 <= Length (Source)
547 and then (if High >= Low
549 <= Natural'Last - By'Length
550 - Natural'Max (Length (Source) - High, 0)
551 else Length (Source) <= Natural'Last - By'Length),
555 = Low - 1 + By'Length + Natural'Max (Length (Source)'Old - High, 0),
557 Length (Source) = Length (Source)'Old + By'Length),
561 (Source : Unbounded_String;
563 New_Item : String) return Unbounded_String
565 Pre => Before - 1 <= Length (Source)
566 and then New_Item'Length <= Natural'Last - Length (Source),
567 Post => Length (Insert'Result) = Length (Source) + New_Item'Length,
571 (Source : in out Unbounded_String;
575 Pre => Before - 1 <= Length (Source)
576 and then New_Item'Length <= Natural'Last - Length (Source),
577 Post => Length (Source) = Length (Source)'Old + New_Item'Length,
581 (Source : Unbounded_String;
583 New_Item : String) return Unbounded_String
585 Pre => Position - 1 <= Length (Source)
586 and then (if New_Item'Length /= 0
588 New_Item'Length <= Natural'Last - (Position - 1)),
590 Length (Overwrite'Result)
591 = Natural'Max (Length (Source), Position - 1 + New_Item'Length),
595 (Source : in out Unbounded_String;
599 Pre => Position - 1 <= Length (Source)
600 and then (if New_Item'Length /= 0
602 New_Item'Length <= Natural'Last - (Position - 1)),
605 = Natural'Max (Length (Source)'Old, Position - 1 + New_Item'Length),
610 (Source : Unbounded_String;
612 Through : Natural) return Unbounded_String
614 Pre => (if Through <= From then From - 1 <= Length (Source)),
617 Length (Delete'Result) = Length (Source) - (Through - From + 1),
619 Length (Delete'Result) = Length (Source)),
623 (Source : in out Unbounded_String;
627 Pre => (if Through <= From then From - 1 <= Length (Source)),
630 Length (Source) = Length (Source)'Old - (Through - From + 1),
632 Length (Source) = Length (Source)'Old),
636 (Source : Unbounded_String;
637 Side : Trim_End) return Unbounded_String
639 Post => Length (Trim'Result) <= Length (Source),
643 (Source : in out Unbounded_String;
646 Post => Length (Source) <= Length (Source)'Old,
650 (Source : Unbounded_String;
651 Left : Maps.Character_Set;
652 Right : Maps.Character_Set) return Unbounded_String
654 Post => Length (Trim'Result) <= Length (Source),
658 (Source : in out Unbounded_String;
659 Left : Maps.Character_Set;
660 Right : Maps.Character_Set)
662 Post => Length (Source) <= Length (Source)'Old,
666 (Source : Unbounded_String;
668 Pad : Character := Space) return Unbounded_String
670 Post => Length (Head'Result) = Count,
674 (Source : in out Unbounded_String;
676 Pad : Character := Space)
678 Post => Length (Source) = Count,
682 (Source : Unbounded_String;
684 Pad : Character := Space) return Unbounded_String
686 Post => Length (Tail'Result) = Count,
690 (Source : in out Unbounded_String;
692 Pad : Character := Space)
694 Post => Length (Source) = Count,
699 Right : Character) return Unbounded_String
701 Pre => Left <= Natural'Last,
702 Post => Length ("*"'Result) = Left,
707 Right : String) return Unbounded_String
709 Pre => (if Left /= 0 then Right'Length <= Natural'Last / Left),
710 Post => Length ("*"'Result) = Left * Right'Length,
715 Right : Unbounded_String) return Unbounded_String
717 Pre => (if Left /= 0 then Length (Right) <= Natural'Last / Left),
718 Post => Length ("*"'Result) = Left * Length (Right),
721 -- Each of the transformation functions (Replace_Slice, Insert, Overwrite,
722 -- Delete), selector functions (Trim, Head, Tail), and constructor
723 -- functions ("*") is likewise analogous to its corresponding subprogram in
724 -- Strings.Fixed. For each of the subprograms, the corresponding
725 -- fixed-length string subprogram is applied to the string represented by
726 -- the Unbounded_String parameter, and To_Unbounded_String is applied the
729 -- For each of the procedures Translate, Replace_Slice, Insert, Overwrite,
730 -- Delete, Trim, Head, and Tail, the resulting string represented by the
731 -- Source parameter is given by the corresponding function for fixed-length
732 -- strings applied to the string represented by Source's original value.
735 pragma Inline (Length);
737 package AF renames Ada.Finalization;
739 Null_String : aliased String := "";
741 function To_Unbounded (S : String) return Unbounded_String
742 renames To_Unbounded_String;
744 type Unbounded_String is new AF.Controlled with record
745 Reference : String_Access := Null_String'Access;
748 -- The Unbounded_String is using a buffered implementation to increase
749 -- speed of the Append/Delete/Insert procedures. The Reference string
750 -- pointer above contains the current string value and extra room at the
751 -- end to be used by the next Append routine. Last is the index of the
752 -- string ending character. So the current string value is really
753 -- Reference (1 .. Last).
755 pragma Stream_Convert (Unbounded_String, To_Unbounded, To_String);
756 -- Provide stream routines without dragging in Ada.Streams
758 pragma Finalize_Storage_Only (Unbounded_String);
759 -- Finalization is required only for freeing storage
761 procedure Initialize (Object : in out Unbounded_String);
762 procedure Adjust (Object : in out Unbounded_String);
763 procedure Finalize (Object : in out Unbounded_String);
765 procedure Realloc_For_Chunk
766 (Source : in out Unbounded_String;
767 Chunk_Size : Natural);
768 pragma Inline (Realloc_For_Chunk);
769 -- Adjust the size allocated for the string. Add at least Chunk_Size so it
770 -- is safe to add a string of this size at the end of the current content.
771 -- The real size allocated for the string is Chunk_Size + x of the current
772 -- string size. This buffered handling makes the Append unbounded string
773 -- routines very fast. This spec is in the private part so that it can be
774 -- accessed from children (e.g. from Unbounded.Text_IO).
776 Null_Unbounded_String : constant Unbounded_String :=
778 Reference => Null_String'Access,
780 end Ada.Strings.Unbounded;