File Coverage

blib/lib/YAML/PP/Emitter.pm
Criterion Covered Total %
statement 542 563 96.2
branch 351 378 92.8
condition 91 92 98.9
subroutine 35 36 97.2
pod 17 25 68.0
total 1036 1094 94.7


line stmt bran cond sub pod time code
1 49     49   152408 use strict;
  49         97  
  49         1350  
2 49     49   208 use warnings;
  49         69  
  49         3363  
3             package YAML::PP::Emitter;
4              
5             our $VERSION = 'v0.41.1'; # TRIAL VERSION
6              
7 49         3384 use YAML::PP::Common qw/
8             YAML_PLAIN_SCALAR_STYLE YAML_SINGLE_QUOTED_SCALAR_STYLE
9             YAML_DOUBLE_QUOTED_SCALAR_STYLE
10             YAML_LITERAL_SCALAR_STYLE YAML_FOLDED_SCALAR_STYLE
11             YAML_FLOW_SEQUENCE_STYLE YAML_FLOW_MAPPING_STYLE
12 49     49   584 /;
  49         109  
13              
14 49 50   49   250 use constant DEBUG => $ENV{YAML_PP_EMIT_DEBUG} ? 1 : 0;
  49         100  
  49         3625  
15             if (DEBUG) { require Data::Dumper }
16 49     49   256 use constant DEFAULT_WIDTH => 80;
  49         102  
  49         273253  
17              
18             sub new {
19 2243     2243 1 175799 my ($class, %args) = @_;
20             my $self = bless {
21             indent => $args{indent} || 2,
22             writer => $args{writer},
23 2243   100     12238 width => $args{width} || DEFAULT_WIDTH,
      50        
24             }, $class;
25 2243         5532 $self->init;
26 2243         4450 return $self;
27             }
28              
29             sub clone {
30 9     9 0 14 my ($self) = @_;
31 9         15 my $clone = {
32             indent => $self->indent,
33             };
34 9         26 return bless $clone, ref $self;
35             }
36              
37 44735     44735 0 51219 sub event_stack { return $_[0]->{event_stack} }
38 6545     6545 0 15401 sub set_event_stack { $_[0]->{event_stack} = $_[1] }
39 4579     4579 1 9834 sub indent { return $_[0]->{indent} }
40 1415     1415 0 2245 sub width { return $_[0]->{width} }
41 0     0 0 0 sub line { return $_[0]->{line} }
42 21567     21567 0 49632 sub column { return $_[0]->{column} }
43 1     1 1 791 sub set_indent { $_[0]->{indent} = $_[1] }
44 28419     28419 1 56353 sub writer { $_[0]->{writer} }
45 5207     5207 1 12341 sub set_writer { $_[0]->{writer} = $_[1] }
46 649     649 0 895 sub tagmap { return $_[0]->{tagmap} }
47 5308     5308 0 8746 sub set_tagmap { $_[0]->{tagmap} = $_[1] }
48              
49             sub init {
50 5308     5308 1 81181 my ($self) = @_;
51 5308 100       8365 unless ($self->writer) {
52 2242         5007 $self->set_writer(YAML::PP::Writer->new);
53             }
54             $self->set_tagmap({
55 5308         14115 'tag:yaml.org,2002:' => '!!',
56             });
57 5308         7466 $self->{open_ended} = 0;
58 5308         7531 $self->{line} = 0;
59 5308         6994 $self->{column} = 0;
60 5308         7301 $self->writer->init;
61             }
62              
63             sub mapping_start_event {
64 1940     1940 1 13538 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ mapping_start_event\n";
65 1940         2933 my ($self, $info) = @_;
66 1940         3243 my $stack = $self->event_stack;
67 1940         2509 my $last = $stack->[-1];
68 1940         2942 my $indent = $last->{indent};
69 1940         2490 my $new_indent = $indent;
70 1940         2334 my $yaml = '';
71              
72 1940         2116 my $props = '';
73 1940         2712 my $anchor = $info->{anchor};
74 1940         2347 my $tag = $info->{tag};
75 1940 100       3326 if (defined $anchor) {
76 98         158 $anchor = "&$anchor";
77             }
78 1940 100       2839 if (defined $tag) {
79 110         235 $tag = $self->_emit_tag('map', $tag);
80             }
81 1940         4998 $props = join ' ', grep defined, ($anchor, $tag);
82              
83 1940   100     4775 my $flow = $last->{flow} || 0;
84 1940 100 100     5631 $flow++ if ($info->{style} || 0) eq YAML_FLOW_MAPPING_STYLE;
85              
86 1940         2444 my $newline = 0;
87 1940 100       3058 if ($flow > 1) {
88 138 100       296 if ($last->{type} eq 'SEQ') {
    100          
    50          
89 95 100       181 if ($last->{newline}) {
90 17         48 $yaml .= ' ';
91             }
92 95 100       154 if ($last->{index} == 0) {
93 27         43 $yaml .= "[";
94             }
95             else {
96 68         82 $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         3 $yaml .= "{";
105             }
106             else {
107 0         0 $yaml .= ",";
108             }
109             }
110             elsif ($last->{type} eq 'MAPVALUE') {
111 41 50       73 if ($last->{index} == 0) {
112 0         0 die "Should not happen (index 0 in MAPVALUE)";
113             }
114 41         45 $yaml .= ": ";
115             }
116 138 100       236 if ($props) {
117 18         25 $yaml .= " $props ";
118             }
119 138         233 $new_indent .= ' ' x $self->indent;
120             }
121             else {
122 1802 100       3282 if ($last->{type} eq 'DOC') {
123 985         1583 $newline = $last->{newline};
124             }
125             else {
126 817 100       1676 if ($last->{newline}) {
127 108         178 $yaml .= "\n";
128 108         203 $last->{column} = 0;
129             }
130 817 100       1378 if ($last->{type} eq 'MAPVALUE') {
131 263         476 $new_indent .= ' ' x $self->indent;
132 263         365 $newline = 1;
133             }
134             else {
135 554         686 $new_indent = $indent;
136 554 100 100     1387 if (not $props and $self->indent == 1) {
137 91         134 $new_indent .= ' ' x 2;
138             }
139             else {
140 463         731 $new_indent .= ' ' x $self->indent;
141             }
142              
143 554 100       1013 if ($last->{column}) {
144 15 100       55 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
145 15         23 $yaml .= $space;
146             }
147             else {
148 539         687 $yaml .= $indent;
149             }
150 554 100       990 if ($last->{type} eq 'SEQ') {
    100          
    50          
151 526         791 $yaml .= '-';
152             }
153             elsif ($last->{type} eq 'MAP') {
154 19         35 $yaml .= "?";
155 19         32 $last->{type} = 'COMPLEX';
156             }
157             elsif ($last->{type} eq 'COMPLEXVALUE') {
158 9         15 $yaml .= ":";
159             }
160             else {
161 0         0 die "Should not happen ($last->{type} in mapping_start)";
162             }
163 554         696 $last->{column} = 1;
164             }
165 817         1162 $last->{newline} = 0;
166             }
167 1802 100       3090 if ($props) {
168 159 100       359 $yaml .= $last->{column} ? ' ' : $indent;
169 159         203 $yaml .= $props;
170 159         181 $newline = 1;
171             }
172             }
173 1940         3888 $self->_write($yaml);
174 1940         4028 my $new_info = {
175             index => 0, indent => $new_indent, info => $info,
176             newline => $newline,
177             column => $self->column,
178             flow => $flow,
179             };
180 1940         4059 $new_info->{type} = 'MAP';
181 1940         2203 push @{ $stack }, $new_info;
  1940         3294  
182 1940         2633 $last->{index}++;
183 1940         3816 $self->{open_ended} = 0;
184             }
185              
186             sub mapping_end_event {
187 1939     1939 1 9629 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ mapping_end_event\n";
188 1939         2869 my ($self, $info) = @_;
189 1939         2787 my $stack = $self->event_stack;
190              
191 1939         2033 my $last = pop @{ $stack };
  1939         2752  
192 1939 100       5060 if ($last->{index} == 0) {
    100          
193 28         46 my $indent = $last->{indent};
194 28         36 my $zero_indent = $last->{zero_indent};
195 28 50       82 if ($last->{zero_indent}) {
196 0         0 $indent .= ' ' x $self->indent;
197             }
198 28 100       52 if ($self->column) {
199 22         37 $self->_write(" {}\n");
200             }
201             else {
202 6         18 $self->_write("$indent\{}\n");
203             }
204             }
205             elsif ($last->{flow}) {
206 359         465 my $yaml = "}";
207 359 100       665 if ($last->{flow} == 1) {
208 223         296 $yaml .= "\n";
209             }
210 359         672 $self->_write("$yaml");
211             }
212 1939         4749 $last = $stack->[-1];
213 1939         2929 $last->{column} = $self->column;
214 1939 100       8060 if ($last->{type} eq 'SEQ') {
    100          
    100          
    100          
    100          
215             }
216             elsif ($last->{type} eq 'MAP') {
217 2         5 $last->{type} = 'MAPVALUE';
218             }
219             elsif ($last->{type} eq 'MAPVALUE') {
220 304         580 $last->{type} = 'MAP';
221             }
222             elsif ($last->{type} eq 'COMPLEX') {
223 19         52 $last->{type} = 'COMPLEXVALUE';
224             }
225             elsif ($last->{type} eq 'COMPLEXVALUE') {
226 9         18 $last->{type} = 'MAP';
227             }
228             }
229              
230             sub sequence_start_event {
231 1355     1355 1 9760 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ sequence_start_event\n";
232 1355         2112 my ($self, $info) = @_;
233 1355         2447 my $stack = $self->event_stack;
234 1355         1862 my $last = $stack->[-1];
235 1355         2243 my $indent = $last->{indent};
236 1355         1697 my $new_indent = $indent;
237 1355         1703 my $yaml = '';
238              
239 1355         1681 my $props = '';
240 1355         1965 my $anchor = $info->{anchor};
241 1355         1668 my $tag = $info->{tag};
242 1355 100       2465 if (defined $anchor) {
243 44         87 $anchor = "&$anchor";
244             }
245 1355 100       2339 if (defined $tag) {
246 47         126 $tag = $self->_emit_tag('seq', $tag);
247             }
248 1355         3570 $props = join ' ', grep defined, ($anchor, $tag);
249              
250 1355   100     3795 my $flow = $last->{flow} || 0;
251 1355 100 100     5600 $flow++ if $flow or ($info->{style} || 0) eq YAML_FLOW_SEQUENCE_STYLE;
      100        
252 1355         1648 my $newline = 0;
253 1355         1673 my $zero_indent = 0;
254 1355 100       2369 if ($flow > 1) {
255 122 100       384 if ($last->{type} eq 'SEQ') {
    100          
    50          
256 52 50       132 if ($last->{newline}) {
257 0         0 $yaml .= ' ';
258             }
259 52 100       87 if ($last->{index} == 0) {
260 16         24 $yaml .= "[";
261             }
262             else {
263 36         45 $yaml .= ",";
264             }
265             }
266             elsif ($last->{type} eq 'MAP') {
267 14 100       36 if ($last->{newline}) {
268 1         2 $yaml .= ' ';
269             }
270 14 100       29 if ($last->{index} == 0) {
271 8         14 $yaml .= "{";
272             }
273             else {
274 6         10 $yaml .= ",";
275             }
276             }
277             elsif ($last->{type} eq 'MAPVALUE') {
278 56 50       116 if ($last->{index} == 0) {
279 0         0 die "Should not happen (index 0 in MAPVALUE)";
280             }
281 56         76 $yaml .= ": ";
282             }
283 122 100       239 if ($props) {
284 10         18 $yaml .= " $props ";
285             }
286 122         209 $new_indent .= ' ' x $self->indent;
287             }
288             else {
289 1233 100       2490 if ($last->{type} eq 'DOC') {
290 634         1000 $newline = $last->{newline};
291             }
292             else {
293 599 100       1296 if ($last->{newline}) {
294 51         71 $yaml .= "\n";
295 51         86 $last->{column} = 0;
296             }
297 599 100       1093 if ($last->{type} eq 'MAPVALUE') {
298 245         306 $zero_indent = 1;
299 245         296 $newline = 1;
300             }
301             else {
302 354 100 100     946 if (not $props and $self->indent == 1) {
303 68         71 $new_indent .= ' ' x 2;
304             }
305             else {
306 286         518 $new_indent .= ' ' x $self->indent;
307             }
308 354 100       595 if ($last->{column}) {
309 24 100       44 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
310 24         36 $yaml .= $space;
311             }
312             else {
313 330         459 $yaml .= $indent;
314             }
315 354 100       705 if ($last->{type} eq 'SEQ') {
    100          
    50          
316 278         319 $yaml .= "-";
317             }
318             elsif ($last->{type} eq 'MAP') {
319 47         66 $last->{type} = 'COMPLEX';
320 47         62 $zero_indent = 1;
321 47         93 $yaml .= "?";
322             }
323             elsif ($last->{type} eq 'COMPLEXVALUE') {
324 29         32 $yaml .= ":";
325 29         41 $zero_indent = 1;
326             }
327             else {
328 0         0 die "Should not happen ($last->{type} in sequence_start)";
329             }
330 354         437 $last->{column} = 1;
331             }
332 599         843 $last->{newline} = 0;
333             }
334 1233 100       2221 if ($props) {
335 73 100       184 $yaml .= $last->{column} ? ' ' : $indent;
336 73         102 $yaml .= $props;
337 73         91 $newline = 1;
338             }
339             }
340 1355         2856 $self->_write($yaml);
341 1355         1989 $last->{index}++;
342 1355         2804 my $new_info = {
343             index => 0,
344             indent => $new_indent,
345             info => $info,
346             zero_indent => $zero_indent,
347             newline => $newline,
348             column => $self->column,
349             flow => $flow,
350             };
351 1355         2474 $new_info->{type} = 'SEQ';
352 1355         1641 push @{ $stack }, $new_info;
  1355         2100  
353 1355         2952 $self->{open_ended} = 0;
354             }
355              
356             sub sequence_end_event {
357 1355     1355 1 6845 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ sequence_end_event\n";
358 1355         2167 my ($self, $info) = @_;
359 1355         1936 my $stack = $self->event_stack;
360              
361 1355         1661 my $last = pop @{ $stack };
  1355         1861  
362 1355 100       3413 if ($last->{index} == 0) {
    100          
363 59         94 my $indent = $last->{indent};
364 59         73 my $zero_indent = $last->{zero_indent};
365 59 100       131 if ($last->{zero_indent}) {
366 7         18 $indent .= ' ' x $self->indent;
367             }
368 59 100       88 my $yaml .= $self->column ? ' ' : $indent;
369 59         70 $yaml .= "[]";
370 59 100       116 if ($last->{flow} < 2) {
371 51         61 $yaml .= "\n";
372             }
373 59         118 $self->_write($yaml);
374             }
375             elsif ($last->{flow}) {
376 212         240 my $yaml = "]";
377 212 100       384 if ($last->{flow} == 1) {
378 98         141 $yaml .= "\n";
379             }
380 212         345 $self->_write($yaml);
381             }
382 1355         3358 $last = $stack->[-1];
383 1355         2031 $last->{column} = $self->column;
384 1355 100       5732 if ($last->{type} eq 'SEQ') {
    100          
    100          
    100          
    100          
385             }
386             elsif ($last->{type} eq 'MAP') {
387 14         27 $last->{type} = 'MAPVALUE';
388             }
389             elsif ($last->{type} eq 'MAPVALUE') {
390 301         649 $last->{type} = 'MAP';
391             }
392             elsif ($last->{type} eq 'COMPLEX') {
393 47         112 $last->{type} = 'COMPLEXVALUE';
394             }
395             elsif ($last->{type} eq 'COMPLEXVALUE') {
396 29         60 $last->{type} = 'MAP';
397             }
398             }
399              
400             my %forbidden_first = (qw/
401             ! 1 & 1 * 1 { 1 } 1 [ 1 ] 1 | 1 > 1 @ 1 ` 1 " 1 ' 1
402             /, '#' => 1, '%' => 1, ',' => 1, " " => 1);
403             my %forbidden_first_plus_space = (qw/
404             ? 1 - 1 : 1
405             /);
406              
407             my %control = (
408             "\x00" => '\0',
409             "\x01" => '\x01',
410             "\x02" => '\x02',
411             "\x03" => '\x03',
412             "\x04" => '\x04',
413             "\x05" => '\x05',
414             "\x06" => '\x06',
415             "\x07" => '\a',
416             "\x08" => '\b',
417             "\x0b" => '\v',
418             "\x0c" => '\f',
419             "\x0e" => '\x0e',
420             "\x0f" => '\x0f',
421             "\x10" => '\x10',
422             "\x11" => '\x11',
423             "\x12" => '\x12',
424             "\x13" => '\x13',
425             "\x14" => '\x14',
426             "\x15" => '\x15',
427             "\x16" => '\x16',
428             "\x17" => '\x17',
429             "\x18" => '\x18',
430             "\x19" => '\x19',
431             "\x1a" => '\x1a',
432             "\x1b" => '\e',
433             "\x1c" => '\x1c',
434             "\x1d" => '\x1d',
435             "\x1e" => '\x1e',
436             "\x1f" => '\x1f',
437             "\x7f" => '\x7f',
438             "\x80" => '\x80',
439             "\x81" => '\x81',
440             "\x82" => '\x82',
441             "\x83" => '\x83',
442             "\x84" => '\x84',
443             "\x86" => '\x86',
444             "\x87" => '\x87',
445             "\x88" => '\x88',
446             "\x89" => '\x89',
447             "\x8a" => '\x8a',
448             "\x8b" => '\x8b',
449             "\x8c" => '\x8c',
450             "\x8d" => '\x8d',
451             "\x8e" => '\x8e',
452             "\x8f" => '\x8f',
453             "\x90" => '\x90',
454             "\x91" => '\x91',
455             "\x92" => '\x92',
456             "\x93" => '\x93',
457             "\x94" => '\x94',
458             "\x95" => '\x95',
459             "\x96" => '\x96',
460             "\x97" => '\x97',
461             "\x98" => '\x98',
462             "\x99" => '\x99',
463             "\x9a" => '\x9a',
464             "\x9b" => '\x9b',
465             "\x9c" => '\x9c',
466             "\x9d" => '\x9d',
467             "\x9e" => '\x9e',
468             "\x9f" => '\x9f',
469             "\x{2029}" => '\P',
470             "\x{2028}" => '\L',
471             "\x85" => '\N',
472             "\xa0" => '\_',
473             );
474              
475             my $control_re = '\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x84\x86-\x9f\x{d800}-\x{dfff}\x{fffe}\x{ffff}\x{2028}\x{2029}\x85\xa0';
476             my %to_escape = (
477             "\n" => '\n',
478             "\t" => '\t',
479             "\r" => '\r',
480             '\\' => '\\\\',
481             '"' => '\\"',
482             %control,
483             );
484             my $escape_re = $control_re . '\n\t\r';
485             my $escape_re_without_lb = $control_re . '\t\r';
486              
487              
488             sub scalar_event {
489 9486     9486 1 40420 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ scalar_event\n";
490 9486         11364 my ($self, $info) = @_;
491 9486         13510 my $stack = $self->event_stack;
492 9486         10938 my $last = $stack->[-1];
493 9486         11801 my $indent = $last->{indent};
494 9486         12029 my $value = $info->{value};
495 9486         10515 my $flow = $last->{flow};
496              
497 9486         10814 my $props = '';
498 9486         10845 my $anchor = $info->{anchor};
499 9486         10378 my $tag = $info->{tag};
500 9486 100       13996 if (defined $anchor) {
501 460         615 $anchor = "&$anchor";
502             }
503 9486 100       12593 if (defined $tag) {
504 492         837 $tag = $self->_emit_tag('scalar', $tag);
505             }
506 9486         18569 $props = join ' ', grep defined, ($anchor, $tag);
507              
508 9486         9214 DEBUG and local $Data::Dumper::Useqq = 1;
509 9486 50       13976 $value = '' unless defined $value;
510              
511 9486         16443 my $style = $self->_find_best_scalar_style(
512             info => $info,
513             value => $value,
514             );
515              
516 9486         10899 my $open_ended = 0;
517              
518 9486 100       14803 if ($style == YAML_PLAIN_SCALAR_STYLE) {
    100          
    100          
    100          
519 7726         11030 $value =~ s/\n/\n\n/g;
520             }
521             elsif ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
522 508         1071 my $new_indent = $last->{indent} . (' ' x $self->indent);
523 508         979 $value =~ s/(\n+)/"\n" x (1 + (length $1))/eg;
  10         47  
524 508         1188 my @lines = split m/\n/, $value, -1;
525 508 100       977 if (@lines > 1) {
526 10         36 for my $line (@lines[1 .. $#lines]) {
527 20 100       50 $line = $new_indent . $line
528             if length $line;
529             }
530             }
531 508         912 $value = join "\n", @lines;
532 508         775 $value =~ s/'/''/g;
533 508         837 $value = "'" . $value . "'";
534             }
535             elsif ($style == YAML_LITERAL_SCALAR_STYLE) {
536 365         404 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$value], ['value']);
537 365         579 my $indicators = '';
538 365 100       1350 if ($value =~ m/\A\n* +/) {
539 36         86 $indicators .= $self->indent;
540             }
541 365         763 my $indent = $indent . ' ' x $self->indent;
542 365 100       2233 if ($value !~ m/\n\z/) {
    100          
543 87         137 $indicators .= '-';
544 87         135 $value .= "\n";
545             }
546             elsif ($value =~ m/(\n|\A)\n\z/) {
547 36         60 $indicators .= '+';
548 36         51 $open_ended = 1;
549             }
550 365         1940 $value =~ s/^(?=.)/$indent/gm;
551 365         837 $value = "|$indicators\n$value";
552             }
553             elsif ($style == YAML_FOLDED_SCALAR_STYLE) {
554 120         162 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$value], ['value']);
555 120         373 my @lines = split /\n/, $value, -1;
556 120         154 DEBUG and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\@lines], ['lines']);
557 120         187 my $trailing = -1;
558 120         271 while (@lines) {
559 218 100       462 last if $lines[-1] ne '';
560 99         171 pop @lines;
561 99         169 $trailing++;
562             }
563 120         193 my %start_with_space;
564 120         312 for my $i (0 .. $#lines) {
565 211 100       616 if ($lines[ $i ] =~ m/^[ \t]+/) {
566 31         72 $start_with_space{ $i } = 1;
567             }
568             }
569 120         241 my $indicators = '';
570 120 100       424 if ($value =~ m/\A\n* +/) {
571 19         46 $indicators .= $self->indent;
572             }
573 120         256 my $indent = $indent . ' ' x $self->indent;
574 120 100       381 if ($trailing > 0) {
    100          
575 3         5 $indicators .= '+';
576 3         4 $open_ended = 1;
577             }
578             elsif ($trailing < 0) {
579 24         36 $indicators .= '-';
580             }
581 120         161 $value = ">$indicators\n";
582 120         190 my $got_content = 0;
583 120         210 for my $i (0 .. $#lines) {
584 211         402 my $line = $lines[ $i ];
585 211   100     605 my $sp = $start_with_space{ $i } || 0;
586 211 100 100     493 my $spnext = $i == $#lines ? 1 : $start_with_space{ $i+1 } || 0;
587 211 100 100     457 my $spprev = $i == 0 ? 1 : $start_with_space{ $i-1 } || 0;
588 211 100       351 my $empty = length $line ? 0 : 1;
589 211 100       444 my $emptynext = $i == $#lines ? '' : length $lines[$i+1] ? 0 : 1;
    100          
590 211         242 my $nl = 0;
591 211 100       298 if ($empty) {
592 47 100 100     127 if ($spnext and $spprev) {
    100          
    100          
593 8         10 $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         171 $got_content = 1;
604 164         238 $value .= "$indent$line\n";
605 164 100 100     423 if (not $sp and not $spnext) {
606 32         37 $nl = 1;
607             }
608             }
609 211 100       385 if ($nl) {
610 78         1418 $value .= "\n";
611             }
612             }
613 120 100       382 $value .= "\n" x ($trailing) if $trailing > 0;
614             }
615             else {
616 767 50       3743 $value =~ s/([$escape_re"\\])/$to_escape{ $1 } || sprintf '\\u%04x', ord($1)/eg;
  722         2821  
617 767         1277 $value = '"' . $value . '"';
618             }
619              
620 9486         8839 DEBUG and warn __PACKAGE__.':'.__LINE__.": (@$stack)\n";
621 9486         16744 my $yaml = $self->_emit_scalar(
622             indent => $indent,
623             props => $props,
624             value => $value,
625             style => $style,
626             );
627              
628 9486         11609 $last->{index}++;
629 9486         10763 $last->{newline} = 0;
630 9486         17021 $self->_write($yaml);
631 9486         13820 $last->{column} = $self->column;
632 9486         28839 $self->{open_ended} = $open_ended;
633             }
634              
635             sub _find_best_scalar_style {
636 9486     9486   19236 my ($self, %args) = @_;
637 9486         11589 my $info = $args{info};
638 9486         11520 my $style = $info->{style};
639 9486         11721 my $value = $args{value};
640 9486         12530 my $stack = $self->event_stack;
641 9486         10659 my $last = $stack->[-1];
642 9486         10379 my $flow = $last->{flow};
643              
644 9486         16068 my $first = substr($value, 0, 1);
645 9486 100       45382 if ($value eq '') {
    100          
646 897 100 100     3272 if ($flow and $last->{type} ne 'MAPVALUE' and $last->{type} ne 'MAP') {
    100 100        
647 24         33 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
648             }
649             elsif (not $style) {
650 2         2 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
651             }
652             }
653             # no control characters anywhere
654             elsif ($value =~ m/[$control_re]/) {
655 55         91 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
656             }
657 9486   100     18499 $style ||= YAML_PLAIN_SCALAR_STYLE;
658              
659 9486 100 100     32222 if ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
    100          
    100          
660 356 100 100     2554 if ($value =~ m/ \n/ or $value =~ m/\n / or $value =~ m/^\n/ or $value =~ m/\n$/) {
    50 100        
      100        
661 16         23 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
662             }
663             elsif ($value eq "\n") {
664 0         0 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
665             }
666             }
667             elsif ($style == YAML_LITERAL_SCALAR_STYLE or $style == YAML_FOLDED_SCALAR_STYLE) {
668 444 100       1232 if ($value eq '') {
    100          
669 22         33 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
670             }
671             elsif ($flow) {
672             # no block scalars in flow
673 69 100       121 if ($value =~ tr/\n//) {
674 61         77 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
675             }
676             else {
677 8         12 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
678             }
679             }
680             }
681             elsif ($style == YAML_PLAIN_SCALAR_STYLE) {
682 8112 100 100     78271 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         87 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
686             }
687             elsif ($value eq "\n") {
688 8         20 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
689             }
690             elsif ($value !~ tr/ //c) {
691 10         17 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
692             }
693             elsif ($value !~ tr/ \n//c) {
694 12         42 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
695             }
696             elsif ($value =~ tr/\n//) {
697 134 100       330 $style = $flow ? YAML_DOUBLE_QUOTED_SCALAR_STYLE : YAML_LITERAL_SCALAR_STYLE;
698             }
699             elsif ($forbidden_first{ $first }) {
700 94         165 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
701             }
702             elsif ($flow and $value =~ tr/,[]{}//) {
703 5         11 $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         15 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
710             }
711             elsif ($value =~ m/ #/) {
712 8         12 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
713             }
714             elsif ($value =~ m/[: \t]\z/) {
715 27         46 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
716             }
717             elsif ($value =~ m/[^\x20-\x3A\x3B-\x7E\x85\xA0-\x{D7FF}\x{E000}-\x{FEFE}\x{FF00}-\x{FFFD}\x{10000}-\x{10FFFF}]/) {
718 0         0 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
719             }
720             elsif ($forbidden_first_plus_space{ $first }) {
721 211 100 100     1004 if (length ($value) == 1 or substr($value, 1, 1) =~ m/^\s/) {
722 16         23 $style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
723             }
724             }
725             }
726 9486 100 100     18410 if ($style == YAML_SINGLE_QUOTED_SCALAR_STYLE and not $info->{style}) {
727 158 100 100     371 if ($value =~ tr/'// and $value !~ tr/"//) {
728 20         23 $style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
729             }
730             }
731 9486         22995 return $style;
732             }
733              
734             sub _emit_scalar {
735 9486     9486   26489 my ($self, %args) = @_;
736 9486         12820 my $props = $args{props};
737 9486         11437 my $value = $args{value};
738 9486         10411 my $style = $args{style};
739 9486         12500 my $stack = $self->event_stack;
740 9486         10334 my $last = $stack->[-1];
741 9486         10496 my $flow = $last->{flow};
742              
743 9486         10190 my $yaml = '';
744 9486         10032 my $pvalue = $props;
745 9486 100 100     23906 if ($props and length $value) {
    100          
746 524         770 $pvalue .= " $value";
747             }
748             elsif (length $value) {
749 8190         10490 $pvalue .= $value;
750             }
751 9486 100       12927 if ($flow) {
752 1415 100 100     2307 if ($props and not length $value) {
753 52         64 $pvalue .= ' ';
754             }
755             $yaml = $self->_emit_flow_scalar(
756             value => $value,
757             pvalue => $pvalue,
758             style => $args{style},
759 1415         2566 );
760             }
761             else {
762             $yaml = $self->_emit_block_scalar(
763             props => $props,
764             value => $value,
765             pvalue => $pvalue,
766             indent => $args{indent},
767             style => $args{style},
768 8071         16852 );
769             }
770 9486         20547 return $yaml;
771             }
772              
773             sub _emit_block_scalar {
774 8071     8071   25156 my ($self, %args) = @_;
775 8071         10076 my $props = $args{props};
776 8071         9457 my $value = $args{value};
777 8071         9025 my $pvalue = $args{pvalue};
778 8071         8382 my $indent = $args{indent};
779 8071         8219 my $style = $args{style};
780 8071         9968 my $stack = $self->event_stack;
781 8071         8838 my $last = $stack->[-1];
782              
783 8071         7600 my $yaml;
784 8071 100 100     20995 if ($last->{type} eq 'MAP' or $last->{type} eq 'SEQ') {
785 4220 100 100     10211 if ($last->{index} == 0 and $last->{newline}) {
786 994         1924 $yaml .= "\n";
787 994         1359 $last->{column} = 0;
788 994         1351 $last->{newline} = 0;
789             }
790             }
791 8071         9124 my $space = ' ';
792 8071   100     16860 my $multiline = ($style == YAML_LITERAL_SCALAR_STYLE or $style == YAML_FOLDED_SCALAR_STYLE);
793 8071 100       11895 if ($last->{type} eq 'MAP') {
794              
795 2733 100       3716 if ($last->{column}) {
796 448 100       680 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
797 448         877 $yaml .= $space;
798             }
799             else {
800 2285         3329 $yaml .= $indent;
801             }
802 2733 100 100     4903 if ($props and not length $value) {
803 100         115 $pvalue .= ' ';
804             }
805 2733         3525 $last->{type} = 'MAPVALUE';
806 2733 100       4027 if ($multiline) {
807             # oops, a complex key
808 17         33 $yaml .= "? ";
809 17         30 $last->{type} = 'COMPLEXVALUE';
810             }
811 2733 100       3875 if (not $multiline) {
812 2716         3065 $pvalue .= ":";
813             }
814             }
815             else {
816 5338 100       9835 if ($last->{type} eq 'MAPVALUE') {
    100          
817 2155         2978 $last->{type} = 'MAP';
818             }
819             elsif ($last->{type} eq 'DOC') {
820             }
821             else {
822 1529 100       2557 if ($last->{column}) {
823 260 100       402 my $space = $self->indent > 1 ? ' ' x ($self->indent - 1) : ' ';
824 260         457 $yaml .= $space;
825             }
826             else {
827 1269         1963 $yaml .= $indent;
828             }
829 1529 100       3213 if ($last->{type} eq 'COMPLEXVALUE') {
    50          
830 42         80 $last->{type} = 'MAP';
831 42         55 $yaml .= ":";
832             }
833             elsif ($last->{type} eq 'SEQ') {
834 1487         1771 $yaml .= "-";
835             }
836             else {
837 0         0 die "Should not happen ($last->{type} in scalar_event)";
838              
839             }
840 1529         1912 $last->{column} = 1;
841             }
842              
843 5338 100       8270 if (length $pvalue) {
844 5044 100       7958 if ($last->{column}) {
845 3881         5672 $pvalue = "$space$pvalue";
846             }
847             }
848 5338 100       7993 if (not $multiline) {
849 4870         5443 $pvalue .= "\n";
850             }
851             }
852 8071         10929 $yaml .= $pvalue;
853 8071         20105 return $yaml;
854             }
855              
856             sub _emit_flow_scalar {
857 1415     1415   3172 my ($self, %args) = @_;
858 1415         1662 my $value = $args{value};
859 1415         1604 my $pvalue = $args{pvalue};
860 1415         1806 my $stack = $self->event_stack;
861 1415         1447 my $last = $stack->[-1];
862              
863 1415         1295 my $yaml;
864 1415 100       2890 if ($last->{type} eq 'SEQ') {
    100          
    50          
865 326 100       520 if ($last->{index} == 0) {
866 168 100       237 if ($self->column) {
867 131         247 $yaml .= ' ';
868             }
869 168         285 $yaml .= "[";
870             }
871             else {
872 158         224 $yaml .= ", ";
873             }
874             }
875             elsif ($last->{type} eq 'MAP') {
876 589 100       809 if ($last->{index} == 0) {
877 347 100       546 if ($self->column) {
878 237         329 $yaml .= ' ';
879             }
880 347         494 $yaml .= "{";
881             }
882             else {
883 242         298 $yaml .= ", ";
884             }
885 589         798 $last->{type} = 'MAPVALUE';
886             }
887             elsif ($last->{type} eq 'MAPVALUE') {
888 500 50       855 if ($last->{index} == 0) {
889 0         0 die "Should not happen (index 0 in MAPVALUE)";
890             }
891 500         684 $yaml .= ": ";
892 500         609 $last->{type} = 'MAP';
893             }
894 1415 100       1733 if ($self->column + length $pvalue > $self->width) {
895 51         62 $yaml .= "\n";
896 51         59 $yaml .= $last->{indent};
897 51         85 $yaml .= ' ' x $self->indent;
898             }
899 1415         1713 $yaml .= $pvalue;
900 1415         2901 return $yaml;
901             }
902              
903             sub alias_event {
904 202     202 1 909 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ alias_event\n";
905 202         348 my ($self, $info) = @_;
906 202         323 my $stack = $self->event_stack;
907 202         301 my $last = $stack->[-1];
908 202         308 my $indent = $last->{indent};
909 202         258 my $flow = $last->{flow};
910              
911 202         360 my $alias = '*' . $info->{value};
912              
913 202         253 my $yaml = '';
914 202 100 100     757 if ($last->{type} eq 'MAP' or $last->{type} eq 'SEQ') {
915 107 100 100     227 if ($last->{index} == 0 and $last->{newline}) {
916 12         16 $yaml .= "\n";
917 12         14 $last->{column} = 0;
918 12         16 $last->{newline} = 0;
919             }
920             }
921 202 100       417 $yaml .= $last->{column} ? ' ' : $indent;
922 202 100       342 if ($flow) {
923 27         36 my $space = '';
924 27 100       91 if ($last->{type} eq 'SEQ') {
    100          
    50          
925 5 100       11 if ($last->{index} == 0) {
926 1 50       4 if ($flow == 1) {
927 0         0 $yaml .= ' ';
928             }
929 1         2 $yaml .= "[";
930             }
931             else {
932 4         6 $yaml .= ", ";
933             }
934             }
935             elsif ($last->{type} eq 'MAP') {
936 7 100       18 if ($last->{index} == 0) {
937 2 50       5 if ($flow == 1) {
938 0         0 $yaml .= ' ';
939             }
940 2         2 $yaml .= "{";
941             }
942             else {
943 5         5 $yaml .= ", ";
944             }
945 7         12 $last->{type} = 'MAPVALUE';
946 7         8 $space = ' ';
947             }
948             elsif ($last->{type} eq 'MAPVALUE') {
949 15 50       30 if ($last->{index} == 0) {
950 0         0 die 23;
951 0 0       0 if ($flow == 1) {
952 0         0 $yaml .= ' ';
953             }
954 0         0 $yaml .= "{";
955             }
956             else {
957 15         17 $yaml .= ": ";
958             }
959 15         27 $last->{type} = 'MAP';
960             }
961 27         44 $yaml .= "$alias$space";
962             }
963             else {
964 175 100       310 if ($last->{type} eq 'MAP') {
965 25         32 $yaml .= "$alias :";
966 25         39 $last->{type} = 'MAPVALUE';
967             }
968             else {
969              
970 150 100       317 if ($last->{type} eq 'MAPVALUE') {
    50          
971 77         115 $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       218 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         80 $yaml .= "- ";
986             }
987             else {
988 0         0 die "Unexpected";
989             }
990             }
991 150         1584 $yaml .= "$alias\n";
992             }
993             }
994              
995 202         477 $self->_write("$yaml");
996 202         320 $last->{index}++;
997 202         310 $last->{column} = $self->column;
998 202         396 $self->{open_ended} = 0;
999             }
1000              
1001             sub document_start_event {
1002 3273     3273 1 12265 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ document_start_event\n";
1003 3273         5238 my ($self, $info) = @_;
1004 3273         4095 my $newline = 0;
1005 3273         5209 my $implicit = $info->{implicit};
1006 3273 100       6513 if ($info->{version_directive}) {
1007 18 100       27 if ($self->{open_ended}) {
1008 10         17 $self->_write("...\n");
1009             }
1010 18         59 $self->_write("%YAML $info->{version_directive}->{major}.$info->{version_directive}->{minor}\n");
1011 18         24 $self->{open_ended} = 0;
1012 18         21 $implicit = 0; # we need ---
1013             }
1014 3273 100       6028 unless ($implicit) {
1015 1196         1468 $newline = 1;
1016 1196         2672 $self->_write("---");
1017             }
1018             $self->set_event_stack([
1019             {
1020 3273         7241 type => 'DOC', index => 0, indent => '', info => $info,
1021             newline => $newline, column => $self->column,
1022             }
1023             ]);
1024             }
1025              
1026             sub document_end_event {
1027 3272     3272 1 11664 DEBUG and warn __PACKAGE__.':'.__LINE__.": +++ document_end_event\n";
1028 3272         4750 my ($self, $info) = @_;
1029 3272         7078 $self->set_event_stack([]);
1030 3272 100 100     10622 if ($self->{open_ended} or not $info->{implicit}) {
1031 243         502 $self->_write("...\n");
1032 243         463 $self->{open_ended} = 0;
1033             }
1034             else {
1035 3029         7767 $self->{open_ended} = 1;
1036             }
1037             }
1038              
1039       3065 1   sub stream_start_event {
1040             }
1041              
1042       3064 1   sub stream_end_event {
1043             }
1044              
1045             sub _emit_tag {
1046 649     649   1242 my ($self, $type, $tag) = @_;
1047 649         1199 my $map = $self->tagmap;
1048 649         1696 for my $key (sort keys %$map) {
1049 649 100       4053 if ($tag =~ m/^\Q$key\E(.*)/) {
1050 487         1207 $tag = $map->{ $key } . $1;
1051 487         1075 return $tag;
1052             }
1053             }
1054 162 100       797 if ($tag =~ m/^(!.*)/) {
1055 107         317 $tag = "$1";
1056             }
1057             else {
1058 55         140 $tag = "!<$tag>";
1059             }
1060 162         331 return $tag;
1061             }
1062              
1063             sub finish {
1064 1585     1585 1 2413 my ($self) = @_;
1065 1585         2179 $self->writer->finish;
1066             }
1067              
1068             sub _write {
1069 15108     15108   20349 my ($self, $yaml) = @_;
1070 15108 100       22743 return unless length $yaml;
1071 13154         28478 my @lines = split m/\n/, $yaml, -1;
1072 13154         16335 my $newlines = @lines - 1;
1073 13154         16169 $self->{line} += $newlines;
1074 13154 100       18003 if (length $lines[-1]) {
1075 6978 100       9068 if ($newlines) {
1076 881         1491 $self->{column} = length $lines[-1];
1077             }
1078             else {
1079 6097         9034 $self->{column} += length $lines[-1];
1080             }
1081             }
1082             else {
1083 6176         7273 $self->{column} = 0;
1084             }
1085 13154         18614 $self->writer->write($yaml);
1086             }
1087              
1088             1;
1089              
1090             __END__