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 7578 : ulong sz ) {
30 :
31 7578 : uchar const * cur = (uchar const *)str;
32 7578 : if( FD_UNLIKELY( cur==NULL ) ) {
33 9 : return 1;
34 9 : }
35 :
36 7569 : uchar const * const end = cur+sz;
37 :
38 451626 : while( cur<end ) {
39 445674 : uint c0 = *cur;
40 445674 : if( c0>=0x80U ) {
41 25476 : ulong width = fd_utf8_char_width[ c0 ];
42 25476 : if( FD_UNLIKELY( width > (ulong)(end-cur) ) )
43 219 : return 0;
44 25257 : cur++;
45 25257 : switch( width ) {
46 9195 : case 2: {
47 9195 : schar c1 = (schar)( *cur++ );
48 9195 : if( FD_UNLIKELY( (c1>=-64) ) )
49 195 : return 0;
50 9000 : break;
51 9195 : }
52 9012 : case 3: {
53 9012 : uint c1 = *cur++;
54 9012 : int c2 = (schar)( *cur++ );
55 9012 : if( FD_UNLIKELY(
56 9012 : !( ( (c0==0xe0)& (c1>=0xa0)&(c1<=0xbf) )
57 9012 : | ( (c0>=0xe1)&(c0<=0xec)&(c1>=0x80)&(c1<=0xbf) )
58 9012 : | ( (c0==0xed)& (c1>=0x80)&(c1<=0x9f) )
59 9012 : | ( (c0>=0xee)&(c0<=0xef)&(c1>=0x80)&(c1<=0xbf) ) )
60 9012 : | (c2>=-64) ) )
61 156 : return 0;
62 8856 : break;
63 9012 : }
64 8856 : case 4: {
65 6093 : uint c1 = *cur++;
66 6093 : int c2 = (schar)( *cur++ );
67 6093 : int c3 = (schar)( *cur++ );
68 6093 : if( FD_UNLIKELY(
69 6093 : !( ( (c0==0xf0)& (c1>=0x90)&(c1<=0xbf) )
70 6093 : | ( (c0>=0xf1)&(c0<=0xf3)&(c1>=0x80)&(c1<=0xbf) )
71 6093 : | ( (c0==0xf4)& (c1>=0x80)&(c1<=0x8f) ) )
72 6093 : | (c2>=-64)
73 6093 : | (c3>=-64) ) )
74 90 : return 0;
75 6003 : break;
76 6093 : }
77 6003 : default:
78 957 : return 0;
79 25257 : }
80 420198 : } else {
81 420198 : cur++;
82 420198 : }
83 445674 : }
84 :
85 5952 : return 1;
86 7569 : }
|