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   153109 use strict;
  49         75  
  49         1403  
2 49     49   165 use warnings;
  49         58  
  49         2914  
3             package YAML::PP::Emitter;
4              
5             our $VERSION = 'v0.40.1'; # TRIAL VERSION
6 49     49   14587 use Data::Dumper;
  49         202672  
  49         3298  
7              
8 49         3025 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   754 /;
  49         92  
14              
15 49 50   49   214 use constant DEBUG => $ENV{YAML_PP_EMIT_DEBUG} ? 1 : 0;
  49         67  
  49         2713  
16 49     49   204 use constant DEFAULT_WIDTH => 80;
  49         75  
  49         269899  
17              
18             sub new {
19 2243     2243 1 184995 my ($class, %args) = @_;
20             my $self = bless {
21             indent => $args{indent} || 2,
22             writer => $args{writer},
23 2243   100     13172 width => $args{width} || DEFAULT_WIDTH,
      50        
24             }, $class;
25 2243         6554 $self->init;
26 2243         4245 return $self;
27             }
28              
29             sub clone {
30 9     9 0 11 my ($self) = @_;
31 9         20 my $clone = {
32             indent => $self->indent,
33             };
34 9         38 return bless $clone, ref $self;
35             }
36              
37 44735     44735 0 51401 sub event_stack { return $_[0]->{event_stack} }
38 6545     6545 0 15368 sub set_event_stack { $_[0]->{event_stack} = $_[1] }
39 4579     4579 1 10223 sub indent { return $_[0]->{indent} }
40 1415     1415 0 2349 sub width { return $_[0]->{width} }
41 0     0 0 0 sub line { return $_[0]->{line} }
42 21567     21567 0 51833 sub column { return $_[0]->{column} }
43 1     1 1 791 sub set_indent { $_[0]->{indent} = $_[1] }
44 28419     28419 1 58520 sub writer { $_[0]->{writer} }
45 5207     5207 1 12713 sub set_writer { $_[0]->{writer} = $_[1] }
46 649     649 0 863 sub tagmap { return $_[0]->{tagmap} }
47 5308     5308 0 9354 sub set_tagmap { $_[0]->{tagmap} = $_[1] }
48              
49             sub init {
50 5308     5308 1 90160 my ($self) = @_;
51 5308 100       9455 unless ($self->writer) {
52 2242         5396 $self->set_writer(YAML::PP::Writer->new);
53             }
54             $self->set_tagmap({
55 5308         15220 'tag:yaml.org,2002:' => '!!',
56             });
57 5308         7711 $self->{open_ended} = 0;
58 5308         8893 $self->{line} = 0;
59 5308         6974 $self->{column} = 0;
60 5308         7765 $self->writer->init;
61             }
62              
63             sub mapping_start_event {
64 1940     1940 1 13804 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ mapping_start_event\n";
65 1940         2782 my ($self, $info) = @_;
66 1940         3110 my $stack = $self->event_stack;
67 1940         2595 my $last = $stack->[-1];
68 1940         2670 my $indent = $last->{indent};
69 1940         2329 my $new_indent = $indent;
70 1940         2257 my $yaml = '';
71              
72 1940         2232 my $props = '';
73 1940         2560 my $anchor = $info->{anchor};
74 1940         2331 my $tag = $info->{tag};
75 1940 100       3227 if (defined $anchor) {
76 98         169 $anchor = "&$anchor";
77             }
78 1940 100       3117 if (defined $tag) {
79 110         293 $tag = $self->_emit_tag('map', $tag);
80             }
81 1940         5147 $props = join ' ', grep defined, ($anchor, $tag);
82              
83 1940   100     5171 my $flow = $last->{flow} || 0;
84 1940 100 100     10906 $flow++ if ($info->{style} || 0) eq YAML_FLOW_MAPPING_STYLE;
85              
86 1940         3521 my $newline = 0;
87 1940 100       3182 if ($flow > 1) {
88 138 100       315 if ($last->{type} eq 'SEQ') {
    100          
    50          
89 95 100       177 if ($last->{newline}) {
90 17         23 $yaml .= ' ';
91             }
92 95 100       3963 if ($last->{index} == 0) {
93 27         39 $yaml .= "[";
94             }
95             else {
96 68         88 $yaml .= ",";
97             }
98             }
99             elsif ($last->{type} eq 'MAP') {
100 2 50       6 if ($last->{newline}) {
101 0         0 $yaml .= ' ';
102             }
103 2 50       5 if ($last->{index} == 0) {
104 2         4 $yaml .= "{";
105             }
106             else {
107 0         0 $yaml .= ",";
108             }
109             }
110             elsif ($last->{type} eq 'MAPVALUE') {
111 41 50       64 if ($last->{index} == 0) {
112 0         0 die "Should not happen (index 0 in MAPVALUE)";
113             }
114 41         79 $yaml .= ": ";
115             }
116 138 100       270 if ($props) {
117 18         23 $yaml .= " $props ";
118             }
119 138         237 $new_indent .= ' ' x $self->indent;
120             }
121             else {
122 1802 100       3440 if ($last->{type} eq 'DOC') {
123 985         1716 $newline = $last->{newline};
124             }
125             else {
126 817 100       1410 if ($last->{newline}) {
127 108         186 $yaml .= "\n";
128 108         205 $last->{column} = 0;
129             }
130 817 100       1351 if ($last->{type} eq 'MAPVALUE') {
131 263         507 $new_indent .= ' ' x $self->indent;
132 263         371 $newline = 1;
133             }
134             else {
135 554         687 $new_indent = $indent;
136 554 100 100     1533 if (not $props and $self->indent == 1) {
137 91         114 $new_indent .= ' ' x 2;
138             }
139             else {
140 463         751 $new_indent .= ' ' x $self->indent;
141             }
142              
143 554 100       1015 if ($last->{column}) {
144 15 100       57 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
145 15         27 $yaml .= $space;
146             }
147             else {
148 539         646 $yaml .= $indent;
149             }
150 554 100       1016 if ($last->{type} eq 'SEQ') {
    100          
    50          
151 526         684 $yaml .= '-';
152             }
153             elsif ($last->{type} eq 'MAP') {
154 19         33 $yaml .= "?";
155 19         35 $last->{type} = 'COMPLEX';
156             }
157             elsif ($last->{type} eq 'COMPLEXVALUE') {
158 9         17 $yaml .= ":";
159             }
160             else {
161 0         0 die "Should not happen ($last->{type} in mapping_start)";
162             }
163 554         861 $last->{column} = 1;
164             }
165 817         1074 $last->{newline} = 0;
166             }
167 1802 100       3027 if ($props) {
168 159 100       390 $yaml .= $last->{column} ? ' ' : $indent;
169 159         215 $yaml .= $props;
170 159         192 $newline = 1;
171             }
172             }
173 1940         4270 $self->_write($yaml);
174 1940         3776 my $new_info = {
175             index => 0, indent => $new_indent, info => $info,
176             newline => $newline,
177             column => $self->column,
178             flow => $flow,
179             };
180 1940         3626 $new_info->{type} = 'MAP';
181 1940         2249 push @{ $stack }, $new_info;
  1940         3189  
182 1940         2448 $last->{index}++;
183 1940         4580 $self->{open_ended} = 0;
184             }
185              
186             sub mapping_end_event {
187 1939     1939 1 10027 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ mapping_end_event\n";
188 1939         2740 my ($self, $info) = @_;
189 1939         2559 my $stack = $self->event_stack;
190              
191 1939         2156 my $last = pop @{ $stack };
  1939         2746  
192 1939 100       4888 if ($last->{index} == 0) {
    100          
193 28         55 my $indent = $last->{indent};
194 28         40 my $zero_indent = $last->{zero_indent};
195 28 50       58 if ($last->{zero_indent}) {
196 0         0 $indent .= ' ' x $self->indent;
197             }
198 28 100       51 if ($self->column) {
199 22         47 $self->_write(" {}\n");
200             }
201             else {
202 6         21 $self->_write("$indent\{}\n");
203             }
204             }
205             elsif ($last->{flow}) {
206 359         389 my $yaml = "}";
207 359 100       561 if ($last->{flow} == 1) {
208 223         286 $yaml .= "\n";
209             }
210 359         627 $self->_write("$yaml");
211             }
212 1939         4547 $last = $stack->[-1];
213 1939         2730 $last->{column} = $self->column;
214 1939 100       7853 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         576 $last->{type} = 'MAP';
221             }
222             elsif ($last->{type} eq 'COMPLEX') {
223 19         43 $last->{type} = 'COMPLEXVALUE';
224             }
225             elsif ($last->{type} eq 'COMPLEXVALUE') {
226 9         22 $last->{type} = 'MAP';
227             }
228             }
229              
230             sub sequence_start_event {
231 1355     1355 1 9718 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ sequence_start_event\n";
232 1355         2215 my ($self, $info) = @_;
233 1355         2238 my $stack = $self->event_stack;
234 1355         1884 my $last = $stack->[-1];
235 1355         2035 my $indent = $last->{indent};
236 1355         1709 my $new_indent = $indent;
237 1355         1686 my $yaml = '';
238              
239 1355         1719 my $props = '';
240 1355         1945 my $anchor = $info->{anchor};
241 1355         1678 my $tag = $info->{tag};
242 1355 100       2485 if (defined $anchor) {
243 44         88 $anchor = "&$anchor";
244             }
245 1355 100       2265 if (defined $tag) {
246 47         124 $tag = $self->_emit_tag('seq', $tag);
247             }
248 1355         3444 $props = join ' ', grep defined, ($anchor, $tag);
249              
250 1355   100     3744 my $flow = $last->{flow} || 0;
251 1355 100 100     5222 $flow++ if $flow or ($info->{style} || 0) eq YAML_FLOW_SEQUENCE_STYLE;
      100        
252 1355         1592 my $newline = 0;
253 1355         1574 my $zero_indent = 0;
254 1355 100       2320 if ($flow > 1) {
255 122 100       352 if ($last->{type} eq 'SEQ') {
    100          
    50          
256 52 50       92 if ($last->{newline}) {
257 0         0 $yaml .= ' ';
258             }
259 52 100       83 if ($last->{index} == 0) {
260 16         29 $yaml .= "[";
261             }
262             else {
263 36         48 $yaml .= ",";
264             }
265             }
266             elsif ($last->{type} eq 'MAP') {
267 14 100       39 if ($last->{newline}) {
268 1         1 $yaml .= ' ';
269             }
270 14 100       29 if ($last->{index} == 0) {
271 8         13 $yaml .= "{";
272             }
273             else {
274 6         11 $yaml .= ",";
275             }
276             }
277             elsif ($last->{type} eq 'MAPVALUE') {
278 56 50       119 if ($last->{index} == 0) {
279 0         0 die "Should not happen (index 0 in MAPVALUE)";
280             }
281 56         88 $yaml .= ": ";
282             }
283 122 100       220 if ($props) {
284 10         17 $yaml .= " $props ";
285             }
286 122         243 $new_indent .= ' ' x $self->indent;
287             }
288             else {
289 1233 100       2363 if ($last->{type} eq 'DOC') {
290 634         1107 $newline = $last->{newline};
291             }
292             else {
293 599 100       1053 if ($last->{newline}) {
294 51         73 $yaml .= "\n";
295 51         82 $last->{column} = 0;
296             }
297 599 100       1036 if ($last->{type} eq 'MAPVALUE') {
298 245         356 $zero_indent = 1;
299 245         338 $newline = 1;
300             }
301             else {
302 354 100 100     908 if (not $props and $self->indent == 1) {
303 68         80 $new_indent .= ' ' x 2;
304             }
305             else {
306 286         471 $new_indent .= ' ' x $self->indent;
307             }
308 354 100       603 if ($last->{column}) {
309 24 100       40 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
310 24         33 $yaml .= $space;
311             }
312             else {
313 330         408 $yaml .= $indent;
314             }
315 354 100       770 if ($last->{type} eq 'SEQ') {
    100          
    50          
316 278         311 $yaml .= "-";
317             }
318             elsif ($last->{type} eq 'MAP') {
319 47         79 $last->{type} = 'COMPLEX';
320 47         62 $zero_indent = 1;
321 47         64 $yaml .= "?";
322             }
323             elsif ($last->{type} eq 'COMPLEXVALUE') {
324 29         39 $yaml .= ":";
325 29         35 $zero_indent = 1;
326             }
327             else {
328 0         0 die "Should not happen ($last->{type} in sequence_start)";
329             }
330 354         517 $last->{column} = 1;
331             }
332 599         799 $last->{newline} = 0;
333             }
334 1233 100       2364 if ($props) {
335 73 100       185 $yaml .= $last->{column} ? ' ' : $indent;
336 73         130 $yaml .= $props;
337 73         92 $newline = 1;
338             }
339             }
340 1355         3045 $self->_write($yaml);
341 1355         1808 $last->{index}++;
342 1355         2703 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         2492 $new_info->{type} = 'SEQ';
352 1355         1578 push @{ $stack }, $new_info;
  1355         2242  
353 1355         2800 $self->{open_ended} = 0;
354             }
355              
356             sub sequence_end_event {
357 1355     1355 1 6789 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ sequence_end_event\n";
358 1355         2097 my ($self, $info) = @_;
359 1355         1991 my $stack = $self->event_stack;
360              
361 1355         1748 my $last = pop @{ $stack };
  1355         2062  
362 1355 100       3487 if ($last->{index} == 0) {
    100          
363 59         99 my $indent = $last->{indent};
364 59         72 my $zero_indent = $last->{zero_indent};
365 59 100       120 if ($last->{zero_indent}) {
366 7         18 $indent .= ' ' x $self->indent;
367             }
368 59 100       106 my $yaml .= $self->column ? ' ' : $indent;
369 59         73 $yaml .= "[]";
370 59 100       123 if ($last->{flow} < 2) {
371 51         61 $yaml .= "\n";
372             }
373 59         90 $self->_write($yaml);
374             }
375             elsif ($last->{flow}) {
376 212         300 my $yaml = "]";
377 212 100       381 if ($last->{flow} == 1) {
378 98         116 $yaml .= "\n";
379             }
380 212         342 $self->_write($yaml);
381             }
382 1355         3370 $last = $stack->[-1];
383 1355         1920 $last->{column} = $self->column;
384 1355 100       5644 if ($last->{type} eq 'SEQ') {
    100          
    100          
    100          
    100          
385             }
386             elsif ($last->{type} eq 'MAP') {
387 14         33 $last->{type} = 'MAPVALUE';
388             }
389             elsif ($last->{type} eq 'MAPVALUE') {
390 301         604 $last->{type} = 'MAP';
391             }
392             elsif ($last->{type} eq 'COMPLEX') {
393 47         97 $last->{type} = 'COMPLEXVALUE';
394             }
395             elsif ($last->{type} eq 'COMPLEXVALUE') {
396 29         60 $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 41282 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ scalar_event\n";
490 9486         11311 my ($self, $info) = @_;
491 9486         13392 my $stack = $self->event_stack;
492 9486         11228 my $last = $stack->[-1];
493 9486         11752 my $indent = $last->{indent};
494 9486         11403 my $value = $info->{value};
495 9486         11130 my $flow = $last->{flow};
496              
497 9486         10455 my $props = '';
498 9486         10749 my $anchor = $info->{anchor};
499 9486         10786 my $tag = $info->{tag};
500 9486 100       13364 if (defined $anchor) {
501 460         678 $anchor = "&$anchor";
502             }
503 9486 100       13633 if (defined $tag) {
504 492         1074 $tag = $self->_emit_tag('scalar', $tag);
505             }
506 9486         19229 $props = join ' ', grep defined, ($anchor, $tag);
507              
508 9486         9421 DEBUG and local $Data::Dumper::Useqq = 1;
509 9486 50       13016 $value = '' unless defined $value;
510              
511 9486         16302 my $style = $self->_find_best_scalar_style(
512             info => $info,
513             value => $value,
514             );
515              
516 9486         10900 my $open_ended = 0;
517              
518 9486 100       15433 if ($style == YAML_PLAIN_SCALAR_STYLE) {
    100          
    100          
    100          
519 7726         11074 $value =~ s/\n/\n\n/g;
520             }
521             elsif ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
522 508         1054 my $new_indent = $last->{indent} . (' ' x $self->indent);
523 508         1082 $value =~ s/(\n+)/"\n" x (1 + (length $1))/eg;
  10         51  
524 508         1208 my @lines = split m/\n/, $value, -1;
525 508 100       937 if (@lines > 1) {
526 10         41 for my $line (@lines[1 .. $#lines]) {
527 20 100       58 $line = $new_indent . $line
528             if length $line;
529             }
530             }
531 508         897 $value = join "\n", @lines;
532 508         859 $value =~ s/'/''/g;
533 508         895 $value = "'" . $value . "'";
534             }
535             elsif ($style == YAML_LITERAL_SCALAR_STYLE) {
536 365         421 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$value], ['value']);
537 365         583 my $indicators = '';
538 365 100       1458 if ($value =~ m/\A\n* +/) {
539 36         77 $indicators .= $self->indent;
540             }
541 365         878 my $indent = $indent . ' ' x $self->indent;
542 365 100       2097 if ($value !~ m/\n\z/) {
    100          
543 87         224 $indicators .= '-';
544 87         148 $value .= "\n";
545             }
546             elsif ($value =~ m/(\n|\A)\n\z/) {
547 36         54 $indicators .= '+';
548 36         51 $open_ended = 1;
549             }
550 365         1985 $value =~ s/^(?=.)/$indent/gm;
551 365         814 $value = "|$indicators\n$value";
552             }
553             elsif ($style == YAML_FOLDED_SCALAR_STYLE) {
554 120         139 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$value], ['value']);
555 120         393 my @lines = split /\n/, $value, -1;
556 120         139 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\@lines], ['lines']);
557 120         153 my $trailing = -1;
558 120         263 while (@lines) {
559 218 100       412 last if $lines[-1] ne '';
560 99         135 pop @lines;
561 99         174 $trailing++;
562             }
563 120         160 my %start_with_space;
564 120         328 for my $i (0 .. $#lines) {
565 211 100       641 if ($lines[ $i ] =~ m/^[ \t]+/) {
566 31         70 $start_with_space{ $i } = 1;
567             }
568             }
569 120         229 my $indicators = '';
570 120 100       939 if ($value =~ m/\A\n* +/) {
571 19         36 $indicators .= $self->indent;
572             }
573 120         271 my $indent = $indent . ' ' x $self->indent;
574 120 100       403 if ($trailing > 0) {
    100          
575 3         4 $indicators .= '+';
576 3         4 $open_ended = 1;
577             }
578             elsif ($trailing < 0) {
579 24         47 $indicators .= '-';
580             }
581 120         180 $value = ">$indicators\n";
582 120         198 my $got_content = 0;
583 120         213 for my $i (0 .. $#lines) {
584 211         284 my $line = $lines[ $i ];
585 211   100     573 my $sp = $start_with_space{ $i } || 0;
586 211 100 100     500 my $spnext = $i == $#lines ? 1 : $start_with_space{ $i+1 } || 0;
587 211 100 100     443 my $spprev = $i == 0 ? 1 : $start_with_space{ $i-1 } || 0;
588 211 100       1671 my $empty = length $line ? 0 : 1;
589 211 100       413 my $emptynext = $i == $#lines ? '' : length $lines[$i+1] ? 0 : 1;
    100          
590 211         237 my $nl = 0;
591 211 100       341 if ($empty) {
592 47 100 100     120 if ($spnext and $spprev) {
    100          
    100          
593 8         12 $nl = 1;
594             }
595             elsif (not $spnext) {
596 37         42 $nl = 1;
597             }
598             elsif (not $got_content) {
599 1         2 $nl = 1;
600             }
601             }
602             else {
603 164         224 $got_content = 1;
604 164         249 $value .= "$indent$line\n";
605 164 100 100     471 if (not $sp and not $spnext) {
606 32         42 $nl = 1;
607             }
608             }
609 211 100       409 if ($nl) {
610 78         110 $value .= "\n";
611             }
612             }
613 120 100       330 $value .= "\n" x ($trailing) if $trailing > 0;
614             }
615             else {
616 767 50       3786 $value =~ s/([$escape_re"\\])/$to_escape{ $1 } || sprintf '\\u%04x', ord($1)/eg;
  722         3006  
617 767         1375 $value = '"' . $value . '"';
618             }
619              
620 9486         9166 DEBUG and warn __PACKAGE__.':'.__LINE__.": (@$stack)\n";
621 9486         16536 my $yaml = $self->_emit_scalar(
622             indent => $indent,
623             props => $props,
624             value => $value,
625             style => $style,
626             );
627              
628 9486         11557 $last->{index}++;
629 9486         10968 $last->{newline} = 0;
630 9486         17090 $self->_write($yaml);
631 9486         14500 $last->{column} = $self->column;
632 9486         28822 $self->{open_ended} = $open_ended;
633             }
634              
635             sub _find_best_scalar_style {
636 9486     9486   18948 my ($self, %args) = @_;
637 9486         11539 my $info = $args{info};
638 9486         11867 my $style = $info->{style};
639 9486         11400 my $value = $args{value};
640 9486         12088 my $stack = $self->event_stack;
641 9486         10685 my $last = $stack->[-1];
642 9486         10444 my $flow = $last->{flow};
643              
644 9486         15539 my $first = substr($value, 0, 1);
645 9486 100       44510 if ($value eq '') {
    100          
646 897 100 100     3084 if ($flow and $last->{type} ne 'MAPVALUE' and $last->{type} ne 'MAP') {
    100 100        
647 24         33 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
648             }
649             elsif (not $style) {
650 2         4 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
651             }
652             }
653             # no control characters anywhere
654             elsif ($value =~ m/[$control_re]/) {
655 55         92 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
656             }
657 9486   100     18637 $style ||= YAML_PLAIN_SCALAR_STYLE;
658              
659 9486 100 100     31037 if ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
    100          
    100          
660 356 100 100     2739 if ($value =~ m/ \n/ or $value =~ m/\n / or $value =~ m/^\n/ or $value =~ m/\n$/) {
    50 100        
      100        
661 16         23 $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       1263 if ($value eq '') {
    100          
669 22         30 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
670             }
671             elsif ($flow) {
672             # no block scalars in flow
673 69 100       135 if ($value =~ tr/\n//) {
674 61         75 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
675             }
676             else {
677 8         12 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
678             }
679             }
680             }
681             elsif ($style == YAML_PLAIN_SCALAR_STYLE) {
682 8112 100 100     77745 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         15 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
689             }
690             elsif ($value !~ tr/ //c) {
691 10         16 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
692             }
693             elsif ($value !~ tr/ \n//c) {
694 12         31 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
695             }
696             elsif ($value =~ tr/\n//) {
697 134 100       362 $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         31 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
707             }
708             elsif ($value =~ m/: /) {
709 8         14 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
710             }
711             elsif ($value =~ m/ #/) {
712 8         15 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
713             }
714             elsif ($value =~ m/[: \t]\z/) {
715 27         44 $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     1108 if (length ($value) == 1 or substr($value, 1, 1) =~ m/^\s/) {
722 16         22 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
723             }
724             }
725             }
726 9486 100 100     18567 if ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE and not $info->{style}) {
727 158 100 100     422 if ($value =~ tr/'// and $value !~ tr/"//) {
728 20         28 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
729             }
730             }
731 9486         22670 return $style;
732             }
733              
734             sub _emit_scalar {
735 9486     9486   25732 my ($self, %args) = @_;
736 9486         12046 my $props = $args{props};
737 9486         11794 my $value = $args{value};
738 9486         11248 my $style = $args{style};
739 9486         13912 my $stack = $self->event_stack;
740 9486         10063 my $last = $stack->[-1];
741 9486         10273 my $flow = $last->{flow};
742              
743 9486         10306 my $yaml = '';
744 9486         10907 my $pvalue = $props;
745 9486 100 100     23692 if ($props and length $value) {
    100          
746 524         771 $pvalue .= " $value";
747             }
748             elsif (length $value) {
749 8190         10555 $pvalue .= $value;
750             }
751 9486 100       11888 if ($flow) {
752 1415 100 100     2219 if ($props and not length $value) {
753 52         60 $pvalue .= ' ';
754             }
755             $yaml = $self->_emit_flow_scalar(
756             value => $value,
757             pvalue => $pvalue,
758             style => $args{style},
759 1415         2414 );
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         17573 );
769             }
770 9486         20895 return $yaml;
771             }
772              
773             sub _emit_block_scalar {
774 8071     8071   24857 my ($self, %args) = @_;
775 8071         10190 my $props = $args{props};
776 8071         9445 my $value = $args{value};
777 8071         9124 my $pvalue = $args{pvalue};
778 8071         8950 my $indent = $args{indent};
779 8071         8921 my $style = $args{style};
780 8071         9985 my $stack = $self->event_stack;
781 8071         8805 my $last = $stack->[-1];
782              
783 8071         8561 my $yaml;
784 8071 100 100     20360 if ($last->{type} eq 'MAP' or $last->{type} eq 'SEQ') {
785 4220 100 100     10196 if ($last->{index} == 0 and $last->{newline}) {
786 994         1675 $yaml .= "\n";
787 994         1415 $last->{column} = 0;
788 994         1389 $last->{newline} = 0;
789             }
790             }
791 8071         8994 my $space = ' ';
792 8071   100     17140 my $multiline = ($style == YAML_LITERAL_SCALAR_STYLE or $style == YAML_FOLDED_SCALAR_STYLE);
793 8071 100       12445 if ($last->{type} eq 'MAP') {
794              
795 2733 100       4089 if ($last->{column}) {
796 448 100       667 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
797 448         812 $yaml .= $space;
798             }
799             else {
800 2285         3187 $yaml .= $indent;
801             }
802 2733 100 100     5340 if ($props and not length $value) {
803 100         159 $pvalue .= ' ';
804             }
805 2733         3616 $last->{type} = 'MAPVALUE';
806 2733 100       3902 if ($multiline) {
807             # oops, a complex key
808 17         27 $yaml .= "? ";
809 17         29 $last->{type} = 'COMPLEXVALUE';
810             }
811 2733 100       3913 if (not $multiline) {
812 2716         3307 $pvalue .= ":";
813             }
814             }
815             else {
816 5338 100       10418 if ($last->{type} eq 'MAPVALUE') {
    100          
817 2155         3069 $last->{type} = 'MAP';
818             }
819             elsif ($last->{type} eq 'DOC') {
820             }
821             else {
822 1529 100       2247 if ($last->{column}) {
823 260 100       442 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
824 260         451 $yaml .= $space;
825             }
826             else {
827 1269         1835 $yaml .= $indent;
828             }
829 1529 100       3115 if ($last->{type} eq 'COMPLEXVALUE') {
    50          
830 42         66 $last->{type} = 'MAP';
831 42         57 $yaml .= ":";
832             }
833             elsif ($last->{type} eq 'SEQ') {
834 1487         1688 $yaml .= "-";
835             }
836             else {
837 0         0 die "Should not happen ($last->{type} in scalar_event)";
838              
839             }
840 1529         1831 $last->{column} = 1;
841             }
842              
843 5338 100       7541 if (length $pvalue) {
844 5044 100       7863 if ($last->{column}) {
845 3881         5123 $pvalue = "$space$pvalue";
846             }
847             }
848 5338 100       7558 if (not $multiline) {
849 4870         5448 $pvalue .= "\n";
850             }
851             }
852 8071         10546 $yaml .= $pvalue;
853 8071         20331 return $yaml;
854             }
855              
856             sub _emit_flow_scalar {
857 1415     1415   3080 my ($self, %args) = @_;
858 1415         1604 my $value = $args{value};
859 1415         1773 my $pvalue = $args{pvalue};
860 1415         1662 my $stack = $self->event_stack;
861 1415         1463 my $last = $stack->[-1];
862              
863 1415         1455 my $yaml;
864 1415 100       3048 if ($last->{type} eq 'SEQ') {
    100          
    50          
865 326 100       513 if ($last->{index} == 0) {
866 168 100       295 if ($self->column) {
867 131         206 $yaml .= ' ';
868             }
869 168         238 $yaml .= "[";
870             }
871             else {
872 158         215 $yaml .= ", ";
873             }
874             }
875             elsif ($last->{type} eq 'MAP') {
876 589 100       882 if ($last->{index} == 0) {
877 347 100       467 if ($self->column) {
878 237         335 $yaml .= ' ';
879             }
880 347         473 $yaml .= "{";
881             }
882             else {
883 242         320 $yaml .= ", ";
884             }
885 589         723 $last->{type} = 'MAPVALUE';
886             }
887             elsif ($last->{type} eq 'MAPVALUE') {
888 500 50       848 if ($last->{index} == 0) {
889 0         0 die "Should not happen (index 0 in MAPVALUE)";
890             }
891 500         656 $yaml .= ": ";
892 500         627 $last->{type} = 'MAP';
893             }
894 1415 100       1734 if ($self->column + length $pvalue > $self->width) {
895 51         59 $yaml .= "\n";
896 51         67 $yaml .= $last->{indent};
897 51         119 $yaml .= ' ' x $self->indent;
898             }
899 1415         1647 $yaml .= $pvalue;
900 1415         2904 return $yaml;
901             }
902              
903             sub alias_event {
904 202     202 1 937 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ alias_event\n";
905 202         329 my ($self, $info) = @_;
906 202         349 my $stack = $self->event_stack;
907 202         624 my $last = $stack->[-1];
908 202         354 my $indent = $last->{indent};
909 202         301 my $flow = $last->{flow};
910              
911 202         380 my $alias = '*' . $info->{value};
912              
913 202         292 my $yaml = '';
914 202 100 100     767 if ($last->{type} eq 'MAP' or $last->{type} eq 'SEQ') {
915 107 100 100     254 if ($last->{index} == 0 and $last->{newline}) {
916 12         18 $yaml .= "\n";
917 12         17 $last->{column} = 0;
918 12         16 $last->{newline} = 0;
919             }
920             }
921 202 100       466 $yaml .= $last->{column} ? ' ' : $indent;
922 202 100       351 if ($flow) {
923 27         30 my $space = '';
924 27 100       82 if ($last->{type} eq 'SEQ') {
    100          
    50          
925 5 100       11 if ($last->{index} == 0) {
926 1 50       3 if ($flow == 1) {
927 0         0 $yaml .= ' ';
928             }
929 1         1 $yaml .= "[";
930             }
931             else {
932 4         7 $yaml .= ", ";
933             }
934             }
935             elsif ($last->{type} eq 'MAP') {
936 7 100       16 if ($last->{index} == 0) {
937 2 50       4 if ($flow == 1) {
938 0         0 $yaml .= ' ';
939             }
940 2         3 $yaml .= "{";
941             }
942             else {
943 5         8 $yaml .= ", ";
944             }
945 7         11 $last->{type} = 'MAPVALUE';
946 7         10 $space = ' ';
947             }
948             elsif ($last->{type} eq 'MAPVALUE') {
949 15 50       36 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         16 $yaml .= ": ";
958             }
959 15         29 $last->{type} = 'MAP';
960             }
961 27         1338 $yaml .= "$alias$space";
962             }
963             else {
964 175 100       318 if ($last->{type} eq 'MAP') {
965 25         37 $yaml .= "$alias :";
966 25         46 $last->{type} = 'MAPVALUE';
967             }
968             else {
969              
970 150 100       372 if ($last->{type} eq 'MAPVALUE') {
    50          
971 77         134 $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       251 if ($last->{type} eq 'COMPLEXVALUE') {
    50          
    50          
978 3         5 $last->{type} = 'MAP';
979 3         5 $yaml .= ": ";
980             }
981             elsif ($last->{type} eq 'COMPLEX') {
982 0         0 $yaml .= ": ";
983             }
984             elsif ($last->{type} eq 'SEQ') {
985 70         128 $yaml .= "- ";
986             }
987             else {
988 0         0 die "Unexpected";
989             }
990             }
991 150         233 $yaml .= "$alias\n";
992             }
993             }
994              
995 202         547 $self->_write("$yaml");
996 202         308 $last->{index}++;
997 202         334 $last->{column} = $self->column;
998 202         388 $self->{open_ended} = 0;
999             }
1000              
1001             sub document_start_event {
1002 3273     3273 1 12262 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ document_start_event\n";
1003 3273         5174 my ($self, $info) = @_;
1004 3273         4073 my $newline = 0;
1005 3273         5134 my $implicit = $info->{implicit};
1006 3273 100       6353 if ($info->{version_directive}) {
1007 18 100       31 if ($self->{open_ended}) {
1008 10         13 $self->_write("...\n");
1009             }
1010 18         58 $self->_write("%YAML $info->{version_directive}->{major}.$info->{version_directive}->{minor}\n");
1011 18         21 $self->{open_ended} = 0;
1012 18         22 $implicit = 0; # we need ---
1013             }
1014 3273 100       6189 unless ($implicit) {
1015 1196         1420 $newline = 1;
1016 1196         2762 $self->_write("---");
1017             }
1018             $self->set_event_stack([
1019             {
1020 3273         7738 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 12044 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ document_end_event\n";
1028 3272         4394 my ($self, $info) = @_;
1029 3272         6970 $self->set_event_stack([]);
1030 3272 100 100     11272 if ($self->{open_ended} or not $info->{implicit}) {
1031 243         527 $self->_write("...\n");
1032 243         496 $self->{open_ended} = 0;
1033             }
1034             else {
1035 3029         7671 $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   1278 my ($self, $type, $tag) = @_;
1047 649         1399 my $map = $self->tagmap;
1048 649         1776 for my $key (sort keys %$map) {
1049 649 100       4308 if ($tag =~ m/^\Q$key\E(.*)/) {
1050 487         1229 $tag = $map->{ $key } . $1;
1051 487         1049 return $tag;
1052             }
1053             }
1054 162 100       762 if ($tag =~ m/^(!.*)/) {
1055 107         280 $tag = "$1";
1056             }
1057             else {
1058 55         131 $tag = "!<$tag>";
1059             }
1060 162         368 return $tag;
1061             }
1062              
1063             sub finish {
1064 1585     1585 1 2363 my ($self) = @_;
1065 1585         2182 $self->writer->finish;
1066             }
1067              
1068             sub _write {
1069 15108     15108   20286 my ($self, $yaml) = @_;
1070 15108 100       22532 return unless length $yaml;
1071 13154         27768 my @lines = split m/\n/, $yaml, -1;
1072 13154         16567 my $newlines = @lines - 1;
1073 13154         16865 $self->{line} += $newlines;
1074 13154 100       17946 if (length $lines[-1]) {
1075 6978 100       8788 if ($newlines) {
1076 881         1569 $self->{column} = length $lines[-1];
1077             }
1078             else {
1079 6097         8771 $self->{column} += length $lines[-1];
1080             }
1081             }
1082             else {
1083 6176         7930 $self->{column} = 0;
1084             }
1085 13154         19371 $self->writer->write($yaml);
1086             }
1087              
1088             1;
1089              
1090             __END__