line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Text::CSV_XS; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# Copyright (c) 2007-2023 H.Merijn Brand. All rights reserved. |
4
|
|
|
|
|
|
|
# Copyright (c) 1998-2001 Jochen Wiedmann. All rights reserved. |
5
|
|
|
|
|
|
|
# Copyright (c) 1997 Alan Citterman. All rights reserved. |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or |
8
|
|
|
|
|
|
|
# modify it under the same terms as Perl itself. |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
# HISTORY |
11
|
|
|
|
|
|
|
# |
12
|
|
|
|
|
|
|
# 0.24 - |
13
|
|
|
|
|
|
|
# H.Merijn Brand (h.m.brand@xs4all.nl) |
14
|
|
|
|
|
|
|
# 0.10 - 0.23 |
15
|
|
|
|
|
|
|
# Jochen Wiedmann |
16
|
|
|
|
|
|
|
# Based on (the original) Text::CSV by: |
17
|
|
|
|
|
|
|
# Alan Citterman |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
require 5.006001; |
20
|
|
|
|
|
|
|
|
21
|
30
|
|
|
30
|
|
2049496
|
use strict; |
|
30
|
|
|
|
|
352
|
|
|
30
|
|
|
|
|
914
|
|
22
|
30
|
|
|
30
|
|
161
|
use warnings; |
|
30
|
|
|
|
|
53
|
|
|
30
|
|
|
|
|
1089
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
require Exporter; |
25
|
30
|
|
|
30
|
|
176
|
use XSLoader; |
|
30
|
|
|
|
|
58
|
|
|
30
|
|
|
|
|
795
|
|
26
|
30
|
|
|
30
|
|
166
|
use Carp; |
|
30
|
|
|
|
|
67
|
|
|
30
|
|
|
|
|
2175
|
|
27
|
|
|
|
|
|
|
|
28
|
30
|
|
|
30
|
|
242
|
use vars qw( $VERSION @ISA @EXPORT_OK %EXPORT_TAGS ); |
|
30
|
|
|
|
|
85
|
|
|
30
|
|
|
|
|
8949
|
|
29
|
|
|
|
|
|
|
$VERSION = "1.50"; |
30
|
|
|
|
|
|
|
@ISA = qw( Exporter ); |
31
|
|
|
|
|
|
|
XSLoader::load ("Text::CSV_XS", $VERSION); |
32
|
|
|
|
|
|
|
|
33
|
4
|
|
|
4
|
1
|
9
|
sub PV { 0 } sub CSV_TYPE_PV { PV } |
|
12
|
|
|
12
|
1
|
137
|
|
34
|
4
|
|
|
4
|
1
|
10
|
sub IV { 1 } sub CSV_TYPE_IV { IV } |
|
12
|
|
|
12
|
1
|
1346
|
|
35
|
4
|
|
|
4
|
1
|
9
|
sub NV { 2 } sub CSV_TYPE_NV { NV } |
|
12
|
|
|
12
|
1
|
71
|
|
36
|
|
|
|
|
|
|
|
37
|
11
|
|
|
11
|
1
|
60
|
sub CSV_FLAGS_IS_QUOTED { 0x0001 } |
38
|
12
|
|
|
12
|
1
|
60
|
sub CSV_FLAGS_IS_BINARY { 0x0002 } |
39
|
4
|
|
|
4
|
1
|
17
|
sub CSV_FLAGS_ERROR_IN_FIELD { 0x0004 } |
40
|
20
|
|
|
20
|
1
|
86
|
sub CSV_FLAGS_IS_MISSING { 0x0010 } |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
%EXPORT_TAGS = ( |
43
|
|
|
|
|
|
|
CONSTANTS => [qw( |
44
|
|
|
|
|
|
|
CSV_FLAGS_IS_QUOTED |
45
|
|
|
|
|
|
|
CSV_FLAGS_IS_BINARY |
46
|
|
|
|
|
|
|
CSV_FLAGS_ERROR_IN_FIELD |
47
|
|
|
|
|
|
|
CSV_FLAGS_IS_MISSING |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
CSV_TYPE_PV |
50
|
|
|
|
|
|
|
CSV_TYPE_IV |
51
|
|
|
|
|
|
|
CSV_TYPE_NV |
52
|
|
|
|
|
|
|
)], |
53
|
|
|
|
|
|
|
); |
54
|
|
|
|
|
|
|
@EXPORT_OK = (qw( csv PV IV NV ), @{$EXPORT_TAGS{CONSTANTS}}); |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
if ($] < 5.008002) { |
57
|
30
|
|
|
30
|
|
224
|
no warnings "redefine"; |
|
30
|
|
|
|
|
59
|
|
|
30
|
|
|
|
|
348523
|
|
58
|
|
|
|
|
|
|
*utf8::decode = sub {}; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# version |
62
|
|
|
|
|
|
|
# |
63
|
|
|
|
|
|
|
# class/object method expecting no arguments and returning the version |
64
|
|
|
|
|
|
|
# number of Text::CSV. there are no side-effects. |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub version { |
67
|
2
|
|
|
2
|
1
|
596
|
return $VERSION; |
68
|
|
|
|
|
|
|
} # version |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# new |
71
|
|
|
|
|
|
|
# |
72
|
|
|
|
|
|
|
# class/object method expecting no arguments and returning a reference to |
73
|
|
|
|
|
|
|
# a newly created Text::CSV object. |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
my %def_attr = ( |
76
|
|
|
|
|
|
|
'eol' => '', |
77
|
|
|
|
|
|
|
'sep_char' => ',', |
78
|
|
|
|
|
|
|
'quote_char' => '"', |
79
|
|
|
|
|
|
|
'escape_char' => '"', |
80
|
|
|
|
|
|
|
'binary' => 0, |
81
|
|
|
|
|
|
|
'decode_utf8' => 1, |
82
|
|
|
|
|
|
|
'auto_diag' => 0, |
83
|
|
|
|
|
|
|
'diag_verbose' => 0, |
84
|
|
|
|
|
|
|
'strict' => 0, |
85
|
|
|
|
|
|
|
'blank_is_undef' => 0, |
86
|
|
|
|
|
|
|
'empty_is_undef' => 0, |
87
|
|
|
|
|
|
|
'allow_whitespace' => 0, |
88
|
|
|
|
|
|
|
'allow_loose_quotes' => 0, |
89
|
|
|
|
|
|
|
'allow_loose_escapes' => 0, |
90
|
|
|
|
|
|
|
'allow_unquoted_escape' => 0, |
91
|
|
|
|
|
|
|
'always_quote' => 0, |
92
|
|
|
|
|
|
|
'quote_empty' => 0, |
93
|
|
|
|
|
|
|
'quote_space' => 1, |
94
|
|
|
|
|
|
|
'quote_binary' => 1, |
95
|
|
|
|
|
|
|
'escape_null' => 1, |
96
|
|
|
|
|
|
|
'keep_meta_info' => 0, |
97
|
|
|
|
|
|
|
'verbatim' => 0, |
98
|
|
|
|
|
|
|
'formula' => 0, |
99
|
|
|
|
|
|
|
'skip_empty_rows' => 0, |
100
|
|
|
|
|
|
|
'undef_str' => undef, |
101
|
|
|
|
|
|
|
'comment_str' => undef, |
102
|
|
|
|
|
|
|
'types' => undef, |
103
|
|
|
|
|
|
|
'callbacks' => undef, |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
'_EOF' => "", |
106
|
|
|
|
|
|
|
'_RECNO' => 0, |
107
|
|
|
|
|
|
|
'_STATUS' => undef, |
108
|
|
|
|
|
|
|
'_FIELDS' => undef, |
109
|
|
|
|
|
|
|
'_FFLAGS' => undef, |
110
|
|
|
|
|
|
|
'_STRING' => undef, |
111
|
|
|
|
|
|
|
'_ERROR_INPUT' => undef, |
112
|
|
|
|
|
|
|
'_COLUMN_NAMES' => undef, |
113
|
|
|
|
|
|
|
'_BOUND_COLUMNS' => undef, |
114
|
|
|
|
|
|
|
'_AHEAD' => undef, |
115
|
|
|
|
|
|
|
'_FORMULA_CB' => undef, |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
'ENCODING' => undef, |
118
|
|
|
|
|
|
|
); |
119
|
|
|
|
|
|
|
my %attr_alias = ( |
120
|
|
|
|
|
|
|
'quote_always' => "always_quote", |
121
|
|
|
|
|
|
|
'verbose_diag' => "diag_verbose", |
122
|
|
|
|
|
|
|
'quote_null' => "escape_null", |
123
|
|
|
|
|
|
|
'escape' => "escape_char", |
124
|
|
|
|
|
|
|
'comment' => "comment_str", |
125
|
|
|
|
|
|
|
); |
126
|
|
|
|
|
|
|
my $last_new_err = Text::CSV_XS->SetDiag (0); |
127
|
|
|
|
|
|
|
my $ebcdic = ord ("A") == 0xC1; # Faster than $Config{'ebcdic'} |
128
|
|
|
|
|
|
|
my @internal_kh; |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# NOT a method: is also used before bless |
131
|
|
|
|
|
|
|
sub _unhealthy_whitespace { |
132
|
15611
|
|
|
15611
|
|
25925
|
my ($self, $aw) = @_; |
133
|
15611
|
100
|
|
|
|
43418
|
$aw or return 0; # no checks needed without allow_whitespace |
134
|
|
|
|
|
|
|
|
135
|
3564
|
|
|
|
|
5242
|
my $quo = $self->{'quote'}; |
136
|
3564
|
100
|
100
|
|
|
8361
|
defined $quo && length ($quo) or $quo = $self->{'quote_char'}; |
137
|
3564
|
|
|
|
|
5492
|
my $esc = $self->{'escape_char'}; |
138
|
|
|
|
|
|
|
|
139
|
3564
|
100
|
100
|
|
|
35654
|
defined $quo && $quo =~ m/^[ \t]/ and return 1002; |
140
|
3322
|
100
|
100
|
|
|
36168
|
defined $esc && $esc =~ m/^[ \t]/ and return 1002; |
141
|
|
|
|
|
|
|
|
142
|
3032
|
|
|
|
|
7189
|
return 0; |
143
|
|
|
|
|
|
|
} # _unhealty_whitespace |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub _check_sanity { |
146
|
12305
|
|
|
12305
|
|
16563
|
my $self = shift; |
147
|
|
|
|
|
|
|
|
148
|
12305
|
|
|
|
|
19125
|
my $eol = $self->{'eol'}; |
149
|
12305
|
|
|
|
|
17309
|
my $sep = $self->{'sep'}; |
150
|
12305
|
100
|
100
|
|
|
30380
|
defined $sep && length ($sep) or $sep = $self->{'sep_char'}; |
151
|
12305
|
|
|
|
|
17829
|
my $quo = $self->{'quote'}; |
152
|
12305
|
100
|
100
|
|
|
25814
|
defined $quo && length ($quo) or $quo = $self->{'quote_char'}; |
153
|
12305
|
|
|
|
|
16822
|
my $esc = $self->{'escape_char'}; |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
# use DP;::diag ("SEP: '", DPeek ($sep), |
156
|
|
|
|
|
|
|
# "', QUO: '", DPeek ($quo), |
157
|
|
|
|
|
|
|
# "', ESC: '", DPeek ($esc),"'"); |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# sep_char should not be undefined |
160
|
12305
|
100
|
|
|
|
22830
|
$sep ne "" or return 1008; |
161
|
12303
|
100
|
|
|
|
23372
|
length ($sep) > 16 and return 1006; |
162
|
12302
|
100
|
|
|
|
32413
|
$sep =~ m/[\r\n]/ and return 1003; |
163
|
|
|
|
|
|
|
|
164
|
12296
|
100
|
|
|
|
20870
|
if (defined $quo) { |
165
|
12286
|
100
|
|
|
|
47589
|
$quo eq $sep and return 1001; |
166
|
12058
|
100
|
|
|
|
19931
|
length ($quo) > 16 and return 1007; |
167
|
12057
|
100
|
|
|
|
22723
|
$quo =~ m/[\r\n]/ and return 1003; |
168
|
|
|
|
|
|
|
} |
169
|
12061
|
100
|
|
|
|
20361
|
if (defined $esc) { |
170
|
12045
|
100
|
|
|
|
38728
|
$esc eq $sep and return 1001; |
171
|
11877
|
100
|
|
|
|
21409
|
$esc =~ m/[\r\n]/ and return 1003; |
172
|
|
|
|
|
|
|
} |
173
|
11887
|
100
|
|
|
|
19572
|
if (defined $eol) { |
174
|
11883
|
100
|
|
|
|
19768
|
length ($eol) > 16 and return 1005; |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
|
177
|
11886
|
|
|
|
|
21445
|
return _unhealthy_whitespace ($self, $self->{'allow_whitespace'}); |
178
|
|
|
|
|
|
|
} # _check_sanity |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
sub known_attributes { |
181
|
3
|
|
|
3
|
1
|
628
|
sort grep !m/^_/ => "sep", "quote", keys %def_attr; |
182
|
|
|
|
|
|
|
} # known_attributes |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
sub new { |
185
|
907
|
|
|
907
|
1
|
64379662
|
$last_new_err = Text::CSV_XS->SetDiag (1000, |
186
|
|
|
|
|
|
|
"usage: my \$csv = Text::CSV_XS->new ([{ option => value, ... }]);"); |
187
|
|
|
|
|
|
|
|
188
|
907
|
|
|
|
|
2036
|
my $proto = shift; |
189
|
907
|
100
|
100
|
|
|
4298
|
my $class = ref $proto || $proto or return; |
190
|
906
|
100
|
100
|
|
|
3902
|
@_ > 0 && ref $_[0] ne "HASH" and return; |
191
|
898
|
|
100
|
|
|
2101
|
my $attr = shift || {}; |
192
|
|
|
|
|
|
|
my %attr = map { |
193
|
2074
|
100
|
|
|
|
7984
|
my $k = m/^[a-zA-Z]\w+$/ ? lc $_ : $_; |
194
|
2074
|
100
|
|
|
|
4435
|
exists $attr_alias{$k} and $k = $attr_alias{$k}; |
195
|
2074
|
|
|
|
|
5692
|
($k => $attr->{$_}); |
196
|
898
|
|
|
|
|
1313
|
} keys %{$attr}; |
|
898
|
|
|
|
|
2783
|
|
197
|
|
|
|
|
|
|
|
198
|
898
|
|
|
|
|
1921
|
my $sep_aliased = 0; |
199
|
898
|
100
|
|
|
|
1889
|
if (exists $attr{'sep'}) { |
200
|
10
|
|
|
|
|
33
|
$attr{'sep_char'} = delete $attr{'sep'}; |
201
|
10
|
|
|
|
|
41
|
$sep_aliased = 1; |
202
|
|
|
|
|
|
|
} |
203
|
898
|
|
|
|
|
1291
|
my $quote_aliased = 0; |
204
|
898
|
100
|
|
|
|
1729
|
if (exists $attr{'quote'}) { |
205
|
25
|
|
|
|
|
62
|
$attr{'quote_char'} = delete $attr{'quote'}; |
206
|
25
|
|
|
|
|
39
|
$quote_aliased = 1; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
exists $attr{'formula_handling'} and |
209
|
898
|
100
|
|
|
|
1713
|
$attr{'formula'} = delete $attr{'formula_handling'}; |
210
|
898
|
|
|
|
|
1356
|
my $attr_formula = delete $attr{'formula'}; |
211
|
|
|
|
|
|
|
|
212
|
898
|
|
|
|
|
2152
|
for (keys %attr) { |
213
|
2037
|
100
|
100
|
|
|
7114
|
if (m/^[a-z]/ && exists $def_attr{$_}) { |
214
|
|
|
|
|
|
|
# uncoverable condition false |
215
|
2030
|
100
|
100
|
|
|
6800
|
defined $attr{$_} && m/_char$/ and utf8::decode ($attr{$_}); |
216
|
2030
|
|
|
|
|
3426
|
next; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
# croak? |
219
|
7
|
|
|
|
|
36
|
$last_new_err = Text::CSV_XS->SetDiag (1000, "INI - Unknown attribute '$_'"); |
220
|
7
|
100
|
|
|
|
36
|
$attr{'auto_diag'} and error_diag (); |
221
|
7
|
|
|
|
|
37
|
return; |
222
|
|
|
|
|
|
|
} |
223
|
891
|
100
|
|
|
|
2044
|
if ($sep_aliased) { |
224
|
10
|
|
|
|
|
60
|
my @b = unpack "U0C*", $attr{'sep_char'}; |
225
|
10
|
100
|
|
|
|
49
|
if (@b > 1) { |
226
|
6
|
|
|
|
|
17
|
$attr{'sep'} = $attr{'sep_char'}; |
227
|
6
|
|
|
|
|
14
|
$attr{'sep_char'} = "\0"; |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
else { |
230
|
4
|
|
|
|
|
11
|
$attr{'sep'} = undef; |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
} |
233
|
891
|
100
|
100
|
|
|
1986
|
if ($quote_aliased and defined $attr{'quote_char'}) { |
234
|
21
|
|
|
|
|
79
|
my @b = unpack "U0C*", $attr{'quote_char'}; |
235
|
21
|
100
|
|
|
|
52
|
if (@b > 1) { |
236
|
7
|
|
|
|
|
14
|
$attr{'quote'} = $attr{'quote_char'}; |
237
|
7
|
|
|
|
|
17
|
$attr{'quote_char'} = "\0"; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
else { |
240
|
14
|
|
|
|
|
32
|
$attr{'quote'} = undef; |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
891
|
|
|
|
|
15020
|
my $self = { %def_attr, %attr }; |
245
|
891
|
100
|
|
|
|
3235
|
if (my $ec = _check_sanity ($self)) { |
246
|
35
|
|
|
|
|
131
|
$last_new_err = Text::CSV_XS->SetDiag ($ec); |
247
|
35
|
100
|
|
|
|
83
|
$attr{'auto_diag'} and error_diag (); |
248
|
35
|
|
|
|
|
226
|
return; |
249
|
|
|
|
|
|
|
} |
250
|
856
|
100
|
100
|
|
|
2497
|
if (defined $self->{'callbacks'} && ref $self->{'callbacks'} ne "HASH") { |
251
|
6
|
|
|
|
|
727
|
carp ("The 'callbacks' attribute is set but is not a hash: ignored\n"); |
252
|
6
|
|
|
|
|
203
|
$self->{'callbacks'} = undef; |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
856
|
|
|
|
|
3252
|
$last_new_err = Text::CSV_XS->SetDiag (0); |
256
|
856
|
100
|
100
|
|
|
2686
|
defined $\ && !exists $attr{'eol'} and $self->{'eol'} = $\; |
257
|
856
|
|
|
|
|
1479
|
bless $self, $class; |
258
|
856
|
100
|
|
|
|
1922
|
defined $self->{'types'} and $self->types ($self->{'types'}); |
259
|
856
|
100
|
|
|
|
1636
|
defined $attr_formula and $self->{'formula'} = _supported_formula ($self, $attr_formula); |
260
|
855
|
|
|
|
|
4818
|
$self; |
261
|
|
|
|
|
|
|
} # new |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
# Keep in sync with XS! |
264
|
|
|
|
|
|
|
my %_cache_id = ( # Only expose what is accessed from within PM |
265
|
|
|
|
|
|
|
'quote_char' => 0, |
266
|
|
|
|
|
|
|
'escape_char' => 1, |
267
|
|
|
|
|
|
|
'sep_char' => 2, |
268
|
|
|
|
|
|
|
'sep' => 39, # 39 .. 55 |
269
|
|
|
|
|
|
|
'binary' => 3, |
270
|
|
|
|
|
|
|
'keep_meta_info' => 4, |
271
|
|
|
|
|
|
|
'always_quote' => 5, |
272
|
|
|
|
|
|
|
'allow_loose_quotes' => 6, |
273
|
|
|
|
|
|
|
'allow_loose_escapes' => 7, |
274
|
|
|
|
|
|
|
'allow_unquoted_escape' => 8, |
275
|
|
|
|
|
|
|
'allow_whitespace' => 9, |
276
|
|
|
|
|
|
|
'blank_is_undef' => 10, |
277
|
|
|
|
|
|
|
'eol' => 11, |
278
|
|
|
|
|
|
|
'quote' => 15, |
279
|
|
|
|
|
|
|
'verbatim' => 22, |
280
|
|
|
|
|
|
|
'empty_is_undef' => 23, |
281
|
|
|
|
|
|
|
'auto_diag' => 24, |
282
|
|
|
|
|
|
|
'diag_verbose' => 33, |
283
|
|
|
|
|
|
|
'quote_space' => 25, |
284
|
|
|
|
|
|
|
'quote_empty' => 37, |
285
|
|
|
|
|
|
|
'quote_binary' => 32, |
286
|
|
|
|
|
|
|
'escape_null' => 31, |
287
|
|
|
|
|
|
|
'decode_utf8' => 35, |
288
|
|
|
|
|
|
|
'_has_ahead' => 30, |
289
|
|
|
|
|
|
|
'_has_hooks' => 36, |
290
|
|
|
|
|
|
|
'_is_bound' => 26, # 26 .. 29 |
291
|
|
|
|
|
|
|
'formula' => 38, |
292
|
|
|
|
|
|
|
'strict' => 42, |
293
|
|
|
|
|
|
|
'skip_empty_rows' => 43, |
294
|
|
|
|
|
|
|
'undef_str' => 46, |
295
|
|
|
|
|
|
|
'comment_str' => 54, |
296
|
|
|
|
|
|
|
'types' => 62, |
297
|
|
|
|
|
|
|
); |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
# A `character' |
300
|
|
|
|
|
|
|
sub _set_attr_C { |
301
|
11095
|
|
|
11095
|
|
22443
|
my ($self, $name, $val, $ec) = @_; |
302
|
11095
|
100
|
|
|
|
31379
|
defined $val and utf8::decode ($val); |
303
|
11095
|
|
|
|
|
18268
|
$self->{$name} = $val; |
304
|
11095
|
100
|
|
|
|
17058
|
$ec = _check_sanity ($self) and croak ($self->SetDiag ($ec)); |
305
|
10185
|
|
|
|
|
35940
|
$self->_cache_set ($_cache_id{$name}, $val); |
306
|
|
|
|
|
|
|
} # _set_attr_C |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# A flag |
309
|
|
|
|
|
|
|
sub _set_attr_X { |
310
|
5642
|
|
|
5642
|
|
10072
|
my ($self, $name, $val) = @_; |
311
|
5642
|
100
|
|
|
|
10685
|
defined $val or $val = 0; |
312
|
5642
|
|
|
|
|
8949
|
$self->{$name} = $val; |
313
|
5642
|
|
|
|
|
21348
|
$self->_cache_set ($_cache_id{$name}, 0 + $val); |
314
|
|
|
|
|
|
|
} # _set_attr_X |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
# A number |
317
|
|
|
|
|
|
|
sub _set_attr_N { |
318
|
38
|
|
|
38
|
|
97
|
my ($self, $name, $val) = @_; |
319
|
38
|
|
|
|
|
82
|
$self->{$name} = $val; |
320
|
38
|
|
|
|
|
193
|
$self->_cache_set ($_cache_id{$name}, 0 + $val); |
321
|
|
|
|
|
|
|
} # _set_attr_N |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
# Accessor methods. |
324
|
|
|
|
|
|
|
# It is unwise to change them halfway through a single file! |
325
|
|
|
|
|
|
|
sub quote_char { |
326
|
4836
|
|
|
4836
|
1
|
644060
|
my $self = shift; |
327
|
4836
|
100
|
|
|
|
10829
|
if (@_) { |
328
|
3601
|
|
|
|
|
8053
|
$self->_set_attr_C ("quote_char", shift); |
329
|
3374
|
|
|
|
|
7767
|
$self->_cache_set ($_cache_id{'quote'}, ""); |
330
|
|
|
|
|
|
|
} |
331
|
4609
|
|
|
|
|
13978
|
$self->{'quote_char'}; |
332
|
|
|
|
|
|
|
} # quote_char |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
sub quote { |
335
|
20
|
|
|
20
|
1
|
46
|
my $self = shift; |
336
|
20
|
100
|
|
|
|
60
|
if (@_) { |
337
|
11
|
|
|
|
|
23
|
my $quote = shift; |
338
|
11
|
100
|
|
|
|
59
|
defined $quote or $quote = ""; |
339
|
11
|
|
|
|
|
32
|
utf8::decode ($quote); |
340
|
11
|
|
|
|
|
45
|
my @b = unpack "U0C*", $quote; |
341
|
11
|
100
|
|
|
|
36
|
if (@b > 1) { |
342
|
5
|
100
|
|
|
|
101
|
@b > 16 and croak ($self->SetDiag (1007)); |
343
|
4
|
|
|
|
|
13
|
$self->quote_char ("\0"); |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
else { |
346
|
6
|
|
|
|
|
17
|
$self->quote_char ($quote); |
347
|
6
|
|
|
|
|
16
|
$quote = ""; |
348
|
|
|
|
|
|
|
} |
349
|
10
|
|
|
|
|
19
|
$self->{'quote'} = $quote; |
350
|
|
|
|
|
|
|
|
351
|
10
|
|
|
|
|
19
|
my $ec = _check_sanity ($self); |
352
|
10
|
100
|
|
|
|
123
|
$ec and croak ($self->SetDiag ($ec)); |
353
|
|
|
|
|
|
|
|
354
|
9
|
|
|
|
|
33
|
$self->_cache_set ($_cache_id{'quote'}, $quote); |
355
|
|
|
|
|
|
|
} |
356
|
18
|
|
|
|
|
30
|
my $quote = $self->{'quote'}; |
357
|
18
|
100
|
100
|
|
|
136
|
defined $quote && length ($quote) ? $quote : $self->{'quote_char'}; |
358
|
|
|
|
|
|
|
} # quote |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
sub escape_char { |
361
|
4826
|
|
|
4826
|
1
|
652237
|
my $self = shift; |
362
|
4826
|
100
|
|
|
|
11190
|
if (@_) { |
363
|
3595
|
|
|
|
|
5321
|
my $ec = shift; |
364
|
3595
|
|
|
|
|
8297
|
$self->_set_attr_C ("escape_char", $ec); |
365
|
3480
|
100
|
|
|
|
6887
|
$ec or $self->_set_attr_X ("escape_null", 0); |
366
|
|
|
|
|
|
|
} |
367
|
4711
|
|
|
|
|
14632
|
$self->{'escape_char'}; |
368
|
|
|
|
|
|
|
} # escape_char |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
sub sep_char { |
371
|
5142
|
|
|
5142
|
1
|
644133
|
my $self = shift; |
372
|
5142
|
100
|
|
|
|
12512
|
if (@_) { |
373
|
3899
|
|
|
|
|
8580
|
$self->_set_attr_C ("sep_char", shift); |
374
|
3331
|
|
|
|
|
7516
|
$self->_cache_set ($_cache_id{'sep'}, ""); |
375
|
|
|
|
|
|
|
} |
376
|
4574
|
|
|
|
|
13976
|
$self->{'sep_char'}; |
377
|
|
|
|
|
|
|
} # sep_char |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
sub sep { |
380
|
346
|
|
|
346
|
1
|
3123
|
my $self = shift; |
381
|
346
|
100
|
|
|
|
735
|
if (@_) { |
382
|
313
|
|
|
|
|
539
|
my $sep = shift; |
383
|
313
|
100
|
|
|
|
606
|
defined $sep or $sep = ""; |
384
|
313
|
|
|
|
|
943
|
utf8::decode ($sep); |
385
|
313
|
|
|
|
|
1099
|
my @b = unpack "U0C*", $sep; |
386
|
313
|
100
|
|
|
|
733
|
if (@b > 1) { |
387
|
13
|
100
|
|
|
|
121
|
@b > 16 and croak ($self->SetDiag (1006)); |
388
|
12
|
|
|
|
|
33
|
$self->sep_char ("\0"); |
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
else { |
391
|
300
|
|
|
|
|
796
|
$self->sep_char ($sep); |
392
|
297
|
|
|
|
|
424
|
$sep = ""; |
393
|
|
|
|
|
|
|
} |
394
|
309
|
|
|
|
|
651
|
$self->{'sep'} = $sep; |
395
|
|
|
|
|
|
|
|
396
|
309
|
|
|
|
|
561
|
my $ec = _check_sanity ($self); |
397
|
309
|
100
|
|
|
|
643
|
$ec and croak ($self->SetDiag ($ec)); |
398
|
|
|
|
|
|
|
|
399
|
308
|
|
|
|
|
848
|
$self->_cache_set ($_cache_id{'sep'}, $sep); |
400
|
|
|
|
|
|
|
} |
401
|
341
|
|
|
|
|
626
|
my $sep = $self->{'sep'}; |
402
|
341
|
100
|
100
|
|
|
1376
|
defined $sep && length ($sep) ? $sep : $self->{'sep_char'}; |
403
|
|
|
|
|
|
|
} # sep |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
sub eol { |
406
|
157
|
|
|
157
|
1
|
6895
|
my $self = shift; |
407
|
157
|
100
|
|
|
|
383
|
if (@_) { |
408
|
125
|
|
|
|
|
229
|
my $eol = shift; |
409
|
125
|
100
|
|
|
|
285
|
defined $eol or $eol = ""; |
410
|
125
|
100
|
|
|
|
425
|
length ($eol) > 16 and croak ($self->SetDiag (1005)); |
411
|
124
|
|
|
|
|
230
|
$self->{'eol'} = $eol; |
412
|
124
|
|
|
|
|
445
|
$self->_cache_set ($_cache_id{'eol'}, $eol); |
413
|
|
|
|
|
|
|
} |
414
|
156
|
|
|
|
|
328
|
$self->{'eol'}; |
415
|
|
|
|
|
|
|
} # eol |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
sub always_quote { |
418
|
3032
|
|
|
3032
|
1
|
662820
|
my $self = shift; |
419
|
3032
|
100
|
|
|
|
8214
|
@_ and $self->_set_attr_X ("always_quote", shift); |
420
|
3032
|
|
|
|
|
8366
|
$self->{'always_quote'}; |
421
|
|
|
|
|
|
|
} # always_quote |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
sub quote_space { |
424
|
10
|
|
|
10
|
1
|
26
|
my $self = shift; |
425
|
10
|
100
|
|
|
|
52
|
@_ and $self->_set_attr_X ("quote_space", shift); |
426
|
10
|
|
|
|
|
44
|
$self->{'quote_space'}; |
427
|
|
|
|
|
|
|
} # quote_space |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
sub quote_empty { |
430
|
5
|
|
|
5
|
1
|
12
|
my $self = shift; |
431
|
5
|
100
|
|
|
|
22
|
@_ and $self->_set_attr_X ("quote_empty", shift); |
432
|
5
|
|
|
|
|
23
|
$self->{'quote_empty'}; |
433
|
|
|
|
|
|
|
} # quote_empty |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
sub escape_null { |
436
|
6
|
|
|
6
|
1
|
13
|
my $self = shift; |
437
|
6
|
100
|
|
|
|
23
|
@_ and $self->_set_attr_X ("escape_null", shift); |
438
|
6
|
|
|
|
|
30
|
$self->{'escape_null'}; |
439
|
|
|
|
|
|
|
} # escape_null |
440
|
3
|
|
|
3
|
1
|
12
|
sub quote_null { goto &escape_null; } |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
sub quote_binary { |
443
|
7
|
|
|
7
|
1
|
18
|
my $self = shift; |
444
|
7
|
100
|
|
|
|
42
|
@_ and $self->_set_attr_X ("quote_binary", shift); |
445
|
7
|
|
|
|
|
24
|
$self->{'quote_binary'}; |
446
|
|
|
|
|
|
|
} # quote_binary |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
sub binary { |
449
|
21
|
|
|
21
|
1
|
110781
|
my $self = shift; |
450
|
21
|
100
|
|
|
|
100
|
@_ and $self->_set_attr_X ("binary", shift); |
451
|
21
|
|
|
|
|
60
|
$self->{'binary'}; |
452
|
|
|
|
|
|
|
} # binary |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
sub strict { |
455
|
2
|
|
|
2
|
1
|
6
|
my $self = shift; |
456
|
2
|
100
|
|
|
|
8
|
@_ and $self->_set_attr_X ("strict", shift); |
457
|
2
|
|
|
|
|
8
|
$self->{'strict'}; |
458
|
|
|
|
|
|
|
} # always_quote |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
sub skip_empty_rows { |
461
|
2
|
|
|
2
|
1
|
4
|
my $self = shift; |
462
|
2
|
100
|
|
|
|
9
|
@_ and $self->_set_attr_X ("skip_empty_rows", shift); |
463
|
2
|
|
|
|
|
8
|
$self->{'skip_empty_rows'}; |
464
|
|
|
|
|
|
|
} # always_quote |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
sub _SetDiagInfo { |
467
|
17
|
|
|
17
|
|
40
|
my ($self, $err, $msg) = @_; |
468
|
17
|
|
|
|
|
138
|
$self->SetDiag ($err); |
469
|
17
|
|
|
|
|
42
|
my $em = $self->error_diag (); |
470
|
17
|
50
|
|
|
|
71
|
$em =~ s/^\d+$// and $msg =~ s/^/# /; |
471
|
17
|
50
|
|
|
|
61
|
my $sep = $em =~ m/[;\n]$/ ? "\n\t" : ": "; |
472
|
17
|
|
|
|
|
1755
|
join $sep => grep m/\S\S\S/ => $em, $msg; |
473
|
|
|
|
|
|
|
} # _SetDiagInfo |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
sub _supported_formula { |
476
|
103
|
|
|
103
|
|
184
|
my ($self, $f) = @_; |
477
|
103
|
100
|
|
|
|
186
|
defined $f or return 5; |
478
|
102
|
100
|
66
|
|
|
480
|
if ($self && $f && ref $f && ref $f eq "CODE") { |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
479
|
6
|
|
|
|
|
10
|
$self->{'_FORMULA_CB'} = $f; |
480
|
6
|
|
|
|
|
15
|
return 6; |
481
|
|
|
|
|
|
|
} |
482
|
|
|
|
|
|
|
$f =~ m/^(?: 0 | none )$/xi ? 0 : |
483
|
|
|
|
|
|
|
$f =~ m/^(?: 1 | die )$/xi ? 1 : |
484
|
|
|
|
|
|
|
$f =~ m/^(?: 2 | croak )$/xi ? 2 : |
485
|
|
|
|
|
|
|
$f =~ m/^(?: 3 | diag )$/xi ? 3 : |
486
|
|
|
|
|
|
|
$f =~ m/^(?: 4 | empty | )$/xi ? 4 : |
487
|
|
|
|
|
|
|
$f =~ m/^(?: 5 | undef )$/xi ? 5 : |
488
|
96
|
100
|
|
|
|
840
|
$f =~ m/^(?: 6 | cb )$/xi ? 6 : do { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
489
|
7
|
|
50
|
|
|
16
|
$self ||= "Text::CSV_XS"; |
490
|
7
|
|
|
|
|
30
|
croak ($self->_SetDiagInfo (1500, "formula-handling '$f' is not supported")); |
491
|
|
|
|
|
|
|
}; |
492
|
|
|
|
|
|
|
} # _supported_formula |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
sub formula { |
495
|
44
|
|
|
44
|
1
|
3152
|
my $self = shift; |
496
|
44
|
100
|
|
|
|
136
|
@_ and $self->_set_attr_N ("formula", _supported_formula ($self, shift)); |
497
|
38
|
100
|
|
|
|
115
|
$self->{'formula'} == 6 or $self->{'_FORMULA_CB'} = undef; |
498
|
38
|
|
|
|
|
126
|
[qw( none die croak diag empty undef cb )]->[_supported_formula ($self, $self->{'formula'})]; |
499
|
|
|
|
|
|
|
} # always_quote |
500
|
|
|
|
|
|
|
sub formula_handling { |
501
|
7
|
|
|
7
|
1
|
14
|
my $self = shift; |
502
|
7
|
|
|
|
|
18
|
$self->formula (@_); |
503
|
|
|
|
|
|
|
} # formula_handling |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
sub decode_utf8 { |
506
|
2
|
|
|
2
|
1
|
6
|
my $self = shift; |
507
|
2
|
100
|
|
|
|
9
|
@_ and $self->_set_attr_X ("decode_utf8", shift); |
508
|
2
|
|
|
|
|
9
|
$self->{'decode_utf8'}; |
509
|
|
|
|
|
|
|
} # decode_utf8 |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
sub keep_meta_info { |
512
|
12
|
|
|
12
|
1
|
917
|
my $self = shift; |
513
|
12
|
100
|
|
|
|
45
|
if (@_) { |
514
|
11
|
|
|
|
|
19
|
my $v = shift; |
515
|
11
|
100
|
100
|
|
|
67
|
!defined $v || $v eq "" and $v = 0; |
516
|
11
|
100
|
|
|
|
61
|
$v =~ m/^[0-9]/ or $v = lc $v eq "false" ? 0 : 1; # true/truth = 1 |
|
|
100
|
|
|
|
|
|
517
|
11
|
|
|
|
|
33
|
$self->_set_attr_X ("keep_meta_info", $v); |
518
|
|
|
|
|
|
|
} |
519
|
12
|
|
|
|
|
59
|
$self->{'keep_meta_info'}; |
520
|
|
|
|
|
|
|
} # keep_meta_info |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
sub allow_loose_quotes { |
523
|
12
|
|
|
12
|
1
|
27
|
my $self = shift; |
524
|
12
|
100
|
|
|
|
48
|
@_ and $self->_set_attr_X ("allow_loose_quotes", shift); |
525
|
12
|
|
|
|
|
29
|
$self->{'allow_loose_quotes'}; |
526
|
|
|
|
|
|
|
} # allow_loose_quotes |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
sub allow_loose_escapes { |
529
|
12
|
|
|
12
|
1
|
1107
|
my $self = shift; |
530
|
12
|
100
|
|
|
|
86
|
@_ and $self->_set_attr_X ("allow_loose_escapes", shift); |
531
|
12
|
|
|
|
|
45
|
$self->{'allow_loose_escapes'}; |
532
|
|
|
|
|
|
|
} # allow_loose_escapes |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
sub allow_whitespace { |
535
|
4954
|
|
|
4954
|
1
|
2218847
|
my $self = shift; |
536
|
4954
|
100
|
|
|
|
13299
|
if (@_) { |
537
|
3725
|
|
|
|
|
4975
|
my $aw = shift; |
538
|
3725
|
100
|
|
|
|
7364
|
_unhealthy_whitespace ($self, $aw) and |
539
|
|
|
|
|
|
|
croak ($self->SetDiag (1002)); |
540
|
3721
|
|
|
|
|
8658
|
$self->_set_attr_X ("allow_whitespace", $aw); |
541
|
|
|
|
|
|
|
} |
542
|
4950
|
|
|
|
|
15404
|
$self->{'allow_whitespace'}; |
543
|
|
|
|
|
|
|
} # allow_whitespace |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
sub allow_unquoted_escape { |
546
|
3
|
|
|
3
|
1
|
9
|
my $self = shift; |
547
|
3
|
100
|
|
|
|
15
|
@_ and $self->_set_attr_X ("allow_unquoted_escape", shift); |
548
|
3
|
|
|
|
|
19
|
$self->{'allow_unquoted_escape'}; |
549
|
|
|
|
|
|
|
} # allow_unquoted_escape |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
sub blank_is_undef { |
552
|
2
|
|
|
2
|
1
|
6
|
my $self = shift; |
553
|
2
|
100
|
|
|
|
9
|
@_ and $self->_set_attr_X ("blank_is_undef", shift); |
554
|
2
|
|
|
|
|
17
|
$self->{'blank_is_undef'}; |
555
|
|
|
|
|
|
|
} # blank_is_undef |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
sub empty_is_undef { |
558
|
2
|
|
|
2
|
1
|
5
|
my $self = shift; |
559
|
2
|
100
|
|
|
|
12
|
@_ and $self->_set_attr_X ("empty_is_undef", shift); |
560
|
2
|
|
|
|
|
12
|
$self->{'empty_is_undef'}; |
561
|
|
|
|
|
|
|
} # empty_is_undef |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
sub verbatim { |
564
|
9
|
|
|
9
|
1
|
10635
|
my $self = shift; |
565
|
9
|
100
|
|
|
|
44
|
@_ and $self->_set_attr_X ("verbatim", shift); |
566
|
9
|
|
|
|
|
29
|
$self->{'verbatim'}; |
567
|
|
|
|
|
|
|
} # verbatim |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
sub undef_str { |
570
|
12
|
|
|
12
|
1
|
3184
|
my $self = shift; |
571
|
12
|
100
|
|
|
|
62
|
if (@_) { |
572
|
11
|
|
|
|
|
20
|
my $v = shift; |
573
|
11
|
100
|
|
|
|
44
|
$self->{'undef_str'} = defined $v ? "$v" : undef; |
574
|
11
|
|
|
|
|
46
|
$self->_cache_set ($_cache_id{'undef_str'}, $self->{'undef_str'}); |
575
|
|
|
|
|
|
|
} |
576
|
12
|
|
|
|
|
56
|
$self->{'undef_str'}; |
577
|
|
|
|
|
|
|
} # undef_str |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
sub comment_str { |
580
|
15
|
|
|
15
|
1
|
60
|
my $self = shift; |
581
|
15
|
100
|
|
|
|
34
|
if (@_) { |
582
|
14
|
|
|
|
|
20
|
my $v = shift; |
583
|
14
|
100
|
|
|
|
50
|
$self->{'comment_str'} = defined $v ? "$v" : undef; |
584
|
14
|
|
|
|
|
51
|
$self->_cache_set ($_cache_id{'comment_str'}, $self->{'comment_str'}); |
585
|
|
|
|
|
|
|
} |
586
|
15
|
|
|
|
|
35
|
$self->{'comment_str'}; |
587
|
|
|
|
|
|
|
} # comment_str |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
sub auto_diag { |
590
|
12
|
|
|
12
|
1
|
364
|
my $self = shift; |
591
|
12
|
100
|
|
|
|
37
|
if (@_) { |
592
|
9
|
|
|
|
|
33
|
my $v = shift; |
593
|
9
|
100
|
100
|
|
|
68
|
!defined $v || $v eq "" and $v = 0; |
594
|
9
|
100
|
|
|
|
56
|
$v =~ m/^[0-9]/ or $v = lc $v eq "false" ? 0 : 1; # true/truth = 1 |
|
|
100
|
|
|
|
|
|
595
|
9
|
|
|
|
|
23
|
$self->_set_attr_X ("auto_diag", $v); |
596
|
|
|
|
|
|
|
} |
597
|
12
|
|
|
|
|
82
|
$self->{'auto_diag'}; |
598
|
|
|
|
|
|
|
} # auto_diag |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
sub diag_verbose { |
601
|
10
|
|
|
10
|
1
|
532
|
my $self = shift; |
602
|
10
|
100
|
|
|
|
35
|
if (@_) { |
603
|
8
|
|
|
|
|
12
|
my $v = shift; |
604
|
8
|
100
|
100
|
|
|
38
|
!defined $v || $v eq "" and $v = 0; |
605
|
8
|
100
|
|
|
|
39
|
$v =~ m/^[0-9]/ or $v = lc $v eq "false" ? 0 : 1; # true/truth = 1 |
|
|
100
|
|
|
|
|
|
606
|
8
|
|
|
|
|
20
|
$self->_set_attr_X ("diag_verbose", $v); |
607
|
|
|
|
|
|
|
} |
608
|
10
|
|
|
|
|
59
|
$self->{'diag_verbose'}; |
609
|
|
|
|
|
|
|
} # diag_verbose |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
# status |
612
|
|
|
|
|
|
|
# |
613
|
|
|
|
|
|
|
# object method returning the success or failure of the most recent |
614
|
|
|
|
|
|
|
# combine () or parse (). there are no side-effects. |
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
sub status { |
617
|
5
|
|
|
5
|
1
|
11
|
my $self = shift; |
618
|
5
|
|
|
|
|
26
|
return $self->{'_STATUS'}; |
619
|
|
|
|
|
|
|
} # status |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
sub eof { |
622
|
33
|
|
|
33
|
1
|
151231
|
my $self = shift; |
623
|
33
|
|
|
|
|
141
|
return $self->{'_EOF'}; |
624
|
|
|
|
|
|
|
} # status |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
sub types { |
627
|
7
|
|
|
7
|
1
|
1591
|
my $self = shift; |
628
|
7
|
100
|
|
|
|
15
|
if (@_) { |
629
|
2
|
100
|
|
|
|
6
|
if (my $types = shift) { |
630
|
1
|
|
|
|
|
9
|
$self->{'_types'} = join "", map { chr } @{$types}; |
|
3
|
|
|
|
|
11
|
|
|
1
|
|
|
|
|
4
|
|
631
|
1
|
|
|
|
|
3
|
$self->{'types'} = $types; |
632
|
1
|
|
|
|
|
7
|
$self->_cache_set ($_cache_id{'types'}, $self->{'_types'}); |
633
|
|
|
|
|
|
|
} |
634
|
|
|
|
|
|
|
else { |
635
|
1
|
|
|
|
|
2
|
delete $self->{'types'}; |
636
|
1
|
|
|
|
|
3
|
delete $self->{'_types'}; |
637
|
1
|
|
|
|
|
6
|
$self->_cache_set ($_cache_id{'types'}, undef); |
638
|
1
|
|
|
|
|
4
|
undef; |
639
|
|
|
|
|
|
|
} |
640
|
|
|
|
|
|
|
} |
641
|
|
|
|
|
|
|
else { |
642
|
5
|
|
|
|
|
22
|
$self->{'types'}; |
643
|
|
|
|
|
|
|
} |
644
|
|
|
|
|
|
|
} # types |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
sub callbacks { |
647
|
73
|
|
|
73
|
1
|
24075
|
my $self = shift; |
648
|
73
|
100
|
|
|
|
170
|
if (@_) { |
649
|
43
|
|
|
|
|
58
|
my $cb; |
650
|
43
|
|
|
|
|
68
|
my $hf = 0x00; |
651
|
43
|
100
|
|
|
|
92
|
if (defined $_[0]) { |
|
|
100
|
|
|
|
|
|
652
|
41
|
100
|
|
|
|
71
|
grep { !defined } @_ and croak ($self->SetDiag (1004)); |
|
73
|
|
|
|
|
397
|
|
653
|
39
|
100
|
100
|
|
|
990
|
$cb = @_ == 1 && ref $_[0] eq "HASH" ? shift |
|
|
100
|
|
|
|
|
|
654
|
|
|
|
|
|
|
: @_ % 2 == 0 ? { @_ } |
655
|
|
|
|
|
|
|
: croak ($self->SetDiag (1004)); |
656
|
34
|
|
|
|
|
53
|
foreach my $cbk (keys %{$cb}) { |
|
34
|
|
|
|
|
100
|
|
657
|
|
|
|
|
|
|
# A key cannot be a ref. That would be stored as the *string |
658
|
|
|
|
|
|
|
# 'SCALAR(0x1f3e710)' or 'ARRAY(0x1a5ae18)' |
659
|
36
|
100
|
100
|
|
|
1468
|
$cbk =~ m/^[\w.]+$/ && ref $cb->{$cbk} eq "CODE" or |
660
|
|
|
|
|
|
|
croak ($self->SetDiag (1004)); |
661
|
|
|
|
|
|
|
} |
662
|
20
|
100
|
|
|
|
51
|
exists $cb->{'error'} and $hf |= 0x01; |
663
|
20
|
100
|
|
|
|
45
|
exists $cb->{'after_parse'} and $hf |= 0x02; |
664
|
20
|
100
|
|
|
|
39
|
exists $cb->{'before_print'} and $hf |= 0x04; |
665
|
|
|
|
|
|
|
} |
666
|
|
|
|
|
|
|
elsif (@_ > 1) { |
667
|
|
|
|
|
|
|
# (undef, whatever) |
668
|
1
|
|
|
|
|
91
|
croak ($self->SetDiag (1004)); |
669
|
|
|
|
|
|
|
} |
670
|
21
|
|
|
|
|
56
|
$self->_set_attr_X ("_has_hooks", $hf); |
671
|
21
|
|
|
|
|
51
|
$self->{'callbacks'} = $cb; |
672
|
|
|
|
|
|
|
} |
673
|
51
|
|
|
|
|
140
|
$self->{'callbacks'}; |
674
|
|
|
|
|
|
|
} # callbacks |
675
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
# error_diag |
677
|
|
|
|
|
|
|
# |
678
|
|
|
|
|
|
|
# If (and only if) an error occurred, this function returns a code that |
679
|
|
|
|
|
|
|
# indicates the reason of failure |
680
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
sub error_diag { |
682
|
1710
|
|
|
1710
|
1
|
146306
|
my $self = shift; |
683
|
1710
|
|
|
|
|
4606
|
my @diag = (0 + $last_new_err, $last_new_err, 0, 0, 0); |
684
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
# Docs state to NEVER use UNIVERSAL::isa, because it will *never* call an |
686
|
|
|
|
|
|
|
# overridden isa method in any class. Well, that is exacly what I want here |
687
|
1710
|
100
|
100
|
|
|
14058
|
if ($self && ref $self and # Not a class method or direct call |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
688
|
|
|
|
|
|
|
UNIVERSAL::isa ($self, __PACKAGE__) && exists $self->{'_ERROR_DIAG'}) { |
689
|
1535
|
|
|
|
|
3029
|
$diag[0] = 0 + $self->{'_ERROR_DIAG'}; |
690
|
1535
|
|
|
|
|
2565
|
$diag[1] = $self->{'_ERROR_DIAG'}; |
691
|
1535
|
100
|
|
|
|
3134
|
$diag[2] = 1 + $self->{'_ERROR_POS'} if exists $self->{'_ERROR_POS'}; |
692
|
1535
|
|
|
|
|
2259
|
$diag[3] = $self->{'_RECNO'}; |
693
|
1535
|
100
|
|
|
|
2874
|
$diag[4] = $self->{'_ERROR_FLD'} if exists $self->{'_ERROR_FLD'}; |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
$diag[0] && $self->{'callbacks'} && $self->{'callbacks'}{'error'} and |
696
|
1535
|
100
|
100
|
|
|
6100
|
return $self->{'callbacks'}{'error'}->(@diag); |
|
|
|
100
|
|
|
|
|
697
|
|
|
|
|
|
|
} |
698
|
|
|
|
|
|
|
|
699
|
1701
|
|
|
|
|
3044
|
my $context = wantarray; |
700
|
1701
|
100
|
|
|
|
3340
|
unless (defined $context) { # Void context, auto-diag |
701
|
281
|
100
|
100
|
|
|
1307
|
if ($diag[0] && $diag[0] != 2012) { |
702
|
19
|
|
|
|
|
131
|
my $msg = "# CSV_XS ERROR: $diag[0] - $diag[1] \@ rec $diag[3] pos $diag[2]\n"; |
703
|
19
|
100
|
|
|
|
102
|
$diag[4] and $msg =~ s/$/ field $diag[4]/; |
704
|
|
|
|
|
|
|
|
705
|
19
|
100
|
100
|
|
|
88
|
unless ($self && ref $self) { # auto_diag |
706
|
|
|
|
|
|
|
# called without args in void context |
707
|
4
|
|
|
|
|
43
|
warn $msg; |
708
|
4
|
|
|
|
|
32
|
return; |
709
|
|
|
|
|
|
|
} |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
$self->{'diag_verbose'} && $self->{'_ERROR_INPUT'} and |
712
|
15
|
50
|
66
|
|
|
55
|
$msg .= $self->{'_ERROR_INPUT'}."\n". |
713
|
|
|
|
|
|
|
(" " x ($diag[2] - 1))."^\n"; |
714
|
|
|
|
|
|
|
|
715
|
15
|
|
|
|
|
29
|
my $lvl = $self->{'auto_diag'}; |
716
|
15
|
100
|
|
|
|
51
|
if ($lvl < 2) { |
717
|
12
|
|
|
|
|
77
|
my @c = caller (2); |
718
|
12
|
50
|
66
|
|
|
78
|
if (@c >= 11 && $c[10] && ref $c[10] eq "HASH") { |
|
|
|
33
|
|
|
|
|
719
|
0
|
|
|
|
|
0
|
my $hints = $c[10]; |
720
|
|
|
|
|
|
|
(exists $hints->{'autodie'} && $hints->{'autodie'} or |
721
|
|
|
|
|
|
|
exists $hints->{'guard Fatal'} && |
722
|
0
|
0
|
0
|
|
|
0
|
!exists $hints->{'no Fatal'}) and |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
723
|
|
|
|
|
|
|
$lvl++; |
724
|
|
|
|
|
|
|
# Future releases of autodie will probably set $^H{autodie} |
725
|
|
|
|
|
|
|
# to "autodie @args", like "autodie :all" or "autodie open" |
726
|
|
|
|
|
|
|
# so we can/should check for "open" or "new" |
727
|
|
|
|
|
|
|
} |
728
|
|
|
|
|
|
|
} |
729
|
15
|
100
|
|
|
|
142
|
$lvl > 1 ? die $msg : warn $msg; |
730
|
|
|
|
|
|
|
} |
731
|
274
|
|
|
|
|
2274
|
return; |
732
|
|
|
|
|
|
|
} |
733
|
1420
|
100
|
|
|
|
6009
|
return $context ? @diag : $diag[1]; |
734
|
|
|
|
|
|
|
} # error_diag |
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
sub record_number { |
737
|
3
|
|
|
3
|
1
|
5
|
my $self = shift; |
738
|
3
|
|
|
|
|
12
|
return $self->{'_RECNO'}; |
739
|
|
|
|
|
|
|
} # record_number |
740
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
# string |
742
|
|
|
|
|
|
|
# |
743
|
|
|
|
|
|
|
# object method returning the result of the most recent combine () or the |
744
|
|
|
|
|
|
|
# input to the most recent parse (), whichever is more recent. there are |
745
|
|
|
|
|
|
|
# no side-effects. |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
sub string { |
748
|
1398
|
|
|
1398
|
1
|
354949
|
my $self = shift; |
749
|
1398
|
100
|
|
|
|
4260
|
return ref $self->{'_STRING'} ? ${$self->{'_STRING'}} : undef; |
|
1397
|
|
|
|
|
5632
|
|
750
|
|
|
|
|
|
|
} # string |
751
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
# fields |
753
|
|
|
|
|
|
|
# |
754
|
|
|
|
|
|
|
# object method returning the result of the most recent parse () or the |
755
|
|
|
|
|
|
|
# input to the most recent combine (), whichever is more recent. there |
756
|
|
|
|
|
|
|
# are no side-effects. |
757
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
sub fields { |
759
|
1600
|
|
|
1600
|
1
|
19460
|
my $self = shift; |
760
|
1600
|
100
|
|
|
|
4290
|
return ref $self->{'_FIELDS'} ? @{$self->{'_FIELDS'}} : undef; |
|
1599
|
|
|
|
|
9815
|
|
761
|
|
|
|
|
|
|
} # fields |
762
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
# meta_info |
764
|
|
|
|
|
|
|
# |
765
|
|
|
|
|
|
|
# object method returning the result of the most recent parse () or the |
766
|
|
|
|
|
|
|
# input to the most recent combine (), whichever is more recent. there |
767
|
|
|
|
|
|
|
# are no side-effects. meta_info () returns (if available) some of the |
768
|
|
|
|
|
|
|
# field's properties |
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
sub meta_info { |
771
|
21
|
|
|
21
|
1
|
609
|
my $self = shift; |
772
|
21
|
100
|
|
|
|
65
|
return ref $self->{'_FFLAGS'} ? @{$self->{'_FFLAGS'}} : undef; |
|
16
|
|
|
|
|
72
|
|
773
|
|
|
|
|
|
|
} # meta_info |
774
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
sub is_quoted { |
776
|
12
|
|
|
12
|
1
|
18101
|
my ($self, $idx) = @_; |
777
|
|
|
|
|
|
|
ref $self->{'_FFLAGS'} && |
778
|
12
|
100
|
100
|
|
|
89
|
$idx >= 0 && $idx < @{$self->{'_FFLAGS'}} or return; |
|
8
|
|
100
|
|
|
31
|
|
779
|
7
|
100
|
|
|
|
28
|
$self->{'_FFLAGS'}[$idx] & CSV_FLAGS_IS_QUOTED () ? 1 : 0; |
780
|
|
|
|
|
|
|
} # is_quoted |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
sub is_binary { |
783
|
11
|
|
|
11
|
1
|
1029
|
my ($self, $idx) = @_; |
784
|
|
|
|
|
|
|
ref $self->{'_FFLAGS'} && |
785
|
11
|
100
|
100
|
|
|
74
|
$idx >= 0 && $idx < @{$self->{'_FFLAGS'}} or return; |
|
9
|
|
100
|
|
|
38
|
|
786
|
8
|
100
|
|
|
|
25
|
$self->{'_FFLAGS'}[$idx] & CSV_FLAGS_IS_BINARY () ? 1 : 0; |
787
|
|
|
|
|
|
|
} # is_binary |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
sub is_missing { |
790
|
19
|
|
|
19
|
1
|
44
|
my ($self, $idx) = @_; |
791
|
19
|
100
|
100
|
|
|
134
|
$idx < 0 || !ref $self->{'_FFLAGS'} and return; |
792
|
11
|
100
|
|
|
|
18
|
$idx >= @{$self->{'_FFLAGS'}} and return 1; |
|
11
|
|
|
|
|
33
|
|
793
|
10
|
100
|
|
|
|
24
|
$self->{'_FFLAGS'}[$idx] & CSV_FLAGS_IS_MISSING () ? 1 : 0; |
794
|
|
|
|
|
|
|
} # is_missing |
795
|
|
|
|
|
|
|
|
796
|
|
|
|
|
|
|
# combine |
797
|
|
|
|
|
|
|
# |
798
|
|
|
|
|
|
|
# Object method returning success or failure. The given arguments are |
799
|
|
|
|
|
|
|
# combined into a single comma-separated value. Failure can be the |
800
|
|
|
|
|
|
|
# result of no arguments or an argument containing an invalid character. |
801
|
|
|
|
|
|
|
# side-effects include: |
802
|
|
|
|
|
|
|
# setting status () |
803
|
|
|
|
|
|
|
# setting fields () |
804
|
|
|
|
|
|
|
# setting string () |
805
|
|
|
|
|
|
|
# setting error_input () |
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
sub combine { |
808
|
1397
|
|
|
1397
|
1
|
679872
|
my $self = shift; |
809
|
1397
|
|
|
|
|
2726
|
my $str = ""; |
810
|
1397
|
|
|
|
|
4615
|
$self->{'_FIELDS'} = \@_; |
811
|
1397
|
|
100
|
|
|
22344
|
$self->{'_STATUS'} = (@_ > 0) && $self->Combine (\$str, \@_, 0); |
812
|
1393
|
|
|
|
|
3469
|
$self->{'_STRING'} = \$str; |
813
|
1393
|
|
|
|
|
4709
|
$self->{'_STATUS'}; |
814
|
|
|
|
|
|
|
} # combine |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
# parse |
817
|
|
|
|
|
|
|
# |
818
|
|
|
|
|
|
|
# Object method returning success or failure. The given argument is |
819
|
|
|
|
|
|
|
# expected to be a valid comma-separated value. Failure can be the |
820
|
|
|
|
|
|
|
# result of no arguments or an argument containing an invalid sequence |
821
|
|
|
|
|
|
|
# of characters. Side-effects include: |
822
|
|
|
|
|
|
|
# setting status () |
823
|
|
|
|
|
|
|
# setting fields () |
824
|
|
|
|
|
|
|
# setting meta_info () |
825
|
|
|
|
|
|
|
# setting string () |
826
|
|
|
|
|
|
|
# setting error_input () |
827
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
sub parse { |
829
|
1938
|
|
|
1938
|
1
|
107057
|
my ($self, $str) = @_; |
830
|
|
|
|
|
|
|
|
831
|
1938
|
100
|
|
|
|
4730
|
ref $str and croak ($self->SetDiag (1500)); |
832
|
|
|
|
|
|
|
|
833
|
1934
|
|
|
|
|
3147
|
my $fields = []; |
834
|
1934
|
|
|
|
|
2955
|
my $fflags = []; |
835
|
1934
|
|
|
|
|
4191
|
$self->{'_STRING'} = \$str; |
836
|
1934
|
100
|
100
|
|
|
33663
|
if (defined $str && $self->Parse ($str, $fields, $fflags)) { |
837
|
1724
|
|
|
|
|
4544
|
$self->{'_FIELDS'} = $fields; |
838
|
1724
|
|
|
|
|
2522
|
$self->{'_FFLAGS'} = $fflags; |
839
|
1724
|
|
|
|
|
2794
|
$self->{'_STATUS'} = 1; |
840
|
|
|
|
|
|
|
} |
841
|
|
|
|
|
|
|
else { |
842
|
207
|
|
|
|
|
475
|
$self->{'_FIELDS'} = undef; |
843
|
207
|
|
|
|
|
301
|
$self->{'_FFLAGS'} = undef; |
844
|
207
|
|
|
|
|
303
|
$self->{'_STATUS'} = 0; |
845
|
|
|
|
|
|
|
} |
846
|
1931
|
|
|
|
|
7523
|
$self->{'_STATUS'}; |
847
|
|
|
|
|
|
|
} # parse |
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
sub column_names { |
850
|
982
|
|
|
982
|
1
|
72695
|
my ($self, @keys) = @_; |
851
|
|
|
|
|
|
|
@keys or |
852
|
982
|
100
|
|
|
|
2415
|
return defined $self->{'_COLUMN_NAMES'} ? @{$self->{'_COLUMN_NAMES'}} : (); |
|
282
|
100
|
|
|
|
1191
|
|
853
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
@keys == 1 && ! defined $keys[0] and |
855
|
657
|
100
|
100
|
|
|
2386
|
return $self->{'_COLUMN_NAMES'} = undef; |
856
|
|
|
|
|
|
|
|
857
|
519
|
100
|
100
|
|
|
1684
|
if (@keys == 1 && ref $keys[0] eq "ARRAY") { |
|
|
100
|
|
|
|
|
|
858
|
211
|
|
|
|
|
280
|
@keys = @{$keys[0]}; |
|
211
|
|
|
|
|
500
|
|
859
|
|
|
|
|
|
|
} |
860
|
655
|
100
|
|
|
|
2004
|
elsif (join "", map { defined $_ ? ref $_ : "" } @keys) { |
861
|
5
|
|
|
|
|
605
|
croak ($self->SetDiag (3001)); |
862
|
|
|
|
|
|
|
} |
863
|
|
|
|
|
|
|
|
864
|
514
|
100
|
100
|
|
|
1305
|
$self->{'_BOUND_COLUMNS'} && @keys != @{$self->{'_BOUND_COLUMNS'}} and |
|
2
|
|
|
|
|
97
|
|
865
|
|
|
|
|
|
|
croak ($self->SetDiag (3003)); |
866
|
|
|
|
|
|
|
|
867
|
513
|
100
|
|
|
|
842
|
$self->{'_COLUMN_NAMES'} = [ map { defined $_ ? $_ : "\cAUNDEF\cA" } @keys ]; |
|
1153
|
|
|
|
|
2911
|
|
868
|
513
|
|
|
|
|
796
|
@{$self->{'_COLUMN_NAMES'}}; |
|
513
|
|
|
|
|
1248
|
|
869
|
|
|
|
|
|
|
} # column_names |
870
|
|
|
|
|
|
|
|
871
|
|
|
|
|
|
|
sub header { |
872
|
320
|
|
|
320
|
1
|
39105
|
my ($self, $fh, @args) = @_; |
873
|
|
|
|
|
|
|
|
874
|
320
|
100
|
|
|
|
907
|
$fh or croak ($self->SetDiag (1014)); |
875
|
|
|
|
|
|
|
|
876
|
319
|
|
|
|
|
484
|
my (@seps, %args); |
877
|
319
|
|
|
|
|
647
|
for (@args) { |
878
|
212
|
100
|
|
|
|
472
|
if (ref $_ eq "ARRAY") { |
879
|
18
|
|
|
|
|
27
|
push @seps, @{$_}; |
|
18
|
|
|
|
|
48
|
|
880
|
18
|
|
|
|
|
37
|
next; |
881
|
|
|
|
|
|
|
} |
882
|
194
|
100
|
|
|
|
408
|
if (ref $_ eq "HASH") { |
883
|
193
|
|
|
|
|
242
|
%args = %{$_}; |
|
193
|
|
|
|
|
443
|
|
884
|
193
|
|
|
|
|
403
|
next; |
885
|
|
|
|
|
|
|
} |
886
|
1
|
|
|
|
|
87
|
croak ('usage: $csv->header ($fh, [ seps ], { options })'); |
887
|
|
|
|
|
|
|
} |
888
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
defined $args{'munge'} && !defined $args{'munge_column_names'} and |
890
|
318
|
100
|
66
|
|
|
779
|
$args{'munge_column_names'} = $args{'munge'}; # munge as alias |
891
|
318
|
100
|
|
|
|
780
|
defined $args{'detect_bom'} or $args{'detect_bom'} = 1; |
892
|
318
|
100
|
|
|
|
698
|
defined $args{'set_column_names'} or $args{'set_column_names'} = 1; |
893
|
318
|
100
|
|
|
|
690
|
defined $args{'munge_column_names'} or $args{'munge_column_names'} = "lc"; |
894
|
|
|
|
|
|
|
|
895
|
|
|
|
|
|
|
# Reset any previous leftovers |
896
|
318
|
|
|
|
|
498
|
$self->{'_RECNO'} = 0; |
897
|
318
|
|
|
|
|
461
|
$self->{'_AHEAD'} = undef; |
898
|
318
|
100
|
|
|
|
674
|
$self->{'_COLUMN_NAMES'} = undef if $args{'set_column_names'}; |
899
|
318
|
100
|
|
|
|
614
|
$self->{'_BOUND_COLUMNS'} = undef if $args{'set_column_names'}; |
900
|
|
|
|
|
|
|
|
901
|
318
|
100
|
|
|
|
631
|
if (defined $args{'sep_set'}) { |
902
|
27
|
100
|
|
|
|
72
|
ref $args{'sep_set'} eq "ARRAY" or |
903
|
|
|
|
|
|
|
croak ($self->_SetDiagInfo (1500, "sep_set should be an array ref")); |
904
|
22
|
|
|
|
|
33
|
@seps = @{$args{'sep_set'}}; |
|
22
|
|
|
|
|
46
|
|
905
|
|
|
|
|
|
|
} |
906
|
|
|
|
|
|
|
|
907
|
313
|
50
|
|
|
|
917
|
$^O eq "MSWin32" and binmode $fh; |
908
|
313
|
|
|
|
|
5346
|
my $hdr = <$fh>; |
909
|
|
|
|
|
|
|
# check if $hdr can be empty here, I don't think so |
910
|
313
|
100
|
66
|
|
|
2109
|
defined $hdr && $hdr ne "" or croak ($self->SetDiag (1010)); |
911
|
|
|
|
|
|
|
|
912
|
311
|
|
|
|
|
463
|
my %sep; |
913
|
311
|
100
|
|
|
|
961
|
@seps or @seps = (",", ";"); |
914
|
311
|
|
|
|
|
609
|
foreach my $sep (@seps) { |
915
|
706
|
100
|
|
|
|
2007
|
index ($hdr, $sep) >= 0 and $sep{$sep}++; |
916
|
|
|
|
|
|
|
} |
917
|
|
|
|
|
|
|
|
918
|
311
|
100
|
|
|
|
824
|
keys %sep >= 2 and croak ($self->SetDiag (1011)); |
919
|
|
|
|
|
|
|
|
920
|
307
|
|
|
|
|
1111
|
$self->sep (keys %sep); |
921
|
307
|
|
|
|
|
520
|
my $enc = ""; |
922
|
307
|
100
|
|
|
|
650
|
if ($args{'detect_bom'}) { # UTF-7 is not supported |
923
|
306
|
100
|
|
|
|
2670
|
if ($hdr =~ s/^\x00\x00\xfe\xff//) { $enc = "utf-32be" } |
|
24
|
100
|
|
|
|
50
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
924
|
24
|
|
|
|
|
49
|
elsif ($hdr =~ s/^\xff\xfe\x00\x00//) { $enc = "utf-32le" } |
925
|
25
|
|
|
|
|
58
|
elsif ($hdr =~ s/^\xfe\xff//) { $enc = "utf-16be" } |
926
|
24
|
|
|
|
|
69
|
elsif ($hdr =~ s/^\xff\xfe//) { $enc = "utf-16le" } |
927
|
48
|
|
|
|
|
87
|
elsif ($hdr =~ s/^\xef\xbb\xbf//) { $enc = "utf-8" } |
928
|
1
|
|
|
|
|
3
|
elsif ($hdr =~ s/^\xf7\x64\x4c//) { $enc = "utf-1" } |
929
|
1
|
|
|
|
|
3
|
elsif ($hdr =~ s/^\xdd\x73\x66\x73//) { $enc = "utf-ebcdic" } |
930
|
1
|
|
|
|
|
2
|
elsif ($hdr =~ s/^\x0e\xfe\xff//) { $enc = "scsu" } |
931
|
1
|
|
|
|
|
3
|
elsif ($hdr =~ s/^\xfb\xee\x28//) { $enc = "bocu-1" } |
932
|
1
|
|
|
|
|
3
|
elsif ($hdr =~ s/^\x84\x31\x95\x33//) { $enc = "gb-18030" } |
933
|
36
|
|
|
|
|
58
|
elsif ($hdr =~ s/^\x{feff}//) { $enc = "" } |
934
|
|
|
|
|
|
|
|
935
|
306
|
100
|
|
|
|
754
|
$self->{'ENCODING'} = $enc ? uc $enc : undef; |
936
|
|
|
|
|
|
|
|
937
|
306
|
100
|
|
|
|
1171
|
$hdr eq "" and croak ($self->SetDiag (1010)); |
938
|
|
|
|
|
|
|
|
939
|
300
|
100
|
|
|
|
566
|
if ($enc) { |
940
|
144
|
50
|
33
|
|
|
330
|
$ebcdic && $enc eq "utf-ebcdic" and $enc = ""; |
941
|
144
|
100
|
|
|
|
403
|
if ($enc =~ m/([13]).le$/) { |
942
|
48
|
|
|
|
|
184
|
my $l = 0 + $1; |
943
|
48
|
|
|
|
|
87
|
my $x; |
944
|
48
|
|
|
|
|
121
|
$hdr .= "\0" x $l; |
945
|
48
|
|
|
|
|
165
|
read $fh, $x, $l; |
946
|
|
|
|
|
|
|
} |
947
|
144
|
50
|
|
|
|
291
|
if ($enc) { |
948
|
144
|
100
|
|
|
|
288
|
if ($enc ne "utf-8") { |
949
|
96
|
|
|
|
|
580
|
require Encode; |
950
|
96
|
|
|
|
|
544
|
$hdr = Encode::decode ($enc, $hdr); |
951
|
|
|
|
|
|
|
} |
952
|
144
|
|
|
|
|
5509
|
binmode $fh, ":encoding($enc)"; |
953
|
|
|
|
|
|
|
} |
954
|
|
|
|
|
|
|
} |
955
|
|
|
|
|
|
|
} |
956
|
|
|
|
|
|
|
|
957
|
301
|
|
|
|
|
8428
|
my ($ahead, $eol); |
958
|
301
|
100
|
66
|
|
|
1569
|
if ($hdr and $hdr =~ s/\Asep=(\S)([\r\n]+)//i) { # Also look in xs:Parse |
959
|
1
|
|
|
|
|
9
|
$self->sep ($1); |
960
|
1
|
50
|
|
|
|
6
|
length $hdr or $hdr = <$fh>; |
961
|
|
|
|
|
|
|
} |
962
|
301
|
100
|
|
|
|
1973
|
if ($hdr =~ s/^([^\r\n]+)([\r\n]+)([^\r\n].+)\z/$1/s) { |
963
|
142
|
|
|
|
|
289
|
$eol = $2; |
964
|
142
|
|
|
|
|
317
|
$ahead = $3; |
965
|
|
|
|
|
|
|
} |
966
|
|
|
|
|
|
|
|
967
|
301
|
|
|
|
|
509
|
my $hr = \$hdr; # Will cause croak on perl-5.6.x |
968
|
301
|
50
|
|
|
|
3144
|
open my $h, "<", $hr or croak ($self->SetDiag (1010)); |
969
|
|
|
|
|
|
|
|
970
|
301
|
100
|
|
|
|
11644
|
my $row = $self->getline ($h) or croak (); |
971
|
299
|
|
|
|
|
12608
|
close $h; |
972
|
|
|
|
|
|
|
|
973
|
299
|
100
|
|
|
|
829
|
if ( $args{'munge_column_names'} eq "lc") { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
974
|
280
|
|
|
|
|
369
|
$_ = lc for @{$row}; |
|
280
|
|
|
|
|
978
|
|
975
|
|
|
|
|
|
|
} |
976
|
|
|
|
|
|
|
elsif ($args{'munge_column_names'} eq "uc") { |
977
|
7
|
|
|
|
|
15
|
$_ = uc for @{$row}; |
|
7
|
|
|
|
|
46
|
|
978
|
|
|
|
|
|
|
} |
979
|
|
|
|
|
|
|
elsif ($args{'munge_column_names'} eq "db") { |
980
|
3
|
|
|
|
|
9
|
for (@{$row}) { |
|
3
|
|
|
|
|
9
|
|
981
|
7
|
|
|
|
|
15
|
s/\W+/_/g; |
982
|
7
|
|
|
|
|
16
|
s/^_+//; |
983
|
7
|
|
|
|
|
14
|
$_ = lc; |
984
|
|
|
|
|
|
|
} |
985
|
|
|
|
|
|
|
} |
986
|
|
|
|
|
|
|
|
987
|
299
|
100
|
|
|
|
651
|
if ($ahead) { # Must be after getline, which creates the cache |
988
|
142
|
|
|
|
|
560
|
$self->_cache_set ($_cache_id{'_has_ahead'}, 1); |
989
|
142
|
|
|
|
|
231
|
$self->{'_AHEAD'} = $ahead; |
990
|
142
|
100
|
|
|
|
559
|
$eol =~ m/^\r([^\n]|\z)/ and $self->eol ($eol); |
991
|
|
|
|
|
|
|
} |
992
|
|
|
|
|
|
|
|
993
|
299
|
|
|
|
|
374
|
my @hdr = @{$row}; |
|
299
|
|
|
|
|
807
|
|
994
|
|
|
|
|
|
|
ref $args{'munge_column_names'} eq "CODE" and |
995
|
299
|
100
|
|
|
|
802
|
@hdr = map { $args{'munge_column_names'}->($_) } @hdr; |
|
4
|
|
|
|
|
19
|
|
996
|
|
|
|
|
|
|
ref $args{'munge_column_names'} eq "HASH" and |
997
|
299
|
100
|
|
|
|
582
|
@hdr = map { $args{'munge_column_names'}->{$_} || $_ } @hdr; |
|
3
|
100
|
|
|
|
16
|
|
998
|
299
|
|
|
|
|
416
|
my %hdr; $hdr{$_}++ for @hdr; |
|
299
|
|
|
|
|
1076
|
|
999
|
299
|
100
|
|
|
|
759
|
exists $hdr{""} and croak ($self->SetDiag (1012)); |
1000
|
297
|
100
|
|
|
|
792
|
unless (keys %hdr == @hdr) { |
1001
|
|
|
|
|
|
|
croak ($self->_SetDiagInfo (1013, join ", " => |
1002
|
1
|
|
|
|
|
7
|
map { "$_ ($hdr{$_})" } grep { $hdr{$_} > 1 } keys %hdr)); |
|
1
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
7
|
|
1003
|
|
|
|
|
|
|
} |
1004
|
296
|
100
|
|
|
|
970
|
$args{'set_column_names'} and $self->column_names (@hdr); |
1005
|
296
|
100
|
|
|
|
2488
|
wantarray ? @hdr : $self; |
1006
|
|
|
|
|
|
|
} # header |
1007
|
|
|
|
|
|
|
|
1008
|
|
|
|
|
|
|
sub bind_columns { |
1009
|
27
|
|
|
27
|
1
|
21233
|
my ($self, @refs) = @_; |
1010
|
|
|
|
|
|
|
@refs or |
1011
|
27
|
100
|
|
|
|
110
|
return defined $self->{'_BOUND_COLUMNS'} ? @{$self->{'_BOUND_COLUMNS'}} : undef; |
|
2
|
100
|
|
|
|
13
|
|
1012
|
|
|
|
|
|
|
|
1013
|
23
|
100
|
100
|
|
|
119
|
if (@refs == 1 && ! defined $refs[0]) { |
1014
|
5
|
|
|
|
|
14
|
$self->{'_COLUMN_NAMES'} = undef; |
1015
|
5
|
|
|
|
|
27
|
return $self->{'_BOUND_COLUMNS'} = undef; |
1016
|
|
|
|
|
|
|
} |
1017
|
|
|
|
|
|
|
|
1018
|
18
|
100
|
100
|
|
|
70
|
$self->{'_COLUMN_NAMES'} && @refs != @{$self->{'_COLUMN_NAMES'}} and |
|
3
|
|
|
|
|
449
|
|
1019
|
|
|
|
|
|
|
croak ($self->SetDiag (3003)); |
1020
|
|
|
|
|
|
|
|
1021
|
17
|
100
|
|
|
|
196
|
join "", map { ref $_ eq "SCALAR" ? "" : "*" } @refs and |
|
74606
|
100
|
|
|
|
139475
|
|
1022
|
|
|
|
|
|
|
croak ($self->SetDiag (3004)); |
1023
|
|
|
|
|
|
|
|
1024
|
15
|
|
|
|
|
3236
|
$self->_set_attr_N ("_is_bound", scalar @refs); |
1025
|
15
|
|
|
|
|
4261
|
$self->{'_BOUND_COLUMNS'} = [ @refs ]; |
1026
|
15
|
|
|
|
|
1403
|
@refs; |
1027
|
|
|
|
|
|
|
} # bind_columns |
1028
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
sub getline_hr { |
1030
|
119
|
|
|
119
|
1
|
11829
|
my ($self, @args, %hr) = @_; |
1031
|
119
|
100
|
|
|
|
430
|
$self->{'_COLUMN_NAMES'} or croak ($self->SetDiag (3002)); |
1032
|
118
|
100
|
|
|
|
2454
|
my $fr = $self->getline (@args) or return; |
1033
|
116
|
100
|
|
|
|
2278
|
if (ref $self->{'_FFLAGS'}) { # missing |
1034
|
|
|
|
|
|
|
$self->{'_FFLAGS'}[$_] = CSV_FLAGS_IS_MISSING () |
1035
|
5
|
50
|
|
|
|
12
|
for (@{$fr} ? $#{$fr} + 1 : 0) .. $#{$self->{'_COLUMN_NAMES'}}; |
|
5
|
|
|
|
|
14
|
|
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
22
|
|
1036
|
5
|
|
|
|
|
33
|
@{$fr} == 1 && (!defined $fr->[0] || $fr->[0] eq "") and |
1037
|
5
|
100
|
33
|
|
|
9
|
$self->{'_FFLAGS'}[0] ||= CSV_FLAGS_IS_MISSING (); |
|
|
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
1038
|
|
|
|
|
|
|
} |
1039
|
116
|
|
|
|
|
167
|
@hr{@{$self->{'_COLUMN_NAMES'}}} = @{$fr}; |
|
116
|
|
|
|
|
414
|
|
|
116
|
|
|
|
|
201
|
|
1040
|
116
|
|
|
|
|
560
|
\%hr; |
1041
|
|
|
|
|
|
|
} # getline_hr |
1042
|
|
|
|
|
|
|
|
1043
|
|
|
|
|
|
|
sub getline_hr_all { |
1044
|
235
|
|
|
235
|
1
|
439
|
my ($self, @args) = @_; |
1045
|
235
|
100
|
|
|
|
891
|
$self->{'_COLUMN_NAMES'} or croak ($self->SetDiag (3002)); |
1046
|
233
|
|
|
|
|
299
|
my @cn = @{$self->{'_COLUMN_NAMES'}}; |
|
233
|
|
|
|
|
512
|
|
1047
|
233
|
|
|
|
|
358
|
[ map { my %h; @h{@cn} = @{$_}; \%h } @{$self->getline_all (@args)} ]; |
|
338
|
|
|
|
|
3755
|
|
|
338
|
|
|
|
|
433
|
|
|
338
|
|
|
|
|
1176
|
|
|
338
|
|
|
|
|
1716
|
|
|
233
|
|
|
|
|
6456
|
|
1048
|
|
|
|
|
|
|
} # getline_hr_all |
1049
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
sub say { |
1051
|
13
|
|
|
13
|
1
|
2922
|
my ($self, $io, @f) = @_; |
1052
|
13
|
|
|
|
|
35
|
my $eol = $self->eol (); |
1053
|
13
|
100
|
33
|
|
|
93
|
$eol eq "" and $self->eol ($\ || $/); |
1054
|
|
|
|
|
|
|
# say ($fh, undef) does not propage actual undef to print () |
1055
|
13
|
100
|
66
|
|
|
200
|
my $state = $self->print ($io, @f == 1 && !defined $f[0] ? undef : @f); |
1056
|
13
|
|
|
|
|
148
|
$self->eol ($eol); |
1057
|
13
|
|
|
|
|
68
|
return $state; |
1058
|
|
|
|
|
|
|
} # say |
1059
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
sub print_hr { |
1061
|
3
|
|
|
3
|
1
|
308
|
my ($self, $io, $hr) = @_; |
1062
|
3
|
100
|
|
|
|
169
|
$self->{'_COLUMN_NAMES'} or croak ($self->SetDiag (3009)); |
1063
|
2
|
100
|
|
|
|
100
|
ref $hr eq "HASH" or croak ($self->SetDiag (3010)); |
1064
|
1
|
|
|
|
|
4
|
$self->print ($io, [ map { $hr->{$_} } $self->column_names () ]); |
|
3
|
|
|
|
|
15
|
|
1065
|
|
|
|
|
|
|
} # print_hr |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
sub fragment { |
1068
|
58
|
|
|
58
|
1
|
29070
|
my ($self, $io, $spec) = @_; |
1069
|
|
|
|
|
|
|
|
1070
|
58
|
|
|
|
|
211
|
my $qd = qr{\s* [0-9]+ \s* }x; # digit |
1071
|
58
|
|
|
|
|
136
|
my $qs = qr{\s* (?: [0-9]+ | \* ) \s*}x; # digit or star |
1072
|
58
|
|
|
|
|
381
|
my $qr = qr{$qd (?: - $qs )?}x; # range |
1073
|
58
|
|
|
|
|
304
|
my $qc = qr{$qr (?: ; $qr )*}x; # list |
1074
|
58
|
100
|
100
|
|
|
3416
|
defined $spec && $spec =~ m{^ \s* |
1075
|
|
|
|
|
|
|
\x23 ? \s* # optional leading # |
1076
|
|
|
|
|
|
|
( row | col | cell ) \s* = |
1077
|
|
|
|
|
|
|
( $qc # for row and col |
1078
|
|
|
|
|
|
|
| $qd , $qd (?: - $qs , $qs)? # for cell (ranges) |
1079
|
|
|
|
|
|
|
(?: ; $qd , $qd (?: - $qs , $qs)? )* # and cell (range) lists |
1080
|
|
|
|
|
|
|
) \s* $}xi or croak ($self->SetDiag (2013)); |
1081
|
38
|
|
|
|
|
179
|
my ($type, $range) = (lc $1, $2); |
1082
|
|
|
|
|
|
|
|
1083
|
38
|
|
|
|
|
102
|
my @h = $self->column_names (); |
1084
|
|
|
|
|
|
|
|
1085
|
38
|
|
|
|
|
69
|
my @c; |
1086
|
38
|
100
|
|
|
|
103
|
if ($type eq "cell") { |
1087
|
21
|
|
|
|
|
33
|
my @spec; |
1088
|
|
|
|
|
|
|
my $min_row; |
1089
|
21
|
|
|
|
|
29
|
my $max_row = 0; |
1090
|
21
|
|
|
|
|
104
|
for (split m/\s*;\s*/ => $range) { |
1091
|
37
|
100
|
|
|
|
315
|
my ($tlr, $tlc, $brr, $brc) = (m{ |
1092
|
|
|
|
|
|
|
^ \s* ([0-9]+ ) \s* , \s* ([0-9]+ ) \s* |
1093
|
|
|
|
|
|
|
(?: - \s* ([0-9]+ | \*) \s* , \s* ([0-9]+ | \*) \s* )? |
1094
|
|
|
|
|
|
|
$}x) or croak ($self->SetDiag (2013)); |
1095
|
36
|
100
|
|
|
|
95
|
defined $brr or ($brr, $brc) = ($tlr, $tlc); |
1096
|
36
|
100
|
100
|
|
|
1091
|
$tlr == 0 || $tlc == 0 || |
|
|
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
1097
|
|
|
|
|
|
|
($brr ne "*" && ($brr == 0 || $brr < $tlr)) || |
1098
|
|
|
|
|
|
|
($brc ne "*" && ($brc == 0 || $brc < $tlc)) |
1099
|
|
|
|
|
|
|
and croak ($self->SetDiag (2013)); |
1100
|
28
|
|
|
|
|
40
|
$tlc--; |
1101
|
28
|
100
|
|
|
|
55
|
$brc-- unless $brc eq "*"; |
1102
|
28
|
100
|
|
|
|
52
|
defined $min_row or $min_row = $tlr; |
1103
|
28
|
100
|
|
|
|
52
|
$tlr < $min_row and $min_row = $tlr; |
1104
|
28
|
100
|
100
|
|
|
92
|
$brr eq "*" || $brr > $max_row and |
1105
|
|
|
|
|
|
|
$max_row = $brr; |
1106
|
28
|
|
|
|
|
98
|
push @spec, [ $tlr, $tlc, $brr, $brc ]; |
1107
|
|
|
|
|
|
|
} |
1108
|
12
|
|
|
|
|
18
|
my $r = 0; |
1109
|
12
|
|
|
|
|
377
|
while (my $row = $self->getline ($io)) { |
1110
|
77
|
100
|
|
|
|
2883
|
++$r < $min_row and next; |
1111
|
33
|
|
|
|
|
53
|
my %row; |
1112
|
|
|
|
|
|
|
my $lc; |
1113
|
33
|
|
|
|
|
50
|
foreach my $s (@spec) { |
1114
|
77
|
|
|
|
|
103
|
my ($tlr, $tlc, $brr, $brc) = @{$s}; |
|
77
|
|
|
|
|
139
|
|
1115
|
77
|
100
|
100
|
|
|
280
|
$r < $tlr || ($brr ne "*" && $r > $brr) and next; |
|
|
|
100
|
|
|
|
|
1116
|
45
|
100
|
100
|
|
|
110
|
!defined $lc || $tlc < $lc and $lc = $tlc; |
1117
|
45
|
100
|
|
|
|
78
|
my $rr = $brc eq "*" ? $#{$row} : $brc; |
|
5
|
|
|
|
|
10
|
|
1118
|
45
|
|
|
|
|
231
|
$row{$_} = $row->[$_] for $tlc .. $rr; |
1119
|
|
|
|
|
|
|
} |
1120
|
33
|
|
|
|
|
115
|
push @c, [ @row{sort { $a <=> $b } keys %row } ]; |
|
59
|
|
|
|
|
161
|
|
1121
|
33
|
100
|
|
|
|
89
|
if (@h) { |
1122
|
2
|
|
|
|
|
3
|
my %h; @h{@h} = @{$c[-1]}; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
7
|
|
1123
|
2
|
|
|
|
|
5
|
$c[-1] = \%h; |
1124
|
|
|
|
|
|
|
} |
1125
|
33
|
100
|
100
|
|
|
571
|
$max_row ne "*" && $r == $max_row and last; |
1126
|
|
|
|
|
|
|
} |
1127
|
12
|
|
|
|
|
140
|
return \@c; |
1128
|
|
|
|
|
|
|
} |
1129
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
# row or col |
1131
|
17
|
|
|
|
|
23
|
my @r; |
1132
|
17
|
|
|
|
|
24
|
my $eod = 0; |
1133
|
17
|
|
|
|
|
74
|
for (split m/\s*;\s*/ => $range) { |
1134
|
25
|
50
|
|
|
|
138
|
my ($from, $to) = m/^\s* ([0-9]+) (?: \s* - \s* ([0-9]+ | \* ))? \s* $/x |
1135
|
|
|
|
|
|
|
or croak ($self->SetDiag (2013)); |
1136
|
25
|
|
100
|
|
|
105
|
$to ||= $from; |
1137
|
25
|
100
|
|
|
|
50
|
$to eq "*" and ($to, $eod) = ($from, 1); |
1138
|
|
|
|
|
|
|
# $to cannot be <= 0 due to regex and ||= |
1139
|
25
|
100
|
100
|
|
|
403
|
$from <= 0 || $to < $from and croak ($self->SetDiag (2013)); |
1140
|
22
|
|
|
|
|
85
|
$r[$_] = 1 for $from .. $to; |
1141
|
|
|
|
|
|
|
} |
1142
|
|
|
|
|
|
|
|
1143
|
14
|
|
|
|
|
33
|
my $r = 0; |
1144
|
14
|
100
|
|
|
|
35
|
$type eq "col" and shift @r; |
1145
|
14
|
|
100
|
|
|
146
|
$_ ||= 0 for @r; |
1146
|
14
|
|
|
|
|
505
|
while (my $row = $self->getline ($io)) { |
1147
|
109
|
|
|
|
|
3209
|
$r++; |
1148
|
109
|
100
|
|
|
|
207
|
if ($type eq "row") { |
1149
|
64
|
100
|
100
|
|
|
267
|
if (($r > $#r && $eod) || $r[$r]) { |
|
|
|
100
|
|
|
|
|
1150
|
20
|
|
|
|
|
34
|
push @c, $row; |
1151
|
20
|
100
|
|
|
|
43
|
if (@h) { |
1152
|
3
|
|
|
|
|
6
|
my %h; @h{@h} = @{$c[-1]}; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
14
|
|
1153
|
3
|
|
|
|
|
9
|
$c[-1] = \%h; |
1154
|
|
|
|
|
|
|
} |
1155
|
|
|
|
|
|
|
} |
1156
|
64
|
|
|
|
|
1247
|
next; |
1157
|
|
|
|
|
|
|
} |
1158
|
45
|
100
|
100
|
|
|
69
|
push @c, [ map { ($_ > $#r && $eod) || $r[$_] ? $row->[$_] : () } 0..$#{$row} ]; |
|
405
|
|
|
|
|
1413
|
|
|
45
|
|
|
|
|
80
|
|
1159
|
45
|
100
|
|
|
|
777
|
if (@h) { |
1160
|
9
|
|
|
|
|
13
|
my %h; @h{@h} = @{$c[-1]}; |
|
9
|
|
|
|
|
11
|
|
|
9
|
|
|
|
|
87
|
|
1161
|
9
|
|
|
|
|
193
|
$c[-1] = \%h; |
1162
|
|
|
|
|
|
|
} |
1163
|
|
|
|
|
|
|
} |
1164
|
|
|
|
|
|
|
|
1165
|
14
|
|
|
|
|
356
|
return \@c; |
1166
|
|
|
|
|
|
|
} # fragment |
1167
|
|
|
|
|
|
|
|
1168
|
|
|
|
|
|
|
my $csv_usage = q{usage: my $aoa = csv (in => $file);}; |
1169
|
|
|
|
|
|
|
|
1170
|
|
|
|
|
|
|
sub _csv_attr { |
1171
|
300
|
100
|
66
|
300
|
|
1618
|
my %attr = (@_ == 1 && ref $_[0] eq "HASH" ? %{$_[0]} : @_) or croak (); |
|
4
|
50
|
|
|
|
23
|
|
1172
|
|
|
|
|
|
|
|
1173
|
300
|
|
|
|
|
606
|
$attr{'binary'} = 1; |
1174
|
|
|
|
|
|
|
|
1175
|
300
|
|
100
|
|
|
1372
|
my $enc = delete $attr{'enc'} || delete $attr{'encoding'} || ""; |
1176
|
300
|
100
|
|
|
|
671
|
$enc eq "auto" and ($attr{'detect_bom'}, $enc) = (1, ""); |
1177
|
300
|
50
|
|
|
|
723
|
my $stack = $enc =~ s/(:\w.*)// ? $1 : ""; |
1178
|
300
|
100
|
|
|
|
613
|
$enc =~ m/^[-\w.]+$/ and $enc = ":encoding($enc)"; |
1179
|
300
|
|
|
|
|
557
|
$enc .= $stack; |
1180
|
|
|
|
|
|
|
|
1181
|
300
|
|
|
|
|
390
|
my $fh; |
1182
|
300
|
|
|
|
|
418
|
my $sink = 0; |
1183
|
300
|
|
|
|
|
416
|
my $cls = 0; # If I open a file, I have to close it |
1184
|
300
|
100
|
100
|
|
|
1351
|
my $in = delete $attr{'in'} || delete $attr{'file'} or croak ($csv_usage); |
1185
|
|
|
|
|
|
|
my $out = exists $attr{'out'} && !$attr{'out'} ? \"skip" |
1186
|
297
|
50
|
66
|
|
|
1256
|
: delete $attr{'out'} || delete $attr{'file'}; |
|
|
|
100
|
|
|
|
|
1187
|
|
|
|
|
|
|
|
1188
|
297
|
100
|
100
|
|
|
1010
|
ref $in eq "CODE" || ref $in eq "ARRAY" and $out ||= \*STDOUT; |
|
|
|
100
|
|
|
|
|
1189
|
|
|
|
|
|
|
|
1190
|
297
|
100
|
66
|
|
|
1163
|
$in && $out && !ref $in && !ref $out and croak (join "\n" => |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
1191
|
|
|
|
|
|
|
qq{Cannot use a string for both in and out. Instead use:}, |
1192
|
|
|
|
|
|
|
qq{ csv (in => csv (in => "$in"), out => "$out");\n}); |
1193
|
|
|
|
|
|
|
|
1194
|
296
|
100
|
|
|
|
545
|
if ($out) { |
1195
|
32
|
100
|
100
|
|
|
244
|
if (ref $out and ("ARRAY" eq ref $out or "HASH" eq ref $out)) { |
|
|
100
|
100
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
1196
|
5
|
|
|
|
|
10
|
delete $attr{'out'}; |
1197
|
5
|
|
|
|
|
6
|
$sink = 1; |
1198
|
|
|
|
|
|
|
} |
1199
|
|
|
|
|
|
|
elsif ((ref $out and "SCALAR" ne ref $out) or "GLOB" eq ref \$out) { |
1200
|
14
|
|
|
|
|
22
|
$fh = $out; |
1201
|
|
|
|
|
|
|
} |
1202
|
6
|
|
|
|
|
21
|
elsif (ref $out and "SCALAR" eq ref $out and defined ${$out} and ${$out} eq "skip") { |
|
6
|
|
|
|
|
18
|
|
1203
|
1
|
|
|
|
|
3
|
delete $attr{'out'}; |
1204
|
1
|
|
|
|
|
2
|
$sink = 1; |
1205
|
|
|
|
|
|
|
} |
1206
|
|
|
|
|
|
|
else { |
1207
|
12
|
100
|
|
|
|
623
|
open $fh, ">", $out or croak ("$out: $!"); |
1208
|
11
|
|
|
|
|
36
|
$cls = 1; |
1209
|
|
|
|
|
|
|
} |
1210
|
31
|
100
|
|
|
|
72
|
if ($fh) { |
1211
|
25
|
100
|
|
|
|
43
|
if ($enc) { |
1212
|
1
|
|
|
|
|
8
|
binmode $fh, $enc; |
1213
|
1
|
|
|
|
|
55
|
my $fn = fileno $fh; # This is a workaround for a bug in PerlIO::via::gzip |
1214
|
|
|
|
|
|
|
} |
1215
|
25
|
100
|
|
|
|
63
|
unless (defined $attr{'eol'}) { |
1216
|
18
|
|
|
|
|
47
|
my @layers = eval { PerlIO::get_layers ($fh) }; |
|
18
|
|
|
|
|
106
|
|
1217
|
18
|
100
|
|
|
|
112
|
$attr{'eol'} = (grep m/crlf/ => @layers) ? "\n" : "\r\n"; |
1218
|
|
|
|
|
|
|
} |
1219
|
|
|
|
|
|
|
} |
1220
|
|
|
|
|
|
|
} |
1221
|
|
|
|
|
|
|
|
1222
|
295
|
100
|
100
|
|
|
1602
|
if ( ref $in eq "CODE" or ref $in eq "ARRAY") { |
|
|
100
|
100
|
|
|
|
|
|
|
100
|
|
|
|
|
|
1223
|
|
|
|
|
|
|
# All done |
1224
|
|
|
|
|
|
|
} |
1225
|
|
|
|
|
|
|
elsif (ref $in eq "SCALAR") { |
1226
|
|
|
|
|
|
|
# Strings with code points over 0xFF may not be mapped into in-memory file handles |
1227
|
|
|
|
|
|
|
# "<$enc" does not change that :( |
1228
|
23
|
50
|
|
5
|
|
315
|
open $fh, "<", $in or croak ("Cannot open from SCALAR using PerlIO"); |
|
5
|
|
|
|
|
46
|
|
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
38
|
|
1229
|
23
|
|
|
|
|
1853
|
$cls = 1; |
1230
|
|
|
|
|
|
|
} |
1231
|
|
|
|
|
|
|
elsif (ref $in or "GLOB" eq ref \$in) { |
1232
|
16
|
50
|
66
|
|
|
47
|
if (!ref $in && $] < 5.008005) { |
1233
|
0
|
|
|
|
|
0
|
$fh = \*{$in}; # uncoverable statement ancient perl version required |
|
0
|
|
|
|
|
0
|
|
1234
|
|
|
|
|
|
|
} |
1235
|
|
|
|
|
|
|
else { |
1236
|
16
|
|
|
|
|
28
|
$fh = $in; |
1237
|
|
|
|
|
|
|
} |
1238
|
|
|
|
|
|
|
} |
1239
|
|
|
|
|
|
|
else { |
1240
|
232
|
100
|
|
|
|
8988
|
open $fh, "<$enc", $in or croak ("$in: $!"); |
1241
|
230
|
|
|
|
|
17629
|
$cls = 1; |
1242
|
|
|
|
|
|
|
} |
1243
|
293
|
50
|
33
|
|
|
780
|
$fh || $sink or croak (qq{No valid source passed. "in" is required}); |
1244
|
|
|
|
|
|
|
|
1245
|
293
|
|
|
|
|
538
|
my $hdrs = delete $attr{'headers'}; |
1246
|
293
|
|
|
|
|
467
|
my $frag = delete $attr{'fragment'}; |
1247
|
293
|
|
|
|
|
471
|
my $key = delete $attr{'key'}; |
1248
|
293
|
|
|
|
|
428
|
my $val = delete $attr{'value'}; |
1249
|
|
|
|
|
|
|
my $kh = delete $attr{'keep_headers'} || |
1250
|
|
|
|
|
|
|
delete $attr{'keep_column_names'} || |
1251
|
293
|
|
100
|
|
|
1283
|
delete $attr{'kh'}; |
1252
|
|
|
|
|
|
|
|
1253
|
|
|
|
|
|
|
my $cbai = delete $attr{'callbacks'}{'after_in'} || |
1254
|
|
|
|
|
|
|
delete $attr{'after_in'} || |
1255
|
|
|
|
|
|
|
delete $attr{'callbacks'}{'after_parse'} || |
1256
|
293
|
|
100
|
|
|
1784
|
delete $attr{'after_parse'}; |
1257
|
|
|
|
|
|
|
my $cbbo = delete $attr{'callbacks'}{'before_out'} || |
1258
|
293
|
|
100
|
|
|
861
|
delete $attr{'before_out'}; |
1259
|
|
|
|
|
|
|
my $cboi = delete $attr{'callbacks'}{'on_in'} || |
1260
|
293
|
|
100
|
|
|
756
|
delete $attr{'on_in'}; |
1261
|
|
|
|
|
|
|
|
1262
|
|
|
|
|
|
|
my $hd_s = delete $attr{'sep_set'} || |
1263
|
293
|
|
100
|
|
|
742
|
delete $attr{'seps'}; |
1264
|
|
|
|
|
|
|
my $hd_b = delete $attr{'detect_bom'} || |
1265
|
293
|
|
100
|
|
|
847
|
delete $attr{'bom'}; |
1266
|
|
|
|
|
|
|
my $hd_m = delete $attr{'munge'} || |
1267
|
293
|
|
100
|
|
|
796
|
delete $attr{'munge_column_names'}; |
1268
|
293
|
|
|
|
|
422
|
my $hd_c = delete $attr{'set_column_names'}; |
1269
|
|
|
|
|
|
|
|
1270
|
293
|
|
|
|
|
1037
|
for ([ 'quo' => "quote" ], |
1271
|
|
|
|
|
|
|
[ 'esc' => "escape" ], |
1272
|
|
|
|
|
|
|
[ 'escape' => "escape_char" ], |
1273
|
|
|
|
|
|
|
) { |
1274
|
879
|
|
|
|
|
1146
|
my ($f, $t) = @{$_}; |
|
879
|
|
|
|
|
1550
|
|
1275
|
879
|
100
|
100
|
|
|
2118
|
exists $attr{$f} and !exists $attr{$t} and $attr{$t} = delete $attr{$f}; |
1276
|
|
|
|
|
|
|
} |
1277
|
|
|
|
|
|
|
|
1278
|
293
|
|
|
|
|
687
|
my $fltr = delete $attr{'filter'}; |
1279
|
|
|
|
|
|
|
my %fltr = ( |
1280
|
10
|
100
|
33
|
10
|
|
13
|
'not_blank' => sub { @{$_[1]} > 1 or defined $_[1][0] && $_[1][0] ne "" }, |
|
10
|
|
|
|
|
75
|
|
1281
|
10
|
50
|
|
10
|
|
12
|
'not_empty' => sub { grep { defined && $_ ne "" } @{$_[1]} }, |
|
26
|
|
|
|
|
178
|
|
|
10
|
|
|
|
|
18
|
|
1282
|
10
|
50
|
|
10
|
|
13
|
'filled' => sub { grep { defined && m/\S/ } @{$_[1]} }, |
|
26
|
|
|
|
|
244
|
|
|
10
|
|
|
|
|
20
|
|
1283
|
293
|
|
|
|
|
2008
|
); |
1284
|
|
|
|
|
|
|
defined $fltr && !ref $fltr && exists $fltr{$fltr} and |
1285
|
293
|
50
|
100
|
|
|
814
|
$fltr = { '0' => $fltr{$fltr} }; |
|
|
|
66
|
|
|
|
|
1286
|
293
|
100
|
|
|
|
670
|
ref $fltr eq "CODE" and $fltr = { 0 => $fltr }; |
1287
|
293
|
100
|
|
|
|
587
|
ref $fltr eq "HASH" or $fltr = undef; |
1288
|
|
|
|
|
|
|
|
1289
|
293
|
|
|
|
|
451
|
my $form = delete $attr{'formula'}; |
1290
|
|
|
|
|
|
|
|
1291
|
293
|
100
|
|
|
|
712
|
defined $attr{'auto_diag'} or $attr{'auto_diag'} = 1; |
1292
|
293
|
100
|
|
|
|
638
|
defined $attr{'escape_null'} or $attr{'escape_null'} = 0; |
1293
|
293
|
50
|
66
|
|
|
1429
|
my $csv = delete $attr{'csv'} || Text::CSV_XS->new (\%attr) |
1294
|
|
|
|
|
|
|
or croak ($last_new_err); |
1295
|
293
|
100
|
|
|
|
600
|
defined $form and $csv->formula ($form); |
1296
|
|
|
|
|
|
|
|
1297
|
293
|
100
|
100
|
|
|
759
|
$kh && !ref $kh && $kh =~ m/^(?:1|yes|true|internal|auto)$/i and |
|
|
|
100
|
|
|
|
|
1298
|
|
|
|
|
|
|
$kh = \@internal_kh; |
1299
|
|
|
|
|
|
|
|
1300
|
|
|
|
|
|
|
return { |
1301
|
293
|
|
|
|
|
5126
|
'csv' => $csv, |
1302
|
|
|
|
|
|
|
'attr' => { %attr }, |
1303
|
|
|
|
|
|
|
'fh' => $fh, |
1304
|
|
|
|
|
|
|
'cls' => $cls, |
1305
|
|
|
|
|
|
|
'in' => $in, |
1306
|
|
|
|
|
|
|
'sink' => $sink, |
1307
|
|
|
|
|
|
|
'out' => $out, |
1308
|
|
|
|
|
|
|
'enc' => $enc, |
1309
|
|
|
|
|
|
|
'hdrs' => $hdrs, |
1310
|
|
|
|
|
|
|
'key' => $key, |
1311
|
|
|
|
|
|
|
'val' => $val, |
1312
|
|
|
|
|
|
|
'kh' => $kh, |
1313
|
|
|
|
|
|
|
'frag' => $frag, |
1314
|
|
|
|
|
|
|
'fltr' => $fltr, |
1315
|
|
|
|
|
|
|
'cbai' => $cbai, |
1316
|
|
|
|
|
|
|
'cbbo' => $cbbo, |
1317
|
|
|
|
|
|
|
'cboi' => $cboi, |
1318
|
|
|
|
|
|
|
'hd_s' => $hd_s, |
1319
|
|
|
|
|
|
|
'hd_b' => $hd_b, |
1320
|
|
|
|
|
|
|
'hd_m' => $hd_m, |
1321
|
|
|
|
|
|
|
'hd_c' => $hd_c, |
1322
|
|
|
|
|
|
|
}; |
1323
|
|
|
|
|
|
|
} # _csv_attr |
1324
|
|
|
|
|
|
|
|
1325
|
|
|
|
|
|
|
sub csv { |
1326
|
301
|
100
|
100
|
301
|
1
|
67746
|
@_ && ref $_[0] eq __PACKAGE__ and splice @_, 0, 0, "csv"; |
1327
|
301
|
100
|
|
|
|
787
|
@_ or croak ($csv_usage); |
1328
|
|
|
|
|
|
|
|
1329
|
300
|
|
|
|
|
726
|
my $c = _csv_attr (@_); |
1330
|
|
|
|
|
|
|
|
1331
|
293
|
|
|
|
|
580
|
my ($csv, $in, $fh, $hdrs) = @{$c}{qw( csv in fh hdrs )}; |
|
293
|
|
|
|
|
833
|
|
1332
|
293
|
|
|
|
|
420
|
my %hdr; |
1333
|
293
|
100
|
|
|
|
623
|
if (ref $hdrs eq "HASH") { |
1334
|
2
|
|
|
|
|
7
|
%hdr = %{$hdrs}; |
|
2
|
|
|
|
|
7
|
|
1335
|
2
|
|
|
|
|
5
|
$hdrs = "auto"; |
1336
|
|
|
|
|
|
|
} |
1337
|
|
|
|
|
|
|
|
1338
|
293
|
100
|
100
|
|
|
688
|
if ($c->{'out'} && !$c->{'sink'}) { |
1339
|
|
|
|
|
|
|
!$hdrs && ref $c->{'kh'} && $c->{'kh'} == \@internal_kh and |
1340
|
24
|
100
|
100
|
|
|
86
|
$hdrs = $c->{'kh'}; |
|
|
|
66
|
|
|
|
|
1341
|
|
|
|
|
|
|
|
1342
|
24
|
100
|
100
|
|
|
54
|
if (ref $in eq "CODE") { |
|
|
100
|
|
|
|
|
|
1343
|
3
|
|
|
|
|
7
|
my $hdr = 1; |
1344
|
3
|
|
|
|
|
11
|
while (my $row = $in->($csv)) { |
1345
|
7
|
100
|
|
|
|
52
|
if (ref $row eq "ARRAY") { |
1346
|
3
|
|
|
|
|
29
|
$csv->print ($fh, $row); |
1347
|
3
|
|
|
|
|
26
|
next; |
1348
|
|
|
|
|
|
|
} |
1349
|
4
|
50
|
|
|
|
23
|
if (ref $row eq "HASH") { |
1350
|
4
|
100
|
|
|
|
12
|
if ($hdr) { |
1351
|
2
|
50
|
100
|
|
|
6
|
$hdrs ||= [ map { $hdr{$_} || $_ } keys %{$row} ]; |
|
3
|
|
|
|
|
13
|
|
|
1
|
|
|
|
|
4
|
|
1352
|
2
|
|
|
|
|
37
|
$csv->print ($fh, $hdrs); |
1353
|
2
|
|
|
|
|
38
|
$hdr = 0; |
1354
|
|
|
|
|
|
|
} |
1355
|
4
|
|
|
|
|
6
|
$csv->print ($fh, [ @{$row}{@{$hdrs}} ]); |
|
4
|
|
|
|
|
24
|
|
|
4
|
|
|
|
|
8
|
|
1356
|
|
|
|
|
|
|
} |
1357
|
|
|
|
|
|
|
} |
1358
|
|
|
|
|
|
|
} |
1359
|
21
|
|
|
|
|
84
|
elsif (@{$in} == 0 or ref $in->[0] eq "ARRAY") { # aoa |
1360
|
10
|
50
|
|
|
|
22
|
ref $hdrs and $csv->print ($fh, $hdrs); |
1361
|
10
|
|
|
|
|
14
|
for (@{$in}) { |
|
10
|
|
|
|
|
21
|
|
1362
|
12
|
100
|
|
|
|
68
|
$c->{'cboi'} and $c->{'cboi'}->($csv, $_); |
1363
|
12
|
50
|
|
|
|
1086
|
$c->{'cbbo'} and $c->{'cbbo'}->($csv, $_); |
1364
|
12
|
|
|
|
|
191
|
$csv->print ($fh, $_); |
1365
|
|
|
|
|
|
|
} |
1366
|
|
|
|
|
|
|
} |
1367
|
|
|
|
|
|
|
else { # aoh |
1368
|
11
|
100
|
|
|
|
26
|
my @hdrs = ref $hdrs ? @{$hdrs} : keys %{$in->[0]}; |
|
5
|
|
|
|
|
12
|
|
|
6
|
|
|
|
|
19
|
|
1369
|
11
|
100
|
|
|
|
27
|
defined $hdrs or $hdrs = "auto"; |
1370
|
|
|
|
|
|
|
ref $hdrs || $hdrs eq "auto" and @hdrs and |
1371
|
11
|
100
|
100
|
|
|
50
|
$csv->print ($fh, [ map { $hdr{$_} || $_ } @hdrs ]); |
|
20
|
100
|
66
|
|
|
250
|
|
1372
|
11
|
|
|
|
|
119
|
for (@{$in}) { |
|
11
|
|
|
|
|
28
|
|
1373
|
17
|
|
|
|
|
82
|
local %_; |
1374
|
17
|
|
|
|
|
36
|
*_ = $_; |
1375
|
17
|
50
|
|
|
|
39
|
$c->{'cboi'} and $c->{'cboi'}->($csv, $_); |
1376
|
17
|
50
|
|
|
|
33
|
$c->{'cbbo'} and $c->{'cbbo'}->($csv, $_); |
1377
|
17
|
|
|
|
|
29
|
$csv->print ($fh, [ @{$_}{@hdrs} ]); |
|
17
|
|
|
|
|
107
|
|
1378
|
|
|
|
|
|
|
} |
1379
|
|
|
|
|
|
|
} |
1380
|
|
|
|
|
|
|
|
1381
|
24
|
100
|
|
|
|
771
|
$c->{'cls'} and close $fh; |
1382
|
24
|
|
|
|
|
307
|
return 1; |
1383
|
|
|
|
|
|
|
} |
1384
|
|
|
|
|
|
|
|
1385
|
269
|
|
|
|
|
367
|
my @row1; |
1386
|
269
|
100
|
100
|
|
|
1398
|
if (defined $c->{'hd_s'} || defined $c->{'hd_b'} || defined $c->{'hd_m'} || defined $c->{'hd_c'}) { |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
1387
|
163
|
|
|
|
|
236
|
my %harg; |
1388
|
|
|
|
|
|
|
!defined $c->{'hd_s'} && $c->{'attr'}{'sep_char'} and |
1389
|
163
|
100
|
100
|
|
|
570
|
$c->{'hd_s'} = [ $c->{'attr'}{'sep_char'} ]; |
1390
|
|
|
|
|
|
|
!defined $c->{'hd_s'} && $c->{'attr'}{'sep'} and |
1391
|
163
|
100
|
100
|
|
|
585
|
$c->{'hd_s'} = [ $c->{'attr'}{'sep'} ]; |
1392
|
163
|
100
|
|
|
|
303
|
defined $c->{'hd_s'} and $harg{'sep_set'} = $c->{'hd_s'}; |
1393
|
163
|
50
|
|
|
|
315
|
defined $c->{'hd_d'} and $harg{'detect_bom'} = $c->{'hd_b'}; |
1394
|
163
|
50
|
|
|
|
303
|
defined $c->{'hd_m'} and $harg{'munge_column_names'} = $hdrs ? "none" : $c->{'hd_m'}; |
|
|
100
|
|
|
|
|
|
1395
|
163
|
50
|
|
|
|
311
|
defined $c->{'hd_c'} and $harg{'set_column_names'} = $hdrs ? 0 : $c->{'hd_c'}; |
|
|
100
|
|
|
|
|
|
1396
|
163
|
|
|
|
|
393
|
@row1 = $csv->header ($fh, \%harg); |
1397
|
160
|
|
|
|
|
396
|
my @hdr = $csv->column_names (); |
1398
|
160
|
100
|
50
|
|
|
791
|
@hdr and $hdrs ||= \@hdr; |
1399
|
|
|
|
|
|
|
} |
1400
|
|
|
|
|
|
|
|
1401
|
266
|
100
|
|
|
|
668
|
if ($c->{'kh'}) { |
1402
|
15
|
|
|
|
|
28
|
@internal_kh = (); |
1403
|
15
|
100
|
|
|
|
711
|
ref $c->{'kh'} eq "ARRAY" or croak ($csv->SetDiag (1501)); |
1404
|
10
|
|
100
|
|
|
27
|
$hdrs ||= "auto"; |
1405
|
|
|
|
|
|
|
} |
1406
|
|
|
|
|
|
|
|
1407
|
261
|
|
|
|
|
453
|
my $key = $c->{'key'}; |
1408
|
261
|
100
|
|
|
|
486
|
if ($key) { |
1409
|
27
|
100
|
100
|
|
|
550
|
!ref $key or ref $key eq "ARRAY" && @{$key} > 1 or croak ($csv->SetDiag (1501)); |
|
8
|
|
100
|
|
|
436
|
|
1410
|
20
|
|
100
|
|
|
56
|
$hdrs ||= "auto"; |
1411
|
|
|
|
|
|
|
} |
1412
|
254
|
|
|
|
|
446
|
my $val = $c->{'val'}; |
1413
|
254
|
100
|
|
|
|
479
|
if ($val) { |
1414
|
9
|
100
|
|
|
|
134
|
$key or croak ($csv->SetDiag (1502)); |
1415
|
8
|
100
|
100
|
|
|
263
|
!ref $val or ref $val eq "ARRAY" && @{$val} > 0 or croak ($csv->SetDiag (1503)); |
|
3
|
|
100
|
|
|
118
|
|
1416
|
|
|
|
|
|
|
} |
1417
|
|
|
|
|
|
|
|
1418
|
250
|
100
|
100
|
|
|
519
|
$c->{'fltr'} && grep m/\D/ => keys %{$c->{'fltr'}} and $hdrs ||= "auto"; |
|
16
|
|
100
|
|
|
107
|
|
1419
|
250
|
100
|
|
|
|
470
|
if (defined $hdrs) { |
1420
|
208
|
100
|
|
|
|
584
|
if (!ref $hdrs) { |
|
|
100
|
|
|
|
|
|
1421
|
45
|
100
|
|
|
|
108
|
if ($hdrs eq "skip") { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1422
|
1
|
|
|
|
|
40
|
$csv->getline ($fh); # discard; |
1423
|
|
|
|
|
|
|
} |
1424
|
|
|
|
|
|
|
elsif ($hdrs eq "auto") { |
1425
|
42
|
50
|
|
|
|
1624
|
my $h = $csv->getline ($fh) or return; |
1426
|
42
|
100
|
|
|
|
2138
|
$hdrs = [ map { $hdr{$_} || $_ } @{$h} ]; |
|
122
|
|
|
|
|
502
|
|
|
42
|
|
|
|
|
91
|
|
1427
|
|
|
|
|
|
|
} |
1428
|
|
|
|
|
|
|
elsif ($hdrs eq "lc") { |
1429
|
1
|
50
|
|
|
|
39
|
my $h = $csv->getline ($fh) or return; |
1430
|
1
|
|
33
|
|
|
57
|
$hdrs = [ map { lc ($hdr{$_} || $_) } @{$h} ]; |
|
3
|
|
|
|
|
14
|
|
|
1
|
|
|
|
|
3
|
|
1431
|
|
|
|
|
|
|
} |
1432
|
|
|
|
|
|
|
elsif ($hdrs eq "uc") { |
1433
|
1
|
50
|
|
|
|
39
|
my $h = $csv->getline ($fh) or return; |
1434
|
1
|
|
33
|
|
|
61
|
$hdrs = [ map { uc ($hdr{$_} || $_) } @{$h} ]; |
|
3
|
|
|
|
|
14
|
|
|
1
|
|
|
|
|
4
|
|
1435
|
|
|
|
|
|
|
} |
1436
|
|
|
|
|
|
|
} |
1437
|
|
|
|
|
|
|
elsif (ref $hdrs eq "CODE") { |
1438
|
1
|
50
|
|
|
|
40
|
my $h = $csv->getline ($fh) or return; |
1439
|
1
|
|
|
|
|
47
|
my $cr = $hdrs; |
1440
|
1
|
|
33
|
|
|
2
|
$hdrs = [ map { $cr->($hdr{$_} || $_) } @{$h} ]; |
|
3
|
|
|
|
|
20
|
|
|
1
|
|
|
|
|
3
|
|
1441
|
|
|
|
|
|
|
} |
1442
|
208
|
100
|
66
|
|
|
580
|
$c->{'kh'} and $hdrs and @{$c->{'kh'}} = @{$hdrs}; |
|
10
|
|
|
|
|
28
|
|
|
10
|
|
|
|
|
19
|
|
1443
|
|
|
|
|
|
|
} |
1444
|
|
|
|
|
|
|
|
1445
|
250
|
100
|
|
|
|
457
|
if ($c->{'fltr'}) { |
1446
|
16
|
|
|
|
|
28
|
my %f = %{$c->{'fltr'}}; |
|
16
|
|
|
|
|
48
|
|
1447
|
|
|
|
|
|
|
# convert headers to index |
1448
|
16
|
|
|
|
|
27
|
my @hdr; |
1449
|
16
|
100
|
|
|
|
35
|
if (ref $hdrs) { |
1450
|
7
|
|
|
|
|
10
|
@hdr = @{$hdrs}; |
|
7
|
|
|
|
|
20
|
|
1451
|
7
|
|
|
|
|
21
|
for (0 .. $#hdr) { |
1452
|
21
|
100
|
|
|
|
60
|
exists $f{$hdr[$_]} and $f{$_ + 1} = delete $f{$hdr[$_]}; |
1453
|
|
|
|
|
|
|
} |
1454
|
|
|
|
|
|
|
} |
1455
|
|
|
|
|
|
|
$csv->callbacks ('after_parse' => sub { |
1456
|
114
|
|
|
114
|
|
4020
|
my ($CSV, $ROW) = @_; # lexical sub-variables in caps |
1457
|
114
|
|
|
|
|
368
|
foreach my $FLD (sort keys %f) { |
1458
|
115
|
|
|
|
|
284
|
local $_ = $ROW->[$FLD - 1]; |
1459
|
115
|
|
|
|
|
161
|
local %_; |
1460
|
115
|
100
|
|
|
|
213
|
@hdr and @_{@hdr} = @{$ROW}; |
|
51
|
|
|
|
|
150
|
|
1461
|
115
|
100
|
|
|
|
268
|
$f{$FLD}->($CSV, $ROW) or return \"skip"; |
1462
|
52
|
|
|
|
|
1185
|
$ROW->[$FLD - 1] = $_; |
1463
|
|
|
|
|
|
|
} |
1464
|
16
|
|
|
|
|
85
|
}); |
1465
|
|
|
|
|
|
|
} |
1466
|
|
|
|
|
|
|
|
1467
|
250
|
|
|
|
|
372
|
my $frag = $c->{'frag'}; |
1468
|
|
|
|
|
|
|
my $ref = ref $hdrs |
1469
|
|
|
|
|
|
|
? # aoh |
1470
|
250
|
100
|
|
|
|
2452
|
do { |
|
|
100
|
|
|
|
|
|
1471
|
207
|
|
|
|
|
421
|
my @h = $csv->column_names ($hdrs); |
1472
|
207
|
|
|
|
|
307
|
my %h; $h{$_}++ for @h; |
|
207
|
|
|
|
|
680
|
|
1473
|
207
|
50
|
|
|
|
483
|
exists $h{""} and croak ($csv->SetDiag (1012)); |
1474
|
207
|
50
|
|
|
|
476
|
unless (keys %h == @h) { |
1475
|
|
|
|
|
|
|
croak ($csv->_SetDiagInfo (1013, join ", " => |
1476
|
0
|
|
|
|
|
0
|
map { "$_ ($h{$_})" } grep { $h{$_} > 1 } keys %h)); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
1477
|
|
|
|
|
|
|
} |
1478
|
|
|
|
|
|
|
$frag ? $csv->fragment ($fh, $frag) : |
1479
|
207
|
100
|
|
|
|
646
|
$key ? do { |
|
|
100
|
|
|
|
|
|
1480
|
17
|
100
|
|
|
|
53
|
my ($k, $j, @f) = ref $key ? (undef, @{$key}) : ($key); |
|
5
|
|
|
|
|
13
|
|
1481
|
17
|
100
|
|
|
|
34
|
if (my @mk = grep { !exists $h{$_} } grep { defined } $k, @f) { |
|
22
|
|
|
|
|
84
|
|
|
27
|
|
|
|
|
58
|
|
1482
|
2
|
|
|
|
|
11
|
croak ($csv->_SetDiagInfo (4001, join ", " => @mk)); |
1483
|
|
|
|
|
|
|
} |
1484
|
|
|
|
|
|
|
+{ map { |
1485
|
26
|
|
|
|
|
40
|
my $r = $_; |
1486
|
26
|
100
|
|
|
|
66
|
my $K = defined $k ? $r->{$k} : join $j => @{$r}{@f}; |
|
4
|
|
|
|
|
12
|
|
1487
|
|
|
|
|
|
|
( $K => ( |
1488
|
|
|
|
|
|
|
$val |
1489
|
|
|
|
|
|
|
? ref $val |
1490
|
4
|
|
|
|
|
22
|
? { map { $_ => $r->{$_} } @{$val} } |
|
2
|
|
|
|
|
4
|
|
1491
|
26
|
100
|
|
|
|
111
|
: $r->{$val} |
|
|
100
|
|
|
|
|
|
1492
|
|
|
|
|
|
|
: $r )); |
1493
|
15
|
|
|
|
|
25
|
} @{$csv->getline_hr_all ($fh)} } |
|
15
|
|
|
|
|
36
|
|
1494
|
|
|
|
|
|
|
} |
1495
|
|
|
|
|
|
|
: $csv->getline_hr_all ($fh); |
1496
|
|
|
|
|
|
|
} |
1497
|
|
|
|
|
|
|
: # aoa |
1498
|
|
|
|
|
|
|
$frag ? $csv->fragment ($fh, $frag) |
1499
|
|
|
|
|
|
|
: $csv->getline_all ($fh); |
1500
|
248
|
50
|
|
|
|
577
|
if ($ref) { |
1501
|
248
|
100
|
66
|
|
|
1127
|
@row1 && !$c->{'hd_c'} && !ref $hdrs and unshift @{$ref}, \@row1; |
|
4
|
|
100
|
|
|
10
|
|
1502
|
|
|
|
|
|
|
} |
1503
|
|
|
|
|
|
|
else { |
1504
|
0
|
|
|
|
|
0
|
Text::CSV_XS->auto_diag (); |
1505
|
|
|
|
|
|
|
} |
1506
|
248
|
100
|
|
|
|
3158
|
$c->{'cls'} and close $fh; |
1507
|
248
|
100
|
100
|
|
|
1489
|
if ($ref and $c->{'cbai'} || $c->{'cboi'}) { |
|
|
|
66
|
|
|
|
|
1508
|
|
|
|
|
|
|
# Default is ARRAYref, but with key =>, you'll get a hashref |
1509
|
22
|
100
|
|
|
|
67
|
foreach my $r (ref $ref eq "ARRAY" ? @{$ref} : values %{$ref}) { |
|
21
|
|
|
|
|
47
|
|
|
1
|
|
|
|
|
4
|
|
1510
|
71
|
|
|
|
|
6741
|
local %_; |
1511
|
71
|
100
|
|
|
|
172
|
ref $r eq "HASH" and *_ = $r; |
1512
|
71
|
100
|
|
|
|
182
|
$c->{'cbai'} and $c->{'cbai'}->($csv, $r); |
1513
|
71
|
100
|
|
|
|
4197
|
$c->{'cboi'} and $c->{'cboi'}->($csv, $r); |
1514
|
|
|
|
|
|
|
} |
1515
|
|
|
|
|
|
|
} |
1516
|
|
|
|
|
|
|
|
1517
|
248
|
100
|
|
|
|
1851
|
if ($c->{'sink'}) { |
1518
|
6
|
50
|
|
|
|
26
|
my $ro = ref $c->{'out'} or return; |
1519
|
|
|
|
|
|
|
|
1520
|
6
|
100
|
66
|
|
|
19
|
$ro eq "SCALAR" && ${$c->{'out'}} eq "skip" and |
|
1
|
|
|
|
|
15
|
|
1521
|
|
|
|
|
|
|
return; |
1522
|
|
|
|
|
|
|
|
1523
|
5
|
50
|
|
|
|
10
|
$ro eq ref $ref or |
1524
|
|
|
|
|
|
|
croak ($csv->_SetDiagInfo (5001, "Output type mismatch")); |
1525
|
|
|
|
|
|
|
|
1526
|
5
|
100
|
|
|
|
12
|
if ($ro eq "ARRAY") { |
1527
|
4
|
100
|
33
|
|
|
6
|
if (@{$c->{'out'}} and @$ref and ref $c->{'out'}[0] eq ref $ref->[0]) { |
|
4
|
|
66
|
|
|
25
|
|
1528
|
2
|
|
|
|
|
4
|
push @{$c->{'out'}} => @$ref; |
|
2
|
|
|
|
|
10
|
|
1529
|
2
|
|
|
|
|
36
|
return $c->{'out'}; |
1530
|
|
|
|
|
|
|
} |
1531
|
2
|
|
|
|
|
7
|
croak ($csv->_SetDiagInfo (5001, "Output type mismatch")); |
1532
|
|
|
|
|
|
|
} |
1533
|
|
|
|
|
|
|
|
1534
|
1
|
50
|
|
|
|
5
|
if ($ro eq "HASH") { |
1535
|
1
|
|
|
|
|
3
|
@{$c->{'out'}}{keys %{$ref}} = values %{$ref}; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
4
|
|
1536
|
1
|
|
|
|
|
15
|
return $c->{'out'}; |
1537
|
|
|
|
|
|
|
} |
1538
|
|
|
|
|
|
|
|
1539
|
0
|
|
|
|
|
0
|
croak ($csv->_SetDiagInfo (5002, "Unsupported output type")); |
1540
|
|
|
|
|
|
|
} |
1541
|
|
|
|
|
|
|
|
1542
|
|
|
|
|
|
|
defined wantarray or |
1543
|
|
|
|
|
|
|
return csv ( |
1544
|
|
|
|
|
|
|
'in' => $ref, |
1545
|
|
|
|
|
|
|
'headers' => $hdrs, |
1546
|
242
|
100
|
|
|
|
534
|
%{$c->{'attr'}}, |
|
1
|
|
|
|
|
17
|
|
1547
|
|
|
|
|
|
|
); |
1548
|
|
|
|
|
|
|
|
1549
|
241
|
|
|
|
|
3702
|
return $ref; |
1550
|
|
|
|
|
|
|
} # csv |
1551
|
|
|
|
|
|
|
|
1552
|
|
|
|
|
|
|
1; |
1553
|
|
|
|
|
|
|
|
1554
|
|
|
|
|
|
|
__END__ |