| Filename | C:/tmp64ng/perl/vendor/lib/Portable/LoadYaml.pm |
| Statements | Executed 2103 statements in 15.6ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 99 | 2 | 1 | 15.6ms | 15.6ms | Portable::LoadYaml::_load_scalar |
| 1 | 1 | 1 | 0s | 0s | Portable::LoadYaml::BEGIN@5 |
| 1 | 1 | 1 | 0s | 0s | Portable::LoadYaml::BEGIN@6 |
| 1 | 1 | 1 | 0s | 0s | Portable::LoadYaml::BEGIN@7 |
| 1 | 1 | 1 | 0s | 0s | Portable::LoadYaml::BEGIN@78 |
| 1 | 1 | 1 | 0s | 0s | Portable::LoadYaml::CORE:close (opcode) |
| 1 | 1 | 1 | 0s | 0s | Portable::LoadYaml::CORE:fteread (opcode) |
| 1 | 1 | 1 | 0s | 0s | Portable::LoadYaml::CORE:ftfile (opcode) |
| 1 | 1 | 1 | 0s | 0s | Portable::LoadYaml::CORE:ftis (opcode) |
| 906 | 17 | 1 | 0s | 0s | Portable::LoadYaml::CORE:match (opcode) |
| 1 | 1 | 1 | 0s | 0s | Portable::LoadYaml::CORE:open (opcode) |
| 5 | 5 | 1 | 0s | 0s | Portable::LoadYaml::CORE:qr (opcode) |
| 1 | 1 | 1 | 0s | 0s | Portable::LoadYaml::CORE:readline (opcode) |
| 473 | 3 | 1 | 0s | 0s | Portable::LoadYaml::CORE:regcomp (opcode) |
| 586 | 6 | 1 | 0s | 0s | Portable::LoadYaml::CORE:subst (opcode) |
| 1 | 1 | 1 | 0s | 0s | Portable::LoadYaml::_load_array |
| 1 | 1 | 1 | 0s | 15.6ms | Portable::LoadYaml::_load_file |
| 6 | 2 | 1 | 0s | 15.6ms | Portable::LoadYaml::_load_hash (recurses: max depth 1, inclusive time 15.6ms) |
| 1 | 1 | 1 | 0s | 15.6ms | Portable::LoadYaml::_load_string |
| 0 | 0 | 0 | 0s | 0s | Portable::LoadYaml::_unquote_double |
| 32 | 1 | 1 | 0s | 0s | Portable::LoadYaml::_unquote_single |
| 1 | 1 | 1 | 0s | 15.6ms | Portable::LoadYaml::load_file |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Portable::LoadYaml; | ||||
| 2 | |||||
| 3 | ### UGLY HACK: these functions where completely copied from Parse::CPAN::Meta | ||||
| 4 | |||||
| 5 | 2 | 0s | 1 | 0s | # spent 0s within Portable::LoadYaml::BEGIN@5 which was called:
# once (0s+0s) by Portable::BEGIN@54 at line 5 # spent 0s making 1 call to Portable::LoadYaml::BEGIN@5 |
| 6 | 2 | 0s | 2 | 0s | # spent 0s within Portable::LoadYaml::BEGIN@6 which was called:
# once (0s+0s) by Portable::BEGIN@54 at line 6 # spent 0s making 1 call to Portable::LoadYaml::BEGIN@6
# spent 0s making 1 call to strict::import |
| 7 | 2 | 0s | 2 | 0s | # spent 0s within Portable::LoadYaml::BEGIN@7 which was called:
# once (0s+0s) by Portable::BEGIN@54 at line 7 # spent 0s making 1 call to Portable::LoadYaml::BEGIN@7
# spent 0s making 1 call to warnings::import |
| 8 | |||||
| 9 | 1 | 0s | our $VERSION = '1.22'; | ||
| 10 | |||||
| 11 | # spent 15.6ms (0s+15.6) within Portable::LoadYaml::load_file which was called:
# once (0s+15.6ms) by Portable::default at line 206 of Portable.pm | ||||
| 12 | 1 | 0s | my $file = shift; | ||
| 13 | 1 | 0s | 1 | 15.6ms | my $self = __PACKAGE__->_load_file($file); # spent 15.6ms making 1 call to Portable::LoadYaml::_load_file |
| 14 | 1 | 0s | return $self->[-1]; | ||
| 15 | } | ||||
| 16 | |||||
| 17 | ##################################################################### | ||||
| 18 | # Constants | ||||
| 19 | |||||
| 20 | # Printed form of the unprintable characters in the lowest range | ||||
| 21 | # of ASCII characters, listed by ASCII ordinal position. | ||||
| 22 | 1 | 0s | my @UNPRINTABLE = qw( | ||
| 23 | 0 x01 x02 x03 x04 x05 x06 a | ||||
| 24 | b t n v f r x0E x0F | ||||
| 25 | x10 x11 x12 x13 x14 x15 x16 x17 | ||||
| 26 | x18 x19 x1A e x1C x1D x1E x1F | ||||
| 27 | ); | ||||
| 28 | |||||
| 29 | # Printable characters for escapes | ||||
| 30 | 1 | 0s | my %UNESCAPES = ( | ||
| 31 | 0 => "\x00", z => "\x00", N => "\x85", | ||||
| 32 | a => "\x07", b => "\x08", t => "\x09", | ||||
| 33 | n => "\x0a", v => "\x0b", f => "\x0c", | ||||
| 34 | r => "\x0d", e => "\x1b", '\\' => '\\', | ||||
| 35 | ); | ||||
| 36 | |||||
| 37 | # These 3 values have special meaning when unquoted and using the | ||||
| 38 | # default YAML schema. They need quotes if they are strings. | ||||
| 39 | 1 | 0s | my %QUOTE = map { $_ => 1 } qw{ | ||
| 40 | null true false | ||||
| 41 | }; | ||||
| 42 | |||||
| 43 | # The commented out form is simpler, but overloaded the Perl regex | ||||
| 44 | # engine due to recursion and backtracking problems on strings | ||||
| 45 | # larger than 32,000ish characters. Keep it for reference purposes. | ||||
| 46 | # qr/\"((?:\\.|[^\"])*)\"/ | ||||
| 47 | 1 | 0s | 1 | 0s | my $re_capture_double_quoted = qr/\"([^\\"]*(?:\\.[^\\"]*)*)\"/; # spent 0s making 1 call to Portable::LoadYaml::CORE:qr |
| 48 | 1 | 0s | 1 | 0s | my $re_capture_single_quoted = qr/\'([^\']*(?:\'\'[^\']*)*)\'/; # spent 0s making 1 call to Portable::LoadYaml::CORE:qr |
| 49 | # unquoted re gets trailing space that needs to be stripped | ||||
| 50 | 1 | 0s | 1 | 0s | my $re_capture_unquoted_key = qr/([^:]+(?::+\S[^:]*)*)(?=\s*\:(?:\s+|$))/; # spent 0s making 1 call to Portable::LoadYaml::CORE:qr |
| 51 | 1 | 0s | 1 | 0s | my $re_trailing_comment = qr/(?:\s+\#.*)?/; # spent 0s making 1 call to Portable::LoadYaml::CORE:qr |
| 52 | 1 | 0s | 1 | 0s | my $re_key_value_separator = qr/\s*:(?:\s+(?:\#.*)?|$)/; # spent 0s making 1 call to Portable::LoadYaml::CORE:qr |
| 53 | |||||
| 54 | ### | ||||
| 55 | # Loader functions: | ||||
| 56 | |||||
| 57 | # Create an object from a file | ||||
| 58 | # spent 15.6ms (0s+15.6) within Portable::LoadYaml::_load_file which was called:
# once (0s+15.6ms) by Portable::LoadYaml::load_file at line 13 | ||||
| 59 | 1 | 0s | my $class = ref $_[0] ? ref shift : shift; | ||
| 60 | |||||
| 61 | # Check the file | ||||
| 62 | 1 | 0s | my $file = shift or $class->_error( 'You did not specify a file name' ); | ||
| 63 | 1 | 0s | 1 | 0s | $class->_error( "File '$file' does not exist" ) # spent 0s making 1 call to Portable::LoadYaml::CORE:ftis |
| 64 | unless -e $file; | ||||
| 65 | 1 | 0s | 1 | 0s | $class->_error( "'$file' is a directory, not a file" ) # spent 0s making 1 call to Portable::LoadYaml::CORE:ftfile |
| 66 | unless -f _; | ||||
| 67 | 1 | 0s | 1 | 0s | $class->_error( "Insufficient permissions to read '$file'" ) # spent 0s making 1 call to Portable::LoadYaml::CORE:fteread |
| 68 | unless -r _; | ||||
| 69 | |||||
| 70 | # Open unbuffered | ||||
| 71 | 1 | 0s | 1 | 0s | open( my $fh, "<:unix", $file ); # spent 0s making 1 call to Portable::LoadYaml::CORE:open |
| 72 | 1 | 0s | unless ( $fh ) { | ||
| 73 | $class->_error("Failed to open file '$file': $!"); | ||||
| 74 | } | ||||
| 75 | |||||
| 76 | # slurp the contents | ||||
| 77 | 1 | 0s | my $contents = eval { | ||
| 78 | 2 | 0s | 2 | 0s | # spent 0s within Portable::LoadYaml::BEGIN@78 which was called:
# once (0s+0s) by Portable::BEGIN@54 at line 78 # spent 0s making 1 call to Portable::LoadYaml::BEGIN@78
# spent 0s making 1 call to warnings::import |
| 79 | 1 | 0s | local $/; | ||
| 80 | <$fh> | ||||
| 81 | 1 | 0s | 1 | 0s | }; # spent 0s making 1 call to Portable::LoadYaml::CORE:readline |
| 82 | 1 | 0s | if ( my $err = $@ ) { | ||
| 83 | $class->_error("Error reading from file '$file': $err"); | ||||
| 84 | } | ||||
| 85 | |||||
| 86 | # close the file (release the lock) | ||||
| 87 | 1 | 0s | 1 | 0s | unless ( close $fh ) { # spent 0s making 1 call to Portable::LoadYaml::CORE:close |
| 88 | $class->_error("Failed to close file '$file': $!"); | ||||
| 89 | } | ||||
| 90 | |||||
| 91 | 1 | 0s | 1 | 15.6ms | $class->_load_string( $contents ); # spent 15.6ms making 1 call to Portable::LoadYaml::_load_string |
| 92 | } | ||||
| 93 | |||||
| 94 | # Create an object from a string | ||||
| 95 | # spent 15.6ms (0s+15.6) within Portable::LoadYaml::_load_string which was called:
# once (0s+15.6ms) by Portable::LoadYaml::_load_file at line 91 | ||||
| 96 | 1 | 0s | my $class = ref $_[0] ? ref shift : shift; | ||
| 97 | 1 | 0s | my $self = bless [], $class; | ||
| 98 | 1 | 0s | my $string = $_[0]; | ||
| 99 | 1 | 0s | eval { | ||
| 100 | 1 | 0s | unless ( defined $string ) { | ||
| 101 | die \"Did not provide a string to load"; | ||||
| 102 | } | ||||
| 103 | |||||
| 104 | # Check if Perl has it marked as characters, but it's internally | ||||
| 105 | # inconsistent. E.g. maybe latin1 got read on a :utf8 layer | ||||
| 106 | 1 | 0s | 1 | 0s | if ( utf8::is_utf8($string) && ! utf8::valid($string) ) { # spent 0s making 1 call to utf8::is_utf8 |
| 107 | die \<<'...'; | ||||
| 108 | Read an invalid UTF-8 string (maybe mixed UTF-8 and 8-bit character set). | ||||
| 109 | Did you decode with lax ":utf8" instead of strict ":encoding(UTF-8)"? | ||||
| 110 | ... | ||||
| 111 | } | ||||
| 112 | |||||
| 113 | # Ensure Unicode character semantics, even for 0x80-0xff | ||||
| 114 | 1 | 0s | 1 | 0s | utf8::upgrade($string); # spent 0s making 1 call to utf8::upgrade |
| 115 | |||||
| 116 | # Check for and strip any leading UTF-8 BOM | ||||
| 117 | 1 | 0s | 1 | 0s | $string =~ s/^\x{FEFF}//; # spent 0s making 1 call to Portable::LoadYaml::CORE:subst |
| 118 | |||||
| 119 | # Check for some special cases | ||||
| 120 | 1 | 0s | return $self unless length $string; | ||
| 121 | |||||
| 122 | # Split the file into lines | ||||
| 123 | 107 | 0s | 106 | 0s | my @lines = grep { ! /^\s*(?:\#.*)?\z/ } # spent 0s making 106 calls to Portable::LoadYaml::CORE:match, avg 0s/call |
| 124 | split /(?:\015{1,2}\012|\015|\012)/, $string; | ||||
| 125 | |||||
| 126 | # Strip the initial YAML header | ||||
| 127 | 1 | 0s | 1 | 0s | @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines; # spent 0s making 1 call to Portable::LoadYaml::CORE:match |
| 128 | |||||
| 129 | # A nibbling parser | ||||
| 130 | 1 | 0s | my $in_document = 0; | ||
| 131 | 1 | 0s | while ( @lines ) { | ||
| 132 | # Do we have a document header? | ||||
| 133 | 1 | 0s | 1 | 0s | if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) { # spent 0s making 1 call to Portable::LoadYaml::CORE:match |
| 134 | # Handle scalar documents | ||||
| 135 | 1 | 0s | shift @lines; | ||
| 136 | 1 | 0s | if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) { | ||
| 137 | push @$self, | ||||
| 138 | $self->_load_scalar( "$1", [ undef ], \@lines ); | ||||
| 139 | next; | ||||
| 140 | } | ||||
| 141 | 1 | 0s | $in_document = 1; | ||
| 142 | } | ||||
| 143 | |||||
| 144 | 1 | 0s | 3 | 0s | if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) { # spent 0s making 3 calls to Portable::LoadYaml::CORE:match, avg 0s/call |
| 145 | # A naked document | ||||
| 146 | push @$self, undef; | ||||
| 147 | while ( @lines and $lines[0] !~ /^---/ ) { | ||||
| 148 | shift @lines; | ||||
| 149 | } | ||||
| 150 | $in_document = 0; | ||||
| 151 | |||||
| 152 | # XXX The final '-+$' is to look for -- which ends up being an | ||||
| 153 | # error later. | ||||
| 154 | } elsif ( ! $in_document && @$self ) { | ||||
| 155 | # only the first document can be explicit | ||||
| 156 | die \"failed to classify the line '$lines[0]'"; | ||||
| 157 | } elsif ( $lines[0] =~ /^\s*\-(?:\s|$|-+$)/ ) { | ||||
| 158 | # An array at the root | ||||
| 159 | my $document = [ ]; | ||||
| 160 | push @$self, $document; | ||||
| 161 | $self->_load_array( $document, [ 0 ], \@lines ); | ||||
| 162 | |||||
| 163 | } elsif ( $lines[0] =~ /^(\s*)\S/ ) { | ||||
| 164 | # A hash at the root | ||||
| 165 | 1 | 0s | my $document = { }; | ||
| 166 | 1 | 0s | push @$self, $document; | ||
| 167 | 1 | 0s | 1 | 15.6ms | $self->_load_hash( $document, [ length($1) ], \@lines ); # spent 15.6ms making 1 call to Portable::LoadYaml::_load_hash |
| 168 | |||||
| 169 | } else { | ||||
| 170 | # Shouldn't get here. @lines have whitespace-only lines | ||||
| 171 | # stripped, and previous match is a line with any | ||||
| 172 | # non-whitespace. So this clause should only be reachable via | ||||
| 173 | # a perlbug where \s is not symmetric with \S | ||||
| 174 | |||||
| 175 | # uncoverable statement | ||||
| 176 | die \"failed to classify the line '$lines[0]'"; | ||||
| 177 | } | ||||
| 178 | } | ||||
| 179 | }; | ||||
| 180 | 1 | 0s | if ( ref $@ eq 'SCALAR' ) { | ||
| 181 | $self->_error(${$@}); | ||||
| 182 | } elsif ( $@ ) { | ||||
| 183 | $self->_error($@); | ||||
| 184 | } | ||||
| 185 | |||||
| 186 | 1 | 0s | return $self; | ||
| 187 | } | ||||
| 188 | |||||
| 189 | # spent 0s within Portable::LoadYaml::_unquote_single which was called 32 times, avg 0s/call:
# 32 times (0s+0s) by Portable::LoadYaml::_load_scalar at line 218, avg 0s/call | ||||
| 190 | 32 | 0s | my ($self, $string) = @_; | ||
| 191 | 32 | 0s | return '' unless length $string; | ||
| 192 | 8 | 0s | 8 | 0s | $string =~ s/\'\'/\'/g; # spent 0s making 8 calls to Portable::LoadYaml::CORE:subst, avg 0s/call |
| 193 | 8 | 0s | return $string; | ||
| 194 | } | ||||
| 195 | |||||
| 196 | sub _unquote_double { | ||||
| 197 | my ($self, $string) = @_; | ||||
| 198 | return '' unless length $string; | ||||
| 199 | $string =~ s/\\"/"/g; | ||||
| 200 | $string =~ | ||||
| 201 | s{\\([Nnever\\fartz0b]|x([0-9a-fA-F]{2}))} | ||||
| 202 | {(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}}gex; | ||||
| 203 | return $string; | ||||
| 204 | } | ||||
| 205 | |||||
| 206 | # Load a YAML scalar string to the actual Perl scalar | ||||
| 207 | sub _load_scalar { | ||||
| 208 | 99 | 0s | my ($self, $string, $indent, $lines) = @_; | ||
| 209 | |||||
| 210 | # Trim trailing whitespace | ||||
| 211 | 99 | 0s | 99 | 0s | $string =~ s/\s*\z//; # spent 0s making 99 calls to Portable::LoadYaml::CORE:subst, avg 0s/call |
| 212 | |||||
| 213 | # Explitic null/undef | ||||
| 214 | 99 | 0s | return undef if $string eq '~'; | ||
| 215 | |||||
| 216 | # Single quote | ||||
| 217 | 98 | 0s | 196 | 0s | if ( $string =~ /^$re_capture_single_quoted$re_trailing_comment\z/ ) { # spent 0s making 98 calls to Portable::LoadYaml::CORE:match, avg 0s/call
# spent 0s making 98 calls to Portable::LoadYaml::CORE:regcomp, avg 0s/call |
| 218 | 32 | 0s | 32 | 0s | return $self->_unquote_single($1); # spent 0s making 32 calls to Portable::LoadYaml::_unquote_single, avg 0s/call |
| 219 | } | ||||
| 220 | |||||
| 221 | # Double quote. | ||||
| 222 | 66 | 0s | 132 | 0s | if ( $string =~ /^$re_capture_double_quoted$re_trailing_comment\z/ ) { # spent 0s making 66 calls to Portable::LoadYaml::CORE:match, avg 0s/call
# spent 0s making 66 calls to Portable::LoadYaml::CORE:regcomp, avg 0s/call |
| 223 | return $self->_unquote_double($1); | ||||
| 224 | } | ||||
| 225 | |||||
| 226 | # Special cases | ||||
| 227 | 66 | 0s | 66 | 0s | if ( $string =~ /^[\'\"!&]/ ) { # spent 0s making 66 calls to Portable::LoadYaml::CORE:match, avg 0s/call |
| 228 | die \"does not support a feature in line '$string'"; | ||||
| 229 | } | ||||
| 230 | 66 | 15.6ms | 66 | 0s | return {} if $string =~ /^{}(?:\s+\#.*)?\z/; # spent 0s making 66 calls to Portable::LoadYaml::CORE:match, avg 0s/call |
| 231 | 66 | 0s | 66 | 0s | return [] if $string =~ /^\[\](?:\s+\#.*)?\z/; # spent 0s making 66 calls to Portable::LoadYaml::CORE:match, avg 0s/call |
| 232 | |||||
| 233 | # Regular unquoted string | ||||
| 234 | 66 | 0s | 66 | 0s | if ( $string !~ /^[>|]/ ) { # spent 0s making 66 calls to Portable::LoadYaml::CORE:match, avg 0s/call |
| 235 | 66 | 0s | 132 | 0s | die \"found illegal characters in plain scalar: '$string'" # spent 0s making 132 calls to Portable::LoadYaml::CORE:match, avg 0s/call |
| 236 | if $string =~ /^(?:-(?:\s|$)|[\@\%\`])/ or | ||||
| 237 | $string =~ /:(?:\s|$)/; | ||||
| 238 | 66 | 0s | 66 | 0s | $string =~ s/\s+#.*\z//; # spent 0s making 66 calls to Portable::LoadYaml::CORE:subst, avg 0s/call |
| 239 | 66 | 0s | return $string; | ||
| 240 | } | ||||
| 241 | |||||
| 242 | # Error | ||||
| 243 | die \"failed to find multi-line scalar content" unless @$lines; | ||||
| 244 | |||||
| 245 | # Check the indent depth | ||||
| 246 | $lines->[0] =~ /^(\s*)/; | ||||
| 247 | $indent->[-1] = length("$1"); | ||||
| 248 | if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) { | ||||
| 249 | die \"found bad indenting in line '$lines->[0]'"; | ||||
| 250 | } | ||||
| 251 | |||||
| 252 | # Pull the lines | ||||
| 253 | my @multiline = (); | ||||
| 254 | while ( @$lines ) { | ||||
| 255 | $lines->[0] =~ /^(\s*)/; | ||||
| 256 | last unless length($1) >= $indent->[-1]; | ||||
| 257 | push @multiline, substr(shift(@$lines), length($1)); | ||||
| 258 | } | ||||
| 259 | |||||
| 260 | my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n"; | ||||
| 261 | my $t = (substr($string, 1, 1) eq '-') ? '' : "\n"; | ||||
| 262 | return join( $j, @multiline ) . $t; | ||||
| 263 | } | ||||
| 264 | |||||
| 265 | # Load an array | ||||
| 266 | # spent 0s within Portable::LoadYaml::_load_array which was called:
# once (0s+0s) by Portable::LoadYaml::_load_hash at line 410 | ||||
| 267 | 1 | 0s | my ($self, $array, $indent, $lines) = @_; | ||
| 268 | |||||
| 269 | 1 | 0s | while ( @$lines ) { | ||
| 270 | # Check for a new document | ||||
| 271 | 2 | 0s | 2 | 0s | if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { # spent 0s making 2 calls to Portable::LoadYaml::CORE:match, avg 0s/call |
| 272 | while ( @$lines and $lines->[0] !~ /^---/ ) { | ||||
| 273 | shift @$lines; | ||||
| 274 | } | ||||
| 275 | return 1; | ||||
| 276 | } | ||||
| 277 | |||||
| 278 | # Check the indent level | ||||
| 279 | 2 | 0s | 2 | 0s | $lines->[0] =~ /^(\s*)/; # spent 0s making 2 calls to Portable::LoadYaml::CORE:match, avg 0s/call |
| 280 | 2 | 0s | if ( length($1) < $indent->[-1] ) { | ||
| 281 | return 1; | ||||
| 282 | } elsif ( length($1) > $indent->[-1] ) { | ||||
| 283 | die \"found bad indenting in line '$lines->[0]'"; | ||||
| 284 | } | ||||
| 285 | |||||
| 286 | 2 | 0s | 6 | 0s | if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) { # spent 0s making 6 calls to Portable::LoadYaml::CORE:match, avg 0s/call |
| 287 | # Inline nested hash | ||||
| 288 | my $indent2 = length("$1"); | ||||
| 289 | $lines->[0] =~ s/-/ /; | ||||
| 290 | push @$array, { }; | ||||
| 291 | $self->_load_hash( $array->[-1], [ @$indent, $indent2 ], $lines ); | ||||
| 292 | |||||
| 293 | } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) { | ||||
| 294 | shift @$lines; | ||||
| 295 | unless ( @$lines ) { | ||||
| 296 | push @$array, undef; | ||||
| 297 | return 1; | ||||
| 298 | } | ||||
| 299 | if ( $lines->[0] =~ /^(\s*)\-/ ) { | ||||
| 300 | my $indent2 = length("$1"); | ||||
| 301 | if ( $indent->[-1] == $indent2 ) { | ||||
| 302 | # Null array entry | ||||
| 303 | push @$array, undef; | ||||
| 304 | } else { | ||||
| 305 | # Naked indenter | ||||
| 306 | push @$array, [ ]; | ||||
| 307 | $self->_load_array( | ||||
| 308 | $array->[-1], [ @$indent, $indent2 ], $lines | ||||
| 309 | ); | ||||
| 310 | } | ||||
| 311 | |||||
| 312 | } elsif ( $lines->[0] =~ /^(\s*)\S/ ) { | ||||
| 313 | push @$array, { }; | ||||
| 314 | $self->_load_hash( | ||||
| 315 | $array->[-1], [ @$indent, length("$1") ], $lines | ||||
| 316 | ); | ||||
| 317 | |||||
| 318 | } else { | ||||
| 319 | die \"failed to classify line '$lines->[0]'"; | ||||
| 320 | } | ||||
| 321 | |||||
| 322 | } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) { | ||||
| 323 | # Array entry with a value | ||||
| 324 | 2 | 0s | shift @$lines; | ||
| 325 | 2 | 0s | 2 | 0s | push @$array, $self->_load_scalar( # spent 0s making 2 calls to Portable::LoadYaml::_load_scalar, avg 0s/call |
| 326 | "$2", [ @$indent, undef ], $lines | ||||
| 327 | ); | ||||
| 328 | |||||
| 329 | } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) { | ||||
| 330 | # This is probably a structure like the following... | ||||
| 331 | # --- | ||||
| 332 | # foo: | ||||
| 333 | # - list | ||||
| 334 | # bar: value | ||||
| 335 | # | ||||
| 336 | # ... so lets return and let the hash parser handle it | ||||
| 337 | return 1; | ||||
| 338 | |||||
| 339 | } else { | ||||
| 340 | die \"failed to classify line '$lines->[0]'"; | ||||
| 341 | } | ||||
| 342 | } | ||||
| 343 | |||||
| 344 | 1 | 0s | return 1; | ||
| 345 | } | ||||
| 346 | |||||
| 347 | # Load a hash | ||||
| 348 | sub _load_hash { | ||||
| 349 | 6 | 0s | my ($self, $hash, $indent, $lines) = @_; | ||
| 350 | |||||
| 351 | 6 | 0s | while ( @$lines ) { | ||
| 352 | # Check for a new document | ||||
| 353 | 107 | 0s | 107 | 0s | if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { # spent 0s making 107 calls to Portable::LoadYaml::CORE:match, avg 0s/call |
| 354 | while ( @$lines and $lines->[0] !~ /^---/ ) { | ||||
| 355 | shift @$lines; | ||||
| 356 | } | ||||
| 357 | return 1; | ||||
| 358 | } | ||||
| 359 | |||||
| 360 | # Check the indent level | ||||
| 361 | 107 | 0s | 107 | 0s | $lines->[0] =~ /^(\s*)/; # spent 0s making 107 calls to Portable::LoadYaml::CORE:match, avg 0s/call |
| 362 | 107 | 0s | if ( length($1) < $indent->[-1] ) { | ||
| 363 | return 1; | ||||
| 364 | } elsif ( length($1) > $indent->[-1] ) { | ||||
| 365 | die \"found bad indenting in line '$lines->[0]'"; | ||||
| 366 | } | ||||
| 367 | |||||
| 368 | # Find the key | ||||
| 369 | 103 | 0s | my $key; | ||
| 370 | |||||
| 371 | # Quoted keys | ||||
| 372 | 103 | 0s | 618 | 0s | if ( $lines->[0] =~ # spent 0s making 309 calls to Portable::LoadYaml::CORE:regcomp, avg 0s/call
# spent 0s making 309 calls to Portable::LoadYaml::CORE:subst, avg 0s/call |
| 373 | s/^\s*$re_capture_single_quoted$re_key_value_separator// | ||||
| 374 | ) { | ||||
| 375 | $key = $self->_unquote_single($1); | ||||
| 376 | } | ||||
| 377 | elsif ( $lines->[0] =~ | ||||
| 378 | s/^\s*$re_capture_double_quoted$re_key_value_separator// | ||||
| 379 | ) { | ||||
| 380 | $key = $self->_unquote_double($1); | ||||
| 381 | } | ||||
| 382 | elsif ( $lines->[0] =~ | ||||
| 383 | s/^\s*$re_capture_unquoted_key$re_key_value_separator// | ||||
| 384 | ) { | ||||
| 385 | 103 | 0s | $key = $1; | ||
| 386 | 103 | 0s | 103 | 0s | $key =~ s/\s+$//; # spent 0s making 103 calls to Portable::LoadYaml::CORE:subst, avg 0s/call |
| 387 | } | ||||
| 388 | elsif ( $lines->[0] =~ /^\s*\?/ ) { | ||||
| 389 | die \"does not support a feature in line '$lines->[0]'"; | ||||
| 390 | } | ||||
| 391 | else { | ||||
| 392 | die \"failed to classify line '$lines->[0]'"; | ||||
| 393 | } | ||||
| 394 | |||||
| 395 | # Do we have a value? | ||||
| 396 | 103 | 0s | 97 | 15.6ms | if ( length $lines->[0] ) { # spent 15.6ms making 97 calls to Portable::LoadYaml::_load_scalar, avg 161µs/call |
| 397 | # Yes | ||||
| 398 | $hash->{$key} = $self->_load_scalar( | ||||
| 399 | shift(@$lines), [ @$indent, undef ], $lines | ||||
| 400 | ); | ||||
| 401 | } else { | ||||
| 402 | # An indent | ||||
| 403 | 6 | 0s | shift @$lines; | ||
| 404 | 6 | 0s | unless ( @$lines ) { | ||
| 405 | $hash->{$key} = undef; | ||||
| 406 | return 1; | ||||
| 407 | } | ||||
| 408 | 6 | 0s | 11 | 0s | if ( $lines->[0] =~ /^(\s*)-/ ) { # spent 0s making 11 calls to Portable::LoadYaml::CORE:match, avg 0s/call |
| 409 | 1 | 0s | $hash->{$key} = []; | ||
| 410 | 1 | 0s | 1 | 0s | $self->_load_array( # spent 0s making 1 call to Portable::LoadYaml::_load_array |
| 411 | $hash->{$key}, [ @$indent, length($1) ], $lines | ||||
| 412 | ); | ||||
| 413 | } elsif ( $lines->[0] =~ /^(\s*)./ ) { | ||||
| 414 | 5 | 0s | my $indent2 = length("$1"); | ||
| 415 | 5 | 0s | if ( $indent->[-1] >= $indent2 ) { | ||
| 416 | # Null hash entry | ||||
| 417 | $hash->{$key} = undef; | ||||
| 418 | } else { | ||||
| 419 | 5 | 0s | $hash->{$key} = {}; | ||
| 420 | 5 | 0s | 5 | 0s | $self->_load_hash( # spent 15.6ms making 5 calls to Portable::LoadYaml::_load_hash, avg 3.12ms/call, recursion: max depth 1, sum of overlapping time 15.6ms |
| 421 | $hash->{$key}, [ @$indent, length($1) ], $lines | ||||
| 422 | ); | ||||
| 423 | } | ||||
| 424 | } | ||||
| 425 | } | ||||
| 426 | } | ||||
| 427 | |||||
| 428 | 2 | 0s | return 1; | ||
| 429 | } | ||||
| 430 | |||||
| 431 | 1 | 0s | 1; | ||
# spent 0s within Portable::LoadYaml::CORE:close which was called:
# once (0s+0s) by Portable::LoadYaml::_load_file at line 87 | |||||
# spent 0s within Portable::LoadYaml::CORE:fteread which was called:
# once (0s+0s) by Portable::LoadYaml::_load_file at line 67 | |||||
# spent 0s within Portable::LoadYaml::CORE:ftfile which was called:
# once (0s+0s) by Portable::LoadYaml::_load_file at line 65 | |||||
# spent 0s within Portable::LoadYaml::CORE:ftis which was called:
# once (0s+0s) by Portable::LoadYaml::_load_file at line 63 | |||||
# spent 0s within Portable::LoadYaml::CORE:match which was called 906 times, avg 0s/call:
# 132 times (0s+0s) by Portable::LoadYaml::_load_scalar at line 235, avg 0s/call
# 107 times (0s+0s) by Portable::LoadYaml::_load_hash at line 353, avg 0s/call
# 107 times (0s+0s) by Portable::LoadYaml::_load_hash at line 361, avg 0s/call
# 106 times (0s+0s) by Portable::LoadYaml::_load_string at line 123, avg 0s/call
# 98 times (0s+0s) by Portable::LoadYaml::_load_scalar at line 217, avg 0s/call
# 66 times (0s+0s) by Portable::LoadYaml::_load_scalar at line 230, avg 0s/call
# 66 times (0s+0s) by Portable::LoadYaml::_load_scalar at line 222, avg 0s/call
# 66 times (0s+0s) by Portable::LoadYaml::_load_scalar at line 231, avg 0s/call
# 66 times (0s+0s) by Portable::LoadYaml::_load_scalar at line 234, avg 0s/call
# 66 times (0s+0s) by Portable::LoadYaml::_load_scalar at line 227, avg 0s/call
# 11 times (0s+0s) by Portable::LoadYaml::_load_hash at line 408, avg 0s/call
# 6 times (0s+0s) by Portable::LoadYaml::_load_array at line 286, avg 0s/call
# 3 times (0s+0s) by Portable::LoadYaml::_load_string at line 144, avg 0s/call
# 2 times (0s+0s) by Portable::LoadYaml::_load_array at line 271, avg 0s/call
# 2 times (0s+0s) by Portable::LoadYaml::_load_array at line 279, avg 0s/call
# once (0s+0s) by Portable::LoadYaml::_load_string at line 127
# once (0s+0s) by Portable::LoadYaml::_load_string at line 133 | |||||
# spent 0s within Portable::LoadYaml::CORE:open which was called:
# once (0s+0s) by Portable::LoadYaml::_load_file at line 71 | |||||
# spent 0s within Portable::LoadYaml::CORE:qr which was called 5 times, avg 0s/call:
# once (0s+0s) by Portable::BEGIN@54 at line 51
# once (0s+0s) by Portable::BEGIN@54 at line 48
# once (0s+0s) by Portable::BEGIN@54 at line 47
# once (0s+0s) by Portable::BEGIN@54 at line 50
# once (0s+0s) by Portable::BEGIN@54 at line 52 | |||||
# spent 0s within Portable::LoadYaml::CORE:readline which was called:
# once (0s+0s) by Portable::LoadYaml::_load_file at line 81 | |||||
# spent 0s within Portable::LoadYaml::CORE:regcomp which was called 473 times, avg 0s/call:
# 309 times (0s+0s) by Portable::LoadYaml::_load_hash at line 372, avg 0s/call
# 98 times (0s+0s) by Portable::LoadYaml::_load_scalar at line 217, avg 0s/call
# 66 times (0s+0s) by Portable::LoadYaml::_load_scalar at line 222, avg 0s/call | |||||
# spent 0s within Portable::LoadYaml::CORE:subst which was called 586 times, avg 0s/call:
# 309 times (0s+0s) by Portable::LoadYaml::_load_hash at line 372, avg 0s/call
# 103 times (0s+0s) by Portable::LoadYaml::_load_hash at line 386, avg 0s/call
# 99 times (0s+0s) by Portable::LoadYaml::_load_scalar at line 211, avg 0s/call
# 66 times (0s+0s) by Portable::LoadYaml::_load_scalar at line 238, avg 0s/call
# 8 times (0s+0s) by Portable::LoadYaml::_unquote_single at line 192, avg 0s/call
# once (0s+0s) by Portable::LoadYaml::_load_string at line 117 |