⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 struct.pm

📁 Mac OS X 10.4.9 for x86 Source Code automake实现源代码
💻 PM
📖 第 1 页 / 共 2 页
字号:
# autoconf -- create `configure' using m4 macros# Copyright 2001 Free Software Foundation, Inc.# This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2, or (at your option)# any later version.# This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the# GNU General Public License for more details.# You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA# 02111-1307, USA.# This file is basically Perl 5.6's Class::Struct, but made compatible# with Perl 5.5.  If someday this has to be updated, be sure to rename# all the occurrences of Class::Struct into Automake::Struct, otherwise# if we `use' a Perl module (e.g., File::stat) that uses Class::Struct,# we would have two packages defining the same symbols.  Boom.package Automake::Struct;## See POD after __END__use 5.005;use strict;use vars qw(@ISA @EXPORT $VERSION);use Carp;require Exporter;@ISA = qw(Exporter);@EXPORT = qw(struct);$VERSION = '0.58';## Tested on 5.002 and 5.003 without class membership tests:my $CHECK_CLASS_MEMBERSHIP = ($] >= 5.003_95);my $print = 0;sub printem {    if (@_) { $print = shift }    else    { $print++ }}{    package Automake::Struct::Tie_ISA;    sub TIEARRAY {        my $class = shift;        return bless [], $class;    }    sub STORE {        my ($self, $index, $value) = @_;        Automake::Struct::_subclass_error();    }    sub FETCH {        my ($self, $index) = @_;        $self->[$index];    }    sub FETCHSIZE {        my $self = shift;        return scalar(@$self);    }    sub DESTROY { }}sub struct {    # Determine parameter list structure, one of:    #   struct( class => [ element-list ])    #   struct( class => { element-list })    #   struct( element-list )    # Latter form assumes current package name as struct name.    my ($class, @decls);    my $base_type = ref $_[1];    if ( $base_type eq 'HASH' ) {        $class = shift;        @decls = %{shift()};        _usage_error() if @_;    }    elsif ( $base_type eq 'ARRAY' ) {        $class = shift;        @decls = @{shift()};        _usage_error() if @_;    }    else {        $base_type = 'ARRAY';        $class = (caller())[0];        @decls = @_;    }    _usage_error() if @decls % 2 == 1;    # Ensure we are not, and will not be, a subclass.    my $isa = do {        no strict 'refs';        \@{$class . '::ISA'};    };    _subclass_error() if @$isa;    tie @$isa, 'Automake::Struct::Tie_ISA';    # Create constructor.    croak "function 'new' already defined in package $class"        if do { no strict 'refs'; defined &{$class . "::new"} };    my @methods = ();    my %refs = ();    my %arrays = ();    my %hashes = ();    my %classes = ();    my $got_class = 0;    my $out = '';    $out = "{\n  package $class;\n  use Carp;\n  sub new {\n";    $out .= "    my (\$class, \%init) = \@_;\n";    $out .= "    \$class = __PACKAGE__ unless \@_;\n";    my $cnt = 0;    my $idx = 0;    my( $cmt, $name, $type, $elem );    if( $base_type eq 'HASH' ){        $out .= "    my(\$r) = {};\n";        $cmt = '';    }    elsif( $base_type eq 'ARRAY' ){        $out .= "    my(\$r) = [];\n";    }    while( $idx < @decls ){        $name = $decls[$idx];        $type = $decls[$idx+1];        push( @methods, $name );        if( $base_type eq 'HASH' ){            $elem = "{'${class}::$name'}";        }        elsif( $base_type eq 'ARRAY' ){            $elem = "[$cnt]";            ++$cnt;            $cmt = " # $name";        }        if( $type =~ /^\*(.)/ ){            $refs{$name}++;            $type = $1;        }        my $init = "defined(\$init{'$name'}) ? \$init{'$name'} :";        if( $type eq '@' ){            $out .= "    croak 'Initializer for $name must be array reference'\n";            $out .= "        if defined(\$init{'$name'}) && ref(\$init{'$name'}) ne 'ARRAY';\n";            $out .= "    \$r->$elem = $init [];$cmt\n";            $arrays{$name}++;        }        elsif( $type eq '%' ){            $out .= "    croak 'Initializer for $name must be hash reference'\n";            $out .= "        if defined(\$init{'$name'}) && ref(\$init{'$name'}) ne 'HASH';\n";            $out .= "    \$r->$elem = $init {};$cmt\n";            $hashes{$name}++;        }        elsif ( $type eq '$') {            $out .= "    \$r->$elem = $init undef;$cmt\n";        }        elsif( $type =~ /^\w+(?:::\w+)*$/ ){            $init = "defined(\$init{'$name'}) ? \%{\$init{'$name'}} : ()";            $out .= "    croak 'Initializer for $name must be hash reference'\n";            $out .= "        if defined(\$init{'$name'}) && ref(\$init{'$name'}) ne 'HASH';\n";            $out .= "    \$r->$elem = '${type}'->new($init);$cmt\n";            $classes{$name} = $type;            $got_class = 1;        }        else{            croak "'$type' is not a valid struct element type";        }        $idx += 2;    }    $out .= "    bless \$r, \$class;\n  }\n";    # Create accessor methods.    my( $pre, $pst, $sel );    $cnt = 0;    foreach $name (@methods){        if ( do { no strict 'refs'; defined &{$class . "::$name"} } ) {            carp "function '$name' already defined, overrides struct accessor method";        }        else {            $pre = $pst = $cmt = $sel = '';            if( defined $refs{$name} ){                $pre = "\\(";                $pst = ")";                $cmt = " # returns ref";            }            $out .= "  sub $name {$cmt\n    my \$r = shift;\n";            if( $base_type eq 'ARRAY' ){                $elem = "[$cnt]";                ++$cnt;            }            elsif( $base_type eq 'HASH' ){                $elem = "{'${class}::$name'}";            }            if( defined $arrays{$name} ){                $out .= "    my \$i;\n";                $out .= "    \@_ ? (\$i = shift) : return \$r->$elem;\n";                $sel = "->[\$i]";            }            elsif( defined $hashes{$name} ){                $out .= "    my \$i;\n";                $out .= "    \@_ ? (\$i = shift) : return \$r->$elem;\n";                $sel = "->{\$i}";            }            elsif( defined $classes{$name} ){                if ( $CHECK_CLASS_MEMBERSHIP ) {                    $out .= "    croak '$name argument is wrong class' if \@_ && ! UNIVERSAL::isa(\$_[0], '$classes{$name}');\n";                }            }            $out .= "    croak 'Too many args to $name' if \@_ > 1;\n";            $out .= "    \@_ ? ($pre\$r->$elem$sel = shift$pst) : $pre\$r->$elem$sel$pst;\n";            $out .= "  }\n";        }    }    $out .= "}\n1;\n";    print $out if $print;    my $result = eval $out;    carp $@ if $@;}sub _usage_error {    confess "struct usage error";}sub _subclass_error {    croak 'struct class cannot be a subclass (@ISA not allowed)';}1; # for require__END__=head1 NAMEAutomake::Struct - declare struct-like datatypes as Perl classes=head1 SYNOPSIS    use Automake::Struct;            # declare struct, based on array:    struct( CLASS_NAME => [ ELEMENT_NAME => ELEMENT_TYPE, ... ]);            # declare struct, based on hash:    struct( CLASS_NAME => { ELEMENT_NAME => ELEMENT_TYPE, ... });    package CLASS_NAME;    use Automake::Struct;            # declare struct, based on array, implicit class name:    struct( ELEMENT_NAME => ELEMENT_TYPE, ... );    package Myobj;    use Automake::Struct;            # declare struct with four types of elements:    struct( s => '$', a => '@', h => '%', c => 'My_Other_Class' );    $obj = new Myobj;               # constructor                                    # scalar type accessor:    $element_value = $obj->s;           # element value    $obj->s('new value');               # assign to element                                    # array type accessor:    $ary_ref = $obj->a;                 # reference to whole array    $ary_element_value = $obj->a(2);    # array element value    $obj->a(2, 'new value');            # assign to array element                                    # hash type accessor:    $hash_ref = $obj->h;                # reference to whole hash    $hash_element_value = $obj->h('x'); # hash element value    $obj->h('x', 'new value');        # assign to hash element                                    # class type accessor:    $element_value = $obj->c;           # object reference    $obj->c->method(...);               # call method of object    $obj->c(new My_Other_Class);        # assign a new object=head1 DESCRIPTIONC<Automake::Struct> exports a single function, C<struct>.Given a list of element names and types, and optionallya class name, C<struct> creates a Perl 5 class that implementsa "struct-like" data structure.The new class is given a constructor method, C<new>, for creatingstruct objects.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -