Line data Source code
1 : #include "fd_utf8.h"
2 :
3 : /* Basic UTF-8 validator imported from Rust's core/src/str/validations.rs */
4 :
5 : /* FIXME: Add high-performance AVX version */
6 :
7 : static uchar const fd_utf8_char_width[ 256 ] = {
8 : // 1 2 3 4 5 6 7 8 9 A B C D E F
9 : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
10 : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
11 : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
12 : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
13 : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
14 : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
15 : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
16 : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
17 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
18 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
19 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
20 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
21 : 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C
22 : 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // D
23 : 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // E
24 : 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F
25 : };
26 :
27 : FD_FN_PURE int
28 : fd_utf8_verify( char const * str,
29 7593 : ulong sz ) {
30 :
31 7593 : uchar const * cur = (uchar const *)str;
32 7593 : if( FD_UNLIKELY( cur==NULL ) ) {
33 9 : return 1;
34 9 : }
35 :
36 7584 : uchar const * const end = cur+sz;
37 :
38 452139 : while( cur<end ) {
39 446172 : uint c0 = *cur;
40 446172 : if( c0>=0x80U ) {
41 25497 : ulong width = fd_utf8_char_width[ c0 ];
42 25497 : if( FD_UNLIKELY( width > (ulong)(end-cur) ) )
43 219 : return 0;
44 25278 : cur++;
45 25278 : switch( width ) {
46 9201 : case 2: {
47 9201 : schar c1 = (schar)( *cur++ );
48 9201 : if( FD_UNLIKELY( (c1>=-64) ) )
49 195 : return 0;
50 9006 : break;
51 9201 : }
52 9021 : case 3: {
53 9021 : uint c1 = *cur++;
54 9021 : int c2 = (schar)( *cur++ );
55 9021 : if( FD_UNLIKELY(
56 9021 : !( ( (c0==0xe0)& (c1>=0xa0)&(c1<=0xbf) )
57 9021 : | ( (c0>=0xe1)&(c0<=0xec)&(c1>=0x80)&(c1<=0xbf) )
58 9021 : | ( (c0==0xed)& (c1>=0x80)&(c1<=0x9f) )
59 9021 : | ( (c0>=0xee)&(c0<=0xef)&(c1>=0x80)&(c1<=0xbf) ) )
60 9021 : | (c2>=-64) ) )
61 156 : return 0;
62 8865 : break;
63 9021 : }
64 8865 : case 4: {
65 6099 : uint c1 = *cur++;
66 6099 : int c2 = (schar)( *cur++ );
67 6099 : int c3 = (schar)( *cur++ );
68 6099 : if( FD_UNLIKELY(
69 6099 : !( ( (c0==0xf0)& (c1>=0x90)&(c1<=0xbf) )
70 6099 : | ( (c0>=0xf1)&(c0<=0xf3)&(c1>=0x80)&(c1<=0xbf) )
71 6099 : | ( (c0==0xf4)& (c1>=0x80)&(c1<=0x8f) ) )
72 6099 : | (c2>=-64)
73 6099 : | (c3>=-64) ) )
74 90 : return 0;
75 6009 : break;
76 6099 : }
77 6009 : default:
78 957 : return 0;
79 25278 : }
80 420675 : } else {
81 420675 : cur++;
82 420675 : }
83 446172 : }
84 :
85 5967 : return 1;
86 7584 : }
|