UNIT STR_STF; {**------------------------------------------------**} {** STRING Library OPERATIONS **} {** Version 1.2 **} {** Added Pos_Reverse **} {** Version 1.1 (sped-ups) **} {** (delete_duplicate_Chars_in_str) **} {** Added Int_To_Str_Zero_Fill **} {**------------------------------------------------**} {$O-,F+} INTERFACE {**************************************************************} {* Trim removes leading/trailing blanks. *} {* *} {**************************************************************} FUNCTION TRIM (Str : string) : string; FUNCTION TRIM_Leading_Only (Str : string) : string; FUNCTION TRIM_Trailing_Only (Str : string) : string; FUNCTION TRIM_Quotes (Str : string) : string; {**************************************************************} {* Right_Justify adds leading blanks. *} {* NOTE: does not handle cases when *} {* Size_To_Be < ACTUAL NUMBER OF CHARACTERS *} {**************************************************************} FUNCTION Right_Justify (Str : string; Size_To_Be : integer) : string; {***************************************************************} {* Center_Str centers the characters in the string based *} {* upon the size/midpoint specified. *} {***************************************************************} FUNCTION Center_Str (Str : string; Output_Size : integer) : string; {**************************************************************} {* Change_Case changes the case of the string to UPPER. *} {* *} {**************************************************************} FUNCTION CHANGE_CASE (Str : string) : string; FUNCTION Lower_Case (Str : string) : string; {**************************************************************} {* Int_To_Str returns the number converted into ascii chars. *} {* *} {**************************************************************} FUNCTION Int_To_Str (Num : LongInt) : string; FUNCTION Int_To_Str_Zero_Fill (Num : LongInt; Fill : byte) : string; FUNCTION Int_Num_Digits (Num : LongInt) : integer; {**************************************************************} {* Pos_Reverse returns the last occurance of the string *} {* just before the specified start pos! *} {**************************************************************} FUNCTION Pos_Reverse (Str : string; Delimiter : string; Start_At : integer) : integer; {**************************************************************} {* Find_Char returns the position of the char *} {* *} {**************************************************************} FUNCTION Find_Char (Str : string; Char_Is : char; Start_At : integer) : INTEGER; {**************************************************************} {* Delete_The_Char delete all occurances of the char *} {* *} {**************************************************************} FUNCTION Delete_The_Char (Str : string; Char_Is : char) : string; {**************************************************************} {* Replace_Str_Into inserts the small string into the *} {* org_str at the position specified *} {**************************************************************} FUNCTION Replace_Str_Into (Org_Str : String; Small_Str : string; Start, Stop : integer) : string; {**************************************************************} {* procedure Get_Word_Around_Position *} {* returns the word based AROUND the position specified *} {* Searches for blanks around the start_pos *} {* looking left then right. *} {**************************************************************} function Get_Word_Around_Position (Str : string; Start_Pos : integer; Leftmost_Char_Boundry : integer; Rightmost_Char_Boundry : integer; VAR Found_Left_Pos : integer; VAR Found_Word_Size : integer) : string; {**************************************************************} {* returns a string with duplicate chars deleted. *} {**************************************************************} function Delete_Duplicate_Chars_In_Str (Str : string; Limit_In_A_Row : byte): string; {**************************************************************} {* returns a string filled with the character specified *} {**************************************************************} function Fill_String(Len : Byte; Ch : Char) : String; {**************************************************************} {* Truncates a string to a specified length *} {**************************************************************} function Trunc_Str(TString : String; Len : Byte) : String; {**************************************************************} {* Pads a string to a specified length with a specified character } {**************************************************************} function Pad_Char(PString : String; Ch : Char; Len : Byte) : String; {**************************************************************} {* Left-justify a string within a certain width *} {**************************************************************} function Left_Justify_Str (S : String; Width : Byte) : String; {**************************************************************} {* Note that "Count" is the number of *WORDS* to fill. *} {* So e.g. you'd use *} {* "FillWord(My_Int_Array, SizeOf(My_Int_Array) DIV 2, 1);" *} {* by Neil Rubenking *} {**************************************************************} PROCEDURE FillWord (VAR Dest; Count, What : Word); {**************************************************************} {**************************************************************} {**************************************************************} IMPLEMENTATION {**************************************************************************} function Min(N1, N2 : Longint) : Longint; { Returns the smaller of two numbers } begin if N1 <= N2 then Min := N1 else Min := N2; end; { Min } (* {**************************************************************************} function Max(N1, N2 : Longint) : Longint; { Returns the larger of two numbers } begin if N1 >= N2 then Max := N1 else Max := N2; end; { Max } *) {**************************************************************} {* returns a string filled with the character specified *} {**************************************************************} function Fill_String(Len : Byte; Ch : Char) : String; var S : String; begin IF (Len > 0) THEN BEGIN S[0] := Chr(Len); FillChar(S[1], Len, Ch); Fill_String := S; END ELSE Fill_String := ''; end; { FillString } {**************************************************************} {* Truncates a string to a specified length *} {**************************************************************} function Trunc_Str(TString : String; Len : Byte) : String; begin if (Length(TString) > Len) then begin {Delete(TString, Succ(Len), Length(TString) - Len);} {Move(TString[Succ(Len)+(LENGTH(TString)-Len)], TString[Succ(Len)], Succ(Length(TString)) - Succ(Len) - Length(TString) - Len));} Move(TString[LENGTH(TString)+1], TString[Succ(Len)], 2*Len); Dec(TString[0], Length(TString) - Len); end; Str_Stf.Trunc_Str := TString; end; { TruncStr } {**************************************************************} {* Pads a string to a specified length with a specified character } {**************************************************************} function Pad_Char(PString : String; Ch : Char; Len : Byte) : String; var CurrLen : Byte; begin CurrLen := Min(Length(PString), Len); PString[0] := Chr(Len); FillChar(PString[Succ(CurrLen)], Len - CurrLen, Ch); Pad_Char := PString; end; { PadChar } {**************************************************************} {* Left-justify a string within a certain width *} {**************************************************************} function Left_Justify_Str(S : String; Width : Byte) : String; begin Left_Justify_Str := Str_Stf.Pad_Char(S, ' ', Width); end; { Left_Justify_Str } {**************************************************************} {* Trim removes leading/trailing blanks. *} {* *} {**************************************************************} FUNCTION TRIM (Str : string) : string; VAR i : integer; BEGIN i := 1; WHILE ((i < LENGTH(Str)) and (Str[i] = ' ')) DO INC(i); IF (i > 1) THEN BEGIN {Str := COPY (Str, i, Length(Str));} Move (Str[i], Str[1], Succ(LENGTH(Str))-i); DEC (Str[0], pred(i)); END; WHILE (Str[LENGTH(str)] = ' ') DO DEC (Str[0]); Trim := Str; END; {trim} {**************************************************************} {* Trim_Lead removes leading blanks. *} {* *} {**************************************************************} FUNCTION TRIM_Leading_Only (Str : string) : string; VAR i : integer; BEGIN i := 1; WHILE ((i < LENGTH(Str)) and (Str[i] = ' ')) DO INC(i); IF (i > 1) THEN BEGIN {Str := COPY (Str, i, Length(Str));} Move (Str[i], Str[1], Succ(LENGTH(Str))-i); DEC (Str[0], pred(i)); END; Trim_Leading_Only := Str; END; {trim_leading_Only} {***************************************************************} FUNCTION TRIM_Trailing_Only (Str : string) : string; BEGIN WHILE (Str[LENGTH(str)] = ' ') DO DEC (Str[0]); Trim_Trailing_Only := Str; END; {trim} {***************************************************************} {*------------------------------------------------------*} {* Trim off any lead/trail quotes! *} {*------------------------------------------------------*} FUNCTION TRIM_Quotes (Str : string) : string; begin IF ((LENGTH(Str) > 0) and (Str[1] = '"')) THEN BEGIN Move (Str[2], Str[1], pred(LENGTH(Str))); DEC (Str[0]); IF (Str[LENGTH(Str)] = '"') THEN DEC(Str[0]); END; {if} Trim_Quotes := Str; end; {Trim_Quotes} {***************************************************************} {* Right_Justify adds leading blanks. *} {* NOTE: does not handle cases when *} {* Size_To_Be < ACTUAL NUMBER OF CHARACTERS *} {***************************************************************} FUNCTION Right_Justify (Str : string; Size_To_Be : integer) : string; VAR Temp_Str : string; BEGIN Temp_Str := TRIM (Str); {to assure proper length--and NON-BLANK} Right_Justify := Str_Stf.Left_Justify_Str ('', Size_To_Be - Length(Str)) + Str; { WHILE ((LENGTH(Temp_Str) > 0) AND ( (Size_To_Be > LENGTH (Temp_Str)) OR (Temp_Str[Size_To_Be] = ' ') ) ) DO Temp_Str := ' '+ COPY (Temp_Str, 1, Size_To_Be-1); Right_Justify := Temp_Str;} END; {right_justify} {***************************************************************} {* Center_Str centers the characters in the string based *} {* upon the size/midpoint specified. *} {***************************************************************} FUNCTION Center_Str (Str : string; Output_Size : integer) : string; VAR Ret_Str : string; Size : integer; BEGIN { blank out returning string} Ret_Str := Str_Stf.Fill_String(Output_Size, ' '); {FillChar (Ret_Str, output_size, ' '); Ret_Str[0] := chr(Output_Size);} Str := TRIM (Str); Size := LENGTH (Str); IF (Output_Size <= Size) THEN Ret_Str := Str ELSE BEGIN Insert (Str, Ret_Str, (((Output_Size - Size) div 2)+1)); Ret_Str := COPY (Ret_Str, 1, OutPut_Size); END; Center_Str := Ret_Str; END; {center_str} {**************************************************************} {* Change_Case changes the case of the string to UPPER. *} {* *} {**************************************************************} FUNCTION Change_Case (Str : string) : string; var i : integer; BEGIN for i := 1 to LENGTH (Str) do Str[i] := UpCase(Str[i]); Change_Case := Str; END; {change_case} {**************************************************************} FUNCTION Lower_Case (Str : string) : string; var i : integer; BEGIN for i := 1 to LENGTH (Str) do IF ((ORD (Str[i]) >= 65) and (ORD(Str[i]) <= 90)) THEN Str[i] := CHR(ORD(Str[i])+32); Lower_Case := Str; END; {lower_case} {**************************************************************} {* Int_To_Str returns the number converted into ascii chars. *} {* *} {**************************************************************} FUNCTION Int_To_Str (Num : LongInt) : string; var Temp_Str : string; BEGIN STR(Num, Temp_Str); Int_To_Str := Temp_Str; END; {int_to_str} FUNCTION Int_To_Str_Zero_Fill (Num : LongInt; Fill : byte) : string; var Temp_Str : string; Len : byte; BEGIN STR(Num, Temp_Str); Len := LENGTH(Temp_Str); IF (Len < Fill) THEN Temp_Str := Fill_String(Fill-Len, '0')+Temp_Str; Int_To_Str_Zero_Fill := Temp_Str; END; {int_to_str_zero_fill} FUNCTION Int_Num_Digits (Num : LongInt) : integer; var Tens, Digits : Integer; BEGIN IF (Num = 0) THEN Int_Num_Digits := 1 ELSE BEGIN Tens := 1; Digits := 1; WHILE ((Num DIV Tens) <> 0) DO BEGIN INC (Digits); Tens := Tens * 10; END; {while} IF (Digits > 1) THEN DEC (Digits); Int_Num_Digits := Digits; END; {if} END; {int_num_digits} {**************************************************************} {* Pos_Reverse returns the last occurance of the string *} {* just before the specified start pos! *} {**************************************************************} FUNCTION Pos_Reverse (Str : string; Delimiter : string; Start_At : integer) : integer; VAR Temp_Str : string; Found_Pos, Found_Pos_0 : integer; BEGIN Temp_Str := COPY(Str, 1, Start_At); {dont use move since ?start_at 0) THEN BEGIN Found_Pos_0 := Found_Pos_0+Found_Pos; {Temp_Str := COPY(Temp_Str, Found_Pos+1, LENGTH(Temp_Str));} Move (Temp_Str[Found_Pos+1], Temp_Str[1], LENGTH(Str)-Found_Pos+2); DEC (Temp_Str[0], Found_Pos); END; UNTIL (Found_Pos = 0); Pos_Reverse := Found_Pos_0; END; {pos_reverse} {**************************************************************} {* Find_Char returns the position of the char *} {* *} {**************************************************************} FUNCTION Find_Char (Str : string; Char_Is : char; Start_At : integer) : INTEGER; VAR Loc : integer; BEGIN Loc := POS (Char_Is, COPY(Str, Start_At, LENGTH(STR))); IF (Loc <> 0) THEN Loc := Loc + Start_At -1; Find_Char := Loc; END; {function Find_Char} {**************************************************************} {* Delete_The_Char delete all occurances of the char *} {* *} {**************************************************************} FUNCTION Delete_The_Char (Str : string; Char_Is : char) : string; VAR Loc : integer; BEGIN Loc := 0; REPEAT Loc := POS (Char_Is, Str); IF (Loc <> 0) THEN BEGIN {DELETE (Str, Loc, 1);} Move(Str[Succ(Loc)], Str[Loc], Length(Str)-Loc); Dec(Str[0]); END; UNTIL (Loc = 0); Delete_The_Char := STR; END; {function Delete_The_Char} {**************************************************************} {* Replace_Str_Into inserts the small string into the *} {* org_str at the position specified *} {**************************************************************} FUNCTION Replace_Str_Into (Org_Str : String; Small_Str : string; Start, Stop : integer) : string; var Temp_Small_Str : string; begin IF (Start = 0) THEN Start := 1; IF (LENGTH(Small_Str) >= (Stop-Start+1)) THEN Temp_Small_Str := Small_Str ELSE Temp_Small_Str := Small_Str + Fill_String ( (Stop-Start+1-LENGTH(Small_Str)), ' '); IF (Start > 1) THEN Replace_Str_Into := Copy (Org_Str, 1, (Start -1)) + Copy (Temp_Small_Str, 1, (Stop-Start+1))+ Copy (Org_Str, (Stop+1) , LENGTH(Org_Str)) ELSE Replace_Str_Into := Copy (Temp_Small_Str, 1, (Stop-Start+1)) + Copy (Org_Str, Stop+1, LENGTH(Org_Str)); end; {Replace_Str_into} {**************************************************************} {* procedure Get_Word_Around_Position *} {* returns the word based AROUND the position specified *} {* Searches for blanks around the start_pos *} {* looking left then right. *} {**************************************************************} function Get_Word_Around_Position (Str : string; Start_Pos : integer; Leftmost_Char_Boundry : integer; Rightmost_Char_Boundry : integer; VAR Found_Left_Pos : integer; VAR Found_Word_Size : integer) : string; var adjust : integer; begin IF ((Start_Pos <= LENGTH(Str))) THEN BEGIN Get_Word_Around_Position := Str[Start_Pos]; Found_Left_Pos := Start_Pos; Found_Word_Size := 1; END ELSE {* Bad Params! *} BEGIN Get_Word_Around_Position := ' '; Found_Left_Pos := 0; Found_Word_Size := 0; Exit; END; if (Str[Start_Pos] <> ' ') then begin {************************************************} {* FIRST: find left-most position *} {************************************************} adjust := Start_Pos -1; while ((adjust >= leftmost_char_boundry) and (Str[adjust] <> ' ')) do adjust := adjust - 1; if ((adjust = leftmost_char_boundry) and (Str[adjust] <> ' ')) then Found_Left_Pos := adjust else Found_Left_Pos := adjust +1; {************************************************} {* find right-most position *} {************************************************} adjust := Start_Pos +1; while ((adjust <= Rightmost_Char_Boundry) and (Str[adjust] <> ' ')) do adjust := adjust + 1; if ((adjust = Rightmost_char_boundry) and (Str[adjust] <> ' ')) then Found_Word_Size := adjust - Found_Left_Pos +1 else Found_Word_Size := adjust - Found_Left_Pos; Get_Word_Around_Position := Copy (Str, Found_Left_Pos, Found_Word_Size); end; {if} end; {get_word_around_position} {**************************************************************} {* returns a string with duplicate chars deleted. *} {**************************************************************} function Delete_Duplicate_Chars_In_Str (Str : string; Limit_In_A_Row : byte) : string; var Curr_Pos : integer; i : integer; Same_Chars : boolean; begin IF (Limit_In_A_Row = 1) THEN {* must catch or infinite loop *} BEGIN Delete_Duplicate_Chars_In_Str := ''; exit; END; Curr_Pos := 1; WHILE ((Curr_Pos+Limit_In_A_Row-1) <= LENGTH(Str)) DO BEGIN {*---------------------------------------*} {* Quickly look for at least 2 in a row! *} {*---------------------------------------*} WHILE (((Curr_Pos+Limit_In_A_Row-1) <= LENGTH(Str)) AND (Str[Curr_Pos] <> Str[Succ(Curr_Pos)])) DO INC(Curr_Pos); IF ((Curr_Pos+Limit_In_A_Row-1) <= LENGTH(Str)) THEN BEGIN i := Curr_Pos+1; Same_Chars := TRUE; WHILE ((Same_Chars) and (i <= (Curr_Pos+Limit_In_A_Row-1))) DO IF (Str[Curr_Pos] <> Str[i]) THEN Same_Chars := FALSE ELSE INC(i); IF (Same_Chars) THEN BEGIN Move(Str[Curr_Pos+Limit_In_A_Row-1], Str[Curr_Pos], Length(Str)-(Curr_Pos+Limit_In_A_Row-2)); Dec(Str[0],Pred(Limit_In_A_Row)); END ELSE Inc(Curr_Pos); END; {if} END; {while} Delete_Duplicate_Chars_In_Str := Str; end; {delete_duplicate_chars_in_str} {* Note that "Count" is the number of *WORDS* to fill. So e.g. you'd use "FillWord(My_Int_Array, SizeOf(My_Int_Array) DIV 2, 1);" by Neil Rubenking *} {**************************************************************} PROCEDURE FillWord(VAR Dest; Count, What : Word); Assembler; ASM LES DI, Dest {ES:DI points to destination} MOV CX, Count {count in CX} MOV AX, What {word to fill with in AX} CLD {forward direction} REP STOSW {perform the fill} END; {fillWord} END. {unit str_stf}