IMPLEMENTATION MODULE StringsLib;
(*------------------------------------------------------------------------*)
(* Stelle grundlegende Routinen zur Verarbeitung von Zeichenketten zur *)
(* Verfuegung. *)
(* Module provides basic string operations. *)
(*------------------------------------------------------------------------*)
(* Letzte Bearbeitung: *)
(* *)
(* 14.11.94, MRi: Durchsicht *)
(* 08.10.15, MRi: Erstellen der ersten Version von Centered, *)
(* LeftJustified,RightJustified,Stripped, *)
(* StripLeading,StripTrailing *)
(* 08.12.16, MRi: Hinzufuegen von RmMultBlnk *)
(* 16.01.18, MRi: Zusammenfuegen von StrUtils und StringsLib *)
(* 25.03.18, MRi: PosChar eingefuegt *)
(* 30.03.18, MRi: CapChar eingefuegt *)
(* 29.06.18, MRi: AppendChar eingefuegt *)
(* 03.07.18, MRi: SubString eingefuegt *)
(*------------------------------------------------------------------------*)
(* Ref.: Lins, Charles; "The Modula-2 software component library Vol. 1" *)
(* Springer, Berlin (1988) *)
(*------------------------------------------------------------------------*)
(* Implementation : Michael Riedl *)
(* Licence : GNU Lesser General Public License (LGPL) *)
(*------------------------------------------------------------------------*)
(* $Id: StringsLib.mod,v 1.3 2018/07/03 07:51:09 mriedl Exp mriedl $ *)
PROCEDURE Length(Str : ARRAY OF CHAR) : CARDINAL;
VAR i : CARDINAL;
BEGIN
i:=0;
WHILE (Str[i] # 0C) DO
IF (i = HIGH(Str)) THEN RETURN i+1; END;
INC(i);
END;
RETURN i;
END Length;
PROCEDURE Delete(VAR Str : ARRAY OF CHAR;
pos,anz : CARDINAL);
VAR Len,i : CARDINAL;
BEGIN
Len := Length(Str);
IF (pos < Len) THEN
IF (anz < Len - pos) THEN
i := pos + anz;
REPEAT
Str[pos] := Str[i];
INC(pos); INC(i);
UNTIL i = Len;
END;
Str[pos] := 0C;
END;
END Delete;
PROCEDURE Insert(VAR String : ARRAY OF CHAR;
SubStr : ARRAY OF CHAR;
pos : CARDINAL);
VAR i,j,len1,len2 : CARDINAL;
BEGIN
len1 := Length(String); len2 := Length(SubStr);
j := len1;
IF (j < pos) THEN pos := j; END;
DEC(j,pos);
FOR i:=j TO 0 BY -1 DO
IF (i+pos+len2 < HIGH(String)) THEN
String[i+pos+len2] := String[i+pos];
END;
END;
i:=0;
WHILE (i < len2) AND (pos + i < HIGH(String)) DO
String[pos+i] := SubStr[i];
INC(i);
END;
END Insert;
PROCEDURE SubString(VAR Quelle : ARRAY OF CHAR;
s,e : CARDINAL;
VAR SubStr : ARRAY OF CHAR);
VAR i,j : CARDINAL;
BEGIN
j:=0;
IF NOT ((e < s) OR (e > LENGTH(Quelle)) OR ((e-s+1) > HIGH(SubStr))) THEN
FOR i:=s TO e DO SubStr[j]:=Quelle[i]; INC(j); END;
END;
SubStr[j]:=0C;
END SubString;
PROCEDURE AppendChar(VAR str : ARRAY OF CHAR;
char : CHAR);
VAR l : CARDINAL;
BEGIN
l := Length(str);
IF (l+1 <= HIGH(str)) THEN
str[l] := char;
str[l+1]:=0C;
END;
END AppendChar;
PROCEDURE Append(VAR Str1 : ARRAY OF CHAR;
Str2 : ARRAY OF CHAR);
VAR i,j : CARDINAL;
BEGIN
i := Length(Str1); j:=0; (* j <= HIGH in d. n"achsten Zeile wegen Mocka *)
WHILE (i < HIGH(Str1)) AND (j <= HIGH(Str2)) AND (Str2[j] # 0C) DO
Str1[i] := Str2[j];
INC(i); INC(j);
END;
Str1[i]:=0C;
END Append;
PROCEDURE Copy(VAR Str1 : ARRAY OF CHAR;
Str2 : ARRAY OF CHAR);
VAR i : CARDINAL;
BEGIN
i:=0;
WHILE (i <= HIGH(Str2)) AND (Str2[i] # 0C) AND (i < HIGH(Str1)) DO
Str1[i]:=Str2[i]; INC(i);
END;
Str1[i]:=0C;
END Copy;
PROCEDURE Concat(VAR NStr : ARRAY OF CHAR;
Str1,Str2 : ARRAY OF CHAR);
VAR i,j : CARDINAL;
BEGIN
j:=0;
WHILE (j < HIGH(NStr)) AND (j <= HIGH(Str1)) AND (Str1[j] # 0C) DO
NStr[j] := Str1[j]; INC(j);
END;
i:=0;
LOOP
IF (j = HIGH(NStr)) THEN EXIT END;
IF (i > HIGH(Str2)) THEN EXIT END;
NStr[j] := Str2[i];
IF (Str2[i] = 0C) THEN RETURN; END;
INC(i); INC(j);
END;
NStr[j]:=0C; (* Falls Str2 nicht 0C-terminiert (Mocka) *)
END Concat;
PROCEDURE Pos(Str1,Str2 : ARRAY OF CHAR) : CARDINAL;
VAR i,j,k : CARDINAL;
BEGIN
i:=0;
LOOP
IF (i > HIGH(Str1)) OR (Str1[i] = 0C) THEN RETURN MAX(CARDINAL) END;
j:=0; k:=i;
LOOP
IF (j > HIGH(Str2)) OR (Str2[j] = 0C) THEN RETURN i END;
IF (k > HIGH(Str1)) THEN RETURN MAX(CARDINAL); END;
IF (Str1[k] # Str2[j]) THEN EXIT END;
INC(j); INC(k);
END;
INC(i);
END;
END Pos;
PROCEDURE PosChar(VAR str : ARRAY OF CHAR;
chr : CHAR;
start : CARDINAL) : CARDINAL;
VAR p : CARDINAL;
found : BOOLEAN;
BEGIN
p:=start;
LOOP
found := (str[p] # 0C) AND (p < HIGH(str));
IF NOT found THEN p:=MAX(CARDINAL); EXIT; END;
found := (str[p] = chr);
IF found THEN EXIT; END;
INC(p);
END;
RETURN p;
END PosChar;
PROCEDURE Compare (str1, str2: ARRAY OF CHAR): CompareResults;
VAR len1,len2,max,Index : CARDINAL;
BEGIN
len1 := Length(str1); len2 := Length(str2);
IF (len1 < len2) THEN max := len1; ELSE max := len2; END;
Index:=0;
WHILE (str1[Index] = str2[Index]) AND (Index < max) DO INC(Index); END;
IF (Index < max) THEN
IF (str1[Index] < str2[Index]) THEN
RETURN less;
ELSE
RETURN greater;
END;
ELSIF (len1 = len2) THEN (* Index = max *)
RETURN equal;
ELSIF (len1 < len2) THEN
RETURN less;
ELSE
RETURN greater;
END;
END Compare;
PROCEDURE Equal(str1, str2: ARRAY OF CHAR) : BOOLEAN;
VAR i,max,l1,l2 : CARDINAL;
Gleich : BOOLEAN;
BEGIN
(*
IF HIGH(str1) > HIGH(str2) THEN max:=HIGH(str1) ELSE max:=HIGH(str2) END;
*)
l1:=Length(str1); l2:=Length(str2);
IF (l1 # l2) THEN RETURN FALSE; END;
max:=l1;
i:=0;
REPEAT
Gleich := str1[i] = str2[i]; INC(i);
UNTIL NOT Gleich OR (i >= max);
RETURN Gleich;
END Equal;
PROCEDURE InsertChar( char : CHAR;
Index : CARDINAL;
len : CARDINAL;
VAR Str : ARRAY OF CHAR);
VAR ic : CARDINAL; (* InsertCount *)
Char : ARRAY [0..1] OF CHAR;
BEGIN
Char[1] := 0C;
IF (Index <= HIGH(Str)) THEN
Char[0] := char;
ic := 0;
WHILE (ic < len) DO
Insert(Str,Char,Index);
INC(ic);
END;
END;
END InsertChar;
PROCEDURE Centered(VAR Str : ARRAY OF CHAR;
Width : CARDINAL;
fuell : CHAR);
VAR lm : CARDINAL; (* leftMargin *)
rm : CARDINAL; (* rightMargin *)
Len : CARDINAL;
BEGIN
Len := Length(Str);
IF Width > Len THEN
IF (Width > HIGH(Str)) THEN
Width := HIGH(Str);
END;
lm := (Width - Len) DIV 2;
rm := Width - Len - lm;
(* Fill at the left *)
InsertChar(fuell,0,lm,Str);
(* Fill at the right *)
InsertChar(fuell,Len + lm,rm,Str);
END;
END Centered;
PROCEDURE LeftJustified(VAR Str : ARRAY OF CHAR;
Width : CARDINAL;
fuell : CHAR);
VAR index: CARDINAL; (*-- loop index over characters of the string *)
BEGIN
index := 0;
WHILE (index < HIGH(Str)) AND (Str[index] # 0C) DO
INC(index);
END;
WHILE (index < HIGH(Str)) AND (index < Width) DO
Str [index] := fuell;
INC(index);
END;
Str[index] := 0C;
END LeftJustified;
PROCEDURE RightJustified(VAR Str : ARRAY OF CHAR;
Width : CARDINAL;
fuell : CHAR);
VAR i : CARDINAL;
Len : CARDINAL;
moveWidth : CARDINAL;
BEGIN
Len := Length(Str);
IF (Len < Width) THEN
(* If given width exceeds limit of string, readjust to the limit *)
IF (HIGH(Str) < Width) THEN Width := HIGH(Str); END;
(* Calculate how many positions to added to the string *)
moveWidth := Width - Len;
(* Shift the input string right, based on given width *)
FOR i := Width TO moveWidth BY -1 DO
Str[i] := Str[i-moveWidth];
END;
(* Fill the front of the string with the given filler character *)
DEC(moveWidth);
FOR i := 0 TO moveWidth DO
Str[i] := fuell;
END;
END;
END RightJustified;
PROCEDURE Stripped(VAR Str : ARRAY OF CHAR;
char : CHAR);
VAR i,max,Index,nstrip : CARDINAL;
BEGIN
max := HIGH(Str);
i := 0;
WHILE (i <= max) AND (Str[i] # 0C) DO
IF (char = Str[i]) THEN
Index := i;
nstrip := 1;
INC(i);
WHILE (i <= max) AND (Str[i] # 0C) AND (char = Str[i]) DO
INC(nstrip);
INC(i);
END;
Delete(Str,Index,nstrip);
DEC(i, nstrip);
ELSE
INC(i);
END;
END;
END Stripped;
PROCEDURE StripLeading(VAR Str : ARRAY OF CHAR;
char : CHAR);
VAR i,max,nstrip : CARDINAL;
BEGIN
max := HIGH(Str);
i := 0;
nstrip := 0;
WHILE (i <= max) AND (Str[i] # 0C) AND (char = Str[i]) DO
INC(nstrip);
INC(i);
END;
Delete(Str,0,nstrip);
END StripLeading;
PROCEDURE StripTrailing(VAR Str : ARRAY OF CHAR;
char : CHAR);
VAR i : CARDINAL;
BEGIN
i := Length(Str);
IF (i > 0) THEN
REPEAT
DEC(i);
UNTIL (i = 0) OR (char # Str[i]);
IF (i+1 <= HIGH(Str)) THEN
Str[i+1] := 0C;
ELSE
Str[HIGH(Str)] := 0C; (* Truncating Str *)
END;
END;
END StripTrailing;
PROCEDURE RmMultBlnk(VAR Str : ARRAY OF CHAR);
VAR i,max,Index,nstrip : CARDINAL;
BEGIN
max := HIGH(Str);
i := 0;
WHILE (i <= max) AND (Str[i] # 0C) DO
IF (Str[i] = " ") THEN
Index := i;
nstrip := 1;
INC(i);
WHILE (i <= max) AND (Str[i] # 0C) AND (Str[i] = " ") DO
INC(nstrip);
INC(i);
END;
Delete(Str,Index+1,nstrip-1);
DEC(i,nstrip-1);
ELSE
INC(i);
END;
END;
END RmMultBlnk;
PROCEDURE CapStr(VAR Str : ARRAY OF CHAR);
VAR i : CARDINAL;
BEGIN
FOR i:=0 TO LENGTH(Str) DO Str[i]:=CAP(Str[i]); END;
END CapStr;
END StringsLib.