File Coverage

blib/lib/WordList.pm
Criterion Covered Total %
statement 71 72 98.6
branch 21 26 80.7
condition 3 3 100.0
subroutine 15 15 100.0
pod 8 8 100.0
total 118 124 95.1


line stmt bran cond sub pod time code
1             package WordList;
2              
3             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
4             our $DATE = '2021-02-23'; # DATE
5             our $DIST = 'WordList'; # DIST
6             our $VERSION = '0.7.8'; # VERSION
7              
8 2     2   31 use strict 'subs', 'vars';
  2         4  
  2         71  
9              
10 2     2   884 use WordListBase ();
  2         4  
  2         1466  
11             our @ISA = qw(WordListBase);
12              
13             # IFUNBUILT
14             # use Role::Tiny::With;
15             # with 'WordListRole::WordList';
16             # END IFUNBUILT
17              
18             sub new {
19 5     5 1 295 my $class = shift;
20 5         30 my $self = $class->SUPER::new(@_);
21              
22 5         36 my $fh = \*{"$class\::DATA"};
  5         23  
23 2     2   11 binmode $fh, "encoding(utf8)";
  2         3  
  2         13  
  5         60  
24 5         24747 my $fh_orig_pos = tell $fh;
25 5 50       10 unless (defined ${"$class\::DATA_POS"}) {
  5         37  
26 5         10 ${"$class\::DATA_POS"} = $fh_orig_pos;
  5         20  
27             }
28              
29 5         33 $self->{fh} = $fh;
30 5         13 $self->{fh_orig_pos} = $fh_orig_pos;
31 5         9 $self->{fh_seekable} = 1;
32 5         14 $self;
33             }
34              
35             sub each_word {
36 10     10 1 1922 my ($self, $code) = @_;
37              
38 10         15 my $i = 0;
39 10         15 while (1) {
40 24 100       82 my $word = $i++ ? $self->next_word : $self->first_word;
41 24 100       50 last unless defined $word;
42 17         31 my $res = $code->($word);
43 17 100 100     73 last if defined $res && $res == -2;
44             }
45             }
46              
47             sub next_word {
48 33     33 1 60 my $self = shift;
49              
50 33         46 my $fh = $self->{fh};
51 33         325 my $word = <$fh>;
52 33 100       198 chomp $word if defined $word;
53 33         91 $word;
54             }
55              
56             sub reset_iterator {
57 15     15 1 26 my $self = shift;
58              
59             die "Cannot reset iterator, filehandle not seekable"
60 15 50       43 unless $self->{fh_seekable};
61 15         23 my $fh = $self->{fh};
62 15         197 seek $fh, $self->{fh_orig_pos}, 0;
63             }
64              
65             sub first_word {
66 13     13 1 3288 my $self = shift;
67              
68 13         38 $self->reset_iterator;
69 13         55 $self->next_word;
70             }
71              
72             sub pick {
73 16     16 1 15909 my ($self, $n, $allow_duplicates) = @_; # but this implementaiton never produces duplicates
74              
75 16 100       49 $n = 1 if !defined $n;
76 16 100       76 die "Please specify a positive number of words to pick" if $n < 1;
77              
78 12 100       28 if ($n == 1) {
79 4         8 my $i = 0;
80 4         7 my $word;
81             # algorithm from Learning Perl
82             $self->each_word(
83             sub {
84 8     8   15 $i++;
85 8 100       88 $word = $_[0] if rand($i) < 1;
86             }
87 4         25 );
88 4         20 return $word;
89             }
90              
91 8         12 my $i = 0;
92 8         16 my @words;
93             $self->each_word(
94             sub {
95 16     16   26 $i++;
96 16 50       33 if (@words < $n) {
97             # we haven't reached $n, put word to result in a random position
98 16         61 splice @words, rand(@words+1), 0, $_[0];
99             } else {
100             # we have reached $n, just replace a word randomly, using
101             # algorithm from Learning Perl, slightly modified
102 0 0       0 rand($i) < @words and splice @words, rand(@words), 1, $_[0];
103             }
104             }
105 8         57 );
106 8         59 @words;
107             }
108              
109             sub word_exists {
110 16     16 1 9501 my ($self, $word) = @_;
111              
112 16         23 my $found = 0;
113             $self->each_word(
114             sub {
115 24 100   24   84 if ($word eq $_[0]) {
116 8         14 $found = 1;
117 8         19 return -2;
118             }
119             }
120 16         92 );
121 16         90 $found;
122             }
123              
124             sub all_words {
125 4     4 1 11553 my ($self) = @_;
126              
127 4         8 my @words;
128             $self->each_word(
129             sub {
130 8     8   20 push @words, $_[0];
131             }
132 4         25 );
133 4         70 @words;
134             }
135              
136             1;
137             # ABSTRACT: Specification and base class for WordList::*, modules that contain word list
138              
139             __END__