line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Class::CSV |
2
|
|
|
|
|
|
|
# Class Based CSV Parser/Writer |
3
|
|
|
|
|
|
|
# Written by DJ |
4
|
|
|
|
|
|
|
# |
5
|
|
|
|
|
|
|
# $Id: CSV.pm,v 1.2 2005/03/07 02:43:48 david Exp $ |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
# Class::CSV::Base |
8
|
|
|
|
|
|
|
package Class::CSV::Base; |
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
43040
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
189
|
|
11
|
1
|
|
|
1
|
|
7
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
298
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
BEGIN { |
14
|
|
|
|
|
|
|
## Modules |
15
|
|
|
|
|
|
|
# Core |
16
|
1
|
|
|
1
|
|
7
|
use Carp qw/confess/; |
|
1
|
|
|
|
|
14
|
|
|
1
|
|
|
|
|
876
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# Base |
19
|
1
|
|
|
1
|
|
7
|
use base qw(Class::Accessor); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4547
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
## Constants |
22
|
1
|
|
|
1
|
|
5008
|
use constant TRUE => 1; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
138
|
|
23
|
1
|
|
|
1
|
|
8
|
use constant FALSE => 0; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
67
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
## Variables |
26
|
1
|
|
|
1
|
|
7
|
use vars qw($VERSION); |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
348
|
|
27
|
1
|
|
|
1
|
|
4
|
$VERSION = do { my @r=(q$Revision: 1.3 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r}; |
|
1
|
|
|
|
|
11
|
|
|
1
|
|
|
|
|
730
|
|
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub _build_fields { |
31
|
0
|
|
|
0
|
|
|
my ($self, $fields) = @_; |
32
|
|
|
|
|
|
|
|
33
|
0
|
0
|
0
|
|
|
|
confess "Field list must be an array reference\n" |
34
|
|
|
|
|
|
|
unless (defined $fields and ref $fields eq 'ARRAY'); |
35
|
|
|
|
|
|
|
|
36
|
0
|
|
|
|
|
|
$self->{_field_list} = $fields; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# make the accessors via Class::Accessor |
39
|
0
|
|
|
|
|
|
__PACKAGE__->mk_accessors(@{$fields}); |
|
0
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
|
41
|
0
|
|
|
|
|
|
foreach my $field (@{$fields}) { |
|
0
|
|
|
|
|
|
|
42
|
0
|
|
|
|
|
|
$self->{__fields}->{$field} = TRUE; |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub set { |
47
|
0
|
|
|
0
|
|
|
my ($self, %items) = @_; |
48
|
|
|
|
|
|
|
|
49
|
0
|
|
|
|
|
|
foreach my $field (keys %items) { |
50
|
0
|
0
|
|
|
|
|
if (exists $self->{__fields}->{$field}) { |
51
|
0
|
|
|
|
|
|
$self->_set($field, $items{$field}); |
52
|
|
|
|
|
|
|
} else { |
53
|
0
|
|
|
|
|
|
confess "Cannot set field: ". $field. " as it doesnt exist!\n"; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub _set { |
59
|
0
|
|
|
0
|
|
|
my ($self, $key, $value) = @_; |
60
|
|
|
|
|
|
|
|
61
|
0
|
|
|
|
|
|
return $self->{$key} = $value; |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub get { |
65
|
0
|
|
|
0
|
|
|
my ($self, @fields) = @_; |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
# sanity check |
68
|
0
|
|
|
|
|
|
foreach my $field (@fields) { |
69
|
0
|
0
|
|
|
|
|
unless (exists $self->{__fields}->{$field}) { |
70
|
0
|
|
|
|
|
|
confess "Cannot get field: ". $field. " as it doesnt exist!\n"; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
|
74
|
0
|
|
|
|
|
|
return $self->_get(@fields); |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub _get { |
78
|
0
|
|
|
0
|
|
|
my $self = shift; |
79
|
|
|
|
|
|
|
|
80
|
0
|
0
|
|
|
|
|
if(@_ == 1) { |
|
|
0
|
|
|
|
|
|
81
|
0
|
|
|
|
|
|
return $self->{$_[0]}; |
82
|
|
|
|
|
|
|
} elsif( @_ > 1 ) { |
83
|
0
|
|
|
|
|
|
return @{$self}{@_}; |
|
0
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
0
|
|
|
|
|
|
return; |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
1; |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
# Class::CSV::CSV_XS_Options |
92
|
|
|
|
|
|
|
package Class::CSV::CSV_XS_Options; |
93
|
|
|
|
|
|
|
|
94
|
1
|
|
|
1
|
|
488
|
BEGIN { |
95
|
|
|
|
|
|
|
## Modules |
96
|
|
|
|
|
|
|
# Core |
97
|
1
|
|
|
1
|
|
10
|
use Carp qw/confess/; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
300
|
|
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
## Constants |
100
|
1
|
|
|
1
|
|
9
|
use constant TRUE => 1; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
72
|
|
101
|
1
|
|
|
1
|
|
8
|
use constant FALSE => 0; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
80
|
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# Base |
104
|
1
|
|
|
1
|
|
8
|
use base qw(Class::CSV::Base); |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
1102
|
|
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
sub new { |
108
|
0
|
|
|
0
|
|
|
my ($class, $opts) = @_; |
109
|
|
|
|
|
|
|
|
110
|
0
|
|
|
|
|
|
my $self = bless({}, $class); |
111
|
|
|
|
|
|
|
|
112
|
0
|
|
|
|
|
|
$self->_build_fields([qw/quote_char eol escape_char sep_char binary |
113
|
|
|
|
|
|
|
types always_quote/]); |
114
|
|
|
|
|
|
|
|
115
|
0
|
0
|
|
|
|
|
if (defined $opts) { |
116
|
0
|
0
|
|
|
|
|
if (ref $opts eq 'HASH') { |
117
|
0
|
|
|
|
|
|
$self->set(%{$opts}); |
|
0
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
} else { |
119
|
0
|
|
|
|
|
|
confess "Please provide csv_xs_options as a HASH ref!\n"; |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
0
|
|
|
|
|
|
return $self; |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub set { |
127
|
0
|
|
|
0
|
|
|
my ($self, %items) = @_; |
128
|
|
|
|
|
|
|
|
129
|
0
|
|
|
|
|
|
foreach my $field (keys %items) { |
130
|
0
|
0
|
|
|
|
|
unless (exists $self->{__fields}->{$field}) { |
131
|
0
|
|
|
|
|
|
$self->{__fields}->{$field} = TRUE; |
132
|
0
|
|
|
|
|
|
$self->mk_accessors($field); |
133
|
|
|
|
|
|
|
} |
134
|
0
|
|
|
|
|
|
$self->_set($field => $items{$field}); |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
sub to_hash_ref { |
139
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
140
|
|
|
|
|
|
|
|
141
|
0
|
|
|
|
|
|
my $hash = {}; |
142
|
0
|
|
|
|
|
|
foreach my $field (keys %{$self->{__fields}}) { |
|
0
|
|
|
|
|
|
|
143
|
0
|
|
|
|
|
|
my $value = $self->get($field); |
144
|
0
|
0
|
|
|
|
|
if (defined $value) { |
145
|
0
|
|
|
|
|
|
$hash->{$field} = $value; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
0
|
|
|
|
|
|
return $hash; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
# Class::CSV::Line |
153
|
|
|
|
|
|
|
package Class::CSV::Line; |
154
|
|
|
|
|
|
|
|
155
|
1
|
|
|
1
|
|
824
|
BEGIN { |
156
|
|
|
|
|
|
|
## Modules |
157
|
|
|
|
|
|
|
# Core |
158
|
1
|
|
|
1
|
|
201
|
use Carp qw/confess/; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
101
|
|
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
# CPAN |
161
|
1
|
|
|
1
|
|
2706
|
use Text::CSV_XS; |
|
1
|
|
|
|
|
14420
|
|
|
1
|
|
|
|
|
119
|
|
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
## Constants |
164
|
1
|
|
|
1
|
|
13
|
use constant TRUE => 1; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
76
|
|
165
|
1
|
|
|
1
|
|
4
|
use constant FALSE => 0; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
42
|
|
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
# Base |
168
|
1
|
|
|
1
|
|
5
|
use base qw(Class::CSV::Base); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
479
|
|
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub new { |
172
|
0
|
|
|
0
|
|
|
my ($class, %opts) = @_; |
173
|
|
|
|
|
|
|
|
174
|
0
|
0
|
|
|
|
|
confess "Please provide a list of fields\n" |
175
|
|
|
|
|
|
|
unless (exists $opts{fields}); |
176
|
|
|
|
|
|
|
|
177
|
0
|
|
|
|
|
|
my $self = bless({}, $class); |
178
|
|
|
|
|
|
|
|
179
|
0
|
|
|
|
|
|
$self->{__csv_xs_options} = $opts{csv_xs_options}; |
180
|
|
|
|
|
|
|
|
181
|
0
|
|
|
|
|
|
$self->_build_fields($opts{fields}); |
182
|
0
|
0
|
|
|
|
|
$self->_do_parse($opts{line}) if (exists $opts{line}); |
183
|
|
|
|
|
|
|
|
184
|
0
|
|
|
|
|
|
return $self; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
sub parse { |
188
|
0
|
|
|
0
|
|
|
my ($class, %opts) = @_; |
189
|
|
|
|
|
|
|
|
190
|
0
|
0
|
|
|
|
|
confess "Please provide a line to parse\n" |
191
|
|
|
|
|
|
|
unless (exists $opts{line}); |
192
|
|
|
|
|
|
|
|
193
|
0
|
|
|
|
|
|
my $self = $class->new(%opts); |
194
|
|
|
|
|
|
|
|
195
|
0
|
|
|
|
|
|
$self->_do_parse($opts{line}); |
196
|
|
|
|
|
|
|
|
197
|
0
|
|
|
|
|
|
return $self; |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
sub _build_fields { |
201
|
0
|
|
|
0
|
|
|
my ($self, $fields) = @_; |
202
|
|
|
|
|
|
|
|
203
|
0
|
0
|
0
|
|
|
|
confess "Field list must be an array reference\n" |
204
|
|
|
|
|
|
|
unless (defined $fields and ref $fields eq 'ARRAY'); |
205
|
|
|
|
|
|
|
|
206
|
0
|
|
|
|
|
|
$self->{_field_list} = $fields; |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# make the accessors via Class::Accessor |
209
|
0
|
|
|
|
|
|
__PACKAGE__->mk_accessors(@{$fields}); |
|
0
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
|
211
|
0
|
|
|
|
|
|
foreach my $field (@{$fields}) { |
|
0
|
|
|
|
|
|
|
212
|
0
|
|
|
|
|
|
$self->{__fields}->{$field} = TRUE; |
213
|
0
|
|
|
|
|
|
$self->_set($field, undef); |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
sub _do_parse { |
218
|
0
|
|
|
0
|
|
|
my ($self, $line) = @_; |
219
|
|
|
|
|
|
|
|
220
|
0
|
0
|
0
|
|
|
|
confess "Unable to find field array ref to build object with\n" |
221
|
|
|
|
|
|
|
unless (defined $self->{_field_list} |
222
|
|
|
|
|
|
|
and ref $self->{_field_list} eq 'ARRAY'); |
223
|
|
|
|
|
|
|
|
224
|
0
|
|
|
|
|
|
my $csv = new Text::CSV_XS($self->{__csv_xs_options}->to_hash_ref()); |
225
|
0
|
|
|
|
|
|
my $r = $csv->parse($line); |
226
|
0
|
0
|
0
|
|
|
|
if (defined $r and $r) { |
227
|
0
|
|
|
|
|
|
my @columns = $csv->fields(); |
228
|
0
|
|
|
|
|
|
for (my $i = 0; $i < @columns; $i++) { |
229
|
0
|
|
|
|
|
|
$self->set(${$self->{_field_list}}[$i], $columns[$i]); |
|
0
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
} else { |
232
|
0
|
0
|
|
|
|
|
if ($csv->error_input()) { |
233
|
0
|
|
|
|
|
|
confess "Failed to parse line: ". $csv->error_input(). "\n"; |
234
|
|
|
|
|
|
|
} else { |
235
|
0
|
|
|
|
|
|
confess "Failed to parse line: unknown reason\n"; |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
sub string { |
241
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
242
|
|
|
|
|
|
|
|
243
|
0
|
0
|
0
|
|
|
|
confess "Uninitiated Line Objects cannot be converted to a string!\n" |
244
|
|
|
|
|
|
|
unless (exists $self->{_field_list} |
245
|
|
|
|
|
|
|
and ref $self->{_field_list} eq 'ARRAY'); |
246
|
|
|
|
|
|
|
|
247
|
0
|
|
|
|
|
|
my @cols = (); |
248
|
0
|
|
|
|
|
|
foreach my $field (@{$self->{_field_list}}) { |
|
0
|
|
|
|
|
|
|
249
|
0
|
|
|
|
|
|
push(@cols, $self->_get($field)); |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
0
|
|
|
|
|
|
my $csv = new Text::CSV_XS($self->{__csv_xs_options}->to_hash_ref()); |
253
|
0
|
|
|
|
|
|
my $r = $csv->combine(@cols); |
254
|
0
|
0
|
|
|
|
|
if ($r) { |
255
|
0
|
|
|
|
|
|
return $csv->string(); |
256
|
|
|
|
|
|
|
} else { |
257
|
0
|
|
|
|
|
|
confess "Failed to create CSV line from line: ". $csv->error_input(). "\n" |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
1; |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
# Class::CSV |
265
|
|
|
|
|
|
|
package Class::CSV; |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
BEGIN { |
268
|
|
|
|
|
|
|
## Modules |
269
|
|
|
|
|
|
|
# Core |
270
|
1
|
|
|
1
|
|
7
|
use Carp qw/confess/; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
55
|
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
# Base |
273
|
1
|
|
|
1
|
|
5
|
use base qw(Class::CSV::Base); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
849
|
|
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
## Constants |
276
|
1
|
|
|
1
|
|
7
|
use constant TRUE => 1; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
55
|
|
277
|
1
|
|
|
1
|
|
6
|
use constant FALSE => 0; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
51
|
|
278
|
|
|
|
|
|
|
|
279
|
1
|
|
|
1
|
|
5
|
use constant DEFAULT_LINE_SEPARATOR => "\n"; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
64
|
|
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
## Setup Accessors |
282
|
1
|
|
|
1
|
|
12
|
__PACKAGE__->mk_ro_accessors(qw(fields)); |
283
|
1
|
|
|
|
|
106
|
__PACKAGE__->mk_accessors(qw(lines line_separator csv_xs_options)); |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
sub new { |
287
|
0
|
|
|
0
|
1
|
|
my ($class, %opts) = @_; |
288
|
|
|
|
|
|
|
|
289
|
0
|
|
|
|
|
|
my $self = bless({}, $class); |
290
|
|
|
|
|
|
|
|
291
|
0
|
0
|
0
|
|
|
|
confess "Please provide an array ref of fields\n" |
292
|
|
|
|
|
|
|
unless (exists $opts{fields} |
293
|
|
|
|
|
|
|
and ref $opts{fields} eq 'ARRAY'); |
294
|
|
|
|
|
|
|
|
295
|
0
|
|
0
|
|
|
|
$self->_private_set( |
296
|
|
|
|
|
|
|
line_separator => $opts{line_separator} || DEFAULT_LINE_SEPARATOR, |
297
|
|
|
|
|
|
|
csv_xs_options => |
298
|
|
|
|
|
|
|
new Class::CSV::CSV_XS_Options($opts{csv_xs_options}), |
299
|
|
|
|
|
|
|
fields => $opts{fields}, |
300
|
|
|
|
|
|
|
lines => [] |
301
|
|
|
|
|
|
|
); |
302
|
|
|
|
|
|
|
|
303
|
0
|
|
|
|
|
|
return $self; |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
sub parse { |
307
|
0
|
|
|
0
|
1
|
|
my ($class, %opts) = @_; |
308
|
|
|
|
|
|
|
|
309
|
0
|
|
|
|
|
|
my $self = $class->new(%opts); |
310
|
|
|
|
|
|
|
|
311
|
0
|
0
|
|
|
|
|
if (exists $opts{classdbi_objects}) { |
312
|
0
|
|
|
|
|
|
$opts{objects} = $opts{classdbi_objects}; |
313
|
0
|
|
|
|
|
|
delete($opts{classdbi_objects}); |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
|
316
|
0
|
0
|
0
|
|
|
|
if (exists $opts{filename} or exists $opts{filehandle}) { |
|
|
0
|
|
|
|
|
|
317
|
0
|
|
|
|
|
|
$self->_do_parse(%opts); |
318
|
|
|
|
|
|
|
} elsif (exists $opts{objects}) { |
319
|
0
|
|
|
|
|
|
$self->_do_parse_objects(%opts); |
320
|
|
|
|
|
|
|
} else { |
321
|
0
|
|
|
|
|
|
confess "Please provide objects or a filename/filehandle to parse\n"; |
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
|
324
|
0
|
|
|
|
|
|
return $self; |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
sub _do_parse { |
328
|
0
|
|
|
0
|
|
|
my ($self, %opts) = @_; |
329
|
|
|
|
|
|
|
|
330
|
0
|
|
|
|
|
|
my @CSV_Content = (); |
331
|
0
|
0
|
0
|
|
|
|
if (exists $opts{'filename'} and defined $opts{'filename'}) { |
|
|
0
|
0
|
|
|
|
|
332
|
0
|
0
|
|
|
|
|
confess "Cannot find filename: ". $opts{'filename'}. "\n" |
333
|
|
|
|
|
|
|
unless (-f $opts{'filename'}); |
334
|
0
|
0
|
|
|
|
|
confess "Cannot read filename: ". $opts{'filename'}. "\n" |
335
|
|
|
|
|
|
|
unless (-r $opts{'filename'}); |
336
|
0
|
0
|
|
|
|
|
open(CSV, $opts{'filename'}) |
337
|
|
|
|
|
|
|
or confess "Failed to open filename: ". $opts{'filename'}. ': '. $!. "\n"; |
338
|
0
|
|
|
|
|
|
while (my $line = ) { |
339
|
0
|
|
|
|
|
|
push(@CSV_Content, $self->strip_crlf($line)); |
340
|
|
|
|
|
|
|
} |
341
|
0
|
|
|
|
|
|
close(CSV); |
342
|
|
|
|
|
|
|
} elsif (exists $opts{'filehandle'} and defined $opts{'filehandle'}) { |
343
|
0
|
0
|
|
|
|
|
confess "filehandle provided is not a file handle\n" |
344
|
|
|
|
|
|
|
unless (defined(fileno($opts{'filehandle'}))); |
345
|
0
|
|
|
|
|
|
my $fh = $opts{'filehandle'}; |
346
|
0
|
|
|
|
|
|
while (my $line = <$fh>) { |
347
|
0
|
|
|
|
|
|
push(@CSV_Content, $self->strip_crlf($line)); |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
} else { |
350
|
0
|
|
|
|
|
|
confess "Please provide a filename/filehandle to parse\n"; |
351
|
|
|
|
|
|
|
} |
352
|
|
|
|
|
|
|
|
353
|
0
|
|
|
|
|
|
foreach my $line (@CSV_Content) { |
354
|
0
|
0
|
0
|
|
|
|
unless ($line and $line !~ /^([,"']|\s)+$/) { |
355
|
|
|
|
|
|
|
# Skip empty lines |
356
|
0
|
|
|
|
|
|
next; |
357
|
|
|
|
|
|
|
} |
358
|
0
|
|
|
|
|
|
push(@{$self->{lines}}, $self->new_line(undef, { line => $line })); |
|
0
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
sub _do_parse_objects { |
363
|
0
|
|
|
0
|
|
|
my ($self, %opts) = @_; |
364
|
|
|
|
|
|
|
|
365
|
0
|
0
|
|
|
|
|
confess "Please specify objects as an ARRAY ref!\n" |
366
|
|
|
|
|
|
|
unless (ref $opts{objects} eq 'ARRAY'); |
367
|
|
|
|
|
|
|
|
368
|
0
|
|
|
|
|
|
foreach my $object (@{$opts{objects}}) { |
|
0
|
|
|
|
|
|
|
369
|
0
|
|
|
|
|
|
my $line = $self->new_line(); |
370
|
|
|
|
|
|
|
|
371
|
0
|
|
|
|
|
|
foreach my $field (@{$self->fields()}) { |
|
0
|
|
|
|
|
|
|
372
|
0
|
0
|
|
|
|
|
confess ((ref $object). " does not contain method ". $field. "\n") |
373
|
|
|
|
|
|
|
unless ($object->can($field)); |
374
|
|
|
|
|
|
|
|
375
|
0
|
|
|
|
|
|
$line->set( $field => $object->$field ); |
376
|
|
|
|
|
|
|
} |
377
|
|
|
|
|
|
|
|
378
|
0
|
|
|
|
|
|
push(@{$self->{lines}}, $line); |
|
0
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
sub new_line { |
383
|
0
|
|
|
0
|
1
|
|
my ($self, $args, $opts) = @_; |
384
|
|
|
|
|
|
|
|
385
|
0
|
|
|
|
|
|
my %opts = (); |
386
|
0
|
0
|
0
|
|
|
|
if ($opts and ref $opts eq 'HASH') { |
387
|
0
|
|
|
|
|
|
%opts = %{$opts}; |
|
0
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
} |
389
|
|
|
|
|
|
|
|
390
|
0
|
|
|
|
|
|
my $line = new Class::CSV::Line( |
391
|
|
|
|
|
|
|
fields => $self->fields(), |
392
|
|
|
|
|
|
|
csv_xs_options => $self->csv_xs_options(), |
393
|
|
|
|
|
|
|
%opts |
394
|
|
|
|
|
|
|
); |
395
|
|
|
|
|
|
|
|
396
|
0
|
0
|
|
|
|
|
confess "Failed to create new line\n" |
397
|
|
|
|
|
|
|
unless ($line); |
398
|
|
|
|
|
|
|
|
399
|
0
|
0
|
|
|
|
|
if (defined $args) { |
400
|
0
|
0
|
|
|
|
|
if (ref $args eq 'ARRAY') { |
|
|
0
|
|
|
|
|
|
401
|
0
|
|
|
|
|
|
my @dr_array = @{$args}; |
|
0
|
|
|
|
|
|
|
402
|
0
|
|
|
|
|
|
foreach my $field (@{$self->fields()}) { |
|
0
|
|
|
|
|
|
|
403
|
0
|
|
|
|
|
|
my $value = shift @dr_array; |
404
|
0
|
|
|
|
|
|
$line->set( $field => $value ); |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
} elsif (ref $args eq 'HASH') { |
407
|
0
|
|
|
|
|
|
foreach my $field (keys %{$args}) { |
|
0
|
|
|
|
|
|
|
408
|
0
|
|
|
|
|
|
$line->set( $field => $args->{$field} ); |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
} else { |
411
|
0
|
|
|
|
|
|
confess "Need the arguments passed as either an ARRAY ref or a HASH ref!\n"; |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
0
|
|
|
|
|
|
return $line; |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
sub add_line { |
419
|
0
|
|
|
0
|
1
|
|
my ($self, $args) = @_; |
420
|
|
|
|
|
|
|
|
421
|
0
|
0
|
0
|
|
|
|
confess "Cannot call add_line without an argument!\n" |
422
|
|
|
|
|
|
|
unless (defined $args and $args); |
423
|
|
|
|
|
|
|
|
424
|
0
|
|
|
|
|
|
my $line = $self->new_line($args); |
425
|
|
|
|
|
|
|
|
426
|
0
|
|
|
|
|
|
push(@{$self->{lines}}, $line); |
|
0
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
sub string { |
430
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
431
|
|
|
|
|
|
|
|
432
|
0
|
0
|
|
|
|
|
confess "No lines to write!\n" unless (ref $self->lines() eq 'ARRAY'); |
433
|
|
|
|
|
|
|
|
434
|
0
|
|
|
|
|
|
my @string = (); |
435
|
0
|
|
|
|
|
|
map { push(@string, $_->string()); } @{$self->lines()}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
|
437
|
0
|
|
|
|
|
|
return join($self->line_separator(), @string). $self->line_separator(); |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
sub print { |
441
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
442
|
|
|
|
|
|
|
|
443
|
0
|
|
|
|
|
|
print $self->string(); |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
sub strip_crlf { |
447
|
0
|
|
|
0
|
0
|
|
my ($self, $string) = @_; |
448
|
|
|
|
|
|
|
|
449
|
0
|
|
|
|
|
|
$string =~ s/[\n\r]+$//g; |
450
|
|
|
|
|
|
|
|
451
|
0
|
|
|
|
|
|
return $string; |
452
|
|
|
|
|
|
|
} |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
sub _private_set { |
455
|
0
|
|
|
0
|
|
|
my ($self, %items) = @_; |
456
|
|
|
|
|
|
|
|
457
|
0
|
|
|
|
|
|
foreach my $field (keys %items) { |
458
|
0
|
|
|
|
|
|
$self->{$field} = $items{$field}; |
459
|
0
|
|
|
|
|
|
$self->{__fields}->{$field} = TRUE; |
460
|
|
|
|
|
|
|
} |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
1; |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
__END__ |