summaryrefslogtreecommitdiff
path: root/Build/source/texk/ptexenc/unicode.c
blob: 2e723f6cd31e05fea99d4b09e351373c1e9f1815 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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 */
}