blob: f6fa49d9d4ed64159567f215030c413cfef86b31 (
plain) (
blame)
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
|
#include "aplwc_internal.h"
struct string *
chars_to_string(struct aplwc *aplwc, const char *chars)
{
const uint8_t *utf8;
size_t bytecount, charcount;
struct string *string;
uint32_t c;
uint8_t b;
int seqlen, extra;
utf8 = (const uint8_t *)chars;
seqlen = extra = 0;
for(bytecount = 0, charcount = 0; utf8[bytecount]; bytecount++){
b = utf8[bytecount];
if(extra == 0){
c = 0;
if((b & 0x80) == 0){
seqlen = 0;
c |= (b & 0x7F);
}else if((b & 0xE0) == 0xC0){
seqlen = 1;
c |= (b & 0x1F);
}else if((b & 0xF0) == 0xE0){
seqlen = 2;
c |= (b & 0x0F);
}else if((b & 0xF8) == 0xF0){
seqlen = 3;
c |= (b & 0x7);
}else{
invalid:
aplwc->last_error = APLWC_INVALID_UTF8;
return NULL;
}
extra = seqlen;
}else{
extra--;
c <<= 6;
if((b & 0xC0) == 0x80)
c |= (b & 0x3F);
else
goto invalid;
}
if(extra == 0){
charcount++;
switch(seqlen){
case 0:
if(NEVER(c > 0x7F))
goto invalid;
break;
case 1:
if((c < 0x80) || NEVER(c > 0x07FF))
goto invalid;
break;
case 2:
if((c < 0x0800) || NEVER(c > 0xFFFF))
goto invalid;
break;
case 3:
if((c < 0x010000) || NEVER(c > 0x10FFFF))
goto invalid;
break;
}
}
}
if(extra != 0)
goto invalid;
string = memory_alloc_string(&aplwc->memory, bytecount);
if(string){
string->bytes = bytecount;
string->chars = charcount;
string->utf8 = ((uint8_t *)string)+sizeof(*string);
memcpy(string->utf8, utf8, bytecount);
}else
aplwc->last_error = APLWC_OUT_OF_MEMORY;
return string;
}
|