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 2034 : ulong sz ) {
30 :
31 2034 : uchar const * cur = (uchar const *)str;
32 2034 : if( FD_UNLIKELY( cur==NULL ) ) {
33 3 : return 1;
34 3 : }
35 :
36 2031 : uchar const * const end = cur+sz;
37 :
38 33591 : while( cur<end ) {
39 32925 : uint c0 = *cur;
40 32925 : if( c0>=0x80U ) {
41 2130 : ulong width = fd_utf8_char_width[ c0 ];
42 2130 : if( FD_UNLIKELY( width > (ulong)(end-cur) ) )
43 264 : return 0;
44 1866 : cur++;
45 1866 : switch( width ) {
46 171 : case 2: {
47 171 : schar c1 = (schar)( *cur++ );
48 171 : if( FD_UNLIKELY( (c1>=-64) ) )
49 0 : return 0;
50 171 : break;
51 171 : }
52 870 : case 3: {
53 870 : uint c1 = *cur++;
54 870 : int c2 = (schar)( *cur++ );
55 870 : if( FD_UNLIKELY(
56 870 : !( ( (c0==0xe0)& (c1>=0xa0)&(c1<=0xbf) )
57 870 : | ( (c0>=0xe1)&(c0<=0xec)&(c1>=0x80)&(c1<=0xbf) )
58 870 : | ( (c0==0xed)& (c1>=0x80)&(c1<=0x9f) )
59 870 : | ( (c0>=0xee)&(c0<=0xef)&(c1>=0x80)&(c1<=0xbf) ) )
60 870 : | (c2>=-64) ) )
61 450 : return 0;
62 420 : break;
63 870 : }
64 420 : case 4: {
65 366 : uint c1 = *cur++;
66 366 : int c2 = (schar)( *cur++ );
67 366 : int c3 = (schar)( *cur++ );
68 366 : if( FD_UNLIKELY(
69 366 : !( ( (c0==0xf0)& (c1>=0x90)&(c1<=0xbf) )
70 366 : | ( (c0>=0xf1)&(c0<=0xf3)&(c1>=0x80)&(c1<=0xbf) )
71 366 : | ( (c0==0xf4)& (c1>=0x80)&(c1<=0x8f) ) )
72 366 : | (c2>=-64)
73 366 : | (c3>=-64) ) )
74 192 : return 0;
75 174 : break;
76 366 : }
77 459 : default:
78 459 : return 0;
79 1866 : }
80 30795 : } else {
81 30795 : cur++;
82 30795 : }
83 32925 : }
84 :
85 666 : return 1;
86 2031 : }
|