(* BSD 2-Clause License Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) MODULE STRINGS; IMPORT UTILS; PROCEDURE copy* (src: ARRAY OF CHAR; VAR dst: ARRAY OF CHAR; spos, dpos, count: INTEGER); BEGIN WHILE count > 0 DO dst[dpos] := src[spos]; INC(spos); INC(dpos); DEC(count) END END copy; PROCEDURE append* (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); VAR n1, n2: INTEGER; BEGIN n1 := LENGTH(s1); n2 := LENGTH(s2); ASSERT(n1 + n2 < LEN(s1)); copy(s2, s1, 0, n1, n2); s1[n1 + n2] := 0X END append; PROCEDURE IntToStr* (x: INTEGER; VAR str: ARRAY OF CHAR); VAR i, a: INTEGER; BEGIN IF x = UTILS.minint THEN IF UTILS.bit_depth = 32 THEN COPY("-2147483648", str) ELSIF UTILS.bit_depth = 64 THEN COPY("-9223372036854775808", str) END ELSE i := 0; IF x < 0 THEN x := -x; i := 1; str[0] := "-" END; a := x; REPEAT INC(i); a := a DIV 10 UNTIL a = 0; str[i] := 0X; REPEAT DEC(i); str[i] := CHR(x MOD 10 + ORD("0")); x := x DIV 10 UNTIL x = 0 END END IntToStr; PROCEDURE IntToHex* (x: INTEGER; VAR str: ARRAY OF CHAR; n: INTEGER); BEGIN str[n] := 0X; WHILE n > 0 DO str[n - 1] := CHR(UTILS.hexdgt(x MOD 16)); x := x DIV 16; DEC(n) END END IntToHex; PROCEDURE search* (s: ARRAY OF CHAR; VAR pos: INTEGER; c: CHAR; forward: BOOLEAN); VAR length: INTEGER; BEGIN length := LENGTH(s); IF (0 <= pos) & (pos < length) THEN IF forward THEN WHILE (pos < length) & (s[pos] # c) DO INC(pos) END; IF pos = length THEN pos := -1 END ELSE WHILE (pos >= 0) & (s[pos] # c) DO DEC(pos) END END ELSE pos := -1 END END search; PROCEDURE letter* (c: CHAR): BOOLEAN; RETURN ("a" <= c) & (c <= "z") OR ("A" <= c) & (c <= "Z") OR (c = "_") END letter; PROCEDURE digit* (c: CHAR): BOOLEAN; RETURN ("0" <= c) & (c <= "9") END digit; PROCEDURE hexdigit* (c: CHAR): BOOLEAN; RETURN ("0" <= c) & (c <= "9") OR ("A" <= c) & (c <= "F") END hexdigit; PROCEDURE space* (c: CHAR): BOOLEAN; RETURN (0X < c) & (c <= 20X) END space; PROCEDURE cap (VAR c: CHAR); BEGIN IF ("a" <= c) & (c <= "z") THEN c := CHR(ORD(c) - 32) END END cap; PROCEDURE UpCase* (VAR str: ARRAY OF CHAR); VAR i: INTEGER; BEGIN i := LENGTH(str) - 1; WHILE i >= 0 DO cap(str[i]); DEC(i) END END UpCase; PROCEDURE StrToInt* (str: ARRAY OF CHAR; VAR x: INTEGER): BOOLEAN; VAR i, k: INTEGER; res: BOOLEAN; BEGIN res := TRUE; i := 0; x := 0; k := LENGTH(str); WHILE i < k DO IF digit(str[i]) THEN x := x * 10 + ORD(str[i]) - ORD("0") ELSE i := k; res := FALSE END; INC(i) END RETURN res END StrToInt; PROCEDURE CheckVer (str: ARRAY OF CHAR): BOOLEAN; VAR i, k: INTEGER; res: BOOLEAN; BEGIN k := LENGTH(str); res := k < LEN(str); IF res & digit(str[0]) THEN i := 0; WHILE (i < k) & digit(str[i]) DO INC(i) END; IF (i < k) & (str[i] = ".") THEN INC(i); IF i < k THEN WHILE (i < k) & digit(str[i]) DO INC(i) END ELSE res := FALSE END ELSE res := FALSE END; res := res & (i = k) ELSE res := FALSE END RETURN res END CheckVer; PROCEDURE StrToVer* (str: ARRAY OF CHAR; VAR major, minor: INTEGER): BOOLEAN; VAR i: INTEGER; res: BOOLEAN; BEGIN res := CheckVer(str); IF res THEN i := 0; minor := 0; major := 0; WHILE digit(str[i]) DO major := major * 10 + ORD(str[i]) - ORD("0"); INC(i) END; INC(i); WHILE digit(str[i]) DO minor := minor * 10 + ORD(str[i]) - ORD("0"); INC(i) END END RETURN res END StrToVer; PROCEDURE Utf8To16* (src: ARRAY OF CHAR; VAR dst: ARRAY OF WCHAR): INTEGER; VAR i, j, u, srclen, dstlen: INTEGER; c: CHAR; BEGIN srclen := LEN(src); dstlen := LEN(dst); i := 0; j := 0; WHILE (i < srclen) & (j < dstlen) & (src[i] # 0X) DO c := src[i]; CASE c OF |00X..7FX: u := ORD(c) |0C1X..0DFX: u := (ORD(c) - 0C0H) * 64; IF i + 1 < srclen THEN INC(i); INC(u, ORD(src[i]) MOD 64) END |0E1X..0EFX: u := (ORD(c) - 0E0H) * 4096; IF i + 1 < srclen THEN INC(i); INC(u, (ORD(src[i]) MOD 64) * 64) END; IF i + 1 < srclen THEN INC(i); INC(u, ORD(src[i]) MOD 64) END (* |0F1X..0F7X: |0F9X..0FBX: |0FDX: *) ELSE END; INC(i); dst[j] := WCHR(u); INC(j) END; IF j < dstlen THEN dst[j] := WCHR(0) END RETURN j END Utf8To16; END STRINGS.