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.008001;
17              
18 35     35   3007723 use strict;
  35         68  
  35         1334  
19 35     35   179 use warnings;
  35         72  
  35         1869  
20              
21             require Exporter;
22 35     35   175 use XSLoader;
  35         52  
  35         698  
23 35     35   117 use Carp;
  35         89  
  35         2447  
24              
25 35     35   193 use vars qw( $VERSION @ISA @EXPORT_OK %EXPORT_TAGS );
  35         52  
  35         8466  
26             $VERSION = "1.64";
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 145137  
31 4     4 1 8 sub IV { 1 } sub CSV_TYPE_IV { IV }
  12     12 1 132760  
32 4     4 1 8 sub NV { 2 } sub CSV_TYPE_NV { NV }
  12     12 1 48  
33              
34 11     11 1 46 sub CSV_FLAGS_IS_QUOTED { 0x0001 }
35 12     12 1 56 sub CSV_FLAGS_IS_BINARY { 0x0002 }
36 4     4 1 17 sub CSV_FLAGS_ERROR_IN_FIELD { 0x0004 }
37 20     20 1 63 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 35     35   178 no warnings "redefine";
  35         68  
  35         380580  
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 636 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 15739     15739   26461 my ($self, $aw) = @_;
132 15739 100       43392 $aw or return 0; # no checks needed without allow_whitespace
133              
134 3569         5271 my $quo = $self->{'quote'};
135 3569 100 100     9502 defined $quo && length ($quo) or $quo = $self->{'quote_char'};
136 3569         4963 my $esc = $self->{'escape_char'};
137              
138 3569 100 100     42540 defined $quo && $quo =~ m/^[ \t]/ and return 1002;
139 3327 100 100     44419 defined $esc && $esc =~ m/^[ \t]/ and return 1002;
140              
141 3037         7154 return 0;
142             } # _unhealty_whitespace
143              
144             sub _check_sanity {
145 12433     12433   15353 my $self = shift;
146              
147 12433         18113 my $eol = $self->{'eol'};
148 12433         18091 my $sep = $self->{'sep'};
149 12433 100 100     29022 defined $sep && length ($sep) or $sep = $self->{'sep_char'};
150 12433         17225 my $quo = $self->{'quote'};
151 12433 100 100     26578 defined $quo && length ($quo) or $quo = $self->{'quote_char'};
152 12433         17864 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 12433 100       22121 $sep ne "" or return 1008;
160 12431 100       23401 length ($sep) > 16 and return 1006;
161 12430 100       33316 $sep =~ m/[\r\n]/ and return 1003;
162              
163 12424 100       21950 if (defined $quo) {
164 12414 100       61153 $quo eq $sep and return 1001;
165 12186 100       19859 length ($quo) > 16 and return 1007;
166 12185 100       22537 $quo =~ m/[\r\n]/ and return 1003;
167             }
168 12189 100       19528 if (defined $esc) {
169 12173 100       45944 $esc eq $sep and return 1001;
170 12005 100       20445 $esc =~ m/[\r\n]/ and return 1003;
171             }
172 12015 100       17481 if (defined $eol) {
173 12010 100       18030 length ($eol) > 16 and return 1005;
174             }
175              
176 12014         20673 return _unhealthy_whitespace ($self, $self->{'allow_whitespace'});
177             } # _check_sanity
178              
179             sub known_attributes {
180 3     3 1 627 sort grep !m/^_/ => "sep", "quote", keys %def_attr;
181             } # known_attributes
182              
183             sub new {
184 1009     1009 1 53589398 $last_err = Text::CSV_XS->SetDiag (1000,
185             "usage: my \$csv = Text::CSV_XS->new ([{ option => value, ... }]);");
186              
187 1009         1834 my $proto = shift;
188 1009 100 100     4555 my $class = ref $proto || $proto or return;
189 1008 100 100     3894 @_ > 0 && ref $_[0] ne "HASH" and return;
190 1000   100     2090 my $attr = shift || +{};
191             my %attr = map {
192 2765 100       8484 my $k = m/^[a-zA-Z]\w+$/ ? lc $_ : $_;
193 2765 100       4789 exists $attr_alias{$k} and $k = $attr_alias{$k};
194 2765         6071 ($k => $attr->{$_});
195 1000         1302 } keys %{$attr};
  1000         2780  
196              
197 1000         1923 my $sep_aliased = 0;
198 1000 100       2020 if (exists $attr{'sep'}) {
199 10         30 $attr{'sep_char'} = delete $attr{'sep'};
200 10         17 $sep_aliased = 1;
201             }
202 1000         1211 my $quote_aliased = 0;
203 1000 100       1774 if (exists $attr{'quote'}) {
204 25         43 $attr{'quote_char'} = delete $attr{'quote'};
205 25         31 $quote_aliased = 1;
206             }
207             exists $attr{'formula_handling'} and
208 1000 100       1687 $attr{'formula'} = delete $attr{'formula_handling'};
209 1000         1396 my $attr_formula = delete $attr{'formula'};
210              
211 1000         1991 for (keys %attr) {
212 2729 100 100     7563 if (m/^[a-z]/ && exists $def_attr{$_}) {
213             # uncoverable condition false
214 2722 100 100     6890 defined $attr{$_} && m/_char$/ and utf8::decode ($attr{$_});
215 2722         3678 next;
216             }
217             # croak?
218 7         27 $last_err = Text::CSV_XS->SetDiag (1000, "INI - Unknown attribute '$_'");
219 7 100       19 $attr{'auto_diag'} and error_diag ();
220 7         29 return;
221             }
222 993 100       1948 if ($sep_aliased) {
223 10         40 my @b = unpack "U0C*", $attr{'sep_char'};
224 10 100       24 if (@b > 1) {
225 6         14 $attr{'sep'} = $attr{'sep_char'};
226 6         15 $attr{'sep_char'} = "\0";
227             }
228             else {
229 4         9 $attr{'sep'} = undef;
230             }
231             }
232 993 100 100     1934 if ($quote_aliased and defined $attr{'quote_char'}) {
233 21         69 my @b = unpack "U0C*", $attr{'quote_char'};
234 21 100       43 if (@b > 1) {
235 7         16 $attr{'quote'} = $attr{'quote_char'};
236 7         13 $attr{'quote_char'} = "\0";
237             }
238             else {
239 14         21 $attr{'quote'} = undef;
240             }
241             }
242              
243 993         17638 my $self = { %def_attr, %attr };
244 993 100       3304 if (my $ec = _check_sanity ($self)) {
245 35         101 $last_err = Text::CSV_XS->SetDiag ($ec);
246 35 100       74 $attr{'auto_diag'} and error_diag ();
247 35         234 return;
248             }
249 958 100 100     2404 if (defined $self->{'callbacks'} && ref $self->{'callbacks'} ne "HASH") {
250 6         715 carp ("The 'callbacks' attribute is set but is not a hash: ignored\n");
251 6         28 $self->{'callbacks'} = undef;
252             }
253              
254 958         3112 $last_err = Text::CSV_XS->SetDiag (0);
255 958 100 100     2536 defined $\ && !exists $attr{'eol'} and $self->{'eol'} = $\;
256 958         1547 bless $self, $class;
257 958 100       1928 defined $self->{'types'} and $self->types ($self->{'types'});
258 958 50       2526 defined $self->{'skip_empty_rows'} and $self->{'skip_empty_rows'} = _supported_skip_empty_rows ($self, $self->{'skip_empty_rows'});
259 958 100       1643 defined $attr_formula and $self->{'formula'} = _supported_formula ($self, $attr_formula);
260 957         5121 $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   21808 my ($self, $name, $val, $ec) = @_;
303 11108 100       33368 defined $val and utf8::decode ($val);
304 11108         20678 $self->{$name} = $val;
305 11108 100       18972 $ec = _check_sanity ($self) and croak ($self->SetDiag ($ec));
306 10198         36999 $self->_cache_set ($_cache_id{$name}, $val);
307             } # _set_attr_C
308              
309             # A flag
310             sub _set_attr_X {
311 5644     5644   10863 my ($self, $name, $val) = @_;
312 5644 100       10662 defined $val or $val = 0;
313 5644         9682 $self->{$name} = $val;
314 5644         25035 $self->_cache_set ($_cache_id{$name}, 0 + $val);
315             } # _set_attr_X
316              
317             # A number
318             sub _set_attr_N {
319 68     68   118 my ($self, $name, $val) = @_;
320 68         157 $self->{$name} = $val;
321 68         363 $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 770460 my $self = shift;
328 4836 100       11520 if (@_) {
329 3601         8510 $self->_set_attr_C ("quote_char", shift);
330 3374         8278 $self->_cache_set ($_cache_id{'quote'}, "");
331             }
332 4609         14112 $self->{'quote_char'};
333             } # quote_char
334              
335             sub quote {
336 20     20 1 46 my $self = shift;
337 20 100       69 if (@_) {
338 11         21 my $quote = shift;
339 11 100       36 defined $quote or $quote = "";
340 11         40 utf8::decode ($quote);
341 11         43 my @b = unpack "U0C*", $quote;
342 11 100       30 if (@b > 1) {
343 5 100       134 @b > 16 and croak ($self->SetDiag (1007));
344 4         14 $self->quote_char ("\0");
345             }
346             else {
347 6         20 $self->quote_char ($quote);
348 6         13 $quote = "";
349             }
350 10         23 $self->{'quote'} = $quote;
351              
352 10         22 my $ec = _check_sanity ($self);
353 10 100       173 $ec and croak ($self->SetDiag ($ec));
354              
355 9         34 $self->_cache_set ($_cache_id{'quote'}, $quote);
356             }
357 18         32 my $quote = $self->{'quote'};
358 18 100 100     143 defined $quote && length ($quote) ? $quote : $self->{'quote_char'};
359             } # quote
360              
361             sub escape_char {
362 4826     4826 1 776182 my $self = shift;
363 4826 100       11390 if (@_) {
364 3595         5670 my $ec = shift;
365 3595         9001 $self->_set_attr_C ("escape_char", $ec);
366 3480 100       7451 $ec or $self->_set_attr_X ("escape_null", 0);
367             }
368 4711         15391 $self->{'escape_char'};
369             } # escape_char
370              
371             sub sep_char {
372 5155     5155 1 767203 my $self = shift;
373 5155 100       11262 if (@_) {
374 3912         9002 $self->_set_attr_C ("sep_char", shift);
375 3344         7221 $self->_cache_set ($_cache_id{'sep'}, "");
376             }
377 4587         13457 $self->{'sep_char'};
378             } # sep_char
379              
380             sub sep {
381 359     359 1 3810 my $self = shift;
382 359 100       656 if (@_) {
383 326         436 my $sep = shift;
384 326 100       498 defined $sep or $sep = "";
385 326         848 utf8::decode ($sep);
386 326         967 my @b = unpack "U0C*", $sep;
387 326 100       704 if (@b > 1) {
388 13 100       132 @b > 16 and croak ($self->SetDiag (1006));
389 12         28 $self->sep_char ("\0");
390             }
391             else {
392 313         623 $self->sep_char ($sep);
393 310         412 $sep = "";
394             }
395 322         581 $self->{'sep'} = $sep;
396              
397 322         405 my $ec = _check_sanity ($self);
398 322 100       605 $ec and croak ($self->SetDiag ($ec));
399              
400 321         736 $self->_cache_set ($_cache_id{'sep'}, $sep);
401             }
402 354         450 my $sep = $self->{'sep'};
403 354 100 100     1228 defined $sep && length ($sep) ? $sep : $self->{'sep_char'};
404             } # sep
405              
406             sub eol {
407 280     280 1 4630 my $self = shift;
408 280 100       507 if (@_) {
409 227         253 my $eol = shift;
410 227 100       383 defined $eol or $eol = ""; # Also reset strict_eol?
411 227 100       472 length ($eol) > 16 and croak ($self->SetDiag (1005));
412 226         309 $self->{'eol'} = $eol;
413 226         540 $self->_cache_set ($_cache_id{'eol'}, $eol);
414             }
415 279         884 $self->{'eol'};
416             } # eol
417              
418             sub eol_type {
419 32     32 1 48 my $self = shift;
420 32         159 $self->_cache_get_eolt;
421             } # eol_type
422              
423             sub always_quote {
424 3032     3032 1 793568 my $self = shift;
425 3032 100       9251 @_ and $self->_set_attr_X ("always_quote", shift);
426 3032         8779 $self->{'always_quote'};
427             } # always_quote
428              
429             sub quote_space {
430 10     10 1 21 my $self = shift;
431 10 100       41 @_ and $self->_set_attr_X ("quote_space", shift);
432 10         33 $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         20 $self->{'quote_empty'};
439             } # quote_empty
440              
441             sub escape_null {
442 6     6 1 12 my $self = shift;
443 6 100       28 @_ and $self->_set_attr_X ("escape_null", shift);
444 6         27 $self->{'escape_null'};
445             } # escape_null
446 3     3 1 13 sub quote_null { goto &escape_null; }
447              
448             sub quote_binary {
449 7     7 1 14 my $self = shift;
450 7 100       27 @_ and $self->_set_attr_X ("quote_binary", shift);
451 7         23 $self->{'quote_binary'};
452             } # quote_binary
453              
454             sub binary {
455 21     21 1 73273 my $self = shift;
456 21 100       102 @_ and $self->_set_attr_X ("binary", shift);
457 21         52 $self->{'binary'};
458             } # binary
459              
460             sub strict {
461 2     2 1 5 my $self = shift;
462 2 100       11 @_ and $self->_set_attr_X ("strict", shift);
463 2         10 $self->{'strict'};
464             } # strict
465              
466             sub strict_eol {
467 2     2 1 6 my $self = shift;
468 2 100       24 @_ and $self->_set_attr_X ("strict_eol", shift);
469 2         11 $self->{'strict_eol'};
470             } # strict_eol
471              
472             sub _supported_skip_empty_rows {
473 980     980   1453 my ($self, $f) = @_;
474 980 100       1427 defined $f or return 0;
475 979 100 66     3035 if ($self && $f && ref $f && ref $f eq "CODE") {
      100        
      66        
476 5         6 $self->{'_EMPTROW_CB'} = $f;
477 5         11 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 974 50       3761 $f =~ m/^(?: 6 | cb )$/xi ? 6 : do {
    100          
    100          
    100          
    100          
    100          
    100          
486 1   50     3 $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 626 my $self = shift;
493 24 100       103 @_ and $self->_set_attr_N ("skip_empty_rows", _supported_skip_empty_rows ($self, shift));
494 23         31 my $ser = $self->{'skip_empty_rows'};
495 23 100       78 $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       135 $self->{'_EMPTROW_CB'};
    100          
    100          
    100          
    100          
499             } # skip_empty_rows
500              
501             sub _SetDiagInfo {
502 18     18   48 my ($self, $err, $msg) = @_;
503 18         175 $self->SetDiag ($err);
504 18         52 my $em = $self->error_diag ();
505 18 50       79 $em =~ s/^\d+$// and $msg =~ s/^/# /;
506 18 50       51 my $sep = $em =~ m/[;\n]$/ ? "\n\t" : ": ";
507 18         2214 join $sep => grep m/\S\S\S/ => $em, $msg;
508             } # _SetDiagInfo
509              
510             sub _supported_formula {
511 103     103   167 my ($self, $f) = @_;
512 103 100       156 defined $f or return 5;
513 102 100 66     362 if ($self && $f && ref $f && ref $f eq "CODE") {
      100        
      100        
514 6         10 $self->{'_FORMULA_CB'} = $f;
515 6         12 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       676 $f =~ m/^(?: 6 | cb )$/xi ? 6 : do {
    100          
    100          
    100          
    100          
    100          
    100          
524 7   50     10 $self ||= "Text::CSV_XS";
525 7         21 croak ($self->_SetDiagInfo (1500, "formula-handling '$f' is not supported"));
526             };
527             } # _supported_formula
528              
529             sub formula {
530 44     44 1 2563 my $self = shift;
531 44 100       148 @_ and $self->_set_attr_N ("formula", _supported_formula ($self, shift));
532 38 100       88 $self->{'formula'} == 6 or $self->{'_FORMULA_CB'} = undef;
533 38         132 [qw( none die croak diag empty undef cb )]->[_supported_formula ($self, $self->{'formula'})];
534             } # formula
535              
536             sub formula_handling {
537 7     7 1 11 my $self = shift;
538 7         13 $self->formula (@_);
539             } # formula_handling
540              
541             sub decode_utf8 {
542 2     2 1 5 my $self = shift;
543 2 100       11 @_ and $self->_set_attr_X ("decode_utf8", shift);
544 2         9 $self->{'decode_utf8'};
545             } # decode_utf8
546              
547             sub keep_meta_info {
548 12     12 1 844 my $self = shift;
549 12 100       53 if (@_) {
550 11         18 my $v = shift;
551 11 100 100     58 !defined $v || $v eq "" and $v = 0;
552 11 100       54 $v =~ m/^[0-9]/ or $v = lc $v eq "false" ? 0 : 1; # true/truth = 1
    100          
553 11         37 $self->_set_attr_X ("keep_meta_info", $v);
554             }
555 12         57 $self->{'keep_meta_info'};
556             } # keep_meta_info
557              
558             sub allow_loose_quotes {
559 12     12 1 20 my $self = shift;
560 12 100       43 @_ and $self->_set_attr_X ("allow_loose_quotes", shift);
561 12         25 $self->{'allow_loose_quotes'};
562             } # allow_loose_quotes
563              
564             sub allow_loose_escapes {
565 12     12 1 1135 my $self = shift;
566 12 100       94 @_ and $self->_set_attr_X ("allow_loose_escapes", shift);
567 12         29 $self->{'allow_loose_escapes'};
568             } # allow_loose_escapes
569              
570             sub allow_whitespace {
571 4954     4954 1 2313155 my $self = shift;
572 4954 100       13951 if (@_) {
573 3725         4788 my $aw = shift;
574 3725 100       7970 _unhealthy_whitespace ($self, $aw) and
575             croak ($self->SetDiag (1002));
576 3721         8659 $self->_set_attr_X ("allow_whitespace", $aw);
577             }
578 4950         15300 $self->{'allow_whitespace'};
579             } # allow_whitespace
580              
581             sub allow_unquoted_escape {
582 3     3 1 21 my $self = shift;
583 3 100       20 @_ and $self->_set_attr_X ("allow_unquoted_escape", shift);
584 3         12 $self->{'allow_unquoted_escape'};
585             } # allow_unquoted_escape
586              
587             sub blank_is_undef {
588 2     2 1 6 my $self = shift;
589 2 100       11 @_ and $self->_set_attr_X ("blank_is_undef", shift);
590 2         10 $self->{'blank_is_undef'};
591             } # blank_is_undef
592              
593             sub empty_is_undef {
594 2     2 1 22 my $self = shift;
595 2 100       12 @_ and $self->_set_attr_X ("empty_is_undef", shift);
596 2         16 $self->{'empty_is_undef'};
597             } # empty_is_undef
598              
599             sub verbatim {
600 9     9 1 16184 my $self = shift;
601 9 100       49 @_ and $self->_set_attr_X ("verbatim", shift);
602 9         26 $self->{'verbatim'};
603             } # verbatim
604              
605             sub undef_str {
606 13     13 1 7784 my $self = shift;
607 13 100       48 if (@_) {
608 12         29 my $v = shift;
609 12 100       62 $self->{'undef_str'} = defined $v ? "$v" : undef;
610 12         78 $self->_cache_set ($_cache_id{'undef_str'}, $self->{'undef_str'});
611             }
612 13         65 $self->{'undef_str'};
613             } # undef_str
614              
615             sub comment_str {
616 15     15 1 55 my $self = shift;
617 15 100       29 if (@_) {
618 14         21 my $v = shift;
619 14 100       43 $self->{'comment_str'} = defined $v ? "$v" : undef;
620 14         83 $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 339 my $self = shift;
627 12 100       43 if (@_) {
628 9         14 my $v = shift;
629 9 100 100     53 !defined $v || $v eq "" and $v = 0;
630 9 100       44 $v =~ m/^[0-9]/ or $v = lc $v eq "false" ? 0 : 1; # true/truth = 1
    100          
631 9         27 $self->_set_attr_X ("auto_diag", $v);
632             }
633 12         103 $self->{'auto_diag'};
634             } # auto_diag
635              
636             sub diag_verbose {
637 10     10 1 645 my $self = shift;
638 10 100       37 if (@_) {
639 8         17 my $v = shift;
640 8 100 100     44 !defined $v || $v eq "" and $v = 0;
641 8 100       39 $v =~ m/^[0-9]/ or $v = lc $v eq "false" ? 0 : 1; # true/truth = 1
    100          
642 8         29 $self->_set_attr_X ("diag_verbose", $v);
643             }
644 10         53 $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 8 my $self = shift;
654 5         29 return $self->{'_STATUS'};
655             } # status
656              
657             sub eof {
658 33     33 1 14992 my $self = shift;
659 33         148 return $self->{'_EOF'};
660             } # eof
661              
662             sub types {
663 7     7 1 1570 my $self = shift;
664 7 100       14 if (@_) {
665 2 100       5 if (my $types = shift) {
666 1         1 $self->{'_types'} = join "", map { chr } @{$types};
  3         8  
  1         2  
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         14 $self->{'types'};
679             }
680             } # types
681              
682             sub callbacks {
683 75     75 1 19348 my $self = shift;
684 75 100       142 if (@_) {
685 45         45 my $cb;
686 45         46 my $hf = 0x00;
687 45 100       64 if (defined $_[0]) {
    100          
688 43 100       62 grep { !defined } @_ and croak ($self->SetDiag (1004));
  77         379  
689 41 100 100     672 $cb = @_ == 1 && ref $_[0] eq "HASH" ? shift
    100          
690             : @_ % 2 == 0 ? { @_ }
691             : croak ($self->SetDiag (1004));
692 36         43 foreach my $cbk (keys %{$cb}) {
  36         72  
693             # A key cannot be a ref. That would be stored as the *string
694             # 'SCALAR(0x1f3e710)' or 'ARRAY(0x1a5ae18)'
695 38 100 100     1774 $cbk =~ m/^[\w.]+$/ && ref $cb->{$cbk} eq "CODE" or
696             croak ($self->SetDiag (1004));
697             }
698 22 100       43 exists $cb->{'error'} and $hf |= 0x01;
699 22 100       64 exists $cb->{'after_parse'} and $hf |= 0x02;
700 22 100       69 exists $cb->{'before_print'} and $hf |= 0x04;
701             }
702             elsif (@_ > 1) {
703             # (undef, whatever)
704 1         108 croak ($self->SetDiag (1004));
705             }
706 23         60 $self->_set_attr_X ("_has_hooks", $hf);
707 23         61 $self->{'callbacks'} = $cb;
708             }
709 53         119 $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 53301 my $self = shift;
719 1823         4613 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     11570 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         2256 $diag[0] = 0 + $self->{'_ERROR_DIAG'};
726 1644         2329 $diag[1] = $self->{'_ERROR_DIAG'};
727 1644 100       2940 $diag[2] = 1 + $self->{'_ERROR_POS'} if exists $self->{'_ERROR_POS'};
728 1644         1913 $diag[3] = $self->{'_RECNO'};
729 1644 100       2688 $diag[4] = $self->{'_ERROR_FLD'} if exists $self->{'_ERROR_FLD'};
730 1644 100 66     4853 $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     5136 return $self->{'callbacks'}{'error'}->(@diag);
      100        
734             }
735              
736 1813         2539 my $context = wantarray;
737 1813 100       3051 unless (defined $context) { # Void context, auto-diag
738 344 100 100     869 if ($diag[0] && $diag[0] != 2012) {
739 36         101 my $msg = "# CSV_XS ERROR: $diag[0] - $diag[1] \@ rec $diag[3] pos $diag[2]\n";
740 36 100       209 $diag[4] and $msg =~ s/$/ field $diag[4]/;
741 36 100       102 $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         37 warn $msg;
746 4         23 return;
747             }
748              
749             $self->{'diag_verbose'} && $self->{'_ERROR_INPUT'} and
750 32 50 66     141 $msg .= $self->{'_ERROR_INPUT'}."\n".
751             (" " x ($diag[2] - 1))."^\n";
752              
753 32         53 my $lvl = $self->{'auto_diag'};
754 32 100       68 if ($lvl < 2) {
755 29         96 my @c = caller (2);
756 29 50 66     137 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       226 $lvl > 1 ? die $msg : warn $msg;
768             }
769 337         2544 return;
770             }
771 1469 100       6153 return $context ? @diag : $diag[1];
772             } # error_diag
773              
774             sub record_number {
775 14     14 1 2655 my $self = shift;
776 14         42 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 1400     1400 1 357099 my $self = shift;
787 1400 100       4373 return ref $self->{'_STRING'} ? ${$self->{'_STRING'}} : undef;
  1399         5691  
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 16918 my $self = shift;
798 1603 100       4147 return ref $self->{'_FIELDS'} ? @{$self->{'_FIELDS'}} : undef;
  1602         9557  
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 474 my $self = shift;
810 21 100       58 return ref $self->{'_FFLAGS'} ? @{$self->{'_FFLAGS'}} : undef;
  16         53  
811             } # meta_info
812              
813             sub is_quoted {
814 12     12 1 1753 my ($self, $idx) = @_;
815             ref $self->{'_FFLAGS'} &&
816 12 100 100     70 $idx >= 0 && $idx < @{$self->{'_FFLAGS'}} or return;
  8   100     24  
817 7 100       19 $self->{'_FFLAGS'}[$idx] & CSV_FLAGS_IS_QUOTED () ? 1 : 0;
818             } # is_quoted
819              
820             sub is_binary {
821 11     11 1 318 my ($self, $idx) = @_;
822             ref $self->{'_FFLAGS'} &&
823 11 100 100     68 $idx >= 0 && $idx < @{$self->{'_FFLAGS'}} or return;
  9   100     23  
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 36 my ($self, $idx) = @_;
829 19 100 100     96 $idx < 0 || !ref $self->{'_FFLAGS'} and return;
830 11 100       13 $idx >= @{$self->{'_FFLAGS'}} and return 1;
  11         23  
831 10 100       21 $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 1399     1399 1 800886 my $self = shift;
847 1399         2927 my $str = "";
848 1399         6306 $self->{'_FIELDS'} = \@_;
849 1399   100     28612 $self->{'_STATUS'} = (@_ > 0) && $self->Combine (\$str, \@_, 0);
850 1395         3458 $self->{'_STRING'} = \$str;
851 1395         4859 $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 108197 my ($self, $str) = @_;
868              
869 1947 100       5244 ref $str and croak ($self->SetDiag (1500));
870              
871 1943         2719 my $fields = [];
872 1943         2238 my $fflags = [];
873 1943         3768 $self->{'_STRING'} = \$str;
874 1943 100 100     40590 if (defined $str && $self->Parse ($str, $fields, $fflags)) {
875 1729         4223 $self->{'_FIELDS'} = $fields;
876 1729         3014 $self->{'_FFLAGS'} = $fflags;
877 1729         2984 $self->{'_STATUS'} = 1;
878             }
879             else {
880 211         397 $self->{'_FIELDS'} = undef;
881 211         292 $self->{'_FFLAGS'} = undef;
882 211         276 $self->{'_STATUS'} = 0;
883             }
884 1940         7470 $self->{'_STATUS'};
885             } # parse
886              
887             sub column_names {
888 1025     1025 1 48148 my ($self, @keys) = @_;
889             @keys or
890 1025 100       2087 return defined $self->{'_COLUMN_NAMES'} ? @{$self->{'_COLUMN_NAMES'}} : ();
  293 100       1089  
891              
892             @keys == 1 && ! defined $keys[0] and
893 689 100 100     1828 return $self->{'_COLUMN_NAMES'} = undef;
894              
895 551 100 100     1354 if (@keys == 1 && ref $keys[0] eq "ARRAY") {
    100          
896 227         224 @keys = @{$keys[0]};
  227         472  
897             }
898 712 100       1642 elsif (join "", map { defined $_ ? ref $_ : "" } @keys) {
899 5         657 croak ($self->SetDiag (3001));
900             }
901              
902 546 100 100     1058 $self->{'_BOUND_COLUMNS'} && @keys != @{$self->{'_BOUND_COLUMNS'}} and
  2         136  
903             croak ($self->SetDiag (3003));
904              
905 545 100       640 $self->{'_COLUMN_NAMES'} = [ map { defined $_ ? $_ : "\cAUNDEF\cA" } @keys ];
  1262         2369  
906 545         630 @{$self->{'_COLUMN_NAMES'}};
  545         1101  
907             } # column_names
908              
909             sub header {
910 333     333 1 36604 my ($self, $fh, @args) = @_;
911              
912 333 100       863 $fh or croak ($self->SetDiag (1014));
913              
914 332         467 my (@seps, %args);
915 332         560 for (@args) {
916 225 100       394 if (ref $_ eq "ARRAY") {
917 18         19 push @seps, @{$_};
  18         38  
918 18         31 next;
919             }
920 207 100       332 if (ref $_ eq "HASH") {
921 206         186 %args = %{$_};
  206         372  
922 206         330 next;
923             }
924 1         134 croak ('usage: $csv->header ($fh, [ seps ], { options })');
925             }
926              
927             defined $args{'munge'} && !defined $args{'munge_column_names'} and
928 331 100 66     824 $args{'munge_column_names'} = $args{'munge'}; # munge as alias
929 331 100       693 defined $args{'detect_bom'} or $args{'detect_bom'} = 1;
930 331 100       714 defined $args{'set_column_names'} or $args{'set_column_names'} = 1;
931 331 100       621 defined $args{'munge_column_names'} or $args{'munge_column_names'} = "lc";
932              
933             # Reset any previous leftovers
934 331         426 $self->{'_RECNO'} = 0;
935 331         455 $self->{'_AHEAD'} = undef;
936 331 100       619 $self->{'_COLUMN_NAMES'} = undef if $args{'set_column_names'};
937 331 100       594 $self->{'_BOUND_COLUMNS'} = undef if $args{'set_column_names'};
938              
939 331 100       510 if (defined $args{'sep_set'}) {
940 27 100       67 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         36  
943             }
944              
945 326 50       823 $^O eq "MSWin32" and binmode $fh;
946 326         5734 my $hdr = <$fh>;
947             # check if $hdr can be empty here, I don't think so
948 326 100 66     1511 defined $hdr && $hdr ne "" or croak ($self->SetDiag (1010));
949              
950 324         371 my %sep;
951 324 100       741 @seps or @seps = (",", ";");
952 324         499 foreach my $sep (@seps) {
953 732 100       1660 index ($hdr, $sep) >= 0 and $sep{$sep}++;
954             }
955              
956 324 100       713 keys %sep >= 2 and croak ($self->SetDiag (1011));
957              
958 320         984 $self->sep (keys %sep);
959 320         583 my $enc = "";
960 320 100       508 if ($args{'detect_bom'}) { # UTF-7 is not supported
961 319 100       2266 if ($hdr =~ s/^\x00\x00\xfe\xff//) { $enc = "utf-32be" }
  24 100       35  
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
962 24         38 elsif ($hdr =~ s/^\xff\xfe\x00\x00//) { $enc = "utf-32le" }
963 25         38 elsif ($hdr =~ s/^\xfe\xff//) { $enc = "utf-16be" }
964 24         33 elsif ($hdr =~ s/^\xff\xfe//) { $enc = "utf-16le" }
965 48         76 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         3 elsif ($hdr =~ s/^\x0e\xfe\xff//) { $enc = "scsu" }
969 1         2 elsif ($hdr =~ s/^\xfb\xee\x28//) { $enc = "bocu-1" }
970 1         3 elsif ($hdr =~ s/^\x84\x31\x95\x33//) { $enc = "gb-18030" }
971 36         71 elsif ($hdr =~ s/^\x{feff}//) { $enc = "" }
972              
973 319 100       690 $self->{'ENCODING'} = $enc ? uc $enc : undef;
974              
975 319 100       1111 $hdr eq "" and croak ($self->SetDiag (1010));
976              
977 313 100       504 if ($enc) {
978 144 50 33     280 $ebcdic && $enc eq "utf-ebcdic" and $enc = "";
979 144 100       420 if ($enc =~ m/([13]).le$/) {
980 48         114 my $l = 0 + $1;
981 48         54 my $x;
982 48         95 $hdr .= "\0" x $l;
983 48         188 read $fh, $x, $l;
984             }
985 144 50       227 if ($enc) {
986 144 100       229 if ($enc ne "utf-8") {
987 96         608 require Encode;
988 96         477 $hdr = Encode::decode ($enc, $hdr);
989             }
990 144     2   4486 binmode $fh, ":encoding($enc)";
  2         1657  
  2         34  
  2         11  
991             }
992             }
993             }
994              
995 314         6622 my ($ahead, $eol);
996 314 100 66     888 if ($hdr and $hdr =~ s/\Asep=(\S)([\r\n]+)//i) { # Also look in xs:Parse
997 1         3 $self->sep ($1);
998 1 50       3 length $hdr or $hdr = <$fh>;
999             }
1000 314 100       1810 if ($hdr =~ s/^([^\r\n]+)([\r\n]+)([^\r\n].+)\z/$1/s) {
1001 142         237 $eol = $2;
1002 142         291 $ahead = $3;
1003             }
1004              
1005 314         421 my $hr = \$hdr;
1006 314 50       2646 open my $h, "<", $hr or croak ($self->SetDiag (1010));
1007              
1008 314 100       6104 my $row = $self->getline ($h) or croak ();
1009 312         748 close $h;
1010              
1011 312 100       709 if ( $args{'munge_column_names'} eq "lc") {
    100          
    100          
1012 293         292 $_ = lc for @{$row};
  293         907  
1013             }
1014             elsif ($args{'munge_column_names'} eq "uc") {
1015 7         9 $_ = uc for @{$row};
  7         38  
1016             }
1017             elsif ($args{'munge_column_names'} eq "db") {
1018 3         5 for (@{$row}) {
  3         7  
1019 7         12 s/\W+/_/g;
1020 7         12 s/^_+//;
1021 7         11 $_ = lc;
1022             }
1023             }
1024              
1025 312 100       501 if ($ahead) { # Must be after getline, which creates the cache
1026 142         424 $self->_cache_set ($_cache_id{'_has_ahead'}, 1);
1027 142         185 $self->{'_AHEAD'} = $ahead;
1028 142 100       512 $eol =~ m/^\r([^\n]|\z)/ and $self->eol ($eol);
1029             }
1030              
1031 312         333 my @hdr = @{$row};
  312         666  
1032             ref $args{'munge_column_names'} eq "CODE" and
1033 312 100       597 @hdr = map { $args{'munge_column_names'}->($_) } @hdr;
  4         13  
1034             ref $args{'munge_column_names'} eq "HASH" and
1035 312 100       484 @hdr = map { $args{'munge_column_names'}->{$_} || $_ } @hdr;
  3 100       29  
1036 312         324 my %hdr; $hdr{$_}++ for @hdr;
  312         811  
1037 312 100       624 exists $hdr{''} and croak ($self->SetDiag (1012));
1038 310 100       560 unless (keys %hdr == @hdr) {
1039             croak ($self->_SetDiagInfo (1013, join ", " =>
1040 1         3 map { "$_ ($hdr{$_})" } grep { $hdr{$_} > 1 } keys %hdr));
  1         7  
  2         4  
1041             }
1042 309 100       832 $args{'set_column_names'} and $self->column_names (@hdr);
1043 309 100       2395 wantarray ? @hdr : $self;
1044             } # header
1045              
1046             sub bind_columns {
1047 36     36 1 6937 my ($self, @refs) = @_;
1048             @refs or
1049 36 100       102 return defined $self->{'_BOUND_COLUMNS'} ? @{$self->{'_BOUND_COLUMNS'}} : undef;
  2 100       9  
1050              
1051 32 100 100     126 if (@refs == 1 && ! defined $refs[0]) {
1052 5         11 $self->{'_COLUMN_NAMES'} = undef;
1053 5         25 return $self->{'_BOUND_COLUMNS'} = undef;
1054             }
1055              
1056 27 100 100     80 $self->{'_COLUMN_NAMES'} && @refs != @{$self->{'_COLUMN_NAMES'}} and
  3         147  
1057             croak ($self->SetDiag (3003));
1058              
1059 26 100       333 join "", map { ref $_ eq "SCALAR" ? "" : "*" } @refs and
  74632 100       97087  
1060             croak ($self->SetDiag (3004));
1061              
1062 24         2566 $self->_set_attr_N ("_is_bound", scalar @refs);
1063 24         4100 $self->{'_BOUND_COLUMNS'} = [ @refs ];
1064 24         1139 @refs;
1065             } # bind_columns
1066              
1067             sub getline_hr {
1068 131     131 1 12905 my ($self, @args, %hr) = @_;
1069 131 100       465 $self->{'_COLUMN_NAMES'} or croak ($self->SetDiag (3002));
1070 130 100       1837 my $fr = $self->getline (@args) or return;
1071 127 100       406 if (ref $self->{'_FFLAGS'}) { # missing
1072             $self->{'_FFLAGS'}[$_] = CSV_FLAGS_IS_MISSING ()
1073 5 50       6 for (@{$fr} ? $#{$fr} + 1 : 0) .. $#{$self->{'_COLUMN_NAMES'}};
  5         11  
  5         8  
  5         15  
1074 5         26 @{$fr} == 1 && (!defined $fr->[0] || $fr->[0] eq "") and
1075 5 100 33     5 $self->{'_FFLAGS'}[0] ||= CSV_FLAGS_IS_MISSING ();
      66        
      100        
1076             }
1077 127         157 @hr{@{$self->{'_COLUMN_NAMES'}}} = @{$fr};
  127         501  
  127         211  
1078 127         586 \%hr;
1079             } # getline_hr
1080              
1081             sub getline_hr_all {
1082 251     251 1 372 my ($self, @args) = @_;
1083 251 100       975 $self->{'_COLUMN_NAMES'} or croak ($self->SetDiag (3002));
1084 249         270 my @cn = @{$self->{'_COLUMN_NAMES'}};
  249         475  
1085 249         286 [ map { my %h; @h{@cn} = @{$_}; \%h } @{$self->getline_all (@args)} ];
  376         509  
  376         402  
  376         1175  
  376         1457  
  249         5194  
1086             } # getline_hr_all
1087              
1088             sub say {
1089 34     34 1 3372 my ($self, $io, @f) = @_;
1090 34         81 my $eol = $self->eol ();
1091             # say ($fh, undef) does not propage actual undef to print ()
1092 34 100 66     387 my $state = $self->print ($io, @f == 1 && !defined $f[0] ? undef : @f);
1093 34 100       377 unless (length $eol) {
1094 32   33     52 $eol = $self->eol_type () || $\ || $/;
1095 32         58 print $io $eol;
1096             }
1097 34         82 return $state;
1098             } # say
1099              
1100             sub print_hr {
1101 3     3 1 207 my ($self, $io, $hr) = @_;
1102 3 100       158 $self->{'_COLUMN_NAMES'} or croak ($self->SetDiag (3009));
1103 2 100       142 ref $hr eq "HASH" or croak ($self->SetDiag (3010));
1104 1         4 $self->print ($io, [ map { $hr->{$_} } $self->column_names () ]);
  3         10  
1105             } # print_hr
1106              
1107             sub fragment {
1108 58     58 1 22027 my ($self, $io, $spec) = @_;
1109              
1110 58         181 my $qd = qr{\s* [0-9]+ \s* }x; # digit
1111 58         94 my $qs = qr{\s* (?: [0-9]+ | \* ) \s*}x; # digit or star
1112 58         539 my $qr = qr{$qd (?: - $qs )?}x; # range
1113 58         450 my $qc = qr{$qr (?: ; $qr )*}x; # list
1114 58 100 100     4539 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         183 my ($type, $range) = (lc $1, $2);
1122              
1123 38         83 my @h = $self->column_names ();
1124              
1125 38         47 my @c;
1126 38 100       63 if ($type eq "cell") {
1127 21         25 my @spec;
1128             my $min_row;
1129 21         24 my $max_row = 0;
1130 21         76 for (split m/\s*;\s*/ => $range) {
1131 37 100       278 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       69 defined $brr or ($brr, $brc) = ($tlr, $tlc);
1136 36 100 100     1475 $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         26 $tlc--;
1141 28 100       42 $brc-- unless $brc eq "*";
1142 28 100       37 defined $min_row or $min_row = $tlr;
1143 28 100       34 $tlr < $min_row and $min_row = $tlr;
1144 28 100 100     61 $brr eq "*" || $brr > $max_row and
1145             $max_row = $brr;
1146 28         58 push @spec, [ $tlr, $tlc, $brr, $brc ];
1147             }
1148 12         16 my $r = 0;
1149 12         168 while (my $row = $self->getline ($io)) {
1150 77 100       283 ++$r < $min_row and next;
1151 33         32 my %row;
1152             my $lc;
1153 33         32 foreach my $s (@spec) {
1154 77         66 my ($tlr, $tlc, $brr, $brc) = @{$s};
  77         125  
1155 77 100 100     163 $r < $tlr || ($brr ne "*" && $r > $brr) and next;
      100        
1156 45 100 100     75 !defined $lc || $tlc < $lc and $lc = $tlc;
1157 45 100       51 my $rr = $brc eq "*" ? $#{$row} : $brc;
  5         6  
1158 45         127 $row{$_} = $row->[$_] for $tlc .. $rr;
1159             }
1160 33         75 push @c, [ @row{sort { $a <=> $b } keys %row } ];
  64         110  
1161 33 100       47 if (@h) {
1162 2         3 my %h; @h{@h} = @{$c[-1]};
  2         3  
  2         4  
1163 2         5 $c[-1] = \%h;
1164             }
1165 33 100 100     233 $max_row ne "*" && $r == $max_row and last;
1166             }
1167 12         62 return \@c;
1168             }
1169              
1170             # row or col
1171 17         20 my @r;
1172 17         22 my $eod = 0;
1173 17         55 for (split m/\s*;\s*/ => $range) {
1174 25 50       99 my ($from, $to) = m/^\s* ([0-9]+) (?: \s* - \s* ([0-9]+ | \* ))? \s* $/x
1175             or croak ($self->SetDiag (2013));
1176 25   100     64 $to ||= $from;
1177 25 100       57 $to eq "*" and ($to, $eod) = ($from, 1);
1178             # $to cannot be <= 0 due to regex and ||=
1179 25 100 100     439 $from <= 0 || $to < $from and croak ($self->SetDiag (2013));
1180 22         64 $r[$_] = 1 for $from .. $to;
1181             }
1182              
1183 14         50 my $r = 0;
1184 14 100       27 $type eq "col" and shift @r;
1185 14   100     96 $_ ||= 0 for @r;
1186 14         350 while (my $row = $self->getline ($io)) {
1187 109         124 $r++;
1188 109 100       120 if ($type eq "row") {
1189 64 100 100     174 if (($r > $#r && $eod) || $r[$r]) {
      100        
1190 20         23 push @c, $row;
1191 20 100       26 if (@h) {
1192 3         4 my %h; @h{@h} = @{$c[-1]};
  3         3  
  3         11  
1193 3         6 $c[-1] = \%h;
1194             }
1195             }
1196 64         342 next;
1197             }
1198 45 100 100     44 push @c, [ map { ($_ > $#r && $eod) || $r[$_] ? $row->[$_] : () } 0..$#{$row} ];
  405         866  
  45         54  
1199 45 100       226 if (@h) {
1200 9         8 my %h; @h{@h} = @{$c[-1]};
  9         10  
  9         30  
1201 9         55 $c[-1] = \%h;
1202             }
1203             }
1204              
1205 14         73 return \@c;
1206             } # fragment
1207              
1208             my $csv_usage = q{usage: my $aoa = csv (in => $file);};
1209              
1210             sub _csv_attr {
1211 345     345   477 my %attr;
1212 345 100 100     1268 if (@_ == 1 && ref $_[0] eq "HASH") {
    100          
1213 4         5 %attr = %{$_[0]};
  4         10  
1214             }
1215             elsif (scalar @_ % 2) {
1216 1         106 croak (Text::CSV_XS->SetDiag (1502));
1217             }
1218             else {
1219 340         1249 %attr = @_;
1220             }
1221              
1222 344         655 $attr{'binary'} = 1;
1223 344         512 $attr{'strict_eol'} = 1;
1224              
1225 344   100     1375 my $enc = delete $attr{'enc'} || delete $attr{'encoding'} || "";
1226 344 100       705 $enc eq "auto" and ($attr{'detect_bom'}, $enc) = (1, "");
1227 344 50       849 my $stack = $enc =~ s/(:\w.*)// ? $1 : "";
1228 344 100       709 $enc =~ m/^[-\w.]+$/ and $enc = ":encoding($enc)";
1229 344         456 $enc .= $stack;
1230              
1231 344         476 my $hdrs = delete $attr{'headers'};
1232 344         410 my $frag = delete $attr{'fragment'};
1233 344         488 my $key = delete $attr{'key'};
1234 344         449 my $val = delete $attr{'value'};
1235             my $kh = delete $attr{'keep_headers'} ||
1236             delete $attr{'keep_column_names'} ||
1237 344   100     1299 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     1870 delete $attr{'after_parse'};
1243             my $cbbo = delete $attr{'callbacks'}{'before_out'} ||
1244 344   100     858 delete $attr{'before_out'};
1245             my $cboi = delete $attr{'callbacks'}{'on_in'} ||
1246 344   100     808 delete $attr{'on_in'};
1247             my $cboe = delete $attr{'callbacks'}{'on_error'} ||
1248 344   66     766 delete $attr{'on_error'};
1249              
1250             my $hd_s = delete $attr{'sep_set'} ||
1251 344   100     788 delete $attr{'seps'};
1252             my $hd_b = delete $attr{'detect_bom'} ||
1253 344   100     896 delete $attr{'bom'};
1254             my $hd_m = delete $attr{'munge'} ||
1255 344   100     772 delete $attr{'munge_column_names'};
1256 344         420 my $hd_c = delete $attr{'set_column_names'};
1257              
1258 344         422 my $fh;
1259 344         411 my $sink = 0;
1260 344         395 my $cls = 0; # If I open a file, I have to close it
1261 344 100 100     1275 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     1217 : delete $attr{'out'} || delete $attr{'file'};
      100        
1264              
1265 341 100 100     1067 ref $in eq "CODE" || ref $in eq "ARRAY" and $out ||= \*STDOUT;
      100        
1266              
1267 341         484 my ($fho, $fho_cls);
1268 341 100 66     1097 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     18 if (ref $out or "GLOB" eq ref \$out) {
1271 2         4 $fho = $out;
1272             }
1273             else {
1274 5 50       553 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         11 $fho_cls = 1;
1280             }
1281 7 100 66     17 if ($cboi && !$cbai) {
1282 1         2 $cbai = $cboi;
1283 1         2 $cboi = undef;
1284             }
1285 7 100       15 if ($cbai) {
1286 2         4 my $cb = $cbai;
1287 2     6   11 $cbai = sub { $cb->(@_); $_[0]->say ($fho, $_[1]); 0 };
  6         19  
  6         21  
  6         44  
1288             }
1289             else {
1290 5     15   19 $cbai = sub { $_[0]->say ($fho, $_[1]); 0 };
  15         45  
  15         126  
1291             }
1292              
1293             # Put all callbacks back in place for streaming behavior
1294 7         13 $attr{'callbacks'}{'after_parse'} = $cbai; $cbai = undef;
  7         9  
1295 7         14 $attr{'callbacks'}{'before_out'} = $cbbo; $cbbo = undef;
  7         9  
1296 7         9 $attr{'callbacks'}{'on_in'} = $cboi; $cboi = undef;
  7         6  
1297 7         10 $attr{'callbacks'}{'on_error'} = $cboe; $cboe = undef;
  7         8  
1298 7         8 $out = undef;
1299 7         7 $sink = 1;
1300             }
1301              
1302 341 100       678 if ($out) {
1303 33 100 100     202 if (ref $out and ("ARRAY" eq ref $out or "HASH" eq ref $out)) {
    100 100        
    100 100        
      100        
      66        
      66        
      66        
1304 5         5 delete $attr{'out'};
1305 5         6 $sink = 1;
1306             }
1307             elsif ((ref $out and "SCALAR" ne ref $out) or "GLOB" eq ref \$out) {
1308 14         15 $fh = $out;
1309             }
1310 7         24 elsif (ref $out and "SCALAR" eq ref $out and defined ${$out} and ${$out} eq "skip") {
  7         31  
1311 2         20 delete $attr{'out'};
1312 2         4 $sink = 1;
1313             }
1314             else {
1315 12 100       705 open $fh, ">", $out or croak ("$out: $!");
1316 11         27 $cls = 1;
1317             }
1318 32 100       54 if ($fh) {
1319 25 100       32 if ($enc) {
1320 1         11 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     72 unless (defined $attr{'eol'} || defined $fho) {
1324 18         21 my @layers = eval { PerlIO::get_layers ($fh) };
  18         107  
1325 18 100       94 $attr{'eol'} = (grep m/crlf/ => @layers) ? "\n" : "\r\n";
1326             }
1327             }
1328             }
1329              
1330 340 100 100     1612 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       330 open $fh, "<", $in or croak ("Cannot open from SCALAR using PerlIO");
1337 30         52 $cls = 1;
1338             }
1339             elsif (ref $in or "GLOB" eq ref \$in) {
1340 18 50 66     38 if (!ref $in && $] < 5.008005) {
1341 0         0 $fh = \*{$in}; # uncoverable statement ancient perl version required
  0         0  
1342             }
1343             else {
1344 18         19 $fh = $in;
1345             }
1346             }
1347             else {
1348 268 100       10896 open $fh, "<$enc", $in or croak ("$in: $!");
1349 266         1727 $cls = 1;
1350             }
1351 338 50 33     752 $fh || $sink or croak (qq{No valid source passed. "in" is required});
1352              
1353 338         1166 for ([ 'quo' => "quote" ],
1354             [ 'esc' => "escape" ],
1355             [ 'escape' => "escape_char" ],
1356             ) {
1357 1014         1060 my ($f, $t) = @{$_};
  1014         1599  
1358 1014 100 100     2191 exists $attr{$f} and !exists $attr{$t} and $attr{$t} = delete $attr{$f};
1359             }
1360              
1361 338         746 my $fltr = delete $attr{'filter'};
1362             my %fltr = (
1363 10 100 33 10   8 'not_blank' => sub { @{$_[1]} > 1 or defined $_[1][0] && $_[1][0] ne "" },
  10         49  
1364 10 50   10   8 'not_empty' => sub { grep { defined && $_ ne "" } @{$_[1]} },
  26         115  
  10         12  
1365 10 50   10   27 'filled' => sub { grep { defined && m/\S/ } @{$_[1]} },
  26         78  
  10         13  
1366 338         2406 );
1367             defined $fltr && !ref $fltr && exists $fltr{$fltr} and
1368 338 50 100     784 $fltr = { '0' => $fltr{$fltr} };
      66        
1369 338 100       646 ref $fltr eq "CODE" and $fltr = { 0 => $fltr };
1370 338 100       704 ref $fltr eq "HASH" or $fltr = undef;
1371              
1372 338         456 my $form = delete $attr{'formula'};
1373              
1374 338 100       761 defined $attr{'auto_diag'} or $attr{'auto_diag'} = 1;
1375 338 100       632 defined $attr{'escape_null'} or $attr{'escape_null'} = 0;
1376 338 50 66     1815 my $csv = delete $attr{'csv'} || Text::CSV_XS->new (\%attr)
1377             or croak ($last_err);
1378 338 100       499 defined $form and $csv->formula ($form);
1379 338 100       477 defined $cboe and $csv->callbacks (error => $cboe);
1380              
1381 338 100 100     614 $kh && !ref $kh && $kh =~ m/^(?:1|yes|true|internal|auto)$/i and
      100        
1382             $kh = \@internal_kh;
1383              
1384             return {
1385 338         6283 '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 614595 @_ && ref $_[0] eq __PACKAGE__ and splice @_, 0, 0, "csv";
1413 346 100       906 @_ or croak ($csv_usage);
1414              
1415 345         765 my $c = _csv_attr (@_);
1416              
1417 338         508 my ($csv, $in, $fh, $hdrs) = @{$c}{qw( csv in fh hdrs )};
  338         771  
1418 338         390 my %hdr;
1419 338 100       594 if (ref $hdrs eq "HASH") {
1420 2         3 %hdr = %{$hdrs};
  2         6  
1421 2         2 $hdrs = "auto";
1422             }
1423              
1424 338 100 100     657 if ($c->{'out'} && !$c->{'sink'}) {
1425             !$hdrs && ref $c->{'kh'} && $c->{'kh'} == \@internal_kh and
1426 24 100 100     67 $hdrs = $c->{'kh'};
      66        
1427              
1428 24 100 100     34 if (ref $in eq "CODE") {
    100          
1429 3         3 my $hdr = 1;
1430 3         10 while (my $row = $in->($csv)) {
1431 7 100       38 if (ref $row eq "ARRAY") {
1432 3         19 $csv->print ($fh, $row);
1433 3         16 next;
1434             }
1435 4 50       29 if (ref $row eq "HASH") {
1436 4 100       6 if ($hdr) {
1437 2 50 100     5 $hdrs ||= [ map { $hdr{$_} || $_ } keys %{$row} ];
  3         10  
  1         2  
1438 2         28 $csv->print ($fh, $hdrs);
1439 2         14 $hdr = 0;
1440             }
1441 4         4 $csv->print ($fh, [ @{$row}{@{$hdrs}} ]);
  4         36  
  4         4  
1442             }
1443             }
1444             }
1445 21         63 elsif (@{$in} == 0 or ref $in->[0] eq "ARRAY") { # aoa
1446 10 50       18 ref $hdrs and $csv->print ($fh, $hdrs);
1447 10         11 for (@{$in}) {
  10         16  
1448 12 100       53 $c->{'cboi'} and $c->{'cboi'}->($csv, $_);
1449 12 50       1052 $c->{'cbbo'} and $c->{'cbbo'}->($csv, $_);
1450 12         154 $csv->print ($fh, $_);
1451             }
1452             }
1453             else { # aoh
1454 11 100       14 my @hdrs = ref $hdrs ? @{$hdrs} : keys %{$in->[0]};
  5         25  
  6         14  
1455 11 100       30 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     183  
1458 11         94 for (@{$in}) {
  11         18  
1459 17         55 local %_;
1460 17         24 *_ = $_;
1461 17 50       26 $c->{'cboi'} and $c->{'cboi'}->($csv, $_);
1462 17 50       21 $c->{'cbbo'} and $c->{'cbbo'}->($csv, $_);
1463 17         16 $csv->print ($fh, [ @{$_}{@hdrs} ]);
  17         72  
1464             }
1465             }
1466              
1467 24 100       540 $c->{'cls'} and close $fh;
1468 24 50       48 $c->{'fho_cls'} and close $c->{'fho'};
1469 24         288 return 1;
1470             }
1471              
1472 314         343 my @row1;
1473 314 100 100     1117 if (defined $c->{'hd_s'} || defined $c->{'hd_b'} || defined $c->{'hd_m'} || defined $c->{'hd_c'}) {
      100        
      100        
1474 173         188 my %harg;
1475             !defined $c->{'hd_s'} && $c->{'attr'}{'sep_char'} and
1476 173 100 100     451 $c->{'hd_s'} = [ $c->{'attr'}{'sep_char'} ];
1477             !defined $c->{'hd_s'} && $c->{'attr'}{'sep'} and
1478 173 100 100     483 $c->{'hd_s'} = [ $c->{'attr'}{'sep'} ];
1479 173 100       301 defined $c->{'hd_s'} and $harg{'sep_set'} = $c->{'hd_s'};
1480 173 100       312 defined $c->{'hd_b'} and $harg{'detect_bom'} = $c->{'hd_b'};
1481 173 50       242 defined $c->{'hd_m'} and $harg{'munge_column_names'} = $hdrs ? "none" : $c->{'hd_m'};
    100          
1482 173 50       241 defined $c->{'hd_c'} and $harg{'set_column_names'} = $hdrs ? 0 : $c->{'hd_c'};
    100          
1483 173         425 @row1 = $csv->header ($fh, \%harg);
1484 170         347 my @hdr = $csv->column_names ();
1485 170 100 100     707 @hdr and $hdrs ||= \@hdr;
1486             }
1487              
1488 311 100       573 if ($c->{'kh'}) {
1489 15         21 @internal_kh = ();
1490 15 100       645 ref $c->{'kh'} eq "ARRAY" or croak ($csv->SetDiag (1501));
1491 10   100     37 $hdrs ||= "auto";
1492             }
1493              
1494 306         459 my $key = $c->{'key'};
1495 306 100       418 if ($key) {
1496 27 100 100     639 !ref $key or ref $key eq "ARRAY" && @{$key} > 1 or croak ($csv->SetDiag (1501));
  8   100     447  
1497 20   100     47 $hdrs ||= "auto";
1498             }
1499 299         340 my $val = $c->{'val'};
1500 299 100       434 if ($val) {
1501 9 100       155 $key or croak ($csv->SetDiag (1502));
1502 8 100 100     329 !ref $val or ref $val eq "ARRAY" && @{$val} > 0 or croak ($csv->SetDiag (1503));
  3   100     157  
1503             }
1504              
1505 295 100 100     536 $c->{'fltr'} && grep m/\D/ => keys %{$c->{'fltr'}} and $hdrs ||= "auto";
  17   100     81  
1506 295 100       465 if (defined $hdrs) {
1507 224 100 100     603 if (!ref $hdrs or ref $hdrs eq "CODE") {
1508 53 100       1635 my $h = $c->{'hd_b'}
1509             ? [ $csv->column_names () ]
1510             : $csv->getline ($fh);
1511 53   33     201 my $has_h = $h && @$h;
1512              
1513 53 100       157 if (ref $hdrs) {
    100          
    100          
    100          
    50          
1514 1 50       3 $has_h or return;
1515 1         2 my $cr = $hdrs;
1516 1   33     2 $hdrs = [ map { $cr->($hdr{$_} || $_) } @{$h} ];
  3         32  
  1         2  
1517             }
1518             elsif ($hdrs eq "skip") {
1519             # discard;
1520             }
1521             elsif ($hdrs eq "auto") {
1522 49 50       76 $has_h or return;
1523 49 100       59 $hdrs = [ map { $hdr{$_} || $_ } @{$h} ];
  139         413  
  49         73  
1524             }
1525             elsif ($hdrs eq "lc") {
1526 1 50       3 $has_h or return;
1527 1   33     1 $hdrs = [ map { lc ($hdr{$_} || $_) } @{$h} ];
  3         14  
  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         12  
  1         2  
1532             }
1533             }
1534 224 100 66     451 $c->{'kh'} and $hdrs and @{$c->{'kh'}} = @{$hdrs};
  10         22  
  10         12  
1535             }
1536              
1537 295 100       464 if ($c->{'fltr'}) {
1538 17         19 my %f = %{$c->{'fltr'}};
  17         61  
1539             # convert headers to index
1540 17         23 my @hdr;
1541 17 100       26 if (ref $hdrs) {
1542 8         8 @hdr = @{$hdrs};
  8         15  
1543 8         22 for (0 .. $#hdr) {
1544 24 100       50 exists $f{$hdr[$_]} and $f{$_ + 1} = delete $f{$hdr[$_]};
1545             }
1546             }
1547             $csv->callbacks ('after_parse' => sub {
1548 116     116   432 my ($CSV, $ROW) = @_; # lexical sub-variables in caps
1549 116         161 foreach my $FLD (sort keys %f) {
1550 117         162 local $_ = $ROW->[$FLD - 1];
1551 117         131 local %_;
1552 117 100       127 @hdr and @_{@hdr} = @{$ROW};
  53         101  
1553 117 100       164 $f{$FLD}->($CSV, $ROW) or return \"skip";
1554 53         408 $ROW->[$FLD - 1] = $_;
1555             }
1556 17         82 });
1557             }
1558              
1559 295         350 my $frag = $c->{'frag'};
1560             my $ref = ref $hdrs
1561             ? # aoh
1562 295 100       3903 do {
    100          
1563 223         420 my @h = $csv->column_names ($hdrs);
1564 223         254 my %h; $h{$_}++ for @h;
  223         535  
1565 223 50       353 exists $h{''} and croak ($csv->SetDiag (1012));
1566 223 50       402 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       588 $key ? do {
    100          
    100          
1572 17 100       38 my ($k, $j, @f) = ref $key ? (undef, @{$key}) : ($key);
  5         9  
1573 17 100       24 if (my @mk = grep { !exists $h{$_} } grep { defined } $k, @f) {
  22         48  
  27         50  
1574 2         8 croak ($csv->_SetDiagInfo (4001, join ", " => @mk));
1575             }
1576             +{ map {
1577 26         27 my $r = $_;
1578 26 100       50 my $K = defined $k ? $r->{$k} : join $j => @{$r}{@f};
  4         10  
1579             ( $K => (
1580             $val
1581             ? ref $val
1582 4         15 ? { map { $_ => $r->{$_} } @{$val} }
  2         3  
1583 26 100       87 : $r->{$val}
    100          
1584             : $r ));
1585 15         16 } @{$csv->getline_hr_all ($fh)} }
  15         29  
1586             }
1587             : $csv->getline_hr_all ($fh);
1588             }
1589             : # aoa
1590             $frag ? $csv->fragment ($fh, $frag)
1591             : $csv->getline_all ($fh);
1592 287 50       526 if ($ref) {
1593 287 100 66     867 @row1 && !$c->{'hd_c'} && !ref $hdrs and unshift @{$ref}, \@row1;
  4   100     6  
1594             }
1595             else {
1596 0         0 Text::CSV_XS->auto_diag ();
1597             }
1598 287 100       3279 $c->{'cls'} and close $fh;
1599 287 50       624 $c->{'fho_cls'} and close $c->{'fho'};
1600 287 100 100     1046 if ($ref and $c->{'cbai'} || $c->{'cboi'}) {
      66        
1601             # Default is ARRAYref, but with key =>, you'll get a hashref
1602 23 100       47 foreach my $r (ref $ref eq "ARRAY" ? @{$ref} : values %{$ref}) {
  22         34  
  1         3  
1603 74         5801 local %_;
1604 74 100       165 ref $r eq "HASH" and *_ = $r;
1605 74 100       153 $c->{'cbai'} and $c->{'cbai'}->($csv, $r);
1606 74 100       3642 $c->{'cboi'} and $c->{'cboi'}->($csv, $r);
1607             }
1608             }
1609              
1610 287 100       1546 if ($c->{'sink'}) {
1611 14 100       341 my $ro = ref $c->{'out'} or return;
1612              
1613 7 100 66     20 $ro eq "SCALAR" && ${$c->{'out'}} eq "skip" and
  2         29  
1614             return;
1615              
1616 5 50       10 $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     19  
1621 2         3 push @{$c->{'out'}} => @$ref;
  2         6  
1622 2         25 return $c->{'out'};
1623             }
1624 2         5 croak ($csv->_SetDiagInfo (5001, "Output type mismatch"));
1625             }
1626              
1627 1 50       3 if ($ro eq "HASH") {
1628 1         2 @{$c->{'out'}}{keys %{$ref}} = values %{$ref};
  1         3  
  1         13  
  1         2  
1629 1         14 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       408 %{$c->{'attr'}},
  1         21  
1640             );
1641              
1642 272   100     946 $last_err ||= $csv->{'_ERROR_DIAG'};
1643 272         4036 return $ref;
1644             } # csv
1645              
1646             1;
1647              
1648             __END__