File Coverage

blib/lib/Text/CSV_XS.pm
Criterion Covered Total %
statement 943 954 98.9
branch 743 790 94.0
condition 399 466 85.4
subroutine 90 90 100.0
pod 68 68 100.0
total 2243 2368 94.7


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