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   3249767 use strict;
  35         69  
  35         1301  
19 35     35   165 use warnings;
  35         83  
  35         1951  
20              
21             require Exporter;
22 35     35   193 use XSLoader;
  35         46  
  35         704  
23 35     35   145 use Carp;
  35         90  
  35         2419  
24              
25 35     35   227 use vars qw( $VERSION @ISA @EXPORT_OK %EXPORT_TAGS );
  35         50  
  35         8612  
26             $VERSION = "1.63";
27             @ISA = qw( Exporter );
28             XSLoader::load ("Text::CSV_XS", $VERSION);
29              
30 4     4 1 12 sub PV { 0 } sub CSV_TYPE_PV { PV }
  12     12 1 130315  
31 4     4 1 10 sub IV { 1 } sub CSV_TYPE_IV { IV }
  12     12 1 142998  
32 4     4 1 12 sub NV { 2 } sub CSV_TYPE_NV { NV }
  12     12 1 74  
33              
34 11     11 1 58 sub CSV_FLAGS_IS_QUOTED { 0x0001 }
35 12     12 1 53 sub CSV_FLAGS_IS_BINARY { 0x0002 }
36 4     4 1 20 sub CSV_FLAGS_ERROR_IN_FIELD { 0x0004 }
37 20     20 1 76 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   200 no warnings "redefine";
  35         67  
  35         417708  
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 646 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   25294 my ($self, $aw) = @_;
132 15739 100       44055 $aw or return 0; # no checks needed without allow_whitespace
133              
134 3569         4986 my $quo = $self->{'quote'};
135 3569 100 100     8065 defined $quo && length ($quo) or $quo = $self->{'quote_char'};
136 3569         4580 my $esc = $self->{'escape_char'};
137              
138 3569 100 100     40802 defined $quo && $quo =~ m/^[ \t]/ and return 1002;
139 3327 100 100     43148 defined $esc && $esc =~ m/^[ \t]/ and return 1002;
140              
141 3037         7058 return 0;
142             } # _unhealty_whitespace
143              
144             sub _check_sanity {
145 12433     12433   16170 my $self = shift;
146              
147 12433         18441 my $eol = $self->{'eol'};
148 12433         17080 my $sep = $self->{'sep'};
149 12433 100 100     28117 defined $sep && length ($sep) or $sep = $self->{'sep_char'};
150 12433         15428 my $quo = $self->{'quote'};
151 12433 100 100     25708 defined $quo && length ($quo) or $quo = $self->{'quote_char'};
152 12433         16388 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       22593 $sep ne "" or return 1008;
160 12431 100       21117 length ($sep) > 16 and return 1006;
161 12430 100       31263 $sep =~ m/[\r\n]/ and return 1003;
162              
163 12424 100       20358 if (defined $quo) {
164 12414 100       58101 $quo eq $sep and return 1001;
165 12186 100       18537 length ($quo) > 16 and return 1007;
166 12185 100       22789 $quo =~ m/[\r\n]/ and return 1003;
167             }
168 12189 100       17839 if (defined $esc) {
169 12173 100       46572 $esc eq $sep and return 1001;
170 12005 100       21936 $esc =~ m/[\r\n]/ and return 1003;
171             }
172 12015 100       17573 if (defined $eol) {
173 12010 100       17037 length ($eol) > 16 and return 1005;
174             }
175              
176 12014         20780 return _unhealthy_whitespace ($self, $self->{'allow_whitespace'});
177             } # _check_sanity
178              
179             sub known_attributes {
180 3     3 1 613 sort grep !m/^_/ => "sep", "quote", keys %def_attr;
181             } # known_attributes
182              
183             sub new {
184 1009     1009 1 55921694 $last_err = Text::CSV_XS->SetDiag (1000,
185             "usage: my \$csv = Text::CSV_XS->new ([{ option => value, ... }]);");
186              
187 1009         2021 my $proto = shift;
188 1009 100 100     4956 my $class = ref $proto || $proto or return;
189 1008 100 100     4266 @_ > 0 && ref $_[0] ne "HASH" and return;
190 1000   100     2188 my $attr = shift || +{};
191             my %attr = map {
192 2765 100       9058 my $k = m/^[a-zA-Z]\w+$/ ? lc $_ : $_;
193 2765 100       5136 exists $attr_alias{$k} and $k = $attr_alias{$k};
194 2765         6669 ($k => $attr->{$_});
195 1000         1450 } keys %{$attr};
  1000         3051  
196              
197 1000         2185 my $sep_aliased = 0;
198 1000 100       2292 if (exists $attr{'sep'}) {
199 10         26 $attr{'sep_char'} = delete $attr{'sep'};
200 10         16 $sep_aliased = 1;
201             }
202 1000         1394 my $quote_aliased = 0;
203 1000 100       1934 if (exists $attr{'quote'}) {
204 25         46 $attr{'quote_char'} = delete $attr{'quote'};
205 25         29 $quote_aliased = 1;
206             }
207             exists $attr{'formula_handling'} and
208 1000 100       1780 $attr{'formula'} = delete $attr{'formula_handling'};
209 1000         1487 my $attr_formula = delete $attr{'formula'};
210              
211 1000         2415 for (keys %attr) {
212 2728 100 100     7948 if (m/^[a-z]/ && exists $def_attr{$_}) {
213             # uncoverable condition false
214 2721 100 100     7578 defined $attr{$_} && m/_char$/ and utf8::decode ($attr{$_});
215 2721         3812 next;
216             }
217             # croak?
218 7         29 $last_err = Text::CSV_XS->SetDiag (1000, "INI - Unknown attribute '$_'");
219 7 100       18 $attr{'auto_diag'} and error_diag ();
220 7         35 return;
221             }
222 993 100       2129 if ($sep_aliased) {
223 10         41 my @b = unpack "U0C*", $attr{'sep_char'};
224 10 100       26 if (@b > 1) {
225 6         11 $attr{'sep'} = $attr{'sep_char'};
226 6         13 $attr{'sep_char'} = "\0";
227             }
228             else {
229 4         10 $attr{'sep'} = undef;
230             }
231             }
232 993 100 100     2274 if ($quote_aliased and defined $attr{'quote_char'}) {
233 21         62 my @b = unpack "U0C*", $attr{'quote_char'};
234 21 100       39 if (@b > 1) {
235 7         11 $attr{'quote'} = $attr{'quote_char'};
236 7         13 $attr{'quote_char'} = "\0";
237             }
238             else {
239 14         25 $attr{'quote'} = undef;
240             }
241             }
242              
243 993         19845 my $self = { %def_attr, %attr };
244 993 100       3788 if (my $ec = _check_sanity ($self)) {
245 35         179 $last_err = Text::CSV_XS->SetDiag ($ec);
246 35 100       79 $attr{'auto_diag'} and error_diag ();
247 35         286 return;
248             }
249 958 100 100     2607 if (defined $self->{'callbacks'} && ref $self->{'callbacks'} ne "HASH") {
250 6         965 carp ("The 'callbacks' attribute is set but is not a hash: ignored\n");
251 6         46 $self->{'callbacks'} = undef;
252             }
253              
254 958         3778 $last_err = Text::CSV_XS->SetDiag (0);
255 958 100 100     2786 defined $\ && !exists $attr{'eol'} and $self->{'eol'} = $\;
256 958         1616 bless $self, $class;
257 958 100       2007 defined $self->{'types'} and $self->types ($self->{'types'});
258 958 50       2718 defined $self->{'skip_empty_rows'} and $self->{'skip_empty_rows'} = _supported_skip_empty_rows ($self, $self->{'skip_empty_rows'});
259 958 100       2694 defined $attr_formula and $self->{'formula'} = _supported_formula ($self, $attr_formula);
260 957         6136 $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   20896 my ($self, $name, $val, $ec) = @_;
303 11108 100       43724 defined $val and utf8::decode ($val);
304 11108         17246 $self->{$name} = $val;
305 11108 100       19378 $ec = _check_sanity ($self) and croak ($self->SetDiag ($ec));
306 10198         46184 $self->_cache_set ($_cache_id{$name}, $val);
307             } # _set_attr_C
308              
309             # A flag
310             sub _set_attr_X {
311 5644     5644   9509 my ($self, $name, $val) = @_;
312 5644 100       9707 defined $val or $val = 0;
313 5644         8919 $self->{$name} = $val;
314 5644         21401 $self->_cache_set ($_cache_id{$name}, 0 + $val);
315             } # _set_attr_X
316              
317             # A number
318             sub _set_attr_N {
319 68     68   181 my ($self, $name, $val) = @_;
320 68         197 $self->{$name} = $val;
321 68         339 $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 767358 my $self = shift;
328 4836 100       11616 if (@_) {
329 3601         7920 $self->_set_attr_C ("quote_char", shift);
330 3374         7963 $self->_cache_set ($_cache_id{'quote'}, "");
331             }
332 4609         13638 $self->{'quote_char'};
333             } # quote_char
334              
335             sub quote {
336 20     20 1 42 my $self = shift;
337 20 100       64 if (@_) {
338 11         18 my $quote = shift;
339 11 100       30 defined $quote or $quote = "";
340 11         31 utf8::decode ($quote);
341 11         38 my @b = unpack "U0C*", $quote;
342 11 100       27 if (@b > 1) {
343 5 100       123 @b > 16 and croak ($self->SetDiag (1007));
344 4         12 $self->quote_char ("\0");
345             }
346             else {
347 6         17 $self->quote_char ($quote);
348 6         9 $quote = "";
349             }
350 10         17 $self->{'quote'} = $quote;
351              
352 10         22 my $ec = _check_sanity ($self);
353 10 100       179 $ec and croak ($self->SetDiag ($ec));
354              
355 9         21 $self->_cache_set ($_cache_id{'quote'}, $quote);
356             }
357 18         26 my $quote = $self->{'quote'};
358 18 100 100     101 defined $quote && length ($quote) ? $quote : $self->{'quote_char'};
359             } # quote
360              
361             sub escape_char {
362 4826     4826 1 776380 my $self = shift;
363 4826 100       11081 if (@_) {
364 3595         4653 my $ec = shift;
365 3595         8429 $self->_set_attr_C ("escape_char", $ec);
366 3480 100       6864 $ec or $self->_set_attr_X ("escape_null", 0);
367             }
368 4711         14407 $self->{'escape_char'};
369             } # escape_char
370              
371             sub sep_char {
372 5155     5155 1 768757 my $self = shift;
373 5155 100       11742 if (@_) {
374 3912         9051 $self->_set_attr_C ("sep_char", shift);
375 3344         7495 $self->_cache_set ($_cache_id{'sep'}, "");
376             }
377 4587         12892 $self->{'sep_char'};
378             } # sep_char
379              
380             sub sep {
381 359     359 1 3471 my $self = shift;
382 359 100       688 if (@_) {
383 326         535 my $sep = shift;
384 326 100       498 defined $sep or $sep = "";
385 326         989 utf8::decode ($sep);
386 326         1007 my @b = unpack "U0C*", $sep;
387 326 100       625 if (@b > 1) {
388 13 100       131 @b > 16 and croak ($self->SetDiag (1006));
389 12         27 $self->sep_char ("\0");
390             }
391             else {
392 313         670 $self->sep_char ($sep);
393 310         392 $sep = "";
394             }
395 322         542 $self->{'sep'} = $sep;
396              
397 322         390 my $ec = _check_sanity ($self);
398 322 100       605 $ec and croak ($self->SetDiag ($ec));
399              
400 321         821 $self->_cache_set ($_cache_id{'sep'}, $sep);
401             }
402 354         556 my $sep = $self->{'sep'};
403 354 100 100     1112 defined $sep && length ($sep) ? $sep : $self->{'sep_char'};
404             } # sep
405              
406             sub eol {
407 280     280 1 4477 my $self = shift;
408 280 100       488 if (@_) {
409 227         238 my $eol = shift;
410 227 100       367 defined $eol or $eol = ""; # Also reset strict_eol?
411 227 100       481 length ($eol) > 16 and croak ($self->SetDiag (1005));
412 226         291 $self->{'eol'} = $eol;
413 226         504 $self->_cache_set ($_cache_id{'eol'}, $eol);
414             }
415 279         920 $self->{'eol'};
416             } # eol
417              
418             sub eol_type {
419 32     32 1 34 my $self = shift;
420 32         185 $self->_cache_get_eolt;
421             } # eol_type
422              
423             sub always_quote {
424 3032     3032 1 795776 my $self = shift;
425 3032 100       8612 @_ and $self->_set_attr_X ("always_quote", shift);
426 3032         8157 $self->{'always_quote'};
427             } # always_quote
428              
429             sub quote_space {
430 10     10 1 25 my $self = shift;
431 10 100       41 @_ and $self->_set_attr_X ("quote_space", shift);
432 10         39 $self->{'quote_space'};
433             } # quote_space
434              
435             sub quote_empty {
436 5     5 1 10 my $self = shift;
437 5 100       18 @_ and $self->_set_attr_X ("quote_empty", shift);
438 5         18 $self->{'quote_empty'};
439             } # quote_empty
440              
441             sub escape_null {
442 6     6 1 9 my $self = shift;
443 6 100       20 @_ and $self->_set_attr_X ("escape_null", shift);
444 6         20 $self->{'escape_null'};
445             } # escape_null
446 3     3 1 9 sub quote_null { goto &escape_null; }
447              
448             sub quote_binary {
449 7     7 1 13 my $self = shift;
450 7 100       20 @_ and $self->_set_attr_X ("quote_binary", shift);
451 7         17 $self->{'quote_binary'};
452             } # quote_binary
453              
454             sub binary {
455 21     21 1 75033 my $self = shift;
456 21 100       105 @_ and $self->_set_attr_X ("binary", shift);
457 21         52 $self->{'binary'};
458             } # binary
459              
460             sub strict {
461 2     2 1 4 my $self = shift;
462 2 100       72 @_ and $self->_set_attr_X ("strict", shift);
463 2         11 $self->{'strict'};
464             } # strict
465              
466             sub strict_eol {
467 2     2 1 4 my $self = shift;
468 2 100       8 @_ 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 980     980   1558 my ($self, $f) = @_;
474 980 100       1590 defined $f or return 0;
475 979 100 66     3294 if ($self && $f && ref $f && ref $f eq "CODE") {
      100        
      66        
476 5         8 $self->{'_EMPTROW_CB'} = $f;
477 5         12 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       4201 $f =~ m/^(?: 6 | cb )$/xi ? 6 : do {
    100          
    100          
    100          
    100          
    100          
    100          
486 1   50     9 $self ||= "Text::CSV_XS";
487 1         8 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 811 my $self = shift;
493 24 100       79 @_ and $self->_set_attr_N ("skip_empty_rows", _supported_skip_empty_rows ($self, shift));
494 23         35 my $ser = $self->{'skip_empty_rows'};
495 23 100       55 $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       127 $self->{'_EMPTROW_CB'};
    100          
    100          
    100          
    100          
499             } # skip_empty_rows
500              
501             sub _SetDiagInfo {
502 18     18   41 my ($self, $err, $msg) = @_;
503 18         254 $self->SetDiag ($err);
504 18         53 my $em = $self->error_diag ();
505 18 50       80 $em =~ s/^\d+$// and $msg =~ s/^/# /;
506 18 50       71 my $sep = $em =~ m/[;\n]$/ ? "\n\t" : ": ";
507 18         2724 join $sep => grep m/\S\S\S/ => $em, $msg;
508             } # _SetDiagInfo
509              
510             sub _supported_formula {
511 103     103   240 my ($self, $f) = @_;
512 103 100       233 defined $f or return 5;
513 102 100 66     607 if ($self && $f && ref $f && ref $f eq "CODE") {
      100        
      100        
514 6         14 $self->{'_FORMULA_CB'} = $f;
515 6         19 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       1114 $f =~ m/^(?: 6 | cb )$/xi ? 6 : do {
    100          
    100          
    100          
    100          
    100          
    100          
524 7   50     21 $self ||= "Text::CSV_XS";
525 7         35 croak ($self->_SetDiagInfo (1500, "formula-handling '$f' is not supported"));
526             };
527             } # _supported_formula
528              
529             sub formula {
530 44     44 1 3030 my $self = shift;
531 44 100       185 @_ and $self->_set_attr_N ("formula", _supported_formula ($self, shift));
532 38 100       131 $self->{'formula'} == 6 or $self->{'_FORMULA_CB'} = undef;
533 38         167 [qw( none die croak diag empty undef cb )]->[_supported_formula ($self, $self->{'formula'})];
534             } # formula
535              
536             sub formula_handling {
537 7     7 1 16 my $self = shift;
538 7         21 $self->formula (@_);
539             } # formula_handling
540              
541             sub decode_utf8 {
542 2     2 1 4 my $self = shift;
543 2 100       9 @_ and $self->_set_attr_X ("decode_utf8", shift);
544 2         8 $self->{'decode_utf8'};
545             } # decode_utf8
546              
547             sub keep_meta_info {
548 12     12 1 782 my $self = shift;
549 12 100       39 if (@_) {
550 11         15 my $v = shift;
551 11 100 100     53 !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         30 $self->_set_attr_X ("keep_meta_info", $v);
554             }
555 12         45 $self->{'keep_meta_info'};
556             } # keep_meta_info
557              
558             sub allow_loose_quotes {
559 12     12 1 26 my $self = shift;
560 12 100       62 @_ and $self->_set_attr_X ("allow_loose_quotes", shift);
561 12         33 $self->{'allow_loose_quotes'};
562             } # allow_loose_quotes
563              
564             sub allow_loose_escapes {
565 12     12 1 1702 my $self = shift;
566 12 100       59 @_ and $self->_set_attr_X ("allow_loose_escapes", shift);
567 12         30 $self->{'allow_loose_escapes'};
568             } # allow_loose_escapes
569              
570             sub allow_whitespace {
571 4954     4954 1 2243532 my $self = shift;
572 4954 100       13581 if (@_) {
573 3725         4875 my $aw = shift;
574 3725 100       7141 _unhealthy_whitespace ($self, $aw) and
575             croak ($self->SetDiag (1002));
576 3721         8466 $self->_set_attr_X ("allow_whitespace", $aw);
577             }
578 4950         14047 $self->{'allow_whitespace'};
579             } # allow_whitespace
580              
581             sub allow_unquoted_escape {
582 3     3 1 6 my $self = shift;
583 3 100       1054 @_ and $self->_set_attr_X ("allow_unquoted_escape", shift);
584 3         11 $self->{'allow_unquoted_escape'};
585             } # allow_unquoted_escape
586              
587             sub blank_is_undef {
588 2     2 1 4 my $self = shift;
589 2 100       7 @_ and $self->_set_attr_X ("blank_is_undef", shift);
590 2         7 $self->{'blank_is_undef'};
591             } # blank_is_undef
592              
593             sub empty_is_undef {
594 2     2 1 4 my $self = shift;
595 2 100       7 @_ and $self->_set_attr_X ("empty_is_undef", shift);
596 2         7 $self->{'empty_is_undef'};
597             } # empty_is_undef
598              
599             sub verbatim {
600 9     9 1 17578 my $self = shift;
601 9 100       42 @_ and $self->_set_attr_X ("verbatim", shift);
602 9         28 $self->{'verbatim'};
603             } # verbatim
604              
605             sub undef_str {
606 13     13 1 3613 my $self = shift;
607 13 100       31 if (@_) {
608 12         16 my $v = shift;
609 12 100       41 $self->{'undef_str'} = defined $v ? "$v" : undef;
610 12         51 $self->_cache_set ($_cache_id{'undef_str'}, $self->{'undef_str'});
611             }
612 13         44 $self->{'undef_str'};
613             } # undef_str
614              
615             sub comment_str {
616 15     15 1 47 my $self = shift;
617 15 100       24 if (@_) {
618 14         22 my $v = shift;
619 14 100       33 $self->{'comment_str'} = defined $v ? "$v" : undef;
620 14         57 $self->_cache_set ($_cache_id{'comment_str'}, $self->{'comment_str'});
621             }
622 15         25 $self->{'comment_str'};
623             } # comment_str
624              
625             sub auto_diag {
626 12     12 1 296 my $self = shift;
627 12 100       30 if (@_) {
628 9         13 my $v = shift;
629 9 100 100     35 !defined $v || $v eq "" and $v = 0;
630 9 100       34 $v =~ m/^[0-9]/ or $v = lc $v eq "false" ? 0 : 1; # true/truth = 1
    100          
631 9         19 $self->_set_attr_X ("auto_diag", $v);
632             }
633 12         43 $self->{'auto_diag'};
634             } # auto_diag
635              
636             sub diag_verbose {
637 10     10 1 545 my $self = shift;
638 10 100       24 if (@_) {
639 8         8 my $v = shift;
640 8 100 100     32 !defined $v || $v eq "" and $v = 0;
641 8 100       30 $v =~ m/^[0-9]/ or $v = lc $v eq "false" ? 0 : 1; # true/truth = 1
    100          
642 8         18 $self->_set_attr_X ("diag_verbose", $v);
643             }
644 10         32 $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 9 my $self = shift;
654 5         21 return $self->{'_STATUS'};
655             } # status
656              
657             sub eof {
658 33     33 1 18097 my $self = shift;
659 33         195 return $self->{'_EOF'};
660             } # eof
661              
662             sub types {
663 7     7 1 1707 my $self = shift;
664 7 100       16 if (@_) {
665 2 100       7 if (my $types = shift) {
666 1         2 $self->{'_types'} = join "", map { chr } @{$types};
  3         23  
  1         4  
667 1         4 $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         21 $self->{'types'};
679             }
680             } # types
681              
682             sub callbacks {
683 75     75 1 20067 my $self = shift;
684 75 100       155 if (@_) {
685 45         50 my $cb;
686 45         47 my $hf = 0x00;
687 45 100       71 if (defined $_[0]) {
    100          
688 43 100       64 grep { !defined } @_ and croak ($self->SetDiag (1004));
  77         362  
689 41 100 100     930 $cb = @_ == 1 && ref $_[0] eq "HASH" ? shift
    100          
690             : @_ % 2 == 0 ? { @_ }
691             : croak ($self->SetDiag (1004));
692 36         38 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     1679 $cbk =~ m/^[\w.]+$/ && ref $cb->{$cbk} eq "CODE" or
696             croak ($self->SetDiag (1004));
697             }
698 22 100       54 exists $cb->{'error'} and $hf |= 0x01;
699 22 100       61 exists $cb->{'after_parse'} and $hf |= 0x02;
700 22 100       48 exists $cb->{'before_print'} and $hf |= 0x04;
701             }
702             elsif (@_ > 1) {
703             # (undef, whatever)
704 1         111 croak ($self->SetDiag (1004));
705             }
706 23         53 $self->_set_attr_X ("_has_hooks", $hf);
707 23         39 $self->{'callbacks'} = $cb;
708             }
709 53         154 $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 57661 my $self = shift;
719 1823         4541 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     12803 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         2592 $diag[0] = 0 + $self->{'_ERROR_DIAG'};
726 1644         2484 $diag[1] = $self->{'_ERROR_DIAG'};
727 1644 100       3194 $diag[2] = 1 + $self->{'_ERROR_POS'} if exists $self->{'_ERROR_POS'};
728 1644         2201 $diag[3] = $self->{'_RECNO'};
729 1644 100       2672 $diag[4] = $self->{'_ERROR_FLD'} if exists $self->{'_ERROR_FLD'};
730 1644 100 66     5078 $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     5280 return $self->{'callbacks'}{'error'}->(@diag);
      100        
734             }
735              
736 1813         2505 my $context = wantarray;
737 1813 100       3037 unless (defined $context) { # Void context, auto-diag
738 344 100 100     857 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       199 $diag[4] and $msg =~ s/$/ field $diag[4]/;
741 36 100       133 $diag[5] and $msg =~ s/$/ (XS#$diag[5])/;
742              
743 36 100 100     163 unless ($self && ref $self) { # auto_diag
744             # called without args in void context
745 4         38 warn $msg;
746 4         27 return;
747             }
748              
749             $self->{'diag_verbose'} && $self->{'_ERROR_INPUT'} and
750 32 50 66     144 $msg .= $self->{'_ERROR_INPUT'}."\n".
751             (" " x ($diag[2] - 1))."^\n";
752              
753 32         45 my $lvl = $self->{'auto_diag'};
754 32 100       65 if ($lvl < 2) {
755 29         97 my @c = caller (2);
756 29 50 66     128 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       225 $lvl > 1 ? die $msg : warn $msg;
768             }
769 337         2570 return;
770             }
771 1469 100       6339 return $context ? @diag : $diag[1];
772             } # error_diag
773              
774             sub record_number {
775 14     14 1 3053 my $self = shift;
776 14         47 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 347860 my $self = shift;
787 1400 100       4161 return ref $self->{'_STRING'} ? ${$self->{'_STRING'}} : undef;
  1399         5508  
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 15091 my $self = shift;
798 1603 100       3806 return ref $self->{'_FIELDS'} ? @{$self->{'_FIELDS'}} : undef;
  1602         9534  
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 683 my $self = shift;
810 21 100       80 return ref $self->{'_FFLAGS'} ? @{$self->{'_FFLAGS'}} : undef;
  16         68  
811             } # meta_info
812              
813             sub is_quoted {
814 12     12 1 2029 my ($self, $idx) = @_;
815             ref $self->{'_FFLAGS'} &&
816 12 100 100     93 $idx >= 0 && $idx < @{$self->{'_FFLAGS'}} or return;
  8   100     27  
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 241 my ($self, $idx) = @_;
822             ref $self->{'_FFLAGS'} &&
823 11 100 100     50 $idx >= 0 && $idx < @{$self->{'_FFLAGS'}} or return;
  9   100     24  
824 8 100       19 $self->{'_FFLAGS'}[$idx] & CSV_FLAGS_IS_BINARY () ? 1 : 0;
825             } # is_binary
826              
827             sub is_missing {
828 19     19 1 32 my ($self, $idx) = @_;
829 19 100 100     102 $idx < 0 || !ref $self->{'_FFLAGS'} and return;
830 11 100       13 $idx >= @{$self->{'_FFLAGS'}} and return 1;
  11         26  
831 10 100       22 $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 804618 my $self = shift;
847 1399         2817 my $str = "";
848 1399         6127 $self->{'_FIELDS'} = \@_;
849 1399   100     27550 $self->{'_STATUS'} = (@_ > 0) && $self->Combine (\$str, \@_, 0);
850 1395         3548 $self->{'_STRING'} = \$str;
851 1395         4928 $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 129349 my ($self, $str) = @_;
868              
869 1947 100       5961 ref $str and croak ($self->SetDiag (1500));
870              
871 1943         2921 my $fields = [];
872 1943         2487 my $fflags = [];
873 1943         4040 $self->{'_STRING'} = \$str;
874 1943 100 100     40790 if (defined $str && $self->Parse ($str, $fields, $fflags)) {
875 1729         4749 $self->{'_FIELDS'} = $fields;
876 1729         3321 $self->{'_FFLAGS'} = $fflags;
877 1729         3116 $self->{'_STATUS'} = 1;
878             }
879             else {
880 211         474 $self->{'_FIELDS'} = undef;
881 211         336 $self->{'_FFLAGS'} = undef;
882 211         380 $self->{'_STATUS'} = 0;
883             }
884 1940         7797 $self->{'_STATUS'};
885             } # parse
886              
887             sub column_names {
888 1025     1025 1 49824 my ($self, @keys) = @_;
889             @keys or
890 1025 100       2155 return defined $self->{'_COLUMN_NAMES'} ? @{$self->{'_COLUMN_NAMES'}} : ();
  293 100       1153  
891              
892             @keys == 1 && ! defined $keys[0] and
893 689 100 100     2057 return $self->{'_COLUMN_NAMES'} = undef;
894              
895 551 100 100     1360 if (@keys == 1 && ref $keys[0] eq "ARRAY") {
    100          
896 227         282 @keys = @{$keys[0]};
  227         419  
897             }
898 712 100       1840 elsif (join "", map { defined $_ ? ref $_ : "" } @keys) {
899 5         718 croak ($self->SetDiag (3001));
900             }
901              
902 546 100 100     1092 $self->{'_BOUND_COLUMNS'} && @keys != @{$self->{'_BOUND_COLUMNS'}} and
  2         111  
903             croak ($self->SetDiag (3003));
904              
905 545 100       605 $self->{'_COLUMN_NAMES'} = [ map { defined $_ ? $_ : "\cAUNDEF\cA" } @keys ];
  1262         2425  
906 545         650 @{$self->{'_COLUMN_NAMES'}};
  545         1152  
907             } # column_names
908              
909             sub header {
910 333     333 1 40127 my ($self, $fh, @args) = @_;
911              
912 333 100       952 $fh or croak ($self->SetDiag (1014));
913              
914 332         428 my (@seps, %args);
915 332         653 for (@args) {
916 225 100       463 if (ref $_ eq "ARRAY") {
917 18         16 push @seps, @{$_};
  18         41  
918 18         32 next;
919             }
920 207 100       322 if (ref $_ eq "HASH") {
921 206         200 %args = %{$_};
  206         470  
922 206         383 next;
923             }
924 1         162 croak ('usage: $csv->header ($fh, [ seps ], { options })');
925             }
926              
927             defined $args{'munge'} && !defined $args{'munge_column_names'} and
928 331 100 66     918 $args{'munge_column_names'} = $args{'munge'}; # munge as alias
929 331 100       760 defined $args{'detect_bom'} or $args{'detect_bom'} = 1;
930 331 100       747 defined $args{'set_column_names'} or $args{'set_column_names'} = 1;
931 331 100       677 defined $args{'munge_column_names'} or $args{'munge_column_names'} = "lc";
932              
933             # Reset any previous leftovers
934 331         473 $self->{'_RECNO'} = 0;
935 331         479 $self->{'_AHEAD'} = undef;
936 331 100       620 $self->{'_COLUMN_NAMES'} = undef if $args{'set_column_names'};
937 331 100       603 $self->{'_BOUND_COLUMNS'} = undef if $args{'set_column_names'};
938              
939 331 100       508 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         28 @seps = @{$args{'sep_set'}};
  22         62  
943             }
944              
945 326 50       977 $^O eq "MSWin32" and binmode $fh;
946 326         5907 my $hdr = <$fh>;
947             # check if $hdr can be empty here, I don't think so
948 326 100 66     1519 defined $hdr && $hdr ne "" or croak ($self->SetDiag (1010));
949              
950 324         359 my %sep;
951 324 100       691 @seps or @seps = (",", ";");
952 324         497 foreach my $sep (@seps) {
953 732 100       1706 index ($hdr, $sep) >= 0 and $sep{$sep}++;
954             }
955              
956 324 100       737 keys %sep >= 2 and croak ($self->SetDiag (1011));
957              
958 320         1154 $self->sep (keys %sep);
959 320         490 my $enc = "";
960 320 100       530 if ($args{'detect_bom'}) { # UTF-7 is not supported
961 319 100       2305 if ($hdr =~ s/^\x00\x00\xfe\xff//) { $enc = "utf-32be" }
  24 100       31  
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
962 24         96 elsif ($hdr =~ s/^\xff\xfe\x00\x00//) { $enc = "utf-32le" }
963 25         40 elsif ($hdr =~ s/^\xfe\xff//) { $enc = "utf-16be" }
964 24         39 elsif ($hdr =~ s/^\xff\xfe//) { $enc = "utf-16le" }
965 48         62 elsif ($hdr =~ s/^\xef\xbb\xbf//) { $enc = "utf-8" }
966 1         4 elsif ($hdr =~ s/^\xf7\x64\x4c//) { $enc = "utf-1" }
967 1         3 elsif ($hdr =~ s/^\xdd\x73\x66\x73//) { $enc = "utf-ebcdic" }
968 1         2 elsif ($hdr =~ s/^\x0e\xfe\xff//) { $enc = "scsu" }
969 1         4 elsif ($hdr =~ s/^\xfb\xee\x28//) { $enc = "bocu-1" }
970 1         3 elsif ($hdr =~ s/^\x84\x31\x95\x33//) { $enc = "gb-18030" }
971 36         72 elsif ($hdr =~ s/^\x{feff}//) { $enc = "" }
972              
973 319 100       689 $self->{'ENCODING'} = $enc ? uc $enc : undef;
974              
975 319 100       1488 $hdr eq "" and croak ($self->SetDiag (1010));
976              
977 313 100       474 if ($enc) {
978 144 50 33     349 $ebcdic && $enc eq "utf-ebcdic" and $enc = "";
979 144 100       394 if ($enc =~ m/([13]).le$/) {
980 48         141 my $l = 0 + $1;
981 48         53 my $x;
982 48         93 $hdr .= "\0" x $l;
983 48         148 read $fh, $x, $l;
984             }
985 144 50       206 if ($enc) {
986 144 100       207 if ($enc ne "utf-8") {
987 96         585 require Encode;
988 96         587 $hdr = Encode::decode ($enc, $hdr);
989             }
990 144     2   4756 binmode $fh, ":encoding($enc)";
  2         1234  
  2         27  
  2         7  
991             }
992             }
993             }
994              
995 314         6830 my ($ahead, $eol);
996 314 100 66     1030 if ($hdr and $hdr =~ s/\Asep=(\S)([\r\n]+)//i) { # Also look in xs:Parse
997 1         3 $self->sep ($1);
998 1 50       5 length $hdr or $hdr = <$fh>;
999             }
1000 314 100       1866 if ($hdr =~ s/^([^\r\n]+)([\r\n]+)([^\r\n].+)\z/$1/s) {
1001 142         285 $eol = $2;
1002 142         279 $ahead = $3;
1003             }
1004              
1005 314         470 my $hr = \$hdr;
1006 314 50       2634 open my $h, "<", $hr or croak ($self->SetDiag (1010));
1007              
1008 314 100       6203 my $row = $self->getline ($h) or croak ();
1009 312         710 close $h;
1010              
1011 312 100       634 if ( $args{'munge_column_names'} eq "lc") {
    100          
    100          
1012 293         349 $_ = lc for @{$row};
  293         915  
1013             }
1014             elsif ($args{'munge_column_names'} eq "uc") {
1015 7         9 $_ = uc for @{$row};
  7         36  
1016             }
1017             elsif ($args{'munge_column_names'} eq "db") {
1018 3         4 for (@{$row}) {
  3         7  
1019 7         10 s/\W+/_/g;
1020 7         14 s/^_+//;
1021 7         12 $_ = lc;
1022             }
1023             }
1024              
1025 312 100       478 if ($ahead) { # Must be after getline, which creates the cache
1026 142         398 $self->_cache_set ($_cache_id{'_has_ahead'}, 1);
1027 142         217 $self->{'_AHEAD'} = $ahead;
1028 142 100       548 $eol =~ m/^\r([^\n]|\z)/ and $self->eol ($eol);
1029             }
1030              
1031 312         305 my @hdr = @{$row};
  312         648  
1032             ref $args{'munge_column_names'} eq "CODE" and
1033 312 100       603 @hdr = map { $args{'munge_column_names'}->($_) } @hdr;
  4         19  
1034             ref $args{'munge_column_names'} eq "HASH" and
1035 312 100       497 @hdr = map { $args{'munge_column_names'}->{$_} || $_ } @hdr;
  3 100       14  
1036 312         358 my %hdr; $hdr{$_}++ for @hdr;
  312         980  
1037 312 100       613 exists $hdr{''} and croak ($self->SetDiag (1012));
1038 310 100       514 unless (keys %hdr == @hdr) {
1039             croak ($self->_SetDiagInfo (1013, join ", " =>
1040 1         3 map { "$_ ($hdr{$_})" } grep { $hdr{$_} > 1 } keys %hdr));
  1         6  
  2         5  
1041             }
1042 309 100       936 $args{'set_column_names'} and $self->column_names (@hdr);
1043 309 100       2486 wantarray ? @hdr : $self;
1044             } # header
1045              
1046             sub bind_columns {
1047 36     36 1 6748 my ($self, @refs) = @_;
1048             @refs or
1049 36 100       109 return defined $self->{'_BOUND_COLUMNS'} ? @{$self->{'_BOUND_COLUMNS'}} : undef;
  2 100       9  
1050              
1051 32 100 100     154 if (@refs == 1 && ! defined $refs[0]) {
1052 5         11 $self->{'_COLUMN_NAMES'} = undef;
1053 5         20 return $self->{'_BOUND_COLUMNS'} = undef;
1054             }
1055              
1056 27 100 100     93 $self->{'_COLUMN_NAMES'} && @refs != @{$self->{'_COLUMN_NAMES'}} and
  3         115  
1057             croak ($self->SetDiag (3003));
1058              
1059 26 100       295 join "", map { ref $_ eq "SCALAR" ? "" : "*" } @refs and
  74632 100       110079  
1060             croak ($self->SetDiag (3004));
1061              
1062 24         2661 $self->_set_attr_N ("_is_bound", scalar @refs);
1063 24         4322 $self->{'_BOUND_COLUMNS'} = [ @refs ];
1064 24         1142 @refs;
1065             } # bind_columns
1066              
1067             sub getline_hr {
1068 131     131 1 13984 my ($self, @args, %hr) = @_;
1069 131 100       481 $self->{'_COLUMN_NAMES'} or croak ($self->SetDiag (3002));
1070 130 100       1958 my $fr = $self->getline (@args) or return;
1071 127 100       435 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         9  
  5         17  
1074 5         27 @{$fr} == 1 && (!defined $fr->[0] || $fr->[0] eq "") and
1075 5 100 33     7 $self->{'_FFLAGS'}[0] ||= CSV_FLAGS_IS_MISSING ();
      66        
      100        
1076             }
1077 127         204 @hr{@{$self->{'_COLUMN_NAMES'}}} = @{$fr};
  127         533  
  127         236  
1078 127         848 \%hr;
1079             } # getline_hr
1080              
1081             sub getline_hr_all {
1082 251     251 1 358 my ($self, @args) = @_;
1083 251 100       994 $self->{'_COLUMN_NAMES'} or croak ($self->SetDiag (3002));
1084 249         239 my @cn = @{$self->{'_COLUMN_NAMES'}};
  249         420  
1085 249         276 [ map { my %h; @h{@cn} = @{$_}; \%h } @{$self->getline_all (@args)} ];
  376         510  
  376         413  
  376         1143  
  376         1517  
  249         4795  
1086             } # getline_hr_all
1087              
1088             sub say {
1089 34     34 1 3360 my ($self, $io, @f) = @_;
1090 34         99 my $eol = $self->eol ();
1091             # say ($fh, undef) does not propage actual undef to print ()
1092 34 100 66     355 my $state = $self->print ($io, @f == 1 && !defined $f[0] ? undef : @f);
1093 34 100       388 unless (length $eol) {
1094 32   33     56 $eol = $self->eol_type () || $\ || $/;
1095 32         58 print $io $eol;
1096             }
1097 34         84 return $state;
1098             } # say
1099              
1100             sub print_hr {
1101 3     3 1 283 my ($self, $io, $hr) = @_;
1102 3 100       253 $self->{'_COLUMN_NAMES'} or croak ($self->SetDiag (3009));
1103 2 100       181 ref $hr eq "HASH" or croak ($self->SetDiag (3010));
1104 1         4 $self->print ($io, [ map { $hr->{$_} } $self->column_names () ]);
  3         11  
1105             } # print_hr
1106              
1107             sub fragment {
1108 58     58 1 23509 my ($self, $io, $spec) = @_;
1109              
1110 58         180 my $qd = qr{\s* [0-9]+ \s* }x; # digit
1111 58         112 my $qs = qr{\s* (?: [0-9]+ | \* ) \s*}x; # digit or star
1112 58         487 my $qr = qr{$qd (?: - $qs )?}x; # range
1113 58         417 my $qc = qr{$qr (?: ; $qr )*}x; # list
1114 58 100 100     4789 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         141 my ($type, $range) = (lc $1, $2);
1122              
1123 38         86 my @h = $self->column_names ();
1124              
1125 38         43 my @c;
1126 38 100       64 if ($type eq "cell") {
1127 21         26 my @spec;
1128             my $min_row;
1129 21         26 my $max_row = 0;
1130 21         75 for (split m/\s*;\s*/ => $range) {
1131 37 100       284 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     1172 $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         24 $tlc--;
1141 28 100       41 $brc-- unless $brc eq "*";
1142 28 100       38 defined $min_row or $min_row = $tlr;
1143 28 100       39 $tlr < $min_row and $min_row = $tlr;
1144 28 100 100     58 $brr eq "*" || $brr > $max_row and
1145             $max_row = $brr;
1146 28         81 push @spec, [ $tlr, $tlc, $brr, $brc ];
1147             }
1148 12         16 my $r = 0;
1149 12         158 while (my $row = $self->getline ($io)) {
1150 77 100       281 ++$r < $min_row and next;
1151 33         36 my %row;
1152             my $lc;
1153 33         35 foreach my $s (@spec) {
1154 77         68 my ($tlr, $tlc, $brr, $brc) = @{$s};
  77         95  
1155 77 100 100     161 $r < $tlr || ($brr ne "*" && $r > $brr) and next;
      100        
1156 45 100 100     70 !defined $lc || $tlc < $lc and $lc = $tlc;
1157 45 100       59 my $rr = $brc eq "*" ? $#{$row} : $brc;
  5         6  
1158 45         132 $row{$_} = $row->[$_] for $tlc .. $rr;
1159             }
1160 33         86 push @c, [ @row{sort { $a <=> $b } keys %row } ];
  62         110  
1161 33 100       39 if (@h) {
1162 2         2 my %h; @h{@h} = @{$c[-1]};
  2         4  
  2         5  
1163 2         4 $c[-1] = \%h;
1164             }
1165 33 100 100     239 $max_row ne "*" && $r == $max_row and last;
1166             }
1167 12         64 return \@c;
1168             }
1169              
1170             # row or col
1171 17         18 my @r;
1172 17         21 my $eod = 0;
1173 17         53 for (split m/\s*;\s*/ => $range) {
1174 25 50       101 my ($from, $to) = m/^\s* ([0-9]+) (?: \s* - \s* ([0-9]+ | \* ))? \s* $/x
1175             or croak ($self->SetDiag (2013));
1176 25   100     73 $to ||= $from;
1177 25 100       39 $to eq "*" and ($to, $eod) = ($from, 1);
1178             # $to cannot be <= 0 due to regex and ||=
1179 25 100 100     430 $from <= 0 || $to < $from and croak ($self->SetDiag (2013));
1180 22         60 $r[$_] = 1 for $from .. $to;
1181             }
1182              
1183 14         30 my $r = 0;
1184 14 100       28 $type eq "col" and shift @r;
1185 14   100     98 $_ ||= 0 for @r;
1186 14         316 while (my $row = $self->getline ($io)) {
1187 109         127 $r++;
1188 109 100       140 if ($type eq "row") {
1189 64 100 100     188 if (($r > $#r && $eod) || $r[$r]) {
      100        
1190 20         22 push @c, $row;
1191 20 100       26 if (@h) {
1192 3         3 my %h; @h{@h} = @{$c[-1]};
  3         4  
  3         13  
1193 3         4 $c[-1] = \%h;
1194             }
1195             }
1196 64         364 next;
1197             }
1198 45 100 100     44 push @c, [ map { ($_ > $#r && $eod) || $r[$_] ? $row->[$_] : () } 0..$#{$row} ];
  405         907  
  45         51  
1199 45 100       236 if (@h) {
1200 9         9 my %h; @h{@h} = @{$c[-1]};
  9         9  
  9         12  
1201 9         51 $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   507 my %attr;
1212 345 100 100     1230 if (@_ == 1 && ref $_[0] eq "HASH") {
    100          
1213 4         4 %attr = %{$_[0]};
  4         11  
1214             }
1215             elsif (scalar @_ % 2) {
1216 1         105 croak (Text::CSV_XS->SetDiag (1502));
1217             }
1218             else {
1219 340         1204 %attr = @_;
1220             }
1221              
1222 344         664 $attr{'binary'} = 1;
1223 344         577 $attr{'strict_eol'} = 1;
1224              
1225 344   100     1514 my $enc = delete $attr{'enc'} || delete $attr{'encoding'} || "";
1226 344 100       685 $enc eq "auto" and ($attr{'detect_bom'}, $enc) = (1, "");
1227 344 50       778 my $stack = $enc =~ s/(:\w.*)// ? $1 : "";
1228 344 100       660 $enc =~ m/^[-\w.]+$/ and $enc = ":encoding($enc)";
1229 344         473 $enc .= $stack;
1230              
1231 344         506 my $hdrs = delete $attr{'headers'};
1232 344         491 my $frag = delete $attr{'fragment'};
1233 344         472 my $key = delete $attr{'key'};
1234 344         432 my $val = delete $attr{'value'};
1235             my $kh = delete $attr{'keep_headers'} ||
1236             delete $attr{'keep_column_names'} ||
1237 344   100     1301 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     1896 delete $attr{'after_parse'};
1243             my $cbbo = delete $attr{'callbacks'}{'before_out'} ||
1244 344   100     850 delete $attr{'before_out'};
1245             my $cboi = delete $attr{'callbacks'}{'on_in'} ||
1246 344   100     840 delete $attr{'on_in'};
1247             my $cboe = delete $attr{'callbacks'}{'on_error'} ||
1248 344   66     838 delete $attr{'on_error'};
1249              
1250             my $hd_s = delete $attr{'sep_set'} ||
1251 344   100     821 delete $attr{'seps'};
1252             my $hd_b = delete $attr{'detect_bom'} ||
1253 344   100     812 delete $attr{'bom'};
1254             my $hd_m = delete $attr{'munge'} ||
1255 344   100     902 delete $attr{'munge_column_names'};
1256 344         416 my $hd_c = delete $attr{'set_column_names'};
1257              
1258 344         448 my $fh;
1259 344         443 my $sink = 0;
1260 344         521 my $cls = 0; # If I open a file, I have to close it
1261 344 100 100     1440 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     1252 : delete $attr{'out'} || delete $attr{'file'};
      100        
1264              
1265 341 100 100     1113 ref $in eq "CODE" || ref $in eq "ARRAY" and $out ||= \*STDOUT;
      100        
1266              
1267 341         483 my ($fho, $fho_cls);
1268 341 100 66     1166 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     26 if (ref $out or "GLOB" eq ref \$out) {
1271 2         4 $fho = $out;
1272             }
1273             else {
1274 5 50       798 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     21 if ($cboi && !$cbai) {
1282 1         1 $cbai = $cboi;
1283 1         2 $cboi = undef;
1284             }
1285 7 100       13 if ($cbai) {
1286 2         2 my $cb = $cbai;
1287 2     6   10 $cbai = sub { $cb->(@_); $_[0]->say ($fho, $_[1]); 0 };
  6         15  
  6         22  
  6         45  
1288             }
1289             else {
1290 5     15   22 $cbai = sub { $_[0]->say ($fho, $_[1]); 0 };
  15         42  
  15         110  
1291             }
1292              
1293             # Put all callbacks back in place for streaming behavior
1294 7         14 $attr{'callbacks'}{'after_parse'} = $cbai; $cbai = undef;
  7         10  
1295 7         10 $attr{'callbacks'}{'before_out'} = $cbbo; $cbbo = undef;
  7         6  
1296 7         8 $attr{'callbacks'}{'on_in'} = $cboi; $cboi = undef;
  7         8  
1297 7         9 $attr{'callbacks'}{'on_error'} = $cboe; $cboe = undef;
  7         8  
1298 7         8 $out = undef;
1299 7         7 $sink = 1;
1300             }
1301              
1302 341 100       608 if ($out) {
1303 33 100 100     236 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         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         19 elsif (ref $out and "SCALAR" eq ref $out and defined ${$out} and ${$out} eq "skip") {
  7         15  
1311 2         3 delete $attr{'out'};
1312 2         3 $sink = 1;
1313             }
1314             else {
1315 12 100       707 open $fh, ">", $out or croak ("$out: $!");
1316 11         27 $cls = 1;
1317             }
1318 32 100       51 if ($fh) {
1319 25 100       31 if ($enc) {
1320 1         11 binmode $fh, $enc;
1321 1         55 my $fn = fileno $fh; # This is a workaround for a bug in PerlIO::via::gzip
1322             }
1323 25 100 66     70 unless (defined $attr{'eol'} || defined $fho) {
1324 18         39 my @layers = eval { PerlIO::get_layers ($fh) };
  18         84  
1325 18 100       88 $attr{'eol'} = (grep m/crlf/ => @layers) ? "\n" : "\r\n";
1326             }
1327             }
1328             }
1329              
1330 340 100 100     1580 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       345 open $fh, "<", $in or croak ("Cannot open from SCALAR using PerlIO");
1337 30         50 $cls = 1;
1338             }
1339             elsif (ref $in or "GLOB" eq ref \$in) {
1340 18 50 66     43 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       11148 open $fh, "<$enc", $in or croak ("$in: $!");
1349 266         1669 $cls = 1;
1350             }
1351 338 50 33     822 $fh || $sink or croak (qq{No valid source passed. "in" is required});
1352              
1353 338         1217 for ([ 'quo' => "quote" ],
1354             [ 'esc' => "escape" ],
1355             [ 'escape' => "escape_char" ],
1356             ) {
1357 1014         1138 my ($f, $t) = @{$_};
  1014         1600  
1358 1014 100 100     2263 exists $attr{$f} and !exists $attr{$t} and $attr{$t} = delete $attr{$f};
1359             }
1360              
1361 338         812 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         63  
1364 10 50   10   11 'not_empty' => sub { grep { defined && $_ ne "" } @{$_[1]} },
  26         62  
  10         11  
1365 10 50   10   11 'filled' => sub { grep { defined && m/\S/ } @{$_[1]} },
  26         95  
  10         12  
1366 338         2324 );
1367             defined $fltr && !ref $fltr && exists $fltr{$fltr} and
1368 338 50 100     761 $fltr = { '0' => $fltr{$fltr} };
      66        
1369 338 100       645 ref $fltr eq "CODE" and $fltr = { 0 => $fltr };
1370 338 100       678 ref $fltr eq "HASH" or $fltr = undef;
1371              
1372 338         457 my $form = delete $attr{'formula'};
1373              
1374 338 100       746 defined $attr{'auto_diag'} or $attr{'auto_diag'} = 1;
1375 338 100       741 defined $attr{'escape_null'} or $attr{'escape_null'} = 0;
1376 338 50 66     1893 my $csv = delete $attr{'csv'} || Text::CSV_XS->new (\%attr)
1377             or croak ($last_err);
1378 338 100       510 defined $form and $csv->formula ($form);
1379 338 100       527 defined $cboe and $csv->callbacks (error => $cboe);
1380              
1381 338 100 100     591 $kh && !ref $kh && $kh =~ m/^(?:1|yes|true|internal|auto)$/i and
      100        
1382             $kh = \@internal_kh;
1383              
1384             return {
1385 338         6078 '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 685937 @_ && ref $_[0] eq __PACKAGE__ and splice @_, 0, 0, "csv";
1413 346 100       788 @_ or croak ($csv_usage);
1414              
1415 345         860 my $c = _csv_attr (@_);
1416              
1417 338         515 my ($csv, $in, $fh, $hdrs) = @{$c}{qw( csv in fh hdrs )};
  338         806  
1418 338         414 my %hdr;
1419 338 100       566 if (ref $hdrs eq "HASH") {
1420 2         3 %hdr = %{$hdrs};
  2         26  
1421 2         4 $hdrs = "auto";
1422             }
1423              
1424 338 100 100     630 if ($c->{'out'} && !$c->{'sink'}) {
1425             !$hdrs && ref $c->{'kh'} && $c->{'kh'} == \@internal_kh and
1426 24 100 100     68 $hdrs = $c->{'kh'};
      66        
1427              
1428 24 100 100     35 if (ref $in eq "CODE") {
    100          
1429 3         4 my $hdr = 1;
1430 3         11 while (my $row = $in->($csv)) {
1431 7 100       34 if (ref $row eq "ARRAY") {
1432 3         20 $csv->print ($fh, $row);
1433 3         15 next;
1434             }
1435 4 50       8 if (ref $row eq "HASH") {
1436 4 100       5 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         25 $hdr = 0;
1440             }
1441 4         5 $csv->print ($fh, [ @{$row}{@{$hdrs}} ]);
  4         16  
  4         4  
1442             }
1443             }
1444             }
1445 21         67 elsif (@{$in} == 0 or ref $in->[0] eq "ARRAY") { # aoa
1446 10 50       18 ref $hdrs and $csv->print ($fh, $hdrs);
1447 10         9 for (@{$in}) {
  10         18  
1448 12 100       73 $c->{'cboi'} and $c->{'cboi'}->($csv, $_);
1449 12 50       1088 $c->{'cbbo'} and $c->{'cbbo'}->($csv, $_);
1450 12         158 $csv->print ($fh, $_);
1451             }
1452             }
1453             else { # aoh
1454 11 100       17 my @hdrs = ref $hdrs ? @{$hdrs} : keys %{$in->[0]};
  5         31  
  6         15  
1455 11 100       17 defined $hdrs or $hdrs = "auto";
1456             ref $hdrs || $hdrs eq "auto" and @hdrs and
1457 11 100 100     49 $csv->print ($fh, [ map { $hdr{$_} || $_ } @hdrs ]);
  20 100 66     211  
1458 11         98 for (@{$in}) {
  11         20  
1459 17         53 local %_;
1460 17         28 *_ = $_;
1461 17 50       45 $c->{'cboi'} and $c->{'cboi'}->($csv, $_);
1462 17 50       23 $c->{'cbbo'} and $c->{'cbbo'}->($csv, $_);
1463 17         17 $csv->print ($fh, [ @{$_}{@hdrs} ]);
  17         76  
1464             }
1465             }
1466              
1467 24 100       607 $c->{'cls'} and close $fh;
1468 24 50       53 $c->{'fho_cls'} and close $c->{'fho'};
1469 24         277 return 1;
1470             }
1471              
1472 314         362 my @row1;
1473 314 100 100     1159 if (defined $c->{'hd_s'} || defined $c->{'hd_b'} || defined $c->{'hd_m'} || defined $c->{'hd_c'}) {
      100        
      100        
1474 173         196 my %harg;
1475             !defined $c->{'hd_s'} && $c->{'attr'}{'sep_char'} and
1476 173 100 100     510 $c->{'hd_s'} = [ $c->{'attr'}{'sep_char'} ];
1477             !defined $c->{'hd_s'} && $c->{'attr'}{'sep'} and
1478 173 100 100     491 $c->{'hd_s'} = [ $c->{'attr'}{'sep'} ];
1479 173 100       299 defined $c->{'hd_s'} and $harg{'sep_set'} = $c->{'hd_s'};
1480 173 100       313 defined $c->{'hd_b'} and $harg{'detect_bom'} = $c->{'hd_b'};
1481 173 50       273 defined $c->{'hd_m'} and $harg{'munge_column_names'} = $hdrs ? "none" : $c->{'hd_m'};
    100          
1482 173 50       236 defined $c->{'hd_c'} and $harg{'set_column_names'} = $hdrs ? 0 : $c->{'hd_c'};
    100          
1483 173         419 @row1 = $csv->header ($fh, \%harg);
1484 170         345 my @hdr = $csv->column_names ();
1485 170 100 100     696 @hdr and $hdrs ||= \@hdr;
1486             }
1487              
1488 311 100       504 if ($c->{'kh'}) {
1489 15         20 @internal_kh = ();
1490 15 100       668 ref $c->{'kh'} eq "ARRAY" or croak ($csv->SetDiag (1501));
1491 10   100     20 $hdrs ||= "auto";
1492             }
1493              
1494 306         448 my $key = $c->{'key'};
1495 306 100       454 if ($key) {
1496 27 100 100     616 !ref $key or ref $key eq "ARRAY" && @{$key} > 1 or croak ($csv->SetDiag (1501));
  8   100     446  
1497 20   100     69 $hdrs ||= "auto";
1498             }
1499 299         370 my $val = $c->{'val'};
1500 299 100       404 if ($val) {
1501 9 100       156 $key or croak ($csv->SetDiag (1502));
1502 8 100 100     321 !ref $val or ref $val eq "ARRAY" && @{$val} > 0 or croak ($csv->SetDiag (1503));
  3   100     154  
1503             }
1504              
1505 295 100 100     489 $c->{'fltr'} && grep m/\D/ => keys %{$c->{'fltr'}} and $hdrs ||= "auto";
  17   100     82  
1506 295 100       470 if (defined $hdrs) {
1507 224 100 100     609 if (!ref $hdrs or ref $hdrs eq "CODE") {
1508 53 100       1712 my $h = $c->{'hd_b'}
1509             ? [ $csv->column_names () ]
1510             : $csv->getline ($fh);
1511 53   33     200 my $has_h = $h && @$h;
1512              
1513 53 100       148 if (ref $hdrs) {
    100          
    100          
    100          
    50          
1514 1 50       4 $has_h or return;
1515 1         1 my $cr = $hdrs;
1516 1   33     2 $hdrs = [ map { $cr->($hdr{$_} || $_) } @{$h} ];
  3         14  
  1         3  
1517             }
1518             elsif ($hdrs eq "skip") {
1519             # discard;
1520             }
1521             elsif ($hdrs eq "auto") {
1522 49 50       73 $has_h or return;
1523 49 100       48 $hdrs = [ map { $hdr{$_} || $_ } @{$h} ];
  139         397  
  49         77  
1524             }
1525             elsif ($hdrs eq "lc") {
1526 1 50       2 $has_h or return;
1527 1   33     2 $hdrs = [ map { lc ($hdr{$_} || $_) } @{$h} ];
  3         11  
  1         3  
1528             }
1529             elsif ($hdrs eq "uc") {
1530 1 50       3 $has_h or return;
1531 1   33     2 $hdrs = [ map { uc ($hdr{$_} || $_) } @{$h} ];
  3         12  
  1         1  
1532             }
1533             }
1534 224 100 66     475 $c->{'kh'} and $hdrs and @{$c->{'kh'}} = @{$hdrs};
  10         25  
  10         12  
1535             }
1536              
1537 295 100       430 if ($c->{'fltr'}) {
1538 17         17 my %f = %{$c->{'fltr'}};
  17         41  
1539             # convert headers to index
1540 17         18 my @hdr;
1541 17 100       25 if (ref $hdrs) {
1542 8         6 @hdr = @{$hdrs};
  8         18  
1543 8         19 for (0 .. $#hdr) {
1544 24 100       74 exists $f{$hdr[$_]} and $f{$_ + 1} = delete $f{$hdr[$_]};
1545             }
1546             }
1547             $csv->callbacks ('after_parse' => sub {
1548 116     116   409 my ($CSV, $ROW) = @_; # lexical sub-variables in caps
1549 116         160 foreach my $FLD (sort keys %f) {
1550 117         173 local $_ = $ROW->[$FLD - 1];
1551 117         126 local %_;
1552 117 100       131 @hdr and @_{@hdr} = @{$ROW};
  53         99  
1553 117 100       173 $f{$FLD}->($CSV, $ROW) or return \"skip";
1554 53         386 $ROW->[$FLD - 1] = $_;
1555             }
1556 17         99 });
1557             }
1558              
1559 295         345 my $frag = $c->{'frag'};
1560             my $ref = ref $hdrs
1561             ? # aoh
1562 295 100       3897 do {
    100          
1563 223         402 my @h = $csv->column_names ($hdrs);
1564 223         320 my %h; $h{$_}++ for @h;
  223         591  
1565 223 50       345 exists $h{''} and croak ($csv->SetDiag (1012));
1566 223 50       370 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       589 $key ? do {
    100          
    100          
1572 17 100       39 my ($k, $j, @f) = ref $key ? (undef, @{$key}) : ($key);
  5         13  
1573 17 100       24 if (my @mk = grep { !exists $h{$_} } grep { defined } $k, @f) {
  22         46  
  27         43  
1574 2         9 croak ($csv->_SetDiagInfo (4001, join ", " => @mk));
1575             }
1576             +{ map {
1577 26         26 my $r = $_;
1578 26 100       41 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         4  
1583 26 100       93 : $r->{$val}
    100          
1584             : $r ));
1585 15         20 } @{$csv->getline_hr_all ($fh)} }
  15         32  
1586             }
1587             : $csv->getline_hr_all ($fh);
1588             }
1589             : # aoa
1590             $frag ? $csv->fragment ($fh, $frag)
1591             : $csv->getline_all ($fh);
1592 287 50       524 if ($ref) {
1593 287 100 66     849 @row1 && !$c->{'hd_c'} && !ref $hdrs and unshift @{$ref}, \@row1;
  4   100     9  
1594             }
1595             else {
1596 0         0 Text::CSV_XS->auto_diag ();
1597             }
1598 287 100       3248 $c->{'cls'} and close $fh;
1599 287 50       540 $c->{'fho_cls'} and close $c->{'fho'};
1600 287 100 100     1054 if ($ref and $c->{'cbai'} || $c->{'cboi'}) {
      66        
1601             # Default is ARRAYref, but with key =>, you'll get a hashref
1602 23 100       49 foreach my $r (ref $ref eq "ARRAY" ? @{$ref} : values %{$ref}) {
  22         37  
  1         3  
1603 74         5548 local %_;
1604 74 100       140 ref $r eq "HASH" and *_ = $r;
1605 74 100       146 $c->{'cbai'} and $c->{'cbai'}->($csv, $r);
1606 74 100       3573 $c->{'cboi'} and $c->{'cboi'}->($csv, $r);
1607             }
1608             }
1609              
1610 287 100       1484 if ($c->{'sink'}) {
1611 14 100       323 my $ro = ref $c->{'out'} or return;
1612              
1613 7 100 66     17 $ro eq "SCALAR" && ${$c->{'out'}} eq "skip" and
  2         30  
1614             return;
1615              
1616 5 50       8 $ro eq ref $ref or
1617             croak ($csv->_SetDiagInfo (5001, "Output type mismatch"));
1618              
1619 5 100       8 if ($ro eq "ARRAY") {
1620 4 100 33     24 if (@{$c->{'out'}} and @$ref and ref $c->{'out'}[0] eq ref $ref->[0]) {
  4   66     20  
1621 2         2 push @{$c->{'out'}} => @$ref;
  2         5  
1622 2         26 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         9  
  1         3  
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       392 %{$c->{'attr'}},
  1         23  
1640             );
1641              
1642 272   100     888 $last_err ||= $csv->{'_ERROR_DIAG'};
1643 272         3948 return $ref;
1644             } # csv
1645              
1646             1;
1647              
1648             __END__