File Coverage

blib/lib/Text/CSV_XS.pm
Criterion Covered Total %
statement 895 906 98.9
branch 718 764 93.9
condition 380 442 85.7
subroutine 86 86 100.0
pod 66 66 100.0
total 2145 2264 94.7


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