(* BSD 2-Clause License Copyright (c) 2018-2021, 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 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 replace* (VAR s: ARRAY OF CHAR; find, repl: CHAR); VAR i, strlen: INTEGER; BEGIN strlen := LENGTH(s) - 1; FOR i := 0 TO strlen DO IF s[i] = find THEN s[i] := repl END END END replace; PROCEDURE trim* (source: ARRAY OF CHAR; VAR result: ARRAY OF CHAR); VAR LenS, start, _end, i, j: INTEGER; BEGIN LenS := LENGTH(source) - 1; j := 0; IF LenS >= 0 THEN start := 0; WHILE (start <= LenS) & (source[start] <= 20X) DO INC(start) END; _end := LenS; WHILE (_end >= 0) & (source[_end] <= 20X) DO DEC(_end) END; FOR i := start TO _end DO result[j] := source[i]; INC(j) END END; result[j] := 0X END trim; 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; PROCEDURE HashStr* (name: ARRAY OF CHAR): INTEGER; VAR i, h: INTEGER; g: SET; BEGIN h := 0; i := 0; WHILE name[i] # 0X DO h := h * 16 + ORD(name[i]); g := BITS(h) * {28..31}; h := ORD(BITS(h) / BITS(LSR(ORD(g), 24)) - g); INC(i) END RETURN h END HashStr; END STRINGS.