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 46     46   145037 use strict;
  46         71  
  46         1266  
2 46     46   161 use warnings;
  46         111  
  46         3035  
3             package YAML::PP::Emitter;
4              
5             our $VERSION = 'v0.39.0'; # VERSION
6 46     46   11201 use Data::Dumper;
  46         151465  
  46         3072  
7              
8 46         3196 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 46     46   638 /;
  46         63  
14              
15 46 50   46   224 use constant DEBUG => $ENV{YAML_PP_EMIT_DEBUG} ? 1 : 0;
  46         137  
  46         2816  
16 46     46   197 use constant DEFAULT_WIDTH => 80;
  46         70  
  46         264044  
17              
18             sub new {
19 2194     2194 1 181543 my ($class, %args) = @_;
20             my $self = bless {
21             indent => $args{indent} || 2,
22             writer => $args{writer},
23 2194   100     14370 width => $args{width} || DEFAULT_WIDTH,
      50        
24             }, $class;
25 2194         6679 $self->init;
26 2194         4566 return $self;
27             }
28              
29             sub clone {
30 9     9 0 12 my ($self) = @_;
31 9         26 my $clone = {
32             indent => $self->indent,
33             };
34 9         26 return bless $clone, ref $self;
35             }
36              
37 43768     43768 0 51701 sub event_stack { return $_[0]->{event_stack} }
38 6465     6465 0 15668 sub set_event_stack { $_[0]->{event_stack} = $_[1] }
39 4475     4475 1 9830 sub indent { return $_[0]->{indent} }
40 1249     1249 0 2091 sub width { return $_[0]->{width} }
41 0     0 0 0 sub line { return $_[0]->{line} }
42 20895     20895 0 51678 sub column { return $_[0]->{column} }
43 1     1 1 843 sub set_indent { $_[0]->{indent} = $_[1] }
44 27868     27868 1 57489 sub writer { $_[0]->{writer} }
45 5119     5119 1 13142 sub set_writer { $_[0]->{writer} = $_[1] }
46 644     644 0 876 sub tagmap { return $_[0]->{tagmap} }
47 5220     5220 0 8348 sub set_tagmap { $_[0]->{tagmap} = $_[1] }
48              
49             sub init {
50 5220     5220 1 98325 my ($self) = @_;
51 5220 100       9099 unless ($self->writer) {
52 2193         5638 $self->set_writer(YAML::PP::Writer->new);
53             }
54             $self->set_tagmap({
55 5220         14869 'tag:yaml.org,2002:' => '!!',
56             });
57 5220         7309 $self->{open_ended} = 0;
58 5220         6897 $self->{line} = 0;
59 5220         8783 $self->{column} = 0;
60 5220         7640 $self->writer->init;
61             }
62              
63             sub mapping_start_event {
64 1889     1889 1 13896 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ mapping_start_event\n";
65 1889         3118 my ($self, $info) = @_;
66 1889         3268 my $stack = $self->event_stack;
67 1889         2457 my $last = $stack->[-1];
68 1889         2788 my $indent = $last->{indent};
69 1889         2346 my $new_indent = $indent;
70 1889         2190 my $yaml = '';
71              
72 1889         2103 my $props = '';
73 1889         2666 my $anchor = $info->{anchor};
74 1889         2297 my $tag = $info->{tag};
75 1889 100       3217 if (defined $anchor) {
76 98         156 $anchor = "&$anchor";
77             }
78 1889 100       3269 if (defined $tag) {
79 109         278 $tag = $self->_emit_tag('map', $tag);
80             }
81 1889         5465 $props = join ' ', grep defined, ($anchor, $tag);
82              
83 1889   100     4999 my $flow = $last->{flow} || 0;
84 1889 100 100     5439 $flow++ if ($info->{style} || 0) eq YAML_FLOW_MAPPING_STYLE;
85              
86 1889         2250 my $newline = 0;
87 1889 100       3206 if ($flow > 1) {
88 135 100       281 if ($last->{type} eq 'SEQ') {
    100          
    50          
89 92 100       192 if ($last->{newline}) {
90 17         19 $yaml .= ' ';
91             }
92 92 100       146 if ($last->{index} == 0) {
93 27         45 $yaml .= "[";
94             }
95             else {
96 65         87 $yaml .= ",";
97             }
98             }
99             elsif ($last->{type} eq 'MAP') {
100 2 50       6 if ($last->{newline}) {
101 0         0 $yaml .= ' ';
102             }
103 2 50       45 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       97 if ($last->{index} == 0) {
112 0         0 die "Should not happen (index 0 in MAPVALUE)";
113             }
114 41         49 $yaml .= ": ";
115             }
116 135 100       220 if ($props) {
117 18         26 $yaml .= " $props ";
118             }
119 135         205 $new_indent .= ' ' x $self->indent;
120             }
121             else {
122 1754 100       3597 if ($last->{type} eq 'DOC') {
123 963         1544 $newline = $last->{newline};
124             }
125             else {
126 791 100       1425 if ($last->{newline}) {
127 104         183 $yaml .= "\n";
128 104         228 $last->{column} = 0;
129             }
130 791 100       1299 if ($last->{type} eq 'MAPVALUE') {
131 258         539 $new_indent .= ' ' x $self->indent;
132 258         330 $newline = 1;
133             }
134             else {
135 533         778 $new_indent = $indent;
136 533 100 100     1397 if (not $props and $self->indent == 1) {
137 91         110 $new_indent .= ' ' x 2;
138             }
139             else {
140 442         760 $new_indent .= ' ' x $self->indent;
141             }
142              
143 533 100       918 if ($last->{column}) {
144 14 100       34 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
145 14         23 $yaml .= $space;
146             }
147             else {
148 519         637 $yaml .= $indent;
149             }
150 533 100       1021 if ($last->{type} eq 'SEQ') {
    100          
    50          
151 505         672 $yaml .= '-';
152             }
153             elsif ($last->{type} eq 'MAP') {
154 19         41 $yaml .= "?";
155 19         40 $last->{type} = 'COMPLEX';
156             }
157             elsif ($last->{type} eq 'COMPLEXVALUE') {
158 9         18 $yaml .= ":";
159             }
160             else {
161 0         0 die "Should not happen ($last->{type} in mapping_start)";
162             }
163 533         684 $last->{column} = 1;
164             }
165 791         1076 $last->{newline} = 0;
166             }
167 1754 100       3259 if ($props) {
168 158 100       322 $yaml .= $last->{column} ? ' ' : $indent;
169 158         249 $yaml .= $props;
170 158         216 $newline = 1;
171             }
172             }
173 1889         4275 $self->_write($yaml);
174 1889         3944 my $new_info = {
175             index => 0, indent => $new_indent, info => $info,
176             newline => $newline,
177             column => $self->column,
178             flow => $flow,
179             };
180 1889         3667 $new_info->{type} = 'MAP';
181 1889         2110 push @{ $stack }, $new_info;
  1889         3164  
182 1889         2483 $last->{index}++;
183 1889         4038 $self->{open_ended} = 0;
184             }
185              
186             sub mapping_end_event {
187 1888     1888 1 9504 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ mapping_end_event\n";
188 1888         2866 my ($self, $info) = @_;
189 1888         2780 my $stack = $self->event_stack;
190              
191 1888         1992 my $last = pop @{ $stack };
  1888         2705  
192 1888 100       4950 if ($last->{index} == 0) {
    100          
193 25         37 my $indent = $last->{indent};
194 25         36 my $zero_indent = $last->{zero_indent};
195 25 50       96 if ($last->{zero_indent}) {
196 0         0 $indent .= ' ' x $self->indent;
197             }
198 25 100       44 if ($self->column) {
199 20         36 $self->_write(" {}\n");
200             }
201             else {
202 5         18 $self->_write("$indent\{}\n");
203             }
204             }
205             elsif ($last->{flow}) {
206 318         365 my $yaml = "}";
207 318 100       564 if ($last->{flow} == 1) {
208 185         260 $yaml .= "\n";
209             }
210 318         652 $self->_write("$yaml");
211             }
212 1888         4581 $last = $stack->[-1];
213 1888         2852 $last->{column} = $self->column;
214 1888 100       7793 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 299         620 $last->{type} = 'MAP';
221             }
222             elsif ($last->{type} eq 'COMPLEX') {
223 19         40 $last->{type} = 'COMPLEXVALUE';
224             }
225             elsif ($last->{type} eq 'COMPLEXVALUE') {
226 9         19 $last->{type} = 'MAP';
227             }
228             }
229              
230             sub sequence_start_event {
231 1306     1306 1 9546 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ sequence_start_event\n";
232 1306         2087 my ($self, $info) = @_;
233 1306         2491 my $stack = $self->event_stack;
234 1306         2026 my $last = $stack->[-1];
235 1306         1936 my $indent = $last->{indent};
236 1306         1674 my $new_indent = $indent;
237 1306         1632 my $yaml = '';
238              
239 1306         1575 my $props = '';
240 1306         1835 my $anchor = $info->{anchor};
241 1306         1692 my $tag = $info->{tag};
242 1306 100       2397 if (defined $anchor) {
243 43         97 $anchor = "&$anchor";
244             }
245 1306 100       1927 if (defined $tag) {
246 46         113 $tag = $self->_emit_tag('seq', $tag);
247             }
248 1306         3647 $props = join ' ', grep defined, ($anchor, $tag);
249              
250 1306   100     3595 my $flow = $last->{flow} || 0;
251 1306 100 100     5116 $flow++ if $flow or ($info->{style} || 0) eq YAML_FLOW_SEQUENCE_STYLE;
      100        
252 1306         1598 my $newline = 0;
253 1306         1572 my $zero_indent = 0;
254 1306 100       2288 if ($flow > 1) {
255 108 100       326 if ($last->{type} eq 'SEQ') {
    100          
    50          
256 49 50       88 if ($last->{newline}) {
257 0         0 $yaml .= ' ';
258             }
259 49 100       78 if ($last->{index} == 0) {
260 14         24 $yaml .= "[";
261             }
262             else {
263 35         46 $yaml .= ",";
264             }
265             }
266             elsif ($last->{type} eq 'MAP') {
267 12 100       24 if ($last->{newline}) {
268 1         2 $yaml .= ' ';
269             }
270 12 100       25 if ($last->{index} == 0) {
271 7         10 $yaml .= "{";
272             }
273             else {
274 5         7 $yaml .= ",";
275             }
276             }
277             elsif ($last->{type} eq 'MAPVALUE') {
278 47 50       100 if ($last->{index} == 0) {
279 0         0 die "Should not happen (index 0 in MAPVALUE)";
280             }
281 47         64 $yaml .= ": ";
282             }
283 108 100       204 if ($props) {
284 8         48 $yaml .= " $props ";
285             }
286 108         217 $new_indent .= ' ' x $self->indent;
287             }
288             else {
289 1198 100       2422 if ($last->{type} eq 'DOC') {
290 617         1066 $newline = $last->{newline};
291             }
292             else {
293 581 100       1128 if ($last->{newline}) {
294 50         70 $yaml .= "\n";
295 50         76 $last->{column} = 0;
296             }
297 581 100       994 if ($last->{type} eq 'MAPVALUE') {
298 240         302 $zero_indent = 1;
299 240         300 $newline = 1;
300             }
301             else {
302 341 100 100     915 if (not $props and $self->indent == 1) {
303 68         93 $new_indent .= ' ' x 2;
304             }
305             else {
306 273         495 $new_indent .= ' ' x $self->indent;
307             }
308 341 100       646 if ($last->{column}) {
309 21 100       37 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
310 21         29 $yaml .= $space;
311             }
312             else {
313 320         398 $yaml .= $indent;
314             }
315 341 100       672 if ($last->{type} eq 'SEQ') {
    100          
    50          
316 265         307 $yaml .= "-";
317             }
318             elsif ($last->{type} eq 'MAP') {
319 47         72 $last->{type} = 'COMPLEX';
320 47         57 $zero_indent = 1;
321 47         65 $yaml .= "?";
322             }
323             elsif ($last->{type} eq 'COMPLEXVALUE') {
324 29         52 $yaml .= ":";
325 29         33 $zero_indent = 1;
326             }
327             else {
328 0         0 die "Should not happen ($last->{type} in sequence_start)";
329             }
330 341         491 $last->{column} = 1;
331             }
332 581         816 $last->{newline} = 0;
333             }
334 1198 100       1949 if ($props) {
335 73 100       185 $yaml .= $last->{column} ? ' ' : $indent;
336 73         94 $yaml .= $props;
337 73         129 $newline = 1;
338             }
339             }
340 1306         3035 $self->_write($yaml);
341 1306         1959 $last->{index}++;
342 1306         2768 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 1306         2270 $new_info->{type} = 'SEQ';
352 1306         1533 push @{ $stack }, $new_info;
  1306         2139  
353 1306         2925 $self->{open_ended} = 0;
354             }
355              
356             sub sequence_end_event {
357 1306     1306 1 6702 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ sequence_end_event\n";
358 1306         1962 my ($self, $info) = @_;
359 1306         1980 my $stack = $self->event_stack;
360              
361 1306         1583 my $last = pop @{ $stack };
  1306         2009  
362 1306 100       3360 if ($last->{index} == 0) {
    100          
363 56         79 my $indent = $last->{indent};
364 56         69 my $zero_indent = $last->{zero_indent};
365 56 100       110 if ($last->{zero_indent}) {
366 6         13 $indent .= ' ' x $self->indent;
367             }
368 56 100       91 my $yaml .= $self->column ? ' ' : $indent;
369 56         68 $yaml .= "[]";
370 56 100       121 if ($last->{flow} < 2) {
371 48         57 $yaml .= "\n";
372             }
373 56         84 $self->_write($yaml);
374             }
375             elsif ($last->{flow}) {
376 184         244 my $yaml = "]";
377 184 100       360 if ($last->{flow} == 1) {
378 84         119 $yaml .= "\n";
379             }
380 184         283 $self->_write($yaml);
381             }
382 1306         3385 $last = $stack->[-1];
383 1306         1949 $last->{column} = $self->column;
384 1306 100       5570 if ($last->{type} eq 'SEQ') {
    100          
    100          
    100          
    100          
385             }
386             elsif ($last->{type} eq 'MAP') {
387 12         30 $last->{type} = 'MAPVALUE';
388             }
389             elsif ($last->{type} eq 'MAPVALUE') {
390 287         621 $last->{type} = 'MAP';
391             }
392             elsif ($last->{type} eq 'COMPLEX') {
393 47         118 $last->{type} = 'COMPLEXVALUE';
394             }
395             elsif ($last->{type} eq 'COMPLEXVALUE') {
396 29         52 $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 9295     9295 1 39826 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ scalar_event\n";
490 9295         11847 my ($self, $info) = @_;
491 9295         13004 my $stack = $self->event_stack;
492 9295         10805 my $last = $stack->[-1];
493 9295         11236 my $indent = $last->{indent};
494 9295         13248 my $value = $info->{value};
495 9295         11306 my $flow = $last->{flow};
496              
497 9295         10351 my $props = '';
498 9295         10441 my $anchor = $info->{anchor};
499 9295         10103 my $tag = $info->{tag};
500 9295 100       13685 if (defined $anchor) {
501 459         668 $anchor = "&$anchor";
502             }
503 9295 100       14038 if (defined $tag) {
504 489         1233 $tag = $self->_emit_tag('scalar', $tag);
505             }
506 9295         19173 $props = join ' ', grep defined, ($anchor, $tag);
507              
508 9295         9323 DEBUG and local $Data::Dumper::Useqq = 1;
509 9295 50       13018 $value = '' unless defined $value;
510              
511 9295         16427 my $style = $self->_find_best_scalar_style(
512             info => $info,
513             value => $value,
514             );
515              
516 9295         11684 my $open_ended = 0;
517              
518 9295 100       15227 if ($style == YAML_PLAIN_SCALAR_STYLE) {
    100          
    100          
    100          
519 7555         10991 $value =~ s/\n/\n\n/g;
520             }
521             elsif ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
522 506         1121 my $new_indent = $last->{indent} . (' ' x $self->indent);
523 506         1054 $value =~ s/(\n+)/"\n" x (1 + (length $1))/eg;
  10         53  
524 506         1169 my @lines = split m/\n/, $value, -1;
525 506 100       956 if (@lines > 1) {
526 10         41 for my $line (@lines[1 .. $#lines]) {
527 20 100       48 $line = $new_indent . $line
528             if length $line;
529             }
530             }
531 506         908 $value = join "\n", @lines;
532 506         743 $value =~ s/'/''/g;
533 506         956 $value = "'" . $value . "'";
534             }
535             elsif ($style == YAML_LITERAL_SCALAR_STYLE) {
536 364         451 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$value], ['value']);
537 364         566 my $indicators = '';
538 364 100       1308 if ($value =~ m/\A\n* +/) {
539 36         82 $indicators .= $self->indent;
540             }
541 364         804 my $indent = $indent . ' ' x $self->indent;
542 364 100       2151 if ($value !~ m/\n\z/) {
    100          
543 87         131 $indicators .= '-';
544 87         123 $value .= "\n";
545             }
546             elsif ($value =~ m/(\n|\A)\n\z/) {
547 36         56 $indicators .= '+';
548 36         51 $open_ended = 1;
549             }
550 364         1952 $value =~ s/^(?=.)/$indent/gm;
551 364         829 $value = "|$indicators\n$value";
552             }
553             elsif ($style == YAML_FOLDED_SCALAR_STYLE) {
554 120         153 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$value], ['value']);
555 120         377 my @lines = split /\n/, $value, -1;
556 120         133 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\@lines], ['lines']);
557 120         147 my $trailing = -1;
558 120         288 while (@lines) {
559 218 100       498 last if $lines[-1] ne '';
560 99         125 pop @lines;
561 99         157 $trailing++;
562             }
563 120         164 my %start_with_space;
564 120         378 for my $i (0 .. $#lines) {
565 211 100       587 if ($lines[ $i ] =~ m/^[ \t]+/) {
566 31         73 $start_with_space{ $i } = 1;
567             }
568             }
569 120         181 my $indicators = '';
570 120 100       415 if ($value =~ m/\A\n* +/) {
571 19         42 $indicators .= $self->indent;
572             }
573 120         270 my $indent = $indent . ' ' x $self->indent;
574 120 100       349 if ($trailing > 0) {
    100          
575 3         3 $indicators .= '+';
576 3         4 $open_ended = 1;
577             }
578             elsif ($trailing < 0) {
579 24         38 $indicators .= '-';
580             }
581 120         189 $value = ">$indicators\n";
582 120         173 my $got_content = 0;
583 120         198 for my $i (0 .. $#lines) {
584 211         261 my $line = $lines[ $i ];
585 211   100     605 my $sp = $start_with_space{ $i } || 0;
586 211 100 100     451 my $spnext = $i == $#lines ? 1 : $start_with_space{ $i+1 } || 0;
587 211 100 100     466 my $spprev = $i == 0 ? 1 : $start_with_space{ $i-1 } || 0;
588 211 100       337 my $empty = length $line ? 0 : 1;
589 211 100       403 my $emptynext = $i == $#lines ? '' : length $lines[$i+1] ? 0 : 1;
    100          
590 211         583 my $nl = 0;
591 211 100       341 if ($empty) {
592 47 100 100     139 if ($spnext and $spprev) {
    100          
    100          
593 8         12 $nl = 1;
594             }
595             elsif (not $spnext) {
596 37         37 $nl = 1;
597             }
598             elsif (not $got_content) {
599 1         2 $nl = 1;
600             }
601             }
602             else {
603 164         168 $got_content = 1;
604 164         255 $value .= "$indent$line\n";
605 164 100 100     466 if (not $sp and not $spnext) {
606 32         40 $nl = 1;
607             }
608             }
609 211 100       396 if ($nl) {
610 78         125 $value .= "\n";
611             }
612             }
613 120 100       286 $value .= "\n" x ($trailing) if $trailing > 0;
614             }
615             else {
616 750 50       4086 $value =~ s/([$escape_re"\\])/$to_escape{ $1 } || sprintf '\\u%04x', ord($1)/eg;
  722         2995  
617 750         1426 $value = '"' . $value . '"';
618             }
619              
620 9295         8896 DEBUG and warn __PACKAGE__.':'.__LINE__.": (@$stack)\n";
621 9295         16911 my $yaml = $self->_emit_scalar(
622             indent => $indent,
623             props => $props,
624             value => $value,
625             style => $style,
626             );
627              
628 9295         12610 $last->{index}++;
629 9295         10728 $last->{newline} = 0;
630 9295         17244 $self->_write($yaml);
631 9295         13805 $last->{column} = $self->column;
632 9295         28579 $self->{open_ended} = $open_ended;
633             }
634              
635             sub _find_best_scalar_style {
636 9295     9295   19197 my ($self, %args) = @_;
637 9295         11282 my $info = $args{info};
638 9295         11376 my $style = $info->{style};
639 9295         11326 my $value = $args{value};
640 9295         12013 my $stack = $self->event_stack;
641 9295         10399 my $last = $stack->[-1];
642 9295         10315 my $flow = $last->{flow};
643              
644 9295         15857 my $first = substr($value, 0, 1);
645 9295 100       44705 if ($value eq '') {
    100          
646 887 100 100     2963 if ($flow and $last->{type} ne 'MAPVALUE' and $last->{type} ne 'MAP') {
    100 100        
647 24         36 $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         97 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
656             }
657 9295   100     18496 $style ||= YAML_PLAIN_SCALAR_STYLE;
658              
659 9295 100 100     31830 if ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
    100          
    100          
660 354 100 100     2849 if ($value =~ m/ \n/ or $value =~ m/\n / or $value =~ m/^\n/ or $value =~ m/\n$/) {
    50 100        
      100        
661 16         27 $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 443 100       1161 if ($value eq '') {
    100          
669 22         32 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
670             }
671             elsif ($flow) {
672             # no block scalars in flow
673 69 100       134 if ($value =~ tr/\n//) {
674 61         84 $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 7941 100 100     78452 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         102 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
686             }
687             elsif ($value eq "\n") {
688 8         145 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
689             }
690             elsif ($value !~ tr/ //c) {
691 10         18 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
692             }
693             elsif ($value !~ tr/ \n//c) {
694 12         22 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
695             }
696             elsif ($value =~ tr/\n//) {
697 134 100       343 $style = $flow ? YAML_DOUBLE_QUOTED_SCALAR_STYLE : YAML_LITERAL_SCALAR_STYLE;
698             }
699             elsif ($forbidden_first{ $first }) {
700 94         149 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
701             }
702             elsif ($flow and $value =~ tr/,[]{}//) {
703 5         7 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
704             }
705             elsif (substr($value, 0, 3) =~ m/^(?:---|\.\.\.)/) {
706 12         26 $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         12 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
713             }
714             elsif ($value =~ m/[: \t]\z/) {
715 27         59 $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 204 100 100     1042 if (length ($value) == 1 or substr($value, 1, 1) =~ m/^\s/) {
722 16         29 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
723             }
724             }
725             }
726 9295 100 100     18266 if ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE and not $info->{style}) {
727 158 100 100     452 if ($value =~ tr/'// and $value !~ tr/"//) {
728 20         21 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
729             }
730             }
731 9295         23647 return $style;
732             }
733              
734             sub _emit_scalar {
735 9295     9295   26245 my ($self, %args) = @_;
736 9295         11834 my $props = $args{props};
737 9295         11397 my $value = $args{value};
738 9295         10700 my $style = $args{style};
739 9295         12394 my $stack = $self->event_stack;
740 9295         10490 my $last = $stack->[-1];
741 9295         10591 my $flow = $last->{flow};
742              
743 9295         10195 my $yaml = '';
744 9295         9929 my $pvalue = $props;
745 9295 100 100     24003 if ($props and length $value) {
    100          
746 522         868 $pvalue .= " $value";
747             }
748             elsif (length $value) {
749 8011         10665 $pvalue .= $value;
750             }
751 9295 100       12499 if ($flow) {
752 1249 100 100     2070 if ($props and not length $value) {
753 50         52 $pvalue .= ' ';
754             }
755             $yaml = $self->_emit_flow_scalar(
756             value => $value,
757             pvalue => $pvalue,
758             style => $args{style},
759 1249         2254 );
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 8046         17073 );
769             }
770 9295         20453 return $yaml;
771             }
772              
773             sub _emit_block_scalar {
774 8046     8046   26006 my ($self, %args) = @_;
775 8046         10321 my $props = $args{props};
776 8046         9683 my $value = $args{value};
777 8046         9253 my $pvalue = $args{pvalue};
778 8046         8842 my $indent = $args{indent};
779 8046         8618 my $style = $args{style};
780 8046         11176 my $stack = $self->event_stack;
781 8046         8775 my $last = $stack->[-1];
782              
783 8046         8021 my $yaml;
784 8046 100 100     21061 if ($last->{type} eq 'MAP' or $last->{type} eq 'SEQ') {
785 4198 100 100     10400 if ($last->{index} == 0 and $last->{newline}) {
786 992         1703 $yaml .= "\n";
787 992         1335 $last->{column} = 0;
788 992         1431 $last->{newline} = 0;
789             }
790             }
791 8046         9244 my $space = ' ';
792 8046   100     17453 my $multiline = ($style == YAML_LITERAL_SCALAR_STYLE or $style == YAML_FOLDED_SCALAR_STYLE);
793 8046 100       12533 if ($last->{type} eq 'MAP') {
794              
795 2721 100       3918 if ($last->{column}) {
796 447 100       751 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
797 447         788 $yaml .= $space;
798             }
799             else {
800 2274         3496 $yaml .= $indent;
801             }
802 2721 100 100     5347 if ($props and not length $value) {
803 100         110 $pvalue .= ' ';
804             }
805 2721         3718 $last->{type} = 'MAPVALUE';
806 2721 100       3997 if ($multiline) {
807             # oops, a complex key
808 17         25 $yaml .= "? ";
809 17         26 $last->{type} = 'COMPLEXVALUE';
810             }
811 2721 100       4233 if (not $multiline) {
812 2704         3330 $pvalue .= ":";
813             }
814             }
815             else {
816 5325 100       10255 if ($last->{type} eq 'MAPVALUE') {
    100          
817 2153         3264 $last->{type} = 'MAP';
818             }
819             elsif ($last->{type} eq 'DOC') {
820             }
821             else {
822 1519 100       2707 if ($last->{column}) {
823 260 100       478 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
824 260         456 $yaml .= $space;
825             }
826             else {
827 1259         1911 $yaml .= $indent;
828             }
829 1519 100       3413 if ($last->{type} eq 'COMPLEXVALUE') {
    50          
830 42         63 $last->{type} = 'MAP';
831 42         61 $yaml .= ":";
832             }
833             elsif ($last->{type} eq 'SEQ') {
834 1477         1707 $yaml .= "-";
835             }
836             else {
837 0         0 die "Should not happen ($last->{type} in scalar_event)";
838              
839             }
840 1519         1978 $last->{column} = 1;
841             }
842              
843 5325 100       8449 if (length $pvalue) {
844 5032 100       8137 if ($last->{column}) {
845 3869         5388 $pvalue = "$space$pvalue";
846             }
847             }
848 5325 100       7717 if (not $multiline) {
849 4858         5565 $pvalue .= "\n";
850             }
851             }
852 8046         11384 $yaml .= $pvalue;
853 8046         20602 return $yaml;
854             }
855              
856             sub _emit_flow_scalar {
857 1249     1249   3041 my ($self, %args) = @_;
858 1249         1545 my $value = $args{value};
859 1249         1361 my $pvalue = $args{pvalue};
860 1249         1497 my $stack = $self->event_stack;
861 1249         1269 my $last = $stack->[-1];
862              
863 1249         1228 my $yaml;
864 1249 100       2637 if ($last->{type} eq 'SEQ') {
    100          
    50          
865 271 100       506 if ($last->{index} == 0) {
866 142 100       265 if ($self->column) {
867 108         186 $yaml .= ' ';
868             }
869 142         249 $yaml .= "[";
870             }
871             else {
872 129         198 $yaml .= ", ";
873             }
874             }
875             elsif ($last->{type} eq 'MAP') {
876 530 100       763 if ($last->{index} == 0) {
877 307 100       437 if ($self->column) {
878 205         282 $yaml .= ' ';
879             }
880 307         474 $yaml .= "{";
881             }
882             else {
883 223         311 $yaml .= ", ";
884             }
885 530         689 $last->{type} = 'MAPVALUE';
886             }
887             elsif ($last->{type} eq 'MAPVALUE') {
888 448 50       828 if ($last->{index} == 0) {
889 0         0 die "Should not happen (index 0 in MAPVALUE)";
890             }
891 448         558 $yaml .= ": ";
892 448         637 $last->{type} = 'MAP';
893             }
894 1249 100       1697 if ($self->column + length $pvalue > $self->width) {
895 51         75 $yaml .= "\n";
896 51         82 $yaml .= $last->{indent};
897 51         70 $yaml .= ' ' x $self->indent;
898             }
899 1249         1485 $yaml .= $pvalue;
900 1249         2635 return $yaml;
901             }
902              
903             sub alias_event {
904 199     199 1 1002 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ alias_event\n";
905 199         317 my ($self, $info) = @_;
906 199         349 my $stack = $self->event_stack;
907 199         280 my $last = $stack->[-1];
908 199         321 my $indent = $last->{indent};
909 199         257 my $flow = $last->{flow};
910              
911 199         306 my $alias = '*' . $info->{value};
912              
913 199         269 my $yaml = '';
914 199 100 100     770 if ($last->{type} eq 'MAP' or $last->{type} eq 'SEQ') {
915 105 100 100     288 if ($last->{index} == 0 and $last->{newline}) {
916 12         15 $yaml .= "\n";
917 12         15 $last->{column} = 0;
918 12         18 $last->{newline} = 0;
919             }
920             }
921 199 100       448 $yaml .= $last->{column} ? ' ' : $indent;
922 199 100       334 if ($flow) {
923 24         31 my $space = '';
924 24 100       76 if ($last->{type} eq 'SEQ') {
    100          
    50          
925 4 100       11 if ($last->{index} == 0) {
926 1 50       3 if ($flow == 1) {
927 0         0 $yaml .= ' ';
928             }
929 1         2 $yaml .= "[";
930             }
931             else {
932 3         6 $yaml .= ", ";
933             }
934             }
935             elsif ($last->{type} eq 'MAP') {
936 6 100       11 if ($last->{index} == 0) {
937 2 50       4 if ($flow == 1) {
938 0         0 $yaml .= ' ';
939             }
940 2         2 $yaml .= "{";
941             }
942             else {
943 4         6 $yaml .= ", ";
944             }
945 6         11 $last->{type} = 'MAPVALUE';
946 6         7 $space = ' ';
947             }
948             elsif ($last->{type} eq 'MAPVALUE') {
949 14 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 14         17 $yaml .= ": ";
958             }
959 14         20 $last->{type} = 'MAP';
960             }
961 24         39 $yaml .= "$alias$space";
962             }
963             else {
964 175 100       333 if ($last->{type} eq 'MAP') {
965 25         43 $yaml .= "$alias :";
966 25         45 $last->{type} = 'MAPVALUE';
967             }
968             else {
969              
970 150 100       328 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       284 if ($last->{type} eq 'COMPLEXVALUE') {
    50          
    50          
978 3         5 $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         89 $yaml .= "- ";
986             }
987             else {
988 0         0 die "Unexpected";
989             }
990             }
991 150         205 $yaml .= "$alias\n";
992             }
993             }
994              
995 199         571 $self->_write("$yaml");
996 199         318 $last->{index}++;
997 199         351 $last->{column} = $self->column;
998 199         384 $self->{open_ended} = 0;
999             }
1000              
1001             sub document_start_event {
1002 3233     3233 1 12240 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ document_start_event\n";
1003 3233         5240 my ($self, $info) = @_;
1004 3233         3987 my $newline = 0;
1005 3233         4880 my $implicit = $info->{implicit};
1006 3233 100       6407 if ($info->{version_directive}) {
1007 18 100       27 if ($self->{open_ended}) {
1008 10         17 $self->_write("...\n");
1009             }
1010 18         55 $self->_write("%YAML $info->{version_directive}->{major}.$info->{version_directive}->{minor}\n");
1011 18         27 $self->{open_ended} = 0;
1012 18         24 $implicit = 0; # we need ---
1013             }
1014 3233 100       5959 unless ($implicit) {
1015 1183         1481 $newline = 1;
1016 1183         2701 $self->_write("---");
1017             }
1018             $self->set_event_stack([
1019             {
1020 3233         8005 type => 'DOC', index => 0, indent => '', info => $info,
1021             newline => $newline, column => $self->column,
1022             }
1023             ]);
1024             }
1025              
1026             sub document_end_event {
1027 3232     3232 1 12057 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ document_end_event\n";
1028 3232         4880 my ($self, $info) = @_;
1029 3232         7098 $self->set_event_stack([]);
1030 3232 100 100     10781 if ($self->{open_ended} or not $info->{implicit}) {
1031 241         515 $self->_write("...\n");
1032 241         514 $self->{open_ended} = 0;
1033             }
1034             else {
1035 2991         7592 $self->{open_ended} = 1;
1036             }
1037             }
1038              
1039       3026 1   sub stream_start_event {
1040             }
1041              
1042       3025 1   sub stream_end_event {
1043             }
1044              
1045             sub _emit_tag {
1046 644     644   1165 my ($self, $type, $tag) = @_;
1047 644         1222 my $map = $self->tagmap;
1048 644         1862 for my $key (sort keys %$map) {
1049 644 100       4443 if ($tag =~ m/^\Q$key\E(.*)/) {
1050 482         1272 $tag = $map->{ $key } . $1;
1051 482         1018 return $tag;
1052             }
1053             }
1054 162 100       784 if ($tag =~ m/^(!.*)/) {
1055 107         273 $tag = "$1";
1056             }
1057             else {
1058 55         142 $tag = "!<$tag>";
1059             }
1060 162         346 return $tag;
1061             }
1062              
1063             sub finish {
1064 1585     1585 1 2341 my ($self) = @_;
1065 1585         2225 $self->writer->finish;
1066             }
1067              
1068             sub _write {
1069 14724     14724   20273 my ($self, $yaml) = @_;
1070 14724 100       22444 return unless length $yaml;
1071 12818         28200 my @lines = split m/\n/, $yaml, -1;
1072 12818         15999 my $newlines = @lines - 1;
1073 12818         15923 $self->{line} += $newlines;
1074 12818 100       18020 if (length $lines[-1]) {
1075 6715 100       8670 if ($newlines) {
1076 874         1640 $self->{column} = length $lines[-1];
1077             }
1078             else {
1079 5841         8721 $self->{column} += length $lines[-1];
1080             }
1081             }
1082             else {
1083 6103         7381 $self->{column} = 0;
1084             }
1085 12818         18712 $self->writer->write($yaml);
1086             }
1087              
1088             1;
1089              
1090             __END__
1091              
1092             =pod
1093              
1094             =encoding utf-8
1095              
1096             =head1 NAME
1097              
1098             YAML::PP::Emitter - Emitting events
1099              
1100             =head1 SYNOPSIS
1101              
1102             my $emitter = YAML::PP::Emitter->new(
1103             indent => 4,
1104             );
1105              
1106             $emitter->init;
1107              
1108             $emitter->stream_start_event;
1109             $emitter->document_start_event({ implicit => 1 });
1110             $emitter->sequence_start_event;
1111             $emitter->scalar_event({ value => $input, style => $style });
1112             $emitter->sequence_end_event;
1113             $emitter->document_end_event({ implicit => 1 });
1114             $emitter->stream_end_event;
1115              
1116             my $yaml = $emitter->writer->output;
1117             $emitter->finish;
1118              
1119             =head1 DESCRIPTION
1120              
1121             The emitter emits events to YAML. It provides methods for each event
1122             type. The arguments are mostly the same as the events from L<YAML::PP::Parser>.
1123              
1124             =head1 METHODS
1125              
1126             =over
1127              
1128             =item new
1129              
1130             my $emitter = YAML::PP::Emitter->new(
1131             indent => 4,
1132             );
1133              
1134             Constructor. Currently takes these options:
1135              
1136             =over
1137              
1138             =item indent
1139              
1140             =item writer
1141              
1142             =back
1143              
1144             =item stream_start_event, stream_end_event, document_start_event, document_end_event, sequence_start_event, sequence_end_event, mapping_start_event, mapping_end_event, scalar_event, alias_event
1145              
1146             =item indent, set_indent
1147              
1148             Getter/setter for number of indentation spaces.
1149              
1150             TODO: Currently sequences are always zero-indented.
1151              
1152             =item writer, set_writer
1153              
1154             Getter/setter for the writer object. By default L<YAML::PP::Writer>.
1155             You can pass your own writer if you want to output the resulting YAML yourself.
1156              
1157             =item init
1158              
1159             Initialize
1160              
1161             =item finish
1162              
1163             =back
1164              
1165             =cut