diff options
Diffstat (limited to 'lib/Class/MakeMethods/Template/StructBuiltin.pm')
| -rw-r--r-- | lib/Class/MakeMethods/Template/StructBuiltin.pm | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/lib/Class/MakeMethods/Template/StructBuiltin.pm b/lib/Class/MakeMethods/Template/StructBuiltin.pm new file mode 100644 index 0000000..b3ddc21 --- /dev/null +++ b/lib/Class/MakeMethods/Template/StructBuiltin.pm @@ -0,0 +1,148 @@ +package Class::MakeMethods::Template::StructBuiltin; + +use Class::MakeMethods::Template::Generic '-isasubclass'; + +$VERSION = 1.008; +use strict; +require 5.00; +use Carp; + +=head1 NAME + +Class::MakeMethods::Template::StructBuiltin + +=head1 SYNOPSIS + + use Class::MakeMethods::Template::StructBuiltin ( + -TargetClass => 'MyStat', + builtin_isa => [ + '-{new_function}'=>'stat', + qw/ dev ino mode nlink / + ] + ); + + +=head1 DESCRIPTION + +This class generates a wrapper around some builtin function, +storing the results in the object and providing a by-name interface. + +Takes a (core) function name, and a arrayref of return position names +(we will call it pos_list). Creates: + +=over 4 + +=item new + +Calls the core func with any given arguments, stores the result in the +instance. + +=item x + +For each member of pos_list, creates a method of the same name which +gets/sets the nth member of the returned list, where n is the position +of x in pos_list. + +=item fields + +Returns pos_list, in the given order. + +=item dump + +Returns a list item name, item value, in order. + +=back + +Example Usage: + + package Stat; + + use Class::MakeMethods::Template::StructBuiltin + builtin_isa => [ '-{new_function}'=>'stat', qw/ dev ino mode nlink / ], + + package main; + + my $file = "$ENV{HOME}/.template"; + my $s = Stat->new($file); + print "File $file has ", $s->nlink, " links\n"; + +Note that (a) the new method does not check the return value of the +function called (in the above example, if $file does not exist, you will +silently get an empty object), and (b) if you really want the above +example, see the core File::stat module. But you get the idea, I hope. + +=cut + +sub builtin_isa { + ( { + 'template' => { + default => { + '*'=>'get_set', 'dump'=>'dump', 'fields'=>'fields', 'new'=>'new_builtin' + }, + }, + 'behavior' => { + '-init' => sub { + my $m_info = $_[0]; + + $m_info->{class} ||= $m_info->{target_class}; + + my $class_info = + ( $Class::MakeMethods::Struct::builtin{$m_info->{class}} ||= [] ); + if ( ! defined $m_info->{array_index} ) { + foreach ( 0..$#$class_info ) { + if ( $class_info->[$_] eq $m_info->{'name'} ) { + $m_info->{array_index} = $_; last } + } + if ( ! defined $m_info->{array_index} ) { + push @ $class_info, $m_info->{'name'}; + $m_info->{array_index} = $#$class_info; + } + } + + if (defined $m_info->{new_function} and ! ref $m_info->{new_function}) { + # NOTE Below comments found in original version of MethodMaker. -Simon + # Cuz neither \&{"CORE::$func"} or $CORE::{$func} work ... N.B. this + # only works for core functions that take only one arg. But I can't + # quite figure out how to pass in the list without it getting + # evaluated in a scalar context. Hmmm. + $m_info->{new_function} = eval "sub { + scalar \@_ ? CORE::$m_info->{new_function}(shift) + : CORE::$m_info->{new_function} + }"; + } + + return; + }, + + 'new_builtin' => sub { my $m_info = $_[0]; sub { + my $class = shift; + my $function = $m_info->{new_function}; + my $self = [ &$function(@_) ]; + bless $self, $class; + }}, + + 'fields' => sub { my $m_info = $_[0]; sub { + my $class_info = + ( $Class::MakeMethods::Struct::builtin{$m_info->{class}} ||= [] ); + @$class_info; + }}, + 'dump' => sub { my $m_info = $_[0]; sub { + my $self = shift; + my $class_info = + ( $Class::MakeMethods::Struct::builtin{$m_info->{class}} ||= [] ); + my @keys = @$class_info; + map ($keys[$_], $self->[$_]), 0 .. $#keys; + }}, + + 'get_set' => sub { my $m_info = $_[0]; sub { + my $self = shift; + if ( @_ ) { + $self->[ $m_info->{array_index} ] = shift; + } + $self->[ $m_info->{array_index} ]; + }}, + }, + } ) +} + +1; |
