File Coverage

blib/lib/KinoSearch1/Util/Class.pm
Criterion Covered Total %
statement 83 85 97.6
branch 7 10 70.0
condition 1 3 33.3
subroutine 23 24 95.8
pod 9 9 100.0
total 123 131 93.8


line stmt bran cond sub pod time code
1             package KinoSearch1::Util::Class;
2 50     50   57833 use strict;
  50         210  
  50         1899  
3 50     50   263 use warnings;
  50         85  
  50         1221  
4 50     50   834 use KinoSearch1::Util::ToolSet;
  50         74  
  50         7780  
5              
6 50     50   312 use KinoSearch1::Util::VerifyArgs qw( verify_args kerror );
  50         90  
  50         4414  
7              
8             sub new {
9 5955     5955 1 1605422 my $class = shift; # leave the rest of @_ intact.
10              
11             # find a defaults hash and verify args
12 5955   33     22270 $class = ref($class) || $class;
13 5955         13232 my $defaults;
14             {
15 50     50   278 no strict 'refs';
  50         87  
  50         5443  
  5955         7998  
16 5955         6538 $defaults = \%{ $class . '::instance_vars' };
  5955         24013  
17             }
18 5955 100       19360 if ( !verify_args( $defaults, @_ ) ) {
19             # if a user-based subclass, find KinoSearch1 parent class and verify.
20 1         6 my $kinoclass = _traverse_at_isa($class);
21 1 50       4 confess kerror() unless $kinoclass;
22             {
23 50     50   268 no strict 'refs';
  50         80  
  50         7307  
  1         2  
24 1         2 $defaults = \%{ $kinoclass . '::instance_vars' };
  1         6  
25             }
26 1 50       4 confess kerror() unless verify_args( $defaults, @_ );
27             }
28              
29             # merge var => val pairs into new object, call customizable init routine
30 5955         54703 my $self = bless { %$defaults, @_ }, $class;
31 5955         26199 $self->init_instance;
32              
33 5954         29982 return $self;
34             }
35              
36             # Walk @ISA until a parent class starting with 'KinoSearch1::' is found.
37             sub _traverse_at_isa {
38 2     2   6 my $orig = shift;
39             {
40 50     50   311 no strict 'refs';
  50         93  
  50         8700  
  2         3  
41 2         2 my $at_isa = \@{ $orig . '::ISA' };
  2         12  
42 2         6 for my $parent (@$at_isa) {
43 2 100       11 return $parent if $parent =~ /^KinoSearch1::/;
44 1         5 my $grand_parent = _traverse_at_isa($parent);
45 1 50       4 return $grand_parent if $grand_parent;
46             }
47             };
48 1         3 return '';
49             }
50              
51 1407     1407 1 2247 sub init_instance { }
52              
53             sub init_instance_vars {
54 1875     1875 1 4079 my $package = shift;
55              
56 50     50   283 no strict 'refs';
  50         87  
  50         1672  
57 50     50   272 no warnings 'once';
  50         101  
  50         7626  
58 1875         2471 my $first_isa = ${ $package . '::ISA' }[0];
  1875         8018  
59 1875         209658 %{ $package . '::instance_vars' }
  1875         7519  
60 1875         2458 = ( %{ $first_isa . '::instance_vars' }, @_ );
61             }
62              
63             sub ready_get_set {
64 244     244 1 997 ready_get(@_);
65 244         1169 ready_set(@_);
66             }
67              
68             sub ready_get {
69 533     533 1 2790 my $package = shift;
70 50     50   275 no strict 'refs';
  50         92  
  50         7428  
71 533         1544 for my $member (@_) {
72 1462     298099   5871 *{ $package . "::get_$member" } = sub { return $_[0]->{$member} };
  1462         26371  
  298099         1212410  
73             }
74             }
75              
76             sub ready_set {
77 244     244 1 999 my $package = shift;
78 50     50   265 no strict 'refs';
  50         161  
  50         16133  
79 244         715 for my $member (@_) {
80 841     47182   3247 *{ $package . "::set_$member" } = sub { $_[0]->{$member} = $_[1] };
  841         35000  
  47182         156075  
81             }
82             }
83              
84             =for Rationale:
85             KinoSearch1 is not thread-safe. Among other things, the C-struct-based classes
86             cause segfaults or bus errors when their data gets double-freed by DESTROY.
87             Therefore, CLONE dies with a user-friendly error message before that happens.
88              
89             =cut
90              
91             sub CLONE {
92 0     0   0 my $package = shift;
93 0         0 die( "CLONE invoked by package '$package', indicating that threads "
94             . "or Win32 fork were initiated, but KinoSearch1 is not thread-safe"
95             );
96             }
97              
98             sub abstract_death {
99 1     1 1 508 my ( undef, $filename, $line, $methodname ) = caller(1);
100 1         16 die "ERROR: $methodname', called at $filename line $line, is an "
101             . "abstract method and must be defined in a subclass";
102             }
103              
104             sub unimplemented_death {
105 1     1 1 10479 my ( undef, $filename, $line, $methodname ) = caller(1);
106 1         19 die "ERROR: $methodname, called at $filename line $line, is "
107             . "intentionally unimplemented in KinoSearch1, though it is part "
108             . "of Lucene";
109             }
110              
111             sub todo_death {
112 1     1 1 664 my ( undef, $filename, $line, $methodname ) = caller(1);
113 1         13 die "ERROR: $methodname, called at $filename line $line, is not "
114             . "implemented yet in KinoSearch1, but is on the todo list";
115             }
116              
117             1;
118              
119             __END__