diff options
Diffstat (limited to 'Build/source/texk/ptexenc/unicode.c')
-rw-r--r-- | Build/source/texk/ptexenc/unicode.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/Build/source/texk/ptexenc/unicode.c b/Build/source/texk/ptexenc/unicode.c new file mode 100644 index 00000000000..2e723f6cd31 --- /dev/null +++ b/Build/source/texk/ptexenc/unicode.c @@ -0,0 +1,112 @@ +/* + unicode.c -- utilities for Unicode + written by N. Tsuchimura +*/ + +#include <ptexenc/c-auto.h> +#include <ptexenc/unicode.h> +#include <ptexenc/kanjicnv.h> + +#include <stdio.h> /* for fprintf() */ + +/* determine if UTF-8 character or not */ +boolean isUTF8(int length, int nth, int c) +{ + c &= 0xff; + switch (length * 8 + nth) { + case 011: return (0x00 <= c && c < 0x80); + case 021: return (0xc2 <= c && c < 0xe0); + case 031: return (0xe0 <= c && c < 0xf0); + case 041: return (0xf0 <= c && c < 0xf5); + case 022: + case 032: case 033: + case 042: case 043: case 044: + return (0x80 <= c && c < 0xc0); + default: + fprintf(stderr, "isUTF8: unexpected param length=%d, nth=%d\n", + length, nth); + } + return false; +} + + +int UTF8length(int first_byte) +{ + if (first_byte < 0x00) return -2; /* illegal */ + if (first_byte < 0x80) return 1; + if (first_byte < 0xc2) return -2; /* illegal */ + if (first_byte < 0xe0) return 2; + if (first_byte < 0xf0) return 3; + if (first_byte < 0xf5) return 4; + return -1; /* reserved/undefined */ +} + + +/* with strict range check */ +int UTF8Slength(string buff, int buff_len) +{ + int i, len; + + len = UTF8length(buff[0]); + if (len < 0) return -2; /* illegal */ + if (len > buff_len) return -3; /* overflow */ + for (i=0; i<len; i++) { + if (!isUTF8(len, 1+i, buff[i])) return -1; /* not UTF-8 */ + } + return len; +} + + +/* WITHOUT strict range check */ +long UTF8StoUCS(string s) +{ + switch (UTF8length(s[0])) { + case 1: return s[0]; + case 2: return UTF8BtoUCS(s[0], s[1]); + case 3: return UTF8CtoUCS(s[0], s[1], s[2]); + case 4: return UTF8DtoUCS(s[0], s[1], s[2], s[3]); + default: return 0; /* error */ + } +} + +int UCStoUTF8S(long ucs, string s) +{ + if (ucs < 0x80) { + *s = ucs; + return 1; + } else if (ucs < 0x800) { + *s++ = UCStoUTF8B1(ucs); + *s++ = UCStoUTF8B2(ucs); + return 2; + } else if (ucs < 0xFFFF) { + *s++ = UCStoUTF8C1(ucs); + *s++ = UCStoUTF8C2(ucs); + *s++ = UCStoUTF8C3(ucs); + return 3; + } else if (ucs < 0x10FFFF) { + *s++ = UCStoUTF8D1(ucs); + *s++ = UCStoUTF8D2(ucs); + *s++ = UCStoUTF8D3(ucs); + *s++ = UCStoUTF8D4(ucs); + return 4; + } + return 0; /* unsupported */ +} + + +long UCStoUTF8(long ucs) +{ + if (ucs < 0x80) return ucs; + if (ucs < 0x800) return LONG(0,0, + UCStoUTF8B1(ucs), + UCStoUTF8B2(ucs)); + if (ucs < 0xFFFF) return LONG(0, + UCStoUTF8C1(ucs), + UCStoUTF8C2(ucs), + UCStoUTF8C3(ucs)); + if (ucs < 0x10FFFF) return LONG(UCStoUTF8D1(ucs), + UCStoUTF8D2(ucs), + UCStoUTF8D3(ucs), + UCStoUTF8D4(ucs)); + return 0; /* unsupported */ +} |