File Coverage

blib/lib/Text/CSV/Encoded.pm
Criterion Covered Total %
statement 109 113 96.4
branch 51 66 77.2
condition 12 22 54.5
subroutine 21 21 100.0
pod 12 13 92.3
total 205 235 87.2


line stmt bran cond sub pod time code
1             package Text::CSV::Encoded;
2             $Text::CSV::Encoded::VERSION = '0.24';
3 13     13   301041 use strict;
  13         36  
  13         316  
4 13     13   68 use Carp ();
  13         21  
  13         1733  
5              
6             BEGIN {
7 13     13   11289 require Text::CSV;
8 13 50       209986 if ( Text::CSV->VERSION < 1.06 ) {
9 0         0 Carp::croak "Base class Text::CSV version is less than 1.06.";
10             }
11 13         94 my $backend = Text::CSV->backend;
12 13         113 my $version = Text::CSV->backend->VERSION;
13 13 50 33     426 if ( ( $backend =~ /XS/ and $version >= 0.99 ) or ( $backend =~ /PP/ and $version >= 1.30 ) ) {
      33        
      33        
14 13     12 0 1002 eval q/ sub automatic_UTF8 { 1; } /; # parse/getline return strings (UNICODE)
  12         1166  
15             }
16             else {
17 0         0 eval q/ sub automatic_UTF8 { 0; } /;
18             }
19             }
20              
21 13     13   122 use base qw( Text::CSV );
  13         2302  
  13         3203  
22              
23              
24             my $DefaultCoderClass = $] >= 5.008 ? 'Text::CSV::Encoded::Coder::Encode'
25             : 'Text::CSV::Encoded::Coder::Base';
26             my @Attrs;
27              
28              
29             BEGIN {
30 13     13   14488 @Attrs = qw(
31             encoding
32             encoding_in encoding_out
33             encoding_io_in encoding_io_out
34             encoding_to_parse encoding_to_combine
35             );
36             }
37              
38              
39             sub import {
40 4     4   3017 my ( $class, %args ) = @_;
41              
42 4 100       2088 return unless %args;
43              
44 1 50       5 if ( exists $args{ coder_class } ) {
45 1         185 $DefaultCoderClass = $args{ coder_class };
46             }
47              
48             }
49              
50              
51             sub new {
52 10     10 1 52527 my $class = shift;
53 10   100     68 my $opt = shift || {};
54 10         24 my %opt;
55              
56 10         34 $opt->{binary} = 1;
57              
58 10         39 for my $attr ( @Attrs, 'encoding', 'coder_class' ) {
59 90 100       247 $opt{ $attr } = delete $opt->{ $attr } if ( exists $opt->{ $attr } );
60             }
61              
62 10   100     123 my $self = $class->SUPER::new( $opt ) || return;
63              
64 9 50 66     1107 if ( my $coder_class = ( $opt{coder_class} || $DefaultCoderClass ) ) {
65 9         42 $self->coder_class( $coder_class );
66             }
67             else {
68 0         0 Carp::croak "Coder class is not specified.";
69             }
70              
71 9         34 for my $attr ( @Attrs, 'encoding' ) {
72 72 100       501 $self->$attr( $opt{ $attr } ) if ( exists $opt{ $attr } );
73             }
74              
75 9         54 $self;
76             }
77              
78              
79             #
80             # Methods
81             #
82              
83             sub combine {
84 21     21 1 20423 my $self = shift;
85 21         47 my @fields = @_;
86              
87 21 100       613 $self->coder->decode_fields_ref( $self->encoding, \@fields ) if ( $self->encoding );
88              
89 21 100       503 unless ( $self->encoding_out ) {
90 6         22 return $self->SUPER::combine( @fields );
91             }
92              
93 15         347 my $ret = $self->encode( $self->encoding_out, \@fields );
94              
95 15 50       64 $self->{_STRING} = \$ret if ( $ret );
96              
97 15         68 return $self->{_STATUS};
98             }
99              
100              
101             sub parse {
102 24     24 1 5755 my $self = shift;
103 24         36 my $ret;
104              
105 24 100       639 if ( $self->encoding_in ) {
106 18         459 $ret = $self->decode( $self->encoding_in, $_[0] );
107             }
108             else {
109 6 50       27 $ret = [ $self->fields ] if $self->SUPER::parse( @_ );
110             }
111              
112 24 50       930 if ( $ret ) {
113 24 50       706 $self->coder->encode_fields_ref( $self->encoding, $ret ) if ( $self->encoding );
114 24         46 $self->{_FIELDS} = $ret;
115             }
116              
117 24         88 return $self->{_STATUS};
118             }
119              
120              
121             #
122             # IO style
123             #
124              
125             sub print { # to CSV
126 4     4 1 84 my ( $self, $io, $cols ) = @_;
127              
128 4 50       91 $self->coder->decode_fields_ref( $self->encoding, $cols ) if ( $self->encoding );
129 4         10 $self->coder->encode_fields_ref( $self->encoding_out, $cols );
130              
131 4         28 $self->SUPER::print( $io, $cols );
132             }
133              
134              
135             sub getline { # from CSV
136 31     31 1 15371 my ( $self, $io ) = @_;
137 31         96 my $cols = $self->SUPER::getline( $io );
138              
139 31 100       13404 if ( my $binds = $self->{_BOUND_COLUMNS} ) {
140 5         12 for my $val ( @$binds ) {
141 10         21 $$val = $self->coder->decode( $self->encoding_in, $$val );
142 10 50       306 $$val = $self->coder->encode( $self->encoding, $$val ) if ( $self->encoding );
143             }
144 5         12 return $cols;
145             }
146              
147 26 100       71 return unless $cols;
148              
149 21         48 $self->coder->decode_fields_ref( $self->encoding_in, $cols );
150 21 100       504 $self->coder->encode_fields_ref( $self->encoding, $cols ) if ( $self->encoding );
151              
152 21         61 $cols;
153             }
154              
155              
156             #
157             # decode/encode style
158             #
159              
160             sub decode {
161 28     28 1 4398 my ( $self, $enc, $text ) = @_;
162              
163 28 100       86 if ( @_ == 2 ) {
164 5         13 $text = $enc, $enc = '';
165             }
166              
167 28 100       74 $self->coder->upgrade( $text ) unless ( $enc ); # as unicode
168              
169 28 50       66 return unless ( defined $text );
170 28 50       141 return unless ( $self->SUPER::parse( $text ) );
171              
172 28 100       4986 return $enc ? [ map { $self->coder->decode( $enc, $_ ) } $self->fields() ] : [ $self->fields() ];
  37         213  
173             }
174              
175              
176             sub encode {
177 23     23 1 4113 my ( $self, $enc, $array ) = @_;
178              
179 23 100       68 if ( @_ == 2 ) {
180 4         10 $array = $enc, $enc = '';
181             }
182              
183 23 50 33     150 return unless ( defined $array and ref $array eq 'ARRAY' );
184 23 50       104 return unless ( $self->SUPER::combine ( @$array ) );
185              
186 23 100       1613 return $enc ? $self->coder->encode( $enc, $self->string() ) : $self->string();
187             }
188              
189              
190             # Internal
191              
192             sub _load_coder_class {
193 9     9   19 my ( $class, $coder_class ) = @_;
194 9         69 (my $file = "$coder_class.pm") =~ s{::}{/}g;
195              
196 9         19 eval { require $file };
  9         5326  
197              
198 9 50       57 if ( $@ ) {
199 0         0 Carp::croak $@;
200             }
201              
202 9         27 $coder_class;
203             }
204              
205              
206             # Accessors
207              
208             BEGIN {
209 13     13   42 for my $method ( qw( encoding encoding_in encoding_out ) ) {
210 39 100   105 1 8936 eval qq|
  105 100   100 1 331  
  105 100   62 1 234  
  6         15  
  6         17  
  99         390  
  100         11458  
  100         244  
  27         57  
  27         64  
  73         293  
  62         548  
  62         129  
  22         46  
  22         49  
  40         166  
211             sub $method {
212             my ( \$self, \$encoding ) = \@_;
213             if ( \@_ > 1 ) {
214             \$self->{ $method } = \$encoding;
215             return \$self;
216             }
217             else {
218             \$self->{ $method };
219             }
220             }
221             |;
222             }
223             }
224              
225              
226             *encoding_io_in = *encoding_to_parse = *encoding_in;
227             *encoding_io_out = *encoding_to_combine = *encoding_out;
228              
229              
230             sub coder {
231 116     116 1 760 my $self = shift;
232 116   66     1711 $self->{coder} ||= $self->coder_class->new( automatic_UTF8 => $self->automatic_UTF8, @_ );
233             }
234              
235              
236             sub coder_class {
237 18     18 1 58 my ( $self, $coder_class ) = @_;
238              
239 18 100       310 return $self->{coder_class} if ( @_ == 1 );
240              
241 9         38 $self->_load_coder_class( $coder_class );
242 9         31 $self->{coder_class} = $coder_class;
243 9         26 $self;
244             }
245              
246              
247             1;
248             __END__