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-06-23'; # DATE
5             our $DIST = 'WordList'; # DIST
6             our $VERSION = '0.7.10'; # VERSION
7              
8 2     2   31 use strict 'subs', 'vars';
  2         4  
  2         66  
9              
10 2     2   795 use WordListBase ();
  2         4  
  2         1376  
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 279 my $class = shift;
20 5         30 my $self = $class->SUPER::new(@_);
21              
22 5         34 my $fh = \*{"$class\::DATA"};
  5         20  
23 2     2   11 binmode $fh, "encoding(utf8)";
  2         4  
  2         12  
  5         53  
24 5         22160 my $fh_orig_pos = tell $fh;
25 5 50       10 unless (defined ${"$class\::DATA_POS"}) {
  5         32  
26 5         9 ${"$class\::DATA_POS"} = $fh_orig_pos;
  5         18  
27             }
28              
29 5         29 $self->{fh} = $fh;
30 5         10 $self->{fh_orig_pos} = $fh_orig_pos;
31 5         8 $self->{fh_seekable} = 1;
32 5         12 $self;
33             }
34              
35             sub each_word {
36 10     10 1 1650 my ($self, $code) = @_;
37              
38 10         14 my $i = 0;
39 10         12 while (1) {
40 24 100       65 my $word = $i++ ? $self->next_word : $self->first_word;
41 24 100       43 last unless defined $word;
42 17         29 my $res = $code->($word);
43 17 100 100     59 last if defined $res && $res == -2;
44             }
45             }
46              
47             sub next_word {
48 33     33 1 40 my $self = shift;
49              
50 33         44 my $fh = $self->{fh};
51 33         273 my $word = <$fh>;
52 33 100       171 chomp $word if defined $word;
53 33         78 $word;
54             }
55              
56             sub reset_iterator {
57 15     15 1 20 my $self = shift;
58              
59             die "Cannot reset iterator, filehandle not seekable"
60 15 50       48 unless $self->{fh_seekable};
61 15         19 my $fh = $self->{fh};
62 15         171 seek $fh, $self->{fh_orig_pos}, 0;
63             }
64              
65             sub first_word {
66 13     13 1 2837 my $self = shift;
67              
68 13         32 $self->reset_iterator;
69 13         52 $self->next_word;
70             }
71              
72             sub pick {
73 16     16 1 13283 my ($self, $n, $allow_duplicates) = @_; # but this implementaiton never produces duplicates
74              
75 16 100       42 $n = 1 if !defined $n;
76 16 100       61 die "Please specify a positive number of words to pick" if $n < 1;
77              
78 12 100       26 if ($n == 1) {
79 4         4 my $i = 0;
80 4         7 my $word;
81             # algorithm from Learning Perl
82             $self->each_word(
83             sub {
84 8     8   12 $i++;
85 8 100       63 $word = $_[0] if rand($i) < 1;
86             }
87 4         24 );
88 4         18 return $word;
89             }
90              
91 8         11 my $i = 0;
92 8         11 my @words;
93             $self->each_word(
94             sub {
95 16     16   17 $i++;
96 16 50       29 if (@words < $n) {
97             # we haven't reached $n, put word to result in a random position
98 16         51 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         49 );
106 8         49 @words;
107             }
108              
109             sub word_exists {
110 16     16 1 8144 my ($self, $word) = @_;
111              
112 16         19 my $found = 0;
113             $self->each_word(
114             sub {
115 24 100   24   67 if ($word eq $_[0]) {
116 8         11 $found = 1;
117 8         15 return -2;
118             }
119             }
120 16         74 );
121 16         70 $found;
122             }
123              
124             sub all_words {
125 4     4 1 9573 my ($self) = @_;
126              
127 4         7 my @words;
128             $self->each_word(
129             sub {
130 8     8   19 push @words, $_[0];
131             }
132 4         20 );
133 4         23 @words;
134             }
135              
136             1;
137             # ABSTRACT: Specification and base class for WordList::*, modules that contain word list
138              
139             __END__