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   2646 use strict;
  38         79  
  38         1142  
2 38     38   199 use warnings;
  38         83  
  38         2194  
3             package YAML::PP::Emitter;
4              
5             our $VERSION = '0.036_002'; # TRIAL VERSION
6 38     38   9433 use Data::Dumper;
  38         103320  
  38         2600  
7              
8 38         2812 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   295 /;
  38         96  
14              
15 38 50   38   261 use constant DEBUG => $ENV{YAML_PP_EMIT_DEBUG} ? 1 : 0;
  38         90  
  38         2535  
16 38     38   277 use constant DEFAULT_WIDTH => 80;
  38         97  
  38         257594  
17              
18             sub new {
19 2181     2181 1 11216 my ($class, %args) = @_;
20             my $self = bless {
21             indent => $args{indent} || 2,
22             writer => $args{writer},
23 2181   100     13997 width => $args{width} || DEFAULT_WIDTH,
      50        
24             }, $class;
25 2181         6477 $self->init;
26 2181         5262 return $self;
27             }
28              
29             sub clone {
30 9     9 0 16 my ($self) = @_;
31 9         21 my $clone = {
32             indent => $self->indent,
33             };
34 9         34 return bless $clone, ref $self;
35             }
36              
37 43672     43672 0 69568 sub event_stack { return $_[0]->{event_stack} }
38 6449     6449 0 19316 sub set_event_stack { $_[0]->{event_stack} = $_[1] }
39 4468     4468 1 12450 sub indent { return $_[0]->{indent} }
40 1247     1247 0 2625 sub width { return $_[0]->{width} }
41 0     0 0 0 sub line { return $_[0]->{line} }
42 20848     20848 0 55822 sub column { return $_[0]->{column} }
43 1     1 1 1294 sub set_indent { $_[0]->{indent} = $_[1] }
44 27786     27786 1 71835 sub writer { $_[0]->{writer} }
45 5098     5098 1 14885 sub set_writer { $_[0]->{writer} = $_[1] }
46 644     644 0 1229 sub tagmap { return $_[0]->{tagmap} }
47 5199     5199 0 9484 sub set_tagmap { $_[0]->{tagmap} = $_[1] }
48              
49             sub init {
50 5199     5199 1 90008 my ($self) = @_;
51 5199 100       9440 unless ($self->writer) {
52 2180         5495 $self->set_writer(YAML::PP::Writer->new);
53             }
54             $self->set_tagmap({
55 5199         15760 'tag:yaml.org,2002:' => '!!',
56             });
57 5199         8379 $self->{open_ended} = 0;
58 5199         8088 $self->{line} = 0;
59 5199         7700 $self->{column} = 0;
60 5199         8507 $self->writer->init;
61             }
62              
63             sub mapping_start_event {
64 1881     1881 1 17591 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ mapping_start_event\n";
65 1881         3605 my ($self, $info) = @_;
66 1881         3647 my $stack = $self->event_stack;
67 1881         3275 my $last = $stack->[-1];
68 1881         3220 my $indent = $last->{indent};
69 1881         2647 my $new_indent = $indent;
70 1881         2666 my $yaml = '';
71              
72 1881         2765 my $props = '';
73 1881         2925 my $anchor = $info->{anchor};
74 1881         3209 my $tag = $info->{tag};
75 1881 100       4415 if (defined $anchor) {
76 98         241 $anchor = "&$anchor";
77             }
78 1881 100       3559 if (defined $tag) {
79 109         337 $tag = $self->_emit_tag('map', $tag);
80             }
81 1881         6609 $props = join ' ', grep defined, ($anchor, $tag);
82              
83 1881   100     6094 my $flow = $last->{flow} || 0;
84 1881 100 100     6506 $flow++ if ($info->{style} || 0) eq YAML_FLOW_MAPPING_STYLE;
85              
86 1881         2781 my $newline = 0;
87 1881 100       3684 if ($flow > 1) {
88 135 100       417 if ($last->{type} eq 'SEQ') {
    100          
    50          
89 92 100       238 if ($last->{newline}) {
90 17         31 $yaml .= ' ';
91             }
92 92 100       193 if ($last->{index} == 0) {
93 27         55 $yaml .= "[";
94             }
95             else {
96 65         129 $yaml .= ",";
97             }
98             }
99             elsif ($last->{type} eq 'MAP') {
100 2 50       11 if ($last->{newline}) {
101 0         0 $yaml .= ' ';
102             }
103 2 50       8 if ($last->{index} == 0) {
104 2         6 $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         75 $yaml .= ": ";
115             }
116 135 100       273 if ($props) {
117 18         38 $yaml .= " $props ";
118             }
119 135         343 $new_indent .= ' ' x $self->indent;
120             }
121             else {
122 1746 100       3728 if ($last->{type} eq 'DOC') {
123 955         1886 $newline = $last->{newline};
124             }
125             else {
126 791 100       1882 if ($last->{newline}) {
127 104         296 $yaml .= "\n";
128 104         297 $last->{column} = 0;
129             }
130 791 100       1876 if ($last->{type} eq 'MAPVALUE') {
131 258         684 $new_indent .= ' ' x $self->indent;
132 258         473 $newline = 1;
133             }
134             else {
135 533         879 $new_indent = $indent;
136 533 100 100     1600 if (not $props and $self->indent == 1) {
137 91         149 $new_indent .= ' ' x 2;
138             }
139             else {
140 442         945 $new_indent .= ' ' x $self->indent;
141             }
142              
143 533 100       1380 if ($last->{column}) {
144 14 100       46 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
145 14         38 $yaml .= $space;
146             }
147             else {
148 519         853 $yaml .= $indent;
149             }
150 533 100       1311 if ($last->{type} eq 'SEQ') {
    100          
    50          
151 505         894 $yaml .= '-';
152             }
153             elsif ($last->{type} eq 'MAP') {
154 19         43 $yaml .= "?";
155 19         51 $last->{type} = 'COMPLEX';
156             }
157             elsif ($last->{type} eq 'COMPLEXVALUE') {
158 9         37 $yaml .= ":";
159             }
160             else {
161 0         0 die "Should not happen ($last->{type} in mapping_start)";
162             }
163 533         906 $last->{column} = 1;
164             }
165 791         1294 $last->{newline} = 0;
166             }
167 1746 100       3623 if ($props) {
168 158 100       429 $yaml .= $last->{column} ? ' ' : $indent;
169 158         277 $yaml .= $props;
170 158         251 $newline = 1;
171             }
172             }
173 1881         4761 $self->_write($yaml);
174 1881         6089 my $new_info = {
175             index => 0, indent => $new_indent, info => $info,
176             newline => $newline,
177             column => $self->column,
178             flow => $flow,
179             };
180 1881         4171 $new_info->{type} = 'MAP';
181 1881         2643 push @{ $stack }, $new_info;
  1881         3711  
182 1881         2882 $last->{index}++;
183 1881         4886 $self->{open_ended} = 0;
184             }
185              
186             sub mapping_end_event {
187 1880     1880 1 12569 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ mapping_end_event\n";
188 1880         3438 my ($self, $info) = @_;
189 1880         3273 my $stack = $self->event_stack;
190              
191 1880         2654 my $last = pop @{ $stack };
  1880         3250  
192 1880 100       5391 if ($last->{index} == 0) {
    100          
193 25         58 my $indent = $last->{indent};
194 25         60 my $zero_indent = $last->{zero_indent};
195 25 50       79 if ($last->{zero_indent}) {
196 0         0 $indent .= ' ' x $self->indent;
197             }
198 25 100       58 if ($self->column) {
199 20         52 $self->_write(" {}\n");
200             }
201             else {
202 5         23 $self->_write("$indent\{}\n");
203             }
204             }
205             elsif ($last->{flow}) {
206 317         471 my $yaml = "}";
207 317 100       653 if ($last->{flow} == 1) {
208 184         297 $yaml .= "\n";
209             }
210 317         815 $self->_write("$yaml");
211             }
212 1880         4978 $last = $stack->[-1];
213 1880         3557 $last->{column} = $self->column;
214 1880 100       8619 if ($last->{type} eq 'SEQ') {
    100          
    100          
    100          
    100          
215             }
216             elsif ($last->{type} eq 'MAP') {
217 2         8 $last->{type} = 'MAPVALUE';
218             }
219             elsif ($last->{type} eq 'MAPVALUE') {
220 299         776 $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         31 $last->{type} = 'MAP';
227             }
228             }
229              
230             sub sequence_start_event {
231 1306     1306 1 11690 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ sequence_start_event\n";
232 1306         2480 my ($self, $info) = @_;
233 1306         2604 my $stack = $self->event_stack;
234 1306         2315 my $last = $stack->[-1];
235 1306         2354 my $indent = $last->{indent};
236 1306         1974 my $new_indent = $indent;
237 1306         1977 my $yaml = '';
238              
239 1306         2357 my $props = '';
240 1306         2122 my $anchor = $info->{anchor};
241 1306         2078 my $tag = $info->{tag};
242 1306 100       3032 if (defined $anchor) {
243 43         145 $anchor = "&$anchor";
244             }
245 1306 100       2766 if (defined $tag) {
246 46         133 $tag = $self->_emit_tag('seq', $tag);
247             }
248 1306         4482 $props = join ' ', grep defined, ($anchor, $tag);
249              
250 1306   100     4316 my $flow = $last->{flow} || 0;
251 1306 100 100     5898 $flow++ if $flow or ($info->{style} || 0) eq YAML_FLOW_SEQUENCE_STYLE;
      100        
252 1306         2019 my $newline = 0;
253 1306         1924 my $zero_indent = 0;
254 1306 100       2684 if ($flow > 1) {
255 108 100       413 if ($last->{type} eq 'SEQ') {
    100          
    50          
256 49 50       130 if ($last->{newline}) {
257 0         0 $yaml .= ' ';
258             }
259 49 100       104 if ($last->{index} == 0) {
260 14         40 $yaml .= "[";
261             }
262             else {
263 35         63 $yaml .= ",";
264             }
265             }
266             elsif ($last->{type} eq 'MAP') {
267 12 100       34 if ($last->{newline}) {
268 1         3 $yaml .= ' ';
269             }
270 12 100       37 if ($last->{index} == 0) {
271 7         13 $yaml .= "{";
272             }
273             else {
274 5         11 $yaml .= ",";
275             }
276             }
277             elsif ($last->{type} eq 'MAPVALUE') {
278 47 50       128 if ($last->{index} == 0) {
279 0         0 die "Should not happen (index 0 in MAPVALUE)";
280             }
281 47         87 $yaml .= ": ";
282             }
283 108 100       242 if ($props) {
284 8         21 $yaml .= " $props ";
285             }
286 108         230 $new_indent .= ' ' x $self->indent;
287             }
288             else {
289 1198 100       2708 if ($last->{type} eq 'DOC') {
290 617         1285 $newline = $last->{newline};
291             }
292             else {
293 581 100       1506 if ($last->{newline}) {
294 50         112 $yaml .= "\n";
295 50         116 $last->{column} = 0;
296             }
297 581 100       1400 if ($last->{type} eq 'MAPVALUE') {
298 240         401 $zero_indent = 1;
299 240         388 $newline = 1;
300             }
301             else {
302 341 100 100     1291 if (not $props and $self->indent == 1) {
303 68         134 $new_indent .= ' ' x 2;
304             }
305             else {
306 273         544 $new_indent .= ' ' x $self->indent;
307             }
308 341 100       788 if ($last->{column}) {
309 21 100       78 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
310 21         45 $yaml .= $space;
311             }
312             else {
313 320         516 $yaml .= $indent;
314             }
315 341 100       1006 if ($last->{type} eq 'SEQ') {
    100          
    50          
316 265         449 $yaml .= "-";
317             }
318             elsif ($last->{type} eq 'MAP') {
319 47         113 $last->{type} = 'COMPLEX';
320 47         71 $zero_indent = 1;
321 47         81 $yaml .= "?";
322             }
323             elsif ($last->{type} eq 'COMPLEXVALUE') {
324 29         61 $yaml .= ":";
325 29         50 $zero_indent = 1;
326             }
327             else {
328 0         0 die "Should not happen ($last->{type} in sequence_start)";
329             }
330 341         666 $last->{column} = 1;
331             }
332 581         911 $last->{newline} = 0;
333             }
334 1198 100       2452 if ($props) {
335 73 100       251 $yaml .= $last->{column} ? ' ' : $indent;
336 73         130 $yaml .= $props;
337 73         207 $newline = 1;
338             }
339             }
340 1306         3486 $self->_write($yaml);
341 1306         2261 $last->{index}++;
342 1306         3244 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         3925 $new_info->{type} = 'SEQ';
352 1306         2063 push @{ $stack }, $new_info;
  1306         2510  
353 1306         3569 $self->{open_ended} = 0;
354             }
355              
356             sub sequence_end_event {
357 1306     1306 1 8933 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ sequence_end_event\n";
358 1306         2616 my ($self, $info) = @_;
359 1306         2466 my $stack = $self->event_stack;
360              
361 1306         1953 my $last = pop @{ $stack };
  1306         2313  
362 1306 100       4282 if ($last->{index} == 0) {
    100          
363 56         172 my $indent = $last->{indent};
364 56         122 my $zero_indent = $last->{zero_indent};
365 56 100       139 if ($last->{zero_indent}) {
366 6         28 $indent .= ' ' x $self->indent;
367             }
368 56 100       120 my $yaml .= $self->column ? ' ' : $indent;
369 56         105 $yaml .= "[]";
370 56 100       152 if ($last->{flow} < 2) {
371 48         78 $yaml .= "\n";
372             }
373 56         118 $self->_write($yaml);
374             }
375             elsif ($last->{flow}) {
376 184         298 my $yaml = "]";
377 184 100       386 if ($last->{flow} == 1) {
378 84         134 $yaml .= "\n";
379             }
380 184         336 $self->_write($yaml);
381             }
382 1306         3794 $last = $stack->[-1];
383 1306         2528 $last->{column} = $self->column;
384 1306 100       6806 if ($last->{type} eq 'SEQ') {
    100          
    100          
    100          
    100          
385             }
386             elsif ($last->{type} eq 'MAP') {
387 12         40 $last->{type} = 'MAPVALUE';
388             }
389             elsif ($last->{type} eq 'MAPVALUE') {
390 287         747 $last->{type} = 'MAP';
391             }
392             elsif ($last->{type} eq 'COMPLEX') {
393 47         193 $last->{type} = 'COMPLEXVALUE';
394             }
395             elsif ($last->{type} eq 'COMPLEXVALUE') {
396 29         113 $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 55368 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ scalar_event\n";
490 9275         15463 my ($self, $info) = @_;
491 9275         16612 my $stack = $self->event_stack;
492 9275         14475 my $last = $stack->[-1];
493 9275         14048 my $indent = $last->{indent};
494 9275         14805 my $value = $info->{value};
495 9275         13288 my $flow = $last->{flow};
496              
497 9275         12986 my $props = '';
498 9275         13482 my $anchor = $info->{anchor};
499 9275         12570 my $tag = $info->{tag};
500 9275 100       17891 if (defined $anchor) {
501 459         2018 $anchor = "&$anchor";
502             }
503 9275 100       16585 if (defined $tag) {
504 489         1235 $tag = $self->_emit_tag('scalar', $tag);
505             }
506 9275         26987 $props = join ' ', grep defined, ($anchor, $tag);
507              
508 9275         12331 DEBUG and local $Data::Dumper::Useqq = 1;
509 9275 50       16985 $value = '' unless defined $value;
510              
511 9275         19999 my $style = $self->_find_best_scalar_style(
512             info => $info,
513             value => $value,
514             );
515              
516 9275         14612 my $open_ended = 0;
517              
518 9275 100       18797 if ($style == YAML_PLAIN_SCALAR_STYLE) {
    100          
    100          
    100          
519 7542         14653 $value =~ s/\n/\n\n/g;
520             }
521             elsif ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
522 499         1324 my $new_indent = $last->{indent} . (' ' x $self->indent);
523 499         1188 $value =~ s/(\n+)/"\n" x (1 + (length $1))/eg;
  10         67  
524 499         1545 my @lines = split m/\n/, $value, -1;
525 499 100       1341 if (@lines > 1) {
526 10         67 for my $line (@lines[1 .. $#lines]) {
527 20 100       80 $line = $new_indent . $line
528             if length $line;
529             }
530             }
531 499         1253 $value = join "\n", @lines;
532 499         999 $value =~ s/'/''/g;
533 499         1393 $value = "'" . $value . "'";
534             }
535             elsif ($style == YAML_LITERAL_SCALAR_STYLE) {
536 364         595 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$value], ['value']);
537 364         753 my $indicators = '';
538 364 100       1623 if ($value =~ m/\A\n* +/) {
539 36         99 $indicators .= $self->indent;
540             }
541 364         1077 my $indent = $indent . ' ' x $self->indent;
542 364 100       2557 if ($value !~ m/\n\z/) {
    100          
543 87         191 $indicators .= '-';
544 87         201 $value .= "\n";
545             }
546             elsif ($value =~ m/(\n|\A)\n\z/) {
547 36         79 $indicators .= '+';
548 36         85 $open_ended = 1;
549             }
550 364         2150 $value =~ s/^(?=.)/$indent/gm;
551 364         1203 $value = "|$indicators\n$value";
552             }
553             elsif ($style == YAML_FOLDED_SCALAR_STYLE) {
554 120         199 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$value], ['value']);
555 120         602 my @lines = split /\n/, $value, -1;
556 120         192 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\@lines], ['lines']);
557 120         235 my $trailing = -1;
558 120         334 while (@lines) {
559 218 100       532 last if $lines[-1] ne '';
560 99         176 pop @lines;
561 99         204 $trailing++;
562             }
563 120         203 my %start_with_space;
564 120         384 for my $i (0 .. $#lines) {
565 211 100       770 if ($lines[ $i ] =~ m/^[ \t]+/) {
566 31         129 $start_with_space{ $i } = 1;
567             }
568             }
569 120         312 my $indicators = '';
570 120 100       522 if ($value =~ m/\A\n* +/) {
571 19         52 $indicators .= $self->indent;
572             }
573 120         383 my $indent = $indent . ' ' x $self->indent;
574 120 100       506 if ($trailing > 0) {
    100          
575 3         5 $indicators .= '+';
576 3         6 $open_ended = 1;
577             }
578             elsif ($trailing < 0) {
579 24         53 $indicators .= '-';
580             }
581 120         334 $value = ">$indicators\n";
582 120         200 my $got_content = 0;
583 120         333 for my $i (0 .. $#lines) {
584 211         420 my $line = $lines[ $i ];
585 211   100     734 my $sp = $start_with_space{ $i } || 0;
586 211 100 100     639 my $spnext = $i == $#lines ? 1 : $start_with_space{ $i+1 } || 0;
587 211 100 100     635 my $spprev = $i == 0 ? 1 : $start_with_space{ $i-1 } || 0;
588 211 100       514 my $empty = length $line ? 0 : 1;
589 211 100       593 my $emptynext = $i == $#lines ? '' : length $lines[$i+1] ? 0 : 1;
    100          
590 211         339 my $nl = 0;
591 211 100       398 if ($empty) {
592 47 100 100     209 if ($spnext and $spprev) {
    100          
    100          
593 8         16 $nl = 1;
594             }
595             elsif (not $spnext) {
596 37         61 $nl = 1;
597             }
598             elsif (not $got_content) {
599 1         3 $nl = 1;
600             }
601             }
602             else {
603 164         247 $got_content = 1;
604 164         438 $value .= "$indent$line\n";
605 164 100 100     626 if (not $sp and not $spnext) {
606 32         63 $nl = 1;
607             }
608             }
609 211 100       532 if ($nl) {
610 78         180 $value .= "\n";
611             }
612             }
613 120 100       460 $value .= "\n" x ($trailing) if $trailing > 0;
614             }
615             else {
616 750 50       4461 $value =~ s/([$escape_re"\\])/$to_escape{ $1 } || sprintf '\\u%04x', ord($1)/eg;
  722         3773  
617 750         2457 $value = '"' . $value . '"';
618             }
619              
620 9275         11551 DEBUG and warn __PACKAGE__.':'.__LINE__.": (@$stack)\n";
621 9275         21625 my $yaml = $self->_emit_scalar(
622             indent => $indent,
623             props => $props,
624             value => $value,
625             style => $style,
626             );
627              
628 9275         15536 $last->{index}++;
629 9275         13473 $last->{newline} = 0;
630 9275         22029 $self->_write($yaml);
631 9275         20089 $last->{column} = $self->column;
632 9275         32146 $self->{open_ended} = $open_ended;
633             }
634              
635             sub _find_best_scalar_style {
636 9275     9275   26021 my ($self, %args) = @_;
637 9275         15625 my $info = $args{info};
638 9275         14425 my $style = $info->{style};
639 9275         14389 my $value = $args{value};
640 9275         15115 my $stack = $self->event_stack;
641 9275         13587 my $last = $stack->[-1];
642 9275         13302 my $flow = $last->{flow};
643              
644 9275         21638 my $first = substr($value, 0, 1);
645 9275 100       49370 if ($value eq '') {
    100          
646 886 100 100     3890 if ($flow and $last->{type} ne 'MAPVALUE' and $last->{type} ne 'MAP') {
    100 100        
647 24         52 $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         132 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
656             }
657 9275   100     23472 $style ||= YAML_PLAIN_SCALAR_STYLE;
658              
659 9275 100 100     39649 if ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
    100          
    100          
660 353 100 100     3260 if ($value =~ m/ \n/ or $value =~ m/\n / or $value =~ m/^\n/ or $value =~ m/\n$/) {
    50 100        
      100        
661 16         33 $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       1680 if ($value eq '') {
    100          
669 22         44 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
670             }
671             elsif ($flow) {
672             # no block scalars in flow
673 69 100       179 if ($value =~ tr/\n//) {
674 61         123 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
675             }
676             else {
677 8         17 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
678             }
679             }
680             }
681             elsif ($style == YAML_PLAIN_SCALAR_STYLE) {
682 7922 100 100     96337 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         136 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
686             }
687             elsif ($value eq "\n") {
688 8         22 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
689             }
690             elsif ($value !~ tr/ //c) {
691 10         25 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
692             }
693             elsif ($value !~ tr/ \n//c) {
694 12         35 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
695             }
696             elsif ($value =~ tr/\n//) {
697 134 100       421 $style = $flow ? YAML_DOUBLE_QUOTED_SCALAR_STYLE : YAML_LITERAL_SCALAR_STYLE;
698             }
699             elsif ($forbidden_first{ $first }) {
700 94         244 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
701             }
702             elsif ($flow and $value =~ tr/,[]{}//) {
703 5         13 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
704             }
705             elsif (substr($value, 0, 3) =~ m/^(?:---|\.\.\.)/) {
706 12         40 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
707             }
708             elsif ($value =~ m/: /) {
709 8         21 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
710             }
711             elsif ($value =~ m/ #/) {
712 8         23 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
713             }
714             elsif ($value =~ m/[: \t]\z/) {
715 21         65 $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     1363 if (length ($value) == 1 or substr($value, 1, 1) =~ m/^\s/) {
722 16         35 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
723             }
724             }
725             }
726 9275 100 100     26269 if ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE and not $info->{style}) {
727 157 100 100     522 if ($value =~ tr/'// and $value !~ tr/"//) {
728 20         37 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
729             }
730             }
731 9275         30906 return $style;
732             }
733              
734             sub _emit_scalar {
735 9275     9275   33415 my ($self, %args) = @_;
736 9275         16318 my $props = $args{props};
737 9275         14078 my $value = $args{value};
738 9275         13252 my $style = $args{style};
739 9275         15853 my $stack = $self->event_stack;
740 9275         14175 my $last = $stack->[-1];
741 9275         14007 my $flow = $last->{flow};
742              
743 9275         13540 my $yaml = '';
744 9275         14059 my $pvalue = $props;
745 9275 100 100     29052 if ($props and length $value) {
    100          
746 522         1189 $pvalue .= " $value";
747             }
748             elsif (length $value) {
749 7991         13803 $pvalue .= $value;
750             }
751 9275 100       15219 if ($flow) {
752 1247 100 100     2553 if ($props and not length $value) {
753 50         108 $pvalue .= ' ';
754             }
755             $yaml = $self->_emit_flow_scalar(
756             value => $value,
757             pvalue => $pvalue,
758             style => $args{style},
759 1247         2798 );
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         18847 );
769             }
770 9275         24001 return $yaml;
771             }
772              
773             sub _emit_block_scalar {
774 8028     8028   29066 my ($self, %args) = @_;
775 8028         12869 my $props = $args{props};
776 8028         11667 my $value = $args{value};
777 8028         11975 my $pvalue = $args{pvalue};
778 8028         11130 my $indent = $args{indent};
779 8028         11149 my $style = $args{style};
780 8028         13718 my $stack = $self->event_stack;
781 8028         11963 my $last = $stack->[-1];
782              
783 8028         10290 my $yaml;
784 8028 100 100     26671 if ($last->{type} eq 'MAP' or $last->{type} eq 'SEQ') {
785 4189 100 100     12768 if ($last->{index} == 0 and $last->{newline}) {
786 985         2042 $yaml .= "\n";
787 985         1612 $last->{column} = 0;
788 985         1571 $last->{newline} = 0;
789             }
790             }
791 8028         11988 my $space = ' ';
792 8028   100     21806 my $multiline = ($style == YAML_LITERAL_SCALAR_STYLE or $style == YAML_FOLDED_SCALAR_STYLE);
793 8028 100       15714 if ($last->{type} eq 'MAP') {
794              
795 2712 100       4772 if ($last->{column}) {
796 447 100       903 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
797 447         873 $yaml .= $space;
798             }
799             else {
800 2265         3686 $yaml .= $indent;
801             }
802 2712 100 100     6455 if ($props and not length $value) {
803 100         195 $pvalue .= ' ';
804             }
805 2712         4432 $last->{type} = 'MAPVALUE';
806 2712 100       5024 if ($multiline) {
807             # oops, a complex key
808 17         71 $yaml .= "? ";
809 17         39 $last->{type} = 'COMPLEXVALUE';
810             }
811 2712 100       5023 if (not $multiline) {
812 2695         4753 $pvalue .= ":";
813             }
814             }
815             else {
816 5316 100       11778 if ($last->{type} eq 'MAPVALUE') {
    100          
817 2144         3642 $last->{type} = 'MAP';
818             }
819             elsif ($last->{type} eq 'DOC') {
820             }
821             else {
822 1519 100       3027 if ($last->{column}) {
823 260 100       720 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
824 260         594 $yaml .= $space;
825             }
826             else {
827 1259         2122 $yaml .= $indent;
828             }
829 1519 100       3834 if ($last->{type} eq 'COMPLEXVALUE') {
    50          
830 42         81 $last->{type} = 'MAP';
831 42         78 $yaml .= ":";
832             }
833             elsif ($last->{type} eq 'SEQ') {
834 1477         2131 $yaml .= "-";
835             }
836             else {
837 0         0 die "Should not happen ($last->{type} in scalar_event)";
838              
839             }
840 1519         2322 $last->{column} = 1;
841             }
842              
843 5316 100       11980 if (length $pvalue) {
844 5023 100       9825 if ($last->{column}) {
845 3860         8361 $pvalue = "$space$pvalue";
846             }
847             }
848 5316 100       10781 if (not $multiline) {
849 4849         8815 $pvalue .= "\n";
850             }
851             }
852 8028         13413 $yaml .= $pvalue;
853 8028         24071 return $yaml;
854             }
855              
856             sub _emit_flow_scalar {
857 1247     1247   3721 my ($self, %args) = @_;
858 1247         2006 my $value = $args{value};
859 1247         1787 my $pvalue = $args{pvalue};
860 1247         2210 my $stack = $self->event_stack;
861 1247         1782 my $last = $stack->[-1];
862              
863 1247         1722 my $yaml;
864 1247 100       3271 if ($last->{type} eq 'SEQ') {
    100          
    50          
865 271 100       548 if ($last->{index} == 0) {
866 142 100       299 if ($self->column) {
867 108         235 $yaml .= ' ';
868             }
869 142         283 $yaml .= "[";
870             }
871             else {
872 129         230 $yaml .= ", ";
873             }
874             }
875             elsif ($last->{type} eq 'MAP') {
876 529 100       965 if ($last->{index} == 0) {
877 306 100       589 if ($self->column) {
878 204         349 $yaml .= ' ';
879             }
880 306         517 $yaml .= "{";
881             }
882             else {
883 223         363 $yaml .= ", ";
884             }
885 529         888 $last->{type} = 'MAPVALUE';
886             }
887             elsif ($last->{type} eq 'MAPVALUE') {
888 447 50       882 if ($last->{index} == 0) {
889 0         0 die "Should not happen (index 0 in MAPVALUE)";
890             }
891 447         782 $yaml .= ": ";
892 447         706 $last->{type} = 'MAP';
893             }
894 1247 100       2032 if ($self->column + length $pvalue > $self->width) {
895 51         96 $yaml .= "\n";
896 51         81 $yaml .= $last->{indent};
897 51         122 $yaml .= ' ' x $self->indent;
898             }
899 1247         2076 $yaml .= $pvalue;
900 1247         3334 return $yaml;
901             }
902              
903             sub alias_event {
904 199     199 1 1407 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ alias_event\n";
905 199         509 my ($self, $info) = @_;
906 199         425 my $stack = $self->event_stack;
907 199         368 my $last = $stack->[-1];
908 199         375 my $indent = $last->{indent};
909 199         347 my $flow = $last->{flow};
910              
911 199         461 my $alias = '*' . $info->{value};
912              
913 199         320 my $yaml = '';
914 199 100 100     1018 if ($last->{type} eq 'MAP' or $last->{type} eq 'SEQ') {
915 105 100 100     324 if ($last->{index} == 0 and $last->{newline}) {
916 12         23 $yaml .= "\n";
917 12         22 $last->{column} = 0;
918 12         36 $last->{newline} = 0;
919             }
920             }
921 199 100       551 $yaml .= $last->{column} ? ' ' : $indent;
922 199 100       400 if ($flow) {
923 24         55 my $space = '';
924 24 100       90 if ($last->{type} eq 'SEQ') {
    100          
    50          
925 4 100       15 if ($last->{index} == 0) {
926 1 50       4 if ($flow == 1) {
927 0         0 $yaml .= ' ';
928             }
929 1         2 $yaml .= "[";
930             }
931             else {
932 3         7 $yaml .= ", ";
933             }
934             }
935             elsif ($last->{type} eq 'MAP') {
936 6 100       18 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         8 $yaml .= ", ";
944             }
945 6         13 $last->{type} = 'MAPVALUE';
946 6         11 $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         20 $yaml .= ": ";
958             }
959 14         25 $last->{type} = 'MAP';
960             }
961 24         55 $yaml .= "$alias$space";
962             }
963             else {
964 175 100       396 if ($last->{type} eq 'MAP') {
965 25         88 $yaml .= "$alias :";
966 25         57 $last->{type} = 'MAPVALUE';
967             }
968             else {
969              
970 150 100       401 if ($last->{type} eq 'MAPVALUE') {
    50          
971 77         152 $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       273 if ($last->{type} eq 'COMPLEXVALUE') {
    50          
    50          
978 3         12 $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         115 $yaml .= "- ";
986             }
987             else {
988 0         0 die "Unexpected";
989             }
990             }
991 150         316 $yaml .= "$alias\n";
992             }
993             }
994              
995 199         668 $self->_write("$yaml");
996 199         495 $last->{index}++;
997 199         489 $last->{column} = $self->column;
998 199         524 $self->{open_ended} = 0;
999             }
1000              
1001             sub document_start_event {
1002 3225     3225 1 14740 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ document_start_event\n";
1003 3225         5743 my ($self, $info) = @_;
1004 3225         4631 my $newline = 0;
1005 3225         5511 my $implicit = $info->{implicit};
1006 3225 100       6992 if ($info->{version_directive}) {
1007 18 100       40 if ($self->{open_ended}) {
1008 10         21 $self->_write("...\n");
1009             }
1010 18         68 $self->_write("%YAML $info->{version_directive}->{major}.$info->{version_directive}->{minor}\n");
1011 18         29 $self->{open_ended} = 0;
1012 18         28 $implicit = 0; # we need ---
1013             }
1014 3225 100       6626 unless ($implicit) {
1015 1175         1904 $newline = 1;
1016 1175         2773 $self->_write("---");
1017             }
1018             $self->set_event_stack([
1019             {
1020 3225         8541 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 15314 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ document_end_event\n";
1028 3224         5708 my ($self, $info) = @_;
1029 3224         8563 $self->set_event_stack([]);
1030 3224 100 100     13346 if ($self->{open_ended} or not $info->{implicit}) {
1031 241         699 $self->_write("...\n");
1032 241         782 $self->{open_ended} = 0;
1033             }
1034             else {
1035 2983         9147 $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   1622 my ($self, $type, $tag) = @_;
1047 644         1408 my $map = $self->tagmap;
1048 644         2660 for my $key (sort keys %$map) {
1049 644 100       4613 if ($tag =~ m/^\Q$key\E(.*)/) {
1050 482         1961 $tag = $map->{ $key } . $1;
1051 482         1457 return $tag;
1052             }
1053             }
1054 162 100       962 if ($tag =~ m/^(!.*)/) {
1055 107         360 $tag = "$1";
1056             }
1057             else {
1058 55         221 $tag = "!<$tag>";
1059             }
1060 162         451 return $tag;
1061             }
1062              
1063             sub finish {
1064 1582     1582 1 3064 my ($self) = @_;
1065 1582         2680 $self->writer->finish;
1066             }
1067              
1068             sub _write {
1069 14687     14687   26671 my ($self, $yaml) = @_;
1070 14687 100       30824 return unless length $yaml;
1071 12789         36794 my @lines = split m/\n/, $yaml, -1;
1072 12789         21817 my $newlines = @lines - 1;
1073 12789         20170 $self->{line} += $newlines;
1074 12789 100       26379 if (length $lines[-1]) {
1075 6696 100       10991 if ($newlines) {
1076 867         1608 $self->{column} = length $lines[-1];
1077             }
1078             else {
1079 5829         9630 $self->{column} += length $lines[-1];
1080             }
1081             }
1082             else {
1083 6093         9649 $self->{column} = 0;
1084             }
1085 12789         23467 $self->writer->write($yaml);
1086             }
1087              
1088             1;
1089              
1090             __END__