Profile of Data/DPath/Path.pm

← Index
NYTProf Performance Profile «block view•line view•sub view»
For bin/dpath
Run on Tue Jun 5 15:31:33 2012
Reported on Tue Jun 5 15:31:37 2012

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

Subroutines
Calls | P | F | Exclusive Time | Inclusive Time | Subroutine
--- | --- | --- | --- | --- | ---
1 | 1 | 1 | 24.3ms | 54.1ms | Data::DPath::Path::::BEGIN@17Data::DPath::Path::BEGIN@17
1 | 1 | 1 | 23.3ms | 26.0ms | Data::DPath::Path::::BEGIN@13Data::DPath::Path::BEGIN@13
1 | 1 | 1 | 1.97ms | 15.5ms | Data::DPath::Path::::BEGIN@14Data::DPath::Path::BEGIN@14
1 | 1 | 1 | 52µs | 116µs | Data::DPath::Path::::BEGIN@121Data::DPath::Path::BEGIN@121
1 | 1 | 1 | 51µs | 703µs | Data::DPath::Path::::BEGIN@20Data::DPath::Path::BEGIN@20
1 | 1 | 1 | 42µs | 612µs | Data::DPath::Path::::BEGIN@27Data::DPath::Path::BEGIN@27
1 | 1 | 1 | 33µs | 33µs | Data::DPath::Path::::BEGIN@2Data::DPath::Path::BEGIN@2
1 | 1 | 1 | 31µs | 339ms | Data::DPath::Path::::BEGIN@16Data::DPath::Path::BEGIN@16
1 | 1 | 1 | 31µs | 2.48ms | Data::DPath::Path::::BEGIN@15Data::DPath::Path::BEGIN@15
1 | 1 | 1 | 28µs | 39µs | Data::DPath::Path::::BEGIN@10Data::DPath::Path::BEGIN@10
1 | 1 | 1 | 25µs | 45µs | Data::DPath::Path::::BEGIN@11Data::DPath::Path::BEGIN@11
0 | 0 | 0 | 0s | 0s | Data::DPath::Path::::_build__stepsData::DPath::Path::_build__steps
0 | 0 | 0 | 0s | 0s | Data::DPath::Path::::matchData::DPath::Path::match
0 | 0 | 0 | 0s | 0s | Data::DPath::Path::::newData::DPath::Path::new
0 | 0 | 0 | 0s | 0s | Data::DPath::Path::::op_matchData::DPath::Path::op_match
0 | 0 | 0 | 0s | 0s | Data::DPath::Path::::quotedData::DPath::Path::quoted
0 | 0 | 0 | 0s | 0s | Data::DPath::Path::::unescapeData::DPath::Path::unescape
0 | 0 | 0 | 0s | 0s | Data::DPath::Path::::unquoteData::DPath::Path::unquote

Call graph for these subroutines as a Graphviz dot language file.

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 BEGIN {
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 use strict; # 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 use warnings; # 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 use Data::Dumper; # 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 use aliased 'Data::DPath::Step'; # 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 use aliased 'Data::DPath::Point'; # 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 use aliased 'Data::DPath::Context'; # 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 use Text::Balanced 2.02 'extract_delimited', 'extract_codeblock'; # 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 chained => 1, # 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 use constant { ROOT => 'ROOT', # 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 no warnings 'uninitialized'; # 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__