| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773 |
- IMPLEMENTATION MODULE strUtils;
- IMPORT InOut, Strings,MemUtils, SYSTEM ;
- CONST
- CR = 0DH;
- LF = 0AH;
-
- CONST
- less = -1;
- equal = 0;
- greater = 1;
-
- PROCEDURE Compare (stringVal1, stringVal2: ARRAY OF CHAR): INTEGER ;
- VAR
- index : CARDINAL ;
- L,L1,L2 : CARDINAL; (* length of the arrays *)
-
- BEGIN
- L1 := Strings.Length(stringVal1);
- L2 := Strings.Length(stringVal2);
- index := 0;
- (*checking the # lengths of the strings and setting L to the shortest one *)
- IF L1<L2 THEN L := L1 ELSE L := L2 END;
- (* incrementing index as long as the chararcters are equal *)
- WHILE (index < L) & (stringVal1[index] = stringVal2[index]) DO
- INC (index)
- END;
- (* testing the char just after the equal part *)
- IF (stringVal1[index] < stringVal2[index]) THEN
- RETURN less
- ELSIF (stringVal1[index] > stringVal2[index]) THEN
- RETURN greater
- ELSE
- RETURN equal
- END
- END Compare;
- PROCEDURE Copy(VAR Ns: ARRAY OF CHAR; S: ARRAY OF CHAR);
- (*
- MemCopy - copys a region of memory to the required destination.
- PROCEDURE MemCopy (from: ADDRESS; length: CARDINAL; to: ADDRESS) ;
- *)
- VAR
- H,L : CARDINAL;
-
- BEGIN
- H := HIGH(Ns)+1;
- L := Strings.Length(S);
- IF L > H THEN
- L := H
- END;
- MemUtils.MemCopy(SYSTEM.ADR(S),L,SYSTEM.ADR(Ns));
- IF L < H THEN
- Ns[L] := 0C;
- END;
- END Copy;
- PROCEDURE Assign (source: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR);
- (* several cases :
- - the strings are equal length
- - the destination is shorter
- - the destination is longer
- *)
- VAR
- index: CARDINAL ;
- L1,L2 : CARDINAL;
-
- BEGIN
- L1 := Strings.Length(source);
- L2 := HIGH(destination);
- index := 0;
- IF L2 > L1 THEN (* destination longer than source : need to put a 0C ate the end *)
- FOR index := 0 TO L1 DO
- destination[index] := source[index];
- END;
- source[index+1] := 0C;
- ELSIF L2 < L1 THEN (*we only copy what is possible *)
- FOR index := 0 TO L2 DO
- destination[index] := source[index];
- END;
- ELSE (* equal length *)
- FOR index := 0 TO L1 DO
- destination[index] := source[index];
- END;
- END;
- END Assign;
- PROCEDURE Pos (substr : CHAR ; s : ARRAY OF CHAR; n : CARDINAL ) : CARDINAL ;
- (* find th first occurence of a CHAR in the String, search beginning at the n.th Character *)
-
- VAR
- i : CARDINAL ;
- l : CARDINAL;
-
- BEGIN
- l := Strings.Length(s);
- FOR i := n + 1 TO l -1 DO
- IF s[i] = substr THEN RETURN(i) END;
- END;
- RETURN MAX(CARDINAL);
- END Pos;
- (* python like functions *)
- PROCEDURE isalnum(s : ARRAY OF CHAR) : BOOLEAN;
- (* Returns True if all characters in the string are alphanumeric*)
- VAR
- i : CARDINAL;
- l : CARDINAL;
- result : BOOLEAN;
- BEGIN
- result := TRUE;
- l := Strings.Length(s);
- FOR i := 0 TO l -1 DO
- IF Pos(s[i], alphanum,0) = MAX(CARDINAL) THEN
- result := FALSE;
- END;
- END;
- RETURN result
- END isalnum;
- PROCEDURE isalpha(s : ARRAY OF CHAR) : BOOLEAN;
- (* Returns True if all characters in the string are in the alphabet *)
- VAR
- i : CARDINAL;
- l : CARDINAL;
- result : BOOLEAN;
- BEGIN
- result := TRUE;
- l := Strings.Length(s);
- FOR i := 0 TO l -1 DO
- IF Pos(s[i], asciiLetters,0) = MAX(CARDINAL) THEN
- result := FALSE;
- END;
- END;
- RETURN result
- END isalpha;
- PROCEDURE isascii(s : ARRAY OF CHAR) : BOOLEAN;
- (* Returns True if all characters in the string are ascii characters *)
- VAR
- i : CARDINAL;
- l : CARDINAL;
- result : BOOLEAN;
- BEGIN
- result := TRUE;
- l := Strings.Length(s);
- FOR i := 0 TO l -1 DO
- IF ORD(s[i]) > 127 THEN
- result := FALSE;
- END;
- END;
- RETURN result
- END isascii;
- PROCEDURE isdigit(s : ARRAY OF CHAR) : BOOLEAN;
- (* Returns True if all characters in the string are digits *)
- VAR
- i,l : CARDINAL;
- value : CARDINAL;
- result : BOOLEAN;
- BEGIN
- result := TRUE;
- l := Strings.Length(s);
- FOR i := 0 TO l DO
- value := ORD(s[i]);
- IF (value < 48) OR (value > 58) THEN
- result := FALSE;
- END;
- END;
- RETURN result
- END isdigit;
- PROCEDURE isidentifier(s : ARRAY OF CHAR) : BOOLEAN;
- (* Returns True if the string is an identifier *)
- VAR
- i : CARDINAL;
- l : CARDINAL;
- result : BOOLEAN;
- BEGIN
- result := TRUE;
- l := Strings.Length(s);
- i := 1;
- IF Pos(s[i], asciiLetters,0) = MAX(CARDINAL) THEN
- result := FALSE;
- ELSE
- FOR i := 1 TO l DO
- IF Pos(s[i], alphanum,0) = MAX(CARDINAL) THEN
- result := FALSE;
- END;
- END;
- END;
- RETURN result
- END isidentifier;
- PROCEDURE islower(s : ARRAY OF CHAR) : BOOLEAN;
- (* eturns True if all characters in the string are lower case *)
- VAR
- i : CARDINAL;
- l : CARDINAL;
- result : BOOLEAN;
- BEGIN
- result := TRUE;
- l := Strings.Length(s);
- FOR i := 0 TO l DO
- IF Pos(s[i], asciiLowercase,0) = MAX(CARDINAL) THEN
- result := FALSE;
- END;
- END;
- RETURN result
- END islower;
- PROCEDURE isprintable(s : ARRAY OF CHAR) : BOOLEAN;
- (* Returns True if all characters in the string are printable *)
- VAR
- i : CARDINAL;
- l : CARDINAL;
- result : BOOLEAN;
- BEGIN
- result := TRUE;
- l := Strings.Length(s);
- FOR i := 0 TO l DO
- IF Pos(s[i], printable,0) = MAX(CARDINAL) THEN
- result := FALSE;
- END;
- END;
- RETURN result
- END isprintable;
- PROCEDURE isspace(s : ARRAY OF CHAR) : BOOLEAN;
- (* Returns True if all characters in the string are whitespaces *)
- VAR
- i : CARDINAL;
- l : CARDINAL;
- result : BOOLEAN;
- BEGIN
- result := TRUE;
- l := Strings.Length(s);
- FOR i := 0 TO l DO
- IF Pos(s[i], whitespace,0) = MAX(CARDINAL) THEN
- result := FALSE;
- END;
- END;
- RETURN result
- END isspace;
- PROCEDURE istitle(s : ARRAY OF CHAR) : BOOLEAN;
- (* Returns True if the string follows the rules of a title *)
- (* Check if each word start with an upper case letter:*)
- VAR
- i : CARDINAL;
- l : CARDINAL;
- result : BOOLEAN;
- BEGIN
- result := TRUE;
- (* we need to separate the string into words and test the first char of every word *)
- l := Strings.Length(s) -1;
- WHILE i <= l DO
-
- END;
- RETURN result
- END istitle;
- PROCEDURE isupper(s : ARRAY OF CHAR) : BOOLEAN;
- (* Returns True if all characters in the string are upper case *)
- VAR
- i : CARDINAL;
- l : CARDINAL;
- result : BOOLEAN;
- BEGIN
- result := TRUE;
- l := Strings.Length(s) -1 ;
- FOR i := 0 TO l DO
- IF( ORD(s[i]) < 65 ) OR (ORD(s[i]) > 90 ) THEN
- result := FALSE;
- END;
- END;
- RETURN result
- END isupper;
- (* end of python like functions *)
- PROCEDURE RemoveLeftChars (VAR s : ARRAY OF CHAR; ch : CHAR);
- BEGIN
- REPEAT
- IF s[0] = ch THEN
- Strings.Delete (s, 0, 1)
- END;
- UNTIL s[0] # ch;
- END RemoveLeftChars;
- PROCEDURE RemoveRightChars (VAR s : ARRAY OF CHAR; ch : CHAR);
- VAR
- l : INTEGER;
-
- BEGIN
- l := Strings.Length(s);
- REPEAT
- IF s[l] = ch THEN
- Strings.Delete (s, l, 1)
- END;
- DEC(l);
- UNTIL s[l] # ch;
- END RemoveRightChars;
- PROCEDURE WordCount (source : ARRAY OF CHAR; separator : CHAR) : CARDINAL ;
- (* count the number of words separated by the separator*)
- VAR
- k,l : CARDINAL ;
-
- BEGIN
- (* remove the separator from the beginning and from the end : ltrim and rtrim *)
- RemoveLeftChars(source, separator);
- RemoveRightChars (source, separator);
- k := 0;
- l := 0;
- REPEAT
- IF source[l] = separator THEN
- INC(k);
- REPEAT
- INC(l);
- UNTIL source[l] # separator;
- END;
- INC(l);
- UNTIL l = Strings.Length(source);
- INC(k);
- RETURN(k);
- END WordCount;
- PROCEDURE NumberOfChar (s : ARRAY OF CHAR; ch : CHAR) : CARDINAL ;
- (* counts the number of a given char ch in string s*)
- VAR
- n, i : CARDINAL ;
-
- BEGIN
- n := 0;
- FOR i := 0 TO Strings.Length(s) DO
- IF s[i] = ch THEN INC(n) END;
- END;
- RETURN(n);
- END NumberOfChar;
- PROCEDURE Rpos ( s : ARRAY OF CHAR ; ch : CHAR) : CARDINAL ;
- (* display the position OF e caracter ch IN a STRING s beginning FROM the right *)
- VAR
- l : CARDINAL;
-
- BEGIN
- l := Strings.Length (s);
- REPEAT
- DEC(l)
- UNTIL (s[l] = ch) OR (l = 0);
- RETURN l;
- END Rpos;
- PROCEDURE Lpos ( s : ARRAY OF CHAR ; ch : CHAR) : CARDINAL;
- (* display the position OF e caracter ch IN a STRING s beginning FROM the left *)
- VAR
- l : CARDINAL ;
- ll : CARDINAL; (* length *)
-
- BEGIN
- l := 0;
- ll := Strings.Length(s);
- REPEAT
- INC(l)
- UNTIL (s[l] = ch) OR (l = ll);
- RETURN l;
- END Lpos;
- PROCEDURE copyBytes(VAR src, dst: ARRAY OF CHAR; start, quantity: CARDINAL);
- (* copy quantity of char from source to destination, beginning at start *)
- VAR
- i, j : CARDINAL;
- L1 : CARDINAL; (*LENGTH OF the source *)
- L2 : CARDINAL; (* length of the destination*)
-
- BEGIN
- (* the lengths *)
- L1 := Strings.Length(src);
- L2 := Strings.Length(dst);
- (* iteration ;
- initialisation de i au premier caractere à copier,
- et j au début de la chaine destination*)
- i := start; j := 0;
- IF i < (L2 - 1) THEN
- REPEAT
- dst[j] := src[i];
- INC(i);
- INC(j);
- UNTIL (i = L1) OR (j = L2) OR (j = quantity);
- IF i < L2 THEN
- dst[i+1] := 0C;
- END;
- END
- END copyBytes;
- (*
- PROCEDURE appendNumChars(VAR extra: pstring; extraNum: LONGINT; VAR destination: pstring; destinationNum: LONGINT);
- VAR
- tmp: pstring;
- BEGIN
- IF extra # NIL THEN
- IF destination = NIL THEN
- NEW(destination, extraNum);
- copyBytes(extra^, destination^, 0, extraNum);
- ELSE
- NEW(tmp, extraNum + destinationNum);
- copyBytes(destination^, tmp^, 0, destinationNum);
- copyBytes(extra^, tmp^, destinationNum, extraNum);
- NEW(destination, LEN(tmp^));
- copyBytes(tmp^, destination^, 0, LEN(tmp^));
- END;
- END
- END appendNumChars;
- PROCEDURE string2pstring(s: ARRAY OF CHAR; VAR d : pstring);
- BEGIN
- NEW(d, Strings.Length(s)+1);
- Assign (s, d^);
- END string2pstring;
- PROCEDURE string2pstrings(VAR text: ARRAY OF CHAR): pstrings;
- VAR
- i, j, lineNum, start, number: INTEGER;
- pstrs: pstrings;
- pstr: pstring;
- BEGIN
- i := 0;
- j := 0;
- REPEAT
- IF text[i] = 0AH THEN INC(j) END;
- INC(i);
- UNTIL (i = LEN(text)) OR (text[i] = 0H);
- NEW(pstrs, j);
- lineNum := 0;
- number := 0;
- REPEAT
- WHILE (text[number] = 0AH) OR (text[number] = 0DH) DO INC(number) END;
- start := number;
- REPEAT
- INC(number)
- UNTIL (number = LEN(text) - 1) OR (text[number] = 0AH)
- OR (text[number] = 0DH) OR (text[number] = 0H);
- NEW(pstr, number - start + 1);
- Strings.Extract(text, start, number - start, pstr^);
- pstrs^[lineNum] := pstr;
- INC(lineNum);
- UNTIL (lineNum = j) OR (number = i);
- RETURN pstrs
- END string2pstrings;
- PROCEDURE ExtractWord (n : INTEGER; s : ARRAY OF CHAR; ch : CHAR) : pstring;
- VAR
- i, j, k, l : INTEGER;
- str : string;
- pstr : pstring;
- BEGIN
- RemoveLeftChars (s, ch);
- RemoveRightChars (s, ch);
- IF n = WordCount (s, ch) THEN
- l := Rpos (s, ch);
- Strings.Extract (s, l+1, Strings.Length(s)-l-1, str);
- string2pstring(str, pstr);
- RETURN (pstr);
- ELSIF n = 1 THEN
- l := Lpos(s, ch);
- Strings.Extract (s, 0, l, str);
- string2pstring(str, pstr);
- RETURN (pstr);
- ELSE
- j := 0;
- k := 0;
- l := 0;
- i := 0;
- REPEAT
- IF s[i] = ch THEN
- INC(j) ;
- IF j = (n-1) THEN k := i END;
- IF j = n THEN l := i END;
- END;
- INC(i);
- UNTIL i = Strings.Length(s);
- Strings.Extract(s, k+1, l-k-1, str);
- string2pstring(str, pstr);
- RETURN (pstr)
- END
- END ExtractWord;
- PROCEDURE tokenize(s : ARRAY OF CHAR; ch : CHAR) : pstrings;
- VAR
- pstr : pstring;
- pstrs : pstrings;
- l, n : INTEGER;
- BEGIN
- n := WordCount(s, ch);
- IF n # 0 THEN
- NEW (pstrs, n)
- ELSE
- pstrs := NIL;
- RETURN pstrs
- END;
- IF n = 1 THEN
- RemoveRightChars (s, ch);
- RemoveLeftChars (s, ch);
- string2pstring(s, pstrs^[0]);
- ELSE
- l := 0;
- REPEAT
- pstr := ExtractWord ( l+1, s, ch);
- pstrs^[l] := pstr;
- INC(l);
- UNTIL l = n;
- END;
- RETURN pstrs
- END tokenize;
- *)
- PROCEDURE copyAll (src : ARRAY OF CHAR ; VAR dst : ARRAY OF CHAR);
- (* copies all array, even after 0X, but puts 0X in the end *)
- VAR
- i, k : CARDINAL ;
- L1, L2 : CARDINAL;
-
- BEGIN
- L1 := HIGH(src);
- L2 := HIGH(dst);
- InOut.WriteCard(L1,5);
- InOut.WriteCard(L2,5);
- InOut.WriteLn;
- (* 3 cases :
- - the arrays are the same size
- - the source is bigger than the destination
- - the destination is bigger than the source
- *)
- IF L1 = L2 THEN
- FOR i := 0 TO L1 DO
- (* the null if present in the source is copied as it is in the destination *)
- dst[i] := src[i];
- END
- ELSIF L1< L2 THEN
- (* here we need to terminate the des with the 0C char *)
- InOut.WriteString("source plus petite que destination");
- InOut.WriteLn;
- FOR i := 0 TO L1 DO
- dst[i] := src[i]
- END;
- dst[i+1] := 0C;
- ELSE
- (* here we only copy what is possible in the destination : no need for a 0C terminal *)
- InOut.WriteString("source plus grande que destination");
- InOut.WriteLn;
- FOR i := 0 TO L2 DO
- dst[i] := src[i]
- END
- END;
- END copyAll;
- PROCEDURE zeroStr(VAR str: ARRAY OF CHAR);
- VAR
- i, j : CARDINAL ;
- BEGIN
- i := Strings.Length(str);
- FOR j := 0 TO i-1 DO
- str[j] := 0C;
- END;
- (* j := 0;
- REPEAT
- str[j] := 0H;
- INC(j)
- UNTIL j = i;*)
- END zeroStr;
- PROCEDURE appendLFCR(VAR str: ARRAY OF CHAR);
- (* what happens if the array is too small ???? *)
-
- VAR
- l : INTEGER;
- BEGIN
- l := Strings.Length(str);
- IF l <= (l - 3) THEN
- str[l] := CHR(LF);
- str[l+1] := CHR(CR);
- str[l+2] := 0C;
- END;
- END appendLFCR;
- (*
- PROCEDURE findChar(ch: CHAR; VAR line: ARRAY OF CHAR; VAR b: BOOLEAN; VAR pos: INTEGER);
- VAR
- i : INTEGER;
- BEGIN
- i := -1; pos := -1;
- b := FALSE;
- REPEAT
- INC(i);
- IF line[i] = ch THEN b := TRUE; pos := i END;
- UNTIL b OR (i = LEN(line) - 1);
- END findChar;
- PROCEDURE cutLine(VAR src, dst: ARRAY OF CHAR);
- VAR
- found: BOOLEAN;
- pos : INTEGER;
- i : INTEGER;
- BEGIN
- COPY("", dst);
- findChar(LF, src, found, pos);
- IF found THEN
- i := 0;
- REPEAT
- dst[i] := src[i];
- INC(i);
- UNTIL (i = pos) OR (i = LEN(dst)-2);
- dst[i] := src[i];
- dst[i+1] := 0H
- END;
- END cutLine;
- PROCEDURE terminateLine(VAR str: ARRAY OF CHAR);
- VAR
- found: BOOLEAN;
- pos : INTEGER;
- BEGIN
- findChar(LF, str, found, pos);
- IF found THEN
- IF (pos + 1) < LEN(str) THEN
- str[pos + 1] := 0H
- END
- END;
- END terminateLine;
- PROCEDURE getTillEOL(VAR src: ARRAY OF CHAR; spos: INTEGER; VAR dst: ARRAY OF CHAR);
- VAR
- i, j: INTEGER;
- l, k: LONGINT;
- BEGIN
- l := Strings.Length(src);
- k := Strings.Length(dst);
- zeroStr(dst);
- i := 0;
- j := spos+1;
- REPEAT
- dst[i] := src[i+j];
- INC(i);
- UNTIL (i+j >= l) OR (src[i+j] < ' ') OR (i+j >= LEN(src)) OR (j >= LEN(dst));
- END getTillEOL;
- PROCEDURE getNextWord(VAR src: ARRAY OF CHAR; spos: INTEGER; VAR dst: ARRAY OF CHAR);
- VAR
- i, j: INTEGER;
- BEGIN
- zeroStr(dst);
- i := 0;
- j := spos;
- REPEAT
- dst[i] := src[i+j];
- INC(i);
- UNTIL (i+j = Strings.Length(src)) OR (src[i+j] <= ' ');
- END getNextWord;
- PROCEDURE getNextAlphaNumWord(VAR src: ARRAY OF CHAR; spos: INTEGER; VAR dst: ARRAY OF CHAR);
- VAR
- i, j: INTEGER;
- notAN: BOOLEAN;
- o: INTEGER;
- BEGIN
- zeroStr(dst);
- i := 0;
- j := spos;
- notAN := FALSE;
- REPEAT
- dst[i] := src[i+j];
- INC(i);
- o := ORD(src[i+j]);
- IF ~ ( ((o >= 48) & (o <=57)) OR ((o >= 65) & (o <= 90)) OR ( (o >= 97) & (o <= 122) ) ) THEN notAN := TRUE END;
- UNTIL (i+j = Strings.Length(src))OR notAN OR (src[i+j] <= ' ');
- END getNextAlphaNumWord;
- PROCEDURE contains (VAR line : ARRAY OF CHAR; pattern: ARRAY OF CHAR): BOOLEAN;
- END contains;
- PROCEDURE contains1(VAR line: ARRAY OF CHAR; pat : ARRAY OF CHAR): BOOLEAN;
- VAR
- found: BOOLEAN;
- pos : INTEGER;
- BEGIN
- Strings.FindNext(pat, line, 0, found, pos);
- IF found THEN RETURN TRUE ELSE RETURN FALSE END
- END contains1;
-
- PROCEDURE Reverse0 (VAR str : ARRAY OF CHAR; start, end : INTEGER);
- VAR
- h : CHAR;
- BEGIN
- WHILE start < end DO
- h := str[start];
- str[start] := str[end];
- str[end] := h;
- INC(start); DEC(end)
- END
- END Reverse0;
- PROCEDURE dumpChars(VAR s : ARRAY OF CHAR);
- VAR
- i : INTEGER;
- l : LONGINT;
- BEGIN
- i := 0;
- l := Strings.Length(s);
- WHILE i < l DO
- Out.Int(i, 0); Out.Char(" "); Out.Char(s[i]); Out.Ln; INC(i)
- END
- END dumpChars;
- PROCEDURE dumpAllChars(VAR s : ARRAY OF CHAR);
- VAR
- i : INTEGER;
- l : LONGINT;
- BEGIN
- i := 0;
- l := LEN(s);
- WHILE i < l-1 DO
- Out.Int(i, 0); Out.Char(" "); Out.Char(s[i]); Out.Ln; INC(i)
- END
- END dumpAllChars;
- *)
- END strUtils.
|