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 47     47   139239 use strict;
  47         64  
  47         1313  
2 47     47   149 use warnings;
  47         60  
  47         2699  
3             package YAML::PP::Emitter;
4              
5             our $VERSION = 'v0.40.0'; # VERSION
6 47     47   11726 use Data::Dumper;
  47         154879  
  47         3058  
7              
8 47         2936 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 47     47   759 /;
  47         121  
14              
15 47 50   47   204 use constant DEBUG => $ENV{YAML_PP_EMIT_DEBUG} ? 1 : 0;
  47         63  
  47         2617  
16 47     47   202 use constant DEFAULT_WIDTH => 80;
  47         95  
  47         263506  
17              
18             sub new {
19 2195     2195 1 190706 my ($class, %args) = @_;
20             my $self = bless {
21             indent => $args{indent} || 2,
22             writer => $args{writer},
23 2195   100     13857 width => $args{width} || DEFAULT_WIDTH,
      50        
24             }, $class;
25 2195         7090 $self->init;
26 2195         4604 return $self;
27             }
28              
29             sub clone {
30 9     9 0 11 my ($self) = @_;
31 9         16 my $clone = {
32             indent => $self->indent,
33             };
34 9         28 return bless $clone, ref $self;
35             }
36              
37 43768     43768 0 54371 sub event_stack { return $_[0]->{event_stack} }
38 6465     6465 0 17337 sub set_event_stack { $_[0]->{event_stack} = $_[1] }
39 4475     4475 1 10409 sub indent { return $_[0]->{indent} }
40 1249     1249 0 1867 sub width { return $_[0]->{width} }
41 0     0 0 0 sub line { return $_[0]->{line} }
42 20895     20895 0 55297 sub column { return $_[0]->{column} }
43 1     1 1 850 sub set_indent { $_[0]->{indent} = $_[1] }
44 27870     27870 1 60619 sub writer { $_[0]->{writer} }
45 5120     5120 1 12783 sub set_writer { $_[0]->{writer} = $_[1] }
46 644     644 0 1002 sub tagmap { return $_[0]->{tagmap} }
47 5221     5221 0 9279 sub set_tagmap { $_[0]->{tagmap} = $_[1] }
48              
49             sub init {
50 5221     5221 1 93385 my ($self) = @_;
51 5221 100       9019 unless ($self->writer) {
52 2194         16727 $self->set_writer(YAML::PP::Writer->new);
53             }
54             $self->set_tagmap({
55 5221         15584 'tag:yaml.org,2002:' => '!!',
56             });
57 5221         7789 $self->{open_ended} = 0;
58 5221         7853 $self->{line} = 0;
59 5221         7883 $self->{column} = 0;
60 5221         7374 $self->writer->init;
61             }
62              
63             sub mapping_start_event {
64 1889     1889 1 14739 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ mapping_start_event\n";
65 1889         2875 my ($self, $info) = @_;
66 1889         3179 my $stack = $self->event_stack;
67 1889         2708 my $last = $stack->[-1];
68 1889         2862 my $indent = $last->{indent};
69 1889         2339 my $new_indent = $indent;
70 1889         2321 my $yaml = '';
71              
72 1889         2439 my $props = '';
73 1889         2493 my $anchor = $info->{anchor};
74 1889         2477 my $tag = $info->{tag};
75 1889 100       3487 if (defined $anchor) {
76 98         156 $anchor = "&$anchor";
77             }
78 1889 100       3236 if (defined $tag) {
79 109         299 $tag = $self->_emit_tag('map', $tag);
80             }
81 1889         5544 $props = join ' ', grep defined, ($anchor, $tag);
82              
83 1889   100     5391 my $flow = $last->{flow} || 0;
84 1889 100 100     6161 $flow++ if ($info->{style} || 0) eq YAML_FLOW_MAPPING_STYLE;
85              
86 1889         2330 my $newline = 0;
87 1889 100       3133 if ($flow > 1) {
88 135 100       253 if ($last->{type} eq 'SEQ') {
    100          
    50          
89 92 100       181 if ($last->{newline}) {
90 17         22 $yaml .= ' ';
91             }
92 92 100       128 if ($last->{index} == 0) {
93 27         44 $yaml .= "[";
94             }
95             else {
96 65         80 $yaml .= ",";
97             }
98             }
99             elsif ($last->{type} eq 'MAP') {
100 2 50       7 if ($last->{newline}) {
101 0         0 $yaml .= ' ';
102             }
103 2 50       6 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       75 if ($last->{index} == 0) {
112 0         0 die "Should not happen (index 0 in MAPVALUE)";
113             }
114 41         40 $yaml .= ": ";
115             }
116 135 100       201 if ($props) {
117 18         22 $yaml .= " $props ";
118             }
119 135         216 $new_indent .= ' ' x $self->indent;
120             }
121             else {
122 1754 100       3652 if ($last->{type} eq 'DOC') {
123 963         1833 $newline = $last->{newline};
124             }
125             else {
126 791 100       1485 if ($last->{newline}) {
127 104         202 $yaml .= "\n";
128 104         210 $last->{column} = 0;
129             }
130 791 100       1425 if ($last->{type} eq 'MAPVALUE') {
131 258         543 $new_indent .= ' ' x $self->indent;
132 258         336 $newline = 1;
133             }
134             else {
135 533         702 $new_indent = $indent;
136 533 100 100     1482 if (not $props and $self->indent == 1) {
137 91         129 $new_indent .= ' ' x 2;
138             }
139             else {
140 442         855 $new_indent .= ' ' x $self->indent;
141             }
142              
143 533 100       1034 if ($last->{column}) {
144 14 100       35 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
145 14         28 $yaml .= $space;
146             }
147             else {
148 519         760 $yaml .= $indent;
149             }
150 533 100       1053 if ($last->{type} eq 'SEQ') {
    100          
    50          
151 505         738 $yaml .= '-';
152             }
153             elsif ($last->{type} eq 'MAP') {
154 19         29 $yaml .= "?";
155 19         40 $last->{type} = 'COMPLEX';
156             }
157             elsif ($last->{type} eq 'COMPLEXVALUE') {
158 9         21 $yaml .= ":";
159             }
160             else {
161 0         0 die "Should not happen ($last->{type} in mapping_start)";
162             }
163 533         732 $last->{column} = 1;
164             }
165 791         1058 $last->{newline} = 0;
166             }
167 1754 100       3241 if ($props) {
168 158 100       348 $yaml .= $last->{column} ? ' ' : $indent;
169 158         222 $yaml .= $props;
170 158         203 $newline = 1;
171             }
172             }
173 1889         4330 $self->_write($yaml);
174 1889         3889 my $new_info = {
175             index => 0, indent => $new_indent, info => $info,
176             newline => $newline,
177             column => $self->column,
178             flow => $flow,
179             };
180 1889         3860 $new_info->{type} = 'MAP';
181 1889         2262 push @{ $stack }, $new_info;
  1889         3132  
182 1889         2556 $last->{index}++;
183 1889         4284 $self->{open_ended} = 0;
184             }
185              
186             sub mapping_end_event {
187 1888     1888 1 10165 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ mapping_end_event\n";
188 1888         3002 my ($self, $info) = @_;
189 1888         2914 my $stack = $self->event_stack;
190              
191 1888         2141 my $last = pop @{ $stack };
  1888         2854  
192 1888 100       4911 if ($last->{index} == 0) {
    100          
193 25         40 my $indent = $last->{indent};
194 25         35 my $zero_indent = $last->{zero_indent};
195 25 50       55 if ($last->{zero_indent}) {
196 0         0 $indent .= ' ' x $self->indent;
197             }
198 25 100       51 if ($self->column) {
199 20         36 $self->_write(" {}\n");
200             }
201             else {
202 5         17 $self->_write("$indent\{}\n");
203             }
204             }
205             elsif ($last->{flow}) {
206 318         358 my $yaml = "}";
207 318 100       533 if ($last->{flow} == 1) {
208 185         274 $yaml .= "\n";
209             }
210 318         550 $self->_write("$yaml");
211             }
212 1888         4803 $last = $stack->[-1];
213 1888         2954 $last->{column} = $self->column;
214 1888 100       8418 if ($last->{type} eq 'SEQ') {
    100          
    100          
    100          
    100          
215             }
216             elsif ($last->{type} eq 'MAP') {
217 2         6 $last->{type} = 'MAPVALUE';
218             }
219             elsif ($last->{type} eq 'MAPVALUE') {
220 299         641 $last->{type} = 'MAP';
221             }
222             elsif ($last->{type} eq 'COMPLEX') {
223 19         53 $last->{type} = 'COMPLEXVALUE';
224             }
225             elsif ($last->{type} eq 'COMPLEXVALUE') {
226 9         29 $last->{type} = 'MAP';
227             }
228             }
229              
230             sub sequence_start_event {
231 1306     1306 1 10374 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ sequence_start_event\n";
232 1306         2316 my ($self, $info) = @_;
233 1306         2445 my $stack = $self->event_stack;
234 1306         1930 my $last = $stack->[-1];
235 1306         2111 my $indent = $last->{indent};
236 1306         1724 my $new_indent = $indent;
237 1306         1776 my $yaml = '';
238              
239 1306         1651 my $props = '';
240 1306         2144 my $anchor = $info->{anchor};
241 1306         1768 my $tag = $info->{tag};
242 1306 100       2785 if (defined $anchor) {
243 43         1317 $anchor = "&$anchor";
244             }
245 1306 100       2239 if (defined $tag) {
246 46         131 $tag = $self->_emit_tag('seq', $tag);
247             }
248 1306         3814 $props = join ' ', grep defined, ($anchor, $tag);
249              
250 1306   100     3572 my $flow = $last->{flow} || 0;
251 1306 100 100     5892 $flow++ if $flow or ($info->{style} || 0) eq YAML_FLOW_SEQUENCE_STYLE;
      100        
252 1306         1708 my $newline = 0;
253 1306         1605 my $zero_indent = 0;
254 1306 100       2301 if ($flow > 1) {
255 108 100       295 if ($last->{type} eq 'SEQ') {
    100          
    50          
256 49 50       93 if ($last->{newline}) {
257 0         0 $yaml .= ' ';
258             }
259 49 100       75 if ($last->{index} == 0) {
260 14         21 $yaml .= "[";
261             }
262             else {
263 35         47 $yaml .= ",";
264             }
265             }
266             elsif ($last->{type} eq 'MAP') {
267 12 100       23 if ($last->{newline}) {
268 1         3 $yaml .= ' ';
269             }
270 12 100       26 if ($last->{index} == 0) {
271 7         9 $yaml .= "{";
272             }
273             else {
274 5         7 $yaml .= ",";
275             }
276             }
277             elsif ($last->{type} eq 'MAPVALUE') {
278 47 50       97 if ($last->{index} == 0) {
279 0         0 die "Should not happen (index 0 in MAPVALUE)";
280             }
281 47         67 $yaml .= ": ";
282             }
283 108 100       204 if ($props) {
284 8         13 $yaml .= " $props ";
285             }
286 108         155 $new_indent .= ' ' x $self->indent;
287             }
288             else {
289 1198 100       2453 if ($last->{type} eq 'DOC') {
290 617         1036 $newline = $last->{newline};
291             }
292             else {
293 581 100       1295 if ($last->{newline}) {
294 50         78 $yaml .= "\n";
295 50         77 $last->{column} = 0;
296             }
297 581 100       1104 if ($last->{type} eq 'MAPVALUE') {
298 240         311 $zero_indent = 1;
299 240         283 $newline = 1;
300             }
301             else {
302 341 100 100     916 if (not $props and $self->indent == 1) {
303 68         87 $new_indent .= ' ' x 2;
304             }
305             else {
306 273         447 $new_indent .= ' ' x $self->indent;
307             }
308 341 100       647 if ($last->{column}) {
309 21 100       36 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
310 21         30 $yaml .= $space;
311             }
312             else {
313 320         437 $yaml .= $indent;
314             }
315 341 100       732 if ($last->{type} eq 'SEQ') {
    100          
    50          
316 265         328 $yaml .= "-";
317             }
318             elsif ($last->{type} eq 'MAP') {
319 47         86 $last->{type} = 'COMPLEX';
320 47         61 $zero_indent = 1;
321 47         74 $yaml .= "?";
322             }
323             elsif ($last->{type} eq 'COMPLEXVALUE') {
324 29         48 $yaml .= ":";
325 29         38 $zero_indent = 1;
326             }
327             else {
328 0         0 die "Should not happen ($last->{type} in sequence_start)";
329             }
330 341         518 $last->{column} = 1;
331             }
332 581         799 $last->{newline} = 0;
333             }
334 1198 100       2172 if ($props) {
335 73 100       178 $yaml .= $last->{column} ? ' ' : $indent;
336 73         100 $yaml .= $props;
337 73         88 $newline = 1;
338             }
339             }
340 1306         3248 $self->_write($yaml);
341 1306         1925 $last->{index}++;
342 1306         2868 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         2665 $new_info->{type} = 'SEQ';
352 1306         1669 push @{ $stack }, $new_info;
  1306         2263  
353 1306         3220 $self->{open_ended} = 0;
354             }
355              
356             sub sequence_end_event {
357 1306     1306 1 6890 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ sequence_end_event\n";
358 1306         2125 my ($self, $info) = @_;
359 1306         2701 my $stack = $self->event_stack;
360              
361 1306         1662 my $last = pop @{ $stack };
  1306         1962  
362 1306 100       3516 if ($last->{index} == 0) {
    100          
363 56         108 my $indent = $last->{indent};
364 56         73 my $zero_indent = $last->{zero_indent};
365 56 100       111 if ($last->{zero_indent}) {
366 6         16 $indent .= ' ' x $self->indent;
367             }
368 56 100       93 my $yaml .= $self->column ? ' ' : $indent;
369 56         81 $yaml .= "[]";
370 56 100       104 if ($last->{flow} < 2) {
371 48         54 $yaml .= "\n";
372             }
373 56         102 $self->_write($yaml);
374             }
375             elsif ($last->{flow}) {
376 184         202 my $yaml = "]";
377 184 100       287 if ($last->{flow} == 1) {
378 84         106 $yaml .= "\n";
379             }
380 184         253 $self->_write($yaml);
381             }
382 1306         3372 $last = $stack->[-1];
383 1306         2096 $last->{column} = $self->column;
384 1306 100       5837 if ($last->{type} eq 'SEQ') {
    100          
    100          
    100          
    100          
385             }
386             elsif ($last->{type} eq 'MAP') {
387 12         25 $last->{type} = 'MAPVALUE';
388             }
389             elsif ($last->{type} eq 'MAPVALUE') {
390 287         705 $last->{type} = 'MAP';
391             }
392             elsif ($last->{type} eq 'COMPLEX') {
393 47         128 $last->{type} = 'COMPLEXVALUE';
394             }
395             elsif ($last->{type} eq 'COMPLEXVALUE') {
396 29         70 $last->{type} = 'MAP';
397             }
398             }
399              
400             my %forbidden_first = (qw/
401             ! 1 & 1 * 1 { 1 } 1 [ 1 ] 1 | 1 > 1 @ 1 ` 1 " 1 ' 1
402             /, '#' => 1, '%' => 1, ',' => 1, " " => 1);
403             my %forbidden_first_plus_space = (qw/
404             ? 1 - 1 : 1
405             /);
406              
407             my %control = (
408             "\x00" => '\0',
409             "\x01" => '\x01',
410             "\x02" => '\x02',
411             "\x03" => '\x03',
412             "\x04" => '\x04',
413             "\x05" => '\x05',
414             "\x06" => '\x06',
415             "\x07" => '\a',
416             "\x08" => '\b',
417             "\x0b" => '\v',
418             "\x0c" => '\f',
419             "\x0e" => '\x0e',
420             "\x0f" => '\x0f',
421             "\x10" => '\x10',
422             "\x11" => '\x11',
423             "\x12" => '\x12',
424             "\x13" => '\x13',
425             "\x14" => '\x14',
426             "\x15" => '\x15',
427             "\x16" => '\x16',
428             "\x17" => '\x17',
429             "\x18" => '\x18',
430             "\x19" => '\x19',
431             "\x1a" => '\x1a',
432             "\x1b" => '\e',
433             "\x1c" => '\x1c',
434             "\x1d" => '\x1d',
435             "\x1e" => '\x1e',
436             "\x1f" => '\x1f',
437             "\x7f" => '\x7f',
438             "\x80" => '\x80',
439             "\x81" => '\x81',
440             "\x82" => '\x82',
441             "\x83" => '\x83',
442             "\x84" => '\x84',
443             "\x86" => '\x86',
444             "\x87" => '\x87',
445             "\x88" => '\x88',
446             "\x89" => '\x89',
447             "\x8a" => '\x8a',
448             "\x8b" => '\x8b',
449             "\x8c" => '\x8c',
450             "\x8d" => '\x8d',
451             "\x8e" => '\x8e',
452             "\x8f" => '\x8f',
453             "\x90" => '\x90',
454             "\x91" => '\x91',
455             "\x92" => '\x92',
456             "\x93" => '\x93',
457             "\x94" => '\x94',
458             "\x95" => '\x95',
459             "\x96" => '\x96',
460             "\x97" => '\x97',
461             "\x98" => '\x98',
462             "\x99" => '\x99',
463             "\x9a" => '\x9a',
464             "\x9b" => '\x9b',
465             "\x9c" => '\x9c',
466             "\x9d" => '\x9d',
467             "\x9e" => '\x9e',
468             "\x9f" => '\x9f',
469             "\x{2029}" => '\P',
470             "\x{2028}" => '\L',
471             "\x85" => '\N',
472             "\xa0" => '\_',
473             );
474              
475             my $control_re = '\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x84\x86-\x9f\x{d800}-\x{dfff}\x{fffe}\x{ffff}\x{2028}\x{2029}\x85\xa0';
476             my %to_escape = (
477             "\n" => '\n',
478             "\t" => '\t',
479             "\r" => '\r',
480             '\\' => '\\\\',
481             '"' => '\\"',
482             %control,
483             );
484             my $escape_re = $control_re . '\n\t\r';
485             my $escape_re_without_lb = $control_re . '\t\r';
486              
487              
488             sub scalar_event {
489 9295     9295 1 42441 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ scalar_event\n";
490 9295         11929 my ($self, $info) = @_;
491 9295         14352 my $stack = $self->event_stack;
492 9295         11709 my $last = $stack->[-1];
493 9295         12070 my $indent = $last->{indent};
494 9295         12191 my $value = $info->{value};
495 9295         11323 my $flow = $last->{flow};
496              
497 9295         11486 my $props = '';
498 9295         10793 my $anchor = $info->{anchor};
499 9295         12689 my $tag = $info->{tag};
500 9295 100       14304 if (defined $anchor) {
501 459         647 $anchor = "&$anchor";
502             }
503 9295 100       12785 if (defined $tag) {
504 489         1091 $tag = $self->_emit_tag('scalar', $tag);
505             }
506 9295         20221 $props = join ' ', grep defined, ($anchor, $tag);
507              
508 9295         9244 DEBUG and local $Data::Dumper::Useqq = 1;
509 9295 50       13790 $value = '' unless defined $value;
510              
511 9295         16630 my $style = $self->_find_best_scalar_style(
512             info => $info,
513             value => $value,
514             );
515              
516 9295         11354 my $open_ended = 0;
517              
518 9295 100       14975 if ($style == YAML_PLAIN_SCALAR_STYLE) {
    100          
    100          
    100          
519 7555         11491 $value =~ s/\n/\n\n/g;
520             }
521             elsif ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
522 506         989 my $new_indent = $last->{indent} . (' ' x $self->indent);
523 506         983 $value =~ s/(\n+)/"\n" x (1 + (length $1))/eg;
  10         59  
524 506         1224 my @lines = split m/\n/, $value, -1;
525 506 100       994 if (@lines > 1) {
526 10         64 for my $line (@lines[1 .. $#lines]) {
527 20 100       54 $line = $new_indent . $line
528             if length $line;
529             }
530             }
531 506         924 $value = join "\n", @lines;
532 506         894 $value =~ s/'/''/g;
533 506         912 $value = "'" . $value . "'";
534             }
535             elsif ($style == YAML_LITERAL_SCALAR_STYLE) {
536 364         461 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$value], ['value']);
537 364         526 my $indicators = '';
538 364 100       1327 if ($value =~ m/\A\n* +/) {
539 36         73 $indicators .= $self->indent;
540             }
541 364         771 my $indent = $indent . ' ' x $self->indent;
542 364 100       2243 if ($value !~ m/\n\z/) {
    100          
543 87         151 $indicators .= '-';
544 87         129 $value .= "\n";
545             }
546             elsif ($value =~ m/(\n|\A)\n\z/) {
547 36         52 $indicators .= '+';
548 36         68 $open_ended = 1;
549             }
550 364         2095 $value =~ s/^(?=.)/$indent/gm;
551 364         786 $value = "|$indicators\n$value";
552             }
553             elsif ($style == YAML_FOLDED_SCALAR_STYLE) {
554 120         133 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$value], ['value']);
555 120         428 my @lines = split /\n/, $value, -1;
556 120         138 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\@lines], ['lines']);
557 120         166 my $trailing = -1;
558 120         243 while (@lines) {
559 218 100       445 last if $lines[-1] ne '';
560 99         156 pop @lines;
561 99         194 $trailing++;
562             }
563 120         170 my %start_with_space;
564 120         421 for my $i (0 .. $#lines) {
565 211 100       662 if ($lines[ $i ] =~ m/^[ \t]+/) {
566 31         81 $start_with_space{ $i } = 1;
567             }
568             }
569 120         186 my $indicators = '';
570 120 100       393 if ($value =~ m/\A\n* +/) {
571 19         34 $indicators .= $self->indent;
572             }
573 120         267 my $indent = $indent . ' ' x $self->indent;
574 120 100       345 if ($trailing > 0) {
    100          
575 3         5 $indicators .= '+';
576 3         3 $open_ended = 1;
577             }
578             elsif ($trailing < 0) {
579 24         39 $indicators .= '-';
580             }
581 120         225 $value = ">$indicators\n";
582 120         173 my $got_content = 0;
583 120         210 for my $i (0 .. $#lines) {
584 211         275 my $line = $lines[ $i ];
585 211   100     598 my $sp = $start_with_space{ $i } || 0;
586 211 100 100     513 my $spnext = $i == $#lines ? 1 : $start_with_space{ $i+1 } || 0;
587 211 100 100     474 my $spprev = $i == 0 ? 1 : $start_with_space{ $i-1 } || 0;
588 211 100       378 my $empty = length $line ? 0 : 1;
589 211 100       428 my $emptynext = $i == $#lines ? '' : length $lines[$i+1] ? 0 : 1;
    100          
590 211         249 my $nl = 0;
591 211 100       322 if ($empty) {
592 47 100 100     175 if ($spnext and $spprev) {
    100          
    100          
593 8         12 $nl = 1;
594             }
595             elsif (not $spnext) {
596 37         40 $nl = 1;
597             }
598             elsif (not $got_content) {
599 1         2 $nl = 1;
600             }
601             }
602             else {
603 164         194 $got_content = 1;
604 164         261 $value .= "$indent$line\n";
605 164 100 100     421 if (not $sp and not $spnext) {
606 32         46 $nl = 1;
607             }
608             }
609 211 100       413 if ($nl) {
610 78         112 $value .= "\n";
611             }
612             }
613 120 100       313 $value .= "\n" x ($trailing) if $trailing > 0;
614             }
615             else {
616 750 50       3998 $value =~ s/([$escape_re"\\])/$to_escape{ $1 } || sprintf '\\u%04x', ord($1)/eg;
  722         3150  
617 750         1448 $value = '"' . $value . '"';
618             }
619              
620 9295         9123 DEBUG and warn __PACKAGE__.':'.__LINE__.": (@$stack)\n";
621 9295         16930 my $yaml = $self->_emit_scalar(
622             indent => $indent,
623             props => $props,
624             value => $value,
625             style => $style,
626             );
627              
628 9295         12424 $last->{index}++;
629 9295         11517 $last->{newline} = 0;
630 9295         17773 $self->_write($yaml);
631 9295         14471 $last->{column} = $self->column;
632 9295         30041 $self->{open_ended} = $open_ended;
633             }
634              
635             sub _find_best_scalar_style {
636 9295     9295   20403 my ($self, %args) = @_;
637 9295         11937 my $info = $args{info};
638 9295         12688 my $style = $info->{style};
639 9295         11763 my $value = $args{value};
640 9295         12357 my $stack = $self->event_stack;
641 9295         10880 my $last = $stack->[-1];
642 9295         10609 my $flow = $last->{flow};
643              
644 9295         16832 my $first = substr($value, 0, 1);
645 9295 100       46562 if ($value eq '') {
    100          
646 887 100 100     3222 if ($flow and $last->{type} ne 'MAPVALUE' and $last->{type} ne 'MAP') {
    100 100        
647 24         32 $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         100 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
656             }
657 9295   100     19407 $style ||= YAML_PLAIN_SCALAR_STYLE;
658              
659 9295 100 100     33587 if ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
    100          
    100          
660 354 100 100     2611 if ($value =~ m/ \n/ or $value =~ m/\n / or $value =~ m/^\n/ or $value =~ m/\n$/) {
    50 100        
      100        
661 16         39 $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       1461 if ($value eq '') {
    100          
669 22         37 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
670             }
671             elsif ($flow) {
672             # no block scalars in flow
673 69 100       130 if ($value =~ tr/\n//) {
674 61         90 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
675             }
676             else {
677 8         10 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
678             }
679             }
680             }
681             elsif ($style == YAML_PLAIN_SCALAR_STYLE) {
682 7941 100 100     83293 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         79 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
686             }
687             elsif ($value eq "\n") {
688 8         16 $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         26 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
695             }
696             elsif ($value =~ tr/\n//) {
697 134 100       293 $style = $flow ? YAML_DOUBLE_QUOTED_SCALAR_STYLE : YAML_LITERAL_SCALAR_STYLE;
698             }
699             elsif ($forbidden_first{ $first }) {
700 94         154 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
701             }
702             elsif ($flow and $value =~ tr/,[]{}//) {
703 5         8 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
704             }
705             elsif (substr($value, 0, 3) =~ m/^(?:---|\.\.\.)/) {
706 12         27 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
707             }
708             elsif ($value =~ m/: /) {
709 8         13 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
710             }
711             elsif ($value =~ m/ #/) {
712 8         15 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
713             }
714             elsif ($value =~ m/[: \t]\z/) {
715 27         52 $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     1075 if (length ($value) == 1 or substr($value, 1, 1) =~ m/^\s/) {
722 16         25 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
723             }
724             }
725             }
726 9295 100 100     19753 if ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE and not $info->{style}) {
727 158 100 100     388 if ($value =~ tr/'// and $value !~ tr/"//) {
728 20         28 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
729             }
730             }
731 9295         24392 return $style;
732             }
733              
734             sub _emit_scalar {
735 9295     9295   27672 my ($self, %args) = @_;
736 9295         12354 my $props = $args{props};
737 9295         11707 my $value = $args{value};
738 9295         10754 my $style = $args{style};
739 9295         12907 my $stack = $self->event_stack;
740 9295         10581 my $last = $stack->[-1];
741 9295         10786 my $flow = $last->{flow};
742              
743 9295         10444 my $yaml = '';
744 9295         10418 my $pvalue = $props;
745 9295 100 100     23591 if ($props and length $value) {
    100          
746 522         768 $pvalue .= " $value";
747             }
748             elsif (length $value) {
749 8011         10814 $pvalue .= $value;
750             }
751 9295 100       12172 if ($flow) {
752 1249 100 100     2033 if ($props and not length $value) {
753 50         55 $pvalue .= ' ';
754             }
755             $yaml = $self->_emit_flow_scalar(
756             value => $value,
757             pvalue => $pvalue,
758             style => $args{style},
759 1249         2122 );
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         17615 );
769             }
770 9295         21812 return $yaml;
771             }
772              
773             sub _emit_block_scalar {
774 8046     8046   27191 my ($self, %args) = @_;
775 8046         10467 my $props = $args{props};
776 8046         10007 my $value = $args{value};
777 8046         10021 my $pvalue = $args{pvalue};
778 8046         9065 my $indent = $args{indent};
779 8046         9823 my $style = $args{style};
780 8046         11275 my $stack = $self->event_stack;
781 8046         9556 my $last = $stack->[-1];
782              
783 8046         8312 my $yaml;
784 8046 100 100     22648 if ($last->{type} eq 'MAP' or $last->{type} eq 'SEQ') {
785 4198 100 100     10430 if ($last->{index} == 0 and $last->{newline}) {
786 992         1752 $yaml .= "\n";
787 992         1418 $last->{column} = 0;
788 992         1322 $last->{newline} = 0;
789             }
790             }
791 8046         10493 my $space = ' ';
792 8046   100     19286 my $multiline = ($style == YAML_LITERAL_SCALAR_STYLE or $style == YAML_FOLDED_SCALAR_STYLE);
793 8046 100       12856 if ($last->{type} eq 'MAP') {
794              
795 2721 100       4238 if ($last->{column}) {
796 447 100       711 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
797 447         867 $yaml .= $space;
798             }
799             else {
800 2274         3385 $yaml .= $indent;
801             }
802 2721 100 100     5337 if ($props and not length $value) {
803 100         164 $pvalue .= ' ';
804             }
805 2721         3992 $last->{type} = 'MAPVALUE';
806 2721 100       4782 if ($multiline) {
807             # oops, a complex key
808 17         46 $yaml .= "? ";
809 17         27 $last->{type} = 'COMPLEXVALUE';
810             }
811 2721 100       4248 if (not $multiline) {
812 2704         3317 $pvalue .= ":";
813             }
814             }
815             else {
816 5325 100       10935 if ($last->{type} eq 'MAPVALUE') {
    100          
817 2153         3166 $last->{type} = 'MAP';
818             }
819             elsif ($last->{type} eq 'DOC') {
820             }
821             else {
822 1519 100       2454 if ($last->{column}) {
823 260 100       430 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
824 260         565 $yaml .= $space;
825             }
826             else {
827 1259         1950 $yaml .= $indent;
828             }
829 1519 100       3447 if ($last->{type} eq 'COMPLEXVALUE') {
    50          
830 42         74 $last->{type} = 'MAP';
831 42         47 $yaml .= ":";
832             }
833             elsif ($last->{type} eq 'SEQ') {
834 1477         1849 $yaml .= "-";
835             }
836             else {
837 0         0 die "Should not happen ($last->{type} in scalar_event)";
838              
839             }
840 1519         2134 $last->{column} = 1;
841             }
842              
843 5325 100       8296 if (length $pvalue) {
844 5032 100       8046 if ($last->{column}) {
845 3869         5676 $pvalue = "$space$pvalue";
846             }
847             }
848 5325 100       8061 if (not $multiline) {
849 4858         6041 $pvalue .= "\n";
850             }
851             }
852 8046         11020 $yaml .= $pvalue;
853 8046         21652 return $yaml;
854             }
855              
856             sub _emit_flow_scalar {
857 1249     1249   2683 my ($self, %args) = @_;
858 1249         1481 my $value = $args{value};
859 1249         1366 my $pvalue = $args{pvalue};
860 1249         1338 my $stack = $self->event_stack;
861 1249         1256 my $last = $stack->[-1];
862              
863 1249         1145 my $yaml;
864 1249 100       2479 if ($last->{type} eq 'SEQ') {
    100          
    50          
865 271 100       410 if ($last->{index} == 0) {
866 142 100       240 if ($self->column) {
867 108         160 $yaml .= ' ';
868             }
869 142         204 $yaml .= "[";
870             }
871             else {
872 129         179 $yaml .= ", ";
873             }
874             }
875             elsif ($last->{type} eq 'MAP') {
876 530 100       778 if ($last->{index} == 0) {
877 307 100       413 if ($self->column) {
878 205         309 $yaml .= ' ';
879             }
880 307         392 $yaml .= "{";
881             }
882             else {
883 223         299 $yaml .= ", ";
884             }
885 530         646 $last->{type} = 'MAPVALUE';
886             }
887             elsif ($last->{type} eq 'MAPVALUE') {
888 448 50       688 if ($last->{index} == 0) {
889 0         0 die "Should not happen (index 0 in MAPVALUE)";
890             }
891 448         552 $yaml .= ": ";
892 448         601 $last->{type} = 'MAP';
893             }
894 1249 100       1571 if ($self->column + length $pvalue > $self->width) {
895 51         60 $yaml .= "\n";
896 51         57 $yaml .= $last->{indent};
897 51         71 $yaml .= ' ' x $self->indent;
898             }
899 1249         1435 $yaml .= $pvalue;
900 1249         2561 return $yaml;
901             }
902              
903             sub alias_event {
904 199     199 1 959 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ alias_event\n";
905 199         391 my ($self, $info) = @_;
906 199         415 my $stack = $self->event_stack;
907 199         277 my $last = $stack->[-1];
908 199         293 my $indent = $last->{indent};
909 199         265 my $flow = $last->{flow};
910              
911 199         365 my $alias = '*' . $info->{value};
912              
913 199         310 my $yaml = '';
914 199 100 100     756 if ($last->{type} eq 'MAP' or $last->{type} eq 'SEQ') {
915 105 100 100     242 if ($last->{index} == 0 and $last->{newline}) {
916 12         22 $yaml .= "\n";
917 12         17 $last->{column} = 0;
918 12         17 $last->{newline} = 0;
919             }
920             }
921 199 100       404 $yaml .= $last->{column} ? ' ' : $indent;
922 199 100       343 if ($flow) {
923 24         43 my $space = '';
924 24 100       73 if ($last->{type} eq 'SEQ') {
    100          
    50          
925 4 100       10 if ($last->{index} == 0) {
926 1 50       2 if ($flow == 1) {
927 0         0 $yaml .= ' ';
928             }
929 1         2 $yaml .= "[";
930             }
931             else {
932 3         3 $yaml .= ", ";
933             }
934             }
935             elsif ($last->{type} eq 'MAP') {
936 6 100       10 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         8 $last->{type} = 'MAPVALUE';
946 6         8 $space = ' ';
947             }
948             elsif ($last->{type} eq 'MAPVALUE') {
949 14 50       24 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         22 $last->{type} = 'MAP';
960             }
961 24         38 $yaml .= "$alias$space";
962             }
963             else {
964 175 100       359 if ($last->{type} eq 'MAP') {
965 25         47 $yaml .= "$alias :";
966 25         57 $last->{type} = 'MAPVALUE';
967             }
968             else {
969              
970 150 100       371 if ($last->{type} eq 'MAPVALUE') {
    50          
971 77         127 $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       304 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         107 $yaml .= "- ";
986             }
987             else {
988 0         0 die "Unexpected";
989             }
990             }
991 150         253 $yaml .= "$alias\n";
992             }
993             }
994              
995 199         535 $self->_write("$yaml");
996 199         344 $last->{index}++;
997 199         483 $last->{column} = $self->column;
998 199         446 $self->{open_ended} = 0;
999             }
1000              
1001             sub document_start_event {
1002 3233     3233 1 13200 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ document_start_event\n";
1003 3233         5120 my ($self, $info) = @_;
1004 3233         4327 my $newline = 0;
1005 3233         5391 my $implicit = $info->{implicit};
1006 3233 100       6879 if ($info->{version_directive}) {
1007 18 100       29 if ($self->{open_ended}) {
1008 10         16 $self->_write("...\n");
1009             }
1010 18         58 $self->_write("%YAML $info->{version_directive}->{major}.$info->{version_directive}->{minor}\n");
1011 18         20 $self->{open_ended} = 0;
1012 18         22 $implicit = 0; # we need ---
1013             }
1014 3233 100       6149 unless ($implicit) {
1015 1183         1505 $newline = 1;
1016 1183         2889 $self->_write("---");
1017             }
1018             $self->set_event_stack([
1019             {
1020 3233         9248 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 12730 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ document_end_event\n";
1028 3232         4741 my ($self, $info) = @_;
1029 3232         7468 $self->set_event_stack([]);
1030 3232 100 100     10859 if ($self->{open_ended} or not $info->{implicit}) {
1031 241         550 $self->_write("...\n");
1032 241         521 $self->{open_ended} = 0;
1033             }
1034             else {
1035 2991         7613 $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   1253 my ($self, $type, $tag) = @_;
1047 644         1307 my $map = $self->tagmap;
1048 644         1911 for my $key (sort keys %$map) {
1049 644 100       4454 if ($tag =~ m/^\Q$key\E(.*)/) {
1050 482         1333 $tag = $map->{ $key } . $1;
1051 482         1146 return $tag;
1052             }
1053             }
1054 162 100       746 if ($tag =~ m/^(!.*)/) {
1055 107         266 $tag = "$1";
1056             }
1057             else {
1058 55         113 $tag = "!<$tag>";
1059             }
1060 162         348 return $tag;
1061             }
1062              
1063             sub finish {
1064 1585     1585 1 2432 my ($self) = @_;
1065 1585         2446 $self->writer->finish;
1066             }
1067              
1068             sub _write {
1069 14724     14724   21236 my ($self, $yaml) = @_;
1070 14724 100       22957 return unless length $yaml;
1071 12818         29625 my @lines = split m/\n/, $yaml, -1;
1072 12818         17881 my $newlines = @lines - 1;
1073 12818         17040 $self->{line} += $newlines;
1074 12818 100       18484 if (length $lines[-1]) {
1075 6715 100       8836 if ($newlines) {
1076 874         1674 $self->{column} = length $lines[-1];
1077             }
1078             else {
1079 5841         9048 $self->{column} += length $lines[-1];
1080             }
1081             }
1082             else {
1083 6103         7845 $self->{column} = 0;
1084             }
1085 12818         19493 $self->writer->write($yaml);
1086             }
1087              
1088             1;
1089              
1090             __END__