| 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 | Data::DPath::Path::BEGIN@17 |
| 1 | 1 | 1 | 23.3ms | 26.0ms | Data::DPath::Path::BEGIN@13 |
| 1 | 1 | 1 | 1.97ms | 15.5ms | Data::DPath::Path::BEGIN@14 |
| 1 | 1 | 1 | 52µs | 116µs | Data::DPath::Path::BEGIN@121 |
| 1 | 1 | 1 | 51µs | 703µs | Data::DPath::Path::BEGIN@20 |
| 1 | 1 | 1 | 42µs | 612µs | Data::DPath::Path::BEGIN@27 |
| 1 | 1 | 1 | 33µs | 33µs | Data::DPath::Path::BEGIN@2 |
| 1 | 1 | 1 | 31µs | 339ms | Data::DPath::Path::BEGIN@16 |
| 1 | 1 | 1 | 31µs | 2.48ms | Data::DPath::Path::BEGIN@15 |
| 1 | 1 | 1 | 28µs | 39µs | Data::DPath::Path::BEGIN@10 |
| 1 | 1 | 1 | 25µs | 45µs | Data::DPath::Path::BEGIN@11 |
| 0 | 0 | 0 | 0s | 0s | Data::DPath::Path::_build__steps |
| 0 | 0 | 0 | 0s | 0s | Data::DPath::Path::match |
| 0 | 0 | 0 | 0s | 0s | Data::DPath::Path::new |
| 0 | 0 | 0 | 0s | 0s | Data::DPath::Path::op_match |
| 0 | 0 | 0 | 0s | 0s | Data::DPath::Path::quoted |
| 0 | 0 | 0 | 0s | 0s | Data::DPath::Path::unescape |
| 0 | 0 | 0 | 0s | 0s | Data::DPath::Path::unquote |
| 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 | 35µs | 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 | 1 | 186µs | 1 | 703µs | }; # spent 703µs making 1 call to Data::DPath::Path::BEGIN@20 |
| 26 | |||||
| 27 | 1 | 34µs | 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 | 1 | 2.17ms | 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__ |