File Coverage

blib/lib/Unicode/CheckUTF8/PP.pm
Criterion Covered Total %
statement 10 10 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod 1 1 100.0
total 15 15 100.0


line stmt bran cond sub pod time code
1             package Unicode::CheckUTF8::PP;
2             $Unicode::CheckUTF8::PP::VERSION = '0.003';
3 3     3   44946 use base qw(Exporter);
  3         7  
  3         312  
4             # ABSTRACT: Pure Perl implementation of Unicode::CheckUTF8
5              
6 3     3   17 use strict;
  3         3  
  3         74  
7 3     3   19 use warnings;
  3         4  
  3         2014  
8              
9             our @EXPORT = qw();
10             our @EXPORT_OK = qw(is_utf8);
11              
12             my @validSingleByte = (
13             0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
14             1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
15             1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
16             1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
17             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
18             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
19             0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
20             1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0
21             );
22            
23             my @trailingBytesForUTF8 = (
24             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
25             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
26             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
27             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
28             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
29             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
30             1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
31             2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
32             );
33              
34             my $_isLegalUTF8 = sub {
35             my ($bytes, $length) = @_;
36              
37             my $i = $length;
38             if ( $length <= 4 ) {
39             my $c;
40             if ( $length == 4 ) {
41             $c = $bytes->[--$i];
42             return 0 unless defined $c;
43             return 0 if $c < 0x80 || $c > 0xBF;
44             }
45            
46             if ( $length >= 3 ) {
47             $c = $bytes->[--$i];
48             return 0 unless defined $c;
49             return 0 if $c < 0x80 || $c > 0xBF;
50             }
51            
52             if ( $length >= 2 ) {
53             $c = $bytes->[--$i];
54             return 0 unless defined $c;
55             return 0 if $c > 0xBF;
56            
57             if ( $bytes->[$i] == 0xE0 ) { return 0 if $c < 0xA0; }
58             elsif ( $bytes->[$i] == 0xF0 ) { return 0 if $c < 0x90; }
59             elsif ( $bytes->[$i] == 0xF0 ) { return 0 if $c > 0x8F; }
60             else { return 0 if $c < 0x80; }
61             }
62            
63             if ( $length >= 1 ) {
64             return $validSingleByte[ $bytes->[0] ];
65             }
66             }
67             else {
68             return 0;
69             }
70              
71             return 1;
72             };
73              
74             my $_isLegalUTF8String = sub {
75             my ($str) = @_;
76              
77             my @bytes = unpack 'U*', $str;
78             my $len = @bytes;
79             my $l = 0;
80            
81             my $i = 0;
82             while ( $i < $len ) {
83             my $byte = $bytes[$i];
84             my $length = $trailingBytesForUTF8[$byte] + 1;
85            
86             # check for early termination of string
87             foreach my $j ( 1 .. $length - 1 ) {
88             return 0 unless defined $bytes[$j];
89             return 0 if $bytes[$j] == 0;
90             }
91            
92             return 0 unless
93             $_isLegalUTF8->([@bytes[$i..$i+$length-1]], $length);
94            
95             $l = $bytes[$i];
96             $i += $length;
97             }
98              
99             return ($l || 0) == ($bytes[-1] || 0) ? 1 : 0;
100             };
101              
102             sub is_utf8 {
103 176     176 1 81709 return $_isLegalUTF8String->(@_);
104             }
105              
106             1;
107              
108             __END__