← Index
NYTProf Performance Profile   « block view • line view • sub view »
For /usr/bin/epoll_server.pl
  Run on Wed Jan 5 05:34:33 2011
Reported on Wed Jan 5 05:35:59 2011

File /usr/lib/perl5/vendor_perl/5.10.1/i386-linux-thread-multi/Moose/Util.pm
Statements Executed 3176
Statement Execution Time 37.3ms
Subroutines — ordered by exclusive time
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
110510713.2ms37.7msMoose::Util::::find_metaMoose::Util::find_meta
130335.83ms56.6msMoose::Util::::does_roleMoose::Util::does_role
37115.40ms1.58sMoose::Util::::_apply_all_rolesMoose::Util::_apply_all_roles
100223.36ms3.36msMoose::Util::::_caller_infoMoose::Util::_caller_info
34111.07ms16.3msMoose::Util::::resolve_metaclass_aliasMoose::Util::resolve_metaclass_alias
1731863µs25.0msMoose::Util::::add_method_modifierMoose::Util::add_method_modifier
3421777µs17.1msMoose::Util::::resolve_metatrait_aliasMoose::Util::resolve_metatrait_alias
3744707µs1.58sMoose::Util::::apply_all_rolesMoose::Util::apply_all_roles
111146µs324µsMoose::Util::::BEGIN@8Moose::Util::BEGIN@8
111109µs125µsMoose::Util::::BEGIN@3Moose::Util::BEGIN@3
11173µs91µsMoose::Util::::BEGIN@6Moose::Util::BEGIN@6
11137µs169µsMoose::Util::::BEGIN@9Moose::Util::BEGIN@9
11133µs98µsMoose::Util::::BEGIN@4Moose::Util::BEGIN@4
11132µs784µsMoose::Util::::BEGIN@7Moose::Util::BEGIN@7
11116µs16µsMoose::Util::::_build_alias_package_nameMoose::Util::_build_alias_package_name
0000s0sMoose::Util::::__ANON__[:257]Moose::Util::__ANON__[:257]
0000s0sMoose::Util::::__ANON__[:81]Moose::Util::__ANON__[:81]
0000s0sMoose::Util::::_create_aliasMoose::Util::_create_alias
0000s0sMoose::Util::::english_listMoose::Util::english_list
0000s0sMoose::Util::::ensure_all_rolesMoose::Util::ensure_all_roles
0000s0sMoose::Util::::get_all_attribute_valuesMoose::Util::get_all_attribute_values
0000s0sMoose::Util::::get_all_init_argsMoose::Util::get_all_init_args
0000s0sMoose::Util::::meta_attribute_aliasMoose::Util::meta_attribute_alias
0000s0sMoose::Util::::meta_class_aliasMoose::Util::meta_class_alias
0000s0sMoose::Util::::search_class_by_roleMoose::Util::search_class_by_role
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package Moose::Util;
2
3394µs2142µs
# spent 125µs (109+16) within Moose::Util::BEGIN@3 which was called # once (109µs+16µs) by Moose::Meta::Attribute::BEGIN@17 at line 3
use strict;
# spent 125µs making 1 call to Moose::Util::BEGIN@3 # spent 16µs making 1 call to strict::import
4390µs2163µs
# spent 98µs (33+65) within Moose::Util::BEGIN@4 which was called # once (33µs+65µs) by Moose::Meta::Attribute::BEGIN@17 at line 4
use warnings;
# spent 98µs making 1 call to Moose::Util::BEGIN@4 # spent 65µs making 1 call to warnings::import
5
6393µs2109µs
# spent 91µs (73+18) within Moose::Util::BEGIN@6 which was called # once (73µs+18µs) by Moose::Meta::Attribute::BEGIN@17 at line 6
use Data::OptList;
# spent 91µs making 1 call to Moose::Util::BEGIN@6 # spent 18µs making 1 call to Sub::Install::__ANON__[Sub/Install.pm:284]
73268µs21.54ms
# spent 784µs (32+753) within Moose::Util::BEGIN@7 which was called # once (32µs+753µs) by Moose::Meta::Attribute::BEGIN@17 at line 7
use Sub::Exporter;
# spent 784µs making 1 call to Moose::Util::BEGIN@7 # spent 752µs making 1 call to Sub::Exporter::__ANON__[Sub/Exporter.pm:756]
8395µs2503µs
# spent 324µs (146+178) within Moose::Util::BEGIN@8 which was called # once (146µs+178µs) by Moose::Meta::Attribute::BEGIN@17 at line 8
use Scalar::Util 'blessed';
# spent 324µs making 1 call to Moose::Util::BEGIN@8 # spent 178µs making 1 call to Exporter::import
935.03ms2301µs
# spent 169µs (37+132) within Moose::Util::BEGIN@9 which was called # once (37µs+132µs) by Moose::Meta::Attribute::BEGIN@17 at line 9
use Class::MOP 0.60;
# spent 169µs making 1 call to Moose::Util::BEGIN@9 # spent 132µs making 1 call to UNIVERSAL::VERSION
10
1114µsour $VERSION = '1.01';
12150µs$VERSION = eval $VERSION;
1313µsour $AUTHORITY = 'cpan:STEVAN';
14
15111µsmy @exports = qw[
16 find_meta
17 does_role
18 search_class_by_role
19 ensure_all_roles
20 apply_all_roles
21 get_all_init_args
22 get_all_attribute_values
23 resolve_metatrait_alias
24 resolve_metaclass_alias
25 add_method_modifier
26 english_list
27 meta_attribute_alias
28 meta_class_alias
29];
30
31120µs12.45msSub::Exporter::setup_exporter({
# spent 2.45ms making 1 call to Sub::Exporter::setup_exporter
32 exports => \@exports,
33 groups => { all => \@exports }
34});
35
36## some utils for the utils ...
37
38110513.3ms110524.6ms
# spent 37.7ms (13.2+24.6) within Moose::Util::find_meta which was called 1105 times, avg 34µs/call: # 801 times (9.41ms+17.9ms) by Catalyst::Component::__config_accessor or Catalyst::Component::__plugins_accessor or Catalyst::Controller::__action_class_accessor or Catalyst::Controller::__dispatch_steps_accessor or Catalyst::_arguments_accessor or Catalyst::_components_accessor or Catalyst::_context_class_accessor or Catalyst::_dispatcher_accessor or Catalyst::_dispatcher_class_accessor or Catalyst::_engine_accessor or Catalyst::_engine_class_accessor or Catalyst::_log_accessor or Catalyst::_request_class_accessor or Catalyst::_response_class_accessor or Catalyst::_setup_finished_accessor or Catalyst::_stats_class_accessor at line 16 of Catalyst/ClassData.pm, avg 34µs/call # 130 times (1.41ms+2.89ms) by Moose::Util::does_role at line 45, avg 33µs/call # 45 times (420µs+801µs) by MooseX::MethodAttributes::Role::Meta::Class::get_all_methods_with_attributes at line 48 of MooseX/MethodAttributes/Role/Meta/Class.pm, avg 27µs/call # 42 times (587µs+1.16ms) by MooseX::MethodAttributes::init_meta at line 22 of MooseX/MethodAttributes.pm, avg 42µs/call # 35 times (364µs+710µs) by MooseX::MethodAttributes::Role::AttrContainer::MODIFY_CODE_ATTRIBUTES at line 13 of MooseX/MethodAttributes/Role/AttrContainer.pm, avg 31µs/call # 30 times (355µs+509µs) by Catalyst::_controller_init_base_classes at line 2488 of Catalyst.pm, avg 29µs/call # 7 times (302µs+241µs) by Catalyst::setup_plugins at line 2814 of Catalyst.pm, avg 78µs/call # 7 times (211µs+128µs) by Catalyst::Controller::get_action_methods at line 184 of Catalyst/Controller.pm, avg 48µs/call # 7 times (87µs+140µs) by Catalyst::setup_plugins at line 2822 of Catalyst.pm, avg 32µs/call # once (16µs+70µs) by Moose::Util::_apply_all_roles at line 128
sub find_meta { Class::MOP::class_of(@_) }
# spent 24.6ms making 1105 calls to Class::MOP::class_of, avg 22µs/call
39
40## the functions ...
41
42
# spent 56.6ms (5.83+50.8) within Moose::Util::does_role which was called 130 times, avg 435µs/call: # 106 times (3.93ms+49.9ms) by MooseX::MethodAttributes::init_meta at line 24 of MooseX/MethodAttributes.pm, avg 508µs/call # 12 times (1.42ms+424µs) by Class::MOP::Class:::around at line 78 of MooseX/MethodAttributes/Role/Meta/Class.pm, avg 153µs/call # 12 times (485µs+388µs) by MooseX::MethodAttributes::Role::Meta::Method::MaybeWrapped::__ANON__[/usr/lib/perl5/vendor_perl/5.10.1/MooseX/MethodAttributes/Role/Meta/Method/MaybeWrapped.pm:21] at line 14 of MooseX/MethodAttributes/Role/Meta/Method/MaybeWrapped.pm, avg 73µs/call
sub does_role {
436245.12ms my ($class_or_obj, $role) = @_;
44
45 my $meta = find_meta($class_or_obj);
# spent 4.30ms making 130 calls to Moose::Util::find_meta, avg 33µs/call
46
47 return unless defined $meta;
48 return unless $meta->can('does_role');
# spent 620µs making 130 calls to UNIVERSAL::can, avg 5µs/call
49 return 1 if $meta->does_role($role);
# spent 45.8ms making 104 calls to Moose::Meta::Class::does_role, avg 441µs/call
50 return;
51}
52
53sub search_class_by_role {
54 my ($class_or_obj, $role) = @_;
55
56 my $meta = find_meta($class_or_obj);
57
58 return unless defined $meta;
59
60 my $role_name = blessed $role ? $role->name : $role;
61
62 foreach my $class ($meta->class_precedence_list) {
63
64 my $_meta = find_meta($class);
65
66 next unless defined $_meta;
67
68 foreach my $role (@{ $_meta->roles || [] }) {
69 return $class if $role->name eq $role_name;
70 }
71 }
72
73 return;
74}
75
76# this can possibly behave in unexpected ways because the roles being composed
77# before being applied could differ from call to call; I'm not sure if or how
78# to document this possible quirk.
79sub ensure_all_roles {
80 my $applicant = shift;
81 _apply_all_roles($applicant, sub { !does_role($applicant, $_) }, @_);
82}
83
84
# spent 1.58s (707µs+1.58) within Moose::Util::apply_all_roles which was called 37 times, avg 42.7ms/call: # 17 times (263µs+1.22s) by Moose::with at line 57 of Moose.pm, avg 71.5ms/call # 11 times (184µs+119ms) by Moose::Role::with at line 26 of Moose/Role.pm, avg 10.8ms/call # 8 times (240µs+157ms) by Moose::Meta::Class::create at line 94 of Moose/Meta/Class.pm, avg 19.7ms/call # once (20µs+85.4ms) by Catalyst::setup_plugins at line 2826 of Catalyst.pm
sub apply_all_roles {
8574802µs my $applicant = shift;
86174µs381.58s _apply_all_roles($applicant, undef, @_);
# spent 2.30s making 37 calls to Moose::Util::_apply_all_roles, avg 62.2ms/call, recursion: max depth 2, time 725ms # spent 55µs making 1 call to Class::MOP::Class::DESTROY
87}
88
89
# spent 1.58s (5.40ms+1.57) within Moose::Util::_apply_all_roles which was called 37 times, avg 42.6ms/call: # 37 times (5.40ms+1.57s) by Moose::Util::apply_all_roles at line 86, avg 42.6ms/call
sub _apply_all_roles {
906865.71ms my $applicant = shift;
91 my $role_filter = shift;
92
93 unless (@_) {
94 require Moose;
95 Moose->throw_error("Must specify at least one role to apply to $applicant");
96 }
97
98 my $roles = Data::OptList::mkopt( [@_] );
# spent 2.26ms making 37 calls to Data::OptList::mkopt, avg 61µs/call
99
100 my @role_metas;
101 foreach my $role (@$roles) {
102 my $meta;
103
104 if ( blessed $role->[0] ) {
# spent 253µs making 41 calls to Scalar::Util::blessed, avg 6µs/call
105 $meta = $role->[0];
106 }
107 else {
108 Class::MOP::load_class( $role->[0] );
# spent 1.38s making 41 calls to Class::MOP::load_class, avg 33.6ms/call, recursion: max depth 2, time 646ms
109 $meta = Class::MOP::class_of( $role->[0] );
# spent 1.19ms making 41 calls to Class::MOP::class_of, avg 29µs/call
110 }
111
112 unless ($meta && $meta->isa('Moose::Meta::Role') ) {
# spent 245µs making 41 calls to UNIVERSAL::isa, avg 6µs/call
113 require Moose;
114 Moose->throw_error( "You can only consume roles, "
115 . $role->[0]
116 . " is not a Moose role" );
117 }
118
119 push @role_metas, [ $meta, $role->[1] ];
120 }
121
122 if ( defined $role_filter ) {
123 @role_metas = grep { local $_ = $_->[0]; $role_filter->() } @role_metas;
124 }
125
126 return unless @role_metas;
127
128 my $meta = ( blessed $applicant ? $applicant : find_meta($applicant) );
# spent 183µs making 37 calls to Scalar::Util::blessed, avg 5µs/call # spent 86µs making 1 call to Moose::Util::find_meta
129
130 if ( scalar @role_metas == 1 ) {
131 my ( $role, $params ) = @{ $role_metas[0] };
132 $role->apply( $meta, ( defined $params ? %$params : () ) );
# spent 807ms making 33 calls to Moose::Meta::Role::apply, avg 24.5ms/call
133 }
134 else {
135 Moose::Meta::Role->combine(@role_metas)->apply($meta);
# spent 81.0ms making 4 calls to Moose::Meta::Role::combine, avg 20.3ms/call # spent 28.8ms making 4 calls to Moose::Meta::Role::apply, avg 7.21ms/call
136 }
137}
138
139# instance deconstruction ...
140
141sub get_all_attribute_values {
142 my ($class, $instance) = @_;
143 return +{
144 map { $_->name => $_->get_value($instance) }
145 grep { $_->has_value($instance) }
146 $class->get_all_attributes
147 };
148}
149
150sub get_all_init_args {
151 my ($class, $instance) = @_;
152 return +{
153 map { $_->init_arg => $_->get_value($instance) }
154 grep { $_->has_value($instance) }
155 grep { defined($_->init_arg) }
156 $class->get_all_attributes
157 };
158}
159
160
# spent 17.1ms (777µs+16.3) within Moose::Util::resolve_metatrait_alias which was called 34 times, avg 502µs/call: # 17 times (427µs+15.9ms) by Moose::Meta::Attribute::interpolate_class at line 106 of Moose/Meta/Attribute.pm, avg 959µs/call # 17 times (349µs+436µs) by Moose::Meta::Attribute::__ANON__[/usr/lib/perl5/vendor_perl/5.10.1/i386-linux-thread-multi/Moose/Meta/Attribute.pm:35] at line 34 of Moose/Meta/Attribute.pm, avg 46µs/call
sub resolve_metatrait_alias {
161341.02ms3416.3ms return resolve_metaclass_alias( @_, trait => 1 );
# spent 16.3ms making 34 calls to Moose::Util::resolve_metaclass_alias, avg 480µs/call
162}
163
164
# spent 16µs within Moose::Util::_build_alias_package_name which was called # once (16µs+0s) by Moose::Util::resolve_metaclass_alias at line 183
sub _build_alias_package_name {
165224µs my ($type, $name, $trait) = @_;
166 return 'Moose::Meta::'
167 . $type
168 . '::Custom::'
169 . ( $trait ? 'Trait::' : '' )
170 . $name;
171}
172
173{
17425µs my %cache;
175
176
# spent 16.3ms (1.07+15.2) within Moose::Util::resolve_metaclass_alias which was called 34 times, avg 480µs/call: # 34 times (1.07ms+15.2ms) by Moose::Util::resolve_metatrait_alias at line 161, avg 480µs/call
sub resolve_metaclass_alias {
1771051.07ms my ( $type, $metaclass_name, %options ) = @_;
178
179 my $cache_key = $type . q{ } . ( $options{trait} ? '-Trait' : '' );
180 return $cache{$cache_key}{$metaclass_name}
181 if $cache{$cache_key}{$metaclass_name};
182
183 my $possible_full_name = _build_alias_package_name(
# spent 16µs making 1 call to Moose::Util::_build_alias_package_name
184 $type, $metaclass_name, $options{trait}
185 );
186
187 my $loaded_class = Class::MOP::load_first_existing_class(
# spent 15.2ms making 1 call to Class::MOP::load_first_existing_class, recursion: max depth 1, time 15.2ms
188 $possible_full_name,
189 $metaclass_name
190 );
191
192 return $cache{$cache_key}{$metaclass_name}
# spent 18µs making 1 call to UNIVERSAL::can
193 = $loaded_class->can('register_implementation')
194 ? $loaded_class->register_implementation
195 : $loaded_class;
196 }
197}
198
199
# spent 25.0ms (863µs+24.2) within Moose::Util::add_method_modifier which was called 17 times, avg 1.47ms/call: # 12 times (516µs+17.4ms) by Moose::around at line 81 of Moose.pm, avg 1.49ms/call # 4 times (201µs+5.73ms) by Moose::before at line 73 of Moose.pm, avg 1.48ms/call # once (145µs+1.05ms) by Moose::after at line 77 of Moose.pm
sub add_method_modifier {
200119871µs my ( $class_or_obj, $modifier_name, $args ) = @_;
201 my $meta
# spent 89µs making 17 calls to UNIVERSAL::can, avg 5µs/call
202 = $class_or_obj->can('add_before_method_modifier')
203 ? $class_or_obj
204 : find_meta($class_or_obj);
205 my $code = pop @{$args};
206 my $add_modifier_method = 'add_' . $modifier_name . '_method_modifier';
207 if ( my $method_modifier_type = ref( @{$args}[0] ) ) {
208 if ( $method_modifier_type eq 'Regexp' ) {
209 my @all_methods = $meta->get_all_methods;
210 my @matched_methods
211 = grep { $_->name =~ @{$args}[0] } @all_methods;
212 $meta->$add_modifier_method( $_->name, $code )
213 for @matched_methods;
214 }
215 elsif ($method_modifier_type eq 'ARRAY') {
216 $meta->$add_modifier_method( $_, $code ) for @{$args->[0]};
217 }
218 else {
219 $meta->throw_error(
220 sprintf(
221 "Methods passed to %s must be provided as a list, arrayref or regex, not %s",
222 $modifier_name,
223 $method_modifier_type,
224 )
225 );
226 }
227 }
228 else {
229 $meta->$add_modifier_method( $_, $code ) for @{$args};
# spent 10.9ms making 10 calls to Class::MOP::Class::add_around_method_modifier, avg 1.09ms/call # spent 6.46ms making 2 calls to Class::MOP::Class::__ANON__::SERIAL::5::add_around_method_modifier, avg 3.23ms/call # spent 5.71ms making 4 calls to Class::MOP::Class::add_before_method_modifier, avg 1.43ms/call # spent 1.05ms making 1 call to Class::MOP::Class::add_after_method_modifier
230 }
231}
232
233sub english_list {
234 my @items = sort @_;
235
236 return $items[0] if @items == 1;
237 return "$items[0] and $items[1]" if @items == 2;
238
239 my $tail = pop @items;
240 my $list = join ', ', @items;
241 $list .= ', and ' . $tail;
242
243 return $list;
244}
245
246
# spent 3.36ms within Moose::Util::_caller_info which was called 100 times, avg 34µs/call: # 92 times (3.14ms+0s) by Moose::has at line 67 of Moose.pm, avg 34µs/call # 8 times (218µs+0s) by Moose::Role::has at line 45 of Moose/Role.pm, avg 27µs/call
sub _caller_info {
2474003.54ms my $level = @_ ? ($_[0] + 1) : 2;
248 my %info;
249 @info{qw(package file line)} = caller($level);
250 return \%info;
251}
252
253sub _create_alias {
254 my ($type, $name, $trait, $for) = @_;
255 my $package = _build_alias_package_name($type, $name, $trait);
256 Class::MOP::Class->initialize($package)->add_method(
257 register_implementation => sub { $for }
258 );
259}
260
261sub meta_attribute_alias {
262 my ($to, $from) = @_;
263 $from ||= caller;
264 my $meta = Class::MOP::class_of($from);
265 my $trait = $meta->isa('Moose::Meta::Role');
266 _create_alias('Attribute', $to, $trait, $from);
267}
268
269sub meta_class_alias {
270 my ($to, $from) = @_;
271 $from ||= caller;
272 my $meta = Class::MOP::class_of($from);
273 my $trait = $meta->isa('Moose::Meta::Role');
274 _create_alias('Class', $to, $trait, $from);
275}
276
277129µs1;
278
279__END__
280
281=pod
282
283=head1 NAME
284
285Moose::Util - Utilities for working with Moose classes
286
287=head1 SYNOPSIS
288
289 use Moose::Util qw/find_meta does_role search_class_by_role/;
290
291 my $meta = find_meta($object) || die "No metaclass found";
292
293 if (does_role($object, $role)) {
294 print "The object can do $role!\n";
295 }
296
297 my $class = search_class_by_role($object, 'FooRole');
298 print "Nearest class with 'FooRole' is $class\n";
299
300=head1 DESCRIPTION
301
302This module provides a set of utility functions. Many of these
303functions are intended for use in Moose itself or MooseX modules, but
304some of them may be useful for use in your own code.
305
306=head1 EXPORTED FUNCTIONS
307
308=over 4
309
310=item B<find_meta($class_or_obj)>
311
312This method takes a class name or object and attempts to find a
313metaclass for the class, if one exists. It will B<not> create one if it
314does not yet exist.
315
316=item B<does_role($class_or_obj, $role_or_obj)>
317
318Returns true if C<$class_or_obj> does the given C<$role_or_obj>. The role can
319be provided as a name or a L<Moose::Meta::Role> object.
320
321The class must already have a metaclass for this to work. If it doesn't, this
322function simply returns false.
323
324=item B<search_class_by_role($class_or_obj, $role_or_obj)>
325
326Returns the first class in the class's precedence list that does
327C<$role_or_obj>, if any. The role can be either a name or a
328L<Moose::Meta::Role> object.
329
330The class must already have a metaclass for this to work.
331
332=item B<apply_all_roles($applicant, @roles)>
333
334This function applies one or more roles to the given C<$applicant> The
335applicant can be a role name, class name, or object.
336
337The C<$applicant> must already have a metaclass object.
338
339The list of C<@roles> should a list of names or L<Moose::Meta::Role> objects,
340each of which can be followed by an optional hash reference of options
341(C<-excludes> and C<-alias>).
342
343=item B<ensure_all_roles($applicant, @roles)>
344
345This function is similar to L</apply_all_roles>, but only applies roles that
346C<$applicant> does not already consume.
347
348=item B<get_all_attribute_values($meta, $instance)>
349
350Returns a hash reference containing all of the C<$instance>'s
351attributes. The keys are attribute names.
352
353=item B<get_all_init_args($meta, $instance)>
354
355Returns a hash reference containing all of the C<init_arg> values for
356the instance's attributes. The values are the associated attribute
357values. If an attribute does not have a defined C<init_arg>, it is
358skipped.
359
360This could be useful in cloning an object.
361
362=item B<resolve_metaclass_alias($category, $name, %options)>
363
364=item B<resolve_metatrait_alias($category, $name, %options)>
365
366Resolves a short name to a full class name. Short names are often used
367when specifying the C<metaclass> or C<traits> option for an attribute:
368
369 has foo => (
370 metaclass => "Bar",
371 );
372
373The name resolution mechanism is covered in
374L<Moose/Metaclass and Trait Name Resolution>.
375
376=item B<english_list(@items)>
377
378Given a list of scalars, turns them into a proper list in English
379("one and two", "one, two, three, and four"). This is used to help us
380make nicer error messages.
381
382=item B<meta_class_alias($to[, $from])>
383
384=item B<meta_attribute_alias($to[, $from])>
385
386Create an alias from the class C<$from> (or the current package, if
387C<$from> is unspecified), so that
388L<Moose/Metaclass and Trait Name Resolution> works properly.
389
390=back
391
392=head1 TODO
393
394Here is a list of possible functions to write
395
396=over 4
397
398=item discovering original method from modified method
399
400=item search for origin class of a method or attribute
401
402=back
403
404=head1 BUGS
405
406See L<Moose/BUGS> for details on reporting bugs.
407
408=head1 AUTHOR
409
410Anders Nor Berle E<lt>debolaz@gmail.comE<gt>
411
412B<with contributions from:>
413
414Robert (phaylon) Sedlacek
415
416Stevan Little
417
418=head1 COPYRIGHT AND LICENSE
419
420Copyright 2007-2009 by Infinity Interactive, Inc.
421
422L<http://www.iinteractive.com>
423
424This library is free software; you can redistribute it and/or modify
425it under the same terms as Perl itself.
426
427=cut
428