A.4.3 Fixed-Length String Handling
The language-defined package Strings.Fixed provides
string-handling subprograms for fixed-length strings; that is, for values
of type Standard.String. Several of these subprograms are procedures
that modify the contents of a String that is passed as an out
or an in out parameter; each has additional parameters
to control the effect when the logical length of the result differs from
the parameter's length.
For each function that returns a String, the lower
bound of the returned value is 1.
Discussion: {
AI95-00114-01}
Most operations that yield a String are provided both as a function and
as a procedure. The functional form is possibly a more aesthetic style
but may introduce overhead due to extra copying or dynamic memory usage
in some implementations. Thus a procedural form, with an
in out
parameter so that all copying is done `in place', is also supplied.
The basic model embodied in the package is that a
fixed-length string comprises significant characters and possibly padding
(with space characters) on either or both ends. When a shorter string
is copied to a longer string, padding is inserted, and when a longer
string is copied to a shorter one, padding is stripped. The Move procedure
in Strings.Fixed, which takes a String as an out parameter, allows
the programmer to control these effects. Similar control is provided
by the string transformation procedures.
Static Semantics
The library package
Strings.Fixed has the following declaration:
with Ada.Strings.Maps;
package Ada.Strings.Fixed
is
pragma Preelaborate(Fixed);
-- "Copy" procedure for strings of possibly different lengths
procedure Move (Source :
in String;
Target :
out String;
Drop :
in Truncation := Error;
Justify :
in Alignment := Left;
Pad :
in Character := Space);
-- Search subprograms
{
AI95-00301-01}
function Index (Source :
in String;
Pattern :
in String;
From :
in Positive;
Going :
in Direction := Forward;
Mapping :
in Maps.Character_Mapping := Maps.Identity)
return Natural;
{
AI95-00301-01}
function Index (Source :
in String;
Pattern :
in String;
From :
in Positive;
Going :
in Direction := Forward;
Mapping :
in Maps.Character_Mapping_Function)
return Natural;
function Index (Source :
in String;
Pattern :
in String;
Going :
in Direction := Forward;
Mapping :
in Maps.Character_Mapping
:= Maps.Identity)
return Natural;
function Index (Source :
in String;
Pattern :
in String;
Going :
in Direction := Forward;
Mapping :
in Maps.Character_Mapping_Function)
return Natural;
{
AI95-00301-01}
function Index (Source :
in String;
Set :
in Maps.Character_Set;
From :
in Positive;
Test :
in Membership := Inside;
Going :
in Direction := Forward)
return Natural;
function Index (Source :
in String;
Set :
in Maps.Character_Set;
Test :
in Membership := Inside;
Going :
in Direction := Forward)
return Natural;
{
AI95-00301-01}
function Index_Non_Blank (Source :
in String;
From :
in Positive;
Going :
in Direction := Forward)
return Natural;
function Index_Non_Blank (Source :
in String;
Going :
in Direction := Forward)
return Natural;
function Count (Source :
in String;
Pattern :
in String;
Mapping :
in Maps.Character_Mapping
:= Maps.Identity)
return Natural;
function Count (Source :
in String;
Pattern :
in String;
Mapping :
in Maps.Character_Mapping_Function)
return Natural;
function Count (Source :
in String;
Set :
in Maps.Character_Set)
return Natural;
{
AI05-0031-1}
procedure Find_Token (Source :
in String;
Set :
in Maps.Character_Set;
From :
in Positive;
Test :
in Membership;
First :
out Positive;
Last :
out Natural);
procedure Find_Token (Source :
in String;
Set :
in Maps.Character_Set;
Test :
in Membership;
First :
out Positive;
Last :
out Natural);
-- String translation subprograms
function Translate (Source :
in String;
Mapping :
in Maps.Character_Mapping)
return String;
procedure Translate (Source :
in out String;
Mapping :
in Maps.Character_Mapping);
function Translate (Source :
in String;
Mapping :
in Maps.Character_Mapping_Function)
return String;
procedure Translate (Source :
in out String;
Mapping :
in Maps.Character_Mapping_Function);
-- String transformation subprograms
function Replace_Slice (Source :
in String;
Low :
in Positive;
High :
in Natural;
By :
in String)
return String;
procedure Replace_Slice (Source :
in out String;
Low :
in Positive;
High :
in Natural;
By :
in String;
Drop :
in Truncation := Error;
Justify :
in Alignment := Left;
Pad :
in Character := Space);
function Insert (Source :
in String;
Before :
in Positive;
New_Item :
in String)
return String;
procedure Insert (Source :
in out String;
Before :
in Positive;
New_Item :
in String;
Drop :
in Truncation := Error);
function Overwrite (Source :
in String;
Position :
in Positive;
New_Item :
in String)
return String;
procedure Overwrite (Source :
in out String;
Position :
in Positive;
New_Item :
in String;
Drop :
in Truncation := Right);
function Delete (Source :
in String;
From :
in Positive;
Through :
in Natural)
return String;
procedure Delete (Source :
in out String;
From :
in Positive;
Through :
in Natural;
Justify :
in Alignment := Left;
Pad :
in Character := Space);
--
String selector subprograms
function Trim (Source :
in String;
Side :
in Trim_End)
return String;
procedure Trim (Source :
in out String;
Side :
in Trim_End;
Justify :
in Alignment := Left;
Pad :
in Character := Space);
function Trim (Source :
in String;
Left :
in Maps.Character_Set;
Right :
in Maps.Character_Set)
return String;
procedure Trim (Source :
in out String;
Left :
in Maps.Character_Set;
Right :
in Maps.Character_Set;
Justify :
in Alignment := Strings.Left;
Pad :
in Character := Space);
function Head (Source :
in String;
Count :
in Natural;
Pad :
in Character := Space)
return String;
procedure Head (Source :
in out String;
Count :
in Natural;
Justify :
in Alignment := Left;
Pad :
in Character := Space);
function Tail (Source :
in String;
Count :
in Natural;
Pad :
in Character := Space)
return String;
procedure Tail (Source :
in out String;
Count :
in Natural;
Justify :
in Alignment := Left;
Pad :
in Character := Space);
--String constructor functions
function "*" (Left : in Natural;
Right : in Character) return String;
function "*" (Left : in Natural;
Right : in String) return String;
end Ada.Strings.Fixed;
The effects of the above subprograms are as follows.
procedure Move (Source : in String;
Target : out String;
Drop : in Truncation := Error;
Justify : in Alignment := Left;
Pad : in Character := Space);
{
AI05-0264-1}
The Move procedure copies characters from Source to Target. If Source
has the same length as Target, then the effect is to assign Source to
Target. If Source is shorter than Target, then:
If Justify=Left, then Source is copied
into the first Source'Length characters of Target.
If Justify=Right, then Source is copied
into the last Source'Length characters of Target.
If Justify=Center, then Source is copied
into the middle Source'Length characters of Target. In this case, if
the difference in length between Target and Source is odd, then the extra
Pad character is on the right.
Pad is copied to each Target character
not otherwise assigned.
If Source is longer than Target, then the effect
is based on Drop.
If Drop=Left, then the rightmost Target'Length
characters of Source are copied into Target.
If Drop=Right, then the leftmost Target'Length
characters of Source are copied into Target.
If Drop=Error,
then the effect depends on the value of the Justify parameter and also
on whether any characters in Source other than Pad would fail to be copied:
If Justify=Left, and if each of
the rightmost Source'Length-Target'Length characters in Source is Pad,
then the leftmost Target'Length characters of Source are copied to Target.
If Justify=Right, and if each of
the leftmost Source'Length-Target'Length characters in Source is Pad,
then the rightmost Target'Length characters of Source are copied to Target.
Otherwise,
Length_Error is propagated.
Ramification: The Move procedure will
work even if Source and Target overlap.
Reason: The order of parameters (Source
before Target) corresponds to the order in COBOL's MOVE verb.
function Index (Source : in String;
Pattern : in String;
From : in Positive;
Going : in Direction := Forward;
Mapping : in Maps.Character_Mapping := Maps.Identity)
return Natural;
function Index (Source : in String;
Pattern : in String;
From : in Positive;
Going : in Direction := Forward;
Mapping : in Maps.Character_Mapping_Function)
return Natural;
{
AI95-00301-01}
{
AI05-0056-1}
Each Index function searches, starting from From, for a slice of Source,
with length Pattern'Length, that matches Pattern with respect to Mapping;
the parameter Going indicates the direction of the lookup. If Source
is the null string, Index returns 0; otherwise, if From is not in Source'Range,
then Index_Error is propagated. If Going = Forward, then Index returns
the smallest index I which is greater than or equal to From such that
the slice of Source starting at I matches Pattern. If Going = Backward,
then Index returns the largest index I such that the slice of Source
starting at I matches Pattern and has an upper bound less than or equal
to From. If there is no such slice, then 0 is returned. If Pattern is
the null string, then Pattern_Error is propagated.
Discussion: There is no default parameter
for From; the default value would need to depend on other parameters
(the bounds of Source and the direction Going). It is better to use overloaded
functions rather than a special value to represent the default.
There is no default value for the Mapping parameter
that is a Character_Mapping_Function; if there were, a call would be
ambiguous since there is also a default for the Mapping parameter that
is a Character_Mapping.
{
AI05-0056-1}
The language does not define when the Pattern_Error check is made. (That's
because many common searching implementations require a nonempty pattern)
That means that the result for a call like
Index ("", "")
could be 0 or could raise Pattern_Error. Similarly, in the call
Index
("", "", From => 2), the language does not
define whether Pattern_Error or Index_Error is raised.
function Index (Source : in String;
Pattern : in String;
Going : in Direction := Forward;
Mapping : in Maps.Character_Mapping
:= Maps.Identity)
return Natural;
function Index (Source : in String;
Pattern : in String;
Going : in Direction := Forward;
Mapping : in Maps.Character_Mapping_Function)
return Natural;
Index (Source, Pattern, Source'First, Forward, Mapping);
Index (Source, Pattern, Source'Last, Backward, Mapping);
This paragraph
was deleted.There is no default value for the Mapping parameter
that is a Character_Mapping_Function; if there were, a call would be
ambiguous since there is also a default for the Mapping parameter that
is a Character_Mapping.
function Index (Source : in String;
Set : in Maps.Character_Set;
From : in Positive;
Test : in Membership := Inside;
Going : in Direction := Forward)
return Natural;
{
AI95-00301-01}
{
AI05-0056-1}
Index searches for the first or last occurrence of any of a set of characters
(when Test=Inside), or any of the complement of a set of characters (when
Test=Outside). If Source is the null string, Index returns 0; otherwise,
if From is not in Source'Range, then Index_Error is propagated. Otherwise,
it returns the smallest index I >= From (if Going=Forward) or the
largest index I <= From (if Going=Backward) such that Source(I) satisfies
the Test condition with respect to Set; it returns 0 if there is no such
Character in Source.
function Index (Source : in String;
Set : in Maps.Character_Set;
Test : in Membership := Inside;
Going : in Direction := Forward)
return Natural;
Index (Source, Set, Source'First, Test, Forward);
Index (Source, Set, Source'Last, Test, Backward);
function Index_Non_Blank (Source : in String;
From : in Positive;
Going : in Direction := Forward)
return Natural;
{
AI95-00301-01}
Returns Index (Source, Maps.To_Set(Space), From, Outside, Going);
function Index_Non_Blank (Source : in String;
Going : in Direction := Forward)
return Natural;
Returns Index(Source,
Maps.To_Set(Space), Outside, Going)
function Count (Source : in String;
Pattern : in String;
Mapping : in Maps.Character_Mapping
:= Maps.Identity)
return Natural;
function Count (Source : in String;
Pattern : in String;
Mapping : in Maps.Character_Mapping_Function)
return Natural;
Returns the maximum
number of nonoverlapping slices of Source that match Pattern with respect
to Mapping. If Pattern is the null string then Pattern_Error is propagated.
Reason: We say `maximum number' because
it is possible to slice a source string in different ways yielding different
numbers of matches. For example if Source is "ABABABA" and
Pattern is "ABA", then Count yields 2, although there is a
partitioning of Source that yields just 1 match, for the middle slice.
Saying `maximum number' is equivalent to saying that the pattern match
starts either at the low index or the high index position.
function Count (Source : in String;
Set : in Maps.Character_Set)
return Natural;
Returns the number
of occurrences in Source of characters that are in Set.
procedure Find_Token (Source : in String;
Set : in Maps.Character_Set;
From : in Positive;
Test : in Membership;
First : out Positive;
Last : out Natural);
{
AI05-0031-1}
If Source is not the null string and From is not in Source'Range, then
Index_Error is raised. Otherwise, First is set to the index of the first
character in Source(From .. Source'Last) that satisfies the Test condition.
Last is set to the largest index such that all characters in Source(First
.. Last) satisfy the Test condition. If no characters in Source(From
.. Source'Last) satisfy the Test condition, First is set to From, and
Last is set to 0.
procedure Find_Token (Source : in String;
Set : in Maps.Character_Set;
Test : in Membership;
First : out Positive;
Last : out Natural);
Ramification: {
AI05-0031-1}
If Source'First is not in Positive, which can only happen for an empty
string, this will raise Constraint_Error.
function Translate (Source : in String;
Mapping : in Maps.Character_Mapping)
return String;
function Translate (Source : in String;
Mapping : in Maps.Character_Mapping_Function)
return String;
Returns the string
S whose length is Source'Length and such that S(I) is the character to
which Mapping maps the corresponding element of Source, for I in 1..Source'Length.
procedure Translate (Source : in out String;
Mapping : in Maps.Character_Mapping);
procedure Translate (Source : in out String;
Mapping : in Maps.Character_Mapping_Function);
Equivalent to Source
:= Translate(Source, Mapping).
function Replace_Slice (Source : in String;
Low : in Positive;
High : in Natural;
By : in String)
return String;
{
8652/0049}
{
AI95-00128-01}
If Low > Source'Last+1, or High < Source'First–1, then Index_Error
is propagated. Otherwise:
{
8652/0049}
{
AI95-00128-01}
If High >= Low, then the returned string comprises Source(Source'First..Low–1)
& By & Source(High+1..Source'Last), but with lower bound 1.
{
8652/0049}
{
AI95-00128-01}
If High < Low, then the returned string is Insert(Source, Before=>Low,
New_Item=>By).
procedure Replace_Slice (Source : in out String;
Low : in Positive;
High : in Natural;
By : in String;
Drop : in Truncation := Error;
Justify : in Alignment := Left;
Pad : in Character := Space);
Equivalent to Move(Replace_Slice(Source,
Low, High, By), Source, Drop, Justify, Pad).
function Insert (Source : in String;
Before : in Positive;
New_Item : in String)
return String;
{
AI05-0264-1}
Propagates Index_Error if Before is not in Source'First .. Source'Last+1;
otherwise, returns Source(Source'First..Before–1) & New_Item
& Source(Before..Source'Last), but with lower bound 1.
procedure Insert (Source : in out String;
Before : in Positive;
New_Item : in String;
Drop : in Truncation := Error);
Equivalent to Move(Insert(Source,
Before, New_Item), Source, Drop).
function Overwrite (Source : in String;
Position : in Positive;
New_Item : in String)
return String;
{
AI05-0264-1}
Propagates Index_Error if Position is not in Source'First .. Source'Last+1;
otherwise, returns the string obtained from Source by consecutively replacing
characters starting at Position with corresponding characters from New_Item.
If the end of Source is reached before the characters in New_Item are
exhausted, the remaining characters from New_Item are appended to the
string.
procedure Overwrite (Source : in out String;
Position : in Positive;
New_Item : in String;
Drop : in Truncation := Right);
Equivalent to Move(Overwrite(Source,
Position, New_Item), Source, Drop).
function Delete (Source : in String;
From : in Positive;
Through : in Natural)
return String;
{
8652/0049}
{
AI95-00128-01}
{
AI05-0264-1}
If From <= Through, the returned string is Replace_Slice(Source, From,
Through, ""); otherwise, it is Source with lower bound 1.
procedure Delete (Source : in out String;
From : in Positive;
Through : in Natural;
Justify : in Alignment := Left;
Pad : in Character := Space);
Equivalent to Move(Delete(Source,
From, Through), Source, Justify => Justify, Pad => Pad).
function Trim (Source : in String;
Side : in Trim_End)
return String;
Returns the string
obtained by removing from Source all leading Space characters (if Side
= Left), all trailing Space characters (if Side = Right), or all leading
and trailing Space characters (if Side = Both).
procedure Trim (Source : in out String;
Side : in Trim_End;
Justify : in Alignment := Left;
Pad : in Character := Space);
Equivalent to Move(Trim(Source,
Side), Source, Justify=>Justify, Pad=>Pad).
function Trim (Source : in String;
Left : in Maps.Character_Set;
Right : in Maps.Character_Set)
return String;
Returns the string
obtained by removing from Source all leading characters in Left and all
trailing characters in Right.
procedure Trim (Source : in out String;
Left : in Maps.Character_Set;
Right : in Maps.Character_Set;
Justify : in Alignment := Strings.Left;
Pad : in Character := Space);
Equivalent to Move(Trim(Source,
Left, Right), Source, Justify => Justify, Pad=>Pad).
function Head (Source : in String;
Count : in Natural;
Pad : in Character := Space)
return String;
{
AI05-0264-1}
Returns a string of length Count. If Count <= Source'Length, the string
comprises the first Count characters of Source. Otherwise, its contents
are Source concatenated with Count–Source'Length Pad characters.
procedure Head (Source : in out String;
Count : in Natural;
Justify : in Alignment := Left;
Pad : in Character := Space);
Equivalent to Move(Head(Source,
Count, Pad), Source, Drop=>Error, Justify=>Justify, Pad=>Pad).
function Tail (Source : in String;
Count : in Natural;
Pad : in Character := Space)
return String;
{
AI05-0264-1}
Returns a string of length Count. If Count <= Source'Length, the string
comprises the last Count characters of Source. Otherwise, its contents
are Count-Source'Length Pad characters concatenated with Source.
procedure Tail (Source : in out String;
Count : in Natural;
Justify : in Alignment := Left;
Pad : in Character := Space);
Equivalent to Move(Tail(Source,
Count, Pad), Source, Drop=>Error, Justify=>Justify, Pad=>Pad).
function "*" (Left : in Natural;
Right : in Character) return String;
function "*" (Left : in Natural;
Right : in String) return String;
{
8652/0049}
{
AI95-00128-01}
These functions replicate a character or string a specified number of
times. The first function returns a string whose length is Left and each
of whose elements is Right. The second function returns a string whose
length is Left*Right'Length and whose value is the null string if Left
= 0 and otherwise is (Left–1)*Right & Right with lower bound
1.
12 {
AI05-0264-1}
In the Index and Count functions taking Pattern and Mapping parameters,
the actual String parameter passed to Pattern should comprise characters
occurring as target characters of the mapping. Otherwise, the pattern
will not match.
13 In the Insert subprograms, inserting
at the end of a string is obtained by passing Source'Last+1 as the Before
parameter.
14
If a null Character_Mapping_Function
is passed to any of the string handling subprograms, Constraint_Error
is propagated.
Incompatibilities With Ada 95
{
AI95-00301-01}
{
AI05-0005-1}
Overloaded versions of Index and Index_Non_Blank
are added to Strings.Fixed. If Strings.Fixed is referenced in a
use_clause,
and an entity
E with a
defining_identifier
of Index or Index_Non_Blank is defined in a package that is also referenced
in a
use_clause,
the entity
E may no longer be use-visible, resulting in errors.
This should be rare and is easily fixed if it does occur.
Wording Changes from Ada 95
{
8652/0049}
{
AI95-00128-01}
Corrigendum: Clarified that Find_Token may raise Constraint_Error
if Source'First is not in Positive (which is only possible for a null
string).
{
8652/0049}
{
AI95-00128-01}
Corrigendum: Clarified that Replace_Slice, Delete, and "*"
always return a string with lower bound 1.
Incompatibilities With Ada 2005
{
AI05-0031-1}
An overloaded version of Find_Token is added to Strings.Fixed.
If Strings.Fixed is referenced in a
use_clause,
and an entity
E with a
defining_identifier
of Find_Token is defined in a package that is also referenced in a
use_clause,
the entity
E may no longer be use-visible, resulting in errors.
This should be rare and is easily fixed if it does occur.
Wording Changes from Ada 2005
{
AI05-0056-1}
Correction: Clarified that Index never raises Index_Error if the
source string is null.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe