/usr/lib/perl5/KinoSearch1/Util/Class.pm is in libkinosearch1-perl 1.00-1build3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | package KinoSearch1::Util::Class;
use strict;
use warnings;
use KinoSearch1::Util::ToolSet;
use KinoSearch1::Util::VerifyArgs qw( verify_args kerror );
sub new {
my $class = shift; # leave the rest of @_ intact.
# find a defaults hash and verify args
$class = ref($class) || $class;
my $defaults;
{
no strict 'refs';
$defaults = \%{ $class . '::instance_vars' };
}
if ( !verify_args( $defaults, @_ ) ) {
# if a user-based subclass, find KinoSearch1 parent class and verify.
my $kinoclass = _traverse_at_isa($class);
confess kerror() unless $kinoclass;
{
no strict 'refs';
$defaults = \%{ $kinoclass . '::instance_vars' };
}
confess kerror() unless verify_args( $defaults, @_ );
}
# merge var => val pairs into new object, call customizable init routine
my $self = bless { %$defaults, @_ }, $class;
$self->init_instance;
return $self;
}
# Walk @ISA until a parent class starting with 'KinoSearch1::' is found.
sub _traverse_at_isa {
my $orig = shift;
{
no strict 'refs';
my $at_isa = \@{ $orig . '::ISA' };
for my $parent (@$at_isa) {
return $parent if $parent =~ /^KinoSearch1::/;
my $grand_parent = _traverse_at_isa($parent);
return $grand_parent if $grand_parent;
}
};
return '';
}
sub init_instance { }
sub init_instance_vars {
my $package = shift;
no strict 'refs';
no warnings 'once';
my $first_isa = ${ $package . '::ISA' }[0];
%{ $package . '::instance_vars' }
= ( %{ $first_isa . '::instance_vars' }, @_ );
}
sub ready_get_set {
ready_get(@_);
ready_set(@_);
}
sub ready_get {
my $package = shift;
no strict 'refs';
for my $member (@_) {
*{ $package . "::get_$member" } = sub { return $_[0]->{$member} };
}
}
sub ready_set {
my $package = shift;
no strict 'refs';
for my $member (@_) {
*{ $package . "::set_$member" } = sub { $_[0]->{$member} = $_[1] };
}
}
=for Rationale:
KinoSearch1 is not thread-safe. Among other things, the C-struct-based classes
cause segfaults or bus errors when their data gets double-freed by DESTROY.
Therefore, CLONE dies with a user-friendly error message before that happens.
=cut
sub CLONE {
my $package = shift;
die( "CLONE invoked by package '$package', indicating that threads "
. "or Win32 fork were initiated, but KinoSearch1 is not thread-safe"
);
}
sub abstract_death {
my ( undef, $filename, $line, $methodname ) = caller(1);
die "ERROR: $methodname', called at $filename line $line, is an "
. "abstract method and must be defined in a subclass";
}
sub unimplemented_death {
my ( undef, $filename, $line, $methodname ) = caller(1);
die "ERROR: $methodname, called at $filename line $line, is "
. "intentionally unimplemented in KinoSearch1, though it is part "
. "of Lucene";
}
sub todo_death {
my ( undef, $filename, $line, $methodname ) = caller(1);
die "ERROR: $methodname, called at $filename line $line, is not "
. "implemented yet in KinoSearch1, but is on the todo list";
}
1;
__END__
=begin devdocs
=head1 NAME
KinoSearch1::Util::Class - class building utility
=head1 SYNOPSIS
package KinoSearch1::SomePackage::SomeClass;
use base qw( KinoSearch1::Util::Class );
BEGIN {
__PACKAGE__->init_instance_vars(
# constructor params / members
foo => undef,
bar => {},
# members
baz => {},
);
}
=head1 DESCRIPTION
KinoSearch1::Util::Class is a class-building utility a la
L<Class::Accessor|Class::Accessor>, L<Class::Meta|Class::Meta>, etc. It
provides four main services:
=over
=item 1
A mechanism for inheriting instance variable declarations.
=item 2
A constructor with basic argument checking.
=item 3
Manufacturing of get_xxxx and set_xxxx methods.
=item 4
Convenience methods which help in defining abstract classes.
=back
=head1 VARIABLES
=head2 %instance_vars
The %instance_vars hash, which is always a package global, serves as a
template for the creation of a hash-based object. It is built up from all the
%instance_vars hashes in the module's parent classes, using
init_instance_vars().
Key-value pairs in an %instance_vars hash are labeled as "constructor params"
and/or "members". Items which are labeled as constructor params can be used
as arguments to new().
BEGIN {
__PACKAGE__->init_instance_vars(
# constructor params / members
foo => undef,
bar => 10,
# members
baz => '',
);
}
# ok: specifies foo, uses default for bar, derives baz
my $object = __PACKAGE__->new( foo => $foo );
# not ok: baz isn't a constructor param
my $object = __PACKAGE__->new( baz => $baz );
# ok if a parent class defines boffo as a constructor param
my $object = __PACKAGE__->new(
foo => $foo,
boffo => $boffo,
);
%instance_vars may only contain scalar values, as the defaults are merged
into the object using a shallow copy.
init_instance_vars() must be called from within a BEGIN block and before any
C<use> directives load a child class -- if children are born before their
parents, inheritance gets screwed up.
=head1 METHODS
=head2 new
A generic constructor with basic argument checking. new() expects hash-style
labeled parameters; the label names must be present in the %instance_vars
hash, or it will croak().
After verifying the labeled parameters, new() merges %instance_vars and @_
into a new object. It then calls $self->init_instance() before returning the
blessed reference.
=head2 init_instance
$self->init_instance();
Perform customized initialization routine. By default, this is a no-op.
=head2 init_instance_vars
BEGIN {
__PACKAGE__->init_instance_vars(
a_safe_variable_name_that_wont_clash => 1,
freep_warble => undef,
);
}
Package method only. Creates a package global %instance_vars hash in the
passed in package which consists of the passed in arguments plus all the
key-value pairs in the parent class's %instance_vars hash.
=head2 ready_get_set ready_get ready_set
# create get_foo(), set_foo(), get_bar(), set_bar() in __PACKAGE__
BEGIN { __PACKAGE__->ready_get_set(qw( foo bar )) };
Mass manufacture getters and setters. The setters do not return a meaningful
value.
=head2 abstract_death unimplemented_death todo_death
sub an_abstract_method { shift->abstract_death }
sub an_unimplemented_method { shift->unimplemented_death }
sub maybe_someday { shift->todo_death }
These are just different ways to die(), and are of little interest until your
particular application comes face to face with one of them.
abstract_death indicates that a method must be defined in a subclass.
unimplemented_death indicates a feature/function that will probably not be
implemented. Typically, this would appear for a sub that a developer
intimately familiar with Lucene would expect to find.
todo_death indicates a feature that might get implemented someday.
=head1 COPYRIGHT
Copyright 2005-2010 Marvin Humphrey
=head1 LICENSE, DISCLAIMER, BUGS, etc.
See L<KinoSearch1> version 1.00.
=end devdocs
=cut
|