Filename | /home/ss5/perl5/perlbrew/perls/perl-5.14.1/lib/site_perl/5.14.1/Data/DPath/Path.pm |
Statements | Executed 26 statements in 6.32ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 24.3ms | 54.1ms | BEGIN@17 | Data::DPath::Path::
1 | 1 | 1 | 23.3ms | 26.0ms | BEGIN@13 | Data::DPath::Path::
1 | 1 | 1 | 1.97ms | 15.5ms | BEGIN@14 | Data::DPath::Path::
1 | 1 | 1 | 52µs | 116µs | BEGIN@121 | Data::DPath::Path::
1 | 1 | 1 | 51µs | 703µs | BEGIN@20 | Data::DPath::Path::
1 | 1 | 1 | 42µs | 612µs | BEGIN@27 | Data::DPath::Path::
1 | 1 | 1 | 33µs | 33µs | BEGIN@2 | Data::DPath::Path::
1 | 1 | 1 | 31µs | 339ms | BEGIN@16 | Data::DPath::Path::
1 | 1 | 1 | 31µs | 2.48ms | BEGIN@15 | Data::DPath::Path::
1 | 1 | 1 | 28µs | 39µs | BEGIN@10 | Data::DPath::Path::
1 | 1 | 1 | 25µs | 45µs | BEGIN@11 | Data::DPath::Path::
0 | 0 | 0 | 0s | 0s | _build__steps | Data::DPath::Path::
0 | 0 | 0 | 0s | 0s | match | Data::DPath::Path::
0 | 0 | 0 | 0s | 0s | new | Data::DPath::Path::
0 | 0 | 0 | 0s | 0s | op_match | Data::DPath::Path::
0 | 0 | 0 | 0s | 0s | quoted | Data::DPath::Path::
0 | 0 | 0 | 0s | 0s | unescape | Data::DPath::Path::
0 | 0 | 0 | 0s | 0s | unquote | Data::DPath::Path::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Data::DPath::Path; | ||||
2 | # spent 33µs within Data::DPath::Path::BEGIN@2 which was called:
# once (33µs+0s) by Data::DPath::BEGIN@18 at line 4 | ||||
3 | 1 | 24µs | $Data::DPath::Path::AUTHORITY = 'cpan:SCHWIGON'; | ||
4 | 1 | 132µs | 1 | 33µs | } # spent 33µs making 1 call to Data::DPath::Path::BEGIN@2 |
5 | { | ||||
6 | 2 | 5µs | $Data::DPath::Path::VERSION = '0.48'; | ||
7 | } | ||||
8 | # ABSTRACT: Abstraction for a DPath | ||||
9 | |||||
10 | 2 | 89µs | 2 | 50µs | # spent 39µs (28+11) within Data::DPath::Path::BEGIN@10 which was called:
# once (28µs+11µs) by Data::DPath::BEGIN@18 at line 10 # spent 39µs making 1 call to Data::DPath::Path::BEGIN@10
# spent 11µs making 1 call to strict::import |
11 | 2 | 88µs | 2 | 64µs | # spent 45µs (25+19) within Data::DPath::Path::BEGIN@11 which was called:
# once (25µs+19µs) by Data::DPath::BEGIN@18 at line 11 # spent 45µs making 1 call to Data::DPath::Path::BEGIN@11
# spent 20µs making 1 call to warnings::import |
12 | |||||
13 | 2 | 546µs | 2 | 26.2ms | # spent 26.0ms (23.3+2.70) within Data::DPath::Path::BEGIN@13 which was called:
# once (23.3ms+2.70ms) by Data::DPath::BEGIN@18 at line 13 # spent 26.0ms making 1 call to Data::DPath::Path::BEGIN@13
# spent 144µs making 1 call to Exporter::import |
14 | 2 | 582µs | 2 | 28.8ms | # spent 15.5ms (1.97+13.5) within Data::DPath::Path::BEGIN@14 which was called:
# once (1.97ms+13.5ms) by Data::DPath::BEGIN@18 at line 14 # spent 15.5ms making 1 call to Data::DPath::Path::BEGIN@14
# spent 13.3ms making 1 call to aliased::import |
15 | 2 | 135µs | 2 | 4.93ms | # spent 2.48ms (31µs+2.45) within Data::DPath::Path::BEGIN@15 which was called:
# once (31µs+2.45ms) by Data::DPath::BEGIN@18 at line 15 # spent 2.48ms making 1 call to Data::DPath::Path::BEGIN@15
# spent 2.45ms making 1 call to aliased::import |
16 | 2 | 160µs | 2 | 678ms | # spent 339ms (31µs+339) within Data::DPath::Path::BEGIN@16 which was called:
# once (31µs+339ms) by Data::DPath::BEGIN@18 at line 16 # spent 339ms making 1 call to Data::DPath::Path::BEGIN@16
# spent 339ms making 1 call to aliased::import |
17 | 3 | 690µs | 3 | 54.4ms | # spent 54.1ms (24.3+29.8) within Data::DPath::Path::BEGIN@17 which was called:
# once (24.3ms+29.8ms) by Data::DPath::BEGIN@18 at line 17 # spent 54.1ms making 1 call to Data::DPath::Path::BEGIN@17
# spent 306µs making 1 call to Exporter::import
# spent 65µs making 1 call to UNIVERSAL::VERSION |
18 | |||||
19 | use Class::XSAccessor | ||||
20 | 1 | 653µs | # spent 703µs (51+653) within Data::DPath::Path::BEGIN@20 which was called:
# once (51µs+653µs) by Data::DPath::BEGIN@18 at line 25 # spent 653µs making 1 call to Class::XSAccessor::import | ||
21 | accessors => { | ||||
22 | path => 'path', | ||||
23 | _steps => '_steps', | ||||
24 | give_references => 'give_references', | ||||
25 | 2 | 221µs | 1 | 703µs | }; # spent 703µs making 1 call to Data::DPath::Path::BEGIN@20 |
26 | |||||
27 | 1 | 570µs | # spent 612µs (42+570) within Data::DPath::Path::BEGIN@27 which was called:
# once (42µs+570µs) by Data::DPath::BEGIN@18 at line 35 # spent 570µs making 1 call to constant::import | ||
28 | ANYWHERE => 'ANYWHERE', | ||||
29 | KEY => 'KEY', | ||||
30 | ANYSTEP => 'ANYSTEP', | ||||
31 | NOSTEP => 'NOSTEP', | ||||
32 | PARENT => 'PARENT', | ||||
33 | ANCESTOR => 'ANCESTOR', | ||||
34 | ANCESTOR_OR_SELF => 'ANCESTOR_OR_SELF', | ||||
35 | 2 | 2.20ms | 1 | 612µs | }; # spent 612µs making 1 call to Data::DPath::Path::BEGIN@27 |
36 | |||||
37 | sub new { | ||||
38 | my $class = shift; | ||||
39 | my $self = bless { @_ }, $class; | ||||
40 | $self->_build__steps; | ||||
41 | return $self; | ||||
42 | } | ||||
43 | |||||
44 | sub unescape { | ||||
45 | my ($str) = @_; | ||||
46 | |||||
47 | return unless defined $str; | ||||
48 | $str =~ s/(?<!\\)\\(["'])/$1/g; # '"$ | ||||
49 | $str =~ s/\\{2}/\\/g; | ||||
50 | return $str; | ||||
51 | } | ||||
52 | |||||
53 | sub unquote { | ||||
54 | my ($str) = @_; | ||||
55 | $str =~ s/^"(.*)"$/$1/g; | ||||
56 | return $str; | ||||
57 | } | ||||
58 | |||||
59 | sub quoted { shift =~ m,^/["'],; } # " | ||||
60 | |||||
61 | 1 | 159µs | eval 'use overload "~~" => \&op_match' if $] >= 5.010; # spent 55µs executing statements in string eval # includes 52µs spent executing 1 call to 1 sub defined therein. | ||
62 | |||||
63 | sub op_match { | ||||
64 | my ($self, $data, $rhs) = @_; | ||||
65 | |||||
66 | return [ $self->match( $data ) ]; | ||||
67 | } | ||||
68 | |||||
69 | # essentially the Path parser | ||||
70 | sub _build__steps { | ||||
71 | my ($self) = @_; | ||||
72 | |||||
73 | my $remaining_path = $self->path; | ||||
74 | my $extracted; | ||||
75 | my @steps; | ||||
76 | |||||
77 | push @steps, Step->new->part('')->kind(ROOT); | ||||
78 | |||||
79 | while ($remaining_path) { | ||||
80 | my $plain_part; | ||||
81 | my $filter; | ||||
82 | my $kind; | ||||
83 | if ( quoted($remaining_path) ) { | ||||
84 | ($plain_part, $remaining_path) = extract_delimited($remaining_path, q/'"/, "/"); # ' | ||||
85 | ($filter, $remaining_path) = extract_codeblock($remaining_path, "[]"); | ||||
86 | $plain_part = unescape unquote $plain_part; | ||||
87 | $kind = KEY; # quoted is always a key | ||||
88 | } | ||||
89 | else | ||||
90 | { | ||||
91 | my $filter_already_extracted = 0; | ||||
92 | ($extracted, $remaining_path) = extract_delimited($remaining_path,'/'); | ||||
93 | |||||
94 | if (not $extracted) { | ||||
95 | ($extracted, $remaining_path) = ($remaining_path, undef); # END OF PATH | ||||
96 | } else { | ||||
97 | |||||
98 | # work around to recognize slashes in filter expressions and handle them: | ||||
99 | # | ||||
100 | # - 1) see if key unexpectedly contains opening "[" but no closing "]" | ||||
101 | # - 2) use the part before "[" | ||||
102 | # - 3) unshift the rest to remaining | ||||
103 | # - 4) extract_codeblock() explicitely | ||||
104 | if ($extracted =~ /(.*)((?<!\\)\[.*)/ and $extracted !~ m|\]/\s*$|) { | ||||
105 | $remaining_path = $2 . $remaining_path; | ||||
106 | ( $plain_part = $1 ) =~ s|^/||; | ||||
107 | ($filter, $remaining_path) = extract_codeblock($remaining_path, "[]"); | ||||
108 | $filter_already_extracted = 1; | ||||
109 | } else { | ||||
110 | $remaining_path = (chop $extracted) . $remaining_path; | ||||
111 | } | ||||
112 | } | ||||
113 | |||||
114 | ($plain_part, $filter) = $extracted =~ m,^/ # leading / | ||||
115 | (.*?) # path part | ||||
116 | (\[.*\])?$ # optional filter | ||||
117 | ,xg unless $filter_already_extracted; | ||||
118 | $plain_part = unescape $plain_part; | ||||
119 | } | ||||
120 | |||||
121 | 2 | 1.28ms | 2 | 181µs | # spent 116µs (52+64) within Data::DPath::Path::BEGIN@121 which was called:
# once (52µs+64µs) by Data::DPath::BEGIN@18 at line 121 # spent 116µs making 1 call to Data::DPath::Path::BEGIN@121
# spent 64µs making 1 call to warnings::unimport |
122 | if ($plain_part eq '') { $kind ||= ANYWHERE } | ||||
123 | elsif ($plain_part eq '*') { $kind ||= ANYSTEP } | ||||
124 | elsif ($plain_part eq '.') { $kind ||= NOSTEP } | ||||
125 | elsif ($plain_part eq '..') { $kind ||= PARENT } | ||||
126 | elsif ($plain_part eq '::ancestor') { $kind ||= ANCESTOR } | ||||
127 | elsif ($plain_part eq '::ancestor-or-self') { $kind ||= ANCESTOR_OR_SELF } | ||||
128 | else { $kind ||= KEY } | ||||
129 | |||||
130 | push @steps, Step->new->part($plain_part)->kind($kind)->filter($filter); | ||||
131 | } | ||||
132 | pop @steps if $steps[-1]->kind eq ANYWHERE; # ignore final '/' | ||||
133 | $self->_steps( \@steps ); | ||||
134 | } | ||||
135 | |||||
136 | sub match { | ||||
137 | my ($self, $data) = @_; | ||||
138 | |||||
139 | my $context = Context | ||||
140 | ->new | ||||
141 | ->current_points([ Point->new->ref(\$data) ]) | ||||
142 | ->give_references($self->give_references); | ||||
143 | return $context->match($self); | ||||
144 | } | ||||
145 | |||||
146 | 1 | 13µs | 1; | ||
147 | |||||
- - | |||||
150 | =pod | ||||
151 | |||||
152 | =encoding utf-8 | ||||
153 | |||||
154 | =head1 NAME | ||||
155 | |||||
156 | Data::DPath::Path - Abstraction for a DPath | ||||
157 | |||||
158 | =head1 ABOUT | ||||
159 | |||||
160 | Take a string description, parse it, provide frontend methods. | ||||
161 | |||||
162 | =head1 PUBLIC METHODS | ||||
163 | |||||
164 | =head2 new ( %args ) | ||||
165 | |||||
166 | Constructor; creates instance. | ||||
167 | |||||
168 | Args: | ||||
169 | |||||
170 | =over 4 | ||||
171 | |||||
172 | =item give_references | ||||
173 | |||||
174 | Default 0. If set to true value then results are references to the | ||||
175 | matched points in the data structure. | ||||
176 | |||||
177 | =back | ||||
178 | |||||
179 | =head2 match( $data ) | ||||
180 | |||||
181 | Returns an array of all values in C<$data> that match the Path object. | ||||
182 | |||||
183 | =head1 INTERNAL METHODS | ||||
184 | |||||
185 | =head2 op_match( $self, $data ) | ||||
186 | |||||
187 | This sub/method is bound as the overloading function for C<~~>. | ||||
188 | |||||
189 | =head2 quoted | ||||
190 | |||||
191 | Checks whether a path part starts with quotes. | ||||
192 | |||||
193 | =head2 unquote | ||||
194 | |||||
195 | Removes surrounding quotes. | ||||
196 | |||||
197 | =head2 unescape | ||||
198 | |||||
199 | Converts backslashed characters into their non-backslashed form. | ||||
200 | |||||
201 | =head2 _build__steps | ||||
202 | |||||
203 | This method is essentially the DPath parser as it tokenizes the path | ||||
204 | into single steps whose later execution is the base functionality of | ||||
205 | the whole DPath module. | ||||
206 | |||||
207 | =head2 path | ||||
208 | |||||
209 | Attribute / accessor. | ||||
210 | |||||
211 | =head2 _steps | ||||
212 | |||||
213 | Attribute / accessor. | ||||
214 | |||||
215 | =head2 give_references | ||||
216 | |||||
217 | Attribute / accessor. | ||||
218 | |||||
219 | =head1 aliased classes | ||||
220 | |||||
221 | That's just to make Pod::Coverage happy which does not handle aliased | ||||
222 | modules. | ||||
223 | |||||
224 | =head2 Context | ||||
225 | |||||
226 | =head2 Point | ||||
227 | |||||
228 | =head2 Step | ||||
229 | |||||
230 | =head1 AUTHOR | ||||
231 | |||||
232 | Steffen Schwigon <ss5@renormalist.net> | ||||
233 | |||||
234 | =head1 COPYRIGHT AND LICENSE | ||||
235 | |||||
236 | This software is copyright (c) 2012 by Steffen Schwigon. | ||||
237 | |||||
238 | This is free software; you can redistribute it and/or modify it under | ||||
239 | the same terms as the Perl 5 programming language system itself. | ||||
240 | |||||
241 | =cut | ||||
242 | |||||
243 | |||||
244 | __END__ |