File Coverage

blib/lib/Text/CSV_XS.pm
Criterion Covered Total %
statement 885 894 99.1
branch 687 730 94.1
condition 368 425 86.3
subroutine 85 85 100.0
pod 66 66 100.0
total 2091 2200 95.0


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