File Coverage

blib/lib/YAML/PP/Emitter.pm
Criterion Covered Total %
statement 545 566 96.2
branch 351 378 92.8
condition 91 92 98.9
subroutine 36 37 97.3
pod 17 25 68.0
total 1040 1098 94.7


line stmt bran cond sub pod time code
1 49     49   177209 use strict;
  49         72  
  49         1352  
2 49     49   155 use warnings;
  49         60  
  49         3066  
3             package YAML::PP::Emitter;
4              
5             our $VERSION = 'v0.41.0'; # VERSION
6 49     49   14637 use Data::Dumper;
  49         197116  
  49         3372  
7              
8 49         3188 use YAML::PP::Common qw/
9             YAML_PLAIN_SCALAR_STYLE YAML_SINGLE_QUOTED_SCALAR_STYLE
10             YAML_DOUBLE_QUOTED_SCALAR_STYLE
11             YAML_LITERAL_SCALAR_STYLE YAML_FOLDED_SCALAR_STYLE
12             YAML_FLOW_SEQUENCE_STYLE YAML_FLOW_MAPPING_STYLE
13 49     49   761 /;
  49         78  
14              
15 49 50   49   256 use constant DEBUG => $ENV{YAML_PP_EMIT_DEBUG} ? 1 : 0;
  49         67  
  49         2711  
16 49     49   209 use constant DEFAULT_WIDTH => 80;
  49         81  
  49         284106  
17              
18             sub new {
19 2243     2243 1 187730 my ($class, %args) = @_;
20             my $self = bless {
21             indent => $args{indent} || 2,
22             writer => $args{writer},
23 2243   100     20095 width => $args{width} || DEFAULT_WIDTH,
      50        
24             }, $class;
25 2243         7484 $self->init;
26 2243         4745 return $self;
27             }
28              
29             sub clone {
30 9     9 0 11 my ($self) = @_;
31 9         19 my $clone = {
32             indent => $self->indent,
33             };
34 9         29 return bless $clone, ref $self;
35             }
36              
37 44735     44735 0 53712 sub event_stack { return $_[0]->{event_stack} }
38 6545     6545 0 16872 sub set_event_stack { $_[0]->{event_stack} = $_[1] }
39 4579     4579 1 10070 sub indent { return $_[0]->{indent} }
40 1415     1415 0 2340 sub width { return $_[0]->{width} }
41 0     0 0 0 sub line { return $_[0]->{line} }
42 21567     21567 0 54207 sub column { return $_[0]->{column} }
43 1     1 1 839 sub set_indent { $_[0]->{indent} = $_[1] }
44 28419     28419 1 60426 sub writer { $_[0]->{writer} }
45 5207     5207 1 12963 sub set_writer { $_[0]->{writer} = $_[1] }
46 649     649 0 901 sub tagmap { return $_[0]->{tagmap} }
47 5308     5308 0 9021 sub set_tagmap { $_[0]->{tagmap} = $_[1] }
48              
49             sub init {
50 5308     5308 1 87744 my ($self) = @_;
51 5308 100       9422 unless ($self->writer) {
52 2242         5826 $self->set_writer(YAML::PP::Writer->new);
53             }
54             $self->set_tagmap({
55 5308         15231 'tag:yaml.org,2002:' => '!!',
56             });
57 5308         8214 $self->{open_ended} = 0;
58 5308         6837 $self->{line} = 0;
59 5308         7485 $self->{column} = 0;
60 5308         7586 $self->writer->init;
61             }
62              
63             sub mapping_start_event {
64 1940     1940 1 14518 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ mapping_start_event\n";
65 1940         2737 my ($self, $info) = @_;
66 1940         3325 my $stack = $self->event_stack;
67 1940         2529 my $last = $stack->[-1];
68 1940         2670 my $indent = $last->{indent};
69 1940         2625 my $new_indent = $indent;
70 1940         2334 my $yaml = '';
71              
72 1940         2192 my $props = '';
73 1940         2788 my $anchor = $info->{anchor};
74 1940         2530 my $tag = $info->{tag};
75 1940 100       3496 if (defined $anchor) {
76 98         154 $anchor = "&$anchor";
77             }
78 1940 100       3162 if (defined $tag) {
79 110         301 $tag = $self->_emit_tag('map', $tag);
80             }
81 1940         5246 $props = join ' ', grep defined, ($anchor, $tag);
82              
83 1940   100     5121 my $flow = $last->{flow} || 0;
84 1940 100 100     5807 $flow++ if ($info->{style} || 0) eq YAML_FLOW_MAPPING_STYLE;
85              
86 1940         2371 my $newline = 0;
87 1940 100       3138 if ($flow > 1) {
88 138 100       318 if ($last->{type} eq 'SEQ') {
    100          
    50          
89 95 100       196 if ($last->{newline}) {
90 17         27 $yaml .= ' ';
91             }
92 95 100       160 if ($last->{index} == 0) {
93 27         46 $yaml .= "[";
94             }
95             else {
96 68         118 $yaml .= ",";
97             }
98             }
99             elsif ($last->{type} eq 'MAP') {
100 2 50       7 if ($last->{newline}) {
101 0         0 $yaml .= ' ';
102             }
103 2 50       5 if ($last->{index} == 0) {
104 2         3 $yaml .= "{";
105             }
106             else {
107 0         0 $yaml .= ",";
108             }
109             }
110             elsif ($last->{type} eq 'MAPVALUE') {
111 41 50       72 if ($last->{index} == 0) {
112 0         0 die "Should not happen (index 0 in MAPVALUE)";
113             }
114 41         58 $yaml .= ": ";
115             }
116 138 100       209 if ($props) {
117 18         29 $yaml .= " $props ";
118             }
119 138         244 $new_indent .= ' ' x $self->indent;
120             }
121             else {
122 1802 100       3409 if ($last->{type} eq 'DOC') {
123 985         1607 $newline = $last->{newline};
124             }
125             else {
126 817 100       1506 if ($last->{newline}) {
127 108         196 $yaml .= "\n";
128 108         201 $last->{column} = 0;
129             }
130 817 100       1430 if ($last->{type} eq 'MAPVALUE') {
131 263         613 $new_indent .= ' ' x $self->indent;
132 263         350 $newline = 1;
133             }
134             else {
135 554         692 $new_indent = $indent;
136 554 100 100     1353 if (not $props and $self->indent == 1) {
137 91         113 $new_indent .= ' ' x 2;
138             }
139             else {
140 463         766 $new_indent .= ' ' x $self->indent;
141             }
142              
143 554 100       1146 if ($last->{column}) {
144 15 100       32 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
145 15         25 $yaml .= $space;
146             }
147             else {
148 539         683 $yaml .= $indent;
149             }
150 554 100       1038 if ($last->{type} eq 'SEQ') {
    100          
    50          
151 526         618 $yaml .= '-';
152             }
153             elsif ($last->{type} eq 'MAP') {
154 19         31 $yaml .= "?";
155 19         34 $last->{type} = 'COMPLEX';
156             }
157             elsif ($last->{type} eq 'COMPLEXVALUE') {
158 9         12 $yaml .= ":";
159             }
160             else {
161 0         0 die "Should not happen ($last->{type} in mapping_start)";
162             }
163 554         718 $last->{column} = 1;
164             }
165 817         1123 $last->{newline} = 0;
166             }
167 1802 100       3068 if ($props) {
168 159 100       327 $yaml .= $last->{column} ? ' ' : $indent;
169 159         206 $yaml .= $props;
170 159         194 $newline = 1;
171             }
172             }
173 1940         4161 $self->_write($yaml);
174 1940         3909 my $new_info = {
175             index => 0, indent => $new_indent, info => $info,
176             newline => $newline,
177             column => $self->column,
178             flow => $flow,
179             };
180 1940         3808 $new_info->{type} = 'MAP';
181 1940         2473 push @{ $stack }, $new_info;
  1940         3119  
182 1940         2532 $last->{index}++;
183 1940         4343 $self->{open_ended} = 0;
184             }
185              
186             sub mapping_end_event {
187 1939     1939 1 10148 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ mapping_end_event\n";
188 1939         2940 my ($self, $info) = @_;
189 1939         2937 my $stack = $self->event_stack;
190              
191 1939         2460 my $last = pop @{ $stack };
  1939         2873  
192 1939 100       4917 if ($last->{index} == 0) {
    100          
193 28         45 my $indent = $last->{indent};
194 28         40 my $zero_indent = $last->{zero_indent};
195 28 50       63 if ($last->{zero_indent}) {
196 0         0 $indent .= ' ' x $self->indent;
197             }
198 28 100       48 if ($self->column) {
199 22         38 $self->_write(" {}\n");
200             }
201             else {
202 6         27 $self->_write("$indent\{}\n");
203             }
204             }
205             elsif ($last->{flow}) {
206 359         414 my $yaml = "}";
207 359 100       606 if ($last->{flow} == 1) {
208 223         268 $yaml .= "\n";
209             }
210 359         672 $self->_write("$yaml");
211             }
212 1939         4700 $last = $stack->[-1];
213 1939         3157 $last->{column} = $self->column;
214 1939 100       8170 if ($last->{type} eq 'SEQ') {
    100          
    100          
    100          
    100          
215             }
216             elsif ($last->{type} eq 'MAP') {
217 2         5 $last->{type} = 'MAPVALUE';
218             }
219             elsif ($last->{type} eq 'MAPVALUE') {
220 304         614 $last->{type} = 'MAP';
221             }
222             elsif ($last->{type} eq 'COMPLEX') {
223 19         49 $last->{type} = 'COMPLEXVALUE';
224             }
225             elsif ($last->{type} eq 'COMPLEXVALUE') {
226 9         20 $last->{type} = 'MAP';
227             }
228             }
229              
230             sub sequence_start_event {
231 1355     1355 1 10265 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ sequence_start_event\n";
232 1355         2064 my ($self, $info) = @_;
233 1355         2516 my $stack = $self->event_stack;
234 1355         1878 my $last = $stack->[-1];
235 1355         1966 my $indent = $last->{indent};
236 1355         1681 my $new_indent = $indent;
237 1355         1713 my $yaml = '';
238              
239 1355         1547 my $props = '';
240 1355         1791 my $anchor = $info->{anchor};
241 1355         1622 my $tag = $info->{tag};
242 1355 100       2618 if (defined $anchor) {
243 44         89 $anchor = "&$anchor";
244             }
245 1355 100       2150 if (defined $tag) {
246 47         114 $tag = $self->_emit_tag('seq', $tag);
247             }
248 1355         3709 $props = join ' ', grep defined, ($anchor, $tag);
249              
250 1355   100     3599 my $flow = $last->{flow} || 0;
251 1355 100 100     5841 $flow++ if $flow or ($info->{style} || 0) eq YAML_FLOW_SEQUENCE_STYLE;
      100        
252 1355         1516 my $newline = 0;
253 1355         1586 my $zero_indent = 0;
254 1355 100       2445 if ($flow > 1) {
255 122 100       397 if ($last->{type} eq 'SEQ') {
    100          
    50          
256 52 50       98 if ($last->{newline}) {
257 0         0 $yaml .= ' ';
258             }
259 52 100       80 if ($last->{index} == 0) {
260 16         45 $yaml .= "[";
261             }
262             else {
263 36         46 $yaml .= ",";
264             }
265             }
266             elsif ($last->{type} eq 'MAP') {
267 14 100       36 if ($last->{newline}) {
268 1         2 $yaml .= ' ';
269             }
270 14 100       32 if ($last->{index} == 0) {
271 8         12 $yaml .= "{";
272             }
273             else {
274 6         14 $yaml .= ",";
275             }
276             }
277             elsif ($last->{type} eq 'MAPVALUE') {
278 56 50       123 if ($last->{index} == 0) {
279 0         0 die "Should not happen (index 0 in MAPVALUE)";
280             }
281 56         77 $yaml .= ": ";
282             }
283 122 100       223 if ($props) {
284 10         16 $yaml .= " $props ";
285             }
286 122         204 $new_indent .= ' ' x $self->indent;
287             }
288             else {
289 1233 100       2352 if ($last->{type} eq 'DOC') {
290 634         1121 $newline = $last->{newline};
291             }
292             else {
293 599 100       1240 if ($last->{newline}) {
294 51         72 $yaml .= "\n";
295 51         77 $last->{column} = 0;
296             }
297 599 100       1116 if ($last->{type} eq 'MAPVALUE') {
298 245         357 $zero_indent = 1;
299 245         317 $newline = 1;
300             }
301             else {
302 354 100 100     882 if (not $props and $self->indent == 1) {
303 68         73 $new_indent .= ' ' x 2;
304             }
305             else {
306 286         502 $new_indent .= ' ' x $self->indent;
307             }
308 354 100       667 if ($last->{column}) {
309 24 100       40 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
310 24         35 $yaml .= $space;
311             }
312             else {
313 330         429 $yaml .= $indent;
314             }
315 354 100       762 if ($last->{type} eq 'SEQ') {
    100          
    50          
316 278         308 $yaml .= "-";
317             }
318             elsif ($last->{type} eq 'MAP') {
319 47         80 $last->{type} = 'COMPLEX';
320 47         87 $zero_indent = 1;
321 47         62 $yaml .= "?";
322             }
323             elsif ($last->{type} eq 'COMPLEXVALUE') {
324 29         38 $yaml .= ":";
325 29         38 $zero_indent = 1;
326             }
327             else {
328 0         0 die "Should not happen ($last->{type} in sequence_start)";
329             }
330 354         472 $last->{column} = 1;
331             }
332 599         939 $last->{newline} = 0;
333             }
334 1233 100       2237 if ($props) {
335 73 100       195 $yaml .= $last->{column} ? ' ' : $indent;
336 73         108 $yaml .= $props;
337 73         95 $newline = 1;
338             }
339             }
340 1355         3199 $self->_write($yaml);
341 1355         1962 $last->{index}++;
342 1355         2824 my $new_info = {
343             index => 0,
344             indent => $new_indent,
345             info => $info,
346             zero_indent => $zero_indent,
347             newline => $newline,
348             column => $self->column,
349             flow => $flow,
350             };
351 1355         2570 $new_info->{type} = 'SEQ';
352 1355         1571 push @{ $stack }, $new_info;
  1355         2147  
353 1355         3240 $self->{open_ended} = 0;
354             }
355              
356             sub sequence_end_event {
357 1355     1355 1 7001 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ sequence_end_event\n";
358 1355         2026 my ($self, $info) = @_;
359 1355         2326 my $stack = $self->event_stack;
360              
361 1355         1764 my $last = pop @{ $stack };
  1355         2014  
362 1355 100       3467 if ($last->{index} == 0) {
    100          
363 59         87 my $indent = $last->{indent};
364 59         77 my $zero_indent = $last->{zero_indent};
365 59 100       124 if ($last->{zero_indent}) {
366 7         16 $indent .= ' ' x $self->indent;
367             }
368 59 100       102 my $yaml .= $self->column ? ' ' : $indent;
369 59         74 $yaml .= "[]";
370 59 100       113 if ($last->{flow} < 2) {
371 51         56 $yaml .= "\n";
372             }
373 59         88 $self->_write($yaml);
374             }
375             elsif ($last->{flow}) {
376 212         314 my $yaml = "]";
377 212 100       439 if ($last->{flow} == 1) {
378 98         124 $yaml .= "\n";
379             }
380 212         395 $self->_write($yaml);
381             }
382 1355         3305 $last = $stack->[-1];
383 1355         2070 $last->{column} = $self->column;
384 1355 100       5688 if ($last->{type} eq 'SEQ') {
    100          
    100          
    100          
    100          
385             }
386             elsif ($last->{type} eq 'MAP') {
387 14         31 $last->{type} = 'MAPVALUE';
388             }
389             elsif ($last->{type} eq 'MAPVALUE') {
390 301         710 $last->{type} = 'MAP';
391             }
392             elsif ($last->{type} eq 'COMPLEX') {
393 47         106 $last->{type} = 'COMPLEXVALUE';
394             }
395             elsif ($last->{type} eq 'COMPLEXVALUE') {
396 29         70 $last->{type} = 'MAP';
397             }
398             }
399              
400             my %forbidden_first = (qw/
401             ! 1 & 1 * 1 { 1 } 1 [ 1 ] 1 | 1 > 1 @ 1 ` 1 " 1 ' 1
402             /, '#' => 1, '%' => 1, ',' => 1, " " => 1);
403             my %forbidden_first_plus_space = (qw/
404             ? 1 - 1 : 1
405             /);
406              
407             my %control = (
408             "\x00" => '\0',
409             "\x01" => '\x01',
410             "\x02" => '\x02',
411             "\x03" => '\x03',
412             "\x04" => '\x04',
413             "\x05" => '\x05',
414             "\x06" => '\x06',
415             "\x07" => '\a',
416             "\x08" => '\b',
417             "\x0b" => '\v',
418             "\x0c" => '\f',
419             "\x0e" => '\x0e',
420             "\x0f" => '\x0f',
421             "\x10" => '\x10',
422             "\x11" => '\x11',
423             "\x12" => '\x12',
424             "\x13" => '\x13',
425             "\x14" => '\x14',
426             "\x15" => '\x15',
427             "\x16" => '\x16',
428             "\x17" => '\x17',
429             "\x18" => '\x18',
430             "\x19" => '\x19',
431             "\x1a" => '\x1a',
432             "\x1b" => '\e',
433             "\x1c" => '\x1c',
434             "\x1d" => '\x1d',
435             "\x1e" => '\x1e',
436             "\x1f" => '\x1f',
437             "\x7f" => '\x7f',
438             "\x80" => '\x80',
439             "\x81" => '\x81',
440             "\x82" => '\x82',
441             "\x83" => '\x83',
442             "\x84" => '\x84',
443             "\x86" => '\x86',
444             "\x87" => '\x87',
445             "\x88" => '\x88',
446             "\x89" => '\x89',
447             "\x8a" => '\x8a',
448             "\x8b" => '\x8b',
449             "\x8c" => '\x8c',
450             "\x8d" => '\x8d',
451             "\x8e" => '\x8e',
452             "\x8f" => '\x8f',
453             "\x90" => '\x90',
454             "\x91" => '\x91',
455             "\x92" => '\x92',
456             "\x93" => '\x93',
457             "\x94" => '\x94',
458             "\x95" => '\x95',
459             "\x96" => '\x96',
460             "\x97" => '\x97',
461             "\x98" => '\x98',
462             "\x99" => '\x99',
463             "\x9a" => '\x9a',
464             "\x9b" => '\x9b',
465             "\x9c" => '\x9c',
466             "\x9d" => '\x9d',
467             "\x9e" => '\x9e',
468             "\x9f" => '\x9f',
469             "\x{2029}" => '\P',
470             "\x{2028}" => '\L',
471             "\x85" => '\N',
472             "\xa0" => '\_',
473             );
474              
475             my $control_re = '\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x84\x86-\x9f\x{d800}-\x{dfff}\x{fffe}\x{ffff}\x{2028}\x{2029}\x85\xa0';
476             my %to_escape = (
477             "\n" => '\n',
478             "\t" => '\t',
479             "\r" => '\r',
480             '\\' => '\\\\',
481             '"' => '\\"',
482             %control,
483             );
484             my $escape_re = $control_re . '\n\t\r';
485             my $escape_re_without_lb = $control_re . '\t\r';
486              
487              
488             sub scalar_event {
489 9486     9486 1 41632 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ scalar_event\n";
490 9486         11285 my ($self, $info) = @_;
491 9486         13557 my $stack = $self->event_stack;
492 9486         11701 my $last = $stack->[-1];
493 9486         12204 my $indent = $last->{indent};
494 9486         12257 my $value = $info->{value};
495 9486         10614 my $flow = $last->{flow};
496              
497 9486         10569 my $props = '';
498 9486         10717 my $anchor = $info->{anchor};
499 9486         11299 my $tag = $info->{tag};
500 9486 100       14863 if (defined $anchor) {
501 460         657 $anchor = "&$anchor";
502             }
503 9486 100       14071 if (defined $tag) {
504 492         1032 $tag = $self->_emit_tag('scalar', $tag);
505             }
506 9486         19944 $props = join ' ', grep defined, ($anchor, $tag);
507              
508 9486         9764 DEBUG and local $Data::Dumper::Useqq = 1;
509 9486 50       12971 $value = '' unless defined $value;
510              
511 9486         16775 my $style = $self->_find_best_scalar_style(
512             info => $info,
513             value => $value,
514             );
515              
516 9486         11084 my $open_ended = 0;
517              
518 9486 100       16367 if ($style == YAML_PLAIN_SCALAR_STYLE) {
    100          
    100          
    100          
519 7726         12146 $value =~ s/\n/\n\n/g;
520             }
521             elsif ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
522 508         1141 my $new_indent = $last->{indent} . (' ' x $self->indent);
523 508         1035 $value =~ s/(\n+)/"\n" x (1 + (length $1))/eg;
  10         65  
524 508         1210 my @lines = split m/\n/, $value, -1;
525 508 100       977 if (@lines > 1) {
526 10         36 for my $line (@lines[1 .. $#lines]) {
527 20 100       54 $line = $new_indent . $line
528             if length $line;
529             }
530             }
531 508         905 $value = join "\n", @lines;
532 508         877 $value =~ s/'/''/g;
533 508         944 $value = "'" . $value . "'";
534             }
535             elsif ($style == YAML_LITERAL_SCALAR_STYLE) {
536 365         407 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$value], ['value']);
537 365         561 my $indicators = '';
538 365 100       1453 if ($value =~ m/\A\n* +/) {
539 36         74 $indicators .= $self->indent;
540             }
541 365         837 my $indent = $indent . ' ' x $self->indent;
542 365 100       2200 if ($value !~ m/\n\z/) {
    100          
543 87         136 $indicators .= '-';
544 87         247 $value .= "\n";
545             }
546             elsif ($value =~ m/(\n|\A)\n\z/) {
547 36         58 $indicators .= '+';
548 36         55 $open_ended = 1;
549             }
550 365         1936 $value =~ s/^(?=.)/$indent/gm;
551 365         837 $value = "|$indicators\n$value";
552             }
553             elsif ($style == YAML_FOLDED_SCALAR_STYLE) {
554 120         141 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$value], ['value']);
555 120         410 my @lines = split /\n/, $value, -1;
556 120         139 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\@lines], ['lines']);
557 120         215 my $trailing = -1;
558 120         263 while (@lines) {
559 218 100       452 last if $lines[-1] ne '';
560 99         151 pop @lines;
561 99         219 $trailing++;
562             }
563 120         155 my %start_with_space;
564 120         342 for my $i (0 .. $#lines) {
565 211 100       653 if ($lines[ $i ] =~ m/^[ \t]+/) {
566 31         76 $start_with_space{ $i } = 1;
567             }
568             }
569 120         221 my $indicators = '';
570 120 100       389 if ($value =~ m/\A\n* +/) {
571 19         41 $indicators .= $self->indent;
572             }
573 120         277 my $indent = $indent . ' ' x $self->indent;
574 120 100       348 if ($trailing > 0) {
    100          
575 3         4 $indicators .= '+';
576 3         4 $open_ended = 1;
577             }
578             elsif ($trailing < 0) {
579 24         38 $indicators .= '-';
580             }
581 120         185 $value = ">$indicators\n";
582 120         138 my $got_content = 0;
583 120         227 for my $i (0 .. $#lines) {
584 211         279 my $line = $lines[ $i ];
585 211   100     592 my $sp = $start_with_space{ $i } || 0;
586 211 100 100     491 my $spnext = $i == $#lines ? 1 : $start_with_space{ $i+1 } || 0;
587 211 100 100     507 my $spprev = $i == 0 ? 1 : $start_with_space{ $i-1 } || 0;
588 211 100       1824 my $empty = length $line ? 0 : 1;
589 211 100       427 my $emptynext = $i == $#lines ? '' : length $lines[$i+1] ? 0 : 1;
    100          
590 211         234 my $nl = 0;
591 211 100       349 if ($empty) {
592 47 100 100     154 if ($spnext and $spprev) {
    100          
    100          
593 8         9 $nl = 1;
594             }
595             elsif (not $spnext) {
596 37         63 $nl = 1;
597             }
598             elsif (not $got_content) {
599 1         2 $nl = 1;
600             }
601             }
602             else {
603 164         204 $got_content = 1;
604 164         254 $value .= "$indent$line\n";
605 164 100 100     481 if (not $sp and not $spnext) {
606 32         44 $nl = 1;
607             }
608             }
609 211 100       452 if ($nl) {
610 78         134 $value .= "\n";
611             }
612             }
613 120 100       348 $value .= "\n" x ($trailing) if $trailing > 0;
614             }
615             else {
616 767 50       3817 $value =~ s/([$escape_re"\\])/$to_escape{ $1 } || sprintf '\\u%04x', ord($1)/eg;
  722         2910  
617 767         1318 $value = '"' . $value . '"';
618             }
619              
620 9486         8924 DEBUG and warn __PACKAGE__.':'.__LINE__.": (@$stack)\n";
621 9486         17760 my $yaml = $self->_emit_scalar(
622             indent => $indent,
623             props => $props,
624             value => $value,
625             style => $style,
626             );
627              
628 9486         12341 $last->{index}++;
629 9486         11141 $last->{newline} = 0;
630 9486         17887 $self->_write($yaml);
631 9486         14295 $last->{column} = $self->column;
632 9486         30025 $self->{open_ended} = $open_ended;
633             }
634              
635             sub _find_best_scalar_style {
636 9486     9486   21053 my ($self, %args) = @_;
637 9486         12839 my $info = $args{info};
638 9486         12453 my $style = $info->{style};
639 9486         11635 my $value = $args{value};
640 9486         12899 my $stack = $self->event_stack;
641 9486         10662 my $last = $stack->[-1];
642 9486         10584 my $flow = $last->{flow};
643              
644 9486         16596 my $first = substr($value, 0, 1);
645 9486 100       45360 if ($value eq '') {
    100          
646 897 100 100     3102 if ($flow and $last->{type} ne 'MAPVALUE' and $last->{type} ne 'MAP') {
    100 100        
647 24         60 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
648             }
649             elsif (not $style) {
650 2         3 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
651             }
652             }
653             # no control characters anywhere
654             elsif ($value =~ m/[$control_re]/) {
655 55         89 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
656             }
657 9486   100     19708 $style ||= YAML_PLAIN_SCALAR_STYLE;
658              
659 9486 100 100     31330 if ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
    100          
    100          
660 356 100 100     2779 if ($value =~ m/ \n/ or $value =~ m/\n / or $value =~ m/^\n/ or $value =~ m/\n$/) {
    50 100        
      100        
661 16         25 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
662             }
663             elsif ($value eq "\n") {
664 0         0 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
665             }
666             }
667             elsif ($style == YAML_LITERAL_SCALAR_STYLE or $style == YAML_FOLDED_SCALAR_STYLE) {
668 444 100       1302 if ($value eq '') {
    100          
669 22         33 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
670             }
671             elsif ($flow) {
672             # no block scalars in flow
673 69 100       149 if ($value =~ tr/\n//) {
674 61         98 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
675             }
676             else {
677 8         13 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
678             }
679             }
680             }
681             elsif ($style == YAML_PLAIN_SCALAR_STYLE) {
682 8112 100 100     85278 if (not length $value) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    100          
683             }
684             elsif ($value =~ m/[$escape_re_without_lb]/) {
685 52         83 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
686             }
687             elsif ($value eq "\n") {
688 8         12 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
689             }
690             elsif ($value !~ tr/ //c) {
691 10         17 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
692             }
693             elsif ($value !~ tr/ \n//c) {
694 12         25 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
695             }
696             elsif ($value =~ tr/\n//) {
697 134 100       305 $style = $flow ? YAML_DOUBLE_QUOTED_SCALAR_STYLE : YAML_LITERAL_SCALAR_STYLE;
698             }
699             elsif ($forbidden_first{ $first }) {
700 94         143 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
701             }
702             elsif ($flow and $value =~ tr/,[]{}//) {
703 5         8 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
704             }
705             elsif (substr($value, 0, 3) =~ m/^(?:---|\.\.\.)/) {
706 12         27 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
707             }
708             elsif ($value =~ m/: /) {
709 8         13 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
710             }
711             elsif ($value =~ m/ #/) {
712 8         14 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
713             }
714             elsif ($value =~ m/[: \t]\z/) {
715 27         55 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
716             }
717             elsif ($value =~ m/[^\x20-\x3A\x3B-\x7E\x85\xA0-\x{D7FF}\x{E000}-\x{FEFE}\x{FF00}-\x{FFFD}\x{10000}-\x{10FFFF}]/) {
718 0         0 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
719             }
720             elsif ($forbidden_first_plus_space{ $first }) {
721 211 100 100     1098 if (length ($value) == 1 or substr($value, 1, 1) =~ m/^\s/) {
722 16         25 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
723             }
724             }
725             }
726 9486 100 100     19818 if ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE and not $info->{style}) {
727 158 100 100     390 if ($value =~ tr/'// and $value !~ tr/"//) {
728 20         30 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
729             }
730             }
731 9486         24206 return $style;
732             }
733              
734             sub _emit_scalar {
735 9486     9486   26820 my ($self, %args) = @_;
736 9486         12492 my $props = $args{props};
737 9486         11513 my $value = $args{value};
738 9486         10997 my $style = $args{style};
739 9486         12714 my $stack = $self->event_stack;
740 9486         10369 my $last = $stack->[-1];
741 9486         10322 my $flow = $last->{flow};
742              
743 9486         10393 my $yaml = '';
744 9486         10523 my $pvalue = $props;
745 9486 100 100     24361 if ($props and length $value) {
    100          
746 524         771 $pvalue .= " $value";
747             }
748             elsif (length $value) {
749 8190         10502 $pvalue .= $value;
750             }
751 9486 100       12451 if ($flow) {
752 1415 100 100     2374 if ($props and not length $value) {
753 52         64 $pvalue .= ' ';
754             }
755             $yaml = $self->_emit_flow_scalar(
756             value => $value,
757             pvalue => $pvalue,
758             style => $args{style},
759 1415         2647 );
760             }
761             else {
762             $yaml = $self->_emit_block_scalar(
763             props => $props,
764             value => $value,
765             pvalue => $pvalue,
766             indent => $args{indent},
767             style => $args{style},
768 8071         18220 );
769             }
770 9486         21929 return $yaml;
771             }
772              
773             sub _emit_block_scalar {
774 8071     8071   25539 my ($self, %args) = @_;
775 8071         10675 my $props = $args{props};
776 8071         10451 my $value = $args{value};
777 8071         9594 my $pvalue = $args{pvalue};
778 8071         8977 my $indent = $args{indent};
779 8071         8712 my $style = $args{style};
780 8071         10196 my $stack = $self->event_stack;
781 8071         8545 my $last = $stack->[-1];
782              
783 8071         8235 my $yaml;
784 8071 100 100     28747 if ($last->{type} eq 'MAP' or $last->{type} eq 'SEQ') {
785 4220 100 100     10391 if ($last->{index} == 0 and $last->{newline}) {
786 994         1750 $yaml .= "\n";
787 994         1444 $last->{column} = 0;
788 994         1480 $last->{newline} = 0;
789             }
790             }
791 8071         9426 my $space = ' ';
792 8071   100     17234 my $multiline = ($style == YAML_LITERAL_SCALAR_STYLE or $style == YAML_FOLDED_SCALAR_STYLE);
793 8071 100       12565 if ($last->{type} eq 'MAP') {
794              
795 2733 100       4095 if ($last->{column}) {
796 448 100       735 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
797 448         744 $yaml .= $space;
798             }
799             else {
800 2285         3539 $yaml .= $indent;
801             }
802 2733 100 100     5309 if ($props and not length $value) {
803 100         117 $pvalue .= ' ';
804             }
805 2733         3683 $last->{type} = 'MAPVALUE';
806 2733 100       4105 if ($multiline) {
807             # oops, a complex key
808 17         24 $yaml .= "? ";
809 17         31 $last->{type} = 'COMPLEXVALUE';
810             }
811 2733 100       3836 if (not $multiline) {
812 2716         3004 $pvalue .= ":";
813             }
814             }
815             else {
816 5338 100       10828 if ($last->{type} eq 'MAPVALUE') {
    100          
817 2155         3192 $last->{type} = 'MAP';
818             }
819             elsif ($last->{type} eq 'DOC') {
820             }
821             else {
822 1529 100       2296 if ($last->{column}) {
823 260 100       416 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
824 260         452 $yaml .= $space;
825             }
826             else {
827 1269         1839 $yaml .= $indent;
828             }
829 1529 100       3271 if ($last->{type} eq 'COMPLEXVALUE') {
    50          
830 42         75 $last->{type} = 'MAP';
831 42         51 $yaml .= ":";
832             }
833             elsif ($last->{type} eq 'SEQ') {
834 1487         1669 $yaml .= "-";
835             }
836             else {
837 0         0 die "Should not happen ($last->{type} in scalar_event)";
838              
839             }
840 1529         1936 $last->{column} = 1;
841             }
842              
843 5338 100       8370 if (length $pvalue) {
844 5044 100       8014 if ($last->{column}) {
845 3881         5331 $pvalue = "$space$pvalue";
846             }
847             }
848 5338 100       7946 if (not $multiline) {
849 4870         5575 $pvalue .= "\n";
850             }
851             }
852 8071         10873 $yaml .= $pvalue;
853 8071         20984 return $yaml;
854             }
855              
856             sub _emit_flow_scalar {
857 1415     1415   3255 my ($self, %args) = @_;
858 1415         1695 my $value = $args{value};
859 1415         1662 my $pvalue = $args{pvalue};
860 1415         1773 my $stack = $self->event_stack;
861 1415         1551 my $last = $stack->[-1];
862              
863 1415         1370 my $yaml;
864 1415 100       2861 if ($last->{type} eq 'SEQ') {
    100          
    50          
865 326 100       559 if ($last->{index} == 0) {
866 168 100       254 if ($self->column) {
867 131         204 $yaml .= ' ';
868             }
869 168         247 $yaml .= "[";
870             }
871             else {
872 158         215 $yaml .= ", ";
873             }
874             }
875             elsif ($last->{type} eq 'MAP') {
876 589 100       921 if ($last->{index} == 0) {
877 347 100       550 if ($self->column) {
878 237         364 $yaml .= ' ';
879             }
880 347         471 $yaml .= "{";
881             }
882             else {
883 242         305 $yaml .= ", ";
884             }
885 589         750 $last->{type} = 'MAPVALUE';
886             }
887             elsif ($last->{type} eq 'MAPVALUE') {
888 500 50       785 if ($last->{index} == 0) {
889 0         0 die "Should not happen (index 0 in MAPVALUE)";
890             }
891 500         790 $yaml .= ": ";
892 500         626 $last->{type} = 'MAP';
893             }
894 1415 100       1940 if ($self->column + length $pvalue > $self->width) {
895 51         62 $yaml .= "\n";
896 51         68 $yaml .= $last->{indent};
897 51         110 $yaml .= ' ' x $self->indent;
898             }
899 1415         1646 $yaml .= $pvalue;
900 1415         2962 return $yaml;
901             }
902              
903             sub alias_event {
904 202     202 1 1019 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ alias_event\n";
905 202         307 my ($self, $info) = @_;
906 202         318 my $stack = $self->event_stack;
907 202         270 my $last = $stack->[-1];
908 202         310 my $indent = $last->{indent};
909 202         261 my $flow = $last->{flow};
910              
911 202         322 my $alias = '*' . $info->{value};
912              
913 202         271 my $yaml = '';
914 202 100 100     738 if ($last->{type} eq 'MAP' or $last->{type} eq 'SEQ') {
915 107 100 100     232 if ($last->{index} == 0 and $last->{newline}) {
916 12         14 $yaml .= "\n";
917 12         32 $last->{column} = 0;
918 12         16 $last->{newline} = 0;
919             }
920             }
921 202 100       428 $yaml .= $last->{column} ? ' ' : $indent;
922 202 100       321 if ($flow) {
923 27         35 my $space = '';
924 27 100       90 if ($last->{type} eq 'SEQ') {
    100          
    50          
925 5 100       14 if ($last->{index} == 0) {
926 1 50       2 if ($flow == 1) {
927 0         0 $yaml .= ' ';
928             }
929 1         2 $yaml .= "[";
930             }
931             else {
932 4         6 $yaml .= ", ";
933             }
934             }
935             elsif ($last->{type} eq 'MAP') {
936 7 100       14 if ($last->{index} == 0) {
937 2 50       3 if ($flow == 1) {
938 0         0 $yaml .= ' ';
939             }
940 2         3 $yaml .= "{";
941             }
942             else {
943 5         10 $yaml .= ", ";
944             }
945 7         9 $last->{type} = 'MAPVALUE';
946 7         11 $space = ' ';
947             }
948             elsif ($last->{type} eq 'MAPVALUE') {
949 15 50       33 if ($last->{index} == 0) {
950 0         0 die 23;
951 0 0       0 if ($flow == 1) {
952 0         0 $yaml .= ' ';
953             }
954 0         0 $yaml .= "{";
955             }
956             else {
957 15         21 $yaml .= ": ";
958             }
959 15         26 $last->{type} = 'MAP';
960             }
961 27         43 $yaml .= "$alias$space";
962             }
963             else {
964 175 100       279 if ($last->{type} eq 'MAP') {
965 25         38 $yaml .= "$alias :";
966 25         40 $last->{type} = 'MAPVALUE';
967             }
968             else {
969              
970 150 100       327 if ($last->{type} eq 'MAPVALUE') {
    50          
971 77         130 $last->{type} = 'MAP';
972             }
973             elsif ($last->{type} eq 'DOC') {
974             # TODO an alias at document level isn't actually valid
975             }
976             else {
977 73 100       207 if ($last->{type} eq 'COMPLEXVALUE') {
    50          
    50          
978 3         4 $last->{type} = 'MAP';
979 3         4 $yaml .= ": ";
980             }
981             elsif ($last->{type} eq 'COMPLEX') {
982 0         0 $yaml .= ": ";
983             }
984             elsif ($last->{type} eq 'SEQ') {
985 70         79 $yaml .= "- ";
986             }
987             else {
988 0         0 die "Unexpected";
989             }
990             }
991 150         209 $yaml .= "$alias\n";
992             }
993             }
994              
995 202         493 $self->_write("$yaml");
996 202         316 $last->{index}++;
997 202         1649 $last->{column} = $self->column;
998 202         411 $self->{open_ended} = 0;
999             }
1000              
1001             sub document_start_event {
1002 3273     3273 1 12739 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ document_start_event\n";
1003 3273         5215 my ($self, $info) = @_;
1004 3273         4129 my $newline = 0;
1005 3273         5113 my $implicit = $info->{implicit};
1006 3273 100       6269 if ($info->{version_directive}) {
1007 18 100       33 if ($self->{open_ended}) {
1008 10         13 $self->_write("...\n");
1009             }
1010 18         55 $self->_write("%YAML $info->{version_directive}->{major}.$info->{version_directive}->{minor}\n");
1011 18         23 $self->{open_ended} = 0;
1012 18         40 $implicit = 0; # we need ---
1013             }
1014 3273 100       6570 unless ($implicit) {
1015 1196         1482 $newline = 1;
1016 1196         2681 $self->_write("---");
1017             }
1018             $self->set_event_stack([
1019             {
1020 3273         7946 type => 'DOC', index => 0, indent => '', info => $info,
1021             newline => $newline, column => $self->column,
1022             }
1023             ]);
1024             }
1025              
1026             sub document_end_event {
1027 3272     3272 1 12458 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ document_end_event\n";
1028 3272         5262 my ($self, $info) = @_;
1029 3272         7729 $self->set_event_stack([]);
1030 3272 100 100     10970 if ($self->{open_ended} or not $info->{implicit}) {
1031 243         469 $self->_write("...\n");
1032 243         508 $self->{open_ended} = 0;
1033             }
1034             else {
1035 3029         8154 $self->{open_ended} = 1;
1036             }
1037             }
1038              
1039       3065 1   sub stream_start_event {
1040             }
1041              
1042       3064 1   sub stream_end_event {
1043             }
1044              
1045             sub _emit_tag {
1046 649     649   1312 my ($self, $type, $tag) = @_;
1047 649         1193 my $map = $self->tagmap;
1048 649         1717 for my $key (sort keys %$map) {
1049 649 100       4312 if ($tag =~ m/^\Q$key\E(.*)/) {
1050 487         1292 $tag = $map->{ $key } . $1;
1051 487         1032 return $tag;
1052             }
1053             }
1054 162 100       705 if ($tag =~ m/^(!.*)/) {
1055 107         265 $tag = "$1";
1056             }
1057             else {
1058 55         157 $tag = "!<$tag>";
1059             }
1060 162         360 return $tag;
1061             }
1062              
1063             sub finish {
1064 1585     1585 1 2393 my ($self) = @_;
1065 1585         2371 $self->writer->finish;
1066             }
1067              
1068             sub _write {
1069 15108     15108   20974 my ($self, $yaml) = @_;
1070 15108 100       23357 return unless length $yaml;
1071 13154         29144 my @lines = split m/\n/, $yaml, -1;
1072 13154         16613 my $newlines = @lines - 1;
1073 13154         16255 $self->{line} += $newlines;
1074 13154 100       18475 if (length $lines[-1]) {
1075 6978 100       9091 if ($newlines) {
1076 881         1823 $self->{column} = length $lines[-1];
1077             }
1078             else {
1079 6097         8965 $self->{column} += length $lines[-1];
1080             }
1081             }
1082             else {
1083 6176         7929 $self->{column} = 0;
1084             }
1085 13154         19630 $self->writer->write($yaml);
1086             }
1087              
1088             1;
1089              
1090             __END__