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