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   2298837 use strict;
  32         363  
  32         943  
19 32     32   155 use warnings;
  32         71  
  32         1157  
20              
21             require Exporter;
22 32     32   174 use XSLoader;
  32         77  
  32         1071  
23 32     32   192 use Carp;
  32         63  
  32         2489  
24              
25 32     32   254 use vars qw( $VERSION @ISA @EXPORT_OK %EXPORT_TAGS );
  32         68  
  32         10239  
26             $VERSION = "1.51";
27             @ISA = qw( Exporter );
28             XSLoader::load ("Text::CSV_XS", $VERSION);
29              
30 4     4 1 11 sub PV { 0 } sub CSV_TYPE_PV { PV }
  12     12 1 131  
31 4     4 1 11 sub IV { 1 } sub CSV_TYPE_IV { IV }
  12     12 1 1576  
32 4     4 1 10 sub NV { 2 } sub CSV_TYPE_NV { NV }
  12     12 1 65  
33              
34 11     11 1 64 sub CSV_FLAGS_IS_QUOTED { 0x0001 }
35 12     12 1 82 sub CSV_FLAGS_IS_BINARY { 0x0002 }
36 4     4 1 55 sub CSV_FLAGS_ERROR_IN_FIELD { 0x0004 }
37 20     20 1 106 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   239 no warnings "redefine";
  32         65  
  32         406000  
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 674 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   25256 my ($self, $aw) = @_;
131 15664 100       42684 $aw or return 0; # no checks needed without allow_whitespace
132              
133 3564         4903 my $quo = $self->{'quote'};
134 3564 100 100     8371 defined $quo && length ($quo) or $quo = $self->{'quote_char'};
135 3564         4977 my $esc = $self->{'escape_char'};
136              
137 3564 100 100     35941 defined $quo && $quo =~ m/^[ \t]/ and return 1002;
138 3322 100 100     37506 defined $esc && $esc =~ m/^[ \t]/ and return 1002;
139              
140 3032         7382 return 0;
141             } # _unhealty_whitespace
142              
143             sub _check_sanity {
144 12358     12358   18355 my $self = shift;
145              
146 12358         18258 my $eol = $self->{'eol'};
147 12358         17029 my $sep = $self->{'sep'};
148 12358 100 100     30237 defined $sep && length ($sep) or $sep = $self->{'sep_char'};
149 12358         17568 my $quo = $self->{'quote'};
150 12358 100 100     25545 defined $quo && length ($quo) or $quo = $self->{'quote_char'};
151 12358         17358 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       24362 $sep ne "" or return 1008;
159 12356 100       22910 length ($sep) > 16 and return 1006;
160 12355 100       32914 $sep =~ m/[\r\n]/ and return 1003;
161              
162 12349 100       21924 if (defined $quo) {
163 12339 100       46032 $quo eq $sep and return 1001;
164 12111 100       19658 length ($quo) > 16 and return 1007;
165 12110 100       24258 $quo =~ m/[\r\n]/ and return 1003;
166             }
167 12114 100       19083 if (defined $esc) {
168 12098 100       37299 $esc eq $sep and return 1001;
169 11930 100       22289 $esc =~ m/[\r\n]/ and return 1003;
170             }
171 11940 100       19556 if (defined $eol) {
172 11936 100       19984 length ($eol) > 16 and return 1005;
173             }
174              
175 11939         21709 return _unhealthy_whitespace ($self, $self->{'allow_whitespace'});
176             } # _check_sanity
177              
178             sub known_attributes {
179 3     3 1 675 sort grep !m/^_/ => "sep", "quote", keys %def_attr;
180             } # known_attributes
181              
182             sub new {
183 934     934 1 64133191 $last_new_err = Text::CSV_XS->SetDiag (1000,
184             "usage: my \$csv = Text::CSV_XS->new ([{ option => value, ... }]);");
185              
186 934         2127 my $proto = shift;
187 934 100 100     4463 my $class = ref $proto || $proto or return;
188 933 100 100     4034 @_ > 0 && ref $_[0] ne "HASH" and return;
189 925   100     2304 my $attr = shift || {};
190             my %attr = map {
191 2164 100       8727 my $k = m/^[a-zA-Z]\w+$/ ? lc $_ : $_;
192 2164 100       4476 exists $attr_alias{$k} and $k = $attr_alias{$k};
193 2164         5992 ($k => $attr->{$_});
194 925         1428 } keys %{$attr};
  925         2933  
195              
196 925         2042 my $sep_aliased = 0;
197 925 100       1966 if (exists $attr{'sep'}) {
198 10         45 $attr{'sep_char'} = delete $attr{'sep'};
199 10         22 $sep_aliased = 1;
200             }
201 925         1341 my $quote_aliased = 0;
202 925 100       1824 if (exists $attr{'quote'}) {
203 25         51 $attr{'quote_char'} = delete $attr{'quote'};
204 25         56 $quote_aliased = 1;
205             }
206             exists $attr{'formula_handling'} and
207 925 100       1828 $attr{'formula'} = delete $attr{'formula_handling'};
208 925         1857 my $attr_formula = delete $attr{'formula'};
209              
210 925         2318 for (keys %attr) {
211 2126 100 100     7453 if (m/^[a-z]/ && exists $def_attr{$_}) {
212             # uncoverable condition false
213 2119 100 100     7360 defined $attr{$_} && m/_char$/ and utf8::decode ($attr{$_});
214 2119         3606 next;
215             }
216             # croak?
217 7         41 $last_new_err = Text::CSV_XS->SetDiag (1000, "INI - Unknown attribute '$_'");
218 7 100       25 $attr{'auto_diag'} and error_diag ();
219 7         49 return;
220             }
221 918 100       1942 if ($sep_aliased) {
222 10         51 my @b = unpack "U0C*", $attr{'sep_char'};
223 10 100       30 if (@b > 1) {
224 6         13 $attr{'sep'} = $attr{'sep_char'};
225 6         14 $attr{'sep_char'} = "\0";
226             }
227             else {
228 4         12 $attr{'sep'} = undef;
229             }
230             }
231 918 100 100     1996 if ($quote_aliased and defined $attr{'quote_char'}) {
232 21         78 my @b = unpack "U0C*", $attr{'quote_char'};
233 21 100       49 if (@b > 1) {
234 7         25 $attr{'quote'} = $attr{'quote_char'};
235 7         16 $attr{'quote_char'} = "\0";
236             }
237             else {
238 14         32 $attr{'quote'} = undef;
239             }
240             }
241              
242 918         16370 my $self = { %def_attr, %attr };
243 918 100       3568 if (my $ec = _check_sanity ($self)) {
244 35         137 $last_new_err = Text::CSV_XS->SetDiag ($ec);
245 35 100       82 $attr{'auto_diag'} and error_diag ();
246 35         262 return;
247             }
248 883 100 100     2784 if (defined $self->{'callbacks'} && ref $self->{'callbacks'} ne "HASH") {
249 6         703 carp ("The 'callbacks' attribute is set but is not a hash: ignored\n");
250 6         183 $self->{'callbacks'} = undef;
251             }
252              
253 883         3691 $last_new_err = Text::CSV_XS->SetDiag (0);
254 883 100 100     2933 defined $\ && !exists $attr{'eol'} and $self->{'eol'} = $\;
255 883         1543 bless $self, $class;
256 883 100       1966 defined $self->{'types'} and $self->types ($self->{'types'});
257 883 50       2518 defined $self->{'skip_empty_rows'} and $self->{'skip_empty_rows'} = _supported_skip_empty_rows ($self, $self->{'skip_empty_rows'});
258 883 100       2029 defined $attr_formula and $self->{'formula'} = _supported_formula ($self, $attr_formula);
259 882         5314 $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   22678 my ($self, $name, $val, $ec) = @_;
301 11108 100       32075 defined $val and utf8::decode ($val);
302 11108         19232 $self->{$name} = $val;
303 11108 100       17125 $ec = _check_sanity ($self) and croak ($self->SetDiag ($ec));
304 10198         34944 $self->_cache_set ($_cache_id{$name}, $val);
305             } # _set_attr_C
306              
307             # A flag
308             sub _set_attr_X {
309 5641     5641   10072 my ($self, $name, $val) = @_;
310 5641 100       10022 defined $val or $val = 0;
311 5641         8735 $self->{$name} = $val;
312 5641         21678 $self->_cache_set ($_cache_id{$name}, 0 + $val);
313             } # _set_attr_X
314              
315             # A number
316             sub _set_attr_N {
317 59     59   133 my ($self, $name, $val) = @_;
318 59         112 $self->{$name} = $val;
319 59         261 $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 655729 my $self = shift;
326 4836 100       10796 if (@_) {
327 3601         7616 $self->_set_attr_C ("quote_char", shift);
328 3374         7955 $self->_cache_set ($_cache_id{'quote'}, "");
329             }
330 4609         14090 $self->{'quote_char'};
331             } # quote_char
332              
333             sub quote {
334 20     20 1 51 my $self = shift;
335 20 100       59 if (@_) {
336 11         15 my $quote = shift;
337 11 100       31 defined $quote or $quote = "";
338 11         30 utf8::decode ($quote);
339 11         44 my @b = unpack "U0C*", $quote;
340 11 100       34 if (@b > 1) {
341 5 100       100 @b > 16 and croak ($self->SetDiag (1007));
342 4         12 $self->quote_char ("\0");
343             }
344             else {
345 6         20 $self->quote_char ($quote);
346 6         18 $quote = "";
347             }
348 10         21 $self->{'quote'} = $quote;
349              
350 10         20 my $ec = _check_sanity ($self);
351 10 100       169 $ec and croak ($self->SetDiag ($ec));
352              
353 9         34 $self->_cache_set ($_cache_id{'quote'}, $quote);
354             }
355 18         45 my $quote = $self->{'quote'};
356 18 100 100     129 defined $quote && length ($quote) ? $quote : $self->{'quote_char'};
357             } # quote
358              
359             sub escape_char {
360 4826     4826 1 660989 my $self = shift;
361 4826 100       10092 if (@_) {
362 3595         5198 my $ec = shift;
363 3595         7998 $self->_set_attr_C ("escape_char", $ec);
364 3480 100       7104 $ec or $self->_set_attr_X ("escape_null", 0);
365             }
366 4711         14414 $self->{'escape_char'};
367             } # escape_char
368              
369             sub sep_char {
370 5155     5155 1 655529 my $self = shift;
371 5155 100       10903 if (@_) {
372 3912         8844 $self->_set_attr_C ("sep_char", shift);
373 3344         7680 $self->_cache_set ($_cache_id{'sep'}, "");
374             }
375 4587         13929 $self->{'sep_char'};
376             } # sep_char
377              
378             sub sep {
379 359     359 1 3613 my $self = shift;
380 359 100       794 if (@_) {
381 326         556 my $sep = shift;
382 326 100       658 defined $sep or $sep = "";
383 326         1069 utf8::decode ($sep);
384 326         1220 my @b = unpack "U0C*", $sep;
385 326 100       753 if (@b > 1) {
386 13 100       120 @b > 16 and croak ($self->SetDiag (1006));
387 12         33 $self->sep_char ("\0");
388             }
389             else {
390 313         832 $self->sep_char ($sep);
391 310         444 $sep = "";
392             }
393 322         635 $self->{'sep'} = $sep;
394              
395 322         559 my $ec = _check_sanity ($self);
396 322 100       868 $ec and croak ($self->SetDiag ($ec));
397              
398 321         1018 $self->_cache_set ($_cache_id{'sep'}, $sep);
399             }
400 354         594 my $sep = $self->{'sep'};
401 354 100 100     1401 defined $sep && length ($sep) ? $sep : $self->{'sep_char'};
402             } # sep
403              
404             sub eol {
405 157     157 1 7728 my $self = shift;
406 157 100       403 if (@_) {
407 125         221 my $eol = shift;
408 125 100       271 defined $eol or $eol = "";
409 125 100       489 length ($eol) > 16 and croak ($self->SetDiag (1005));
410 124         249 $self->{'eol'} = $eol;
411 124         433 $self->_cache_set ($_cache_id{'eol'}, $eol);
412             }
413 156         405 $self->{'eol'};
414             } # eol
415              
416             sub always_quote {
417 3032     3032 1 675300 my $self = shift;
418 3032 100       8203 @_ and $self->_set_attr_X ("always_quote", shift);
419 3032         7915 $self->{'always_quote'};
420             } # always_quote
421              
422             sub quote_space {
423 10     10 1 28 my $self = shift;
424 10 100       52 @_ and $self->_set_attr_X ("quote_space", shift);
425 10         41 $self->{'quote_space'};
426             } # quote_space
427              
428             sub quote_empty {
429 5     5 1 12 my $self = shift;
430 5 100       21 @_ and $self->_set_attr_X ("quote_empty", shift);
431 5         19 $self->{'quote_empty'};
432             } # quote_empty
433              
434             sub escape_null {
435 6     6 1 11 my $self = shift;
436 6 100       22 @_ and $self->_set_attr_X ("escape_null", shift);
437 6         31 $self->{'escape_null'};
438             } # escape_null
439 3     3 1 11 sub quote_null { goto &escape_null; }
440              
441             sub quote_binary {
442 7     7 1 20 my $self = shift;
443 7 100       28 @_ and $self->_set_attr_X ("quote_binary", shift);
444 7         22 $self->{'quote_binary'};
445             } # quote_binary
446              
447             sub binary {
448 21     21 1 103755 my $self = shift;
449 21 100       103 @_ and $self->_set_attr_X ("binary", shift);
450 21         54 $self->{'binary'};
451             } # binary
452              
453             sub strict {
454 2     2 1 5 my $self = shift;
455 2 100       9 @_ and $self->_set_attr_X ("strict", shift);
456 2         8 $self->{'strict'};
457             } # strict
458              
459             sub _supported_skip_empty_rows {
460 904     904   1688 my ($self, $f) = @_;
461 904 100       1803 defined $f or return 0;
462 903 100 66     3420 if ($self && $f && ref $f && ref $f eq "CODE") {
      100        
      66        
463 5         9 $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       4479 $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 42 my $self = shift;
480 23 100       84 @_ and $self->_set_attr_N ("skip_empty_rows", _supported_skip_empty_rows ($self, shift));
481 23         50 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       140 $self->{'_EMPTROW_CB'};
    100          
    100          
    100          
    100          
486             } # skip_empty_rows
487              
488             sub _SetDiagInfo {
489 17     17   41 my ($self, $err, $msg) = @_;
490 17         152 $self->SetDiag ($err);
491 17         45 my $em = $self->error_diag ();
492 17 50       65 $em =~ s/^\d+$// and $msg =~ s/^/# /;
493 17 50       80 my $sep = $em =~ m/[;\n]$/ ? "\n\t" : ": ";
494 17         1939 join $sep => grep m/\S\S\S/ => $em, $msg;
495             } # _SetDiagInfo
496              
497             sub _supported_formula {
498 103     103   191 my ($self, $f) = @_;
499 103 100       188 defined $f or return 5;
500 102 100 66     454 if ($self && $f && ref $f && ref $f eq "CODE") {
      100        
      100        
501 6         14 $self->{'_FORMULA_CB'} = $f;
502 6         16 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       828 $f =~ m/^(?: 6 | cb )$/xi ? 6 : do {
    100          
    100          
    100          
    100          
    100          
    100          
511 7   50     16 $self ||= "Text::CSV_XS";
512 7         66 croak ($self->_SetDiagInfo (1500, "formula-handling '$f' is not supported"));
513             };
514             } # _supported_formula
515              
516             sub formula {
517 44     44 1 3179 my $self = shift;
518 44 100       131 @_ and $self->_set_attr_N ("formula", _supported_formula ($self, shift));
519 38 100       119 $self->{'formula'} == 6 or $self->{'_FORMULA_CB'} = undef;
520 38         148 [qw( none die croak diag empty undef cb )]->[_supported_formula ($self, $self->{'formula'})];
521             } # formula
522              
523             sub formula_handling {
524 7     7 1 14 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       8 @_ and $self->_set_attr_X ("decode_utf8", shift);
531 2         8 $self->{'decode_utf8'};
532             } # decode_utf8
533              
534             sub keep_meta_info {
535 12     12 1 932 my $self = shift;
536 12 100       38 if (@_) {
537 11         21 my $v = shift;
538 11 100 100     68 !defined $v || $v eq "" and $v = 0;
539 11 100       85 $v =~ m/^[0-9]/ or $v = lc $v eq "false" ? 0 : 1; # true/truth = 1
    100          
540 11         34 $self->_set_attr_X ("keep_meta_info", $v);
541             }
542 12         58 $self->{'keep_meta_info'};
543             } # keep_meta_info
544              
545             sub allow_loose_quotes {
546 12     12 1 20 my $self = shift;
547 12 100       50 @_ and $self->_set_attr_X ("allow_loose_quotes", shift);
548 12         30 $self->{'allow_loose_quotes'};
549             } # allow_loose_quotes
550              
551             sub allow_loose_escapes {
552 12     12 1 1052 my $self = shift;
553 12 100       61 @_ 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 2218068 my $self = shift;
559 4954 100       12129 if (@_) {
560 3725         5028 my $aw = shift;
561 3725 100       7902 _unhealthy_whitespace ($self, $aw) and
562             croak ($self->SetDiag (1002));
563 3721         7993 $self->_set_attr_X ("allow_whitespace", $aw);
564             }
565 4950         15778 $self->{'allow_whitespace'};
566             } # allow_whitespace
567              
568             sub allow_unquoted_escape {
569 3     3 1 10 my $self = shift;
570 3 100       34 @_ and $self->_set_attr_X ("allow_unquoted_escape", shift);
571 3         22 $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       9 @_ and $self->_set_attr_X ("blank_is_undef", shift);
577 2         10 $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       8 @_ and $self->_set_attr_X ("empty_is_undef", shift);
583 2         38 $self->{'empty_is_undef'};
584             } # empty_is_undef
585              
586             sub verbatim {
587 9     9 1 10846 my $self = shift;
588 9 100       36 @_ and $self->_set_attr_X ("verbatim", shift);
589 9         24 $self->{'verbatim'};
590             } # verbatim
591              
592             sub undef_str {
593 12     12 1 3181 my $self = shift;
594 12 100       43 if (@_) {
595 11         25 my $v = shift;
596 11 100       45 $self->{'undef_str'} = defined $v ? "$v" : undef;
597 11         46 $self->_cache_set ($_cache_id{'undef_str'}, $self->{'undef_str'});
598             }
599 12         54 $self->{'undef_str'};
600             } # undef_str
601              
602             sub comment_str {
603 15     15 1 88 my $self = shift;
604 15 100       35 if (@_) {
605 14         25 my $v = shift;
606 14 100       49 $self->{'comment_str'} = defined $v ? "$v" : undef;
607 14         50 $self->_cache_set ($_cache_id{'comment_str'}, $self->{'comment_str'});
608             }
609 15         43 $self->{'comment_str'};
610             } # comment_str
611              
612             sub auto_diag {
613 12     12 1 386 my $self = shift;
614 12 100       38 if (@_) {
615 9         15 my $v = shift;
616 9 100 100     54 !defined $v || $v eq "" and $v = 0;
617 9 100       46 $v =~ m/^[0-9]/ or $v = lc $v eq "false" ? 0 : 1; # true/truth = 1
    100          
618 9         24 $self->_set_attr_X ("auto_diag", $v);
619             }
620 12         54 $self->{'auto_diag'};
621             } # auto_diag
622              
623             sub diag_verbose {
624 10     10 1 705 my $self = shift;
625 10 100       33 if (@_) {
626 8         14 my $v = shift;
627 8 100 100     45 !defined $v || $v eq "" and $v = 0;
628 8 100       52 $v =~ m/^[0-9]/ or $v = lc $v eq "false" ? 0 : 1; # true/truth = 1
    100          
629 8         21 $self->_set_attr_X ("diag_verbose", $v);
630             }
631 10         51 $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         22 return $self->{'_STATUS'};
642             } # status
643              
644             sub eof {
645 33     33 1 152030 my $self = shift;
646 33         148 return $self->{'_EOF'};
647             } # eof
648              
649             sub types {
650 7     7 1 1932 my $self = shift;
651 7 100       17 if (@_) {
652 2 100       6 if (my $types = shift) {
653 1         2 $self->{'_types'} = join "", map { chr } @{$types};
  3         13  
  1         3  
654 1         2 $self->{'types'} = $types;
655 1         6 $self->_cache_set ($_cache_id{'types'}, $self->{'_types'});
656             }
657             else {
658 1         4 delete $self->{'types'};
659 1         3 delete $self->{'_types'};
660 1         10 $self->_cache_set ($_cache_id{'types'}, undef);
661 1         3 undef;
662             }
663             }
664             else {
665 5         18 $self->{'types'};
666             }
667             } # types
668              
669             sub callbacks {
670 73     73 1 19872 my $self = shift;
671 73 100       178 if (@_) {
672 43         56 my $cb;
673 43         65 my $hf = 0x00;
674 43 100       112 if (defined $_[0]) {
    100          
675 41 100       81 grep { !defined } @_ and croak ($self->SetDiag (1004));
  73         392  
676 39 100 100     615 $cb = @_ == 1 && ref $_[0] eq "HASH" ? shift
    100          
677             : @_ % 2 == 0 ? { @_ }
678             : croak ($self->SetDiag (1004));
679 34         52 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     1464 $cbk =~ m/^[\w.]+$/ && ref $cb->{$cbk} eq "CODE" or
683             croak ($self->SetDiag (1004));
684             }
685 20 100       55 exists $cb->{'error'} and $hf |= 0x01;
686 20 100       46 exists $cb->{'after_parse'} and $hf |= 0x02;
687 20 100       43 exists $cb->{'before_print'} and $hf |= 0x04;
688             }
689             elsif (@_ > 1) {
690             # (undef, whatever)
691 1         83 croak ($self->SetDiag (1004));
692             }
693 21         63 $self->_set_attr_X ("_has_hooks", $hf);
694 21         55 $self->{'callbacks'} = $cb;
695             }
696 51         144 $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 159725 my $self = shift;
706 1718         4813 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     14577 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         2965 $diag[0] = 0 + $self->{'_ERROR_DIAG'};
713 1543         2647 $diag[1] = $self->{'_ERROR_DIAG'};
714 1543 100       3199 $diag[2] = 1 + $self->{'_ERROR_POS'} if exists $self->{'_ERROR_POS'};
715 1543         2357 $diag[3] = $self->{'_RECNO'};
716 1543 100       2905 $diag[4] = $self->{'_ERROR_FLD'} if exists $self->{'_ERROR_FLD'};
717              
718             $diag[0] && $self->{'callbacks'} && $self->{'callbacks'}{'error'} and
719 1543 100 100     5617 return $self->{'callbacks'}{'error'}->(@diag);
      100        
720             }
721              
722 1709         2834 my $context = wantarray;
723 1709 100       3446 unless (defined $context) { # Void context, auto-diag
724 285 100 100     1022 if ($diag[0] && $diag[0] != 2012) {
725 19         110 my $msg = "# CSV_XS ERROR: $diag[0] - $diag[1] \@ rec $diag[3] pos $diag[2]\n";
726 19 100       95 $diag[4] and $msg =~ s/$/ field $diag[4]/;
727              
728 19 100 100     104 unless ($self && ref $self) { # auto_diag
729             # called without args in void context
730 4         58 warn $msg;
731 4         52 return;
732             }
733              
734             $self->{'diag_verbose'} && $self->{'_ERROR_INPUT'} and
735 15 50 66     62 $msg .= $self->{'_ERROR_INPUT'}."\n".
736             (" " x ($diag[2] - 1))."^\n";
737              
738 15         32 my $lvl = $self->{'auto_diag'};
739 15 100       43 if ($lvl < 2) {
740 12         121 my @c = caller (2);
741 12 50 66     90 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       153 $lvl > 1 ? die $msg : warn $msg;
753             }
754 278         2469 return;
755             }
756 1424 100       6246 return $context ? @diag : $diag[1];
757             } # error_diag
758              
759             sub record_number {
760 14     14 1 3532 my $self = shift;
761 14         52 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 354592 my $self = shift;
772 1398 100       4041 return ref $self->{'_STRING'} ? ${$self->{'_STRING'}} : undef;
  1397         5356  
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 19711 my $self = shift;
783 1600 100       3987 return ref $self->{'_FIELDS'} ? @{$self->{'_FIELDS'}} : undef;
  1599         9462  
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 606 my $self = shift;
795 21 100       68 return ref $self->{'_FFLAGS'} ? @{$self->{'_FFLAGS'}} : undef;
  16         75  
796             } # meta_info
797              
798             sub is_quoted {
799 12     12 1 17376 my ($self, $idx) = @_;
800             ref $self->{'_FFLAGS'} &&
801 12 100 100     82 $idx >= 0 && $idx < @{$self->{'_FFLAGS'}} or return;
  8   100     37  
802 7 100       25 $self->{'_FFLAGS'}[$idx] & CSV_FLAGS_IS_QUOTED () ? 1 : 0;
803             } # is_quoted
804              
805             sub is_binary {
806 11     11 1 1062 my ($self, $idx) = @_;
807             ref $self->{'_FFLAGS'} &&
808 11 100 100     73 $idx >= 0 && $idx < @{$self->{'_FFLAGS'}} or return;
  9   100     33  
809 8 100       20 $self->{'_FFLAGS'}[$idx] & CSV_FLAGS_IS_BINARY () ? 1 : 0;
810             } # is_binary
811              
812             sub is_missing {
813 19     19 1 49 my ($self, $idx) = @_;
814 19 100 100     121 $idx < 0 || !ref $self->{'_FFLAGS'} and return;
815 11 100       20 $idx >= @{$self->{'_FFLAGS'}} and return 1;
  11         35  
816 10 100       26 $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 688920 my $self = shift;
832 1397         2548 my $str = "";
833 1397         4563 $self->{'_FIELDS'} = \@_;
834 1397   100     21967 $self->{'_STATUS'} = (@_ > 0) && $self->Combine (\$str, \@_, 0);
835 1393         3486 $self->{'_STRING'} = \$str;
836 1393         4939 $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 108699 my ($self, $str) = @_;
853              
854 1938 100       5050 ref $str and croak ($self->SetDiag (1500));
855              
856 1934         3242 my $fields = [];
857 1934         2844 my $fflags = [];
858 1934         3936 $self->{'_STRING'} = \$str;
859 1934 100 100     32833 if (defined $str && $self->Parse ($str, $fields, $fflags)) {
860 1724         4660 $self->{'_FIELDS'} = $fields;
861 1724         2539 $self->{'_FFLAGS'} = $fflags;
862 1724         2818 $self->{'_STATUS'} = 1;
863             }
864             else {
865 207         510 $self->{'_FIELDS'} = undef;
866 207         328 $self->{'_FFLAGS'} = undef;
867 207         360 $self->{'_STATUS'} = 0;
868             }
869 1931         7539 $self->{'_STATUS'};
870             } # parse
871              
872             sub column_names {
873 1017     1017 1 80750 my ($self, @keys) = @_;
874             @keys or
875 1017 100       2503 return defined $self->{'_COLUMN_NAMES'} ? @{$self->{'_COLUMN_NAMES'}} : ();
  293 100       1289  
876              
877             @keys == 1 && ! defined $keys[0] and
878 681 100 100     2383 return $self->{'_COLUMN_NAMES'} = undef;
879              
880 543 100 100     2169 if (@keys == 1 && ref $keys[0] eq "ARRAY") {
    100          
881 222         304 @keys = @{$keys[0]};
  222         580  
882             }
883 702 100       2169 elsif (join "", map { defined $_ ? ref $_ : "" } @keys) {
884 5         596 croak ($self->SetDiag (3001));
885             }
886              
887 538 100 100     1419 $self->{'_BOUND_COLUMNS'} && @keys != @{$self->{'_BOUND_COLUMNS'}} and
  2         91  
888             croak ($self->SetDiag (3003));
889              
890 537 100       828 $self->{'_COLUMN_NAMES'} = [ map { defined $_ ? $_ : "\cAUNDEF\cA" } @keys ];
  1241         3143  
891 537         873 @{$self->{'_COLUMN_NAMES'}};
  537         1280  
892             } # column_names
893              
894             sub header {
895 333     333 1 43675 my ($self, $fh, @args) = @_;
896              
897 333 100       904 $fh or croak ($self->SetDiag (1014));
898              
899 332         502 my (@seps, %args);
900 332         706 for (@args) {
901 225 100       532 if (ref $_ eq "ARRAY") {
902 18         31 push @seps, @{$_};
  18         47  
903 18         42 next;
904             }
905 207 100       441 if (ref $_ eq "HASH") {
906 206         282 %args = %{$_};
  206         557  
907 206         454 next;
908             }
909 1         91 croak ('usage: $csv->header ($fh, [ seps ], { options })');
910             }
911              
912             defined $args{'munge'} && !defined $args{'munge_column_names'} and
913 331 100 66     881 $args{'munge_column_names'} = $args{'munge'}; # munge as alias
914 331 100       850 defined $args{'detect_bom'} or $args{'detect_bom'} = 1;
915 331 100       744 defined $args{'set_column_names'} or $args{'set_column_names'} = 1;
916 331 100       784 defined $args{'munge_column_names'} or $args{'munge_column_names'} = "lc";
917              
918             # Reset any previous leftovers
919 331         482 $self->{'_RECNO'} = 0;
920 331         530 $self->{'_AHEAD'} = undef;
921 331 100       721 $self->{'_COLUMN_NAMES'} = undef if $args{'set_column_names'};
922 331 100       720 $self->{'_BOUND_COLUMNS'} = undef if $args{'set_column_names'};
923              
924 331 100       617 if (defined $args{'sep_set'}) {
925 27 100       75 ref $args{'sep_set'} eq "ARRAY" or
926             croak ($self->_SetDiagInfo (1500, "sep_set should be an array ref"));
927 22         41 @seps = @{$args{'sep_set'}};
  22         70  
928             }
929              
930 326 50       1044 $^O eq "MSWin32" and binmode $fh;
931 326         6112 my $hdr = <$fh>;
932             # check if $hdr can be empty here, I don't think so
933 326 100 66     2319 defined $hdr && $hdr ne "" or croak ($self->SetDiag (1010));
934              
935 324         505 my %sep;
936 324 100       1023 @seps or @seps = (",", ";");
937 324         728 foreach my $sep (@seps) {
938 732 100       2159 index ($hdr, $sep) >= 0 and $sep{$sep}++;
939             }
940              
941 324 100       825 keys %sep >= 2 and croak ($self->SetDiag (1011));
942              
943 320         1068 $self->sep (keys %sep);
944 320         540 my $enc = "";
945 320 100       693 if ($args{'detect_bom'}) { # UTF-7 is not supported
946 319 100       2962 if ($hdr =~ s/^\x00\x00\xfe\xff//) { $enc = "utf-32be" }
  24 100       67  
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
947 24         42 elsif ($hdr =~ s/^\xff\xfe\x00\x00//) { $enc = "utf-32le" }
948 25         60 elsif ($hdr =~ s/^\xfe\xff//) { $enc = "utf-16be" }
949 24         46 elsif ($hdr =~ s/^\xff\xfe//) { $enc = "utf-16le" }
950 48         88 elsif ($hdr =~ s/^\xef\xbb\xbf//) { $enc = "utf-8" }
951 1         3 elsif ($hdr =~ s/^\xf7\x64\x4c//) { $enc = "utf-1" }
952 1         3 elsif ($hdr =~ s/^\xdd\x73\x66\x73//) { $enc = "utf-ebcdic" }
953 1         3 elsif ($hdr =~ s/^\x0e\xfe\xff//) { $enc = "scsu" }
954 1         2 elsif ($hdr =~ s/^\xfb\xee\x28//) { $enc = "bocu-1" }
955 1         3 elsif ($hdr =~ s/^\x84\x31\x95\x33//) { $enc = "gb-18030" }
956 36         67 elsif ($hdr =~ s/^\x{feff}//) { $enc = "" }
957              
958 319 100       810 $self->{'ENCODING'} = $enc ? uc $enc : undef;
959              
960 319 100       1237 $hdr eq "" and croak ($self->SetDiag (1010));
961              
962 313 100       567 if ($enc) {
963 144 50 33     331 $ebcdic && $enc eq "utf-ebcdic" and $enc = "";
964 144 100       780 if ($enc =~ m/([13]).le$/) {
965 48         151 my $l = 0 + $1;
966 48         69 my $x;
967 48         166 $hdr .= "\0" x $l;
968 48         178 read $fh, $x, $l;
969             }
970 144 50       247 if ($enc) {
971 144 100       290 if ($enc ne "utf-8") {
972 96         575 require Encode;
973 96         501 $hdr = Encode::decode ($enc, $hdr);
974             }
975 144         5827 binmode $fh, ":encoding($enc)";
976             }
977             }
978             }
979              
980 314         9055 my ($ahead, $eol);
981 314 100 66     1658 if ($hdr and $hdr =~ s/\Asep=(\S)([\r\n]+)//i) { # Also look in xs:Parse
982 1         7 $self->sep ($1);
983 1 50       11 length $hdr or $hdr = <$fh>;
984             }
985 314 100       2128 if ($hdr =~ s/^([^\r\n]+)([\r\n]+)([^\r\n].+)\z/$1/s) {
986 142         330 $eol = $2;
987 142         267 $ahead = $3;
988             }
989              
990 314         570 my $hr = \$hdr; # Will cause croak on perl-5.6.x
991 314 50   7   3445 open my $h, "<", $hr or croak ($self->SetDiag (1010));
  7         63  
  7         14  
  7         47  
992              
993 314 100       13894 my $row = $self->getline ($h) or croak ();
994 312         13161 close $h;
995              
996 312 100       880 if ( $args{'munge_column_names'} eq "lc") {
    100          
    100          
997 293         418 $_ = lc for @{$row};
  293         1096  
998             }
999             elsif ($args{'munge_column_names'} eq "uc") {
1000 7         15 $_ = uc for @{$row};
  7         44  
1001             }
1002             elsif ($args{'munge_column_names'} eq "db") {
1003 3         6 for (@{$row}) {
  3         9  
1004 7         17 s/\W+/_/g;
1005 7         16 s/^_+//;
1006 7         19 $_ = lc;
1007             }
1008             }
1009              
1010 312 100       718 if ($ahead) { # Must be after getline, which creates the cache
1011 142         520 $self->_cache_set ($_cache_id{'_has_ahead'}, 1);
1012 142         252 $self->{'_AHEAD'} = $ahead;
1013 142 100       622 $eol =~ m/^\r([^\n]|\z)/ and $self->eol ($eol);
1014             }
1015              
1016 312         456 my @hdr = @{$row};
  312         835  
1017             ref $args{'munge_column_names'} eq "CODE" and
1018 312 100       815 @hdr = map { $args{'munge_column_names'}->($_) } @hdr;
  4         17  
1019             ref $args{'munge_column_names'} eq "HASH" and
1020 312 100       620 @hdr = map { $args{'munge_column_names'}->{$_} || $_ } @hdr;
  3 100       13  
1021 312         397 my %hdr; $hdr{$_}++ for @hdr;
  312         1120  
1022 312 100       774 exists $hdr{''} and croak ($self->SetDiag (1012));
1023 310 100       829 unless (keys %hdr == @hdr) {
1024             croak ($self->_SetDiagInfo (1013, join ", " =>
1025 1         4 map { "$_ ($hdr{$_})" } grep { $hdr{$_} > 1 } keys %hdr));
  1         9  
  2         6  
1026             }
1027 309 100       1058 $args{'set_column_names'} and $self->column_names (@hdr);
1028 309 100       2665 wantarray ? @hdr : $self;
1029             } # header
1030              
1031             sub bind_columns {
1032 27     27 1 22724 my ($self, @refs) = @_;
1033             @refs or
1034 27 100       109 return defined $self->{'_BOUND_COLUMNS'} ? @{$self->{'_BOUND_COLUMNS'}} : undef;
  2 100       11  
1035              
1036 23 100 100     152 if (@refs == 1 && ! defined $refs[0]) {
1037 5         14 $self->{'_COLUMN_NAMES'} = undef;
1038 5         75 return $self->{'_BOUND_COLUMNS'} = undef;
1039             }
1040              
1041 18 100 100     85 $self->{'_COLUMN_NAMES'} && @refs != @{$self->{'_COLUMN_NAMES'}} and
  3         139  
1042             croak ($self->SetDiag (3003));
1043              
1044 17 100       200 join "", map { ref $_ eq "SCALAR" ? "" : "*" } @refs and
  74606 100       139344  
1045             croak ($self->SetDiag (3004));
1046              
1047 15         3250 $self->_set_attr_N ("_is_bound", scalar @refs);
1048 15         4277 $self->{'_BOUND_COLUMNS'} = [ @refs ];
1049 15         1438 @refs;
1050             } # bind_columns
1051              
1052             sub getline_hr {
1053 125     125 1 13619 my ($self, @args, %hr) = @_;
1054 125 100       483 $self->{'_COLUMN_NAMES'} or croak ($self->SetDiag (3002));
1055 124 100       2688 my $fr = $self->getline (@args) or return;
1056 122 100       2599 if (ref $self->{'_FFLAGS'}) { # missing
1057             $self->{'_FFLAGS'}[$_] = CSV_FLAGS_IS_MISSING ()
1058 5 50       9 for (@{$fr} ? $#{$fr} + 1 : 0) .. $#{$self->{'_COLUMN_NAMES'}};
  5         13  
  5         10  
  5         22  
1059 5         31 @{$fr} == 1 && (!defined $fr->[0] || $fr->[0] eq "") and
1060 5 100 33     10 $self->{'_FFLAGS'}[0] ||= CSV_FLAGS_IS_MISSING ();
      66        
      100        
1061             }
1062 122         185 @hr{@{$self->{'_COLUMN_NAMES'}}} = @{$fr};
  122         481  
  122         208  
1063 122         613 \%hr;
1064             } # getline_hr
1065              
1066             sub getline_hr_all {
1067 246     246 1 500 my ($self, @args) = @_;
1068 246 100       890 $self->{'_COLUMN_NAMES'} or croak ($self->SetDiag (3002));
1069 244         320 my @cn = @{$self->{'_COLUMN_NAMES'}};
  244         550  
1070 244         353 [ map { my %h; @h{@cn} = @{$_}; \%h } @{$self->getline_all (@args)} ];
  370         4999  
  370         462  
  370         1271  
  370         1722  
  244         6774  
1071             } # getline_hr_all
1072              
1073             sub say {
1074 13     13 1 3303 my ($self, $io, @f) = @_;
1075 13         37 my $eol = $self->eol ();
1076 13 100 33     96 $eol eq "" and $self->eol ($\ || $/);
1077             # say ($fh, undef) does not propage actual undef to print ()
1078 13 100 66     209 my $state = $self->print ($io, @f == 1 && !defined $f[0] ? undef : @f);
1079 13         153 $self->eol ($eol);
1080 13         58 return $state;
1081             } # say
1082              
1083             sub print_hr {
1084 3     3 1 326 my ($self, $io, $hr) = @_;
1085 3 100       120 $self->{'_COLUMN_NAMES'} or croak ($self->SetDiag (3009));
1086 2 100       108 ref $hr eq "HASH" or croak ($self->SetDiag (3010));
1087 1         5 $self->print ($io, [ map { $hr->{$_} } $self->column_names () ]);
  3         16  
1088             } # print_hr
1089              
1090             sub fragment {
1091 58     58 1 29386 my ($self, $io, $spec) = @_;
1092              
1093 58         250 my $qd = qr{\s* [0-9]+ \s* }x; # digit
1094 58         156 my $qs = qr{\s* (?: [0-9]+ | \* ) \s*}x; # digit or star
1095 58         425 my $qr = qr{$qd (?: - $qs )?}x; # range
1096 58         344 my $qc = qr{$qr (?: ; $qr )*}x; # list
1097 58 100 100     3841 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         186 my ($type, $range) = (lc $1, $2);
1105              
1106 38         110 my @h = $self->column_names ();
1107              
1108 38         60 my @c;
1109 38 100       105 if ($type eq "cell") {
1110 21         34 my @spec;
1111             my $min_row;
1112 21         43 my $max_row = 0;
1113 21         97 for (split m/\s*;\s*/ => $range) {
1114 37 100       336 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       102 defined $brr or ($brr, $brc) = ($tlr, $tlc);
1119 36 100 100     1472 $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         43 $tlc--;
1124 28 100       54 $brc-- unless $brc eq "*";
1125 28 100       54 defined $min_row or $min_row = $tlr;
1126 28 100       53 $tlr < $min_row and $min_row = $tlr;
1127 28 100 100     81 $brr eq "*" || $brr > $max_row and
1128             $max_row = $brr;
1129 28         84 push @spec, [ $tlr, $tlc, $brr, $brc ];
1130             }
1131 12         18 my $r = 0;
1132 12         306 while (my $row = $self->getline ($io)) {
1133 77 100       2972 ++$r < $min_row and next;
1134 33         49 my %row;
1135             my $lc;
1136 33         73 foreach my $s (@spec) {
1137 77         97 my ($tlr, $tlc, $brr, $brc) = @{$s};
  77         136  
1138 77 100 100     274 $r < $tlr || ($brr ne "*" && $r > $brr) and next;
      100        
1139 45 100 100     109 !defined $lc || $tlc < $lc and $lc = $tlc;
1140 45 100       82 my $rr = $brc eq "*" ? $#{$row} : $brc;
  5         9  
1141 45         188 $row{$_} = $row->[$_] for $tlc .. $rr;
1142             }
1143 33         122 push @c, [ @row{sort { $a <=> $b } keys %row } ];
  65         167  
1144 33 100       75 if (@h) {
1145 2         4 my %h; @h{@h} = @{$c[-1]};
  2         3  
  2         12  
1146 2         5 $c[-1] = \%h;
1147             }
1148 33 100 100     616 $max_row ne "*" && $r == $max_row and last;
1149             }
1150 12         134 return \@c;
1151             }
1152              
1153             # row or col
1154 17         29 my @r;
1155 17         27 my $eod = 0;
1156 17         94 for (split m/\s*;\s*/ => $range) {
1157 25 50       160 my ($from, $to) = m/^\s* ([0-9]+) (?: \s* - \s* ([0-9]+ | \* ))? \s* $/x
1158             or croak ($self->SetDiag (2013));
1159 25   100     93 $to ||= $from;
1160 25 100       52 $to eq "*" and ($to, $eod) = ($from, 1);
1161             # $to cannot be <= 0 due to regex and ||=
1162 25 100 100     388 $from <= 0 || $to < $from and croak ($self->SetDiag (2013));
1163 22         83 $r[$_] = 1 for $from .. $to;
1164             }
1165              
1166 14         22 my $r = 0;
1167 14 100       34 $type eq "col" and shift @r;
1168 14   100     131 $_ ||= 0 for @r;
1169 14         529 while (my $row = $self->getline ($io)) {
1170 109         3179 $r++;
1171 109 100       236 if ($type eq "row") {
1172 64 100 100     297 if (($r > $#r && $eod) || $r[$r]) {
      100        
1173 20         42 push @c, $row;
1174 20 100       53 if (@h) {
1175 3         5 my %h; @h{@h} = @{$c[-1]};
  3         46  
  3         18  
1176 3         8 $c[-1] = \%h;
1177             }
1178             }
1179 64         1307 next;
1180             }
1181 45 100 100     74 push @c, [ map { ($_ > $#r && $eod) || $r[$_] ? $row->[$_] : () } 0..$#{$row} ];
  405         1433  
  45         91  
1182 45 100       1189 if (@h) {
1183 9         11 my %h; @h{@h} = @{$c[-1]};
  9         10  
  9         25  
1184 9         199 $c[-1] = \%h;
1185             }
1186             }
1187              
1188 14         380 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   1890 my %attr = (@_ == 1 && ref $_[0] eq "HASH" ? %{$_[0]} : @_) or croak ();
  4 50       20  
1195              
1196 322         717 $attr{'binary'} = 1;
1197              
1198 322   100     1441 my $enc = delete $attr{'enc'} || delete $attr{'encoding'} || "";
1199 322 100       703 $enc eq "auto" and ($attr{'detect_bom'}, $enc) = (1, "");
1200 322 50       797 my $stack = $enc =~ s/(:\w.*)// ? $1 : "";
1201 322 100       704 $enc =~ m/^[-\w.]+$/ and $enc = ":encoding($enc)";
1202 322         586 $enc .= $stack;
1203              
1204 322         405 my $fh;
1205 322         546 my $sink = 0;
1206 322         429 my $cls = 0; # If I open a file, I have to close it
1207 322 100 100     1370 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     1394 : delete $attr{'out'} || delete $attr{'file'};
      100        
1210              
1211 319 100 100     1132 ref $in eq "CODE" || ref $in eq "ARRAY" and $out ||= \*STDOUT;
      100        
1212              
1213 319 100 66     1267 $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       596 if ($out) {
1218 32 100 100     320 if (ref $out and ("ARRAY" eq ref $out or "HASH" eq ref $out)) {
    100 100        
    100 100        
      100        
      66        
      66        
      66        
1219 5         7 delete $attr{'out'};
1220 5         9 $sink = 1;
1221             }
1222             elsif ((ref $out and "SCALAR" ne ref $out) or "GLOB" eq ref \$out) {
1223 14         30 $fh = $out;
1224             }
1225 6         21 elsif (ref $out and "SCALAR" eq ref $out and defined ${$out} and ${$out} eq "skip") {
  6         20  
1226 1         2 delete $attr{'out'};
1227 1         2 $sink = 1;
1228             }
1229             else {
1230 12 100       666 open $fh, ">", $out or croak ("$out: $!");
1231 11         39 $cls = 1;
1232             }
1233 31 100       68 if ($fh) {
1234 25 100       51 if ($enc) {
1235 1         14 binmode $fh, $enc;
1236 1         71 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         34 my @layers = eval { PerlIO::get_layers ($fh) };
  18         115  
1240 18 100       171 $attr{'eol'} = (grep m/crlf/ => @layers) ? "\n" : "\r\n";
1241             }
1242             }
1243             }
1244              
1245 317 100 100     1761 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       370 open $fh, "<", $in or croak ("Cannot open from SCALAR using PerlIO");
1252 25         2073 $cls = 1;
1253             }
1254             elsif (ref $in or "GLOB" eq ref \$in) {
1255 16 50 66     44 if (!ref $in && $] < 5.008005) {
1256 0         0 $fh = \*{$in}; # uncoverable statement ancient perl version required
  0         0  
1257             }
1258             else {
1259 16         28 $fh = $in;
1260             }
1261             }
1262             else {
1263 252 100       10264 open $fh, "<$enc", $in or croak ("$in: $!");
1264 250         18872 $cls = 1;
1265             }
1266 315 50 33     893 $fh || $sink or croak (qq{No valid source passed. "in" is required});
1267              
1268 315         599 my $hdrs = delete $attr{'headers'};
1269 315         499 my $frag = delete $attr{'fragment'};
1270 315         470 my $key = delete $attr{'key'};
1271 315         488 my $val = delete $attr{'value'};
1272             my $kh = delete $attr{'keep_headers'} ||
1273             delete $attr{'keep_column_names'} ||
1274 315   100     1433 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     1892 delete $attr{'after_parse'};
1280             my $cbbo = delete $attr{'callbacks'}{'before_out'} ||
1281 315   100     890 delete $attr{'before_out'};
1282             my $cboi = delete $attr{'callbacks'}{'on_in'} ||
1283 315   100     849 delete $attr{'on_in'};
1284              
1285             my $hd_s = delete $attr{'sep_set'} ||
1286 315   100     851 delete $attr{'seps'};
1287             my $hd_b = delete $attr{'detect_bom'} ||
1288 315   100     878 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         1161 for ([ 'quo' => "quote" ],
1294             [ 'esc' => "escape" ],
1295             [ 'escape' => "escape_char" ],
1296             ) {
1297 945         1202 my ($f, $t) = @{$_};
  945         1679  
1298 945 100 100     2238 exists $attr{$f} and !exists $attr{$t} and $attr{$t} = delete $attr{$f};
1299             }
1300              
1301 315         706 my $fltr = delete $attr{'filter'};
1302             my %fltr = (
1303 10 100 33 10   12 'not_blank' => sub { @{$_[1]} > 1 or defined $_[1][0] && $_[1][0] ne "" },
  10         93  
1304 10 50   10   13 'not_empty' => sub { grep { defined && $_ ne "" } @{$_[1]} },
  26         177  
  10         18  
1305 10 50   10   17 'filled' => sub { grep { defined && m/\S/ } @{$_[1]} },
  26         221  
  10         22  
1306 315         2341 );
1307             defined $fltr && !ref $fltr && exists $fltr{$fltr} and
1308 315 50 100     871 $fltr = { '0' => $fltr{$fltr} };
      66        
1309 315 100       699 ref $fltr eq "CODE" and $fltr = { 0 => $fltr };
1310 315 100       650 ref $fltr eq "HASH" or $fltr = undef;
1311              
1312 315         491 my $form = delete $attr{'formula'};
1313              
1314 315 100       749 defined $attr{'auto_diag'} or $attr{'auto_diag'} = 1;
1315 315 100       723 defined $attr{'escape_null'} or $attr{'escape_null'} = 0;
1316 315 50 66     1584 my $csv = delete $attr{'csv'} || Text::CSV_XS->new (\%attr)
1317             or croak ($last_new_err);
1318 315 100       669 defined $form and $csv->formula ($form);
1319              
1320 315 100 100     784 $kh && !ref $kh && $kh =~ m/^(?:1|yes|true|internal|auto)$/i and
      100        
1321             $kh = \@internal_kh;
1322              
1323             return {
1324 315         5919 '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 71622 @_ && ref $_[0] eq __PACKAGE__ and splice @_, 0, 0, "csv";
1350 323 100       924 @_ or croak ($csv_usage);
1351              
1352 322         1995 my $c = _csv_attr (@_);
1353              
1354 315         696 my ($csv, $in, $fh, $hdrs) = @{$c}{qw( csv in fh hdrs )};
  315         936  
1355 315         514 my %hdr;
1356 315 100       713 if (ref $hdrs eq "HASH") {
1357 2         5 %hdr = %{$hdrs};
  2         7  
1358 2         5 $hdrs = "auto";
1359             }
1360              
1361 315 100 100     763 if ($c->{'out'} && !$c->{'sink'}) {
1362             !$hdrs && ref $c->{'kh'} && $c->{'kh'} == \@internal_kh and
1363 24 100 100     127 $hdrs = $c->{'kh'};
      66        
1364              
1365 24 100 100     55 if (ref $in eq "CODE") {
    100          
1366 3         5 my $hdr = 1;
1367 3         12 while (my $row = $in->($csv)) {
1368 7 100       51 if (ref $row eq "ARRAY") {
1369 3         27 $csv->print ($fh, $row);
1370 3         43 next;
1371             }
1372 4 50       10 if (ref $row eq "HASH") {
1373 4 100       8 if ($hdr) {
1374 2 50 100     6 $hdrs ||= [ map { $hdr{$_} || $_ } keys %{$row} ];
  3         15  
  1         7  
1375 2         37 $csv->print ($fh, $hdrs);
1376 2         21 $hdr = 0;
1377             }
1378 4         7 $csv->print ($fh, [ @{$row}{@{$hdrs}} ]);
  4         21  
  4         7  
1379             }
1380             }
1381             }
1382 21         87 elsif (@{$in} == 0 or ref $in->[0] eq "ARRAY") { # aoa
1383 10 50       23 ref $hdrs and $csv->print ($fh, $hdrs);
1384 10         17 for (@{$in}) {
  10         23  
1385 12 100       101 $c->{'cboi'} and $c->{'cboi'}->($csv, $_);
1386 12 50       1064 $c->{'cbbo'} and $c->{'cbbo'}->($csv, $_);
1387 12         217 $csv->print ($fh, $_);
1388             }
1389             }
1390             else { # aoh
1391 11 100       25 my @hdrs = ref $hdrs ? @{$hdrs} : keys %{$in->[0]};
  5         12  
  6         21  
1392 11 100       23 defined $hdrs or $hdrs = "auto";
1393             ref $hdrs || $hdrs eq "auto" and @hdrs and
1394 11 100 100     60 $csv->print ($fh, [ map { $hdr{$_} || $_ } @hdrs ]);
  20 100 66     301  
1395 11         127 for (@{$in}) {
  11         29  
1396 17         68 local %_;
1397 17         37 *_ = $_;
1398 17 50       39 $c->{'cboi'} and $c->{'cboi'}->($csv, $_);
1399 17 50       28 $c->{'cbbo'} and $c->{'cbbo'}->($csv, $_);
1400 17         27 $csv->print ($fh, [ @{$_}{@hdrs} ]);
  17         111  
1401             }
1402             }
1403              
1404 24 100       835 $c->{'cls'} and close $fh;
1405 24         329 return 1;
1406             }
1407              
1408 291         421 my @row1;
1409 291 100 100     1451 if (defined $c->{'hd_s'} || defined $c->{'hd_b'} || defined $c->{'hd_m'} || defined $c->{'hd_c'}) {
      100        
      100        
1410 173         322 my %harg;
1411             !defined $c->{'hd_s'} && $c->{'attr'}{'sep_char'} and
1412 173 100 100     642 $c->{'hd_s'} = [ $c->{'attr'}{'sep_char'} ];
1413             !defined $c->{'hd_s'} && $c->{'attr'}{'sep'} and
1414 173 100 100     588 $c->{'hd_s'} = [ $c->{'attr'}{'sep'} ];
1415 173 100       341 defined $c->{'hd_s'} and $harg{'sep_set'} = $c->{'hd_s'};
1416 173 100       379 defined $c->{'hd_b'} and $harg{'detect_bom'} = $c->{'hd_b'};
1417 173 50       341 defined $c->{'hd_m'} and $harg{'munge_column_names'} = $hdrs ? "none" : $c->{'hd_m'};
    100          
1418 173 50       294 defined $c->{'hd_c'} and $harg{'set_column_names'} = $hdrs ? 0 : $c->{'hd_c'};
    100          
1419 173         447 @row1 = $csv->header ($fh, \%harg);
1420 170         410 my @hdr = $csv->column_names ();
1421 170 100 100     823 @hdr and $hdrs ||= \@hdr;
1422             }
1423              
1424 288 100       677 if ($c->{'kh'}) {
1425 15         40 @internal_kh = ();
1426 15 100       696 ref $c->{'kh'} eq "ARRAY" or croak ($csv->SetDiag (1501));
1427 10   100     27 $hdrs ||= "auto";
1428             }
1429              
1430 283         438 my $key = $c->{'key'};
1431 283 100       572 if ($key) {
1432 27 100 100     576 !ref $key or ref $key eq "ARRAY" && @{$key} > 1 or croak ($csv->SetDiag (1501));
  8   100     437  
1433 20   100     123 $hdrs ||= "auto";
1434             }
1435 276         423 my $val = $c->{'val'};
1436 276 100       499 if ($val) {
1437 9 100       146 $key or croak ($csv->SetDiag (1502));
1438 8 100 100     250 !ref $val or ref $val eq "ARRAY" && @{$val} > 0 or croak ($csv->SetDiag (1503));
  3   100     122  
1439             }
1440              
1441 272 100 100     627 $c->{'fltr'} && grep m/\D/ => keys %{$c->{'fltr'}} and $hdrs ||= "auto";
  16   100     119  
1442 272 100       544 if (defined $hdrs) {
1443 219 100 100     831 if (!ref $hdrs or ref $hdrs eq "CODE") {
1444 48 100       1893 my $h = $c->{'hd_b'}
1445             ? [ $csv->column_names () ]
1446             : $csv->getline ($fh);
1447 48   33     2500 my $has_h = $h && @$h;
1448              
1449 48 100       241 if (ref $hdrs) {
    100          
    100          
    100          
    50          
1450 1 50       15 $has_h or return;
1451 1         2 my $cr = $hdrs;
1452 1   33     2 $hdrs = [ map { $cr->($hdr{$_} || $_) } @{$h} ];
  3         26  
  1         3  
1453             }
1454             elsif ($hdrs eq "skip") {
1455             # discard;
1456             }
1457             elsif ($hdrs eq "auto") {
1458 44 50       104 $has_h or return;
1459 44 100       65 $hdrs = [ map { $hdr{$_} || $_ } @{$h} ];
  128         481  
  44         94  
1460             }
1461             elsif ($hdrs eq "lc") {
1462 1 50       3 $has_h or return;
1463 1   33     3 $hdrs = [ map { lc ($hdr{$_} || $_) } @{$h} ];
  3         15  
  1         3  
1464             }
1465             elsif ($hdrs eq "uc") {
1466 1 50       4 $has_h or return;
1467 1   33     2 $hdrs = [ map { uc ($hdr{$_} || $_) } @{$h} ];
  3         20  
  1         3  
1468             }
1469             }
1470 219 100 66     663 $c->{'kh'} and $hdrs and @{$c->{'kh'}} = @{$hdrs};
  10         28  
  10         24  
1471             }
1472              
1473 272 100       545 if ($c->{'fltr'}) {
1474 16         25 my %f = %{$c->{'fltr'}};
  16         50  
1475             # convert headers to index
1476 16         26 my @hdr;
1477 16 100       33 if (ref $hdrs) {
1478 7         15 @hdr = @{$hdrs};
  7         21  
1479 7         23 for (0 .. $#hdr) {
1480 21 100       109 exists $f{$hdr[$_]} and $f{$_ + 1} = delete $f{$hdr[$_]};
1481             }
1482             }
1483             $csv->callbacks ('after_parse' => sub {
1484 114     114   4304 my ($CSV, $ROW) = @_; # lexical sub-variables in caps
1485 114         337 foreach my $FLD (sort keys %f) {
1486 115         273 local $_ = $ROW->[$FLD - 1];
1487 115         168 local %_;
1488 115 100       219 @hdr and @_{@hdr} = @{$ROW};
  51         184  
1489 115 100       283 $f{$FLD}->($CSV, $ROW) or return \"skip";
1490 52         1279 $ROW->[$FLD - 1] = $_;
1491             }
1492 16         111 });
1493             }
1494              
1495 272         445 my $frag = $c->{'frag'};
1496             my $ref = ref $hdrs
1497             ? # aoh
1498 272 100       2849 do {
    100          
1499 218         469 my @h = $csv->column_names ($hdrs);
1500 218         319 my %h; $h{$_}++ for @h;
  218         741  
1501 218 50       466 exists $h{''} and croak ($csv->SetDiag (1012));
1502 218 50       482 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       731 $key ? do {
    100          
1508 17 100       55 my ($k, $j, @f) = ref $key ? (undef, @{$key}) : ($key);
  5         14  
1509 17 100       36 if (my @mk = grep { !exists $h{$_} } grep { defined } $k, @f) {
  22         76  
  27         57  
1510 2         10 croak ($csv->_SetDiagInfo (4001, join ", " => @mk));
1511             }
1512             +{ map {
1513 26         41 my $r = $_;
1514 26 100       62 my $K = defined $k ? $r->{$k} : join $j => @{$r}{@f};
  4         34  
1515             ( $K => (
1516             $val
1517             ? ref $val
1518 4         22 ? { map { $_ => $r->{$_} } @{$val} }
  2         4  
1519 26 100       116 : $r->{$val}
    100          
1520             : $r ));
1521 15         24 } @{$csv->getline_hr_all ($fh)} }
  15         35  
1522             }
1523             : $csv->getline_hr_all ($fh);
1524             }
1525             : # aoa
1526             $frag ? $csv->fragment ($fh, $frag)
1527             : $csv->getline_all ($fh);
1528 264 50       2462 if ($ref) {
1529 264 100 66     1204 @row1 && !$c->{'hd_c'} && !ref $hdrs and unshift @{$ref}, \@row1;
  4   100     10  
1530             }
1531             else {
1532 0         0 Text::CSV_XS->auto_diag ();
1533             }
1534 264 100       3587 $c->{'cls'} and close $fh;
1535 264 100 100     1649 if ($ref and $c->{'cbai'} || $c->{'cboi'}) {
      66        
1536             # Default is ARRAYref, but with key =>, you'll get a hashref
1537 22 100       77 foreach my $r (ref $ref eq "ARRAY" ? @{$ref} : values %{$ref}) {
  21         54  
  1         7  
1538 71         5739 local %_;
1539 71 100       219 ref $r eq "HASH" and *_ = $r;
1540 71 100       184 $c->{'cbai'} and $c->{'cbai'}->($csv, $r);
1541 71 100       3460 $c->{'cboi'} and $c->{'cboi'}->($csv, $r);
1542             }
1543             }
1544              
1545 264 100       1675 if ($c->{'sink'}) {
1546 6 50       49 my $ro = ref $c->{'out'} or return;
1547              
1548 6 100 66     51 $ro eq "SCALAR" && ${$c->{'out'}} eq "skip" and
  1         20  
1549             return;
1550              
1551 5 50       11 $ro eq ref $ref or
1552             croak ($csv->_SetDiagInfo (5001, "Output type mismatch"));
1553              
1554 5 100       12 if ($ro eq "ARRAY") {
1555 4 100 33     14 if (@{$c->{'out'}} and @$ref and ref $c->{'out'}[0] eq ref $ref->[0]) {
  4   66     29  
1556 2         4 push @{$c->{'out'}} => @$ref;
  2         7  
1557 2         29 return $c->{'out'};
1558             }
1559 2         7 croak ($csv->_SetDiagInfo (5001, "Output type mismatch"));
1560             }
1561              
1562 1 50       15 if ($ro eq "HASH") {
1563 1         3 @{$c->{'out'}}{keys %{$ref}} = values %{$ref};
  1         3  
  1         2  
  1         4  
1564 1         17 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       525 %{$c->{'attr'}},
  1         19  
1575             );
1576              
1577 257         4382 return $ref;
1578             } # csv
1579              
1580             1;
1581              
1582             __END__