File Coverage

blib/lib/Text/Hunspell/FFI.pm
Criterion Covered Total %
statement 31 31 100.0
branch 5 6 83.3
condition n/a
subroutine 8 8 100.0
pod n/a
total 44 45 97.7


line stmt bran cond sub pod time code
1             package Text::Hunspell::FFI;
2              
3 9     9   150167 use strict;
  9         15  
  9         221  
4 9     9   29 use warnings;
  9         9  
  9         179  
5 9     9   140 use 5.020;
  9         20  
6 9     9   4950 use FFI::Platypus;
  9         38632  
  9         246  
7 9     9   3157 use Text::Hunspell::FFI::Lib;
  9         13  
  9         219  
8 9     9   3671 use experimental qw( postderef );
  9         20833  
  9         31  
9              
10             # ABSTRACT: Perl FFI interface to the Hunspell library
11             our $VERSION = '0.02'; # VERSION
12              
13             sub _ffi
14             {
15 121     121   97 state $ffi;
16            
17 121 100       227 unless(defined $ffi)
18             {
19 9         21 my @libs = Text::Hunspell::FFI::Lib::_libs();
20              
21 9 50       41 die "unable to find libs" unless @libs;
22            
23 9         61 $ffi = FFI::Platypus->new(
24             lib => \@libs,
25             );
26 9         191 $ffi->load_custom_type('::StringArray' => 'string_array');
27             }
28            
29 121         27179 $ffi;
30             }
31              
32             _ffi->attach(['Hunspell_create'=>'new'] => ['string','string'] => 'opaque', sub
33             {
34             my($xsub, $class, $aff, $dic) = @_;
35             my $ptr = $xsub->($aff, $dic);
36             bless \$ptr, $class;
37             });
38              
39              
40             _ffi->attach(['Hunspell_destroy'=>'DESTROY'] => ['opaque'] => 'void', sub
41             {
42             my($xsub, $self) = @_;
43             $xsub->($$self);
44             });
45              
46             foreach my $try (qw( Hunspell_add_dic _ZN8Hunspell7add_dicEPKcS1_ ))
47             {
48             eval {
49             _ffi->attach([$try=>'add_dic'] => ['opaque','string'] => 'void', sub
50             {
51             my($xsub, $self, $dpath) = @_;
52             $xsub->($$self, $dpath);
53             });
54             };
55             last unless $@;
56             }
57              
58             unless(__PACKAGE__->can('add_dic'))
59             {
60             # TODO: fallback on Perl implementation ?
61             die "unable to find add_dic";
62             }
63              
64             _ffi->attach(['Hunspell_spell'=>'check'] => ['opaque','string'] => 'int', sub
65             {
66             my($xsub, $self, $word) = @_;
67             $xsub->($$self, $word);
68             });
69              
70             _ffi->attach(['Hunspell_free_list',=>'_free_list'] => ['opaque','opaque*','int'] => 'void');
71              
72             sub _string_array_and_word
73             {
74 2     2   495 my($xsub, $self, $word) = @_;
75 2         3 my $ptr;
76 2         254 my $count = $xsub->($$self, \$ptr, $word);
77 2         8 my @result = map { _ffi->cast('opaque','string',$_) } _ffi->cast('opaque',"opaque[$count]", $ptr)->@*;
  4         305  
78 2         65 _free_list($self, $ptr, $count);
79 2 100       12 wantarray ? @result : $result[0];
80             }
81              
82             _ffi->attach(['Hunspell_suggest'=>'suggest'] => ['opaque','opaque*','string'] => 'int', \&_string_array_and_word);
83             _ffi->attach(['Hunspell_analyze'=>'analyze'] => ['opaque','opaque*','string'] => 'int', \&_string_array_and_word);
84              
85             _ffi->attach(['Hunspell_generate'=>'generate'] => ['opaque','opaque*','string','string'] => 'int', sub {
86             my($xsub, $self, $word, $word2) = @_;
87             my $ptr;
88             my $count = $xsub->($$self, \$ptr, $word, $word2);
89             my @result = map { _ffi->cast('opaque','string',$_) } _ffi->cast('opaque',"opaque[$count]", $ptr)->@*;
90             _free_list($self, $ptr, $count);
91             wantarray ? @result : $result[0];
92             });
93              
94             _ffi->attach(['Hunspell_generate2'=>'generate2'] => ['opaque','opaque*','string','string_array','int'] => 'int', sub
95             {
96             my($xsub, $self, $word, $suggestions) = @_;
97             my $n = scalar @$suggestions;
98             my $ptr;
99             my $count = $xsub->($$self, \$ptr, $word, [@$suggestions], 1);
100             my @result = map { _ffi->cast('opaque','string',$_) } _ffi->cast('opaque',"opaque[$count]", $ptr)->@*;
101             _free_list($self, $ptr, $count);
102             wantarray ? @result : $result[0];
103             });
104              
105             1;
106              
107             __END__