2 * UTF-8 utility functions
4 * (c) 2010-2016 Steve Bennett <steveb@workware.net.au>
6 * See LICENCE for licence details.
16 int utf8_fromunicode(char *p, unsigned uc)
22 else if (uc <= 0x7ff) {
23 *p++ = 0xc0 | ((uc & 0x7c0) >> 6);
24 *p = 0x80 | (uc & 0x3f);
27 else if (uc <= 0xffff) {
28 *p++ = 0xe0 | ((uc & 0xf000) >> 12);
29 *p++ = 0x80 | ((uc & 0xfc0) >> 6);
30 *p = 0x80 | (uc & 0x3f);
33 /* Note: We silently truncate to 21 bits here: 0x1fffff */
35 *p++ = 0xf0 | ((uc & 0x1c0000) >> 18);
36 *p++ = 0x80 | ((uc & 0x3f000) >> 12);
37 *p++ = 0x80 | ((uc & 0xfc0) >> 6);
38 *p = 0x80 | (uc & 0x3f);
43 int utf8_charlen(int c)
45 if ((c & 0x80) == 0) {
48 if ((c & 0xe0) == 0xc0) {
51 if ((c & 0xf0) == 0xe0) {
54 if ((c & 0xf8) == 0xf0) {
57 /* Invalid sequence */
61 int utf8_strlen(const char *str, int bytelen)
65 bytelen = strlen(str);
69 int l = utf8_tounicode(str, &c);
77 int utf8_index(const char *str, int index)
82 s += utf8_tounicode(s, &c);
87 int utf8_tounicode(const char *str, int *uc)
89 unsigned const char *s = (unsigned const char *)str;
96 if ((s[1] & 0xc0) == 0x80) {
97 *uc = ((s[0] & ~0xc0) << 6) | (s[1] & ~0x80);
101 else if (s[0] < 0xf0) {
102 if (((str[1] & 0xc0) == 0x80) && ((str[2] & 0xc0) == 0x80)) {
103 *uc = ((s[0] & ~0xe0) << 12) | ((s[1] & ~0x80) << 6) | (s[2] & ~0x80);
107 else if (s[0] < 0xf8) {
108 if (((str[1] & 0xc0) == 0x80) && ((str[2] & 0xc0) == 0x80) && ((str[3] & 0xc0) == 0x80)) {
109 *uc = ((s[0] & ~0xf0) << 18) | ((s[1] & ~0x80) << 12) | ((s[2] & ~0x80) << 6) | (s[3] & ~0x80);
114 /* Invalid sequence, so just return the byte */