-
Notifications
You must be signed in to change notification settings - Fork 48
/
utf.c
88 lines (84 loc) · 1.4 KB
/
utf.c
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
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include "utf.h"
size_t
utf8enc(unsigned char *s, uint_least32_t c)
{
if (c < 0x80) {
s[0] = c;
return 1;
}
if (c < 0x800) {
s[0] = 0xc0 | c >> 6;
s[1] = 0x80 | c & 0x3f;
return 2;
}
if (c < 0xd800 || c - 0xe000 < 0x2000) {
s[0] = 0xe0 | c >> 12;
s[1] = 0x80 | c >> 6 & 0x3f;
s[2] = 0x80 | c & 0x3f;
return 3;
}
if (c - 0x10000 < 0x100000) {
s[0] = 0xf0 | c >> 18;
s[1] = 0x80 | c >> 12 & 0x3f;
s[2] = 0x80 | c >> 6 & 0x3f;
s[3] = 0x80 | c & 0x3f;
return 4;
}
assert(0);
return 0;
}
size_t
utf8dec(uint_least32_t *c, const unsigned char *s, size_t n)
{
size_t i, l;
unsigned char b;
uint_least32_t x;
b = s[0];
if (b < 0x80) {
*c = b;
return 1;
}
if ((b & 0xe0) == 0xc0) {
x = b & 0x1f;
l = 2;
} else if ((b & 0xf0) == 0xe0) {
x = b & 0x0f;
l = 3;
} else if ((b & 0xf8) == 0xf0) {
x = b & 0x07;
l = 4;
} else {
return -1;
}
if (n < l)
return -1;
for (i = 1; i < l; ++i) {
b = *++s;
if ((b & 0xc0) != 0x80)
return -1;
x = x << 6 | b & 0x3f;
}
if (x >= 0x110000 || x - 0xd800 < 0x0200)
return -1;
*c = x;
return l;
}
size_t
utf16enc(uint_least16_t *s, uint_least32_t c)
{
if (c < 0xd800 || c - 0xe000 < 0x2000) {
s[0] = c;
return 1;
}
c -= 0x10000;
if (c < 0x100000) {
s[0] = 0xd800 | c >> 10 & 0x3ff;
s[1] = 0xdc00 | c & 0x3ff;
return 2;
}
assert(0);
return 0;
}