Filename | /Users/ether/.perlbrew/libs/36.0@std/lib/perl5/YAML/PP/Dumper.pm |
Statements | Executed 34 statements in 3.72ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 6.58ms | 6.87ms | BEGIN@9 | YAML::PP::Dumper::
1 | 1 | 1 | 1.94ms | 2.16ms | BEGIN@10 | YAML::PP::Dumper::
1 | 1 | 1 | 949µs | 1.31ms | BEGIN@12 | YAML::PP::Dumper::
1 | 1 | 1 | 642µs | 721µs | BEGIN@11 | YAML::PP::Dumper::
1 | 1 | 1 | 30µs | 96µs | new | YAML::PP::Dumper::
1 | 1 | 1 | 26µs | 30µs | BEGIN@1.292 | YAML::PP::
1 | 1 | 1 | 11µs | 65µs | BEGIN@13 | YAML::PP::Dumper::
1 | 1 | 1 | 11µs | 50µs | BEGIN@7 | YAML::PP::Dumper::
1 | 1 | 1 | 10µs | 10µs | BEGIN@8 | YAML::PP::Dumper::
1 | 1 | 1 | 7µs | 38µs | BEGIN@2.293 | YAML::PP::
0 | 0 | 0 | 0s | 0s | _check_references | YAML::PP::Dumper::
0 | 0 | 0 | 0s | 0s | _dump_node | YAML::PP::Dumper::
0 | 0 | 0 | 0s | 0s | _emit_node | YAML::PP::Dumper::
0 | 0 | 0 | 0s | 0s | clone | YAML::PP::Dumper::
0 | 0 | 0 | 0s | 0s | dump | YAML::PP::Dumper::
0 | 0 | 0 | 0s | 0s | dump_file | YAML::PP::Dumper::
0 | 0 | 0 | 0s | 0s | dump_string | YAML::PP::Dumper::
0 | 0 | 0 | 0s | 0s | emitter | YAML::PP::Dumper::
0 | 0 | 0 | 0s | 0s | footer | YAML::PP::Dumper::
0 | 0 | 0 | 0s | 0s | header | YAML::PP::Dumper::
0 | 0 | 0 | 0s | 0s | init | YAML::PP::Dumper::
0 | 0 | 0 | 0s | 0s | representer | YAML::PP::Dumper::
0 | 0 | 0 | 0s | 0s | set_representer | YAML::PP::Dumper::
0 | 0 | 0 | 0s | 0s | version_directive | YAML::PP::Dumper::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | 2 | 29µs | 2 | 34µs | # spent 30µs (26+4) within YAML::PP::BEGIN@1.292 which was called:
# once (26µs+4µs) by YAML::PP::BEGIN@11 at line 1 # spent 30µs making 1 call to YAML::PP::BEGIN@1.292
# spent 4µs making 1 call to strict::import |
2 | 2 | 55µs | 2 | 69µs | # spent 38µs (7+31) within YAML::PP::BEGIN@2.293 which was called:
# once (7µs+31µs) by YAML::PP::BEGIN@11 at line 2 # spent 38µs making 1 call to YAML::PP::BEGIN@2.293
# spent 31µs making 1 call to warnings::import |
3 | package YAML::PP::Dumper; | ||||
4 | |||||
5 | 1 | 1µs | our $VERSION = '0.035'; # VERSION | ||
6 | |||||
7 | 2 | 28µs | 2 | 89µs | # spent 50µs (11+39) within YAML::PP::Dumper::BEGIN@7 which was called:
# once (11µs+39µs) by YAML::PP::BEGIN@11 at line 7 # spent 50µs making 1 call to YAML::PP::Dumper::BEGIN@7
# spent 39µs making 1 call to Exporter::import |
8 | 2 | 20µs | 2 | 10µs | # spent 10µs within YAML::PP::Dumper::BEGIN@8 which was called:
# once (10µs+0s) by YAML::PP::BEGIN@11 at line 8 # spent 10µs making 1 call to YAML::PP::Dumper::BEGIN@8
# spent 0s making 1 call to YAML::PP::Dumper::__ANON__ |
9 | 2 | 387µs | 2 | 6.88ms | # spent 6.87ms (6.58+297µs) within YAML::PP::Dumper::BEGIN@9 which was called:
# once (6.58ms+297µs) by YAML::PP::BEGIN@11 at line 9 # spent 6.87ms making 1 call to YAML::PP::Dumper::BEGIN@9
# spent 3µs making 1 call to YAML::PP::Dumper::__ANON__ |
10 | 2 | 443µs | 2 | 2.16ms | # spent 2.16ms (1.94+224µs) within YAML::PP::Dumper::BEGIN@10 which was called:
# once (1.94ms+224µs) by YAML::PP::BEGIN@11 at line 10 # spent 2.16ms making 1 call to YAML::PP::Dumper::BEGIN@10
# spent 3µs making 1 call to YAML::PP::Dumper::__ANON__ |
11 | 2 | 432µs | 2 | 722µs | # spent 721µs (642+79) within YAML::PP::Dumper::BEGIN@11 which was called:
# once (642µs+79µs) by YAML::PP::BEGIN@11 at line 11 # spent 721µs making 1 call to YAML::PP::Dumper::BEGIN@11
# spent 1µs making 1 call to YAML::PP::Dumper::__ANON__ |
12 | 2 | 530µs | 2 | 1.31ms | # spent 1.31ms (949µs+358µs) within YAML::PP::Dumper::BEGIN@12 which was called:
# once (949µs+358µs) by YAML::PP::BEGIN@11 at line 12 # spent 1.31ms making 1 call to YAML::PP::Dumper::BEGIN@12
# spent 2µs making 1 call to YAML::PP::Dumper::__ANON__ |
13 | 1 | 1µs | # spent 65µs (11+54) within YAML::PP::Dumper::BEGIN@13 which was called:
# once (11µs+54µs) by YAML::PP::BEGIN@11 at line 20 | ||
14 | YAML_PLAIN_SCALAR_STYLE YAML_SINGLE_QUOTED_SCALAR_STYLE | ||||
15 | YAML_DOUBLE_QUOTED_SCALAR_STYLE | ||||
16 | YAML_ANY_SCALAR_STYLE | ||||
17 | YAML_LITERAL_SCALAR_STYLE YAML_FOLDED_SCALAR_STYLE | ||||
18 | YAML_FLOW_SEQUENCE_STYLE YAML_FLOW_MAPPING_STYLE | ||||
19 | YAML_BLOCK_MAPPING_STYLE YAML_BLOCK_SEQUENCE_STYLE | ||||
20 | 1 | 1.75ms | 2 | 119µs | /; # spent 65µs making 1 call to YAML::PP::Dumper::BEGIN@13
# spent 54µs making 1 call to Exporter::import |
21 | |||||
22 | # spent 96µs (30+66) within YAML::PP::Dumper::new which was called:
# once (30µs+66µs) by YAML::PP::new at line 73 of YAML/PP.pm | ||||
23 | 1 | 4µs | my ($class, %args) = @_; | ||
24 | |||||
25 | 1 | 1µs | my $header = delete $args{header}; | ||
26 | 1 | 1µs | $header = 1 unless defined $header; | ||
27 | 1 | 0s | my $footer = delete $args{footer}; | ||
28 | 1 | 0s | $footer = 0 unless defined $footer; | ||
29 | 1 | 1µs | my $version_directive = delete $args{version_directive}; | ||
30 | 1 | 1µs | my $preserve = delete $args{preserve}; | ||
31 | |||||
32 | 1 | 0s | my $schema = delete $args{schema} || YAML::PP->default_schema( | ||
33 | boolean => 'perl', | ||||
34 | ); | ||||
35 | |||||
36 | 1 | 0s | my $emitter = delete $args{emitter} || YAML::PP::Emitter->new; | ||
37 | 1 | 12µs | 2 | 58µs | unless (blessed($emitter)) { # spent 56µs making 1 call to YAML::PP::Emitter::new
# spent 2µs making 1 call to Scalar::Util::blessed |
38 | $emitter = YAML::PP::Emitter->new( | ||||
39 | %$emitter | ||||
40 | ); | ||||
41 | } | ||||
42 | |||||
43 | 1 | 0s | if (keys %args) { | ||
44 | die "Unexpected arguments: " . join ', ', sort keys %args; | ||||
45 | } | ||||
46 | 1 | 8µs | 1 | 8µs | my $self = bless { # spent 8µs making 1 call to YAML::PP::Representer::new |
47 | representer => YAML::PP::Representer->new( | ||||
48 | schema => $schema, | ||||
49 | preserve => $preserve, | ||||
50 | ), | ||||
51 | version_directive => $version_directive, | ||||
52 | emitter => $emitter, | ||||
53 | seen => {}, | ||||
54 | anchors => {}, | ||||
55 | anchor_num => 0, | ||||
56 | header => $header, | ||||
57 | footer => $footer, | ||||
58 | }, $class; | ||||
59 | 1 | 3µs | return $self; | ||
60 | } | ||||
61 | |||||
62 | sub clone { | ||||
63 | my ($self) = @_; | ||||
64 | my $clone = { | ||||
65 | representer => $self->representer->clone, | ||||
66 | emitter => $self->emitter->clone, | ||||
67 | version_directive => $self->version_directive, | ||||
68 | seen => {}, | ||||
69 | anchors => {}, | ||||
70 | anchor_num => 0, | ||||
71 | header => $self->header, | ||||
72 | footer => $self->footer, | ||||
73 | }; | ||||
74 | return bless $clone, ref $self; | ||||
75 | } | ||||
76 | |||||
77 | sub init { | ||||
78 | my ($self) = @_; | ||||
79 | $self->{seen} = {}; | ||||
80 | $self->{anchors} = {}; | ||||
81 | $self->{anchor_num} = 0; | ||||
82 | } | ||||
83 | |||||
84 | sub emitter { return $_[0]->{emitter} } | ||||
85 | sub representer { return $_[0]->{representer} } | ||||
86 | sub set_representer { $_[0]->{representer} = $_[1] } | ||||
87 | sub header { return $_[0]->{header} } | ||||
88 | sub footer { return $_[0]->{footer} } | ||||
89 | sub version_directive { return $_[0]->{version_directive} } | ||||
90 | |||||
91 | sub dump { | ||||
92 | my ($self, @docs) = @_; | ||||
93 | $self->emitter->init; | ||||
94 | |||||
95 | $self->emitter->stream_start_event({}); | ||||
96 | |||||
97 | for my $i (0 .. $#docs) { | ||||
98 | my $header_implicit = ($i == 0 and not $self->header); | ||||
99 | my %args = ( | ||||
100 | implicit => $header_implicit, | ||||
101 | ); | ||||
102 | if ($self->version_directive) { | ||||
103 | my ($major, $minor) = split m/\./, $self->representer->schema->yaml_version; | ||||
104 | $args{version_directive} = { major => $major, minor => $minor }; | ||||
105 | } | ||||
106 | $self->emitter->document_start_event( \%args ); | ||||
107 | $self->init; | ||||
108 | $self->_check_references($docs[ $i ]); | ||||
109 | $self->_dump_node($docs[ $i ]); | ||||
110 | my $footer_implicit = (not $self->footer); | ||||
111 | $self->emitter->document_end_event({ implicit => $footer_implicit }); | ||||
112 | } | ||||
113 | |||||
114 | $self->emitter->stream_end_event({}); | ||||
115 | |||||
116 | my $output = $self->emitter->writer->output; | ||||
117 | $self->emitter->finish; | ||||
118 | return $output; | ||||
119 | } | ||||
120 | |||||
121 | sub _dump_node { | ||||
122 | my ($self, $value) = @_; | ||||
123 | my $node = { | ||||
124 | value => $value, | ||||
125 | }; | ||||
126 | if (ref $value) { | ||||
127 | |||||
128 | my $seen = $self->{seen}; | ||||
129 | my $refaddr = refaddr $value; | ||||
130 | if ($seen->{ $refaddr } and $seen->{ $refaddr } > 1) { | ||||
131 | my $anchor = $self->{anchors}->{ $refaddr }; | ||||
132 | unless (defined $anchor) { | ||||
133 | if ($self->representer->preserve_alias) { | ||||
134 | if (ref $node->{value} eq 'YAML::PP::Preserve::Scalar') { | ||||
135 | if (defined $node->{value}->alias) { | ||||
136 | $node->{anchor} = $node->{value}->alias; | ||||
137 | $self->{anchors}->{ $refaddr } = $node->{value}->alias; | ||||
138 | } | ||||
139 | } | ||||
140 | elsif (reftype $node->{value} eq 'HASH') { | ||||
141 | if (my $tied = tied %{ $node->{value} } ) { | ||||
142 | if (defined $tied->{alias}) { | ||||
143 | $node->{anchor} = $tied->{alias}; | ||||
144 | $self->{anchors}->{ $refaddr } = $node->{anchor}; | ||||
145 | } | ||||
146 | } | ||||
147 | } | ||||
148 | elsif (reftype $node->{value} eq 'ARRAY') { | ||||
149 | if (my $tied = tied @{ $node->{value} } ) { | ||||
150 | if (defined $tied->{alias}) { | ||||
151 | $node->{anchor} = $tied->{alias}; | ||||
152 | $self->{anchors}->{ $refaddr } = $node->{anchor}; | ||||
153 | } | ||||
154 | } | ||||
155 | } | ||||
156 | } | ||||
157 | unless (defined $node->{anchor}) { | ||||
158 | my $num = ++$self->{anchor_num}; | ||||
159 | $self->{anchors}->{ $refaddr } = $num; | ||||
160 | $node->{anchor} = $num; | ||||
161 | } | ||||
162 | } | ||||
163 | else { | ||||
164 | $node->{value} = $anchor; | ||||
165 | $self->_emit_node([ alias => $node ]); | ||||
166 | return; | ||||
167 | } | ||||
168 | |||||
169 | } | ||||
170 | } | ||||
171 | $node = $self->representer->represent_node($node); | ||||
172 | $self->_emit_node($node); | ||||
173 | } | ||||
174 | |||||
175 | sub _emit_node { | ||||
176 | my ($self, $item) = @_; | ||||
177 | my ($type, $node, %args) = @$item; | ||||
178 | if ($type eq 'alias') { | ||||
179 | $self->emitter->alias_event({ value => $node->{value} }); | ||||
180 | return; | ||||
181 | } | ||||
182 | if ($type eq 'mapping') { | ||||
183 | my $style = $args{style} || YAML_BLOCK_MAPPING_STYLE; | ||||
184 | # TODO | ||||
185 | if ($node->{items} and @{ $node->{items} } == 0) { | ||||
186 | # $style = YAML_FLOW_MAPPING_STYLE; | ||||
187 | } | ||||
188 | $self->emitter->mapping_start_event({ | ||||
189 | anchor => $node->{anchor}, | ||||
190 | style => $style, | ||||
191 | tag => $node->{tag}, | ||||
192 | }); | ||||
193 | for (@{ $node->{items} }) { | ||||
194 | $self->_dump_node($_); | ||||
195 | } | ||||
196 | $self->emitter->mapping_end_event; | ||||
197 | return; | ||||
198 | } | ||||
199 | if ($type eq 'sequence') { | ||||
200 | my $style = $args{style} || YAML_BLOCK_SEQUENCE_STYLE; | ||||
201 | if (@{ $node->{items} } == 0) { | ||||
202 | # $style = YAML_FLOW_SEQUENCE_STYLE; | ||||
203 | } | ||||
204 | $self->emitter->sequence_start_event({ | ||||
205 | anchor => $node->{anchor}, | ||||
206 | style => $style, | ||||
207 | tag => $node->{tag}, | ||||
208 | }); | ||||
209 | for (@{ $node->{items} }) { | ||||
210 | $self->_dump_node($_); | ||||
211 | } | ||||
212 | $self->emitter->sequence_end_event; | ||||
213 | return; | ||||
214 | } | ||||
215 | $self->emitter->scalar_event({ | ||||
216 | value => $node->{items}->[0], | ||||
217 | style => $node->{style}, | ||||
218 | anchor => $node->{anchor}, | ||||
219 | tag => $node->{tag}, | ||||
220 | }); | ||||
221 | } | ||||
222 | |||||
223 | |||||
224 | sub dump_string { | ||||
225 | my ($self, @docs) = @_; | ||||
226 | my $writer = YAML::PP::Writer->new; | ||||
227 | $self->emitter->set_writer($writer); | ||||
228 | my $output = $self->dump(@docs); | ||||
229 | return $output; | ||||
230 | } | ||||
231 | |||||
232 | sub dump_file { | ||||
233 | my ($self, $file, @docs) = @_; | ||||
234 | my $writer = YAML::PP::Writer::File->new(output => $file); | ||||
235 | $self->emitter->set_writer($writer); | ||||
236 | my $output = $self->dump(@docs); | ||||
237 | return $output; | ||||
238 | } | ||||
239 | |||||
240 | 1 | 4µs | my %_reftypes = ( | ||
241 | HASH => 1, | ||||
242 | ARRAY => 1, | ||||
243 | Regexp => 1, | ||||
244 | REGEXP => 1, | ||||
245 | CODE => 1, | ||||
246 | SCALAR => 1, | ||||
247 | REF => 1, | ||||
248 | GLOB => 1, | ||||
249 | ); | ||||
250 | |||||
251 | sub _check_references { | ||||
252 | my ($self, $doc) = @_; | ||||
253 | my $reftype = reftype $doc or return; | ||||
254 | my $seen = $self->{seen}; | ||||
255 | # check which references are used more than once | ||||
256 | if ($reftype eq 'SCALAR' and | ||||
257 | grep { ref $doc eq $_ } @{ $self->representer->schema->bool_class || [] }) { | ||||
258 | # JSON::PP and boolean.pm always return the same reference for booleans | ||||
259 | # Avoid printing *aliases in those case | ||||
260 | if (ref $doc eq 'boolean' or ref $doc eq 'JSON::PP::Boolean') { | ||||
261 | return; | ||||
262 | } | ||||
263 | } | ||||
264 | if (++$seen->{ refaddr $doc } > 1) { | ||||
265 | # seen already | ||||
266 | return; | ||||
267 | } | ||||
268 | unless ($_reftypes{ $reftype }) { | ||||
269 | die sprintf "Reference %s not implemented", | ||||
270 | $reftype; | ||||
271 | } | ||||
272 | if ($reftype eq 'HASH') { | ||||
273 | $self->_check_references($doc->{ $_ }) for keys %$doc; | ||||
274 | } | ||||
275 | elsif ($reftype eq 'ARRAY') { | ||||
276 | $self->_check_references($_) for @$doc; | ||||
277 | } | ||||
278 | elsif ($reftype eq 'REF') { | ||||
279 | $self->_check_references($$doc); | ||||
280 | } | ||||
281 | } | ||||
282 | |||||
283 | 1 | 7µs | 1; |