/[cvs]/nfo/perl/libs/Data/Mungle/Code/Ref.pm
ViewVC logotype

Annotation of /nfo/perl/libs/Data/Mungle/Code/Ref.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (hide annotations)
Thu Feb 20 19:33:28 2003 UTC (21 years, 4 months ago) by joko
Branch: MAIN
Changes since 1.2: +126 -2 lines
refactored code from Data::Transform::Deep
+ sub ref_slot
+ sub expr2perl

1 root 1.1 ## ---------------------------------------------------------------------------
2 joko 1.3 ## $Id: Ref.pm,v 1.2 2003/02/20 18:55:46 joko Exp $
3 root 1.1 ## ---------------------------------------------------------------------------
4 joko 1.2 ## $Log: Ref.pm,v $
5 joko 1.3 ## Revision 1.2 2003/02/20 18:55:46 joko
6     ## + minor cosmetic update
7     ##
8 joko 1.2 ## Revision 1.1 2003/01/22 17:59:22 root
9     ## + refactored from Mail::Audit::Dispatch
10     ##
11 root 1.1 ## ---------------------------------------------------------------------------
12    
13    
14     package Data::Code::Ref;
15    
16     use strict;
17     use warnings;
18    
19     require Exporter;
20     our @ISA = qw( Exporter );
21     our @EXPORT_OK = qw(
22 joko 1.3 &get_coderef
23     &ref_slot
24 root 1.1 );
25    
26    
27     sub get_coderef {
28     my $codepack = shift;
29     my $method = shift;
30     $codepack || return '[error]';
31     $method ||= '';
32     $method && ($codepack .= '::');
33     return eval '\&' . $codepack . $method . ';';
34     }
35 joko 1.3
36    
37     # this function seems to do similar stuff like these below (refexpr2perlref & co.)
38     # TODO: maybe this mechanism can be replaced completely through some nice module from CPAN .... ? ;-)
39     sub _ref_slot_bylist {
40     my $var = shift;
41     my $indexstack_ref = shift;
42     my @indexstack = @{$indexstack_ref};
43     my $joiner = '->';
44     my @evlist;
45     foreach (@indexstack) {
46     my $elem;
47     if ($_ =~ m/\d+/) { $elem = "[$_]"; }
48     if ($_ =~ m/\D+/) { $elem = "{$_}"; }
49     push @evlist, $elem;
50     }
51     my $evstring = join($joiner, @evlist);
52     $evstring = 'return $var->' . $evstring . ';';
53     #print "ev: $evstring\n";
54     return eval($evstring);
55     }
56    
57    
58     sub ref_slot {
59    
60     my $obj = shift;
61     my $expr = shift;
62     my $values = shift;
63     my $delimiter = shift;
64    
65     $delimiter ||= '->';
66    
67     my $value;
68     # detect for callback (code-reference)
69     if (ref($expr) eq 'CODE') {
70     $value = &$expr($obj);
71    
72     } elsif (ref($expr) eq 'ARRAY') {
73     return _ref_slot_bylist($obj, $expr);
74    
75     } elsif ($expr =~ m/$delimiter/) {
76     # use expr as complex object reference declaration (obj->subObj->subSubObj->0->attribute)
77     (my $objPerlRefString, my $parts) = expr2perl($expr, $delimiter);
78    
79     # trace
80     #print "expr: $expr", "\n";
81     #print "objPerlRefString: $objPerlRefString", "\n";
82    
83     my $evstr = '$obj' . '->' . $objPerlRefString;
84    
85     # trace
86     #print "eval: $evstr", "\n";
87    
88     $value = eval($evstr);
89     die ($@) if $@;
90    
91     # if value isn't set, try to set it
92     my $callbackMap;
93     if ($values) {
94     #if (ref $values eq 'HASH') {
95     if (ref $values eq 'Data::Map') {
96     $callbackMap = $values->getAttributes();
97     } else {
98     # apply $values as single value to referenced slot
99     #print "APPLY!", "\n";
100     eval('$obj' . '->' . $objPerlRefString . ' = $values;');
101     die ($@) if $@;
102     }
103     }
104    
105     # determine $values - if it's a hashref, use it as a "valueMap"
106     # "fallback" to callbackMap
107     # callbacks are applied this way:
108     # take the last element of the expression parts and check if this string exists as a key in the callback-map
109     if (!$value && $callbackMap) {
110     #print Dumper($callbackMap);
111    
112     # prepare needle
113     my @parts = @$parts;
114     my $count = $#parts;
115     my $needle = $parts[$count];
116    
117     # prepare haystack
118     my @haystack = keys %$callbackMap;
119     if (grep($needle, @haystack)) {
120     $value = $callbackMap->{$needle}->();
121     #print "value: ", $value, "\n";
122     }
123     }
124    
125     } else {
126     # use expr as simple scalar key (attributename)
127     $value = $obj->{$expr};
128     }
129    
130     return $value;
131    
132     }
133    
134    
135     sub expr2perl {
136     my $expr = shift;
137     my $delimiter = shift;
138    
139     $delimiter = quotemeta($delimiter);
140    
141     # split expression by dereference operators first
142     my @parts_pure = split(/$delimiter/, $expr);
143    
144     # wrap []'s around each part, if it consists of numeric characters only (=> numeric = array-index),
145     # use {}'s, if there are word-characters in it (=> alphanumeric = hash-key)
146     my @parts_capsule = @parts_pure;
147     map {
148     m/^\d+$/ && ($_ = "[$_]") || ($_ = "{$_}");
149     } @parts_capsule;
150    
151     # join parts with dereference operators together again and return built string
152     return (join('->', @parts_capsule), \@parts_pure);
153     }
154    
155 root 1.1
156     1;
157 joko 1.2 __END__

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed