File Coverage

blib/lib/Text/CSV/Encoded.pm
Criterion Covered Total %
statement 115 119 96.6
branch 51 66 77.2
condition 14 22 63.6
subroutine 23 23 100.0
pod 12 13 92.3
total 215 243 88.4


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