File Coverage

blib/lib/Getopt/Yath/HashBase.pm
Criterion Covered Total %
statement 143 160 89.3
branch 51 70 72.8
condition 11 21 52.3
subroutine 21 24 87.5
pod 1 4 25.0
total 227 279 81.3


line stmt bran cond sub pod time code
1             package Getopt::Yath::HashBase;
2 2     2   133189 use strict;
  2         5  
  2         78  
3 2     2   11 use warnings;
  2         3  
  2         212  
4              
5             our $VERSION = '2.000007';
6              
7             #################################################################
8             # #
9             # This is a generated file! Do not modify this file directly! #
10             # Use hashbase_inc.pl script to regenerate this file. #
11             # The script is part of the Object::HashBase distribution. #
12             # Note: You can modify the version number above this comment #
13             # if needed, that is fine. #
14             # #
15             #################################################################
16              
17             {
18 2     2   10 no warnings 'once';
  2         5  
  2         272  
19             $Getopt::Yath::HashBase::HB_VERSION = '0.015';
20             *Getopt::Yath::HashBase::ATTR_SUBS = \%Object::HashBase::ATTR_SUBS;
21             *Getopt::Yath::HashBase::ATTR_LIST = \%Object::HashBase::ATTR_LIST;
22             *Getopt::Yath::HashBase::VERSION = \%Object::HashBase::VERSION;
23             *Getopt::Yath::HashBase::CAN_CACHE = \%Object::HashBase::CAN_CACHE;
24             }
25              
26              
27             require Carp;
28             {
29 2     2   14 no warnings 'once';
  2         5  
  2         429  
30             $Carp::Internal{+__PACKAGE__} = 1;
31             }
32              
33             BEGIN {
34             {
35             # Make sure none of these get messed up.
36 2     2   6 local ($SIG{__DIE__}, $@, $?, $!, $^E);
  2         23  
37 2 50       4 if (eval { require Class::XSAccessor; Class::XSAccessor->VERSION(1.19); 1 }) {
  2         1167  
  2         5864  
  2         10  
38             *CLASS_XS_ACCESSOR = sub() { 1 }
39 2         38 }
40             else {
41             *CLASS_XS_ACCESSOR = sub() { 0 }
42 0         0 }
43             }
44              
45             # these are not strictly equivalent, but for out use we don't care
46             # about order
47             *_isa = ($] >= 5.010 && require mro) ? \&mro::get_linear_isa : sub {
48 2     2   12 no strict 'refs';
  2         4  
  2         306  
49 0         0 my @packages = ($_[0]);
50 0         0 my %seen;
51 0         0 for my $package (@packages) {
52 0         0 push @packages, grep !$seen{$_}++, @{"$package\::ISA"};
  0         0  
53             }
54 0         0 return \@packages;
55             }
56 2 50 33     1014 }
57              
58             my %SPEC = (
59             '^' => {reader => 1, writer => 0, dep_writer => 1, read_only => 0, strip => 1},
60             '-' => {reader => 1, writer => 0, dep_writer => 0, read_only => 1, strip => 1},
61             '>' => {reader => 0, writer => 1, dep_writer => 0, read_only => 0, strip => 1},
62             '<' => {reader => 1, writer => 0, dep_writer => 0, read_only => 0, strip => 1},
63             '+' => {reader => 0, writer => 0, dep_writer => 0, read_only => 0, strip => 1},
64             '~' => {reader => 1, writer => 1, dep_writer => 0, read_only => 0, strip => 1, no_xs => 1},
65             );
66              
67 73     73 0 237 sub spec { \%SPEC }
68              
69             sub import {
70 21     21   16633 my $class = shift;
71 21         51 my $into = caller;
72 21         98 $class->do_import($into, @_);
73             }
74              
75             sub do_import {
76 21     21 0 30 my $class = shift;
77 21         34 my $into = shift;
78              
79             # Make sure we list the OLDEST version used to create this class.
80 21   33     69 my $ver = $Getopt::Yath::HashBase::HB_VERSION || $Getopt::Yath::HashBase::VERSION;
81 21 50 33     96 $Getopt::Yath::HashBase::VERSION{$into} = $ver if !$Getopt::Yath::HashBase::VERSION{$into} || $Getopt::Yath::HashBase::VERSION{$into} > $ver;
82              
83 21         129 my $isa = _isa($into);
84 21   50     110 my $attr_list = $Getopt::Yath::HashBase::ATTR_LIST{$into} ||= [];
85 21   50     85 my $attr_subs = $Getopt::Yath::HashBase::ATTR_SUBS{$into} ||= {};
86              
87 21         33 my @pre_init;
88             my @post_init;
89              
90 21         32 my $add_new = 1;
91              
92 21 100       193 if (my $have_new = $into->can('new')) {
93 12   50     52 my $new_lookup = $Getopt::Yath::HashBase::NEW_LOOKUP //= {};
94 12 100       60 $add_new = 0 unless $new_lookup->{$have_new};
95             }
96              
97             my %subs = (
98             ($add_new ? ($class->_build_new($into, \@pre_init, \@post_init)) : ()),
99 21 100       98 (map %{$Getopt::Yath::HashBase::ATTR_SUBS{$_} || {}}, @{$isa}[1 .. $#$isa]),
  14 50       169  
  21         73  
100             ($class->args_to_subs($attr_list, $attr_subs, \@_, $into)),
101             );
102              
103 2     2   17 no strict 'refs';
  2         3  
  2         2978  
104 21         117 while (my ($k, $v) = each %subs) {
105 544 100       804 if (ref($v) eq 'CODE') {
106 458         466 *{"$into\::$k"} = $v;
  458         11079  
107             }
108             else {
109 86         191 my ($sub, @args) = @$v;
110 86         1435 $sub->(@args);
111             }
112             }
113             }
114              
115             sub args_to_subs {
116 21     21 0 36 my $class = shift;
117 21         53 my ($attr_list, $attr_subs, $args, $into) = @_;
118              
119 21         78 my $use_gen = $class->can('gen_accessor') ;
120              
121 21         31 my %out;
122              
123 21         57 while (@$args) {
124 73         137 my $x = shift @$args;
125 73         148 my $p = substr($x, 0, 1);
126              
127 73   100     120 my $spec = $class->spec->{$p} || {reader => 1, writer => 1};
128 73 100       160 substr($x, 0, 1) = '' if $spec->{strip};
129              
130 73         143 push @$attr_list => $x;
131 73         142 my ($sub, $attr) = (uc $x, $x);
132              
133 73     0   487 $attr_subs->{$sub} = sub() { $attr };
  0         0  
134 73         167 $out{$sub} = $attr_subs->{$sub};
135              
136 73         106 my $copy = "$attr";
137 73 100       135 if ($spec->{reader}) {
138 63 50       150 if ($use_gen) {
    50          
139 0         0 $out{$attr} = $class->gen_accessor(reader => $copy, $spec, $args);
140             }
141             elsif (CLASS_XS_ACCESSOR && !$spec->{no_xs}) {
142 63         224 $out{$attr} = [\&Class::XSAccessor::newxs_getter, "$into\::$attr", $copy];
143             }
144             else {
145 0     0   0 $out{$attr} = sub { $_[0]->{$attr} };
  0         0  
146             }
147             }
148              
149 73 100       212 if ($spec->{writer}) {
    100          
    100          
150 23 50       58 if ($use_gen) {
    50          
151 0         0 $out{"set_$attr"} = $class->gen_accessor(writer => $copy, $spec, $args);
152             }
153             elsif(CLASS_XS_ACCESSOR && !$spec->{no_xs}) {
154 23         118 $out{"set_$attr"} = [\&Class::XSAccessor::newxs_setter, "$into\::set_$attr", $copy, 0];
155             }
156             else {
157 0     0   0 $out{"set_$attr"} = sub { $_[0]->{$attr} = $_[1] };
  0         0  
158             }
159             }
160             elsif($spec->{read_only}) {
161 1 50   1   8 $out{"set_$attr"} = $use_gen ? $class->gen_accessor(read_only => $copy, $spec, $args) : sub { Carp::croak("'$attr' is read-only") };
  1         8955  
162             }
163             elsif($spec->{dep_writer}) {
164 1 50   1   6 $out{"set_$attr"} = $use_gen ? $class->gen_accessor(dep_writer => $copy, $spec, $args) : sub { Carp::carp("set_$attr() is deprecated"); $_[0]->{$attr} = $_[1] };
  1         1024  
  1         14  
165             }
166              
167 73 50       208 if ($spec->{custom}) {
168 0         0 my %add = $class->gen_accessor(custom => $copy, $spec, $args);
169 0         0 $out{$_} = $add{$_} for keys %add;
170             }
171             }
172              
173 21         204 return %out;
174             }
175              
176             sub attr_list {
177 3     3 1 1775 my $class = shift;
178              
179 3         16 my $isa = _isa($class);
180              
181 3         5 my %seen;
182 15         41 my @list = grep { !$seen{$_}++ } map {
183 3         9 my @out;
  6         11  
184              
185 6 50 50     30 if (0.004 > ($Getopt::Yath::HashBase::VERSION{$_} || 0)) {
186 0         0 Carp::carp("$_ uses an inlined version of Getopt::Yath::HashBase too old to support attr_list()");
187             }
188             else {
189 6         13 my $list = $Getopt::Yath::HashBase::ATTR_LIST{$_};
190 6 50       25 @out = $list ? @$list : ()
191             }
192              
193 6         18 @out;
194             } reverse @$isa;
195              
196 3         22 return @list;
197             }
198              
199             sub _build_new {
200 20     20   37 my $class = shift;
201 20         46 my ($into, $pre_init, $post_init) = @_;
202              
203 20     3   102 my $add_pre_init = sub(&) { push @$pre_init => $_[-1] };
  3         235231  
204 20     4   134 my $add_post_init = sub(&) { push @$post_init => $_[-1] };
  4         4930  
205              
206 20         127 my $__pre_init = $into->can('_pre_init');
207 20 100   26   75 my $_pre_init = $__pre_init ? sub { ($__pre_init->(), @$pre_init) } : sub { @$pre_init };
  26         61  
  29         101  
208              
209 20         92 my $__post_init = $into->can('_post_init');
210 20 100   28   80 my $_post_init = $__post_init ? sub { ($__post_init->(), @$post_init) } : sub { @$post_init };
  24         50  
  28         86  
211              
212             my $new = sub {
213 30     30   18700 my $class = shift;
214              
215 30         48 my $self;
216              
217 30 100       102 if (@_ == 1) {
218 3         6 my $arg = shift;
219 3         9 my $type = ref($arg);
220              
221 3 100       9 if ($type eq 'HASH') {
222 1         6 $self = bless({%$arg}, $class);
223             }
224             else {
225 2 50       12 Carp::croak("Not sure what to do with '$type' in $class constructor")
226             unless $type eq 'ARRAY';
227              
228 2         4 my %proto;
229 2         7 my @attributes = attr_list($class);
230 2         8 while (@$arg) {
231 9         19 my $val = shift @$arg;
232 9 100       191 my $key = shift @attributes or Carp::croak("Too many arguments for $class constructor");
233 8         22 $proto{$key} = $val;
234             }
235              
236 1         4 $self = bless(\%proto, $class);
237             }
238             }
239             else {
240 27         119 $self = bless({@_}, $class);
241             }
242              
243             $Getopt::Yath::HashBase::CAN_CACHE{$class} = $self->can('init')
244 29 100       188 unless exists $Getopt::Yath::HashBase::CAN_CACHE{$class};
245              
246 29         113 $self->$_() for $_pre_init->();
247 29 100       161 $self->init() if $Getopt::Yath::HashBase::CAN_CACHE{$class};
248 28         81 $self->$_() for reverse $_post_init->();
249              
250 28         141 $self;
251 20         131 };
252              
253 20   100     61 my $new_lookup = $Getopt::Yath::HashBase::NEW_LOOKUP //= {};
254 20         60 $new_lookup->{$new} = 1;
255              
256 20         34 my %out;
257              
258             {
259 2     2   17 no strict 'refs';
  2         3  
  2         496  
  20         4097  
260 20 50       31 $out{new} = $new unless defined(&{"${into}\::new"});
  20         108  
261 20 50       27 $out{add_pre_init} = $add_pre_init unless defined(&{"${into}\::add_pre_init"});
  20         120  
262 20 50       29 $out{add_post_init} = $add_post_init unless defined(&{"${into}\::add_post_init"});
  20         87  
263 20 50       29 $out{_pre_init} = $_pre_init unless defined(&{"${into}\::_pre_init"});
  20         66  
264 20 50       29 $out{_post_init} = $_post_init unless defined(&{"${into}\::_post_init"});
  20         67  
265             }
266              
267 20         133 return %out;
268             }
269              
270             1;
271              
272             __END__