File Coverage

blib/lib/TAP/Parser/YAMLish/Writer.pm
Criterion Covered Total %
statement 62 66 93.9
branch 22 28 78.5
condition 5 10 50.0
subroutine 10 11 90.9
pod 1 1 100.0
total 100 116 86.2


line stmt bran cond sub pod time code
1             package TAP::Parser::YAMLish::Writer;
2              
3 10     10   16019 use strict;
  10         16  
  10         292  
4 10     10   43 use warnings;
  10         12  
  10         323  
5              
6 10     10   40 use base 'TAP::Object';
  10         12  
  10         7556  
7              
8             our $VERSION = '3.39';
9              
10             my $ESCAPE_CHAR = qr{ [ \x00-\x1f \" ] }x;
11             my $ESCAPE_KEY = qr{ (?: ^\W ) | $ESCAPE_CHAR }x;
12              
13             my @UNPRINTABLE = qw(
14             z x01 x02 x03 x04 x05 x06 a
15             x08 t n v f r x0e x0f
16             x10 x11 x12 x13 x14 x15 x16 x17
17             x18 x19 x1a e x1c x1d x1e x1f
18             );
19              
20             # new() implementation supplied by TAP::Object
21              
22             sub write {
23 20     20 1 23 my $self = shift;
24              
25 20 50       39 die "Need something to write"
26             unless @_;
27              
28 20         12 my $obj = shift;
29 20   50     36 my $out = shift || \*STDOUT;
30              
31 20 50       32 die "Need a reference to something I can write to"
32             unless ref $out;
33              
34 20         29 $self->{writer} = $self->_make_writer($out);
35              
36 20         31 $self->_write_obj( '---', $obj );
37 20         67 $self->_put('...');
38              
39 20         54 delete $self->{writer};
40             }
41              
42             sub _make_writer {
43 20     20   31 my $self = shift;
44 20         19 my $out = shift;
45              
46 20         22 my $ref = ref $out;
47              
48 20 100 0     33 if ( 'CODE' eq $ref ) {
    100          
    50          
    0          
49 18         32 return $out;
50             }
51             elsif ( 'ARRAY' eq $ref ) {
52 1     26   5 return sub { push @$out, shift };
  26         67  
53             }
54             elsif ( 'SCALAR' eq $ref ) {
55 1     26   4 return sub { $$out .= shift() . "\n" };
  26         53  
56             }
57             elsif ( 'GLOB' eq $ref || 'IO::Handle' eq $ref ) {
58 0     0   0 return sub { print $out shift(), "\n" };
  0         0  
59             }
60              
61 0         0 die "Can't write to $out";
62             }
63              
64             sub _put {
65 168     168   125 my $self = shift;
66 168         325 $self->{writer}->( join '', @_ );
67             }
68              
69             sub _enc_scalar {
70 212     212   151 my $self = shift;
71 212         151 my $val = shift;
72 212         143 my $rule = shift;
73              
74 212 100       264 return '~' unless defined $val;
75              
76 209 100       646 if ( $val =~ /$rule/ ) {
77 19         25 $val =~ s/\\/\\\\/g;
78 19         19 $val =~ s/"/\\"/g;
79 19         40 $val =~ s/ ( [\x00-\x1f] ) / '\\' . $UNPRINTABLE[ ord($1) ] /gex;
  16         43  
80 19         54 return qq{"$val"};
81             }
82              
83 190 100 66     616 if ( length($val) == 0 or $val =~ /\s/ ) {
84 3         3 $val =~ s/'/''/;
85 3         8 return "'$val'";
86             }
87              
88 187         372 return $val;
89             }
90              
91             sub _write_obj {
92 148     148   105 my $self = shift;
93 148         99 my $prefix = shift;
94 148         114 my $obj = shift;
95 148   100     217 my $indent = shift || 0;
96              
97 148 100       220 if ( my $ref = ref $obj ) {
98 41         43 my $pad = ' ' x $indent;
99 41 100       64 if ( 'HASH' eq $ref ) {
    50          
100 30 100       51 if ( keys %$obj ) {
101 28         34 $self->_put($prefix);
102 28         128 for my $key ( sort keys %$obj ) {
103 105         187 my $value = $obj->{$key};
104 105         113 $self->_write_obj(
105             $pad . $self->_enc_scalar( $key, $ESCAPE_KEY ) . ':',
106             $value, $indent + 1
107             );
108             }
109             }
110             else {
111 2         3 $self->_put( $prefix, ' {}' );
112             }
113             }
114             elsif ( 'ARRAY' eq $ref ) {
115 11 100       19 if (@$obj) {
116 9         13 $self->_put($prefix);
117 9         25 for my $value (@$obj) {
118 23         71 $self->_write_obj(
119             $pad . '-', $value,
120             $indent + 1
121             );
122             }
123             }
124             else {
125 2         4 $self->_put( $prefix, ' []' );
126             }
127             }
128             else {
129 0         0 die "Don't know how to encode $ref";
130             }
131             }
132             else {
133 107         108 $self->_put( $prefix, ' ', $self->_enc_scalar( $obj, $ESCAPE_CHAR ) );
134             }
135             }
136              
137             1;
138              
139             __END__