File Coverage

blib/lib/WordList.pm
Criterion Covered Total %
statement 73 74 98.6
branch 21 26 80.7
condition 2 3 66.6
subroutine 15 15 100.0
pod 8 8 100.0
total 119 126 94.4


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