| 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__ |