forked from vurtun/nuklear
-
Notifications
You must be signed in to change notification settings - Fork 0
/
nuklear_utf8.c
144 lines (130 loc) · 3.48 KB
/
nuklear_utf8.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "nuklear.h"
#include "nuklear_internal.h"
/* ===============================================================
*
* UTF-8
*
* ===============================================================*/
NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000};
NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
NK_INTERN int
nk_utf_validate(nk_rune *u, int i)
{
NK_ASSERT(u);
if (!u) return 0;
if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) ||
NK_BETWEEN(*u, 0xD800, 0xDFFF))
*u = NK_UTF_INVALID;
for (i = 1; *u > nk_utfmax[i]; ++i);
return i;
}
NK_INTERN nk_rune
nk_utf_decode_byte(char c, int *i)
{
NK_ASSERT(i);
if (!i) return 0;
for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) {
if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i])
return (nk_byte)(c & ~nk_utfmask[*i]);
}
return 0;
}
NK_API int
nk_utf_decode(const char *c, nk_rune *u, int clen)
{
int i, j, len, type=0;
nk_rune udecoded;
NK_ASSERT(c);
NK_ASSERT(u);
if (!c || !u) return 0;
if (!clen) return 0;
*u = NK_UTF_INVALID;
udecoded = nk_utf_decode_byte(c[0], &len);
if (!NK_BETWEEN(len, 1, NK_UTF_SIZE))
return 1;
for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type);
if (type != 0)
return j;
}
if (j < len)
return 0;
*u = udecoded;
nk_utf_validate(u, len);
return len;
}
NK_INTERN char
nk_utf_encode_byte(nk_rune u, int i)
{
return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i]));
}
NK_API int
nk_utf_encode(nk_rune u, char *c, int clen)
{
int len, i;
len = nk_utf_validate(&u, 0);
if (clen < len || !len || len > NK_UTF_SIZE)
return 0;
for (i = len - 1; i != 0; --i) {
c[i] = nk_utf_encode_byte(u, 0);
u >>= 6;
}
c[0] = nk_utf_encode_byte(u, len);
return len;
}
NK_API int
nk_utf_len(const char *str, int len)
{
const char *text;
int glyphs = 0;
int text_len;
int glyph_len;
int src_len = 0;
nk_rune unicode;
NK_ASSERT(str);
if (!str || !len) return 0;
text = str;
text_len = len;
glyph_len = nk_utf_decode(text, &unicode, text_len);
while (glyph_len && src_len < len) {
glyphs++;
src_len = src_len + glyph_len;
glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len);
}
return glyphs;
}
NK_API const char*
nk_utf_at(const char *buffer, int length, int index,
nk_rune *unicode, int *len)
{
int i = 0;
int src_len = 0;
int glyph_len = 0;
const char *text;
int text_len;
NK_ASSERT(buffer);
NK_ASSERT(unicode);
NK_ASSERT(len);
if (!buffer || !unicode || !len) return 0;
if (index < 0) {
*unicode = NK_UTF_INVALID;
*len = 0;
return 0;
}
text = buffer;
text_len = length;
glyph_len = nk_utf_decode(text, unicode, text_len);
while (glyph_len) {
if (i == index) {
*len = glyph_len;
break;
}
i++;
src_len = src_len + glyph_len;
glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
}
if (i != index) return 0;
return buffer + src_len;
}