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 1998 : ulong sz ) {
30 :
31 1998 : uchar const * cur = (uchar const *)str;
32 1998 : if( FD_UNLIKELY( cur==NULL ) ) {
33 4 : return 1;
34 4 : }
35 :
36 1994 : uchar const * const end = cur+sz;
37 :
38 128496 : while( cur<end ) {
39 126661 : uint c0 = *cur;
40 126661 : if( c0>=0x80U ) {
41 8199 : ulong width = fd_utf8_char_width[ c0 ];
42 8199 : if( FD_UNLIKELY( width > (ulong)(end-cur) ) )
43 8 : return 0;
44 8191 : cur++;
45 8191 : switch( width ) {
46 3038 : case 2: {
47 3038 : schar c1 = (schar)( *cur++ );
48 3038 : if( FD_UNLIKELY( (c1>=-64) ) )
49 22 : return 0;
50 3016 : break;
51 3038 : }
52 3016 : case 3: {
53 2997 : uint c1 = *cur++;
54 2997 : int c2 = (schar)( *cur++ );
55 2997 : if( FD_UNLIKELY(
56 2997 : !( ( (c0==0xe0)& (c1>=0xa0)&(c1<=0xbf) )
57 2997 : | ( (c0>=0xe1)&(c0<=0xec)&(c1>=0x80)&(c1<=0xbf) )
58 2997 : | ( (c0==0xed)& (c1>=0x80)&(c1<=0x9f) )
59 2997 : | ( (c0>=0xee)&(c0<=0xef)&(c1>=0x80)&(c1<=0xbf) ) )
60 2997 : | (c2>=-64) ) )
61 17 : return 0;
62 2980 : break;
63 2997 : }
64 2980 : case 4: {
65 2068 : uint c1 = *cur++;
66 2068 : int c2 = (schar)( *cur++ );
67 2068 : int c3 = (schar)( *cur++ );
68 2068 : if( FD_UNLIKELY(
69 2068 : !( ( (c0==0xf0)& (c1>=0x90)&(c1<=0xbf) )
70 2068 : | ( (c0>=0xf1)&(c0<=0xf3)&(c1>=0x80)&(c1<=0xbf) )
71 2068 : | ( (c0==0xf4)& (c1>=0x80)&(c1<=0x8f) ) )
72 2068 : | (c2>=-64)
73 2068 : | (c3>=-64) ) )
74 21 : return 0;
75 2047 : break;
76 2068 : }
77 2047 : default:
78 91 : return 0;
79 8191 : }
80 118462 : } else {
81 118462 : cur++;
82 118462 : }
83 126661 : }
84 :
85 1835 : return 1;
86 1994 : }
|