File Coverage

CSV_XS.xs
Criterion Covered Total %
statement 987 1011 97.6
branch 1639 3356 48.8
condition n/a
subroutine n/a
pod n/a
total 2626 4367 60.1


line stmt bran cond sub pod time code
1             /* Copyright (c) 2007-2023 H.Merijn Brand. All rights reserved.
2             * Copyright (c) 1998-2001 Jochen Wiedmann. All rights reserved.
3             * This program is free software; you can redistribute it and/or
4             * modify it under the same terms as Perl itself.
5             */
6             #define PERL_NO_GET_CONTEXT
7             #include
8             #include
9             #include
10             #define DPPP_PL_parser_NO_DUMMY
11             #define NEED_utf8_to_uvchr_buf
12             #define NEED_my_snprintf
13             #define NEED_pv_escape
14             #define NEED_pv_pretty
15             #ifndef PERLIO_F_UTF8
16             # define PERLIO_F_UTF8 0x00008000
17             # endif
18             #ifndef MAXINT
19             # define MAXINT ((int)(~(unsigned)0 >> 1))
20             # endif
21             #include "ppport.h"
22             #define is_utf8_sv(s) is_utf8_string ((U8 *)SvPV_nolen (s), SvCUR (s))
23              
24             #define MAINT_DEBUG 0
25              
26             #define BUFFER_SIZE 1024
27              
28             #define CSV_XS_TYPE_WARN 1
29             #define CSV_XS_TYPE_PV 0
30             #define CSV_XS_TYPE_IV 1
31             #define CSV_XS_TYPE_NV 2
32              
33             /* maximum length for EOL, SEP, and QUOTE - keep in sync with .pm */
34             #define MAX_ATTR_LEN 16
35              
36             #define CSV_FLAGS_QUO 0x0001
37             #define CSV_FLAGS_BIN 0x0002
38             #define CSV_FLAGS_EIF 0x0004
39             #define CSV_FLAGS_MIS 0x0010
40              
41             #define HOOK_ERROR 0x0001
42             #define HOOK_AFTER_PARSE 0x0002
43             #define HOOK_BEFORE_PRINT 0x0004
44              
45             #ifdef __THW_370__
46             /* EBCDIC on os390 z/OS: IS_EBCDIC reads better than __THW_370__ */
47             #define IS_EBCDIC
48             #endif
49              
50             #define CH_TAB '\t'
51             #define CH_NL '\n'
52             #define CH_CR '\r'
53             #define CH_SPACE ' '
54             #define CH_QUO '"'
55              
56             #ifdef IS_EBCDIC
57             #define CH_DEL '\007'
58             static unsigned char ec, ebcdic2ascii[256] = {
59             0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f,
60             0x97, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
61             0x10, 0x11, 0x12, 0x13, 0x9d, 0x0a, 0x08, 0x87,
62             0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d, 0x1e, 0x1f,
63             0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1b,
64             0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07,
65             0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
66             0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a,
67             0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5,
68             0xe7, 0xf1, 0xa2, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
69             0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef,
70             0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x5e,
71             0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5,
72             0xc7, 0xd1, 0xa6, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
73             0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf,
74             0xcc, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
75             0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
76             0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1,
77             0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
78             0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4,
79             0xb5, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
80             0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0x5b, 0xde, 0xae,
81             0xac, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc,
82             0xbd, 0xbe, 0xdd, 0xa8, 0xaf, 0x5d, 0xb4, 0xd7,
83             0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
84             /* v this 0xa0 really should be 0xad. Needed for UTF = binary */
85             0x48, 0x49, 0xa0, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5,
86             0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
87             0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xf9, 0xfa, 0xff,
88             0x5c, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
89             0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5,
90             0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
91             0x38, 0x39, 0xb3, 0xdb, 0xdc, 0xd9, 0xda, 0x9f
92             };
93             #define is_csv_binary(ch) ((((ec = ebcdic2ascii[ch]) < 0x20 || ec >= 0x7f) && ch != CH_TAB) || ch == EOF)
94             #else
95             #define CH_DEL '\177'
96             #define is_csv_binary(ch) ((ch < CH_SPACE || ch >= CH_DEL) && ch != CH_TAB)
97             #endif
98             #define CH_EOLX 1215
99             #define CH_EOL *csv->eol
100             #define CH_SEPX 8888
101             #define CH_SEP *csv->sep
102             #define CH_QUOTEX 8889
103             #define CH_QUOTE *csv->quo
104              
105             #define useIO_EOF 0x10
106              
107             #define unless(expr) if (!(expr))
108              
109             #define _is_reftype(f,x) \
110             (f && ((SvGMAGICAL (f) && mg_get (f)) || 1) && SvROK (f) && SvTYPE (SvRV (f)) == x)
111             #define _is_arrayref(f) _is_reftype (f, SVt_PVAV)
112             #define _is_hashref(f) _is_reftype (f, SVt_PVHV)
113             #define _is_coderef(f) _is_reftype (f, SVt_PVCV)
114              
115             #define SvSetUndef(sv) sv_setpvn (sv, NULL, 0)
116             #define SvSetEmpty(sv) sv_setpvn_mg (sv, "", 0)
117              
118             #define CSV_XS_SELF \
119             if (!self || !SvOK (self) || !SvROK (self) || \
120             SvTYPE (SvRV (self)) != SVt_PVHV) \
121             croak ("self is not a hash ref"); \
122             hv = (HV *)SvRV (self)
123              
124             /* Keep in sync with .pm! */
125             #define CACHE_ID_quote_char 0
126             #define CACHE_ID_escape_char 1
127             #define CACHE_ID_sep_char 2
128             #define CACHE_ID_binary 3
129             #define CACHE_ID_keep_meta_info 4
130             #define CACHE_ID_always_quote 5
131             #define CACHE_ID_allow_loose_quotes 6
132             #define CACHE_ID_allow_loose_escapes 7
133             #define CACHE_ID_allow_unquoted_escape 8
134             #define CACHE_ID_allow_whitespace 9
135             #define CACHE_ID_blank_is_undef 10
136             #define CACHE_ID_sep 39
137             #define CACHE_ID_sep_len 38
138             #define CACHE_ID_eol 11
139             #define CACHE_ID_eol_len 12
140             #define CACHE_ID_eol_is_cr 13
141             #define CACHE_ID_quo 15
142             #define CACHE_ID_quo_len 16
143             #define CACHE_ID_verbatim 22
144             #define CACHE_ID_empty_is_undef 23
145             #define CACHE_ID_auto_diag 24
146             #define CACHE_ID_quote_space 25
147             #define CACHE_ID_quote_empty 37
148             #define CACHE_ID__is_bound 26
149             #define CACHE_ID__has_ahead 30
150             #define CACHE_ID_escape_null 31
151             #define CACHE_ID_quote_binary 32
152             #define CACHE_ID_diag_verbose 33
153             #define CACHE_ID_has_error_input 34
154             #define CACHE_ID_decode_utf8 35
155             #define CACHE_ID__has_hooks 36
156             #define CACHE_ID_formula 38
157             #define CACHE_ID_strict 42
158             #define CACHE_ID_skip_empty_rows 43
159             #define CACHE_ID_undef_str 46
160             #define CACHE_ID_comment_str 54
161             #define CACHE_ID_types 62
162              
163             #define byte unsigned char
164             #define ulng unsigned long
165             typedef struct {
166             byte quote_char;
167             byte escape_char;
168             byte fld_idx;
169             byte binary;
170              
171             byte keep_meta_info;
172             byte always_quote;
173             byte useIO; /* Also used to indicate EOF */
174             byte eol_is_cr;
175              
176             byte allow_loose_quotes;
177             byte allow_loose_escapes;
178             byte allow_unquoted_escape;
179             byte allow_whitespace;
180              
181             byte blank_is_undef;
182             byte empty_is_undef;
183             byte verbatim;
184             byte auto_diag;
185              
186             byte quote_space;
187             byte escape_null;
188             byte quote_binary;
189             byte first_safe_char;
190              
191             byte diag_verbose;
192             byte has_error_input;
193             byte decode_utf8;
194             byte has_hooks;
195              
196             byte quote_empty;
197             byte formula;
198             byte utf8;
199             byte has_ahead;
200              
201             byte eolx;
202             byte strict;
203             short strict_n;
204              
205             byte skip_empty_rows;
206              
207             long is_bound;
208             ulng recno;
209              
210             byte * cache;
211              
212             SV * pself; /* PL_self, for error_diag */
213             HV * self;
214             SV * bound;
215              
216             char * types;
217              
218             byte eol_len;
219             byte sep_len;
220             byte quo_len;
221             byte types_len;
222              
223             char * bptr;
224             SV * tmp;
225             byte undef_flg;
226             byte * undef_str;
227             byte * comment_str;
228             int eol_pos;
229             STRLEN size;
230             STRLEN used;
231             byte eol[MAX_ATTR_LEN];
232             byte sep[MAX_ATTR_LEN];
233             byte quo[MAX_ATTR_LEN];
234             char buffer[BUFFER_SIZE];
235             } csv_t;
236              
237             #define bool_opt_def(o,d) \
238             (((svp = hv_fetchs (self, o, FALSE)) && *svp) ? SvTRUE (*svp) : d)
239             #define bool_opt(o) bool_opt_def (o, 0)
240             #define num_opt_def(o,d) \
241             (((svp = hv_fetchs (self, o, FALSE)) && *svp) ? SvIV (*svp) : d)
242             #define num_opt(o) num_opt_def (o, 0)
243              
244             typedef struct {
245             int xs_errno;
246             char *xs_errstr;
247             } xs_error_t;
248             static const xs_error_t xs_errors[] = {
249              
250             /* Generic errors */
251             { 1000, "INI - constructor failed" },
252             { 1001, "INI - sep_char is equal to quote_char or escape_char" },
253             { 1002, "INI - allow_whitespace with escape_char or quote_char SP or TAB" },
254             { 1003, "INI - \\r or \\n in main attr not allowed" },
255             { 1004, "INI - callbacks should be undef or a hashref" },
256             { 1005, "INI - EOL too long" },
257             { 1006, "INI - SEP too long" },
258             { 1007, "INI - QUOTE too long" },
259             { 1008, "INI - SEP undefined" },
260              
261             { 1010, "INI - the header is empty" },
262             { 1011, "INI - the header contains more than one valid separator" },
263             { 1012, "INI - the header contains an empty field" },
264             { 1013, "INI - the header contains nun-unique fields" },
265             { 1014, "INI - header called on undefined stream" },
266              
267             /* Syntax errors */
268             { 1500, "PRM - Invalid/unsupported argument(s)" },
269             { 1501, "PRM - The key attribute is passed as an unsupported type" },
270             { 1502, "PRM - The value attribute is passed without the key attribute" },
271             { 1503, "PRM - The value attribute is passed as an unsupported type" },
272              
273             /* Parse errors */
274             { 2010, "ECR - QUO char inside quotes followed by CR not part of EOL" },
275             { 2011, "ECR - Characters after end of quoted field" },
276             { 2012, "EOF - End of data in parsing input stream" },
277             { 2013, "ESP - Specification error for fragments RFC7111" },
278             { 2014, "ENF - Inconsistent number of fields" },
279             { 2015, "ERW - Empty row" },
280              
281             /* EIQ - Error Inside Quotes */
282             { 2021, "EIQ - NL char inside quotes, binary off" },
283             { 2022, "EIQ - CR char inside quotes, binary off" },
284             { 2023, "EIQ - QUO character not allowed" },
285             { 2024, "EIQ - EOF cannot be escaped, not even inside quotes" },
286             { 2025, "EIQ - Loose unescaped escape" },
287             { 2026, "EIQ - Binary character inside quoted field, binary off" },
288             { 2027, "EIQ - Quoted field not terminated" },
289              
290             /* EIF - Error Inside Field */
291             { 2030, "EIF - NL char inside unquoted verbatim, binary off" },
292             { 2031, "EIF - CR char is first char of field, not part of EOL" },
293             { 2032, "EIF - CR char inside unquoted, not part of EOL" },
294             { 2034, "EIF - Loose unescaped quote" },
295             { 2035, "EIF - Escaped EOF in unquoted field" },
296             { 2036, "EIF - ESC error" },
297             { 2037, "EIF - Binary character in unquoted field, binary off" },
298              
299             /* Combine errors */
300             { 2110, "ECB - Binary character in Combine, binary off" },
301              
302             /* IO errors */
303             { 2200, "EIO - print to IO failed. See errno" },
304              
305             /* Hash-Ref errors */
306             { 3001, "EHR - Unsupported syntax for column_names ()" },
307             { 3002, "EHR - getline_hr () called before column_names ()" },
308             { 3003, "EHR - bind_columns () and column_names () fields count mismatch" },
309             { 3004, "EHR - bind_columns () only accepts refs to scalars" },
310             { 3006, "EHR - bind_columns () did not pass enough refs for parsed fields" },
311             { 3007, "EHR - bind_columns needs refs to writable scalars" },
312             { 3008, "EHR - unexpected error in bound fields" },
313             { 3009, "EHR - print_hr () called before column_names ()" },
314             { 3010, "EHR - print_hr () called with invalid arguments" },
315              
316             { 4001, "PRM - The key does not exist as field in the data" },
317              
318             { 5001, "PRM - The result does not match the output to append to" },
319             { 5002, "PRM - Unsupported output" },
320              
321             { 0, "" },
322             };
323              
324             static int last_error = 0;
325             static SV *m_getline, *m_print;
326              
327             #define is_EOL(c) (c == CH_EOLX)
328              
329             #define __is_SEPX(c) (c == CH_SEP && (csv->sep_len == 0 || (\
330             csv->size - csv->used >= (STRLEN)csv->sep_len - 1 &&\
331             !memcmp (csv->bptr + csv->used, csv->sep + 1, csv->sep_len - 1) &&\
332             (csv->used += csv->sep_len - 1) &&\
333             (c = CH_SEPX))))
334             #if MAINT_DEBUG > 1
335             static byte _is_SEPX (unsigned int c, csv_t *csv, int line) {
336             unsigned int b = __is_SEPX (c);
337             (void)fprintf (stderr, "# %4d - is_SEPX:\t%d (%d)\n", line, b, csv->sep_len);
338             if (csv->sep_len)
339             (void)fprintf (stderr,
340             "# len: %d, siz: %d, usd: %d, c: %03x, *sep: %03x\n",
341             csv->sep_len, csv->size, csv->used, c, CH_SEP);
342             return b;
343             } /* _is_SEPX */
344             #define is_SEP(c) _is_SEPX (c, csv, __LINE__)
345             #else
346             #define is_SEP(c) __is_SEPX (c)
347             #endif
348              
349             #define __is_QUOTEX(c) (CH_QUOTE && c == CH_QUOTE && (csv->quo_len == 0 || (\
350             csv->size - csv->used >= (STRLEN)csv->quo_len - 1 &&\
351             !memcmp (csv->bptr + csv->used, csv->quo + 1, csv->quo_len - 1) &&\
352             (csv->used += csv->quo_len - 1) &&\
353             (c = CH_QUOTEX))))
354             #if MAINT_DEBUG > 1
355             static byte _is_QUOTEX (unsigned int c, csv_t *csv, int line) {
356             unsigned int b = __is_QUOTEX (c);
357             (void)fprintf (stderr, "# %4d - is_QUOTEX:\t%d (%d)\n", line, b, csv->quo_len);
358              
359             if (csv->quo_len)
360             (void)fprintf (stderr,
361             "# len: %d, siz: %d, usd: %d, c: %03x, *quo: %03x\n",
362             csv->quo_len, csv->size, csv->used, c, CH_QUOTE);
363             return b;
364             } /* _is_QUOTEX */
365             #define is_QUOTE(c) _is_QUOTEX (c, csv, __LINE__)
366             #else
367             #define is_QUOTE(c) __is_QUOTEX (c)
368             #endif
369              
370             #define is_whitespace(ch) \
371             ( (ch) != CH_SEP && \
372             (ch) != CH_QUOTE && \
373             (ch) != csv->escape_char && \
374             ( (ch) == CH_SPACE || \
375             (ch) == CH_TAB \
376             ) \
377             )
378              
379             #define SvDiag(xse) cx_SvDiag (aTHX_ xse)
380 3591           static SV *cx_SvDiag (pTHX_ int xse) {
381 3591           int i = 0;
382             SV *err;
383              
384 71066 100         while (xs_errors[i].xs_errno && xs_errors[i].xs_errno != xse) i++;
    100          
385 3591 50         if ((err = newSVpv (xs_errors[i].xs_errstr, 0))) {
386 3591 50         (void)SvUPGRADE (err, SVt_PVIV);
387 3591           SvIV_set (err, xse);
388 3591           SvIOK_on (err);
389             }
390 3591           return (err);
391             } /* SvDiag */
392              
393             /* This function should be altered to deal with the optional extra argument
394             * that holds the replacement message */
395             #define SetDiag(csv,xse) cx_SetDiag (aTHX_ csv, xse)
396 1698           static SV *cx_SetDiag (pTHX_ csv_t *csv, int xse) {
397 1698           dSP;
398 1698           SV *err = SvDiag (xse);
399 1698           SV *pself = csv->pself;
400              
401 1698           last_error = xse;
402 1698           (void)hv_store (csv->self, "_ERROR_DIAG", 11, err, 0);
403 1698 100         if (xse == 0) {
404 6           (void)hv_store (csv->self, "_ERROR_POS", 10, newSViv (0), 0);
405 6           (void)hv_store (csv->self, "_ERROR_FLD", 10, newSViv (0), 0);
406 6           (void)hv_store (csv->self, "_ERROR_INPUT", 12, &PL_sv_undef, 0);
407 6           csv->has_error_input = 0;
408             }
409 1698 100         if (xse == 2012) /* EOF */
410 333           (void)hv_store (csv->self, "_EOF", 4, &PL_sv_yes, 0);
411 1698 100         if (csv->auto_diag) {
412 284 50         unless (_is_hashref (pself))
    50          
    0          
    100          
    50          
413 162           pself = newRV_inc ((SV *)csv->self);
414 284           ENTER;
415 284 50         PUSHMARK (SP);
416 284 50         XPUSHs (pself);
417 284           PUTBACK;
418 284           call_pv ("Text::CSV_XS::error_diag", G_VOID | G_DISCARD);
419 281           LEAVE;
420 281 100         unless (pself == csv->pself)
421 161           sv_free (pself);
422             }
423 1695           return (err);
424             } /* SetDiag */
425              
426             #define xs_cache_set(hv,idx,val) cx_xs_cache_set (aTHX_ hv, idx, val)
427 23241           static void cx_xs_cache_set (pTHX_ HV *hv, int idx, SV *val) {
428             SV **svp;
429             byte *cache;
430              
431             csv_t csvs;
432 23241           csv_t *csv = &csvs;
433              
434             IV iv;
435             byte bv;
436 23241           char *cp = "\0";
437 23241           STRLEN len = 0;
438              
439 23241 100         unless ((svp = hv_fetchs (hv, "_CACHE", FALSE)) && *svp)
    50          
440 764           return;
441              
442 22477 50         cache = (byte *)SvPV_nolen (*svp);
443 22477           (void)memcpy (csv, cache, sizeof (csv_t));
444              
445 22477 100         if (SvPOK (val))
446 16683 50         cp = SvPV (val, len);
447 22477 100         if (SvIOK (val))
448 5782 50         iv = SvIV (val);
449 16695 50         else if (SvNOK (val)) /* Needed for 5.6.x but safe for 5.8.x+ */
450 0 0         iv = (IV)SvNV (val); /* uncoverable statement ancient perl required */
451             else
452 16695           iv = *cp;
453 22477           bv = (unsigned)iv & 0xff;
454              
455 22477           switch (idx) {
456              
457             /* single char/byte */
458             case CACHE_ID_sep_char:
459 3122           CH_SEP = *cp;
460 3122           csv->sep_len = 0;
461 3122           break;
462              
463             case CACHE_ID_quote_char:
464 3369           CH_QUOTE = *cp;
465 3369           csv->quo_len = 0;
466 3369           break;
467              
468 3478           case CACHE_ID_escape_char: csv->escape_char = *cp; break;
469              
470             /* boolean/numeric */
471 11           case CACHE_ID_binary: csv->binary = bv; break;
472 10           case CACHE_ID_keep_meta_info: csv->keep_meta_info = bv; break;
473 1798           case CACHE_ID_always_quote: csv->always_quote = bv; break;
474 3           case CACHE_ID_quote_empty: csv->quote_empty = bv; break;
475 6           case CACHE_ID_quote_space: csv->quote_space = bv; break;
476 10           case CACHE_ID_escape_null: csv->escape_null = bv; break;
477 6           case CACHE_ID_quote_binary: csv->quote_binary = bv; break;
478 1           case CACHE_ID_decode_utf8: csv->decode_utf8 = bv; break;
479 11           case CACHE_ID_allow_loose_escapes: csv->allow_loose_escapes = bv; break;
480 11           case CACHE_ID_allow_loose_quotes: csv->allow_loose_quotes = bv; break;
481 2           case CACHE_ID_allow_unquoted_escape: csv->allow_unquoted_escape = bv; break;
482 3719           case CACHE_ID_allow_whitespace: csv->allow_whitespace = bv; break;
483 1           case CACHE_ID_blank_is_undef: csv->blank_is_undef = bv; break;
484 1           case CACHE_ID_empty_is_undef: csv->empty_is_undef = bv; break;
485 1           case CACHE_ID_formula: csv->formula = bv; break;
486 1           case CACHE_ID_strict: csv->strict = bv; break;
487 6           case CACHE_ID_verbatim: csv->verbatim = bv; break;
488 1           case CACHE_ID_skip_empty_rows: csv->skip_empty_rows = bv; break;
489 9           case CACHE_ID_auto_diag: csv->auto_diag = bv; break;
490 8           case CACHE_ID_diag_verbose: csv->diag_verbose = bv; break;
491 142           case CACHE_ID__has_ahead: csv->has_ahead = bv; break;
492 11           case CACHE_ID__has_hooks: csv->has_hooks = bv; break;
493 1           case CACHE_ID_has_error_input: csv->has_error_input = bv; break;
494              
495             /* a 4-byte IV */
496 11           case CACHE_ID__is_bound: csv->is_bound = iv; break;
497              
498             /* string */
499             case CACHE_ID_sep:
500 3223           (void)memcpy (csv->sep, cp, len);
501 3223 50         csv->sep_len = len == 1 ? 0 : len;
502 3223           break;
503              
504             case CACHE_ID_quo:
505 3377           (void)memcpy (csv->quo, cp, len);
506 3377 50         csv->quo_len = len == 1 ? 0 : len;
507 3377           break;
508              
509             case CACHE_ID_eol:
510 112           (void)memcpy (csv->eol, cp, len);
511 112           csv->eol_len = len;
512 112 100         csv->eol_is_cr = len == 1 && *cp == CH_CR ? 1 : 0;
    100          
513 112           break;
514              
515             case CACHE_ID_undef_str:
516 11 100         if (*cp) {
517 8           csv->undef_str = (byte *)cp;
518 8 100         if (SvUTF8 (val))
519 8           csv->undef_flg = 3;
520             }
521             else {
522 3           csv->undef_str = NULL;
523 3           csv->undef_flg = 0;
524             }
525 11           break;
526              
527             case CACHE_ID_comment_str:
528 2 100         csv->comment_str = *cp ? (byte *)cp : NULL;
529 2           break;
530              
531             case CACHE_ID_types:
532 1 50         if (cp && len) {
    50          
533 0           csv->types = cp;
534 0           csv->types_len = len;
535             }
536             else {
537 1           csv->types = NULL;
538 1           csv->types_len = 0;
539             }
540 1           break;
541              
542             default:
543 1           warn ("Unknown cache index %d ignored\n", idx);
544             }
545              
546 22477           csv->cache = cache;
547 22477           (void)memcpy (cache, csv, sizeof (csv_t));
548             } /* cache_set */
549              
550             #define _pretty_strl(csv) cx_pretty_str (aTHX_ csv, strlen (csv))
551             #define _pretty_str(csv,xse) cx_pretty_str (aTHX_ csv, xse)
552 8           static char *cx_pretty_str (pTHX_ byte *s, STRLEN l) {
553 8           SV *dsv = newSVpvs_flags ("", SVs_TEMP);
554 8           return (pv_pretty (dsv, (char *)s, l, 0, NULL, NULL,
555             (PERL_PV_PRETTY_DUMP | PERL_PV_ESCAPE_UNI_DETECT)));
556             } /* _pretty_str */
557              
558             #define _cache_show_byte(trim,c) \
559             warn (" %-21s %02x:%3d\n", trim, c, c)
560             #define _cache_show_char(trim,c) \
561             warn (" %-21s %02x:%s\n", trim, c, _pretty_str (&c, 1))
562             #define _cache_show_str(trim,l,str) \
563             warn (" %-21s %3d:%s\n", trim, l, _pretty_str (str, l))
564              
565             #define _csv_diag(csv) _xs_csv_diag (aTHX_ csv)
566 1           static void _xs_csv_diag (pTHX_ csv_t *csv) {
567 1           warn ("CACHE:\n");
568 1           _cache_show_char ("quote_char", CH_QUOTE);
569 1           _cache_show_char ("escape_char", csv->escape_char);
570 1           _cache_show_char ("sep_char", CH_SEP);
571 1           _cache_show_byte ("binary", csv->binary);
572 1           _cache_show_byte ("decode_utf8", csv->decode_utf8);
573              
574 1           _cache_show_byte ("allow_loose_escapes", csv->allow_loose_escapes);
575 1           _cache_show_byte ("allow_loose_quotes", csv->allow_loose_quotes);
576 1           _cache_show_byte ("allow_unquoted_escape", csv->allow_unquoted_escape);
577 1           _cache_show_byte ("allow_whitespace", csv->allow_whitespace);
578 1           _cache_show_byte ("always_quote", csv->always_quote);
579 1           _cache_show_byte ("quote_empty", csv->quote_empty);
580 1           _cache_show_byte ("quote_space", csv->quote_space);
581 1           _cache_show_byte ("escape_null", csv->escape_null);
582 1           _cache_show_byte ("quote_binary", csv->quote_binary);
583 1           _cache_show_byte ("auto_diag", csv->auto_diag);
584 1           _cache_show_byte ("diag_verbose", csv->diag_verbose);
585 1           _cache_show_byte ("formula", csv->formula);
586 1           _cache_show_byte ("strict", csv->strict);
587 1           _cache_show_byte ("skip_empty_rows", csv->skip_empty_rows);
588 1           _cache_show_byte ("has_error_input", csv->has_error_input);
589 1           _cache_show_byte ("blank_is_undef", csv->blank_is_undef);
590 1           _cache_show_byte ("empty_is_undef", csv->empty_is_undef);
591 1           _cache_show_byte ("has_ahead", csv->has_ahead);
592 1           _cache_show_byte ("keep_meta_info", csv->keep_meta_info);
593 1           _cache_show_byte ("verbatim", csv->verbatim);
594              
595 1           _cache_show_byte ("has_hooks", csv->has_hooks);
596 1           _cache_show_byte ("eol_is_cr", csv->eol_is_cr);
597 1           _cache_show_byte ("eol_len", csv->eol_len);
598 1           _cache_show_str ("eol", csv->eol_len, csv->eol);
599 1           _cache_show_byte ("sep_len", csv->sep_len);
600 1 50         if (csv->sep_len > 1)
601 1           _cache_show_str ("sep", csv->sep_len, csv->sep);
602 1           _cache_show_byte ("quo_len", csv->quo_len);
603 1 50         if (csv->quo_len > 1)
604 1           _cache_show_str ("quote", csv->quo_len, csv->quo);
605 1 50         if (csv->types_len)
606 0           _cache_show_str ("types", csv->types_len, (byte *)csv->types);
607             else
608 1           _cache_show_str ("types", 0, (byte *)"");
609              
610 1 50         if (csv->bptr)
611 1           _cache_show_str ("bptr", (int)strlen (csv->bptr), (byte *)csv->bptr);
612 1 50         if (csv->tmp && SvPOK (csv->tmp)) {
    50          
613 0 0         char *s = SvPV_nolen (csv->tmp);
614 0           _cache_show_str ("tmp", (int)strlen (s), (byte *)s);
615             }
616 1 50         if (csv->cache)
617 1           warn (" %-20s %4d:0x%08x\n", "cache", sizeof (csv_t), csv->cache);
618             else
619 0           warn (" %-22s --:no cache yet\n", "cache");
620 1           } /* _csv_diag */
621              
622             #define xs_cache_diag(hv) cx_xs_cache_diag (aTHX_ hv)
623 2           static void cx_xs_cache_diag (pTHX_ HV *hv) {
624             SV **svp;
625             byte *cache;
626             csv_t csvs;
627 2           csv_t *csv = &csvs;
628              
629 2 100         unless ((svp = hv_fetchs (hv, "_CACHE", FALSE)) && *svp) {
    50          
630 1           warn ("CACHE: invalid\n");
631 1           return;
632             }
633              
634 1 50         cache = (byte *)SvPV_nolen (*svp);
635 1           (void)memcpy (csv, cache, sizeof (csv_t));
636 1           _csv_diag (csv);
637             } /* xs_cache_diag */
638              
639             #define set_eol_is_cr(csv) cx_set_eol_is_cr (aTHX_ csv)
640 8           static void cx_set_eol_is_cr (pTHX_ csv_t *csv) {
641 8           csv->eol[0] = CH_CR;
642 8           csv->eol_is_cr = 1;
643 8           csv->eol_len = 1;
644 8           (void)memcpy (csv->cache, csv, sizeof (csv_t));
645              
646 8           (void)hv_store (csv->self, "eol", 3, newSVpvn ((char *)csv->eol, 1), 0);
647 8           } /* set_eol_is_cr */
648              
649             #define SetupCsv(csv,self,pself) cx_SetupCsv (aTHX_ csv, self, pself)
650 27276           static void cx_SetupCsv (pTHX_ csv_t *csv, HV *self, SV *pself) {
651             SV **svp;
652             STRLEN len;
653             char *ptr;
654              
655 27276           last_error = 0;
656              
657 27276 100         if ((svp = hv_fetchs (self, "_CACHE", FALSE)) && *svp) {
    50          
658 26453           byte *cache = (byte *)SvPVX (*svp);
659 26453           (void)memcpy (csv, cache, sizeof (csv_t));
660             }
661             else {
662             SV *sv_cache;
663              
664 823           (void)memset (csv, 0, sizeof (csv_t)); /* Reset everything */
665              
666 823           csv->self = self;
667 823           csv->pself = pself;
668              
669 823           CH_SEP = ',';
670 823 50         if ((svp = hv_fetchs (self, "sep_char", FALSE)) && *svp && SvOK (*svp))
    50          
    50          
    0          
    0          
671 823 50         CH_SEP = *SvPV (*svp, len);
672 823 100         if ((svp = hv_fetchs (self, "sep", FALSE)) && *svp && SvOK (*svp)) {
    50          
    50          
    0          
    0          
673 224 50         ptr = SvPV (*svp, len);
674 224           (void)memcpy (csv->sep, ptr, len);
675 224 100         if (len > 1)
676 5           csv->sep_len = len;
677             }
678              
679 823           CH_QUOTE = '"';
680 823 50         if ((svp = hv_fetchs (self, "quote_char", FALSE)) && *svp) {
    50          
681 823 100         if (SvOK (*svp)) {
    50          
    50          
682 820 50         ptr = SvPV (*svp, len);
683 820 50         CH_QUOTE = len ? *ptr : (char)0;
684             }
685             else
686 3           CH_QUOTE = (char)0;
687             }
688 823 100         if ((svp = hv_fetchs (self, "quote", FALSE)) && *svp && SvOK (*svp)) {
    50          
    100          
    50          
    50          
689 5 50         ptr = SvPV (*svp, len);
690 5           (void)memcpy (csv->quo, ptr, len);
691 5 100         if (len > 1)
692 4           csv->quo_len = len;
693             }
694              
695 823           csv->escape_char = '"';
696 823 50         if ((svp = hv_fetchs (self, "escape_char", FALSE)) && *svp) {
    50          
697 823 100         if (SvOK (*svp)) {
    50          
    50          
698 817 50         ptr = SvPV (*svp, len);
699 817 100         csv->escape_char = len ? *ptr : (char)0;
700             }
701             else
702 6           csv->escape_char = (char)0;
703             }
704              
705 823 50         if ((svp = hv_fetchs (self, "eol", FALSE)) && *svp && SvOK (*svp)) {
    50          
    100          
    50          
    50          
706 819 50         char *eol = SvPV (*svp, len);
707 819           (void)memcpy (csv->eol, eol, len);
708 819           csv->eol_len = len;
709 819 100         if (len == 1 && *csv->eol == CH_CR)
    100          
710 42           csv->eol_is_cr = 1;
711             }
712              
713 823           csv->undef_flg = 0;
714 823 50         if ((svp = hv_fetchs (self, "undef_str", FALSE)) && *svp && SvOK (*svp)) {
    50          
    100          
    50          
    50          
715             /*if (sv && (SvOK (sv) || (
716             (SvGMAGICAL (sv) && (mg_get (sv), 1) && SvOK (sv))))) {*/
717 1 50         csv->undef_str = (byte *)SvPV_nolen (*svp);
718 1 50         if (SvUTF8 (*svp))
719 0           csv->undef_flg = 3;
720             }
721             else
722 822           csv->undef_str = NULL;
723              
724 823 50         if ((svp = hv_fetchs (self, "comment_str", FALSE)) && *svp && SvOK (*svp))
    50          
    100          
    50          
    50          
725 12 50         csv->comment_str = (byte *)SvPV_nolen (*svp);
726             else
727 811           csv->comment_str = NULL;
728              
729 823 100         if ((svp = hv_fetchs (self, "_types", FALSE)) && *svp && SvOK (*svp)) {
    50          
    50          
    0          
    0          
730 1 50         csv->types = SvPV (*svp, len);
731 1           csv->types_len = len;
732             }
733              
734 823 100         if ((svp = hv_fetchs (self, "_is_bound", FALSE)) && *svp && SvOK (*svp))
    50          
    50          
    0          
    0          
735 4 50         csv->is_bound = SvIV (*svp);
736 823 50         if ((svp = hv_fetchs (self, "callbacks", FALSE)) && _is_hashref (*svp)) {
    50          
    50          
    0          
    100          
    50          
737 301           HV *cb = (HV *)SvRV (*svp);
738 301 100         if ((svp = hv_fetchs (cb, "after_parse", FALSE)) && _is_coderef (*svp))
    50          
    50          
    0          
    50          
    50          
739 9           csv->has_hooks |= HOOK_AFTER_PARSE;
740 301 100         if ((svp = hv_fetchs (cb, "before_print", FALSE)) && _is_coderef (*svp))
    50          
    50          
    0          
    50          
    50          
741 1           csv->has_hooks |= HOOK_BEFORE_PRINT;
742             }
743              
744 823 50         csv->binary = bool_opt ("binary");
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
745 823 50         csv->decode_utf8 = bool_opt ("decode_utf8");
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
746 823 50         csv->always_quote = bool_opt ("always_quote");
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
747 823 50         csv->strict = bool_opt ("strict");
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
748 823 50         csv->quote_empty = bool_opt ("quote_empty");
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
749 823 50         csv->quote_space = bool_opt_def ("quote_space", 1);
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
750 823 50         csv->escape_null = bool_opt_def ("escape_null", 1);
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
751 823 50         csv->quote_binary = bool_opt_def ("quote_binary", 1);
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
752 823 50         csv->allow_loose_quotes = bool_opt ("allow_loose_quotes");
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
753 823 50         csv->allow_loose_escapes = bool_opt ("allow_loose_escapes");
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
754 823 50         csv->allow_unquoted_escape = bool_opt ("allow_unquoted_escape");
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
755 823 50         csv->allow_whitespace = bool_opt ("allow_whitespace");
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
756 823 50         csv->blank_is_undef = bool_opt ("blank_is_undef");
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
757 823 50         csv->empty_is_undef = bool_opt ("empty_is_undef");
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
758 823 50         csv->verbatim = bool_opt ("verbatim");
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
759              
760 823 50         csv->auto_diag = num_opt ("auto_diag");
    50          
    50          
761 823 50         csv->diag_verbose = num_opt ("diag_verbose");
    50          
    50          
762 823 50         csv->keep_meta_info = num_opt ("keep_meta_info");
    50          
    50          
763 823 50         csv->skip_empty_rows = num_opt ("skip_empty_rows");
    50          
    50          
764 823 50         csv->formula = num_opt ("formula");
    50          
    50          
765              
766 823 100         unless (csv->escape_char) csv->escape_null = 0;
767              
768 823           sv_cache = newSVpvn ((char *)csv, sizeof (csv_t));
769 823           csv->cache = (byte *)SvPVX (sv_cache);
770 823           SvREADONLY_on (sv_cache);
771              
772 823           (void)memcpy (csv->cache, csv, sizeof (csv_t));
773              
774 823           (void)hv_store (self, "_CACHE", 6, sv_cache, 0);
775             }
776              
777 27276           csv->utf8 = 0;
778 27276           csv->size = 0;
779 27276           csv->used = 0;
780              
781             /* This is EBCDIC-safe, as it is used after translation */
782 27276 100         csv->first_safe_char = csv->quote_space ? 0x21 : 0x20;
783              
784 27276 100         if (csv->is_bound) {
785 83 50         if ((svp = hv_fetchs (self, "_BOUND_COLUMNS", FALSE)) && _is_arrayref (*svp))
    50          
    50          
    0          
    100          
    50          
786 69           csv->bound = *svp;
787             else
788 14           csv->is_bound = 0;
789             }
790              
791 27276           csv->eol_pos = -1;
792 54552           csv->eolx = csv->eol_len
793 1305 100         ? csv->verbatim || csv->eol_len >= 2
794             ? 1
795 853 100         : csv->eol[0] == CH_CR || csv->eol[0] == CH_NL
796             ? 0
797 366 100         : 1
798 28581 100         : 0;
    100          
799 27276 100         if (csv->sep_len > 1 && is_utf8_string ((U8 *)(csv->sep), csv->sep_len))
    50          
800 51           csv->utf8 = 1;
801 27276 100         if (csv->quo_len > 1 && is_utf8_string ((U8 *)(csv->quo), csv->quo_len))
    50          
802 27           csv->utf8 = 1;
803 27276           } /* SetupCsv */
804              
805             #define Print(csv,dst) cx_Print (aTHX_ csv, dst)
806 941266           static int cx_Print (pTHX_ csv_t *csv, SV *dst) {
807             int result;
808 941266           int keep = 0;
809              
810 941266 100         if (csv->useIO) {
811 939877           SV *tmp = newSVpvn_flags (csv->buffer, csv->used, SVs_TEMP);
812 939877           dSP;
813 939877 50         PUSHMARK (sp);
814 939877 50         EXTEND (sp, 2);
815 939877           PUSHs ((dst));
816 939877 100         if (csv->utf8) {
817             STRLEN len;
818             char *ptr;
819             int j;
820              
821 939649 50         ptr = SvPV (tmp, len);
822 1690511 50         while (len > 0 && !is_utf8_sv (tmp) && keep < 16) {
    50          
    100          
    50          
823 750862           ptr[--len] = (char)0;
824 750862           SvCUR_set (tmp, len);
825 750862           keep++;
826             }
827 1690511 100         for (j = 0; j < keep; j++)
828 750862           csv->buffer[j] = csv->buffer[csv->used - keep + j];
829 939649           SvUTF8_on (tmp);
830             }
831 939877           PUSHs (tmp);
832 939877           PUTBACK;
833 939877           result = call_sv (m_print, G_METHOD);
834 939877           SPAGAIN;
835 939877 50         if (result) {
836 939877 100         result = POPi;
837 939877 100         unless (result)
838 1           (void)SetDiag (csv, 2200);
839             }
840 939877           PUTBACK;
841             }
842             else {
843 1389           sv_catpvn (SvRV (dst), csv->buffer, csv->used);
844 1389           result = TRUE;
845             }
846 941266 100         if (csv->utf8 && !csv->useIO && csv->decode_utf8
    100          
    50          
847 25 50         && SvROK (dst) && is_utf8_sv (SvRV (dst)))
    50          
    100          
848 24           SvUTF8_on (SvRV (dst));
849 941266           csv->used = keep;
850 941266           return result;
851             } /* Print */
852              
853             #define CSV_PUT(csv,dst,c) { \
854             if ((csv)->used == sizeof ((csv)->buffer) - 1) { \
855             unless (Print ((csv), (dst))) \
856             return FALSE; \
857             } \
858             (csv)->buffer[(csv)->used++] = (c); \
859             }
860              
861             #define bound_field(csv,i,keep) cx_bound_field (aTHX_ csv, i, keep)
862 101           static SV *cx_bound_field (pTHX_ csv_t *csv, SSize_t i, int keep) {
863 101           SV *sv = csv->bound;
864             AV *av;
865              
866             /* fprintf (stderr, "# New bind %d/%d\n", i, csv->is_bound);\ */
867 101 100         if (i >= csv->is_bound) {
868 3           (void)SetDiag (csv, 3006);
869 3           return (NULL);
870             }
871              
872 98 50         if (sv && SvROK (sv)) {
    50          
873 98           av = (AV *)(SvRV (sv));
874             /* fprintf (stderr, "# Bind %d/%d/%d\n", i, csv->is_bound, av_len (av)); */
875 98           sv = *av_fetch (av, i, FALSE);
876 98 50         if (sv && SvROK (sv)) {
    50          
877 98           sv = SvRV (sv);
878 98 100         if (keep)
879 14           return (sv);
880              
881 84 100         unless (SvREADONLY (sv)) {
882 83           SvSetEmpty (sv);
883 83           return (sv);
884             }
885             }
886             }
887 1           (void)SetDiag (csv, 3008);
888 1           return (NULL);
889             } /* bound_field */
890              
891             #define was_quoted(mf,idx) cx_was_quoted (aTHX_ mf, idx)
892 17           static int cx_was_quoted (pTHX_ AV *mf, int idx) {
893 17           SV **x = av_fetch (mf, idx, FALSE);
894 17 50         return (x && SvIOK (*x) && SvIV (*x) & CSV_FLAGS_QUO ? 1 : 0);
    50          
    50          
    100          
    0          
895             } /* was_quoted */
896              
897             #define _formula(csv,sv,len,f) cx_formula (aTHX_ csv, sv, len, f)
898 37           static char *cx_formula (pTHX_ csv_t *csv, SV *sv, STRLEN *len, int f) {
899              
900 37           int fa = csv->formula;
901              
902 37 100         if (fa == 1) die ("Formulas are forbidden\n");
903 34 100         if (fa == 2) croak ("Formulas are forbidden\n");
904              
905 31 100         if (fa == 3) {
906 6 50         char *ptr = SvPV_nolen (sv);
907             char rec[40];
908             char field[128];
909             SV **svp;
910              
911 6 100         if (csv->recno) (void)sprintf (rec, " in record %lu", csv->recno + 1);
912 3           else *rec = (char)0;
913              
914 6           *field = (char)0;
915 6 50         if ((svp = hv_fetchs (csv->self, "_COLUMN_NAMES", FALSE)) && _is_arrayref (*svp)) {
    50          
    50          
    0          
    100          
    50          
916 1           AV *avp = (AV *)SvRV (*svp);
917 1 50         if (avp && av_len (avp) >= (f - 1)) {
    50          
918 1           SV **fnm = av_fetch (avp, f - 1, FALSE);
919 1 50         if (fnm && *fnm && SvOK (*fnm))
    50          
    50          
    0          
    0          
920 1 50         (void)sprintf (field, " (column: '%.100s')", SvPV_nolen (*fnm));
921             }
922             }
923              
924 6           warn ("Field %d%s%s contains formula '%s'\n", f, field, rec, ptr);
925 6           return ptr;
926             }
927              
928 25 100         if (len) *len = 0;
929              
930 25 100         if (fa == 4) {
931 5 100         unless (SvREADONLY (sv)) SvSetEmpty (sv);
932 5           return "";
933             }
934              
935 20 100         if (fa == 5) {
936 5 100         unless (SvREADONLY (sv)) SvSetUndef (sv);
937 5           return NULL;
938             }
939              
940 15 50         if (fa == 6) {
941             int result;
942 15           SV **svp = hv_fetchs (csv->self, "_FORMULA_CB", FALSE);
943 15 50         if (svp && _is_coderef (*svp)) {
    50          
    50          
    0          
    50          
    50          
944 15           dSP;
945 15           ENTER;
946 15           SAVE_DEFSV; /* local $_ */
947 15 50         DEFSV = sv;
948 15 50         PUSHMARK (SP);
949 15           PUTBACK;
950 15           result = call_sv (*svp, G_SCALAR);
951 15           SPAGAIN;
952 15 50         if (result)
953 15           sv_setsv (sv, POPs);
954 15           PUTBACK;
955 15           LEAVE;
956             }
957 15 50         return len ? SvPV (sv, *len) : SvPV_nolen (sv);
    0          
    100          
958             }
959              
960             /* So far undefined behavior */
961 0           return NULL;
962             } /* _formula */
963              
964             #define SkipEmptyRow {\
965             int ser = csv->skip_empty_rows; \
966             \
967             if (ser == 3) { (void)SetDiag (csv, 2015); die ("Empty row"); } \
968             if (ser == 4) { (void)SetDiag (csv, 2015); croak ("Empty row"); } \
969             if (ser == 5) { (void)SetDiag (csv, 2015); return FALSE; } \
970             \
971             if (ser <= 2) { /* skip & eof */ \
972             csv->fld_idx = 0; \
973             c = CSV_GET; \
974             if (c == EOF || ser == 2) { \
975             sv_free (sv); \
976             sv = NULL; \
977             waitingForField = 0; \
978             if (ser == 2) return FALSE; \
979             break; \
980             } \
981             } \
982             \
983             if (ser == 6) { \
984             int result, n, i; \
985             SV *rv, **svp = hv_fetchs (csv->self, "_EMPTROW_CB", FALSE); \
986             AV *avp; \
987             unless (svp && _is_coderef (*svp)) \
988             return FALSE; /* A callback is wanted, but none found */ \
989             \
990             dSP; \
991             ENTER; \
992             SAVE_DEFSV; /* local $_ */ \
993             DEFSV = sv; \
994             PUSHMARK (SP); \
995             PUTBACK; \
996             result = call_sv (*svp, G_SCALAR); \
997             SPAGAIN; \
998             unless (result) { \
999             /* A false return will stop the parsing */ \
1000             sv_free (sv); \
1001             sv = NULL; \
1002             waitingForField = 0; \
1003             return FALSE; \
1004             } \
1005             \
1006             PUTBACK; \
1007             LEAVE; \
1008             \
1009             rv = POPs; \
1010             /* Result should be a ref to a list. */ \
1011             unless (_is_arrayref (rv)) \
1012             return FALSE; \
1013             \
1014             avp = (AV *)SvRV (rv); \
1015             \
1016             unless (avp) return FALSE; \
1017             n = av_len (avp); \
1018             if (n <= 0) return TRUE; \
1019             \
1020             if (csv->is_bound && csv->is_bound < n) \
1021             n = csv->is_bound - 1; \
1022             \
1023             for (i = 0; i <= n; i++) { \
1024             SV **svp = av_fetch (avp, i, FALSE); \
1025             sv = svp && *svp ? *svp : NULL; \
1026             if (sv) { \
1027             SvREFCNT_inc (sv); \
1028             /* upgrade IV to IVPV if needed */ \
1029             (void)SvPV_nolen (sv); \
1030             } \
1031             AV_PUSH; \
1032             } \
1033             return TRUE; \
1034             } \
1035             }
1036              
1037             #define Combine(csv,dst,fields) cx_Combine (aTHX_ csv, dst, fields)
1038 21647           static int cx_Combine (pTHX_ csv_t *csv, SV *dst, AV *fields) {
1039             SSize_t i, n;
1040 21647           int bound = 0;
1041 21647           int aq = (int)csv->always_quote;
1042 21647           int qe = (int)csv->quote_empty;
1043 21647           int kmi = (int)csv->keep_meta_info;
1044 21647           AV *qm = NULL;
1045              
1046 21647           n = (IV)av_len (fields);
1047 21647 100         if (n < 0 && csv->is_bound) {
    100          
1048 5           n = csv->is_bound - 1;
1049 5           bound = 1;
1050             }
1051              
1052 21647 100         if (kmi >= 10) {
1053             SV **svp;
1054 2 50         if ((svp = hv_fetchs (csv->self, "_FFLAGS", FALSE)) && _is_arrayref (*svp)) {
    50          
    50          
    0          
    50          
    50          
1055 2           AV *avp = (AV *)SvRV (*svp);
1056 2 50         if (avp && av_len (avp) >= n)
    50          
1057 2           qm = avp;
1058             }
1059             }
1060              
1061 75481 100         for (i = 0; i <= n; i++) {
1062             SV *sv;
1063 53845           STRLEN len = 0;
1064 53845           char *ptr = NULL;
1065              
1066 53845 100         if (i > 0) {
1067 32206 50         CSV_PUT (csv, dst, CH_SEP);
    0          
1068 32199 100         if (csv->sep_len) {
1069             int x;
1070 30 100         for (x = 1; x < (int)csv->sep_len; x++)
1071 20 50         CSV_PUT (csv, dst, csv->sep[x]);
    0          
1072             }
1073             }
1074              
1075 53845 100         if (bound)
1076 14           sv = bound_field (csv, i, 1);
1077             else {
1078 53831           SV **svp = av_fetch (fields, i, FALSE);
1079 53831 50         sv = svp && *svp ? *svp : NULL;
    50          
1080             }
1081              
1082 53845 50         if (sv && (SvOK (sv) || (
    100          
    50          
    50          
    50          
1083 53779 0         (SvGMAGICAL (sv) && (mg_get (sv), 1) && SvOK (sv))))) {
    0          
    0          
1084              
1085             int quoteMe;
1086              
1087 53792 100         ptr = SvPV (sv, len);
1088              
1089 53792 100         if (*ptr == '=' && csv->formula) {
    100          
1090 10 100         unless (ptr = _formula (csv, sv, &len, i))
1091 2           continue;
1092             }
1093 53786 100         if (len == 0)
1094 1404 100         quoteMe = aq ? 1 : qe ? 1 : qm ? was_quoted (qm, i) : 0;
    100          
    100          
1095             else {
1096              
1097 52382 100         if (SvUTF8 (sv)) {
1098 20041           csv->utf8 = 1;
1099 20041           csv->binary = 1;
1100             }
1101              
1102 52382 100         quoteMe = aq ? 1 : qm ? was_quoted (qm, i) : 0;
    100          
1103              
1104             /* Do we need quoting? We do quote, if the user requested
1105             * (always_quote), if binary or blank characters are found
1106             * and if the string contains quote or escape characters.
1107             */
1108 99136 100         if (!quoteMe &&
    100          
1109 46754 100         ( quoteMe = (!SvIOK (sv) && !SvNOK (sv) && CH_QUOTE))) {
    100          
    100          
1110             char *ptr2;
1111             STRLEN l;
1112              
1113             #if MAINT_DEBUG > 4
1114             (void)fprintf (stderr, "# Combine:\n");
1115             sv_dump (sv);
1116             #endif
1117 85816 100         for (ptr2 = ptr, l = len; l; ++ptr2, --l) {
1118 83767           byte c = *ptr2;
1119             #ifdef IS_EBCDIC
1120             byte x = ebcdic2ascii[c];
1121             #if MAINT_DEBUG > 4
1122             (void)fprintf (stderr, " %02x", x);
1123             #endif
1124             #else
1125 83767           byte x = c;
1126             #endif
1127              
1128 166851 50         if ((CH_QUOTE && c == CH_QUOTE) ||
    100          
    100          
    100          
1129 83459 100         (CH_SEP && c == CH_SEP) ||
    100          
1130 166388 100         (csv->escape_char && c == csv->escape_char) ||
    100          
    100          
1131 83074 100         (csv->quote_binary ? (x >= 0x7f && x <= 0xa0) ||
    100          
    100          
1132 63053           x < csv->first_safe_char
1133 15 50         : c == CH_NL || c == CH_CR ||
    50          
    100          
1134 5 100         (csv->quote_space && (
1135 3 50         c == CH_SPACE || c == CH_TAB)))) {
1136             /* Binary character */
1137             break;
1138             }
1139             }
1140             #if defined(IS_EBCDIC) && MAINT_DEBUG > 4
1141             (void)fprintf (stderr, "\n");
1142             #endif
1143 25179           quoteMe = (l > 0);
1144             }
1145             }
1146 53786 100         if (quoteMe) {
1147 29412 50         CSV_PUT (csv, dst, CH_QUOTE);
    0          
1148 29412 100         if (csv->quo_len) {
1149             int x;
1150 51 100         for (x = 1; x < (int)csv->quo_len; x++)
1151 34 50         CSV_PUT (csv, dst, csv->quo[x]);
    0          
1152             }
1153             }
1154 950415231 100         while (len-- > 0) {
1155 950361452           char c = *ptr++;
1156 950361452           int e = 0;
1157              
1158 950361452 100         if (!csv->binary && is_csv_binary (c)) {
    100          
    50          
    100          
1159 7           SvREFCNT_inc (sv);
1160 7           csv->has_error_input = 1;
1161 7 50         unless (hv_store (csv->self, "_ERROR_INPUT", 12, sv, 0))
1162 0           SvREFCNT_dec (sv); /* uncoverable statement memory fail */
1163 7           (void)SetDiag (csv, 2110);
1164 7           return FALSE;
1165             }
1166 950361445 100         if (CH_QUOTE && (byte)c == CH_QUOTE && (csv->quo_len == 0 ||
    100          
    100          
    100          
1167 9           memcmp (ptr, csv->quo +1, csv->quo_len - 1) == 0))
1168 3217           e = 1;
1169             else
1170 950358228 100         if (c == csv->escape_char && csv->escape_char)
    100          
1171 2163           e = 1;
1172             else
1173 950356065 100         if (c == (char)0 && csv->escape_null) {
    100          
1174 29           e = 1;
1175 29           c = '0';
1176             }
1177 950361445 100         if (e && csv->escape_char)
    50          
1178 5409 50         CSV_PUT (csv, dst, csv->escape_char);
    0          
1179 950361445 100         CSV_PUT (csv, dst, c);
    50          
1180             }
1181 53779 100         if (quoteMe) {
1182 29405 50         CSV_PUT (csv, dst, CH_QUOTE);
    0          
1183 29405 100         if (csv->quo_len) {
1184             int x;
1185 51 100         for (x = 1; x < (int)csv->quo_len; x++)
1186 34 50         CSV_PUT (csv, dst, csv->quo[x]);
    0          
1187             }
1188             }
1189             }
1190             else {
1191 53 100         if (csv->undef_str) {
1192 8           byte *ptr = csv->undef_str;
1193 8           STRLEN len = strlen ((char *)ptr);
1194              
1195 8 100         if (csv->undef_flg) {
1196 3           csv->utf8 = 1;
1197 3           csv->binary = 1;
1198             }
1199              
1200 53852 100         while (len--)
1201 20 50         CSV_PUT (csv, dst, *ptr++);
    0          
1202             }
1203             }
1204             }
1205 21636 100         if (csv->eol_len) {
1206 249           STRLEN len = csv->eol_len;
1207 249           byte *ptr = csv->eol;
1208              
1209 696 100         while (len--)
1210 447 50         CSV_PUT (csv, dst, *ptr++);
    0          
1211             }
1212 21636 100         if (csv->used)
1213 21634           return Print (csv, dst);
1214 2           return TRUE;
1215             } /* Combine */
1216              
1217             #define ParseError(csv,xse,pos) cx_ParseError (aTHX_ csv, xse, pos)
1218 299           static void cx_ParseError (pTHX_ csv_t *csv, int xse, STRLEN pos) {
1219 299           (void)hv_store (csv->self, "_ERROR_POS", 10, newSViv (pos), 0);
1220 299           (void)hv_store (csv->self, "_ERROR_FLD", 10, newSViv (csv->fld_idx), 0);
1221 299 50         if (csv->tmp) {
1222 299           csv->has_error_input = 1;
1223 299 50         if (hv_store (csv->self, "_ERROR_INPUT", 12, csv->tmp, 0))
1224 299           SvREFCNT_inc (csv->tmp);
1225             }
1226 299           (void)SetDiag (csv, xse);
1227 296           } /* ParseError */
1228              
1229             #define CsvGet(csv,src) cx_CsvGet (aTHX_ csv, src)
1230 4868           static int cx_CsvGet (pTHX_ csv_t *csv, SV *src) {
1231 4868 100         unless (csv->useIO)
1232 1518           return EOF;
1233              
1234 3350 100         if (csv->tmp && csv->eol_pos >= 0) {
    100          
1235 348           csv->eol_pos = -2;
1236 348           sv_setpvn (csv->tmp, (char *)csv->eol, csv->eol_len);
1237 348 50         csv->bptr = SvPV (csv->tmp, csv->size);
1238 348           csv->used = 0;
1239 348           return CH_EOLX;
1240             }
1241              
1242             { STRLEN result;
1243 3002           dSP;
1244              
1245 3002 50         PUSHMARK (sp);
1246 3002 50         EXTEND (sp, 1);
1247 3002           PUSHs (src);
1248 3002           PUTBACK;
1249 3002           result = call_sv (m_getline, G_METHOD);
1250 3002           SPAGAIN;
1251 3002           csv->eol_pos = -1;
1252 3002 50         csv->tmp = result ? POPs : NULL;
1253 3002           PUTBACK;
1254              
1255             #if MAINT_DEBUG > 4
1256             (void)fprintf (stderr, "getline () returned:\n");
1257             sv_dump (csv->tmp);
1258             #endif
1259             }
1260 3002 50         if (csv->tmp && SvOK (csv->tmp)) {
    100          
    50          
    50          
1261             STRLEN tmp_len;
1262 2453 50         csv->bptr = SvPV (csv->tmp, tmp_len);
1263 2453           csv->used = 0;
1264 2453           csv->size = tmp_len;
1265 2453 100         if (csv->eolx && csv->size >= csv->eol_len) {
    50          
1266 358           int i, match = 1;
1267 1817 100         for (i = 1; i <= (int)csv->eol_len; i++) {
1268 1463 100         unless (csv->bptr[csv->size - i] == csv->eol[csv->eol_len - i]) {
1269 4           match = 0;
1270 4           break;
1271             }
1272             }
1273 358 100         if (match) {
1274             #if MAINT_DEBUG > 4
1275             (void)fprintf (stderr, "# EOLX match, size: %d\n", csv->size);
1276             #endif
1277 354           csv->size -= csv->eol_len;
1278 354 100         unless (csv->verbatim)
1279 351           csv->eol_pos = csv->size;
1280 354           csv->bptr[csv->size] = (char)0;
1281 354           SvCUR_set (csv->tmp, csv->size);
1282 354 100         unless (csv->verbatim || csv->size)
    100          
1283 2453           return CH_EOLX;
1284             }
1285             }
1286 2447 100         if (SvUTF8 (csv->tmp)) csv->utf8 = 1;
1287 2447 50         if (tmp_len)
1288 2447           return ((byte)csv->bptr[csv->used++]);
1289             }
1290 549           csv->useIO |= useIO_EOF;
1291 549           return EOF;
1292             } /* CsvGet */
1293              
1294             #define ERROR_INSIDE_QUOTES(diag_code) { \
1295             unless (csv->is_bound) SvREFCNT_dec (sv); \
1296             ParseError (csv, diag_code, csv->used - 1); \
1297             return FALSE; \
1298             }
1299             #define ERROR_INSIDE_FIELD(diag_code) { \
1300             unless (csv->is_bound) SvREFCNT_dec (sv); \
1301             ParseError (csv, diag_code, csv->used - 1); \
1302             return FALSE; \
1303             }
1304              
1305             #if MAINT_DEBUG > 4
1306             #define PUT_RPT (void)fprintf (stderr, "# CSV_PUT @ %4d: 0x%02x '%c'\n", __LINE__, c, isprint (c) ? c : '?')
1307             #define PUT_SEPX_RPT1 (void)fprintf (stderr, "# PUT SEPX @ %4d\n", __LINE__)
1308             #define PUT_SEPX_RPT2 (void)fprintf (stderr, "# Done putting SEPX\n")
1309             #define PUT_QUOX_RPT1 (void)fprintf (stderr, "# PUT QUOX @ %4d\n", __LINE__)
1310             #define PUT_QUOX_RPT2 (void)fprintf (stderr, "# Done putting QUOX\n")
1311             #define PUT_EOLX_RPT1 (void)fprintf (stderr, "# PUT EOLX @ %4d\n", __LINE__)
1312             #define PUT_EOLX_RPT2 (void)fprintf (stderr, "# Done putting EOLX\n")
1313             #define PUSH_RPT (void)fprintf (stderr, "# AV_PUSHd @ %4d\n", __LINE__); sv_dump (sv)
1314             #else
1315             #define PUT_RPT
1316             #define PUT_SEPX_RPT1
1317             #define PUT_SEPX_RPT2
1318             #define PUT_QUOX_RPT1
1319             #define PUT_QUOX_RPT2
1320             #define PUT_EOLX_RPT1
1321             #define PUT_EOLX_RPT2
1322             #define PUSH_RPT
1323             #endif
1324             #define CSV_PUT_SV1(c) { \
1325             len = SvCUR ((sv)); \
1326             SvGROW ((sv), len + 2); \
1327             *SvEND ((sv)) = c; \
1328             PUT_RPT; \
1329             SvCUR_set ((sv), len + 1); \
1330             }
1331             #define CSV_PUT_SV(c) { \
1332             if (c == CH_EOLX) { \
1333             int x; PUT_EOLX_RPT1; \
1334             if (csv->eol_pos == -2) \
1335             csv->size = 0; \
1336             for (x = 0; x < (int)csv->eol_len; x++) \
1337             CSV_PUT_SV1 (csv->eol[x]); \
1338             csv->eol_pos = -1; \
1339             PUT_EOLX_RPT2; \
1340             } \
1341             else if (c == CH_SEPX) { \
1342             int x; PUT_SEPX_RPT1; \
1343             for (x = 0; x < (int)csv->sep_len; x++) \
1344             CSV_PUT_SV1 (csv->sep[x]); \
1345             PUT_SEPX_RPT2; \
1346             } \
1347             else if (c == CH_QUOTEX) { \
1348             int x; PUT_QUOX_RPT1; \
1349             for (x = 0; x < (int)csv->quo_len; x++) \
1350             CSV_PUT_SV1 (csv->quo[x]); \
1351             PUT_QUOX_RPT2; \
1352             } \
1353             else \
1354             CSV_PUT_SV1 (c); \
1355             }
1356              
1357             #define CSV_GET1 \
1358             (csv->used < csv->size ? (byte)csv->bptr[csv->used++] : CsvGet (csv, src))
1359              
1360             #if MAINT_DEBUG > 3
1361             int CSV_GET_ (pTHX_ csv_t *csv, SV *src, int l) {
1362             int c;
1363             (void)fprintf (stderr, "# 1-CSV_GET @ %4d: (used: %d, size: %d, eol_pos: %d, eolx = %d)\n", l, csv->used, csv->size, csv->eol_pos, csv->eolx);
1364             c = CSV_GET1;
1365             (void)fprintf (stderr, "# 2-CSV_GET @ %4d: 0x%02x '%c'\n", l, c, isprint (c) ? c : '?');
1366             return (c);
1367             } /* CSV_GET_ */
1368             #define CSV_GET CSV_GET_ (aTHX_ csv, src, __LINE__)
1369             #else
1370             #define CSV_GET CSV_GET1
1371             #endif
1372              
1373             #define AV_PUSH { \
1374             int svc; \
1375             *SvEND (sv) = (char)0; \
1376             svc = SvCUR (sv); \
1377             SvUTF8_off (sv); \
1378             if (svc && csv->formula && *(SvPV_nolen (sv)) == '=') \
1379             (void)_formula (csv, sv, NULL, fnum); \
1380             if (svc == 0 && ( \
1381             csv->empty_is_undef || \
1382             (!(f & CSV_FLAGS_QUO) && csv->blank_is_undef))) \
1383             SvSetUndef (sv); \
1384             else { \
1385             if (csv->allow_whitespace && ! (f & CSV_FLAGS_QUO)) \
1386             strip_trail_whitespace (sv); \
1387             if (f & CSV_FLAGS_BIN && csv->decode_utf8 \
1388             && (csv->utf8 || is_utf8_sv (sv))) \
1389             SvUTF8_on (sv); \
1390             } \
1391             SvSETMAGIC (sv); \
1392             unless (csv->is_bound) av_push (fields, sv); \
1393             PUSH_RPT; \
1394             sv = NULL; \
1395             if (csv->keep_meta_info && fflags) \
1396             av_push (fflags, newSViv (f)); \
1397             waitingForField = 1; \
1398             }
1399              
1400             #define strip_trail_whitespace(sv) cx_strip_trail_whitespace (aTHX_ sv)
1401 1723           static void cx_strip_trail_whitespace (pTHX_ SV *sv) {
1402             STRLEN len;
1403 1723 50         char *s = SvPV (sv, len);
1404 1723 50         unless (s && len) return;
    50          
1405 1899 100         while (s[len - 1] == CH_SPACE || s[len - 1] == CH_TAB)
    50          
1406 176           s[--len] = (char)0;
1407 1723           SvCUR_set (sv, len);
1408             } /* strip_trail_whitespace */
1409              
1410             #define NewField \
1411             unless (sv) { \
1412             if (csv->is_bound) \
1413             sv = bound_field (csv, fnum, 0); \
1414             else \
1415             sv = newSVpvs (""); \
1416             fnum++; \
1417             unless (sv) return FALSE; \
1418             f = 0; csv->fld_idx++; \
1419             }
1420              
1421             #if MAINT_DEBUG
1422             static char str_parsed[40];
1423             #endif
1424              
1425             #if MAINT_DEBUG > 1
1426             static char *_sep_string (csv_t *csv) {
1427             char sep[64];
1428             if (csv->sep_len) {
1429             int x;
1430             for (x = 0; x < csv->sep_len; x++)
1431             (void)sprintf (sep + x * x, "%02x ", csv->sep[x]);
1432             }
1433             else
1434             (void)sprintf (sep, "'%c' (0x%02x)", CH_SEP, CH_SEP);
1435             return sep;
1436             } /* _sep_string */
1437             #endif
1438              
1439             #define Parse(csv,src,fields,fflags) cx_Parse (aTHX_ csv, src, fields, fflags)
1440 4554           static int cx_Parse (pTHX_ csv_t *csv, SV *src, AV *fields, AV *fflags) {
1441 4554           int c, f = 0;
1442 4554           int waitingForField = 1;
1443 4554           SV *sv = NULL;
1444             STRLEN len;
1445 4554           int seenSomething = FALSE;
1446 4554           int fnum = 0;
1447 4554           int spl = -1;
1448             #if MAINT_DEBUG
1449             (void)memset (str_parsed, 0, 40);
1450             #endif
1451              
1452 4554           csv->fld_idx = 0;
1453              
1454 186728 100         while ((c = CSV_GET) != EOF) {
    100          
1455              
1456 185991 100         NewField;
    100          
    100          
1457              
1458 185987           seenSomething = TRUE;
1459 185987           spl++;
1460             #if MAINT_DEBUG
1461             if (spl < 39) str_parsed[spl] = c;
1462             #endif
1463             restart:
1464             #if MAINT_DEBUG > 9
1465             (void)fprintf (stderr, "# at restart: %d/%d/%03x pos %d = 0x%02x\n",
1466             waitingForField ? 1 : 0, sv ? 1 : 0, f, spl, c);
1467             #endif
1468 196721 100         if (is_SEP (c)) {
    100          
    50          
    100          
    50          
1469             #if MAINT_DEBUG > 1
1470             (void)fprintf (stderr, "# %d/%d/%03x pos %d = SEP %s\t%s\n",
1471             waitingForField ? 1 : 0, sv ? 1 : 0, f, spl,
1472             _sep_string (csv), _pretty_strl (csv->bptr + csv->used));
1473             #endif
1474 23634 100         if (waitingForField) {
1475             /* ,1,"foo, 3",,bar,
1476             * ^ ^
1477             */
1478 1170 100         if (csv->blank_is_undef || csv->empty_is_undef)
    100          
1479 50           SvSetUndef (sv);
1480             else
1481 1120           SvSetEmpty (sv);
1482 1170 50         unless (csv->is_bound)
1483 1170           av_push (fields, sv);
1484 1170           sv = NULL;
1485 1170 100         if (csv->keep_meta_info && fflags)
    50          
1486 1170           av_push (fflags, newSViv (f));
1487             }
1488             else
1489 10648 100         if (f & CSV_FLAGS_QUO) {
1490             /* ,1,"foo, 3",,bar,
1491             * ^
1492             */
1493 2194 50         CSV_PUT_SV (c)
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    100          
1494             }
1495             else {
1496             /* ,1,"foo, 3",,bar,
1497             * ^ ^ ^
1498             */
1499 8454 100         AV_PUSH;
    100          
    50          
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    100          
    100          
    100          
    50          
1500             }
1501             } /* SEP char */
1502             else
1503 184903 100         if (is_QUOTE (c)) {
    100          
    100          
    50          
    100          
    50          
1504             #if MAINT_DEBUG > 1
1505             (void)fprintf (stderr, "# %d/%d/%03x pos %d = QUO '%c'\t\t%s\n",
1506             waitingForField ? 1 : 0, sv ? 1 : 0, f, spl, c,
1507             _pretty_strl (csv->bptr + csv->used));
1508             #endif
1509 22820 100         if (waitingForField) {
1510             /* ,1,"foo, 3",,bar,\r\n
1511             * ^
1512             */
1513 10904           f |= CSV_FLAGS_QUO;
1514 10904           waitingForField = 0;
1515 10904           continue;
1516             }
1517              
1518 11916 100         if (f & CSV_FLAGS_QUO) {
1519              
1520             /* ,1,"foo, 3",,bar,\r\n
1521             * ^
1522             */
1523              
1524 11850           int quoesc = 0;
1525 11850 100         int c2 = CSV_GET;
1526              
1527 11850 100         if (csv->allow_whitespace) {
1528             /* , 1 , "foo, 3" , , bar , \r\n
1529             * ^
1530             */
1531 4330 100         while (is_whitespace (c2)) {
    100          
    50          
    100          
    100          
1532 90 100         if (csv->allow_loose_quotes &&
    50          
1533 0 0         !(csv->escape_char && c2 == csv->escape_char)) {
1534             /* This feels like a brittle fix for RT115953, where
1535             * ["foo "bar" baz"] got parsed as [foo "bar"baz]
1536             * when both allow_whitespace and allow_loose_quotes
1537             * are true and escape does not equal quote
1538             */
1539 1 50         CSV_PUT_SV (c);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
1540 1           c = c2;
1541             }
1542 90 100         c2 = CSV_GET;
1543             }
1544             }
1545              
1546 11850 100         if (is_SEP (c2)) {
    100          
    50          
    50          
    50          
1547             /* ,1,"foo, 3",,bar,\r\n
1548             * ^
1549             */
1550 9014 100         AV_PUSH;
    50          
    0          
    0          
    100          
    100          
    50          
    0          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
1551 9014           continue;
1552             }
1553              
1554 2836 100         if (c2 == CH_NL || c2 == CH_EOLX) {
    100          
1555             /* ,1,"foo, 3",,"bar"\n
1556             * ^
1557             */
1558 195 100         AV_PUSH;
    50          
    0          
    0          
    100          
    50          
    50          
    0          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
1559 195           return TRUE;
1560             }
1561              
1562             /* ---
1563             * if QUOTE eq ESCAPE
1564             * AND ( c2 eq QUOTE 1,"abc""def",2
1565             * OR c2 eq ESCAPE 1,"abc""def",2 (QUO eq ESC)
1566             * OR c2 eq NULL ) 1,"abc"0def",2
1567             * ---
1568             */
1569 2641 100         if (csv->escape_char && c == csv->escape_char) {
    100          
1570              
1571 1544           quoesc = 1;
1572 1544 100         if (c2 == '0') {
1573             /* ,1,"foo, 3"056",,bar,\r\n
1574             * ^
1575             */
1576 25 50         CSV_PUT_SV (0)
    50          
1577 25           continue;
1578             }
1579              
1580 1519 50         if (is_QUOTE (c2)) {
    100          
    50          
    0          
    0          
    0          
1581             /* ,1,"foo, 3""56",,bar,\r\n
1582             * ^
1583             */
1584 1056 100         if (csv->utf8)
1585 1           f |= CSV_FLAGS_BIN;
1586 1056 50         CSV_PUT_SV (c2)
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    100          
1587 1056           continue;
1588             }
1589              
1590 463 100         if (csv->allow_loose_escapes && c2 != CH_CR) {
    100          
1591             /* ,1,"foo, 3"56",,bar,\r\n
1592             * ^
1593             */
1594 2 50         CSV_PUT_SV (c);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
1595 2           c = c2;
1596 2           goto restart;
1597             }
1598             }
1599              
1600 1558 100         if (c2 == CH_CR) {
1601             int c3;
1602              
1603 197 100         if (csv->eol_is_cr) {
1604             /* ,1,"foo, 3"\r
1605             * ^
1606             */
1607 102 100         AV_PUSH;
    50          
    0          
    0          
    100          
    50          
    50          
    0          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
1608 102           return TRUE;
1609             }
1610              
1611 95 100         c3 = CSV_GET;
1612              
1613 95 100         if (c3 == CH_NL) { /* \r is not optional before EOLX! */
1614             /* ,1,"foo, 3"\r\n
1615             * ^
1616             */
1617 81 100         AV_PUSH;
    50          
    0          
    0          
    100          
    50          
    50          
    0          
    100          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    0          
1618 81           return TRUE;
1619             }
1620              
1621 14 100         if (csv->useIO && csv->eol_len == 0) {
    50          
1622 1 50         if (c3 == CH_CR) { /* \r followed by an empty line */
1623             /* ,1,"foo, 3"\r\r
1624             * ^
1625             */
1626 0           set_eol_is_cr (csv);
1627 0           goto EOLX;
1628             }
1629              
1630 1 50         if (!is_csv_binary (c3)) {
    50          
    0          
1631             /* ,1,"foo\n 3",,"bar"\r
1632             * baz,4
1633             * ^
1634             */
1635 1           set_eol_is_cr (csv);
1636 1           csv->used--;
1637 1           csv->has_ahead++;
1638 1 50         AV_PUSH;
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
1639 1           return TRUE;
1640             }
1641             }
1642              
1643 13 100         ParseError (csv, quoesc ? 2023 : 2010, csv->used - 2);
1644 13           return FALSE;
1645             }
1646              
1647 1361 100         if (c2 == EOF) {
1648             /* ,1,"foo, 3"
1649             * ^
1650             */
1651 1304 100         AV_PUSH;
    50          
    0          
    0          
    100          
    50          
    50          
    0          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    50          
    100          
    50          
1652 1304           return TRUE;
1653             }
1654              
1655 57 100         if (csv->allow_loose_quotes && !quoesc) {
    100          
1656             /* ,1,"foo, 3"456",,bar,\r\n
1657             * ^
1658             */
1659 10 50         CSV_PUT_SV (c);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    100          
1660 10           c = c2;
1661 10           goto restart;
1662             }
1663              
1664             /* 1,"foo" ",3
1665             * ^
1666             */
1667 47 100         if (quoesc) {
1668 39           csv->used--;
1669 39 50         ERROR_INSIDE_QUOTES (2023);
1670             }
1671              
1672 8 50         ERROR_INSIDE_QUOTES (2011);
1673             }
1674              
1675             /* !waitingForField, !InsideQuotes */
1676 82 100         if (csv->allow_loose_quotes) { /* 1,foo "boo" d'uh,1 */
1677 16           f |= CSV_FLAGS_EIF; /* Mark as error-in-field */
1678 16 50         CSV_PUT_SV (c);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
1679             }
1680             else
1681 50 100         ERROR_INSIDE_FIELD (2034);
1682             } /* QUO char */
1683             else
1684 162083 100         if (c == csv->escape_char && csv->escape_char) {
    100          
1685             #if MAINT_DEBUG > 1
1686             (void)fprintf (stderr, "# %d/%d/%03x pos %d = ESC '%c'\t%s\n",
1687             waitingForField ? 1 : 0, sv ? 1 : 0, f, spl, c,
1688             _pretty_strl (csv->bptr + csv->used));
1689             #endif
1690             /* This means quote_char != escape_char */
1691 9268 100         if (waitingForField) {
1692 33           waitingForField = 0;
1693 33 100         if (csv->allow_unquoted_escape) {
1694             /* The escape character is the first character of an
1695             * unquoted field */
1696             /* ... get and store next character */
1697 3 100         int c2 = CSV_GET;
1698              
1699 3           SvSetEmpty (sv);
1700              
1701 3 100         if (c2 == EOF) {
1702 1           csv->used--;
1703 1 50         ERROR_INSIDE_FIELD (2035);
1704             }
1705              
1706 2 100         if (c2 == '0')
1707 1 50         CSV_PUT_SV (0)
    50          
1708             else
1709 1 50         if ( is_QUOTE (c2) || is_SEP (c2) ||
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
1710 0 0         c2 == csv->escape_char || csv->allow_loose_escapes) {
1711 1 50         if (csv->utf8)
1712 0           f |= CSV_FLAGS_BIN;
1713 1 50         CSV_PUT_SV (c2)
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
1714             }
1715             else {
1716 0           csv->used--;
1717 32 0         ERROR_INSIDE_QUOTES (2025);
1718             }
1719             }
1720             }
1721             else
1722 4618 100         if (f & CSV_FLAGS_QUO) {
1723 4610 100         int c2 = CSV_GET;
1724              
1725 4610 100         if (c2 == EOF) {
1726 3           csv->used--;
1727 3 50         ERROR_INSIDE_QUOTES (2024);
1728             }
1729              
1730 4607 100         if (c2 == '0')
1731 2 50         CSV_PUT_SV (0)
    50          
1732             else
1733 4605 50         if ( is_QUOTE (c2) || is_SEP (c2) ||
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    0          
    0          
    0          
    100          
1734 28 100         c2 == csv->escape_char || csv->allow_loose_escapes) {
1735 4579 100         if (csv->utf8)
1736 1           f |= CSV_FLAGS_BIN;
1737 4582 50         CSV_PUT_SV (c2)
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    100          
    50          
    50          
    100          
    50          
    100          
1738             }
1739             else {
1740 26           csv->used--;
1741 4607 50         ERROR_INSIDE_QUOTES (2025);
1742             }
1743             }
1744             else
1745 8 50         if (sv) {
1746 8 100         int c2 = CSV_GET;
1747              
1748 8 100         if (c2 == EOF) {
1749 4           csv->used--;
1750 4 50         ERROR_INSIDE_FIELD (2035);
1751             }
1752              
1753 4 50         CSV_PUT_SV (c2);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
1754             }
1755             else
1756 0 0         ERROR_INSIDE_FIELD (2036); /* uncoverable statement I think there's no way to get here */
1757             } /* ESC char */
1758             else
1759 157432 100         if (c == CH_NL || is_EOL (c)) {
    100          
1760             EOLX:
1761             #if MAINT_DEBUG > 1
1762             (void)fprintf (stderr, "# %d/%d/%03x pos %d = NL\t%s\n",
1763             waitingForField ? 1 : 0, sv ? 1 : 0, f, spl,
1764             _pretty_strl (csv->bptr + csv->used));
1765             #endif
1766 2638 100         if (fnum == 1 && f == 0 && SvCUR (sv) == 0 && csv->skip_empty_rows) {
    100          
    100          
    100          
1767 91 100         SkipEmptyRow;
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    100          
    50          
    50          
    50          
    50          
    0          
    50          
    50          
    50          
    100          
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    100          
1768 37           goto restart;
1769             }
1770              
1771 2579 100         if (waitingForField) {
1772             /* ,1,"foo, 3",,bar,
1773             * ^
1774             */
1775 226 100         if (csv->blank_is_undef || csv->empty_is_undef)
    100          
1776 16           SvSetUndef (sv);
1777             else
1778 210           SvSetEmpty (sv);
1779 226 50         unless (csv->is_bound)
1780 226           av_push (fields, sv);
1781 226 100         if (csv->keep_meta_info && fflags)
    50          
1782 14           av_push (fflags, newSViv (f));
1783 226           return TRUE;
1784             }
1785              
1786 3086 100         if (f & CSV_FLAGS_QUO) {
1787             /* ,1,"foo\n 3",,bar,
1788             * ^
1789             */
1790 744           f |= CSV_FLAGS_BIN;
1791 744 100         unless (csv->binary)
1792 19 50         ERROR_INSIDE_QUOTES (2021);
1793              
1794 799 100         CSV_PUT_SV (c);
    100          
    50          
    50          
    100          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
1795             }
1796             else
1797 1609 100         if (csv->verbatim) {
1798             /* ,1,foo\n 3,,bar,
1799             * This feature should be deprecated
1800             */
1801 9           f |= CSV_FLAGS_BIN;
1802 9 100         unless (csv->binary)
1803 1 50         ERROR_INSIDE_FIELD (2030);
1804              
1805 14 100         CSV_PUT_SV (c);
    50          
    50          
    100          
    100          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
1806             }
1807             else {
1808             /* sep=,
1809             * ^
1810             */
1811 1600 100         if (csv->recno == 0 && csv->fld_idx == 1 && csv->useIO &&
    100          
    50          
    100          
1812 28 50         (csv->bptr[0] == 's' || csv->bptr[0] == 'S') &&
    50          
1813 5 0         (csv->bptr[1] == 'e' || csv->bptr[1] == 'E') &&
    50          
1814 5 0         (csv->bptr[2] == 'p' || csv->bptr[2] == 'P') &&
    50          
1815 5           csv->bptr[3] == '=') {
1816 5           char *sep = csv->bptr + 4;
1817 5           int lnu = csv->used - 5;
1818 5 100         if (lnu <= MAX_ATTR_LEN) {
1819 4           sep[lnu] = (char)0;
1820 4           (void)memcpy (csv->sep, sep, lnu);
1821 4 100         csv->sep_len = lnu == 1 ? 0 : lnu;
1822 4           return Parse (csv, src, fields, fflags);
1823             }
1824             }
1825              
1826             /* ,1,"foo\n 3",,bar
1827             * ^
1828             */
1829 1596 100         AV_PUSH;
    100          
    50          
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    100          
    100          
    100          
    50          
1830 1596           return TRUE;
1831             }
1832             } /* CH_NL */
1833             else
1834 155257 100         if (c == CH_CR && !(csv->verbatim)) {
    100          
1835             #if MAINT_DEBUG > 1
1836             (void)fprintf (stderr, "# %d/%d/%03x pos %d = CR\n",
1837             waitingForField ? 1 : 0, sv ? 1 : 0, f, spl);
1838             #endif
1839 1106 100         if (waitingForField) {
1840             int c2;
1841              
1842 117 100         if (csv->eol_is_cr) {
1843             /* ,1,"foo\n 3",,bar,\r
1844             * ^
1845             */
1846 29           c = CH_NL;
1847 29           goto EOLX;
1848             }
1849              
1850 88 100         c2 = CSV_GET;
1851              
1852 88 100         if (c2 == EOF) {
1853             /* ,1,"foo\n 3",,bar,\r
1854             * ^
1855             */
1856 5           c = EOF;
1857              
1858             #if MAINT_DEBUG > 9
1859             (void)fprintf (stderr, "# (%d) ... CR EOF 0x%x\n",
1860             seenSomething, c);
1861             #endif
1862 5 50         unless (seenSomething)
1863 0           break;
1864 5           goto restart;
1865             }
1866              
1867 83 100         if (c2 == CH_NL) { /* \r is not optional before EOLX! */
1868             /* ,1,"foo\n 3",,bar,\r\n
1869             * ^
1870             */
1871 73           c = c2;
1872 73           goto EOLX;
1873             }
1874              
1875 10 100         if (csv->useIO && csv->eol_len == 0) {
    50          
1876 5 50         if (c2 == CH_CR) { /* \r followed by an empty line */
1877             /* ,1,"foo\n 3",,bar,\r\r
1878             * ^
1879             */
1880 0           set_eol_is_cr (csv);
1881 0           goto EOLX;
1882             }
1883              
1884 5           waitingForField = 0;
1885              
1886 5 100         if (!is_csv_binary (c2)) {
    50          
    50          
1887             /* ,1,"foo\n 3",,bar,\r
1888             * baz,4
1889             * ^
1890             */
1891 2           set_eol_is_cr (csv);
1892 2           csv->used--;
1893 2           csv->has_ahead++;
1894 2 100         if (fnum == 1 && f == 0 && SvCUR (sv) == 0 && csv->skip_empty_rows) {
    50          
    50          
    50          
1895 1 50         SkipEmptyRow;
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1896 1           goto restart;
1897             }
1898 1 50         AV_PUSH;
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
1899 1           return TRUE;
1900             }
1901             }
1902              
1903             /* ,1,"foo\n 3",,bar,\r\t
1904             * ^
1905             */
1906 8           csv->used--;
1907 8 50         ERROR_INSIDE_FIELD (2031);
1908             }
1909              
1910 1539 100         if (f & CSV_FLAGS_QUO) {
1911             /* ,1,"foo\r 3",,bar,\r\t
1912             * ^
1913             */
1914 620           f |= CSV_FLAGS_BIN;
1915 620 100         unless (csv->binary)
1916 70 50         ERROR_INSIDE_QUOTES (2022);
1917              
1918 550 50         CSV_PUT_SV (c);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    100          
1919             }
1920             else {
1921             int c2;
1922              
1923 369 100         if (csv->eol_is_cr) {
1924             /* ,1,"foo\n 3",,bar\r
1925             * ^
1926             */
1927 181           goto EOLX;
1928             }
1929              
1930 188 100         c2 = CSV_GET;
1931              
1932 188 100         if (c2 == CH_NL) { /* \r is not optional before EOLX! */
1933             /* ,1,"foo\n 3",,bar\r\n
1934             * ^
1935             */
1936 172           goto EOLX;
1937             }
1938              
1939 16 100         if (csv->useIO && csv->eol_len == 0) {
    50          
1940 11 100         if (!is_csv_binary (c2)
    50          
    50          
1941             /* ,1,"foo\n 3",,bar\r
1942             * baz,4
1943             * ^
1944             */
1945 7 100         || c2 == CH_CR) {
1946             /* ,1,"foo\n 3",,bar,\r\r
1947             * ^
1948             */
1949 5           set_eol_is_cr (csv);
1950 5           csv->used--;
1951 5           csv->has_ahead++;
1952 5 50         if (fnum == 1 && f == 0 && SvCUR (sv) == 0 && csv->skip_empty_rows) {
    0          
    0          
    0          
1953 0 0         SkipEmptyRow;
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1954 0           goto restart;
1955             }
1956 5 50         AV_PUSH;
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
1957 5           return TRUE;
1958             }
1959             }
1960              
1961             /* ,1,"foo\n 3",,bar\r\t
1962             * ^
1963             */
1964 11 50         ERROR_INSIDE_FIELD (2032);
1965             }
1966             } /* CH_CR */
1967             else {
1968             #if MAINT_DEBUG > 1
1969             (void)fprintf (stderr, "# %d/%d/%03x pos %d = CCC '%c'\t\t%s\n",
1970             waitingForField ? 1 : 0, sv ? 1 : 0, f, spl, c,
1971             _pretty_strl (csv->bptr + csv->used));
1972             #endif
1973             /* Needed for non-IO parse, where EOL is not set during read */
1974 154151 100         if (csv->eolx && c == CH_EOL &&
    100          
    50          
1975 8 50         csv->size - csv->used >= (STRLEN)csv->eol_len - 1 &&
1976 8 50         !memcmp (csv->bptr + csv->used, csv->eol + 1, csv->eol_len - 1) &&
1977 8           (csv->used += csv->eol_len - 1)) {
1978 8           c = CH_EOLX;
1979             #if MAINT_DEBUG > 5
1980             (void)fprintf (stderr, "# -> EOLX (0x%x)\n", c);
1981             #endif
1982 8           goto EOLX;
1983             }
1984              
1985 154143 100         if (waitingForField) {
1986 10680 100         if (csv->comment_str && !f && !spl && c == *csv->comment_str) {
    50          
    100          
    100          
1987 24           STRLEN cl = strlen ((char *)csv->comment_str);
1988              
1989             #if MAINT_DEBUG > 5
1990             (void)fprintf (stderr,
1991             "COMMENT? cl = %d, size = %d, used = %d\n",
1992             cl, csv->size, csv->used);
1993             #endif
1994 24 100         if (cl == 1 || (
    50          
1995 18 50         (csv->size - csv->used >= cl - 1 &&
1996 18 50         !memcmp (csv->bptr + csv->used, csv->comment_str + 1, cl - 1) &&
1997 18           (csv->used += cl - 1)))) {
1998 24           csv->used = csv->size;
1999 24           csv->fld_idx = 0;
2000 24 50         c = CSV_GET;
2001             #if MAINT_DEBUG > 5
2002             (void)fprintf (stderr, "# COMMENT, SKIPPED\n");
2003             #endif
2004 24           goto restart;
2005             }
2006             }
2007              
2008 10656 100         if (csv->allow_whitespace && is_whitespace (c)) {
    50          
    50          
    50          
    100          
    50          
2009             do {
2010 311 100         c = CSV_GET;
2011             #if MAINT_DEBUG > 5
2012             (void)fprintf (stderr, "# WS next got (0x%x)\n", c);
2013             #endif
2014 311 100         } while (is_whitespace (c));
    100          
    50          
    100          
    50          
2015 201 100         if (c == EOF)
2016 1           break;
2017 200           goto restart;
2018             }
2019 10455           waitingForField = 0;
2020 10455           goto restart;
2021             }
2022              
2023             #if MAINT_DEBUG > 5
2024             (void)fprintf (stderr, "# %sc 0x%x is%s binary %s utf8\n",
2025             f & CSV_FLAGS_QUO ? "quoted " : "", c,
2026             is_csv_binary (c) ? "" : " not",
2027             csv->utf8 ? "is" : "not");
2028             #endif
2029 143463 100         if (f & CSV_FLAGS_QUO) {
2030 111032 100         if (is_csv_binary (c)) {
    100          
    100          
2031 3454           f |= CSV_FLAGS_BIN;
2032 3454 100         unless (csv->binary || csv->utf8)
    100          
2033 5 50         ERROR_INSIDE_QUOTES (2026);
2034             }
2035 111027 50         CSV_PUT_SV (c);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    100          
2036             }
2037             else {
2038 32431 100         if (is_csv_binary (c)) {
    100          
    100          
2039 453 100         if (csv->useIO && c == EOF)
    100          
2040 3           break;
2041 450           f |= CSV_FLAGS_BIN;
2042 450 100         unless (csv->binary || csv->utf8)
    50          
2043 9 50         ERROR_INSIDE_FIELD (2037);
2044             }
2045 32419 50         CSV_PUT_SV (c);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    100          
2046             }
2047             }
2048              
2049             /* continue */
2050 161178 100         if (csv->verbatim && csv->useIO && csv->used == csv->size)
    100          
    100          
2051 3           break;
2052             }
2053              
2054 746 100         if (waitingForField) {
2055 366 100         if (seenSomething || !csv->useIO) {
    100          
2056 34 100         NewField;
    100          
    50          
2057 34 100         if (csv->blank_is_undef || csv->empty_is_undef)
    100          
2058 8           SvSetUndef (sv);
2059             else
2060 26           SvSetEmpty (sv);
2061 34 100         unless (csv->is_bound)
2062 33           av_push (fields, sv);
2063 34 100         if (csv->keep_meta_info && fflags)
    50          
2064 3           av_push (fflags, newSViv (f));
2065 34           return TRUE;
2066             }
2067              
2068 332           (void)SetDiag (csv, 2012);
2069 332           return FALSE;
2070             }
2071              
2072 380 100         if (f & CSV_FLAGS_QUO)
2073 24 50         ERROR_INSIDE_QUOTES (2027);
2074              
2075 356 100         if (sv) {
2076 354 100         AV_PUSH;
    100          
    50          
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    100          
    100          
    100          
    50          
2077             }
2078 2 50         else if (f == 0 && fnum == 1 && csv->skip_empty_rows == 1)
    50          
    50          
2079 2           return FALSE;
2080 354           return TRUE;
2081             } /* Parse */
2082              
2083 125           static int hook (pTHX_ HV *hv, char *cb_name, AV *av) {
2084             SV **svp;
2085             HV *cb;
2086             int res;
2087              
2088             #if MAINT_DEBUG > 1
2089             (void)fprintf (stderr, "# HOOK %s %x\n", cb_name, av);
2090             #endif
2091 125 50         unless ((svp = hv_fetchs (hv, "callbacks", FALSE)) && _is_hashref (*svp))
    50          
    50          
    0          
    50          
    50          
2092 0           return 0; /* uncoverable statement defensive programming */
2093              
2094 125           cb = (HV *)SvRV (*svp);
2095 125           svp = hv_fetch (cb, cb_name, strlen (cb_name), FALSE);
2096 125 50         unless (svp && _is_coderef (*svp))
    50          
    50          
    0          
    50          
    50          
2097 0           return 0;
2098              
2099 125           { dSP;
2100 125           ENTER;
2101 125           SAVETMPS;
2102 125 50         PUSHMARK (SP);
2103 125 50         mXPUSHs (newRV_inc ((SV *)hv));
2104 125 50         mXPUSHs (newRV_inc ((SV *)av));
2105 125           PUTBACK;
2106 125           res = call_sv (*svp, G_SCALAR);
2107 125           SPAGAIN;
2108 125 50         if (res) {
2109 125           SV *rv = POPs;
2110 125 100         if (SvROK (rv) && (rv = SvRV (rv)) && SvPOK (rv)) {
    50          
    50          
2111 64 50         if (strcmp (SvPV_nolen (rv), "skip") == 0)
    50          
2112 64           res = 0;
2113             }
2114             }
2115 125           PUTBACK;
2116 125 50         FREETMPS;
2117 125           LEAVE;
2118             }
2119 125           return res;
2120             } /* hook */
2121              
2122             #define c_xsParse(csv,hv,av,avf,src,useIO) cx_c_xsParse (aTHX_ csv, hv, av, avf, src, useIO)
2123 4550           static int cx_c_xsParse (pTHX_ csv_t csv, HV *hv, AV *av, AV *avf, SV *src, bool useIO) {
2124 4550           int result, ahead = 0;
2125 4550           SV *pos = NULL;
2126              
2127 4550           ENTER;
2128 4550 100         if (csv.eolx || csv.eol_is_cr) {
    100          
2129             /* local $/ = $eol */
2130 849           SAVEGENERICSV (PL_rs);
2131 849           PL_rs = newSVpvn ((char *)csv.eol, csv.eol_len);
2132             }
2133              
2134 4550 100         if ((csv.useIO = useIO)) {
2135 2622           csv.tmp = NULL;
2136              
2137 2622 100         if ((ahead = csv.has_ahead)) {
2138             SV **svp;
2139 176 50         if ((svp = hv_fetchs (hv, "_AHEAD", FALSE)) && *svp) {
    50          
2140 176 100         csv.bptr = SvPV (csv.tmp = *svp, csv.size);
2141 176           csv.used = 0;
2142 176 50         if (pos && SvIV (pos) > (IV)csv.size)
    0          
    0          
2143 2622 0         sv_setiv (pos, SvIV (pos) - csv.size);
2144             }
2145             }
2146             }
2147             else {
2148 1928           csv.tmp = src;
2149 1928           csv.utf8 = SvUTF8 (src) ? 1 : 0;
2150 1928 50         csv.bptr = SvPV (src, csv.size);
2151             }
2152 4550 100         if (csv.has_error_input) {
2153 217           (void)hv_store (hv, "_ERROR_INPUT", 12, &PL_sv_undef, 0);
2154 217           csv.has_error_input = 0;
2155             }
2156              
2157 4550           result = Parse (&csv, src, av, avf);
2158 4539           (void)hv_store (hv, "_RECNO", 6, newSViv (++csv.recno), 0);
2159 4539           (void)hv_store (hv, "_EOF", 4, &PL_sv_no, 0);
2160              
2161 4539 100         if (csv.strict) {
2162 27 100         unless (csv.strict_n) csv.strict_n = (short)csv.fld_idx;
2163 27 100         if (csv.fld_idx != csv.strict_n) {
2164 12 100         unless (csv.useIO & useIO_EOF)
2165 8           ParseError (&csv, 2014, csv.used);
2166 12 100         if (last_error) /* an error callback can reset and accept */
2167 8           result = FALSE;
2168             }
2169             }
2170              
2171 4539 100         if (csv.useIO) {
2172 2651 50         if (csv.tmp && csv.used < csv.size && csv.has_ahead) {
    100          
    100          
2173 37           SV *sv = newSVpvn (csv.bptr + csv.used, csv.size - csv.used);
2174 37           (void)hv_store (hv, "_AHEAD", 6, sv, 0);
2175             }
2176             else {
2177 2577           csv.has_ahead = 0;
2178 2577 100         if (csv.useIO & useIO_EOF)
2179 549           (void)hv_store (hv, "_EOF", 4, &PL_sv_yes, 0);
2180             }
2181             /* csv.cache[CACHE_ID__has_ahead] = csv.has_ahead; */
2182 2614           (void)memcpy (csv.cache, &csv, sizeof (csv_t));
2183              
2184 2614 100         if (avf) {
2185 1580 100         if (csv.keep_meta_info)
2186 11           (void)hv_store (hv, "_FFLAGS", 7, newRV_noinc ((SV *)avf), 0);
2187             else {
2188 1569           av_undef (avf);
2189 2614           sv_free ((SV *)avf);
2190             }
2191             }
2192             }
2193             else { /* just copy to the cache */
2194 1925           SV **svp = hv_fetchs (hv, "_CACHE", FALSE);
2195              
2196 1925 50         if (svp && *svp)
    50          
2197 1925 50         csv.cache = (byte *)SvPV_nolen (*svp);
2198 1925           (void)memcpy (csv.cache, &csv, sizeof (csv_t));
2199             }
2200              
2201 4539 100         if (result && csv.types) {
    100          
2202             STRLEN i;
2203 2           STRLEN len = av_len (av);
2204             SV **svp;
2205              
2206 8 100         for (i = 0; i <= len && i <= csv.types_len; i++) {
    50          
2207 6 50         if ((svp = av_fetch (av, i, FALSE)) && *svp && SvOK (*svp)) {
    50          
    50          
    0          
    0          
2208 6           switch (csv.types[i]) {
2209             case CSV_XS_TYPE_IV:
2210             #ifdef CSV_XS_TYPE_WARN
2211 2 50         sv_setiv (*svp, SvIV (*svp));
2212             #else
2213             if (SvTRUE (*svp))
2214             sv_setiv (*svp, SvIV (*svp));
2215             else
2216             sv_setiv (*svp, 0);
2217             #endif
2218 2           break;
2219              
2220             case CSV_XS_TYPE_NV:
2221             #ifdef CSV_XS_TYPE_WARN
2222 2 50         sv_setnv (*svp, SvNV (*svp));
2223             #else
2224             if (SvTRUE (*svp))
2225             sv_setnv (*svp, SvNV (*svp));
2226             else
2227             sv_setnv (*svp, 0.0);
2228             #endif
2229 2           break;
2230              
2231             default:
2232 2           break;
2233             }
2234             }
2235             }
2236             }
2237              
2238 4539           LEAVE;
2239              
2240 4539           return result;
2241             } /* c_xsParse */
2242              
2243             #define xsParse(self,hv,av,avf,src,useIO) cx_xsParse (aTHX_ self, hv, av, avf, src, useIO)
2244 3510           static int cx_xsParse (pTHX_ SV *self, HV *hv, AV *av, AV *avf, SV *src, bool useIO) {
2245             csv_t csv;
2246             int state;
2247 3510           SetupCsv (&csv, hv, self);
2248 3510           state = c_xsParse (csv, hv, av, avf, src, useIO);
2249 3505 100         if (state && csv.has_hooks & HOOK_AFTER_PARSE)
    100          
2250 5           (void)hook (aTHX_ hv, "after_parse", av);
2251 3505 100         return (state || !last_error);
    100          
2252             } /* xsParse */
2253              
2254             /* API also offers av_clear and av_undef, but they have more overhead */
2255             #define av_empty(av) cx_av_empty (aTHX_ av)
2256 83           static void cx_av_empty (pTHX_ AV *av) {
2257 333 100         while (av_len (av) >= 0)
2258 250           sv_free (av_pop (av));
2259 83           } /* av_empty */
2260              
2261             #define xsParse_all(self,hv,io,off,len) cx_xsParse_all (aTHX_ self, hv, io, off, len)
2262 334           static SV *cx_xsParse_all (pTHX_ SV *self, HV *hv, SV *io, SV *off, SV *len) {
2263             csv_t csv;
2264 334           int n = 0, skip = 0, length = MAXINT, tail = MAXINT;
2265 334           AV *avr = newAV ();
2266 334           AV *row = newAV ();
2267              
2268 334           SetupCsv (&csv, hv, self);
2269              
2270 334 100         if (SvOK (off)) {
    50          
    50          
2271 56 100         skip = SvIV (off);
2272 56 100         if (skip < 0) {
2273 12           tail = -skip;
2274 12           skip = -1;
2275             }
2276             }
2277 334 100         if (SvOK (len))
    50          
    50          
2278 44 100         length = SvIV (len);
2279              
2280 1040 100         while (c_xsParse (csv, hv, row, NULL, io, 1)) {
2281              
2282 738           SetupCsv (&csv, hv, self);
2283              
2284 738 100         if (skip > 0) {
2285 20           skip--;
2286 20           av_empty (row); /* re-use */
2287 20           continue;
2288             }
2289              
2290 718 100         if (n++ >= tail) {
2291 12           SvREFCNT_dec (av_shift (avr));
2292 12           n--;
2293             }
2294              
2295 718 100         if (csv.has_hooks & HOOK_AFTER_PARSE) {
2296 117 100         unless (hook (aTHX_ hv, "after_parse", row)) {
2297 63           av_empty (row); /* re-use */
2298 63           continue;
2299             }
2300             }
2301 655           av_push (avr, newRV_noinc ((SV *)row));
2302              
2303 655 100         if (n >= length && skip >= 0)
    100          
2304 32           break; /* We have enough */
2305              
2306 623           row = newAV ();
2307             }
2308 336 100         while (n > length) {
2309 8           SvREFCNT_dec (av_pop (avr));
2310 8           n--;
2311             }
2312              
2313 328           return (SV *)sv_2mortal (newRV_noinc ((SV *)avr));
2314             } /* xsParse_all */
2315              
2316             #define xsCombine(self,hv,av,io,useIO) cx_xsCombine (aTHX_ self, hv, av, io, useIO)
2317 21647           static int cx_xsCombine (pTHX_ SV *self, HV *hv, AV *av, SV *io, bool useIO) {
2318             csv_t csv;
2319             int result;
2320             #if (PERL_BCDVERSION >= 0x5008000)
2321 21647           SV *ors = PL_ors_sv;
2322             #endif
2323              
2324 21647           SetupCsv (&csv, hv, self);
2325 21647           csv.useIO = useIO;
2326             #if (PERL_BCDVERSION >= 0x5008000)
2327 21647 100         if (*csv.eol)
2328 260           PL_ors_sv = NULL;
2329             #endif
2330 21647 100         if (useIO && csv.has_hooks & HOOK_BEFORE_PRINT)
    100          
2331 3           (void)hook (aTHX_ hv, "before_print", av);
2332 21647           result = Combine (&csv, io, av);
2333             #if (PERL_BCDVERSION >= 0x5008000)
2334 21643           PL_ors_sv = ors;
2335             #endif
2336 21643 100         if (result && !useIO && csv.utf8)
    100          
    100          
2337 25           sv_utf8_upgrade (io);
2338 21643           return result;
2339             } /* xsCombine */
2340              
2341             MODULE = Text::CSV_XS PACKAGE = Text::CSV_XS
2342              
2343             PROTOTYPES: DISABLE
2344              
2345             BOOT:
2346 32           m_getline = newSVpvs ("getline");
2347 32           m_print = newSVpvs ("print");
2348 32           Perl_load_module (aTHX_ PERL_LOADMOD_NOIMPORT, newSVpvs ("IO::Handle"), NULL, NULL, NULL);
2349              
2350             void
2351             SetDiag (SV *self, int xse, ...)
2352              
2353             PPCODE:
2354             HV *hv;
2355             csv_t csv;
2356              
2357 2940 50         if (SvOK (self) && SvROK (self)) {
    0          
    0          
    100          
2358 1047 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2359 1047           SetupCsv (&csv, hv, self);
2360 1047           ST (0) = SetDiag (&csv, xse);
2361             }
2362             else {
2363 1893           last_error = xse;
2364 1893           ST (0) = sv_2mortal (SvDiag (xse));
2365             }
2366              
2367 2940 100         if (xse && items > 2 && SvPOK (ST (2))) {
    100          
    50          
2368 941           sv_setpvn (ST (0), SvPVX (ST (2)), SvCUR (ST (2)));
2369 941           SvIOK_on (ST (0));
2370             }
2371              
2372 2940           XSRETURN (1);
2373             /* XS SetDiag */
2374              
2375             void
2376             error_input (SV *self)
2377              
2378             PPCODE:
2379 12 50         if (self && SvOK (self) && SvROK (self) && SvTYPE (SvRV (self)) == SVt_PVHV) {
    100          
    50          
    50          
    100          
    100          
2380 4           HV *hv = (HV *)SvRV (self);
2381 4           SV **sv = hv_fetchs (hv, "_ERROR_INPUT", FALSE);
2382 4 100         if (SvOK (*sv))
    50          
    50          
2383 3           ST (0) = *sv;
2384             else
2385 1           ST (0) = newSV (0);
2386             }
2387             else
2388 4           ST (0) = newSV (0);
2389              
2390 8           XSRETURN (1);
2391             /* XS error_input */
2392              
2393             void
2394             Combine (SV *self, SV *dst, SV *fields, bool useIO)
2395              
2396             PPCODE:
2397             HV *hv;
2398             AV *av;
2399              
2400 1396 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2401 1396           av = (AV *)SvRV (fields);
2402 1396 100         ST (0) = xsCombine (self, hv, av, dst, useIO) ? &PL_sv_yes : &PL_sv_undef;
2403 1392           XSRETURN (1);
2404             /* XS Combine */
2405              
2406             void
2407             Parse (SV *self, SV *src, SV *fields, SV *fflags)
2408              
2409             PPCODE:
2410             HV *hv;
2411             AV *av;
2412             AV *avf;
2413              
2414 1928 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2415 1928           av = (AV *)SvRV (fields);
2416 1928           avf = (AV *)SvRV (fflags);
2417              
2418 1928 100         ST (0) = xsParse (self, hv, av, avf, src, 0) ? &PL_sv_yes : &PL_sv_no;
2419 1925           XSRETURN (1);
2420             /* XS Parse */
2421              
2422             void
2423             print (SV *self, SV *io, SV *fields)
2424              
2425             PPCODE:
2426             HV *hv;
2427             AV *av;
2428              
2429 20256 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2430 20256 100         if (fields == &PL_sv_undef)
2431 5           av = newAV ();
2432             else {
2433 20251 50         unless (_is_arrayref (fields))
    100          
    50          
    100          
    100          
2434 5           croak ("Expected fields to be an array ref");
2435              
2436 20246           av = (AV *)SvRV (fields);
2437             }
2438              
2439 20251 100         ST (0) = xsCombine (self, hv, av, io, 1) ? &PL_sv_yes : &PL_sv_no;
2440 20251           XSRETURN (1);
2441             /* XS print */
2442              
2443             void
2444             getline (SV *self, SV *io)
2445              
2446             PPCODE:
2447             HV *hv;
2448             AV *av;
2449             AV *avf;
2450              
2451 1582 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2452 1582           av = newAV ();
2453 1582           avf = newAV ();
2454 1582           ST (0) = xsParse (self, hv, av, avf, io, 1)
2455 1443           ? sv_2mortal (newRV_noinc ((SV *)av))
2456 3023 100         : &PL_sv_undef;
2457 1580           XSRETURN (1);
2458             /* XS getline */
2459              
2460             void
2461             getline_all (SV *self, SV *io, ...)
2462              
2463             PPCODE:
2464             HV *hv;
2465             SV *offset, *length;
2466              
2467 334 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2468              
2469 334 100         offset = items > 2 ? ST (2) : &PL_sv_undef;
2470 334 100         length = items > 3 ? ST (3) : &PL_sv_undef;
2471              
2472 334           ST (0) = xsParse_all (self, hv, io, offset, length);
2473 328           XSRETURN (1);
2474             /* XS getline_all */
2475              
2476             void
2477             _cache_set (SV *self, int idx, SV *val)
2478              
2479             PPCODE:
2480             HV *hv;
2481              
2482 23241 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2483 23241           xs_cache_set (hv, idx, val);
2484 23241           XSRETURN (1);
2485             /* XS _cache_set */
2486              
2487             void
2488             _cache_diag (SV *self)
2489              
2490             PPCODE:
2491             HV *hv;
2492              
2493 2 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2494 2           xs_cache_diag (hv);
2495 2           XSRETURN (1);
2496             /* XS _cache_diag */