/[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.3 - (show 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 ## ---------------------------------------------------------------------------
2 ## $Id: Ref.pm,v 1.2 2003/02/20 18:55:46 joko Exp $
3 ## ---------------------------------------------------------------------------
4 ## $Log: Ref.pm,v $
5 ## Revision 1.2 2003/02/20 18:55:46 joko
6 ## + minor cosmetic update
7 ##
8 ## Revision 1.1 2003/01/22 17:59:22 root
9 ## + refactored from Mail::Audit::Dispatch
10 ##
11 ## ---------------------------------------------------------------------------
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 &get_coderef
23 &ref_slot
24 );
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
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
156 1;
157 __END__

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