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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (show annotations)
Tue May 13 07:02:47 2003 UTC (21 years, 1 month ago) by joko
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +9 -3 lines
fix: check for definedness, not for trueness

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

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