From b07045cdb8d186be1fe9f8071492317f65834a96 Mon Sep 17 00:00:00 2001 From: "H.Merijn Brand" Date: Sat, 8 Aug 2009 14:39:20 -0800 Subject: [PATCH] import Text-CSV_XS 0.67 from CPAN git-cpan-module: Text-CSV_XS git-cpan-version: 0.67 git-cpan-authorid: HMBRAND git-cpan-file: authors/id/H/HM/HMBRAND/Text-CSV_XS-0.67.tgz --- CSV_XS.pm | 177 +++++++++----- CSV_XS.xs | 146 +++++------- ChangeLog | 614 +++++++++++++++++++++++++----------------------- MANIFEST | 2 + META.yml | 4 +- ppport.h | 95 +++++++- t/12_acc.t | 11 +- t/15_flags.t | 17 +- t/41_null.t | 77 ++++++ t/65_allow.t | 27 ++- t/80_diag.t | 35 ++- t/81_subclass.t | 28 +++ 12 files changed, 757 insertions(+), 476 deletions(-) create mode 100644 t/41_null.t create mode 100644 t/81_subclass.t diff --git a/CSV_XS.pm b/CSV_XS.pm index 031ea91..870eee7 100644 --- a/CSV_XS.pm +++ b/CSV_XS.pm @@ -30,7 +30,7 @@ use DynaLoader (); use Carp; use vars qw( $VERSION @ISA ); -$VERSION = "0.65"; +$VERSION = "0.67"; @ISA = qw( DynaLoader ); bootstrap Text::CSV_XS $VERSION; @@ -65,7 +65,9 @@ my %def_attr = ( allow_loose_escapes => 0, allow_whitespace => 0, blank_is_undef => 0, + empty_is_undef => 0, verbatim => 0, + auto_diag => 0, types => undef, _EOF => 0, @@ -85,8 +87,10 @@ sub new "usage: my \$csv = Text::CSV_XS->new ([{ option => value, ... }]);"); my $proto = shift; + my $class = ref ($proto) || $proto or return; + @_ > 0 && ref $_[0] ne "HASH" and return; my $attr = shift || {}; - my $class = ref ($proto) || $proto or return; + for (keys %{$attr}) { if (m/^[a-z]/ && exists $def_attr{$_}) { $] >= 5.008002 && m/_char$/ and utf8::decode ($attr->{$_}); @@ -130,10 +134,13 @@ my %_cache_id = ( # Keep in sync with XS! eol_is_cr => 20, has_types => 21, verbatim => 22, + empty_is_undef => 23, + auto_diag => 24, - _is_bound => 23, # 23 .. 26 + _is_bound => 25, # 25 .. 28 ); +# A `character' sub _set_attr_C { my ($self, $name, $val) = @_; @@ -146,6 +153,19 @@ sub _set_attr_C $self->{_CACHE} = pack "C*", @cache; } # _set_attr_C +# A flag +sub _set_attr_X +{ + my ($self, $name, $val) = @_; + defined $val or $val = 0; + $self->{$name} = $val; + $self->{_CACHE} or return; + my @cache = unpack "C*", $self->{_CACHE}; + $cache[$_cache_id{$name}] = 0 + $val; + $self->{_CACHE} = pack "C*", @cache; + } # _set_attr_C + +# A number sub _set_attr_N { my ($self, $name, $val) = @_; @@ -216,35 +236,35 @@ sub eol sub always_quote { my $self = shift; - @_ and $self->_set_attr_C ("always_quote", shift); + @_ and $self->_set_attr_X ("always_quote", shift); $self->{always_quote}; } # always_quote sub binary { my $self = shift; - @_ and $self->_set_attr_C ("binary", shift); + @_ and $self->_set_attr_X ("binary", shift); $self->{binary}; } # binary sub keep_meta_info { my $self = shift; - @_ and $self->_set_attr_C ("keep_meta_info", shift); + @_ and $self->_set_attr_X ("keep_meta_info", shift); $self->{keep_meta_info}; } # keep_meta_info sub allow_loose_quotes { my $self = shift; - @_ and $self->_set_attr_C ("allow_loose_quotes", shift); + @_ and $self->_set_attr_X ("allow_loose_quotes", shift); $self->{allow_loose_quotes}; } # allow_loose_quotes sub allow_loose_escapes { my $self = shift; - @_ and $self->_set_attr_C ("allow_loose_escapes", shift); + @_ and $self->_set_attr_X ("allow_loose_escapes", shift); $self->{allow_loose_escapes}; } # allow_loose_escapes @@ -257,7 +277,7 @@ sub allow_whitespace (defined $self->{quote_char} && $self->{quote_char} =~ m/^[ \t]$/) || (defined $self->{escape_char} && $self->{escape_char} =~ m/^[ \t]$/) and croak ($self->SetDiag (1002)); - $self->_set_attr_C ("allow_whitespace", $aw); + $self->_set_attr_X ("allow_whitespace", $aw); } $self->{allow_whitespace}; } # allow_whitespace @@ -265,10 +285,17 @@ sub allow_whitespace sub blank_is_undef { my $self = shift; - @_ and $self->_set_attr_C ("blank_is_undef", shift); + @_ and $self->_set_attr_X ("blank_is_undef", shift); $self->{blank_is_undef}; } # blank_is_undef +sub empty_is_undef +{ + my $self = shift; + @_ and $self->_set_attr_X ("empty_is_undef", shift); + $self->{empty_is_undef}; + } # empty_is_undef + sub verbatim { my $self = shift; @@ -276,6 +303,13 @@ sub verbatim $self->{verbatim}; } # verbatim +sub auto_diag +{ + my $self = shift; + @_ and $self->_set_attr_X ("auto_diag", shift); + $self->{auto_diag}; + } # auto_diag + # status # # object method returning the success or failure of the most recent @@ -322,7 +356,10 @@ sub error_diag my $context = wantarray; unless (defined $context) { # Void context - $diag[0] and print STDERR "# CSV_XS ERROR: $diag[0] - $diag[1]\n"; + if ($diag[0]) { + my $msg = "# CSV_XS ERROR: $diag[0] - $diag[1]\n"; + $self && ref $self && $self->{auto_diag} > 1 ? die $msg : warn $msg; + } return; } return $context ? @diag : $diag[1]; @@ -590,8 +627,8 @@ or, more safely in perl 5.6 and up =head2 Unicode (UTF8) On parsing (both for C and C), if the source is -marked being UTF8, then parsing that source will mark all fields that -are marked binary will also be marked UTF8. +marked being UTF8, then all fields that are marked binary will also be +be marked UTF8. On combining (C and C), if any of the combining fields was marked UTF8, the resulting string will be marked UTF8. @@ -681,7 +718,7 @@ QUOTATION MARK) (to give some examples of what might look promising) are therefor not allowed. If you use perl-5.8.2 or higher, these three attributes are utf8-decoded, to -increase the likelyhood of success. This way U+00FE will be allowed as a +increase the likelihood of success. This way U+00FE will be allowed as a quote character. =item * @@ -780,6 +817,20 @@ be parsed as ("1", "", undef, " ", "2") +=item empty_is_undef + +Going one step further than C, this attribute converts +all empty fields to undef, so + + 1,"",," ",2 + +is read as + + (1, undef, undef, " ", 2) + +Note that this only effects fields that are I empty, not fields +that are empty after stripping allowed whitespace. YMMV. + =item quote_char The char used for quoting fields containing blanks, by default the @@ -912,6 +963,18 @@ as if \n is just nothing more than a binary character. For parse () this means that the parser has no idea about line ending anymore, and getline () chomps line endings on reading. +=item auto_diag + +Set to true will cause C to be automatically be called +in void context upon errors. + +If set to a value greater than 1, it will die on errors instead of +warn. + +Future extensions to this feature will include auto-detection of the +C module being enabled, which will raise the value of C +with C<1> on the moment the error is detected. + =back To sum it up, @@ -932,7 +995,9 @@ is equivalent to allow_loose_escapes => 0, allow_whitespace => 0, blank_is_undef => 0, + empty_is_undef => 0, verbatim => 0, + auto_diag => 0, }); For all of the above mentioned flags, there is an accessor method @@ -982,8 +1047,8 @@ in perl 5.005_xx and older: as in perl 5.005 and older, the glob C<\*FILE> is not an object, thus it doesn't have a print method. The solution is to use an IO::File object or -to hide the glob behind an IO::Wrap object. See L and -L for details. +to hide the glob behind an IO::Wrap object. See L and L +for details. For performance reasons the print method doesn't create a result string. In particular the I<$csv-Estring ()>, I<$csv-Estatus ()>, @@ -1056,7 +1121,7 @@ string C<"\cAUNDEF\cA">, so $hr = $csv->getline_hr ($io); Will set C<$hr->{"\cAUNDEF\cA"}> to the 1st field, C<$hr->{""}> to the -2nd field, and C<$hr->{name}> to the 4th field, discarding the 2rd field. +2nd field, and C<$hr->{name}> to the 4th field, discarding the 3rd field. C croaks on invalid arguments. @@ -1126,7 +1191,7 @@ Set field type to string. @columns = $csv->fields (); This object function returns the input to C or the resultant -decomposed fields of C successfull , whichever was called more +decomposed fields of C successful , whichever was called more recently. Note that the return value is undefined after using C, which @@ -1244,7 +1309,17 @@ as the API may change in future releases. =head1 EXAMPLES -An example for parsing CSV strings: +Reading a CSV file line by line: + + my $csv = Text::CSV_XS->new ({ binary => 1 }); + open my $fh, "<", "file.csv" or die "file.csv: $!"; + while (my $row = $csv->getline ($fh)) { + # do something with @$row + } + $csv->eof or $csv->error_diag; + close $fh or die "file.csv: $!"; + +Parsing CSV strings: my $csv = Text::CSV_XS->new ({ keep_meta_info => 1, binary => 1 }); @@ -1258,31 +1333,12 @@ An example for parsing CSV strings: } } else { - my $err = $csv->error_input; - print STDERR "parse () failed on argument: ", $err, "\n"; + print STDERR "parse () failed on argument: ", + $csv->error_input, "\n"; $csv->error_diag (); } -An example for creating CSV files: - - my $csv = Text::CSV_XS->new; - - open my $csv_fh, ">", "hello.csv" or die "hello.csv: $!"; - - my @sample_input_fields = ( - 'You said, "Hello!"', 5.67, - '"Surely"', '', '3.14159'); - if ($csv->combine (@sample_input_fields)) { - my $string = $csv->string; - print $csv_fh "$string\n"; - } - else { - my $err = $csv->error_input; - print "combine () failed on argument: ", $err, "\n"; - } - close $csv_fh or die "hello.csv: $!"; - -Or using the C method, which is faster like in +An example for creating CSV files using the C method, like in dumping the content of a database ($dbh) table ($tbl) to CSV: my $csv = Text::CSV_XS->new ({ binary => 1, eol => $/ }); @@ -1291,19 +1347,27 @@ dumping the content of a database ($dbh) table ($tbl) to CSV: $sth->execute; $csv->print ($fh, $sth->{NAME_lc}); while (my $row = $sth->fetch) { - $csv->print ($fh, $row) or ...; + $csv->print ($fh, $row) or $csv->error_diag; } close $fh or die "$tbl.csv: $!"; -Reading a CSV file line by line: +or using the slower C and C methods: - my $csv = Text::CSV_XS->new ({ binary => 1 }); - open my $fh, "<", "file.csv" or die "file.csv: $!"; - while (my $row = $csv->getline ($fh)) { - # do something with @$row + my $csv = Text::CSV_XS->new; + + open my $csv_fh, ">", "hello.csv" or die "hello.csv: $!"; + + my @sample_input_fields = ( + 'You said, "Hello!"', 5.67, + '"Surely"', '', '3.14159'); + if ($csv->combine (@sample_input_fields)) { + print $csv_fh $csv->string, "\n"; } - $csv->eof or $csv->error_diag; - close $fh or die "file.csv: $!"; + else { + print "combine () failed on argument: ", + $csv->error_input, "\n"; + } + close $csv_fh or die "hello.csv: $!"; For more extended examples, see the C subdirectory in the original distribution. The following files can be found there: @@ -1328,8 +1392,8 @@ CSV file and report on its content. =item csv2xls -A script to convert CSV to Microsoft Excel. This requires L -and L. The converter acceps various options and +A script to convert CSV to Microsoft Excel. This requires L +and L. The converter accepts various options and can produce UTF-8 Excel files. =back @@ -1440,6 +1504,11 @@ normal cases - when no error occured - may cause unexpected results. If the constructor failed, the cause can be found using C as a class method, like Cerror_diag ()>. +C<$csv->error_diag ()> is automatically called upon error when the contractor +was called with C set to 1 or 2, or when C is in effect +(NYI). When set to 1, this will cause a C with the error message, +when set to 2, it will C. + Currently errors as described below are available. I've tried to make the error itself explanatory enough, but more descriptions will be added. For most of these errors, the first three capitals describe the error category: @@ -1581,9 +1650,9 @@ exhausted before the quote is found, that field is not terminated. =head1 SEE ALSO -L, L, L, L, -L, L, L, -L, and L. +L, L, L, L, L, +L, L, L, +and L. =head1 AUTHORS and MAINTAINERS diff --git a/CSV_XS.xs b/CSV_XS.xs index 5b45e97..626a25e 100644 --- a/CSV_XS.xs +++ b/CSV_XS.xs @@ -8,6 +8,7 @@ #include #include #define NEED_PL_parser +#define DPPP_PL_parser_NO_DUMMY #define NEED_sv_2pv_flags #define NEED_load_module #define NEED_newRV_noinc @@ -19,7 +20,6 @@ # endif #define MAINT_DEBUG 0 -#define ALLOW_ALLOW 1 #define BUFFER_SIZE 1024 @@ -46,7 +46,9 @@ #define CACHE_ID_eol_is_cr 20 #define CACHE_ID_has_types 21 #define CACHE_ID_verbatim 22 -#define CACHE_ID__is_bound 23 +#define CACHE_ID_empty_is_undef 23 +#define CACHE_ID_auto_diag 24 +#define CACHE_ID__is_bound 25 #define CSV_FLAGS_QUO 0x0001 #define CSV_FLAGS_BIN 0x0002 @@ -84,20 +86,20 @@ typedef struct { byte useIO; /* Also used to indicate EOF */ byte eol_is_cr; -#if ALLOW_ALLOW byte allow_loose_quotes; byte allow_loose_escapes; byte allow_double_quoted; byte allow_whitespace; byte blank_is_undef; + byte empty_is_undef; byte verbatim; + byte auto_diag; long is_bound; - byte reserved1; -#endif byte cache[CACHE_SIZE]; + SV * pself; HV * self; SV * bound; @@ -208,25 +210,37 @@ static SV *cx_SvDiag (pTHX_ int xse) #define SetDiag(csv,xse) cx_SetDiag (aTHX_ csv, xse) static SV *cx_SetDiag (pTHX_ csv_t *csv, int xse) { + dSP; SV *err = SvDiag (xse); if (err) - hv_store (csv->self, "_ERROR_DIAG", 11, err, 0); + (void)hv_store (csv->self, "_ERROR_DIAG", 11, err, 0); if (xse == 0) { - hv_store (csv->self, "_ERROR_POS", 10, newSViv (0), 0); - hv_store (csv->self, "_ERROR_INPUT", 12, newSVpvs (""), 0); + (void)hv_store (csv->self, "_ERROR_POS", 10, newSViv (0), 0); + (void)hv_store (csv->self, "_ERROR_INPUT", 12, newSVpvs (""), 0); + } + if (err && csv->pself && csv->auto_diag) { + ENTER; + SAVETMPS; + PUSHMARK (SP); + XPUSHs (csv->pself); + PUTBACK; + call_pv ("Text::CSV_XS::error_diag", G_VOID | G_DISCARD); + FREETMPS; + LEAVE; } return (err); } /* SetDiag */ -#define SetupCsv(csv,self) cx_SetupCsv (aTHX_ csv, self) -static void cx_SetupCsv (pTHX_ csv_t *csv, HV *self) +#define SetupCsv(csv,self,pself) cx_SetupCsv (aTHX_ csv, self, pself) +static void cx_SetupCsv (pTHX_ csv_t *csv, HV *self, SV *pself) { SV **svp; STRLEN len; char *ptr; csv->self = self; + csv->pself = pself; if ((svp = hv_fetchs (self, "_CACHE", FALSE)) && *svp) { memcpy (csv->cache, SvPV (*svp, len), CACHE_SIZE); @@ -238,15 +252,15 @@ static void cx_SetupCsv (pTHX_ csv_t *csv, HV *self) csv->keep_meta_info = csv->cache[CACHE_ID_keep_meta_info ]; csv->always_quote = csv->cache[CACHE_ID_always_quote ]; + csv->auto_diag = csv->cache[CACHE_ID_auto_diag ]; -#if ALLOW_ALLOW csv->allow_loose_quotes = csv->cache[CACHE_ID_allow_loose_quotes]; csv->allow_loose_escapes = csv->cache[CACHE_ID_allow_loose_escapes]; csv->allow_double_quoted = csv->cache[CACHE_ID_allow_double_quoted]; csv->allow_whitespace = csv->cache[CACHE_ID_allow_whitespace ]; csv->blank_is_undef = csv->cache[CACHE_ID_blank_is_undef ]; + csv->empty_is_undef = csv->cache[CACHE_ID_empty_is_undef ]; csv->verbatim = csv->cache[CACHE_ID_verbatim ]; -#endif csv->eol_is_cr = csv->cache[CACHE_ID_eol_is_cr ]; csv->eol_len = csv->cache[CACHE_ID_eol_len ]; if (csv->eol_len < 8) @@ -326,14 +340,14 @@ static void cx_SetupCsv (pTHX_ csv_t *csv, HV *self) csv->binary = bool_opt ("binary"); csv->keep_meta_info = bool_opt ("keep_meta_info"); csv->always_quote = bool_opt ("always_quote"); -#if ALLOW_ALLOW csv->allow_loose_quotes = bool_opt ("allow_loose_quotes"); csv->allow_loose_escapes = bool_opt ("allow_loose_escapes"); csv->allow_double_quoted = bool_opt ("allow_double_quoted"); csv->allow_whitespace = bool_opt ("allow_whitespace"); csv->blank_is_undef = bool_opt ("blank_is_undef"); + csv->empty_is_undef = bool_opt ("empty_is_undef"); csv->verbatim = bool_opt ("verbatim"); -#endif + csv->auto_diag = bool_opt ("auto_diag"); csv->cache[CACHE_ID_quote_char] = csv->quote_char; csv->cache[CACHE_ID_escape_char] = csv->escape_char; @@ -343,14 +357,14 @@ static void cx_SetupCsv (pTHX_ csv_t *csv, HV *self) csv->cache[CACHE_ID_keep_meta_info] = csv->keep_meta_info; csv->cache[CACHE_ID_always_quote] = csv->always_quote; -#if ALLOW_ALLOW csv->cache[CACHE_ID_allow_loose_quotes] = csv->allow_loose_quotes; csv->cache[CACHE_ID_allow_loose_escapes] = csv->allow_loose_escapes; csv->cache[CACHE_ID_allow_double_quoted] = csv->allow_double_quoted; csv->cache[CACHE_ID_allow_whitespace] = csv->allow_whitespace; csv->cache[CACHE_ID_blank_is_undef] = csv->blank_is_undef; + csv->cache[CACHE_ID_empty_is_undef] = csv->empty_is_undef; csv->cache[CACHE_ID_verbatim] = csv->verbatim; -#endif + csv->cache[CACHE_ID_auto_diag] = csv->auto_diag; csv->cache[CACHE_ID_eol_is_cr] = csv->eol_is_cr; csv->cache[CACHE_ID_eol_len] = csv->eol_len; if (csv->eol_len > 0 && csv->eol_len < 8 && csv->eol) @@ -362,7 +376,7 @@ static void cx_SetupCsv (pTHX_ csv_t *csv, HV *self) csv->cache[CACHE_ID__is_bound + 3] = (csv->is_bound & 0x000000FF); if ((csv->tmp = newSVpvn ((char *)csv->cache, CACHE_SIZE))) - hv_store (self, "_CACHE", 6, csv->tmp, 0); + (void)hv_store (self, "_CACHE", 6, csv->tmp, 0); } if (csv->is_bound) { @@ -517,7 +531,7 @@ static int cx_Combine (pTHX_ csv_t *csv, SV *dst, AV *fields) #define ParseError(csv,xse,pos) cx_ParseError (aTHX_ csv, xse, pos) static void cx_ParseError (pTHX_ csv_t *csv, int xse, int pos) { - hv_store (csv->self, "_ERROR_POS", 10, newSViv (pos), 0); + (void)hv_store (csv->self, "_ERROR_POS", 10, newSViv (pos), 0); if (csv->tmp) { if (hv_store (csv->self, "_ERROR_INPUT", 12, csv->tmp, 0)) SvREFCNT_inc (csv->tmp); @@ -549,7 +563,6 @@ static int cx_CsvGet (pTHX_ csv_t *csv, SV *src) if (csv->tmp && SvOK (csv->tmp)) { csv->bptr = SvPV (csv->tmp, csv->size); csv->used = 0; -#if ALLOW_ALLOW if (csv->verbatim && csv->eol_len && csv->size >= csv->eol_len) { int i, match = 1; for (i = 1; i <= (int)csv->eol_len; i++) { @@ -564,7 +577,6 @@ static int cx_CsvGet (pTHX_ csv_t *csv, SV *src) SvCUR_set (csv->tmp, csv->size); } } -#endif if (SvUTF8 (csv->tmp)) csv->utf8 = 1; if (csv->size) return ((byte)csv->bptr[csv->used++]); @@ -598,10 +610,9 @@ static int cx_CsvGet (pTHX_ csv_t *csv, SV *src) ? ((byte)csv->bptr[(csv)->used++]) \ : CsvGet (csv, src))) -#if ALLOW_ALLOW #define AV_PUSH { \ *SvEND (sv) = (char)0; \ - if (!(f & CSV_FLAGS_QUO) && SvCUR (sv) == 0 && csv->blank_is_undef) {\ + if (SvCUR (sv) == 0 && (csv->empty_is_undef || (!(f & CSV_FLAGS_QUO) && csv->blank_is_undef))) {\ sv_setpvn (sv, NULL, 0); \ unless (csv->is_bound) av_push (fields, sv); \ } \ @@ -617,16 +628,6 @@ static int cx_CsvGet (pTHX_ csv_t *csv, SV *src) av_push (fflags, newSViv (f)); \ waitingForField = 1; \ } -#else -#define AV_PUSH { \ - *SvEND (sv) = (char)0; \ - unless (csv->is_bound) av_push (fields, sv); \ - sv = NULL; \ - if (csv->keep_meta_info) \ - av_push (fflags, newSViv (f)); \ - waitingForField = 1; \ - } -#endif #define strip_trail_whitespace(sv) cx_strip_trail_whitespace (aTHX_ sv) static void cx_strip_trail_whitespace (pTHX_ SV *sv) @@ -718,19 +719,15 @@ restart: waitingForField ? 1 : 0, sv ? 1 : 0, f, spl, c); #endif if (waitingForField) { -#if ALLOW_ALLOW - if (csv->blank_is_undef) + if (csv->blank_is_undef || csv->empty_is_undef) sv_setpvn (sv, NULL, 0); else -#endif sv_setpvn (sv, "", 0); unless (csv->is_bound) av_push (fields, sv); sv = NULL; -#if ALLOW_ALLOW if (csv->keep_meta_info) av_push (fflags, newSViv (f)); -#endif } else if (f & CSV_FLAGS_QUO) @@ -746,18 +743,14 @@ restart: waitingForField ? 1 : 0, sv ? 1 : 0, f, spl); #endif if (waitingForField) { -#if ALLOW_ALLOW - if (csv->blank_is_undef) + if (csv->blank_is_undef || csv->empty_is_undef) sv_setpvn (sv, NULL, 0); else -#endif sv_setpvn (sv, "", 0); unless (csv->is_bound) av_push (fields, sv); -#if ALLOW_ALLOW if (csv->keep_meta_info) av_push (fflags, newSViv (f)); -#endif return TRUE; } @@ -768,7 +761,6 @@ restart: CSV_PUT_SV (c); } -#if ALLOW_ALLOW else if (csv->verbatim) { f |= CSV_FLAGS_BIN; @@ -777,18 +769,13 @@ restart: CSV_PUT_SV (c); } -#endif else { AV_PUSH; return TRUE; } } /* CH_NL */ else - if (c == CH_CR -#if ALLOW_ALLOW - && !(csv->verbatim) -#endif - ) { + if (c == CH_CR && !(csv->verbatim)) { #if MAINT_DEBUG > 1 fprintf (stderr, "# %d/%d/%02x pos %d = CR\n", waitingForField ? 1 : 0, sv ? 1 : 0, f, spl); @@ -862,12 +849,10 @@ restart: /* Field is terminated */ c2 = CSV_GET; -#if ALLOW_ALLOW if (csv->allow_whitespace) { while (is_whitespace (c2)) c2 = CSV_GET; } -#endif if (c2 == csv->sep_char) { AV_PUSH; @@ -914,12 +899,10 @@ restart: c2 = CSV_GET; -#if ALLOW_ALLOW if (csv->allow_whitespace) { while (is_whitespace (c2)) c2 = CSV_GET; } -#endif if (c2 == EOF) { AV_PUSH; @@ -958,13 +941,11 @@ restart: } } -#if ALLOW_ALLOW if (csv->allow_loose_escapes && csv->escape_char == csv->quote_char) { CSV_PUT_SV (c); c = c2; goto restart; } -#endif csv->used--; ERROR_INSIDE_QUOTES (2023); @@ -972,13 +953,11 @@ restart: } else /* !waitingForField, !InsideQuotes */ -#if ALLOW_ALLOW if (csv->allow_loose_quotes) { /* 1,foo "boo" d'uh,1 */ f |= CSV_FLAGS_EIF; CSV_PUT_SV (c); } else -#endif ERROR_INSIDE_FIELD (2034); } /* QUO char */ else @@ -1003,11 +982,7 @@ restart: CSV_PUT_SV (0) else if ( c2 == csv->quote_char || c2 == csv->sep_char || - c2 == csv->escape_char -#if ALLOW_ALLOW - || csv->allow_loose_escapes -#endif - ) + c2 == csv->escape_char || csv->allow_loose_escapes) CSV_PUT_SV (c2) else { csv->used--; @@ -1034,7 +1009,6 @@ restart: waitingForField ? 1 : 0, sv ? 1 : 0, f, spl, c, c_ungetc); #endif if (waitingForField) { -#if ALLOW_ALLOW if (csv->allow_whitespace && is_whitespace (c)) { do { c = CSV_GET; @@ -1043,7 +1017,6 @@ restart: break; goto restart; } -#endif waitingForField = 0; goto restart; } @@ -1067,27 +1040,21 @@ restart: } /* continue */ -#if ALLOW_ALLOW if (csv->verbatim && csv->useIO && csv->used == csv->size) break; -#endif } if (waitingForField) { if (seenSomething) { unless (sv) NewField; -#if ALLOW_ALLOW - if (csv->blank_is_undef) + if (csv->blank_is_undef || csv->empty_is_undef) sv_setpvn (sv, NULL, 0); else -#endif sv_setpvn (sv, "", 0); unless (csv->is_bound) av_push (fields, sv); -#if ALLOW_ALLOW if (csv->keep_meta_info) av_push (fflags, newSViv (f)); -#endif return TRUE; } if (csv->useIO) { @@ -1105,13 +1072,13 @@ restart: return TRUE; } /* Parse */ -#define xsParse(hv,av,avf,src,useIO) cx_xsParse (aTHX_ hv, av, avf, src, useIO) -static int cx_xsParse (pTHX_ HV *hv, AV *av, AV *avf, SV *src, bool useIO) +#define xsParse(self,hv,av,avf,src,useIO) cx_xsParse (aTHX_ self, hv, av, avf, src, useIO) +static int cx_xsParse (pTHX_ SV *self, HV *hv, AV *av, AV *avf, SV *src, bool useIO) { csv_t csv; int result; - SetupCsv (&csv, hv); + SetupCsv (&csv, hv, self); if ((csv.useIO = useIO)) { csv.tmp = NULL; csv.size = 0; @@ -1121,24 +1088,22 @@ static int cx_xsParse (pTHX_ HV *hv, AV *av, AV *avf, SV *src, bool useIO) csv.utf8 = SvUTF8 (src); csv.bptr = SvPV (src, csv.size); } - hv_delete (hv, "_ERROR_INPUT", 12, G_DISCARD); + (void)hv_delete (hv, "_ERROR_INPUT", 12, G_DISCARD); result = Parse (&csv, src, av, avf); -#ifdef ALLOW_ALLOW if (csv.useIO & useIO_EOF) - hv_store (hv, "_EOF", 4, &PL_sv_yes, 0); + (void)hv_store (hv, "_EOF", 4, &PL_sv_yes, 0); else - hv_store (hv, "_EOF", 4, &PL_sv_no, 0); + (void)hv_store (hv, "_EOF", 4, &PL_sv_no, 0); if (csv.useIO) { if (csv.keep_meta_info) { - hv_delete (hv, "_FFLAGS", 7, G_DISCARD); - hv_store (hv, "_FFLAGS", 7, newRV_noinc ((SV *)avf), 0); + (void)hv_delete (hv, "_FFLAGS", 7, G_DISCARD); + (void)hv_store (hv, "_FFLAGS", 7, newRV_noinc ((SV *)avf), 0); } else { av_undef (avf); sv_free ((SV *)avf); } } -#endif if (result && csv.types) { I32 i; STRLEN len = av_len (av); @@ -1164,8 +1129,8 @@ static int cx_xsParse (pTHX_ HV *hv, AV *av, AV *avf, SV *src, bool useIO) return result; } /* xsParse */ -#define xsCombine(hv,av,io,useIO) cx_xsCombine (aTHX_ hv, av, io, useIO) -static int cx_xsCombine (pTHX_ HV *hv, AV *av, SV *io, bool useIO) +#define xsCombine(self,hv,av,io,useIO) cx_xsCombine (aTHX_ self, hv, av, io, useIO) +static int cx_xsCombine (pTHX_ SV *self, HV *hv, AV *av, SV *io, bool useIO) { csv_t csv; int result; @@ -1173,7 +1138,7 @@ static int cx_xsCombine (pTHX_ HV *hv, AV *av, SV *io, bool useIO) SV *ors = PL_ors_sv; #endif - SetupCsv (&csv, hv); + SetupCsv (&csv, hv, self); csv.useIO = useIO; #if (PERL_BCDVERSION >= 0x5008000) if (csv.eol && *csv.eol) @@ -1205,14 +1170,13 @@ SetDiag (self, xse, ...) if (SvOK (self) && SvROK (self)) { CSV_XS_SELF; - SetupCsv (&csv, hv); + SetupCsv (&csv, hv, self); ST (0) = SetDiag (&csv, xse); } else ST (0) = SvDiag (xse); if (xse && items > 1 && SvPOK (ST (2))) { - STRLEN len; sv_setpvn (ST (0), SvPVX (ST (2)), SvCUR (ST (2))); SvIOK_on (ST (0)); } @@ -1233,7 +1197,7 @@ Combine (self, dst, fields, useIO) CSV_XS_SELF; av = (AV *)SvRV (fields); - ST (0) = xsCombine (hv, av, dst, useIO) ? &PL_sv_yes : &PL_sv_undef; + ST (0) = xsCombine (self, hv, av, dst, useIO) ? &PL_sv_yes : &PL_sv_undef; XSRETURN (1); /* XS Combine */ @@ -1251,11 +1215,9 @@ Parse (self, src, fields, fflags) CSV_XS_SELF; av = (AV*)SvRV (fields); -#if ALLOW_ALLOW avf = (AV*)SvRV (fflags); -#endif - ST (0) = xsParse (hv, av, avf, src, 0) ? &PL_sv_yes : &PL_sv_no; + ST (0) = xsParse (self, hv, av, avf, src, 0) ? &PL_sv_yes : &PL_sv_no; XSRETURN (1); /* XS Parse */ @@ -1275,7 +1237,7 @@ print (self, io, fields) av = (AV*)SvRV (fields); - ST (0) = xsCombine (hv, av, io, 1) ? &PL_sv_yes : &PL_sv_no; + ST (0) = xsCombine (self, hv, av, io, 1) ? &PL_sv_yes : &PL_sv_no; XSRETURN (1); /* XS print */ @@ -1292,7 +1254,7 @@ getline (self, io) CSV_XS_SELF; av = newAV (); avf = newAV (); - ST (0) = xsParse (hv, av, avf, io, 1) + ST (0) = xsParse (self, hv, av, avf, io, 1) ? sv_2mortal (newRV_noinc ((SV *)av)) : &PL_sv_undef; XSRETURN (1); diff --git a/ChangeLog b/ChangeLog index 798e1ac..669a2ca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,453 +1,469 @@ +2009-08-08 0.67 - H.Merijn Brand + + * Fix empty_diag typo for attribute handler + * Fix AUTOMATED_TESTING erroneous skip + +2009-08-07 0.66 - H.Merijn Brand + + * Reordered examples in doc to show best method first + * Documentation grammatical fix (John P. Linderman, RT#46411) + * Fail if first arg to new () is not a hash ref + * Implement empty_is_undef on request of Evan Carroll + * Typo in documentation (Herwin Weststrate, RT#47613) + * error_diag () uses warn () in void context instead of STDERR + * Add auto_diag attribute (still under construction) + * FIX: reset attributes (after they have been set) with accessor + 2009-05-14 0.65 - H.Merijn Brand - * Initial known errors can now be checked on number (1002) - * More tests for illegal combinations - * Added -u option to examples/csv-check to validate utf-8 encoding - * Correct documentation for error_diag () return value in case of - contructor failure (Slaven, RT#46076) - * All error_diag () returns should now be dual-var (both numeric - and string context valid) + * Initial known errors can now be checked on number (1002) + * More tests for illegal combinations + * Added -u option to examples/csv-check to validate utf-8 encoding + * Correct documentation for error_diag () return value in case of + constructor failure (Slaven, RT#46076) + * All error_diag () returns should now be dual-var (both numeric + and string context valid) + * Remove (3) from L<..> links (Slaven, RT#46078) 2009-04-03 0.64 - H.Merijn Brand - * Skip perlio tests for perl older than 5.8, as perlio - was experimental in 5.6 - * Up Devel::PPPort to 3.17 - * Fix initialisation of eol => undef (could cause core dump) - * Added configure_require to META.yml + * Skip perlio tests for perl older than 5.8, as perlio + was experimental in 5.6 + * Up Devel::PPPort to 3.17 + * Fix initialization of eol => undef (could cause core dump) + * Added configure_require to META.yml 2009-03-20 0.63 - H.Merijn Brand - * Fixed allow_whitespace with sep_char = TAB (RT#44402) + * Fixed allow_whitespace with sep_char = TAB (RT#44402) 2009-03-13 0.62 - H.Merijn Brand - * Prevent warnings in older perls (without utf8) - * All known errors are covered and/or documented. TODO dropped - * Unicode TODO dropped. All covered, or use Text::CSV::Encoded - * Documented the examples + * Prevent warnings in older perls (without utf8) + * All known errors are covered and/or documented. TODO dropped + * Unicode TODO dropped. All covered, or use Text::CSV::Encoded + * Documented the examples 2009-03-08 0.61 - H.Merijn Brand - * valgrind found a possible uninitialized value - * Restriction in print () was only for really old perls - * Fix for bind_columns () initialisation (vincent, RT#43927) + * valgrind found a possible uninitialized value + * Restriction in print () was only for really old perls + * Fix for bind_columns () initialization (vincent, RT#43927) 2009-01-27 0.60 - H.Merijn Brand - * Optimize for threaded perls. (Goro Fuji, RT#42517) - Non-threaded perls won't notice + * Optimize for threaded perls. (Goro Fuji, RT#42517) + Non-threaded perls won't notice 2009-01-23 0.59 - H.Merijn Brand - * Wrong e-mail in META.yml - * Missing $IO argument in bind_columns example (docs only) - * Upped Copyright notices to 2009 - * Added warning for parse () (RT#42261) - * Small optimisations (Goro Fuji, RT#42517) - * ppport.h updated to 3.15 - * Added git clone command to README - * ppport.h updated to 3.16-pre - * Optimize getline/print method calls (Goro Fuji, RT#42517) - * Decode *_char attributes for perl 5.8.2 and up + * Wrong e-mail in META.yml + * Missing $IO argument in bind_columns example (docs only) + * Upped Copyright notices to 2009 + * Added warning for parse () (RT#42261) + * Small optimizations (Goro Fuji, RT#42517) + * ppport.h updated to 3.15 + * Added git clone command to README + * ppport.h updated to 3.16-pre + * Optimize getline/print method calls (Goro Fuji, RT#42517) + * Decode *_char attributes for perl 5.8.2 and up 2008-10-30 0.58 - H.Merijn Brand - * Small typo in test message (RT#40410, JPL) - * Parse error test on "\0 (RT#40507) - * Fixed allow_loose_escapes bug disclosed by RT#40507 + * Small typo in test message (RT#40410, JPL) + * Parse error test on "\0 (RT#40507) + * Fixed allow_loose_escapes bug disclosed by RT#40507 2008-10-21 0.57 - H.Merijn Brand - * Don't bootstrap twice. Don't know how/when it came in there + * Don't bootstrap twice. Don't know how/when it came in there 2008-10-21 0.56 - H.Merijn Brand - * Update to ppport.h 3.14_01 - * Updated docs (Unicode, TODO, Release Plan) - * As Text::CSV::Encoded is about to be released, refer to it - in the documentation - * Default for eol is "", undef now treated as "" - * Don't print $\ twice (eol prevails over $\ in ->print ()) - Fix only works in perl5.8 and up - * Undef treated as 0 for boolean attributes - * Trailing whitespace in pod removed - * Sync up doc with latest Text::CSV::Encoded - * YAML declared 1.4 (META.yml) instead of 1.1 (YAML) + * Update to ppport.h 3.14_01 + * Updated docs (Unicode, TODO, Release Plan) + * As Text::CSV::Encoded is about to be released, refer to it + in the documentation + * Default for eol is "", undef now treated as "" + * Don't print $\ twice (eol prevails over $\ in ->print ()) + Fix only works in perl5.8 and up + * Undef treated as 0 for boolean attributes + * Trailing whitespace in pod removed + * Sync up doc with latest Text::CSV::Encoded + * YAML declared 1.4 (META.yml) instead of 1.1 (YAML) 2008-10-15 0.55 - H.Merijn Brand - * Improve documentation on eol - * Unicode on perl-5.8.[0-2] sucks. Don't use it! - * Test error codes in expected IO failures - * Allow SetDiag to be used as class method - * Document the MS/Excel separation character - * Hint that eof is not an error per se (RT#40047) + * Improve documentation on eol + * Unicode on perl-5.8.[0-2] sucks. Don't use it! + * Test error codes in expected IO failures + * Allow SetDiag to be used as class method + * Document the MS/Excel separation character + * Hint that eof is not an error per se (RT#40047) 2008-09-04 0.54 - H.Merijn Brand - * IO failure in print () was not propagated (ilmari, RT#38960) + * IO failure in print () was not propagated (ilmari, RT#38960) 2008-09-01 0.53 - H.Merijn Brand - * SvUPGRADE is a safer choice than sv_upgrade (Lubomir Rintel, RT#38890) - * bring docs in sync with reality for msg 2023 - * Default eol for print is $\ - * examples/csv-check should default to CSV , not to ; - * Tests for SetDiag (0) - * Tests for error 2030 - * Code cleanup (Devel::Cover++) + * SvUPGRADE is a safer choice than sv_upgrade (Lubomir Rintel, RT#38890) + * bring docs in sync with reality for msg 2023 + * Default eol for print is $\ + * examples/csv-check should default to CSV , not to ; + * Tests for SetDiag (0) + * Tests for error 2030 + * Code cleanup (Devel::Cover++) 2008-06-28 0.52 - H.Merijn Brand - * Using undef for hash keys is a bad plan - * Fix, tests, and documentation for column_names () + * Using undef for hash keys is a bad plan + * Fix, tests, and documentation for column_names () 2008-06-17 0.51 - H.Merijn Brand - * Allow UTF8 even without binary => 1 - * Fixed a few pod typo's - * Lifted the max of 255 for bind_columns + * Allow UTF8 even without binary => 1 + * Fixed a few pod typo's + * Lifted the max of 255 for bind_columns 2008-06-04 0.50 - H.Merijn Brand - * Skip a few tests in automated testing, as they confuse - reports. This is important for the automated sites that - mark modules as fail if it is not an obvious full PASS - * 0.46 caused the last still open RT bug to be closed! - * Tested on 5.11.0, 5.10.0, 5.8.8, 5.6.2, and 5.005_04, - Strawberry and Cygwin + * Skip a few tests in automated testing, as they confuse + reports. This is important for the automated sites that + mark modules as fail if it is not an obvious full PASS + * 0.46 caused the last still open RT bug to be closed! + * Tested on 5.11.0, 5.10.0, 5.8.8, 5.6.2, and 5.005_04, + Strawberry and Cygwin 2008-06-04 0.46 - H.Merijn Brand - * In examples add die on failed close calls - * Use Test::MinimumVersion (not distributed) - * Added option -F to examples/csv2xls - * More source code cleanup - * Nailed the UTF8 issues for parsing - * Nailed the UTF8 issues for combining + * In examples add die on failed close calls + * Use Test::MinimumVersion (not distributed) + * Added option -F to examples/csv2xls + * More source code cleanup + * Nailed the UTF8 issues for parsing + * Nailed the UTF8 issues for combining 2008-04-23 0.45 - H.Merijn Brand - * Forgot to pack examples/parser-xs.pl + * Forgot to pack examples/parser-xs.pl 2008-04-23 0.44 - H.Merijn Brand - * Fixed the error position returned as third arg in error_diag () - * Made examples/csv-check use this even more vebose - * Removed double-double quote from TODO - * Added examples/parse-xs.pl (attempt to fix bad CSV) + * Fixed the error position returned as third arg in error_diag () + * Made examples/csv-check use this even more vebose + * Removed double-double quote from TODO + * Added examples/parse-xs.pl (attempt to fix bad CSV) 2008-04-21 0.43 - H.Merijn Brand - * parse errors try to remember failing position - * used valgrind to test for leaks (devel-only) - * used Test::Valgrind as alternative leak check (devel-only) - * improve documentation for error 2023 - * nailed the loose quotes in quoted fields + * parse errors try to remember failing position + * used valgrind to test for leaks (devel-only) + * used Test::Valgrind as alternative leak check (devel-only) + * improve documentation for error 2023 + * nailed the loose quotes in quoted fields 2008-04-16 0.42 - H.Merijn Brand - * Generate META.yml myself. I won't use Build.PL - * Array-refs now accept scalars with magic: - $csv->print (*STDOUT, $sth->{NAME_lc}); - * More/better examples - * Added t/76_magic.t + * Generate META.yml myself. I won't use Build.PL + * Array-refs now accept scalars with magic: + $csv->print (*STDOUT, $sth->{NAME_lc}); + * More/better examples + * Added t/76_magic.t 2008-04-11 0.41 - H.Merijn Brand - * error_diag () subclassable - * typo in bind_columns () docs - * examples/csv2xls now uses getline () - * better test for getline in t/75_hashref.t (makamata) - * document return value of getline () with bind_columns () - * add perl version prereq to META.yml + * error_diag () subclassable + * typo in bind_columns () docs + * examples/csv2xls now uses getline () + * better test for getline in t/75_hashref.t (makamata) + * document return value of getline () with bind_columns () + * add perl version prereq to META.yml 2008-04-07 0.40 - H.Merijn Brand - * Implemented getline_hr () and column_names () RT 34474 - (suggestions accepted from Mark Stosberg) - * Corrected misspelled variable names in XS - * Functions are now =head2 type doc entries (Mark Stosberg) - * Make SetDiag() available to the perl level, so errors can - be centralized and consistent - * Integrate the non-XS errors into XS - * Add t/75_hashref.t - * Testcase for error 2023 (Michael P Randall) - * Completely refactored the XS part of parse/getline, which - is now up to 6% faster. YMMV - * Completed bind_columns. On straight fetches now up to three - times as fast as normal fetches (both using getline ()) + * Implemented getline_hr () and column_names () (RT#34474) + (suggestions accepted from Mark Stosberg) + * Corrected misspelled variable names in XS + * Functions are now =head2 type doc entries (Mark Stosberg) + * Make SetDiag () available to the perl level, so errors can + be centralized and consistent + * Integrate the non-XS errors into XS + * Add t/75_hashref.t + * Testcase for error 2023 (Michael P Randall) + * Completely refactored the XS part of parse/getline, which + is now up to 6% faster. YMMV + * Completed bind_columns. On straight fetches now up to three + times as fast as normal fetches (both using getline ()) 2008-03-11 0.37 - H.Merijn Brand - * Copied GIT repo to public mirror - * Fix leak / make meta info available to getline () + tests + * Copied GIT repo to public mirror + * Fix leak / make meta info available to getline () + tests 2008-03-06 0.36 - H.Merijn Brand - * Updated ppport.h - * auto-load IO::Handle when needed - * Tested with all available perl builds, including a fresh - threaded 5.11 (blead) + * Updated ppport.h + * auto-load IO::Handle when needed + * Tested with all available perl builds, including a fresh + threaded 5.11 (blead) 2008-03-01 0.35 (Valloire) - H.Merijn Brand - * use warnings/$^W = 1 - * Tested on 5.10.0, 5.8.8, 5.6.2, and 5.005_04, Strawberry and Cygwin - * Diagnostics for failed new () - * New 'blank_is_undef' option - * Updated docs - * Extended the DIAGNOSTICS a bit - * Updated TODO - * Fixed allow_whitespace issue, revealed by blank_is_undef - * Re-enabled some tests - * Fixed parse error that passed for q{1, "bar",2} with escape_char + - * Reversed an erroneous test result in the funny combo section - * Extended diagnostics tests - * Extended XS coverage - * Removed error 2033 + * use warnings/$^W = 1 + * Tested on 5.10.0, 5.8.8, 5.6.2, and 5.005_04, Strawberry and Cygwin + * Diagnostics for failed new () + * New 'blank_is_undef' option + * Updated docs + * Extended the DIAGNOSTICS a bit + * Updated TODO + * Fixed allow_whitespace issue, revealed by blank_is_undef + * Re-enabled some tests + * Fixed parse error that passed for q{1, "bar",2} with escape_char + + * Reversed an erroneous test result in the funny combo section + * Extended diagnostics tests + * Extended XS coverage + * Removed error 2033 2008-01-04 0.34 - H.Merijn Brand - * No change, but 0.33 was shipped with an old META.yml + * No change, but 0.33 was shipped with an old META.yml 2008-01-02 0.33 - H.Merijn Brand - * Text-CSV_XS now under git - * Upped copyright to 2008 - * Added all prereq's to Makefile.PL - * Tested under perl 5.10 + * Text-CSV_XS now under git + * Upped copyright to 2008 + * Added all prereq's to Makefile.PL + * Tested under perl 5.10 2007-10-24 0.32 - H.Merijn Brand - * Added $csv->error_diag () to SYNOPSIS - * Added need for diag when new () fails to TODO - * Fixed a sneaked-in defined or in examples/csv2xls - * Plugged a 32byte memory leak in the cache code (valgrind++) - * Some perlcritic level1 changes + * Added $csv->error_diag () to SYNOPSIS + * Added need for diag when new () fails to TODO + * Fixed a sneaked-in defined or in examples/csv2xls + * Plugged a 32byte memory leak in the cache code (valgrind++) + * Some perlcritic level1 changes 2007-07-23 0.31 - H.Merijn Brand - * Removed prototypes in examples/csv2xls - * Improved usage for examples/csv2xls (GetOpt::Long now does --help/-?) - * Extended examples/csv2xls to deal with Unicode (-u) - * Serious bug in Text::CSV_XS::NV () type setting, causing the - resulting field to be truncated to IV + * Removed prototypes in examples/csv2xls + * Improved usage for examples/csv2xls (GetOpt::Long now does --help/-?) + * Extended examples/csv2xls to deal with Unicode (-u) + * Serious bug in Text::CSV_XS::NV () type setting, causing the + resulting field to be truncated to IV 2007-06-21 0.30 - H.Merijn Brand - * ,\rx, is definitely an error without binary (used to HANG!) - * Fixed bug in attribute caching for undefined eol - * Cleaned up some code after -W*** warnings - * Added verbatim. - * More test to cover the really dark corners and edge cases - * Even more typo fixes in the docs - * Added error_diag () - * Added t/80_diag.t - Will not be mirrored by Text::CSV_PP - * Added DIAGNOSTICS section to pod - Will grow - * Small pod niot (abeltje) - * Doc fix in TODO (Miller Hall) + * ,\rx, is definitely an error without binary (used to HANG!) + * Fixed bug in attribute caching for undefined eol + * Cleaned up some code after -W*** warnings + * Added verbatim. + * More test to cover the really dark corners and edge cases + * Even more typo fixes in the docs + * Added error_diag () + * Added t/80_diag.t - Will not be mirrored by Text::CSV_PP + * Added DIAGNOSTICS section to pod - Will grow + * Small pod niot (abeltje) + * Doc fix in TODO (Miller Hall) 2007-06-08 0.29 - H.Merijn Brand - * Removed an unused 'use Data::Dumper' - * Added $csv->eof () RT 27424 - * Two typo's in the doc's (Amsterdam.pm) - * Modified examples/speed.pl to better show the diffs between versions - * Cache attribute settings and regain speed of 0.23! and beyond - Relative overall speeds (YMMV, use examples/speed.pl to check), - the 1.0x versions are from Text::CSV_PP. - - 0.23 0.25 0.26 0.27 0.28 0.29 1.00 1.02 1.05 - ==== ==== ==== ==== ==== ==== ==== ==== ==== - combine 1 62 61 61 60 58 100 14 14 14 - combine 10 41 41 41 42 42 100 6 6 6 - combine 100 35 35 36 36 36 100 5 5 5 - parse 1 100 92 87 90 81 96 19 19 17 - parse 10 95 100 86 97 94 94 15 16 14 - parse 100 90 95 84 94 92 100 16 16 14 - print io 93 89 91 91 95 100 0 0 6 - getline io 90 92 84 87 89 100 0 0 13 - ---- ---- ---- ---- ---- ---- ---- ---- ---- - average 75 75 71 74 73 98 9 9 11 - - * Removed prototypes - * Added a SPECIFICATION section to the pod - * Safe caching of eol, and a warning in the docs - * Rewrote t/20_file.t do do actual file IO instead of IO_Scalar fake - * Small optimization for parse (juerd) - * Added make target test_speed - * Merged the items from CAVEAT to SPECIFICATION - * Updated the TODO and Release Plan sections - * Speed up internals by using references instead of copies (juerd) - * Reworked error_input, which also had an undetected internal error - * Added IO tests for lexical IO handles and perlio IO to/from scalars + * Removed an unused 'use Data::Dumper' + * Added $csv->eof () (RT#27424) + * Two typo's in the doc's (Amsterdam.pm) + * Modified examples/speed.pl to better show the diffs between versions + * Cache attribute settings and regain speed of 0.23! and beyond + Relative overall speeds (YMMV, use examples/speed.pl to check), + the 1.0x versions are from Text::CSV_PP. + + 0.23 0.25 0.26 0.27 0.28 0.29 1.00 1.02 1.05 + ==== ==== ==== ==== ==== ==== ==== ==== ==== + combine 1 62 61 61 60 58 100 14 14 14 + combine 10 41 41 41 42 42 100 6 6 6 + combine 100 35 35 36 36 36 100 5 5 5 + parse 1 100 92 87 90 81 96 19 19 17 + parse 10 95 100 86 97 94 94 15 16 14 + parse 100 90 95 84 94 92 100 16 16 14 + print io 93 89 91 91 95 100 0 0 6 + getline io 90 92 84 87 89 100 0 0 13 + ---- ---- ---- ---- ---- ---- ---- ---- ---- + average 75 75 71 74 73 98 9 9 11 + + * Removed prototypes + * Added a SPECIFICATION section to the pod + * Safe caching of eol, and a warning in the docs + * Rewrote t/20_file.t do do actual file IO instead of IO_Scalar fake + * Small optimization for parse (juerd) + * Added make target test_speed + * Merged the items from CAVEAT to SPECIFICATION + * Updated the TODO and Release Plan sections + * Speed up internals by using references instead of copies (juerd) + * Reworked error_input, which also had an undetected internal error + * Added IO tests for lexical IO handles and perlio IO to/from scalars 2007-06-03 0.28 - H.Merijn Brand - * IMPORTANT CHANGE: new () returns undef if it gets unsupported - attributes. Until now, new ({ esc_char => "\\" }) was just - silently ignored. Rejecting it and failing is better than - continuing with false assumptions. - * Added allow_loose_quotes (see doc) - * Added t/65_allow.t - * Added allow_loose_escapes (see doc) RT 15076 - * More code cleanup in XS - * Added allow_whitespace (see doc) + * IMPORTANT CHANGE: new () returns undef if it gets unsupported + attributes. Until now, new ({ esc_char => "\\" }) was just + silently ignored. Rejecting it and failing is better than + continuing with false assumptions. + * Added allow_loose_quotes (see doc) + * Added t/65_allow.t + * Added allow_loose_escapes (see doc) (RT#15076) + * More code cleanup in XS + * Added allow_whitespace (see doc) 2007-05-31 0.27 - H.Merijn Brand - * checked with perlcritic (still works under 5.00504) - so 3-arg open cannot be used (except in the docs) - * 3-arg open in docs too - * Added a lot to the TODO list - * Some more info on using escape character (jZed) - * Mention Text::CSV_PP in README - * Added t/45_eol.t, eol tests - * Added a section about embedded newlines in the pod - * Allow \r as eol ($/) for parsing - * More docs for eol - * More eol = \r fixes, tfrayner's test case added to t/45_eol.t + * checked with perlcritic (still works under 5.00504) + so 3-arg open cannot be used (except in the docs) + * 3-arg open in docs too + * Added a lot to the TODO list + * Some more info on using escape character (jZed) + * Mention Text::CSV_PP in README + * Added t/45_eol.t, eol tests + * Added a section about embedded newlines in the pod + * Allow \r as eol ($/) for parsing + * More docs for eol + * More eol = \r fixes, tfrayner's test case added to t/45_eol.t 2007-05-15 0.26 - H.Merijn Brand - * Add $csv->allow_undef (1) suggestion in TODO - Still have to find the best spot to document - the difference between empty string and undef - * Spell-checked the pod and fixed some typo's - * Added t/70_rt.t - - Regression for RT 24386: \t doesn't work (WFM) - - Regression and fix for RT 21530: getline () return at eof - This one still passes under perl 5.00504 - - Regression for RT 18703: Fails to use quote_char of '~' - * Added t/55_combi.t for most combinations of always_quote, - sep_char, quote_char, and escape_char - * Added docs about sep_char not allowed to be either quote_char - or escape_char - * Both combine () and parse () now return FALSE id sep_char is - equal to either quote_char or escape_char. Done in XS, as it - was a slowdown of 10% when done in perl. + * Add $csv->allow_undef (1) suggestion in TODO + Still have to find the best spot to document + the difference between empty string and undef + * Spell-checked the pod and fixed some typo's + * Added t/70_rt.t + - Regression for RT#24386: \t doesn't work (WFM) + - Regression and fix for RT#21530: getline () return at eof + This one still passes under perl 5.00504 + - Regression for RT#18703: Fails to use quote_char of '~' + * Added t/55_combi.t for most combinations of always_quote, + sep_char, quote_char, and escape_char + * Added docs about sep_char not allowed to be either quote_char + or escape_char + * Both combine () and parse () now return FALSE id sep_char is + equal to either quote_char or escape_char. Done in XS, as it + was a slowdown of 10% when done in perl. 2007-05-07 0.25 - H.Merijn Brand - * Merijn got the maintainership - - code reformat and code cleanup - - renamed internal (Encode, Decode) to (Combine, Parse) to - prevent misinterpretation with upcoming Unicode changes - and possible name clashes - - added pod check (and fixed pod) - - added pod coverage and small additions to the pod. - More to do in this area - - renamed test to fixate the sequence - - Added t/50_utf8.t - - tests now use Test::More - . Makefile.PL requires Test::More - - checked proclaimed version compatibility - . 5.9.x-64int works @31159 - . 5.8.x-64int-dor works @31162 - . 5.8.0-dor works - . 5.6.2 works - . 5.005.04 works - . 5.004.05 fails - - 5.005 is now prerequisite - - Added missing info in docs for new () - - Added meta_info () method and docs - - Added keep_meta_info in new () - - Added t/15_flags.t - - Added test_cover make target - - Added test for error_input () - - Added tests for fields () and meta_info () before parse () - - Added tests for ->types () as method - - Added tests for deleting types (coverage now over 99%) - - Added is_quoted (), is_binary () and tests - - Added COPYRIGHT section to pod - - Added the parse example from the pod to test.pl - - Added accessor methods for internals: quote_char () et all - - Added tests for the new accessor methods - - Added always_quote to the missing places in the doc and in new () - - Changed the tests to use the accessors instead of the hash keys - except for the ->{types} and ->{_types} - - Moved test.pl to examples/speed.pl + * Merijn got the maintainership + - code reformat and code cleanup + - renamed internal (Encode, Decode) to (Combine, Parse) to + prevent misinterpretation with upcoming Unicode changes + and possible name clashes + - added pod check (and fixed pod) + - added pod coverage and small additions to the pod. + More to do in this area + - renamed test to fixate the sequence + - Added t/50_utf8.t + - tests now use Test::More + . Makefile.PL requires Test::More + - checked proclaimed version compatibility + . 5.9.x-64int works @31159 + . 5.8.x-64int-dor works @31162 + . 5.8.0-dor works + . 5.6.2 works + . 5.005.04 works + . 5.004.05 fails + - 5.005 is now prerequisite + - Added missing info in docs for new () + - Added meta_info () method and docs + - Added keep_meta_info in new () + - Added t/15_flags.t + - Added test_cover make target + - Added test for error_input () + - Added tests for fields () and meta_info () before parse () + - Added tests for ->types () as method + - Added tests for deleting types (coverage now over 99%) + - Added is_quoted (), is_binary () and tests + - Added COPYRIGHT section to pod + - Added the parse example from the pod to test.pl + - Added accessor methods for internals: quote_char () et all + - Added tests for the new accessor methods + - Added always_quote to the missing places in the doc and in new () + - Changed the tests to use the accessors instead of the hash keys + except for the ->{types} and ->{_types} + - Moved test.pl to examples/speed.pl 2001-10-10 Jochen Wiedmann (0.23) - * Changed "char" to "unsigned char" in CSV_XS.xs. - Matthew Graham + * Changed "char" to "unsigned char" in CSV_XS.xs. + Matthew Graham 2000-12-22 Jochen Wiedmann (0.22) - * CSV_XS.xs: Added the handling of escape characters - outside of quotes. Kirill Paliy + * CSV_XS.xs: Added the handling of escape characters + outside of quotes. Kirill Paliy 2000-08-18 Jochen Wiedmann (0.21) - * CSV_XS.pm (parse): Minor bugfix in the parse method. - Norikatsu Shigemura (nork@cityfujisawa.ne.jp) + * CSV_XS.pm (parse): Minor bugfix in the parse method. + Norikatsu Shigemura (nork@cityfujisawa.ne.jp) 1999-06-28 Jochen Wiedmann (0.20) - * CSV_XS.xs: Fixed a bug in the decoder where escapeChar wasn't - handled right. Pavel Kotala + * CSV_XS.xs: Fixed a bug in the decoder where escapeChar wasn't + handled right. Pavel Kotala 1999-05-01 Jochen Wiedmann (0.19) - * CSV_XS.xs: Setting escape_char => undef should now work. - Requested by Syed Muhammad Nayeem + * CSV_XS.xs: Setting escape_char => undef should now work. + Requested by Syed Muhammad Nayeem 1999-04-05 Jochen Wiedmann (0.18) - * CSV_XS.pm: Portability fixes (sv_undef => PL_sv_undef - and the like. + * CSV_XS.pm: Portability fixes (sv_undef => PL_sv_undef + and the like. 1999-03-04 Jochen Wiedmann (0.17) - * CSV_XS.pm: Added always_quote attribute. - (Ken Williams ) - * The types method is now implemented in Perl. + * CSV_XS.pm: Added always_quote attribute. + (Ken Williams ) + * The types method is now implemented in Perl. 1999-02-11 Jochen Wiedmann (0.16) - * CSV_XS.pm: PV, IV and NV are no longer exportable, so that I - need not inherit from Exporter any longer. (This caused trying - to autoload DESTROY without any reason. Seems to me to be a - serious performance penalty.) - * CSV_XS.pm: Being a little bit less strict now: If quoteChar and - escapeChar are different, then the quote char may be part of - the field. (Not at the fields start, of course.) + * CSV_XS.pm: PV, IV and NV are no longer exportable, so that I + need not inherit from Exporter any longer. (This caused trying + to autoload DESTROY without any reason. Seems to me to be a + serious performance penalty.) + * CSV_XS.pm: Being a little bit less strict now: If quoteChar and + escapeChar are different, then the quote char may be part of + the field. (Not at the fields start, of course.) 1998-08-21 Jochen Wiedmann (0.15) - * CSV_XS.pm: Moved print() and getline() to XS. + * CSV_XS.pm: Moved print () and getline () to XS. 1998-08-13 Jochen Wiedmann (0.14) - * CSV_XS.xs: Forgot to escape sepchar; patched by Paul Walmsley, - . + * CSV_XS.xs: Forgot to escape sepchar; patched by Paul Walmsley, + . 1998-07-20 Jochen Wiedmann (0.13) - * CSV_XS.xs (Encode): Strings qre quoted only if required. - * CSV_XS.xs: Added support for $csv->{types}. + * CSV_XS.xs (Encode): Strings qre quoted only if required. + * CSV_XS.xs: Added support for $csv->{types}. 1998-06-11 Jochen Wiedmann (0.12) - * CSV_XS.xs (Encode): Integers and Reals are no longer quoted. + * CSV_XS.xs (Encode): Integers and Reals are no longer quoted. - * Added $csv->{types}. + * Added $csv->{types}. 1998-05-12 Jochen Wiedmann (0.11) - * Added $csv->{eol} + * Added $csv->{eol} - * Added $csv->{quote_char} = undef + * Added $csv->{quote_char} = undef 1998-05-05 Jochen Wiedmann (0.10) - * Moved encoding and decoding to XS; added binary mode; added - print() and getline() methods. + * Moved encoding and decoding to XS; added binary mode; added + print () and getline () methods. 1998-06-05 Alan Citterman - * Initial version - + * Initial version diff --git a/MANIFEST b/MANIFEST index 8ce8a12..f6f402e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -16,6 +16,7 @@ t/21_lexicalio.t IO tests (print and getline) lexical handles t/22_scalario.t IO tests (print and getline) scalar io (perlio) t/30_types.t Tests for the "types" attribute. t/40_misc.t Binary mode tests +t/41_null.t NULL test in combination with line endings t/45_eol.t Embedded EOL t/50_utf8.t Unicode stress tests t/55_combi.t Different CSV character combinations @@ -25,6 +26,7 @@ t/70_rt.t Tests based on RT reports t/75_hashref.t getline_hr related tests t/76_magic.t array_ref from magig t/80_diag.t Error diagnostics +t/81_subclass.t Subclassed t/util.pl Extra test utilities examples/csv2xls Script to onvert CSV files to M$Excel examples/csv-check Script to check a CSV file/stream diff --git a/META.yml b/META.yml index 983ca8d..9f3d5d3 100644 --- a/META.yml +++ b/META.yml @@ -1,6 +1,6 @@ --- #YAML:1.1 name: Text-CSV_XS -version: 0.65 +version: 0.67 abstract: Comma-Separated Values manipulation routines license: perl author: @@ -10,7 +10,7 @@ distribution_type: module provides: Text::CSV_XS: file: CSV_XS.pm - version: 0.65 + version: 0.67 requires: perl: 5.005 DynaLoader: 0 diff --git a/ppport.h b/ppport.h index 3e3d52f..ec2f1cc 100644 --- a/ppport.h +++ b/ppport.h @@ -4,7 +4,7 @@ /* ---------------------------------------------------------------------- - ppport.h -- Perl/Pollution/Portability Version 3.17 + ppport.h -- Perl/Pollution/Portability Version 3.19 Automatically created by Devel::PPPort running under perl 5.010000. @@ -21,7 +21,7 @@ SKIP =head1 NAME -ppport.h - Perl/Pollution/Portability version 3.17 +ppport.h - Perl/Pollution/Portability version 3.19 =head1 SYNOPSIS @@ -232,6 +232,7 @@ same function or variable in your project. my_strlcpy() NEED_my_strlcpy NEED_my_strlcpy_GLOBAL newCONSTSUB() NEED_newCONSTSUB NEED_newCONSTSUB_GLOBAL newRV_noinc() NEED_newRV_noinc NEED_newRV_noinc_GLOBAL + newSV_type() NEED_newSV_type NEED_newSV_type_GLOBAL newSVpvn_flags() NEED_newSVpvn_flags NEED_newSVpvn_flags_GLOBAL newSVpvn_share() NEED_newSVpvn_share NEED_newSVpvn_share_GLOBAL pv_display() NEED_pv_display NEED_pv_display_GLOBAL @@ -377,7 +378,7 @@ use strict; # Disable broken TRIE-optimization BEGIN { eval '${^RE_TRIE_MAXBUF} = -1' if $] >= 5.009004 && $] <= 5.009005 } -my $VERSION = 3.17; +my $VERSION = 3.19; my %opt = ( quiet => 0, @@ -486,6 +487,7 @@ G_NOARGS||| G_SCALAR||| G_VOID||5.004000| GetVars||| +GvSVn|5.009003||p GvSV||| Gv_AMupdate||| HEf_SVKEY||5.004000| @@ -498,6 +500,8 @@ HeSVKEY_set||5.004000| HeSVKEY||5.004000| HeUTF8||5.011000| HeVAL||5.004000| +HvNAMELEN_get|5.009003||p +HvNAME_get|5.009003||p HvNAME||| INT2PTR|5.006000||p IN_LOCALE_COMPILETIME|5.007002||p @@ -628,6 +632,9 @@ PERL_SHORT_MAX|5.004000||p PERL_SHORT_MIN|5.004000||p PERL_SIGNALS_UNSAFE_FLAG|5.008001||p PERL_SUBVERSION|5.006000||p +PERL_SYS_INIT3||5.006000| +PERL_SYS_INIT||| +PERL_SYS_TERM||5.011000| PERL_UCHAR_MAX|5.004000||p PERL_UCHAR_MIN|5.004000||p PERL_UINT_MAX|5.004000||p @@ -661,9 +668,12 @@ PL_diehook|5.004050||p PL_dirty|5.004050||p PL_dowarn|||pn PL_errgv|5.004050||p +PL_error_count|5.011000||p PL_expect|5.011000||p PL_hexdigit|5.005000||p PL_hints|5.005000||p +PL_in_my_stash|5.011000||p +PL_in_my|5.011000||p PL_last_in_gv|||n PL_laststatval|5.005000||p PL_lex_state|5.011000||p @@ -769,6 +779,7 @@ SV_MUTABLE_RETURN|5.009003||p SV_NOSTEAL|5.009002||p SV_SMAGIC|5.009003||p SV_UTF8_NO_ENCODING|5.008001||p +SVfARG|5.009005||p SVf_UTF8|5.006000||p SVf|5.006000||p SVt_IV||| @@ -977,6 +988,7 @@ XPUSHn||| XPUSHp||| XPUSHs||| XPUSHu|5.004000||p +XSPROTO|5.010000||p XSRETURN_EMPTY||| XSRETURN_IV||| XSRETURN_NO||| @@ -1055,7 +1067,6 @@ boolSV|5.004000||p boot_core_PerlIO||| boot_core_UNIVERSAL||| boot_core_mro||| -boot_core_xsutils||| bytes_from_utf8||5.007001| bytes_to_uni|||n bytes_to_utf8||5.006001| @@ -1341,7 +1352,6 @@ get_vtbl||5.005030| getcwd_sv||5.007002| getenv_len||| glob_2number||| -glob_2pv||| glob_assign_glob||| glob_assign_ref||| gp_dup||| @@ -1372,7 +1382,8 @@ gv_fetchmethod_autoload||5.004000| gv_fetchmethod_flags||5.011000| gv_fetchmethod||| gv_fetchmeth||| -gv_fetchpvn_flags||5.009002| +gv_fetchpvn_flags|5.009002||p +gv_fetchpvs|5.009004||p gv_fetchpv||| gv_fetchsv||5.009002| gv_fullname3||5.004000| @@ -1384,7 +1395,7 @@ gv_init_sv||| gv_init||| gv_name_set||5.009004| gv_stashpvn|5.004000||p -gv_stashpvs||5.009003| +gv_stashpvs|5.009003||p gv_stashpv||| gv_stashsv||| he_dup||| @@ -1470,6 +1481,7 @@ isBLANK|5.006001||p isCNTRL|5.006000||p isDIGIT||| isGRAPH|5.006000||p +isGV_with_GP|5.009004||p isLOWER||| isPRINT|5.004000||p isPSXSPC|5.006001||p @@ -1774,7 +1786,7 @@ newSTATEOP||| newSUB||| newSVOP||| newSVREF||| -newSV_type||5.009005| +newSV_type|5.009005||p newSVhek||5.009003| newSViv||| newSVnv||| @@ -2195,6 +2207,7 @@ sv_derived_from||5.004000| sv_destroyable||5.010000| sv_does||5.009004| sv_dump||| +sv_dup_inc_multiple||| sv_dup||| sv_eq||| sv_exp_grow||| @@ -3907,6 +3920,13 @@ typedef NVTYPE NV; return; \ } STMT_END #endif +#ifndef XSPROTO +# define XSPROTO(name) void name(pTHX_ CV* cv) +#endif + +#ifndef SVfARG +# define SVfARG(p) ((void*)(p)) +#endif #ifndef PERL_ABS # define PERL_ABS(x) ((x) < 0 ? -(x) : (x)) #endif @@ -4086,9 +4106,11 @@ extern U32 DPPP_(my_PL_signals); # define PL_dirty dirty # define PL_dowarn dowarn # define PL_errgv errgv +# define PL_error_count error_count # define PL_expect expect # define PL_hexdigit hexdigit # define PL_hints hints +# define PL_in_my in_my # define PL_laststatval laststatval # define PL_lex_state lex_state # define PL_lex_stuff lex_stuff @@ -4171,6 +4193,10 @@ extern yy_parser DPPP_(dummy_PL_parser); # define PL_lex_state D_PPP_my_PL_parser_var(lex_state) # define PL_lex_stuff D_PPP_my_PL_parser_var(lex_stuff) # define PL_tokenbuf D_PPP_my_PL_parser_var(tokenbuf) +# define PL_in_my D_PPP_my_PL_parser_var(in_my) +# define PL_in_my_stash D_PPP_my_PL_parser_var(in_my_stash) +# define PL_error_count D_PPP_my_PL_parser_var(error_count) + #else @@ -4711,6 +4737,35 @@ DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv) # define SvREFCNT_inc_simple_void_NN(sv) (void)(++SvREFCNT((SV*)(sv))) #endif +#ifndef newSV_type + +#if defined(NEED_newSV_type) +static SV* DPPP_(my_newSV_type)(pTHX_ svtype const t); +static +#else +extern SV* DPPP_(my_newSV_type)(pTHX_ svtype const t); +#endif + +#ifdef newSV_type +# undef newSV_type +#endif +#define newSV_type(a) DPPP_(my_newSV_type)(aTHX_ a) +#define Perl_newSV_type DPPP_(my_newSV_type) + +#if defined(NEED_newSV_type) || defined(NEED_newSV_type_GLOBAL) + +SV* +DPPP_(my_newSV_type)(pTHX_ svtype const t) +{ + SV* const sv = newSV(0); + sv_upgrade(sv, t); + return sv; +} + +#endif + +#endif + #if (PERL_BCDVERSION < 0x5006000) # define D_PPP_CONSTPV_ARG(x) ((char *) (x)) #else @@ -5298,6 +5353,19 @@ DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash) #ifndef SvSHARED_HASH # define SvSHARED_HASH(sv) (0 + SvUVX(sv)) #endif +#ifndef HvNAME_get +# define HvNAME_get(hv) HvNAME(hv) +#endif +#ifndef HvNAMELEN_get +# define HvNAMELEN_get(hv) (HvNAME_get(hv) ? (I32)strlen(HvNAME_get(hv)) : 0) +#endif +#ifndef GvSVn +# define GvSVn(gv) GvSV(gv) +#endif + +#ifndef isGV_with_GP +# define isGV_with_GP(gv) isGV(gv) +#endif #ifndef WARN_ALL # define WARN_ALL 0 #endif @@ -5561,6 +5629,17 @@ DPPP_(my_warner)(U32 err, const char *pat, ...) #ifndef hv_stores # define hv_stores(hv, key, val) hv_store(hv, key "", sizeof(key) - 1, val, 0) #endif +#ifndef gv_fetchpvn_flags +# define gv_fetchpvn_flags(name, len, flags, svt) gv_fetchpv(name, flags, svt) +#endif + +#ifndef gv_fetchpvs +# define gv_fetchpvs(name, flags, svt) gv_fetchpvn_flags(name "", sizeof(name) - 1, flags, svt) +#endif + +#ifndef gv_stashpvs +# define gv_stashpvs(name, flags) gv_stashpvn(name "", sizeof(name) - 1, flags) +#endif #ifndef SvGETMAGIC # define SvGETMAGIC(x) STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END #endif diff --git a/t/12_acc.t b/t/12_acc.t index 485e6d3..7abb9e3 100644 --- a/t/12_acc.t +++ b/t/12_acc.t @@ -3,7 +3,7 @@ use strict; $^W = 1; # use warnings core since 5.6 -use Test::More tests => 66; +use Test::More tests => 86; BEGIN { use_ok "Text::CSV_XS"; @@ -24,6 +24,8 @@ is ($csv->allow_loose_quotes, 0, "allow_loose_quotes"); is ($csv->allow_loose_escapes, 0, "allow_loose_escapes"); is ($csv->allow_whitespace, 0, "allow_whitespace"); is ($csv->blank_is_undef, 0, "blank_is_undef"); +is ($csv->empty_is_undef, 0, "empty_is_undef"); +is ($csv->auto_diag, 0, "auto_diag"); is ($csv->verbatim, 0, "verbatim"); is ($csv->binary (1), 1, "binary (1)"); @@ -44,6 +46,8 @@ is ($csv->allow_loose_quotes (1), 1, "allow_loose_quotes (1)"); is ($csv->allow_loose_escapes (1), 1, "allow_loose_escapes (1)"); is ($csv->allow_whitespace (1), 1, "allow_whitespace (1)"); is ($csv->blank_is_undef (1), 1, "blank_is_undef (1)"); +is ($csv->empty_is_undef (1), 1, "empty_is_undef (1)"); +is ($csv->auto_diag (1), 1, "auto_diag (1)"); is ($csv->verbatim (1), 1, "verbatim (1)"); is ($csv->escape_char ("\\"), "\\", "escape_char (\\)"); ok ($csv->combine (@fld), "combine"); @@ -101,4 +105,9 @@ is (Text::CSV_XS::error_diag (), "INI - Unknown attribute 'oel'", "Unsupported a is (Text::CSV_XS->new ({ _STATUS => "" }), undef, "private attr"); is (Text::CSV_XS::error_diag (), "INI - Unknown attribute '_STATUS'", "Unsupported private attr"); +foreach my $arg (undef, 0, "", " ", 1, [], [ 0 ], *STDOUT) { + is (Text::CSV_XS->new ($arg), undef, "Illegal type for first arg"); + is ((Text::CSV_XS::error_diag)[0], 1000, "Should be a hashref - numeric error"); + } + 1; diff --git a/t/15_flags.t b/t/15_flags.t index bc7b153..dde73eb 100644 --- a/t/15_flags.t +++ b/t/15_flags.t @@ -3,7 +3,7 @@ use strict; $^W = 1; # use warnings core since 5.6 -use Test::More tests => 173; +use Test::More tests => 185; BEGIN { use_ok "Text::CSV_XS"; @@ -209,3 +209,18 @@ sub crnlsp ok (!$csv->parse (qq{"+\r"}), "Quo ESC CR"); ok (!$csv->parse (qq{"+\r\n"}), "Quo ESC CR NL"); } + +{ my $csv = Text::CSV_XS->new ({ always_quote => 0 }); + ok ($csv->combine (1..3), "Combine"); + is ($csv->string, q{1,2,3}, "String"); + is ($csv->always_quote, 0, "Attr 0"); + ok ($csv->combine (1..3), "Combine"); + ok ($csv->always_quote (1), "Attr 1"); + ok ($csv->combine (1..3), "Combine"); + is ($csv->string, q{"1","2","3"}, "String"); + is ($csv->always_quote, 1, "Attr 1"); + is ($csv->always_quote (0), 0, "Attr 0"); + ok ($csv->combine (1..3), "Combine"); + is ($csv->string, q{1,2,3}, "String"); + is ($csv->always_quote, 0, "Attr 0"); + } diff --git a/t/41_null.t b/t/41_null.t new file mode 100644 index 0000000..de44d25 --- /dev/null +++ b/t/41_null.t @@ -0,0 +1,77 @@ +#!/usr/bin/perl + +use strict; +$^W = 1; + +use Test::More tests => 62; +use Text::CSV_XS; + +my @pat = ( + "00", + "\00", + "0\0", + "\0\0", + + "0\n0", + "\0\n0", + "0\n\0", + "\0\n\0", + + "\"0\n0", + "\"\0\n0", + "\"0\n\0", + "\"\0\n\0", + + "\"0\n\"0", + "\"\0\n\"0", + "\"0\n\"\0", + "\"\0\n\"\0", + + "0\n0", + "\0\n0", + "0\n\0", + "\0\n\0", + ); +my %exp = map { + my $x = $_; + $x =~ s/\0/\\0/g; + $x =~ s/\n/\\n/g; + ($_ => $x); + } @pat; + +my $csv = Text::CSV_XS->new ({ + eol => "\n", + binary => 1, + auto_diag => 1, + blank_is_undef => 1, + }); + +open FH, ">__test.csv" or die $!; +binmode FH; + +for (@pat) { + ok ($csv->print (*FH, [ $_ ]), "print $exp{$_}"); + } + +$csv->always_quote (1); + +my $line = ["", undef, "0\n", "", "\0\n0"]; +ok ($csv->print (*FH, $line), "print [ ... ]"); + +close FH; + +open FH, "<__test.csv" or die $!; +binmode FH; + +foreach my $pat (@pat) { + ok (my $row = $csv->getline (*FH), "getline $exp{$pat}"); + is ($row->[0], $pat, "data $exp{$pat}"); + } + +my $row = $csv->getline (*FH); + +is_deeply ($row, $line, "read [ ... ]"); + +close FH; + +unlink "__test.csv"; diff --git a/t/65_allow.t b/t/65_allow.t index 59163cc..aa6e682 100644 --- a/t/65_allow.t +++ b/t/65_allow.t @@ -4,7 +4,7 @@ use strict; $^W = 1; #use Test::More "no_plan"; - use Test::More tests => 1018; + use Test::More tests => 1115; BEGIN { use_ok "Text::CSV_XS", (); @@ -210,6 +210,31 @@ foreach my $conf ( } } +ok (1, "empty_is_undef"); +foreach my $conf ( + [ 0, 0, 0, 1, "", " ", '""', 2, "", "", "" ], + [ 0, 0, 1, 1, undef, " ", '""', 2, undef, undef, undef ], + [ 0, 1, 0, 1, "", " ", '""', 2, "", "", "" ], + [ 0, 1, 1, 1, undef, " ", '""', 2, undef, undef, undef ], + [ 1, 0, 0, 1, "", " ", '""', 2, "", "", "" ], + [ 1, 0, 1, 1, undef, " ", '""', 2, undef, undef, undef ], + [ 1, 1, 0, 1, "", " ", '""', 2, "", "", "" ], + [ 1, 1, 1, 1, undef, " ", '""', 2, undef, undef, undef ], + ) { + my ($aq, $aw, $bu, @expect, $str) = @$conf; + $csv = Text::CSV_XS->new ({ always_quote => $aq, allow_whitespace => $aw, empty_is_undef => $bu }); + ok ($csv, "new ({ aq $aq aw $aw bu $bu })"); + ok ($csv->combine (1, "", " ", '""', 2, undef, "", undef), "combine ()"); + ok ($str = $csv->string, "string ()"); + foreach my $eol ("", "\n", "\r\n") { + my $s_eol = _readable ($eol); + ok ($csv->parse ($str.$eol), "parse (*$str$s_eol*)"); + ok (my @f = $csv->fields, "fields ()"); + is_deeply (\@f, \@expect, "result"); + } + } + + ok (1, "Trailing junk"); foreach my $bin (0, 1) { foreach my $eol (undef, "\r") { diff --git a/t/80_diag.t b/t/80_diag.t index 38c6a3d..25f691a 100644 --- a/t/80_diag.t +++ b/t/80_diag.t @@ -3,7 +3,7 @@ use strict; $^W = 1; - use Test::More tests => 86; + use Test::More tests => 90; #use Test::More "no_plan"; my %err; @@ -57,9 +57,11 @@ parse_err 2032, 2, qq{ \r}; parse_err 2034, 4, qq{1, "bar",2}; parse_err 2037, 1, qq{\0 }; -unless (($ENV{AUTOMATED_TESTING} || 0) == "1") { - diag ("Next line should be an error message"); +{ my @warn; + local $SIG{__WARN__} = sub { push @warn, @_ }; $csv->error_diag (); + ok (@warn == 1, "Got error message"); + like ($warn[0], qr{^# CSV_XS ERROR: 2037 - EIF}, "error content"); } is (Text::CSV_XS->new ({ ecs_char => ":" }), undef, "Unsupported option"); @@ -74,20 +76,17 @@ $csv->SetDiag (0); is (0 + $csv->error_diag (), 0, "Reset error NUM"); is ( $csv->error_diag (), "", "Reset error NUM"); -package Text::CSV_XS::Subclass; - -use base "Text::CSV_XS"; - -use Test::More; - -ok (1, "Subclassed"); - -my $csvs = Text::CSV_XS::Subclass->new (); -is ($csvs->error_diag (), "", "Last failure for new () - OK"); - -is (Text::CSV_XS::Subclass->new ({ ecs_char => ":" }), undef, "Unsupported option"); - -is (Text::CSV_XS::Subclass->error_diag (), - "INI - Unknown attribute 'ecs_char'", "Last failure for new () - FAIL"); +ok (1, "Test auto_diag"); +$csv = Text::CSV_XS->new ({ auto_diag => 1 }); +{ my @warn; + local $SIG{__WARN__} = sub { push @warn, @_ }; + is ($csv->parse ('"","'), 0, "1 - bad parse"); + ok (@warn == 1, "1 - One error"); + like ($warn[0], qr '^# CSV_XS ERROR: 2027 -', "1 - error message"); + } +{ ok ($csv->{auto_diag} = 2, "auto_diag = 2 to die"); + eval { $csv->parse ('"","') }; + like ($@, qr '^# CSV_XS ERROR: 2027 -', "2 - error message"); + } 1; diff --git a/t/81_subclass.t b/t/81_subclass.t new file mode 100644 index 0000000..d82fd12 --- /dev/null +++ b/t/81_subclass.t @@ -0,0 +1,28 @@ +#!/usr/bin/perl + +package Text::CSV_XS::Subclass; + +BEGIN { require Text::CSV_XS; } # needed for perl5.005 + +use strict; +$^W = 1; +$| = 1; + +use base "Text::CSV_XS"; + +use Test::More tests => 5; + +ok (1, "Subclassed"); + +my $csvs = Text::CSV_XS::Subclass->new (); +is ($csvs->error_diag (), "", "Last failure for new () - OK"); + +my $sc_csv; +eval { $sc_csv = Text::CSV_XS::Subclass->new ({ ecs_char => ":" }); }; +is ($sc_csv, undef, "Unsupported option"); +is ($@, "", "error"); + +is (Text::CSV_XS::Subclass->error_diag (), + "INI - Unknown attribute 'ecs_char'", "Last failure for new () - FAIL"); + +1;