IMPLEMENTATION MODULE Utf8; PROCEDURE Decode (s : ARRAY OF CHAR; lo : CARDINAL; VAR cp : UCHAR; VAR next : CARDINAL) : BOOLEAN; VAR b0, b1, b2, b3, v : INTEGER; i : CARDINAL; PROCEDURE Cont (VAR b : INTEGER) : BOOLEAN; (* consume a continuation byte (0x80..0xBF), or fail *) BEGIN IF i > HIGH(s) THEN RETURN FALSE END; b := ORD(s[i]); INC(i); RETURN (b >= 128) AND (b <= 191) END Cont; BEGIN cp := UCHR(0); next := lo; IF lo > HIGH(s) THEN RETURN FALSE END; b0 := ORD(s[lo]); i := lo + 1; v := -1; IF b0 <= 127 THEN v := b0 ELSIF (b0 >= 194) AND (b0 <= 223) THEN IF Cont(b1) THEN v := ((b0 - 192) * 64) + (b1 - 128) END ELSIF (b0 >= 224) AND (b0 <= 239) THEN IF Cont(b1) AND Cont(b2) THEN v := ((b0 - 224) * 4096) + ((b1 - 128) * 64) + (b2 - 128); IF v < 2048 THEN v := -1 END END ELSIF (b0 >= 240) AND (b0 <= 244) THEN IF Cont(b1) AND Cont(b2) AND Cont(b3) THEN v := ((b0 - 240) * 262144) + ((b1 - 128) * 4096) + ((b2 - 128) * 64) + (b3 - 128); IF v < 65536 THEN v := -1 END END ELSE v := -1 END; IF v < 0 THEN RETURN FALSE END; IF (v >= 55296) AND (v <= 57343) THEN RETURN FALSE END; IF v > 1114111 THEN RETURN FALSE END; cp := UCHR(v); next := i; RETURN TRUE END Decode; PROCEDURE Encode (cp : UCHAR; VAR buf : ARRAY OF CHAR) : CARDINAL; VAR v : INTEGER; n : CARDINAL; BEGIN v := UORD(cp); IF (v >= 0) AND (v <= 127) THEN buf[0] := CHR(v); n := 1 ELSIF (v >= 128) AND (v <= 2047) THEN buf[0] := CHR(192 + (v DIV 64)); buf[1] := CHR(128 + (v MOD 64)); n := 2 ELSIF (v >= 2048) AND (v <= 65535) THEN buf[0] := CHR(224 + (v DIV 4096)); buf[1] := CHR(128 + ((v DIV 64) MOD 64)); buf[2] := CHR(128 + (v MOD 64)); n := 3 ELSIF (v >= 65536) AND (v <= 1114111) THEN buf[0] := CHR(240 + (v DIV 262144)); buf[1] := CHR(128 + ((v DIV 4096) MOD 64)); buf[2] := CHR(128 + ((v DIV 64) MOD 64)); buf[3] := CHR(128 + (v MOD 64)); n := 4 ELSE n := 0 END; RETURN n END Encode; END Utf8.