PACKAGE ada_string is --++ -- Creation Date: 10-MAR-1990 12:00:00.00 -- -- Author: Alan Cohn -- -- Modification History: -- -- Functional Description: -- -- This package contains Ada string and character manipulation -- functions and procedures definitions. -- ---- TYPE ASTRING( count : positive := 80) is private; ASTRING_TOO_SMALL : EXCEPTION; --------character FUNCTIONs--------------------------- --function returns True if parameter 'A'-'Z' or 'a'-'z' FUNCTION IsAlpha( c : in character) return boolean; --function returns True if parameter 0x00 to 0x1f FUNCTION IsCtrl( c : in character) return boolean; --function returns True if parameter '0'-'9' FUNCTION IsNumeric(c : in character) return boolean; --function returns True if parameter Space or Tab FUNCTION IsSpace( c : in character) return boolean; --functions returns Upper case character if 'a'..'z' --otherwise returns same character. FUNCTION ToUpper( c : in character) return character; ------------------------------------------------------------------------- ------------------------------------------------------------------------- ------------------------------------------------------------------------- ------------- FUNCTIONs/PROCEDUREs performed on ASTRING ----------------- ------------------------------------------------------------------------- ------------------------------------------------------------------------- ------------------------------------------------------------------------- -- --convert all lower case letters in an astring to upper case. PROCEDURE StrUpper( astrng : in out astring ); ------------------------------------------------------------------------- --search for small string in big string. --big must be >= small. --return the starting position 1..n or 0 if small not in big string. -- eg x := StrinStr(my_astring,"find this"); FUNCTION StrInStr( big : in astring; small : in string ) return natural; ------------------------------------------------------------------------- -- --return present character length of an astring. -- eg x := StrLen( my_astring ); FUNCTION StrLen(astrng : in astring) return natural; -------------------------------------------------------------------------- --return True if the astring contains no characters. FUNCTION StrEmpty(astrng : in astring) return Boolean; --------------------------------------------------------------------------- --initialize an astring to no characters. PROCEDURE StrInit(astrng : out astring); ----------------------------------------------------------------------------- --truncate an astring by decrement it's string_size. --eg: StrTruncate( my_astring,5); PROCEDURE StrTruncate( astrng : in out astring; truncate : in natural ); -- -- -- ------------------------------------------------------------------------- -- --THE FOLLOWING FUNCTIONS(StrStr) ARE --OVERLOADED STRING FUNCTIONS THAT RETURN A STRING OF VARIOUS SIZES. -- --return whole astring -- eg: my_string := strstr(my_astring); FUNCTION StrStr(astrng : in astring) return string ; ------------------------------------------------------------------------- -- --return part of astring starting from within the astring to end of astring. -- eg: string := strstr(my_astring,5); FUNCTION StrStr(astrng : in astring; start : in positive) return string; -- --return part of string, start and end are within astring. -- eg: my_string := StrStr(my_astring,7,10); FUNCTION StrStr(astrng : in astring; starts : in positive; ends : in positive) return string; ------------------------------------------------------------------------- -- --The following 4 FUNCTIONs are overloaded. --These PROCEDUREs initialize an astring by copying a string to it --and then setting the astring size. --An astring can be initialized to null with: -- StrCpy(my_astring,""); or StrCpy(my_astring); --examples: -- StrCpy(my_astring," date "); -- or -- my_astring := my_astring * "init it"; PROCEDURE StrCpy(astrng : out astring; strng : in string := ""); PROCEDURE StrCpy(dest : out astring; src : in astring); ----------------------------------------------------------- FUNCTION "*"(left : in astring; right : in string) return astring; FUNCTION "*"(left : in string; right : in astring) return astring; ------------------------------------------------------------------------- -- --The following 3 FUNCTIONs are overloaded. --These PROCEDUREs concatenate a string to an astring and set the --new astring size. -- eg StrCat(my_astring,"add this to my_astring"); -- or -- my_string := my_string & " add this to end of my_string." PROCEDURE StrCat(astrng : in out astring; strng : in string); ----------------------------------------------------------------- FUNCTION "&"(left : in astring; right : in string) return astring; FUNCTION "&"(left : in string; right : in astring) return astring; FUNCTION "&"(left : in astring; right : in astring) return astring; ---------------------------------------------------------------------------- --Two PROCEDUREs to insert a string into the middle of a string. --eg StrInsert( my_astring, StrLen(my_astring)," before end."); PROCEDURE StrInsert( astrng : in out astring; where : in positive; insert : in string); PROCEDURE StrInsert( astrng : in out astring; where : in positive; insert : in astring); ------------------------------------------------------------------------- --This procedure is repeatedly called to return tokens of a string. --strng is the field separator string. eg " .," --strng can only be ten characters or less long. --astrng is the astring to be tokenized. eg "Hi mom, how are you." --token is the astring returned to caller. eg "Hi", "mom", "how", "are", "you". --NOTE: -- astrng is an INPUT AND OUTPUT parameter. astrng is modified on each call. --If strng is a null string ("") then the previous token separators will be -- used. Procedures StrSepTok and StrTok share the same strng. -- -- eg first time: StrTok( " ,.?",my_astring,atoken); -- remain calls: StrTok( "",my_astring,atoken); -- PROCEDURE StrTok( strng : in string; astrng : in out astring; token : out astring); ------------------------------------------------------------------------- -- PROCEDURE StrSepTok is the opposite of strtok. It returns an -- astring token containing only the characters specified in strng. --NOTE: --strng can only be ten characters or less long. --astrng is an INPUT AND OUTPUT parameter. --astrng is modified on each call. --If strng is a null string ("") then the previous token separators will be --used. Procedures StrSepTok and StrTok share the same strng. -- PROCEDURE StrSepTok( strng : in string; astrng : in out astring; token : out astring); ------------------------------------------------------------------------- -- --FUNCTION to return a single character from an astring. -- eg char := StrGetChar( my_astring, 3); --NOTE: A null (0) character is returned if pos is greater then strng size. -- FUNCTION StrGetChar(strng : in astring; pos : in positive ) return character; ------------------------------------------------------------------------- --PROCEDURE to store a character into an astring. --If the position specified is beyond the present size of astring --then the size of astring is increased to the new size. -- eg StrPutChar( my_astring, 'x', 35); PROCEDURE StrPutChar(strng : in out astring; c : in character; pos : in positive); ------------------------------------------------------------------------- --An astring contains 3 parts: -- 1. the original space allocated for strings (count), -- 2. the active string size (string_size), -- 3. and the actual character string (the_string). -- PRIVATE type astring( count : positive := 80 ) is --default is 80 record string_size : natural := 0; --initial size is 0 the_string : string( 1..count ); --array space of count chars end record; end ada_string; --package specification ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- PACKAGE body ada_string is --++ -- Creation Date: 10-MAR-1990 12:00:00.00 -- -- Author: Alan Cohn -- -- Modification History: -- -- Functional Description: -- -- This package contains Ada string and character manipulation -- functions and procedures. -- ---- -- strtok_s1 : astring(10); --delimiters for tokens FUNCTION IsAlpha(c : in character) return boolean is BEGIN return (c in 'A'..'Z' OR c in 'a'..'z'); -- return true or false END; FUNCTION IsCtrl (c : in character) return boolean is BEGIN return (c in ascii.nul .. ascii.us); -- return true or false END; FUNCTION IsNumeric(c : in character) return boolean is BEGIN return (c in '0'..'9'); -- return true or false END; FUNCTION IsSpace(c : in character) return boolean is --blank or tab char BEGIN return ( c = ' ' or c = ascii.ht); -- return true or false END; FUNCTION ToUpper(c : in character ) return character is BEGIN if ( c in 'a'..'z') then return ( character'val( character'pos(c) - 32) ); --return uppercase char else return c; end if; END; ------------------------------------------------------------------------- --convert all astring lower case characters to upper case. -- PROCEDURE StrUpper( astrng : in out astring ) is BEGIN for X in 1..astrng.string_size loop astrng.the_string( X ) := ToUpper( astrng.the_string( X ) ); end loop; END; ------------------------------------------------------------------------ --search for string small in string big. --big must be >= small. --return the starting position 1..n or 0 if not in string. -- FUNCTION StrInStr(big : in astring; small : in string ) return natural is L : natural; BEGIN if big.string_size < small'length then --big must be >= small. return 0; --else return 0. end if; L := ( big.string_size - small'length) + 1; for x in 1..L loop --step thru big string if ( small = big.the_string(x .. small'length + x - 1 ) ) then return x; --found match end if; end loop; return 0; --not found. END; ------------------------------------------------------------------------ FUNCTION StrLen(astrng : in astring) return natural is BEGIN return astrng.string_size; -- return present size END; -------------------------------------------------------------------------- FUNCTION StrEmpty(astrng : in astring) return Boolean is BEGIN return astrng.string_size = 0; -- return true if size is 0. END; -------------------------------------------------------------------------- --initialize an astring to empty. PROCEDURE StrInit( astrng : out astring ) is BEGIN astrng.string_size := 0; END; -------------------------------------------------------------------------- --truncate a string by decrement it's string_size PROCEDURE StrTruncate( astrng : in out astring; truncate : in natural ) is BEGIN if truncate < astrng.string_size then --check for negative position astrng.string_size := astrng.string_size - truncate; else astrng.string_size := 0; --set to 0. end if; END; -------------------------------------------------------------------------- --overloaded string FUNCTIONs that return a string of various sizes. -- -- FUNCTION StrStr(astrng : in astring) return string is --return whole string BEGIN if astrng.string_size = 0 then return ""; --return null string else return astrng.the_string( 1 .. astrng.string_size ); -- return the string end if; END; ------------------------------------------------------------------------ -- --return part of string starting from specified parameter to end of string. -- FUNCTION StrStr(astrng : in astring; START : in positive) return string is BEGIN if START > astrng.string_size then --check for beyond end return ""; --return null string else return astrng.the_string( START .. astrng.string_size ); --rtn requested end if; END; ------------------------------------------------------------------------ -- --return part of string, start and end are within string. -- FUNCTION StrStr(astrng : in astring; starts : in positive; ends : in positive) return string is BEGIN if starts > ends or --do range checks starts > astrng.string_size or ends > astrng.string_size then return ""; --return null string else return astrng.the_string( starts .. ends ); --return slice end if; END; ------------------------------------------------------------------------ ------------------------------------------------------------------------ ----------------------- copy strings ----------------------------------- ------------------------------------------------------------------------ ------------------------------------------------------------------------ --this PROCEDURE initializes an astrng by coping a string to it --and sets the string size. -- default is null string PROCEDURE StrCpy(astrng : out astring; strng : in string := "") is BEGIN astrng.string_size := strng'length; --assign new size if strng'length > 0 then astrng.the_string( 1 .. strng'length ) := strng; --assign characters end if; EXCEPTION when others => RAISE ASTRING_TOO_SMALL; END; -- ------------------------------------------------------------------------ PROCEDURE StrCpy(dest : out astring; src : in astring) is BEGIN strcpy( dest, strstr( src ) ); --call with astring, string parameters EXCEPTION when others => RAISE; --something went wrong, re-raise exception END; ------------------------------------------------------------------------ --strcpy function --copy right string to left astring variable FUNCTION "*"(left : in astring; right : in string) return astring is temp : astring( count=>left.count); --build astring BEGIN temp.string_size := right'length; --set string size if right'length > 0 then temp.the_string(1 .. right'length) := right; --set actual string end if; return temp; --return astring EXCEPTION when others => RAISE ASTRING_TOO_SMALL; END; ------------------------------------------------------------------------ FUNCTION "*"(left : in string; right : in astring) return astring is BEGIN return (right * left); --use other * function EXCEPTION when others => raise; END; ------------------------------------------------------------------------ ------------------------------------------------------------------------ -- concatenate strings ------------------------------------------------------------------------ ------------------------------------------------------------------------ -- --this PROCEDURE concatenates a string to an astring and sets the --new astring size. -- PROCEDURE StrCat(astrng : in out astring; strng : in string) is BEGIN --add slice to end of first string astrng.the_string(astrng.string_size+1 .. astrng.string_size + strng'length ) := strng; astrng.string_size := astrng.string_size + strng'length; --set new size EXCEPTION when others => RAISE ASTRING_TOO_SMALL; END; ---------------------------------------------------------------- FUNCTION "&"(left : in astring; right : in string) return astring is temp : astring(count => left.count); BEGIN temp.string_size := left.string_size + right'length; --set new size --add slice to end of left string temp.the_string(1..left.string_size+right'length) :=strstr(left) & right; return temp; EXCEPTION when others => RAISE ASTRING_TOO_SMALL; END; ---------------------------------------------------------------- FUNCTION "&"(left : in string; right : in astring) return astring is temp : astring(count => right.count); --make astring with rights count BEGIN StrCpy(temp,left); --put left string into an astring return ( temp & StrStr( right ) ); --make right a string and call "&" EXCEPTION when others => RAISE ASTRING_TOO_SMALL; END; ------------------------------------------------------------------------- FUNCTION "&"(left : in astring; right : in astring) return astring is BEGIN return ( left & StrStr( right ) ); --make right a string and call & EXCEPTION when others => RAISE ASTRING_TOO_SMALL; END; ------------------------------------------------------------------------- --routine that is repeatedly called to return tokens of a string. --strng is the field separators string. eg " .," --astrng is the astring to be tokenized. eg "Hi mom, how are you." --token is the astring returned to caller. eg "Hi", "mom", "how", "are", "you". --NOTE astrng is an input AND output parameter. astrng is modified on each call. -- PROCEDURE StrTok( strng : in string; astrng : in out astring; token : out astring) is beg,ends,tmp : natural; BEGIN token.string_size := 0; --assume no token found if strng'length /= 0 then --if new separators StrCpy( strtok_s1, strng); --then use them. end if; if astrng.string_size = 0 then --if nothing to search return; --return null string end if; --find beginnning of token for x in 1..astrng.string_size loop beg := x; tmp := StrInStr(strtok_s1,"" & astrng.the_string(x) ); exit when tmp = 0; --stop when char not in list. end loop; if tmp /= 0 then --exit if only separators found. return; end if; --find end of token ends := beg; --might be one character at end tmp := 0; --or end is token separator for x in beg+1 .. astrng.string_size loop ends := x; tmp := StrInStr(strtok_s1,"" & astrng.the_string(x) ); exit when tmp >0; --stop when char not in list end loop; if tmp >0 then --backup one if found char in list ends := ends -1; end if; StrCpy( token, StrStr( astrng, beg, ends) ); --return token to user if ends < astrng.string_size then --if more string left strcpy( astrng, strstr( astrng, ends+1) ); --update old string else astrng.string_size := 0; --old string is now empty end if; END; ------------------------------------------------------------------------- -- PROCEDURE StrSepTok is the opposite of strtok; that is, it returns an -- astring token containing only the characters specified in strng. --NOTE: -- astrng is an INPUT AND OUTPUT parameter. astrng is modified on each call. --If strng is a null string ("") then the previous token separators will be -- used. StrSepTok and StrTok share the same strng. -- PROCEDURE StrSepTok( strng : in string; astrng : in out astring; token : out astring) is beg,ends,tmp : natural; BEGIN token.string_size := 0; --assume no token found if strng'length /= 0 then --check for separator list StrCpy( strtok_s1, strng ); end if; if astrng.string_size = 0 then --exit if no string return; end if; --find beginnining of token for x in 1..astrng.string_size loop beg := x; tmp := StrInStr( strtok_s1, "" & astrng.the_string(x) ); exit when tmp /= 0; end loop; if tmp = 0 then --exit if none return; end if; --find end of token ends := beg; --might be one character at end. tmp := 1; --might be one non-token at end. for x in beg+1 .. astrng.string_size loop ends := x; tmp := StrInStr( strtok_s1, "" & astrng.the_string(x) ); exit when tmp = 0; end loop; if tmp = 0 then --backup one if found separator ends := ends -1; end if; StrCpy( token, StrStr( astrng, beg, ends ) ); --return token to user if ends < astrng.string_size then --if more string left StrCpy(astrng, StrStr( astrng, ends+1 ) ); --update old string else astrng.string_size := 0; --old string is now empty end if; END; --------------------------------------------------------------------------- --FUNCTION to return a character from an astring. -- FUNCTION StrGetChar(strng : in astring; pos : in positive ) return character is BEGIN if pos > strng.string_size then return ascii.nul; --null character if no such position else return strng.the_string(pos); --return the character end if; END; ------------------------------------------------------------------------- --PROCEDURE to store a character into an astring. --if the position specified is beyond the present length of astring --the the length of astring is increased to the new length. -- PROCEDURE StrPutChar(strng : in out astring; c : in character; pos : in positive) is BEGIN strng.the_string(pos) := c; if strng.string_size < pos then --if new position increases the size then strng.string_size := pos; --set the new size. end if; EXCEPTION when others => RAISE ASTRING_TOO_SMALL; END; ----------------------------------------------------------------------------- --PROCEDUREs to insert a string into the middle of a string. PROCEDURE StrInsert( astrng : in out astring; where : in positive; insert : in string) is temp : astring(count => astrng.count); BEGIN temp.the_string(1..where-1) := astrng.the_string(1..where-1); --head is old temp.the_string(where..where+insert'length-1) := insert; --insert new temp.the_string((where+insert'length)..(insert'length+astrng.string_size)) := astrng.the_string(where..astrng.string_size); --tail is old temp.string_size := astrng.string_size + insert'length; --new size astrng := temp; EXCEPTION when others => RAISE ASTRING_TOO_SMALL; END; ----------------------------------------------------------------------------- PROCEDURE StrInsert( astrng : in out astring; where : in positive; insert : in astring) is BEGIN StrInsert( astrng, where, StrStr(insert) ); --make call with insert string END; end ada_string; ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- with ada_string; use ada_string; with text_io; with integer_text_io; PROCEDURE ADA_STRING_TEST is --++ -- Creation Date: 10-MAR-1990 12:00:00.00 -- -- Author: Alan Cohn -- -- Modification History: -- -- Functional Description: -- -- This ada procedure is used to demonstrate -- functions and procedures in the package ada_string. -- After ada_string_.ada and ada_string.ada have been -- compiled, compile this procedure (ada_string_test.ada). -- Then link this procedure with the VAX DCL command -- "ACS LINK ADA_STRING_TEST". -- To run the procedure enter "RUN ADA_STRING_TEST". -- ---- avar : astring( count => 100); avar2 : astring( count => 100); small : astring( count => 2); tstring : constant string := "Now is the time for all good" & ascii.ht & ascii.ht & "men."; loc : natural; ----------------------------------------------------------------------------- begin if StrEmpty( avar ) then --test StrEmpty text_io.put_line(" string empty test ok"); else text_io.put_line(" string empty test error"); end if; text_io.new_line(2); --test * and & text_io.put_line("Expect: PART 1 part 2 part 3. PART 1 part 2 part 3."); avar := " PART 1 " & avar * "part 2 "; -- * is higher priority avar := avar & "part 3."; avar := avar & avar; text_io.put_line( StrStr( avar ) ); --test StrUpper text_io.new_line(2); StrUpper( avar ); text_io.put_line("Next line should be upper case."); text_io.put_line( StrStr( avar ) ); text_io.new_line(2); --test setting astring to 0. StrInit( avar ); text_io.put("Length of initialized avar should be 0, it is "); integer_text_io.put( StrLen( avar ), 2 ); --integer_text_io text_io.new_line(2); if IsSpace(' ') and IsSpace(ascii.ht) then --test IsSpace text_io.put_line(" isspace test ok."); else text_io.put_line(" isspace test fail."); end if; text_io.new_line(2); StrCpy( avar2, "strcpy 2 astring test"); --assign string to astring. StrCpy( avar, avar2 ); --assign astring to another astring text_io.put_line("Next two lines should match."); text_io.put_line( StrStr( avar ) ); text_io.put_line( StrStr( avar2 ) ); text_io.new_line(2); text_io.put_line("StrTok and StrSepTok test to follow."); text_io.put_line( tstring ); StrCpy( avar, tstring ); --avar contains test string StrTok(" " & ascii.ht, avar, avar2); --separators are space and tab chars while StrLen( avar2 ) > 0 loop --avar2 contains token from call text_io.put( StrStr( avar2 ) ); --show what came back from call StrSepTok( "", avar, avar2 ); --not get token separators tabs, spaces if StrLen( avar2 ) > 0 then text_io.put( StrStr( avar2 ) ); StrTok( "", avar, avar2 ); --note the null string "" to use present end if; end loop; text_io.new_line(2); text_io.put_line("StrInsert test, add ***test*** at position 10."); StrCpy( avar, tstring ); StrInsert( avar, 10, "***test***" ); --insert with string text_io.put_line( StrStr( avar ) ); StrCpy( avar2, ">hi<" ); text_io.new_line(2); StrInsert( avar, 1, avar2 ); --add "hi" at start with astring text_io.put_line( StrStr( avar ) ); StrInsert( avar, StrLen( avar )+1, avar2 ); text_io.put_line( StrStr( avar ) ); text_io.new_line(2); BEGIN text_io.put_line("astring Exception test to follow."); --try to put a big string into a small astring variable. StrCpy( small, "bigger then small" ); text_io.put_line("astring too small -- failed"); --line should not execute EXCEPTION when astring_too_small => text_io.put_line("astring too small test ok"); END; text_io.new_line(2); strcpy(avar,tstring); loc := StrInStr(avar,"men"); --find "men" in the test string. text_io.put_line("Testing StrInStr."); text_io.put_line(tstring); text_io.put("Location of men in string is "); integer_text_io.put(loc,2); text_io.put_line("."); text_io.new_line(2); loc := StrInStr(avar,"boys"); --no find "boys" in the test string. text_io.put_line("Testing StrInStr."); text_io.put_line(tstring); text_io.put("Location of boys in string is "); integer_text_io.put(loc,2); text_io.put_line("."); text_io.new_line(2); --StrStr can be called with one, two, or three parameters. --test it with three parameters. text_io.put_line("Test StrStr with three parameters to list: time for all."); text_io.put_line("Test StrStr: " & StrStr(avar, --param1 StrInStr(avar,"time"), --param2 StrInStr(avar,"all")+2 ) );--param3 END ADA_STRING_TEST;