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 38     38   2591 use strict;
  38         83  
  38         1130  
2 38     38   200 use warnings;
  38         78  
  38         2028  
3             package YAML::PP::Emitter;
4              
5             our $VERSION = '0.036_001'; # TRIAL VERSION
6 38     38   9524 use Data::Dumper;
  38         101341  
  38         2516  
7              
8 38         2832 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 38     38   254 /;
  38         92  
14              
15 38 50   38   267 use constant DEBUG => $ENV{YAML_PP_EMIT_DEBUG} ? 1 : 0;
  38         90  
  38         2532  
16 38     38   264 use constant DEFAULT_WIDTH => 80;
  38         103  
  38         252658  
17              
18             sub new {
19 2181     2181 1 10597 my ($class, %args) = @_;
20             my $self = bless {
21             indent => $args{indent} || 2,
22             writer => $args{writer},
23 2181   100     13677 width => $args{width} || DEFAULT_WIDTH,
      50        
24             }, $class;
25 2181         6431 $self->init;
26 2181         5087 return $self;
27             }
28              
29             sub clone {
30 9     9 0 23 my ($self) = @_;
31 9         23 my $clone = {
32             indent => $self->indent,
33             };
34 9         34 return bless $clone, ref $self;
35             }
36              
37 43672     43672 0 68365 sub event_stack { return $_[0]->{event_stack} }
38 6449     6449 0 19174 sub set_event_stack { $_[0]->{event_stack} = $_[1] }
39 4468     4468 1 12758 sub indent { return $_[0]->{indent} }
40 1247     1247 0 2526 sub width { return $_[0]->{width} }
41 0     0 0 0 sub line { return $_[0]->{line} }
42 20848     20848 0 54508 sub column { return $_[0]->{column} }
43 1     1 1 1316 sub set_indent { $_[0]->{indent} = $_[1] }
44 27786     27786 1 71958 sub writer { $_[0]->{writer} }
45 5098     5098 1 14441 sub set_writer { $_[0]->{writer} = $_[1] }
46 644     644 0 1186 sub tagmap { return $_[0]->{tagmap} }
47 5199     5199 0 9708 sub set_tagmap { $_[0]->{tagmap} = $_[1] }
48              
49             sub init {
50 5199     5199 1 79559 my ($self) = @_;
51 5199 100       9391 unless ($self->writer) {
52 2180         5571 $self->set_writer(YAML::PP::Writer->new);
53             }
54             $self->set_tagmap({
55 5199         16336 'tag:yaml.org,2002:' => '!!',
56             });
57 5199         8010 $self->{open_ended} = 0;
58 5199         8059 $self->{line} = 0;
59 5199         8191 $self->{column} = 0;
60 5199         8626 $self->writer->init;
61             }
62              
63             sub mapping_start_event {
64 1881     1881 1 17096 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ mapping_start_event\n";
65 1881         3293 my ($self, $info) = @_;
66 1881         3672 my $stack = $self->event_stack;
67 1881         3091 my $last = $stack->[-1];
68 1881         3045 my $indent = $last->{indent};
69 1881         2884 my $new_indent = $indent;
70 1881         3039 my $yaml = '';
71              
72 1881         6520 my $props = '';
73 1881         2898 my $anchor = $info->{anchor};
74 1881         2891 my $tag = $info->{tag};
75 1881 100       4426 if (defined $anchor) {
76 98         264 $anchor = "&$anchor";
77             }
78 1881 100       3647 if (defined $tag) {
79 109         313 $tag = $self->_emit_tag('map', $tag);
80             }
81 1881         6338 $props = join ' ', grep defined, ($anchor, $tag);
82              
83 1881   100     6017 my $flow = $last->{flow} || 0;
84 1881 100 100     5943 $flow++ if ($info->{style} || 0) eq YAML_FLOW_MAPPING_STYLE;
85              
86 1881         2882 my $newline = 0;
87 1881 100       3793 if ($flow > 1) {
88 135 100       429 if ($last->{type} eq 'SEQ') {
    100          
    50          
89 92 100       208 if ($last->{newline}) {
90 17         30 $yaml .= ' ';
91             }
92 92 100       196 if ($last->{index} == 0) {
93 27         51 $yaml .= "[";
94             }
95             else {
96 65         121 $yaml .= ",";
97             }
98             }
99             elsif ($last->{type} eq 'MAP') {
100 2 50       8 if ($last->{newline}) {
101 0         0 $yaml .= ' ';
102             }
103 2 50       8 if ($last->{index} == 0) {
104 2         5 $yaml .= "{";
105             }
106             else {
107 0         0 $yaml .= ",";
108             }
109             }
110             elsif ($last->{type} eq 'MAPVALUE') {
111 41 50       93 if ($last->{index} == 0) {
112 0         0 die "Should not happen (index 0 in MAPVALUE)";
113             }
114 41         70 $yaml .= ": ";
115             }
116 135 100       322 if ($props) {
117 18         55 $yaml .= " $props ";
118             }
119 135         255 $new_indent .= ' ' x $self->indent;
120             }
121             else {
122 1746 100       4002 if ($last->{type} eq 'DOC') {
123 955         1884 $newline = $last->{newline};
124             }
125             else {
126 791 100       1865 if ($last->{newline}) {
127 104         256 $yaml .= "\n";
128 104         286 $last->{column} = 0;
129             }
130 791 100       1800 if ($last->{type} eq 'MAPVALUE') {
131 258         683 $new_indent .= ' ' x $self->indent;
132 258         541 $newline = 1;
133             }
134             else {
135 533         915 $new_indent = $indent;
136 533 100 100     1690 if (not $props and $self->indent == 1) {
137 91         172 $new_indent .= ' ' x 2;
138             }
139             else {
140 442         948 $new_indent .= ' ' x $self->indent;
141             }
142              
143 533 100       1455 if ($last->{column}) {
144 14 100       58 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
145 14         36 $yaml .= $space;
146             }
147             else {
148 519         843 $yaml .= $indent;
149             }
150 533 100       1216 if ($last->{type} eq 'SEQ') {
    100          
    50          
151 505         940 $yaml .= '-';
152             }
153             elsif ($last->{type} eq 'MAP') {
154 19         52 $yaml .= "?";
155 19         46 $last->{type} = 'COMPLEX';
156             }
157             elsif ($last->{type} eq 'COMPLEXVALUE') {
158 9         23 $yaml .= ":";
159             }
160             else {
161 0         0 die "Should not happen ($last->{type} in mapping_start)";
162             }
163 533         864 $last->{column} = 1;
164             }
165 791         1295 $last->{newline} = 0;
166             }
167 1746 100       3873 if ($props) {
168 158 100       436 $yaml .= $last->{column} ? ' ' : $indent;
169 158         258 $yaml .= $props;
170 158         234 $newline = 1;
171             }
172             }
173 1881         4743 $self->_write($yaml);
174 1881         4497 my $new_info = {
175             index => 0, indent => $new_indent, info => $info,
176             newline => $newline,
177             column => $self->column,
178             flow => $flow,
179             };
180 1881         4694 $new_info->{type} = 'MAP';
181 1881         2570 push @{ $stack }, $new_info;
  1881         3625  
182 1881         2986 $last->{index}++;
183 1881         5007 $self->{open_ended} = 0;
184             }
185              
186             sub mapping_end_event {
187 1880     1880 1 12234 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ mapping_end_event\n";
188 1880         3295 my ($self, $info) = @_;
189 1880         3492 my $stack = $self->event_stack;
190              
191 1880         2744 my $last = pop @{ $stack };
  1880         3263  
192 1880 100       5544 if ($last->{index} == 0) {
    100          
193 25         64 my $indent = $last->{indent};
194 25         47 my $zero_indent = $last->{zero_indent};
195 25 50       83 if ($last->{zero_indent}) {
196 0         0 $indent .= ' ' x $self->indent;
197             }
198 25 100       64 if ($self->column) {
199 20         48 $self->_write(" {}\n");
200             }
201             else {
202 5         25 $self->_write("$indent\{}\n");
203             }
204             }
205             elsif ($last->{flow}) {
206 317         865 my $yaml = "}";
207 317 100       777 if ($last->{flow} == 1) {
208 184         309 $yaml .= "\n";
209             }
210 317         1663 $self->_write("$yaml");
211             }
212 1880         4874 $last = $stack->[-1];
213 1880         3569 $last->{column} = $self->column;
214 1880 100       8810 if ($last->{type} eq 'SEQ') {
    100          
    100          
    100          
    100          
215             }
216             elsif ($last->{type} eq 'MAP') {
217 2         11 $last->{type} = 'MAPVALUE';
218             }
219             elsif ($last->{type} eq 'MAPVALUE') {
220 299         778 $last->{type} = 'MAP';
221             }
222             elsif ($last->{type} eq 'COMPLEX') {
223 19         66 $last->{type} = 'COMPLEXVALUE';
224             }
225             elsif ($last->{type} eq 'COMPLEXVALUE') {
226 9         27 $last->{type} = 'MAP';
227             }
228             }
229              
230             sub sequence_start_event {
231 1306     1306 1 11871 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ sequence_start_event\n";
232 1306         2436 my ($self, $info) = @_;
233 1306         2702 my $stack = $self->event_stack;
234 1306         2252 my $last = $stack->[-1];
235 1306         2240 my $indent = $last->{indent};
236 1306         1905 my $new_indent = $indent;
237 1306         1861 my $yaml = '';
238              
239 1306         1896 my $props = '';
240 1306         2113 my $anchor = $info->{anchor};
241 1306         2026 my $tag = $info->{tag};
242 1306 100       3061 if (defined $anchor) {
243 43         125 $anchor = "&$anchor";
244             }
245 1306 100       2679 if (defined $tag) {
246 46         134 $tag = $self->_emit_tag('seq', $tag);
247             }
248 1306         4389 $props = join ' ', grep defined, ($anchor, $tag);
249              
250 1306   100     4161 my $flow = $last->{flow} || 0;
251 1306 100 100     5959 $flow++ if $flow or ($info->{style} || 0) eq YAML_FLOW_SEQUENCE_STYLE;
      100        
252 1306         1925 my $newline = 0;
253 1306         1771 my $zero_indent = 0;
254 1306 100       2626 if ($flow > 1) {
255 108 100       415 if ($last->{type} eq 'SEQ') {
    100          
    50          
256 49 50       111 if ($last->{newline}) {
257 0         0 $yaml .= ' ';
258             }
259 49 100       105 if ($last->{index} == 0) {
260 14         26 $yaml .= "[";
261             }
262             else {
263 35         97 $yaml .= ",";
264             }
265             }
266             elsif ($last->{type} eq 'MAP') {
267 12 100       28 if ($last->{newline}) {
268 1         3 $yaml .= ' ';
269             }
270 12 100       35 if ($last->{index} == 0) {
271 7         14 $yaml .= "{";
272             }
273             else {
274 5         10 $yaml .= ",";
275             }
276             }
277             elsif ($last->{type} eq 'MAPVALUE') {
278 47 50       157 if ($last->{index} == 0) {
279 0         0 die "Should not happen (index 0 in MAPVALUE)";
280             }
281 47         88 $yaml .= ": ";
282             }
283 108 100       219 if ($props) {
284 8         27 $yaml .= " $props ";
285             }
286 108         204 $new_indent .= ' ' x $self->indent;
287             }
288             else {
289 1198 100       2749 if ($last->{type} eq 'DOC') {
290 617         1204 $newline = $last->{newline};
291             }
292             else {
293 581 100       1634 if ($last->{newline}) {
294 50         97 $yaml .= "\n";
295 50         97 $last->{column} = 0;
296             }
297 581 100       1298 if ($last->{type} eq 'MAPVALUE') {
298 240         421 $zero_indent = 1;
299 240         432 $newline = 1;
300             }
301             else {
302 341 100 100     1079 if (not $props and $self->indent == 1) {
303 68         136 $new_indent .= ' ' x 2;
304             }
305             else {
306 273         582 $new_indent .= ' ' x $self->indent;
307             }
308 341 100       856 if ($last->{column}) {
309 21 100       57 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
310 21         70 $yaml .= $space;
311             }
312             else {
313 320         534 $yaml .= $indent;
314             }
315 341 100       910 if ($last->{type} eq 'SEQ') {
    100          
    50          
316 265         495 $yaml .= "-";
317             }
318             elsif ($last->{type} eq 'MAP') {
319 47         113 $last->{type} = 'COMPLEX';
320 47         97 $zero_indent = 1;
321 47         80 $yaml .= "?";
322             }
323             elsif ($last->{type} eq 'COMPLEXVALUE') {
324 29         79 $yaml .= ":";
325 29         66 $zero_indent = 1;
326             }
327             else {
328 0         0 die "Should not happen ($last->{type} in sequence_start)";
329             }
330 341         581 $last->{column} = 1;
331             }
332 581         942 $last->{newline} = 0;
333             }
334 1198 100       2419 if ($props) {
335 73 100       279 $yaml .= $last->{column} ? ' ' : $indent;
336 73         125 $yaml .= $props;
337 73         238 $newline = 1;
338             }
339             }
340 1306         3365 $self->_write($yaml);
341 1306         2411 $last->{index}++;
342 1306         3155 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         3833 $new_info->{type} = 'SEQ';
352 1306         1934 push @{ $stack }, $new_info;
  1306         2555  
353 1306         3480 $self->{open_ended} = 0;
354             }
355              
356             sub sequence_end_event {
357 1306     1306 1 8652 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ sequence_end_event\n";
358 1306         2544 my ($self, $info) = @_;
359 1306         2499 my $stack = $self->event_stack;
360              
361 1306         1981 my $last = pop @{ $stack };
  1306         2254  
362 1306 100       3956 if ($last->{index} == 0) {
    100          
363 56         118 my $indent = $last->{indent};
364 56         96 my $zero_indent = $last->{zero_indent};
365 56 100       147 if ($last->{zero_indent}) {
366 6         24 $indent .= ' ' x $self->indent;
367             }
368 56 100       131 my $yaml .= $self->column ? ' ' : $indent;
369 56         96 $yaml .= "[]";
370 56 100       149 if ($last->{flow} < 2) {
371 48         80 $yaml .= "\n";
372             }
373 56         118 $self->_write($yaml);
374             }
375             elsif ($last->{flow}) {
376 184         300 my $yaml = "]";
377 184 100       379 if ($last->{flow} == 1) {
378 84         130 $yaml .= "\n";
379             }
380 184         327 $self->_write($yaml);
381             }
382 1306         3767 $last = $stack->[-1];
383 1306         2575 $last->{column} = $self->column;
384 1306 100       6501 if ($last->{type} eq 'SEQ') {
    100          
    100          
    100          
    100          
385             }
386             elsif ($last->{type} eq 'MAP') {
387 12         43 $last->{type} = 'MAPVALUE';
388             }
389             elsif ($last->{type} eq 'MAPVALUE') {
390 287         865 $last->{type} = 'MAP';
391             }
392             elsif ($last->{type} eq 'COMPLEX') {
393 47         147 $last->{type} = 'COMPLEXVALUE';
394             }
395             elsif ($last->{type} eq 'COMPLEXVALUE') {
396 29         98 $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 9275     9275 1 53065 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ scalar_event\n";
490 9275         15009 my ($self, $info) = @_;
491 9275         16870 my $stack = $self->event_stack;
492 9275         14893 my $last = $stack->[-1];
493 9275         14648 my $indent = $last->{indent};
494 9275         14060 my $value = $info->{value};
495 9275         13373 my $flow = $last->{flow};
496              
497 9275         12791 my $props = '';
498 9275         13419 my $anchor = $info->{anchor};
499 9275         13204 my $tag = $info->{tag};
500 9275 100       17735 if (defined $anchor) {
501 459         988 $anchor = "&$anchor";
502             }
503 9275 100       16430 if (defined $tag) {
504 489         1293 $tag = $self->_emit_tag('scalar', $tag);
505             }
506 9275         26406 $props = join ' ', grep defined, ($anchor, $tag);
507              
508 9275         12305 DEBUG and local $Data::Dumper::Useqq = 1;
509 9275 50       16832 $value = '' unless defined $value;
510              
511 9275         19046 my $style = $self->_find_best_scalar_style(
512             info => $info,
513             value => $value,
514             );
515              
516 9275         14185 my $open_ended = 0;
517              
518 9275 100       18862 if ($style == YAML_PLAIN_SCALAR_STYLE) {
    100          
    100          
    100          
519 7542         14401 $value =~ s/\n/\n\n/g;
520             }
521             elsif ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
522 499         1348 my $new_indent = $last->{indent} . (' ' x $self->indent);
523 499         1330 $value =~ s/(\n+)/"\n" x (1 + (length $1))/eg;
  10         62  
524 499         1500 my @lines = split m/\n/, $value, -1;
525 499 100       1321 if (@lines > 1) {
526 10         63 for my $line (@lines[1 .. $#lines]) {
527 20 100       77 $line = $new_indent . $line
528             if length $line;
529             }
530             }
531 499         1178 $value = join "\n", @lines;
532 499         1012 $value =~ s/'/''/g;
533 499         1375 $value = "'" . $value . "'";
534             }
535             elsif ($style == YAML_LITERAL_SCALAR_STYLE) {
536 364         533 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$value], ['value']);
537 364         742 my $indicators = '';
538 364 100       1545 if ($value =~ m/\A\n* +/) {
539 36         118 $indicators .= $self->indent;
540             }
541 364         939 my $indent = $indent . ' ' x $self->indent;
542 364 100       2567 if ($value !~ m/\n\z/) {
    100          
543 87         204 $indicators .= '-';
544 87         221 $value .= "\n";
545             }
546             elsif ($value =~ m/(\n|\A)\n\z/) {
547 36         82 $indicators .= '+';
548 36         71 $open_ended = 1;
549             }
550 364         2128 $value =~ s/^(?=.)/$indent/gm;
551 364         1214 $value = "|$indicators\n$value";
552             }
553             elsif ($style == YAML_FOLDED_SCALAR_STYLE) {
554 120         234 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$value], ['value']);
555 120         548 my @lines = split /\n/, $value, -1;
556 120         213 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\@lines], ['lines']);
557 120         239 my $trailing = -1;
558 120         380 while (@lines) {
559 218 100       568 last if $lines[-1] ne '';
560 99         177 pop @lines;
561 99         206 $trailing++;
562             }
563 120         213 my %start_with_space;
564 120         366 for my $i (0 .. $#lines) {
565 211 100       800 if ($lines[ $i ] =~ m/^[ \t]+/) {
566 31         118 $start_with_space{ $i } = 1;
567             }
568             }
569 120         323 my $indicators = '';
570 120 100       517 if ($value =~ m/\A\n* +/) {
571 19         51 $indicators .= $self->indent;
572             }
573 120         368 my $indent = $indent . ' ' x $self->indent;
574 120 100       423 if ($trailing > 0) {
    100          
575 3         5 $indicators .= '+';
576 3         5 $open_ended = 1;
577             }
578             elsif ($trailing < 0) {
579 24         57 $indicators .= '-';
580             }
581 120         297 $value = ">$indicators\n";
582 120         188 my $got_content = 0;
583 120         302 for my $i (0 .. $#lines) {
584 211         408 my $line = $lines[ $i ];
585 211   100     693 my $sp = $start_with_space{ $i } || 0;
586 211 100 100     669 my $spnext = $i == $#lines ? 1 : $start_with_space{ $i+1 } || 0;
587 211 100 100     649 my $spprev = $i == 0 ? 1 : $start_with_space{ $i-1 } || 0;
588 211 100       495 my $empty = length $line ? 0 : 1;
589 211 100       613 my $emptynext = $i == $#lines ? '' : length $lines[$i+1] ? 0 : 1;
    100          
590 211         315 my $nl = 0;
591 211 100       399 if ($empty) {
592 47 100 100     193 if ($spnext and $spprev) {
    100          
    100          
593 8         14 $nl = 1;
594             }
595             elsif (not $spnext) {
596 37         54 $nl = 1;
597             }
598             elsif (not $got_content) {
599 1         3 $nl = 1;
600             }
601             }
602             else {
603 164         250 $got_content = 1;
604 164         444 $value .= "$indent$line\n";
605 164 100 100     578 if (not $sp and not $spnext) {
606 32         48 $nl = 1;
607             }
608             }
609 211 100       600 if ($nl) {
610 78         187 $value .= "\n";
611             }
612             }
613 120 100       414 $value .= "\n" x ($trailing) if $trailing > 0;
614             }
615             else {
616 750 50       4251 $value =~ s/([$escape_re"\\])/$to_escape{ $1 } || sprintf '\\u%04x', ord($1)/eg;
  722         3845  
617 750         2719 $value = '"' . $value . '"';
618             }
619              
620 9275         11735 DEBUG and warn __PACKAGE__.':'.__LINE__.": (@$stack)\n";
621 9275         19857 my $yaml = $self->_emit_scalar(
622             indent => $indent,
623             props => $props,
624             value => $value,
625             style => $style,
626             );
627              
628 9275         14892 $last->{index}++;
629 9275         13945 $last->{newline} = 0;
630 9275         21645 $self->_write($yaml);
631 9275         19081 $last->{column} = $self->column;
632 9275         32238 $self->{open_ended} = $open_ended;
633             }
634              
635             sub _find_best_scalar_style {
636 9275     9275   25225 my ($self, %args) = @_;
637 9275         14733 my $info = $args{info};
638 9275         14630 my $style = $info->{style};
639 9275         13518 my $value = $args{value};
640 9275         15526 my $stack = $self->event_stack;
641 9275         13663 my $last = $stack->[-1];
642 9275         13124 my $flow = $last->{flow};
643              
644 9275         20271 my $first = substr($value, 0, 1);
645 9275 100       47479 if ($value eq '') {
    100          
646 886 100 100     4030 if ($flow and $last->{type} ne 'MAPVALUE' and $last->{type} ne 'MAP') {
    100 100        
647 24         41 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
648             }
649             elsif (not $style) {
650 2         6 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
651             }
652             }
653             # no control characters anywhere
654             elsif ($value =~ m/[$control_re]/) {
655 55         168 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
656             }
657 9275   100     23438 $style ||= YAML_PLAIN_SCALAR_STYLE;
658              
659 9275 100 100     38131 if ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
    100          
    100          
660 353 100 100     3316 if ($value =~ m/ \n/ or $value =~ m/\n / or $value =~ m/^\n/ or $value =~ m/\n$/) {
    50 100        
      100        
661 16         30 $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       1610 if ($value eq '') {
    100          
669 22         45 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
670             }
671             elsif ($flow) {
672             # no block scalars in flow
673 69 100       244 if ($value =~ tr/\n//) {
674 61         120 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
675             }
676             else {
677 8         21 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
678             }
679             }
680             }
681             elsif ($style == YAML_PLAIN_SCALAR_STYLE) {
682 7922 100 100     96030 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         137 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
686             }
687             elsif ($value eq "\n") {
688 8         21 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
689             }
690             elsif ($value !~ tr/ //c) {
691 10         24 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
692             }
693             elsif ($value !~ tr/ \n//c) {
694 12         33 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
695             }
696             elsif ($value =~ tr/\n//) {
697 134 100       476 $style = $flow ? YAML_DOUBLE_QUOTED_SCALAR_STYLE : YAML_LITERAL_SCALAR_STYLE;
698             }
699             elsif ($forbidden_first{ $first }) {
700 94         234 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
701             }
702             elsif ($flow and $value =~ tr/,[]{}//) {
703 5         12 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
704             }
705             elsif (substr($value, 0, 3) =~ m/^(?:---|\.\.\.)/) {
706 12         38 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
707             }
708             elsif ($value =~ m/: /) {
709 8         23 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
710             }
711             elsif ($value =~ m/ #/) {
712 8         25 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
713             }
714             elsif ($value =~ m/[: \t]\z/) {
715 21         53 $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     1305 if (length ($value) == 1 or substr($value, 1, 1) =~ m/^\s/) {
722 16         39 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
723             }
724             }
725             }
726 9275 100 100     25376 if ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE and not $info->{style}) {
727 157 100 100     547 if ($value =~ tr/'// and $value !~ tr/"//) {
728 20         39 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
729             }
730             }
731 9275         28917 return $style;
732             }
733              
734             sub _emit_scalar {
735 9275     9275   32343 my ($self, %args) = @_;
736 9275         15689 my $props = $args{props};
737 9275         13519 my $value = $args{value};
738 9275         13124 my $style = $args{style};
739 9275         15889 my $stack = $self->event_stack;
740 9275         13753 my $last = $stack->[-1];
741 9275         12986 my $flow = $last->{flow};
742              
743 9275         13410 my $yaml = '';
744 9275         12283 my $pvalue = $props;
745 9275 100 100     29528 if ($props and length $value) {
    100          
746 522         1167 $pvalue .= " $value";
747             }
748             elsif (length $value) {
749 7991         13759 $pvalue .= $value;
750             }
751 9275 100       15339 if ($flow) {
752 1247 100 100     2455 if ($props and not length $value) {
753 50         88 $pvalue .= ' ';
754             }
755             $yaml = $self->_emit_flow_scalar(
756             value => $value,
757             pvalue => $pvalue,
758             style => $args{style},
759 1247         2556 );
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 8028         18861 );
769             }
770 9275         23949 return $yaml;
771             }
772              
773             sub _emit_block_scalar {
774 8028     8028   29453 my ($self, %args) = @_;
775 8028         12571 my $props = $args{props};
776 8028         11992 my $value = $args{value};
777 8028         11972 my $pvalue = $args{pvalue};
778 8028         11326 my $indent = $args{indent};
779 8028         11088 my $style = $args{style};
780 8028         13725 my $stack = $self->event_stack;
781 8028         11660 my $last = $stack->[-1];
782              
783 8028         10388 my $yaml;
784 8028 100 100     27315 if ($last->{type} eq 'MAP' or $last->{type} eq 'SEQ') {
785 4189 100 100     12224 if ($last->{index} == 0 and $last->{newline}) {
786 985         1765 $yaml .= "\n";
787 985         1620 $last->{column} = 0;
788 985         1536 $last->{newline} = 0;
789             }
790             }
791 8028         12417 my $space = ' ';
792 8028   100     21698 my $multiline = ($style == YAML_LITERAL_SCALAR_STYLE or $style == YAML_FOLDED_SCALAR_STYLE);
793 8028 100       16106 if ($last->{type} eq 'MAP') {
794              
795 2712 100       4700 if ($last->{column}) {
796 447 100       925 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
797 447         883 $yaml .= $space;
798             }
799             else {
800 2265         3645 $yaml .= $indent;
801             }
802 2712 100 100     6066 if ($props and not length $value) {
803 100         177 $pvalue .= ' ';
804             }
805 2712         4400 $last->{type} = 'MAPVALUE';
806 2712 100       5117 if ($multiline) {
807             # oops, a complex key
808 17         37 $yaml .= "? ";
809 17         41 $last->{type} = 'COMPLEXVALUE';
810             }
811 2712 100       4858 if (not $multiline) {
812 2695         4953 $pvalue .= ":";
813             }
814             }
815             else {
816 5316 100       11977 if ($last->{type} eq 'MAPVALUE') {
    100          
817 2144         3562 $last->{type} = 'MAP';
818             }
819             elsif ($last->{type} eq 'DOC') {
820             }
821             else {
822 1519 100       2940 if ($last->{column}) {
823 260 100       601 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
824 260         517 $yaml .= $space;
825             }
826             else {
827 1259         2116 $yaml .= $indent;
828             }
829 1519 100       4104 if ($last->{type} eq 'COMPLEXVALUE') {
    50          
830 42         100 $last->{type} = 'MAP';
831 42         71 $yaml .= ":";
832             }
833             elsif ($last->{type} eq 'SEQ') {
834 1477         2133 $yaml .= "-";
835             }
836             else {
837 0         0 die "Should not happen ($last->{type} in scalar_event)";
838              
839             }
840 1519         2445 $last->{column} = 1;
841             }
842              
843 5316 100       11091 if (length $pvalue) {
844 5023 100       9558 if ($last->{column}) {
845 3860         8575 $pvalue = "$space$pvalue";
846             }
847             }
848 5316 100       11168 if (not $multiline) {
849 4849         8215 $pvalue .= "\n";
850             }
851             }
852 8028         13710 $yaml .= $pvalue;
853 8028         23825 return $yaml;
854             }
855              
856             sub _emit_flow_scalar {
857 1247     1247   3455 my ($self, %args) = @_;
858 1247         2109 my $value = $args{value};
859 1247         1795 my $pvalue = $args{pvalue};
860 1247         2019 my $stack = $self->event_stack;
861 1247         1759 my $last = $stack->[-1];
862              
863 1247         1623 my $yaml;
864 1247 100       3340 if ($last->{type} eq 'SEQ') {
    100          
    50          
865 271 100       568 if ($last->{index} == 0) {
866 142 100       259 if ($self->column) {
867 108         186 $yaml .= ' ';
868             }
869 142         240 $yaml .= "[";
870             }
871             else {
872 129         218 $yaml .= ", ";
873             }
874             }
875             elsif ($last->{type} eq 'MAP') {
876 529 100       923 if ($last->{index} == 0) {
877 306 100       536 if ($self->column) {
878 204         327 $yaml .= ' ';
879             }
880 306         568 $yaml .= "{";
881             }
882             else {
883 223         372 $yaml .= ", ";
884             }
885 529         856 $last->{type} = 'MAPVALUE';
886             }
887             elsif ($last->{type} eq 'MAPVALUE') {
888 447 50       847 if ($last->{index} == 0) {
889 0         0 die "Should not happen (index 0 in MAPVALUE)";
890             }
891 447         684 $yaml .= ": ";
892 447         766 $last->{type} = 'MAP';
893             }
894 1247 100       2120 if ($self->column + length $pvalue > $self->width) {
895 51         115 $yaml .= "\n";
896 51         88 $yaml .= $last->{indent};
897 51         104 $yaml .= ' ' x $self->indent;
898             }
899 1247         2254 $yaml .= $pvalue;
900 1247         3432 return $yaml;
901             }
902              
903             sub alias_event {
904 199     199 1 1291 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ alias_event\n";
905 199         451 my ($self, $info) = @_;
906 199         439 my $stack = $self->event_stack;
907 199         384 my $last = $stack->[-1];
908 199         364 my $indent = $last->{indent};
909 199         353 my $flow = $last->{flow};
910              
911 199         439 my $alias = '*' . $info->{value};
912              
913 199         375 my $yaml = '';
914 199 100 100     945 if ($last->{type} eq 'MAP' or $last->{type} eq 'SEQ') {
915 105 100 100     312 if ($last->{index} == 0 and $last->{newline}) {
916 12         20 $yaml .= "\n";
917 12         21 $last->{column} = 0;
918 12         21 $last->{newline} = 0;
919             }
920             }
921 199 100       567 $yaml .= $last->{column} ? ' ' : $indent;
922 199 100       405 if ($flow) {
923 24         45 my $space = '';
924 24 100       93 if ($last->{type} eq 'SEQ') {
    100          
    50          
925 4 100       16 if ($last->{index} == 0) {
926 1 50       5 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       19 if ($last->{index} == 0) {
937 2 50       5 if ($flow == 1) {
938 0         0 $yaml .= ' ';
939             }
940 2         3 $yaml .= "{";
941             }
942             else {
943 4         7 $yaml .= ", ";
944             }
945 6         11 $last->{type} = 'MAPVALUE';
946 6         9 $space = ' ';
947             }
948             elsif ($last->{type} eq 'MAPVALUE') {
949 14 50       41 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         21 $yaml .= ": ";
958             }
959 14         28 $last->{type} = 'MAP';
960             }
961 24         59 $yaml .= "$alias$space";
962             }
963             else {
964 175 100       388 if ($last->{type} eq 'MAP') {
965 25         55 $yaml .= "$alias :";
966 25         77 $last->{type} = 'MAPVALUE';
967             }
968             else {
969              
970 150 100       434 if ($last->{type} eq 'MAPVALUE') {
    50          
971 77         165 $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       298 if ($last->{type} eq 'COMPLEXVALUE') {
    50          
    50          
978 3         7 $last->{type} = 'MAP';
979 3         6 $yaml .= ": ";
980             }
981             elsif ($last->{type} eq 'COMPLEX') {
982 0         0 $yaml .= ": ";
983             }
984             elsif ($last->{type} eq 'SEQ') {
985 70         118 $yaml .= "- ";
986             }
987             else {
988 0         0 die "Unexpected";
989             }
990             }
991 150         297 $yaml .= "$alias\n";
992             }
993             }
994              
995 199         654 $self->_write("$yaml");
996 199         462 $last->{index}++;
997 199         556 $last->{column} = $self->column;
998 199         493 $self->{open_ended} = 0;
999             }
1000              
1001             sub document_start_event {
1002 3225     3225 1 15082 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ document_start_event\n";
1003 3225         5896 my ($self, $info) = @_;
1004 3225         4709 my $newline = 0;
1005 3225         5356 my $implicit = $info->{implicit};
1006 3225 100       6728 if ($info->{version_directive}) {
1007 18 100       38 if ($self->{open_ended}) {
1008 10         22 $self->_write("...\n");
1009             }
1010 18         71 $self->_write("%YAML $info->{version_directive}->{major}.$info->{version_directive}->{minor}\n");
1011 18         66 $self->{open_ended} = 0;
1012 18         31 $implicit = 0; # we need ---
1013             }
1014 3225 100       6719 unless ($implicit) {
1015 1175         1716 $newline = 1;
1016 1175         2658 $self->_write("---");
1017             }
1018             $self->set_event_stack([
1019             {
1020 3225         8470 type => 'DOC', index => 0, indent => '', info => $info,
1021             newline => $newline, column => $self->column,
1022             }
1023             ]);
1024             }
1025              
1026             sub document_end_event {
1027 3224     3224 1 15123 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ document_end_event\n";
1028 3224         5926 my ($self, $info) = @_;
1029 3224         8686 $self->set_event_stack([]);
1030 3224 100 100     13542 if ($self->{open_ended} or not $info->{implicit}) {
1031 241         814 $self->_write("...\n");
1032 241         766 $self->{open_ended} = 0;
1033             }
1034             else {
1035 2983         8856 $self->{open_ended} = 1;
1036             }
1037             }
1038              
1039       3018 1   sub stream_start_event {
1040             }
1041              
1042       3017 1   sub stream_end_event {
1043             }
1044              
1045             sub _emit_tag {
1046 644     644   1594 my ($self, $type, $tag) = @_;
1047 644         1383 my $map = $self->tagmap;
1048 644         2740 for my $key (sort keys %$map) {
1049 644 100       4384 if ($tag =~ m/^\Q$key\E(.*)/) {
1050 482         1512 $tag = $map->{ $key } . $1;
1051 482         1422 return $tag;
1052             }
1053             }
1054 162 100       843 if ($tag =~ m/^(!.*)/) {
1055 107         338 $tag = "$1";
1056             }
1057             else {
1058 55         275 $tag = "!<$tag>";
1059             }
1060 162         500 return $tag;
1061             }
1062              
1063             sub finish {
1064 1582     1582 1 3027 my ($self) = @_;
1065 1582         2791 $self->writer->finish;
1066             }
1067              
1068             sub _write {
1069 14687     14687   26201 my ($self, $yaml) = @_;
1070 14687 100       30346 return unless length $yaml;
1071 12789         36741 my @lines = split m/\n/, $yaml, -1;
1072 12789         22220 my $newlines = @lines - 1;
1073 12789         20151 $self->{line} += $newlines;
1074 12789 100       26909 if (length $lines[-1]) {
1075 6696 100       11562 if ($newlines) {
1076 867         1733 $self->{column} = length $lines[-1];
1077             }
1078             else {
1079 5829         9635 $self->{column} += length $lines[-1];
1080             }
1081             }
1082             else {
1083 6093         9824 $self->{column} = 0;
1084             }
1085 12789         23992 $self->writer->write($yaml);
1086             }
1087              
1088             1;
1089              
1090             __END__