File Coverage

CSV_XS.xs
Criterion Covered Total %
statement 980 1002 97.8
branch 1635 3348 48.8
condition n/a
subroutine n/a
pod n/a
total 2615 4350 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 %02d:%s\n", trim, l, _pretty_str (str, l))
564              
565             #define xs_cache_diag(hv) cx_xs_cache_diag (aTHX_ hv)
566 2           static void cx_xs_cache_diag (pTHX_ HV *hv) {
567             SV **svp;
568             byte *cache;
569             csv_t csvs;
570 2           csv_t *csv = &csvs;
571              
572 2 100         unless ((svp = hv_fetchs (hv, "_CACHE", FALSE)) && *svp) {
    50          
573 1           warn ("CACHE: invalid\n");
574 1           return;
575             }
576              
577 1 50         cache = (byte *)SvPV_nolen (*svp);
578 1           (void)memcpy (csv, cache, sizeof (csv_t));
579 1           warn ("CACHE:\n");
580 1           _cache_show_char ("quote_char", CH_QUOTE);
581 1           _cache_show_char ("escape_char", csv->escape_char);
582 1           _cache_show_char ("sep_char", CH_SEP);
583 1           _cache_show_byte ("binary", csv->binary);
584 1           _cache_show_byte ("decode_utf8", csv->decode_utf8);
585              
586 1           _cache_show_byte ("allow_loose_escapes", csv->allow_loose_escapes);
587 1           _cache_show_byte ("allow_loose_quotes", csv->allow_loose_quotes);
588 1           _cache_show_byte ("allow_unquoted_escape", csv->allow_unquoted_escape);
589 1           _cache_show_byte ("allow_whitespace", csv->allow_whitespace);
590 1           _cache_show_byte ("always_quote", csv->always_quote);
591 1           _cache_show_byte ("quote_empty", csv->quote_empty);
592 1           _cache_show_byte ("quote_space", csv->quote_space);
593 1           _cache_show_byte ("escape_null", csv->escape_null);
594 1           _cache_show_byte ("quote_binary", csv->quote_binary);
595 1           _cache_show_byte ("auto_diag", csv->auto_diag);
596 1           _cache_show_byte ("diag_verbose", csv->diag_verbose);
597 1           _cache_show_byte ("formula", csv->formula);
598 1           _cache_show_byte ("strict", csv->strict);
599 1           _cache_show_byte ("skip_empty_rows", csv->skip_empty_rows);
600 1           _cache_show_byte ("has_error_input", csv->has_error_input);
601 1           _cache_show_byte ("blank_is_undef", csv->blank_is_undef);
602 1           _cache_show_byte ("empty_is_undef", csv->empty_is_undef);
603 1           _cache_show_byte ("has_ahead", csv->has_ahead);
604 1           _cache_show_byte ("keep_meta_info", csv->keep_meta_info);
605 1           _cache_show_byte ("verbatim", csv->verbatim);
606              
607 1           _cache_show_byte ("has_hooks", csv->has_hooks);
608 1           _cache_show_byte ("eol_is_cr", csv->eol_is_cr);
609 1           _cache_show_byte ("eol_len", csv->eol_len);
610 1           _cache_show_str ("eol", csv->eol_len, csv->eol);
611 1           _cache_show_byte ("sep_len", csv->sep_len);
612 1 50         if (csv->sep_len > 1)
613 1           _cache_show_str ("sep", csv->sep_len, csv->sep);
614 1           _cache_show_byte ("quo_len", csv->quo_len);
615 1 50         if (csv->quo_len > 1)
616 1           _cache_show_str ("quote", csv->quo_len, csv->quo);
617 1 50         if (csv->types_len)
618 0           _cache_show_str ("types", csv->types_len, (byte *)csv->types);
619             else
620 1           _cache_show_str ("types", 0, (byte *)"");
621              
622 1 50         if (csv->bptr)
623 1           _cache_show_str ("bptr", (int)strlen (csv->bptr), (byte *)csv->bptr);
624 1 50         if (csv->tmp && SvPOK (csv->tmp)) {
    50          
625 0 0         char *s = SvPV_nolen (csv->tmp);
626 1           _cache_show_str ("tmp", (int)strlen (s), (byte *)s);
627             }
628             } /* xs_cache_diag */
629              
630             #define set_eol_is_cr(csv) cx_set_eol_is_cr (aTHX_ csv)
631 8           static void cx_set_eol_is_cr (pTHX_ csv_t *csv) {
632 8           csv->eol[0] = CH_CR;
633 8           csv->eol_is_cr = 1;
634 8           csv->eol_len = 1;
635 8           (void)memcpy (csv->cache, csv, sizeof (csv_t));
636              
637 8           (void)hv_store (csv->self, "eol", 3, newSVpvn ((char *)csv->eol, 1), 0);
638 8           } /* set_eol_is_cr */
639              
640             #define SetupCsv(csv,self,pself) cx_SetupCsv (aTHX_ csv, self, pself)
641 27276           static void cx_SetupCsv (pTHX_ csv_t *csv, HV *self, SV *pself) {
642             SV **svp;
643             STRLEN len;
644             char *ptr;
645              
646 27276           last_error = 0;
647              
648 27276 100         if ((svp = hv_fetchs (self, "_CACHE", FALSE)) && *svp) {
    50          
649 26453           byte *cache = (byte *)SvPVX (*svp);
650 26453           (void)memcpy (csv, cache, sizeof (csv_t));
651             }
652             else {
653             SV *sv_cache;
654              
655 823           (void)memset (csv, 0, sizeof (csv_t)); /* Reset everything */
656              
657 823           csv->self = self;
658 823           csv->pself = pself;
659              
660 823           CH_SEP = ',';
661 823 50         if ((svp = hv_fetchs (self, "sep_char", FALSE)) && *svp && SvOK (*svp))
    50          
    50          
    0          
    0          
662 823 50         CH_SEP = *SvPV (*svp, len);
663 823 100         if ((svp = hv_fetchs (self, "sep", FALSE)) && *svp && SvOK (*svp)) {
    50          
    50          
    0          
    0          
664 224 50         ptr = SvPV (*svp, len);
665 224           (void)memcpy (csv->sep, ptr, len);
666 224 100         if (len > 1)
667 5           csv->sep_len = len;
668             }
669              
670 823           CH_QUOTE = '"';
671 823 50         if ((svp = hv_fetchs (self, "quote_char", FALSE)) && *svp) {
    50          
672 823 100         if (SvOK (*svp)) {
    50          
    50          
673 820 50         ptr = SvPV (*svp, len);
674 820 50         CH_QUOTE = len ? *ptr : (char)0;
675             }
676             else
677 3           CH_QUOTE = (char)0;
678             }
679 823 100         if ((svp = hv_fetchs (self, "quote", FALSE)) && *svp && SvOK (*svp)) {
    50          
    100          
    50          
    50          
680 5 50         ptr = SvPV (*svp, len);
681 5           (void)memcpy (csv->quo, ptr, len);
682 5 100         if (len > 1)
683 4           csv->quo_len = len;
684             }
685              
686 823           csv->escape_char = '"';
687 823 50         if ((svp = hv_fetchs (self, "escape_char", FALSE)) && *svp) {
    50          
688 823 100         if (SvOK (*svp)) {
    50          
    50          
689 817 50         ptr = SvPV (*svp, len);
690 817 100         csv->escape_char = len ? *ptr : (char)0;
691             }
692             else
693 6           csv->escape_char = (char)0;
694             }
695              
696 823 50         if ((svp = hv_fetchs (self, "eol", FALSE)) && *svp && SvOK (*svp)) {
    50          
    100          
    50          
    50          
697 819 50         char *eol = SvPV (*svp, len);
698 819           (void)memcpy (csv->eol, eol, len);
699 819           csv->eol_len = len;
700 819 100         if (len == 1 && *csv->eol == CH_CR)
    100          
701 42           csv->eol_is_cr = 1;
702             }
703              
704 823           csv->undef_flg = 0;
705 823 50         if ((svp = hv_fetchs (self, "undef_str", FALSE)) && *svp && SvOK (*svp)) {
    50          
    100          
    50          
    50          
706             /*if (sv && (SvOK (sv) || (
707             (SvGMAGICAL (sv) && (mg_get (sv), 1) && SvOK (sv))))) {*/
708 1 50         csv->undef_str = (byte *)SvPV_nolen (*svp);
709 1 50         if (SvUTF8 (*svp))
710 0           csv->undef_flg = 3;
711             }
712             else
713 822           csv->undef_str = NULL;
714              
715 823 50         if ((svp = hv_fetchs (self, "comment_str", FALSE)) && *svp && SvOK (*svp))
    50          
    100          
    50          
    50          
716 12 50         csv->comment_str = (byte *)SvPV_nolen (*svp);
717             else
718 811           csv->comment_str = NULL;
719              
720 823 100         if ((svp = hv_fetchs (self, "_types", FALSE)) && *svp && SvOK (*svp)) {
    50          
    50          
    0          
    0          
721 1 50         csv->types = SvPV (*svp, len);
722 1           csv->types_len = len;
723             }
724              
725 823 100         if ((svp = hv_fetchs (self, "_is_bound", FALSE)) && *svp && SvOK (*svp))
    50          
    50          
    0          
    0          
726 4 50         csv->is_bound = SvIV (*svp);
727 823 50         if ((svp = hv_fetchs (self, "callbacks", FALSE)) && _is_hashref (*svp)) {
    50          
    50          
    0          
    100          
    50          
728 301           HV *cb = (HV *)SvRV (*svp);
729 301 100         if ((svp = hv_fetchs (cb, "after_parse", FALSE)) && _is_coderef (*svp))
    50          
    50          
    0          
    50          
    50          
730 9           csv->has_hooks |= HOOK_AFTER_PARSE;
731 301 100         if ((svp = hv_fetchs (cb, "before_print", FALSE)) && _is_coderef (*svp))
    50          
    50          
    0          
    50          
    50          
732 1           csv->has_hooks |= HOOK_BEFORE_PRINT;
733             }
734              
735 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          
736 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          
737 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          
738 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          
739 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          
740 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          
741 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          
742 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          
743 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          
744 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          
745 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          
746 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          
747 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          
748 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          
749 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          
750              
751 823 50         csv->auto_diag = num_opt ("auto_diag");
    50          
    50          
752 823 50         csv->diag_verbose = num_opt ("diag_verbose");
    50          
    50          
753 823 50         csv->keep_meta_info = num_opt ("keep_meta_info");
    50          
    50          
754 823 50         csv->skip_empty_rows = num_opt ("skip_empty_rows");
    50          
    50          
755 823 50         csv->formula = num_opt ("formula");
    50          
    50          
756              
757 823 100         unless (csv->escape_char) csv->escape_null = 0;
758              
759 823           sv_cache = newSVpvn ((char *)csv, sizeof (csv_t));
760 823           csv->cache = (byte *)SvPVX (sv_cache);
761 823           SvREADONLY_on (sv_cache);
762              
763 823           (void)memcpy (csv->cache, csv, sizeof (csv_t));
764              
765 823           (void)hv_store (self, "_CACHE", 6, sv_cache, 0);
766             }
767              
768 27276           csv->utf8 = 0;
769 27276           csv->size = 0;
770 27276           csv->used = 0;
771              
772             /* This is EBCDIC-safe, as it is used after translation */
773 27276 100         csv->first_safe_char = csv->quote_space ? 0x21 : 0x20;
774              
775 27276 100         if (csv->is_bound) {
776 83 50         if ((svp = hv_fetchs (self, "_BOUND_COLUMNS", FALSE)) && _is_arrayref (*svp))
    50          
    50          
    0          
    100          
    50          
777 69           csv->bound = *svp;
778             else
779 14           csv->is_bound = 0;
780             }
781              
782 27276           csv->eol_pos = -1;
783 54552           csv->eolx = csv->eol_len
784 1305 100         ? csv->verbatim || csv->eol_len >= 2
785             ? 1
786 853 100         : csv->eol[0] == CH_CR || csv->eol[0] == CH_NL
787             ? 0
788 366 100         : 1
789 28581 100         : 0;
    100          
790 27276 100         if (csv->sep_len > 1 && is_utf8_string ((U8 *)(csv->sep), csv->sep_len))
    50          
791 51           csv->utf8 = 1;
792 27276 100         if (csv->quo_len > 1 && is_utf8_string ((U8 *)(csv->quo), csv->quo_len))
    50          
793 27           csv->utf8 = 1;
794 27276           } /* SetupCsv */
795              
796             #define Print(csv,dst) cx_Print (aTHX_ csv, dst)
797 941266           static int cx_Print (pTHX_ csv_t *csv, SV *dst) {
798             int result;
799 941266           int keep = 0;
800              
801 941266 100         if (csv->useIO) {
802 939877           SV *tmp = newSVpvn_flags (csv->buffer, csv->used, SVs_TEMP);
803 939877           dSP;
804 939877 50         PUSHMARK (sp);
805 939877 50         EXTEND (sp, 2);
806 939877           PUSHs ((dst));
807 939877 100         if (csv->utf8) {
808             STRLEN len;
809             char *ptr;
810             int j;
811              
812 939649 50         ptr = SvPV (tmp, len);
813 1690511 50         while (len > 0 && !is_utf8_sv (tmp) && keep < 16) {
    50          
    100          
    50          
814 750862           ptr[--len] = (char)0;
815 750862           SvCUR_set (tmp, len);
816 750862           keep++;
817             }
818 1690511 100         for (j = 0; j < keep; j++)
819 750862           csv->buffer[j] = csv->buffer[csv->used - keep + j];
820 939649           SvUTF8_on (tmp);
821             }
822 939877           PUSHs (tmp);
823 939877           PUTBACK;
824 939877           result = call_sv (m_print, G_METHOD);
825 939877           SPAGAIN;
826 939877 50         if (result) {
827 939877 100         result = POPi;
828 939877 100         unless (result)
829 1           (void)SetDiag (csv, 2200);
830             }
831 939877           PUTBACK;
832             }
833             else {
834 1389           sv_catpvn (SvRV (dst), csv->buffer, csv->used);
835 1389           result = TRUE;
836             }
837 941266 100         if (csv->utf8 && !csv->useIO && csv->decode_utf8
    100          
    50          
838 25 50         && SvROK (dst) && is_utf8_sv (SvRV (dst)))
    50          
    100          
839 24           SvUTF8_on (SvRV (dst));
840 941266           csv->used = keep;
841 941266           return result;
842             } /* Print */
843              
844             #define CSV_PUT(csv,dst,c) { \
845             if ((csv)->used == sizeof ((csv)->buffer) - 1) { \
846             unless (Print ((csv), (dst))) \
847             return FALSE; \
848             } \
849             (csv)->buffer[(csv)->used++] = (c); \
850             }
851              
852             #define bound_field(csv,i,keep) cx_bound_field (aTHX_ csv, i, keep)
853 101           static SV *cx_bound_field (pTHX_ csv_t *csv, SSize_t i, int keep) {
854 101           SV *sv = csv->bound;
855             AV *av;
856              
857             /* fprintf (stderr, "# New bind %d/%d\n", i, csv->is_bound);\ */
858 101 100         if (i >= csv->is_bound) {
859 3           (void)SetDiag (csv, 3006);
860 3           return (NULL);
861             }
862              
863 98 50         if (sv && SvROK (sv)) {
    50          
864 98           av = (AV *)(SvRV (sv));
865             /* fprintf (stderr, "# Bind %d/%d/%d\n", i, csv->is_bound, av_len (av)); */
866 98           sv = *av_fetch (av, i, FALSE);
867 98 50         if (sv && SvROK (sv)) {
    50          
868 98           sv = SvRV (sv);
869 98 100         if (keep)
870 14           return (sv);
871              
872 84 100         unless (SvREADONLY (sv)) {
873 83           SvSetEmpty (sv);
874 83           return (sv);
875             }
876             }
877             }
878 1           (void)SetDiag (csv, 3008);
879 1           return (NULL);
880             } /* bound_field */
881              
882             #define was_quoted(mf,idx) cx_was_quoted (aTHX_ mf, idx)
883 17           static int cx_was_quoted (pTHX_ AV *mf, int idx) {
884 17           SV **x = av_fetch (mf, idx, FALSE);
885 17 50         return (x && SvIOK (*x) && SvIV (*x) & CSV_FLAGS_QUO ? 1 : 0);
    50          
    50          
    100          
    0          
886             } /* was_quoted */
887              
888             #define _formula(csv,sv,len,f) cx_formula (aTHX_ csv, sv, len, f)
889 37           static char *cx_formula (pTHX_ csv_t *csv, SV *sv, STRLEN *len, int f) {
890              
891 37           int fa = csv->formula;
892              
893 37 100         if (fa == 1) die ("Formulas are forbidden\n");
894 34 100         if (fa == 2) croak ("Formulas are forbidden\n");
895              
896 31 100         if (fa == 3) {
897 6 50         char *ptr = SvPV_nolen (sv);
898             char rec[40];
899             char field[128];
900             SV **svp;
901              
902 6 100         if (csv->recno) (void)sprintf (rec, " in record %lu", csv->recno + 1);
903 3           else *rec = (char)0;
904              
905 6           *field = (char)0;
906 6 50         if ((svp = hv_fetchs (csv->self, "_COLUMN_NAMES", FALSE)) && _is_arrayref (*svp)) {
    50          
    50          
    0          
    100          
    50          
907 1           AV *avp = (AV *)SvRV (*svp);
908 1 50         if (avp && av_len (avp) >= (f - 1)) {
    50          
909 1           SV **fnm = av_fetch (avp, f - 1, FALSE);
910 1 50         if (fnm && *fnm && SvOK (*fnm))
    50          
    50          
    0          
    0          
911 1 50         (void)sprintf (field, " (column: '%.100s')", SvPV_nolen (*fnm));
912             }
913             }
914              
915 6           warn ("Field %d%s%s contains formula '%s'\n", f, field, rec, ptr);
916 6           return ptr;
917             }
918              
919 25 100         if (len) *len = 0;
920              
921 25 100         if (fa == 4) {
922 5 100         unless (SvREADONLY (sv)) SvSetEmpty (sv);
923 5           return "";
924             }
925              
926 20 100         if (fa == 5) {
927 5 100         unless (SvREADONLY (sv)) SvSetUndef (sv);
928 5           return NULL;
929             }
930              
931 15 50         if (fa == 6) {
932             int result;
933 15           SV **svp = hv_fetchs (csv->self, "_FORMULA_CB", FALSE);
934 15 50         if (svp && _is_coderef (*svp)) {
    50          
    50          
    0          
    50          
    50          
935 15           dSP;
936 15           ENTER;
937 15           SAVE_DEFSV; /* local $_ */
938 15 50         DEFSV = sv;
939 15 50         PUSHMARK (SP);
940 15           PUTBACK;
941 15           result = call_sv (*svp, G_SCALAR);
942 15           SPAGAIN;
943 15 50         if (result)
944 15           sv_setsv (sv, POPs);
945 15           PUTBACK;
946 15           LEAVE;
947             }
948 15 50         return len ? SvPV (sv, *len) : SvPV_nolen (sv);
    0          
    100          
949             }
950              
951             /* So far undefined behavior */
952 0           return NULL;
953             } /* _formula */
954              
955             #define SkipEmptyRow {\
956             int ser = csv->skip_empty_rows; \
957             \
958             if (ser == 3) { (void)SetDiag (csv, 2015); die ("Empty row"); } \
959             if (ser == 4) { (void)SetDiag (csv, 2015); croak ("Empty row"); } \
960             if (ser == 5) { (void)SetDiag (csv, 2015); return FALSE; } \
961             \
962             if (ser <= 2) { /* skip & eof */ \
963             csv->fld_idx = 0; \
964             c = CSV_GET; \
965             if (c == EOF || ser == 2) { \
966             sv_free (sv); \
967             sv = NULL; \
968             waitingForField = 0; \
969             if (ser == 2) return FALSE; \
970             break; \
971             } \
972             } \
973             \
974             if (ser == 6) { \
975             int result, n, i; \
976             SV *rv, **svp = hv_fetchs (csv->self, "_EMPTROW_CB", FALSE); \
977             AV *avp; \
978             unless (svp && _is_coderef (*svp)) \
979             return FALSE; /* A callback is wanted, but none found */ \
980             \
981             dSP; \
982             ENTER; \
983             SAVE_DEFSV; /* local $_ */ \
984             DEFSV = sv; \
985             PUSHMARK (SP); \
986             PUTBACK; \
987             result = call_sv (*svp, G_SCALAR); \
988             SPAGAIN; \
989             unless (result) { \
990             /* A false return will stop the parsing */ \
991             sv_free (sv); \
992             sv = NULL; \
993             waitingForField = 0; \
994             return FALSE; \
995             } \
996             \
997             PUTBACK; \
998             LEAVE; \
999             \
1000             rv = POPs; \
1001             /* Result should be a ref to a list. */ \
1002             unless (_is_arrayref (rv)) \
1003             return FALSE; \
1004             \
1005             avp = (AV *)SvRV (rv); \
1006             \
1007             unless (avp) return FALSE; \
1008             n = av_len (avp); \
1009             if (n <= 0) return TRUE; \
1010             \
1011             if (csv->is_bound && csv->is_bound < n) \
1012             n = csv->is_bound - 1; \
1013             \
1014             for (i = 0; i <= n; i++) { \
1015             SV **svp = av_fetch (avp, i, FALSE); \
1016             sv = svp && *svp ? *svp : NULL; \
1017             if (sv) { \
1018             SvREFCNT_inc (sv); \
1019             /* upgrade IV to IVPV if needed */ \
1020             (void)SvPV_nolen (sv); \
1021             } \
1022             AV_PUSH; \
1023             } \
1024             return TRUE; \
1025             } \
1026             }
1027              
1028             #define Combine(csv,dst,fields) cx_Combine (aTHX_ csv, dst, fields)
1029 21647           static int cx_Combine (pTHX_ csv_t *csv, SV *dst, AV *fields) {
1030             SSize_t i, n;
1031 21647           int bound = 0;
1032 21647           int aq = (int)csv->always_quote;
1033 21647           int qe = (int)csv->quote_empty;
1034 21647           int kmi = (int)csv->keep_meta_info;
1035 21647           AV *qm = NULL;
1036              
1037 21647           n = (IV)av_len (fields);
1038 21647 100         if (n < 0 && csv->is_bound) {
    100          
1039 5           n = csv->is_bound - 1;
1040 5           bound = 1;
1041             }
1042              
1043 21647 100         if (kmi >= 10) {
1044             SV **svp;
1045 2 50         if ((svp = hv_fetchs (csv->self, "_FFLAGS", FALSE)) && _is_arrayref (*svp)) {
    50          
    50          
    0          
    50          
    50          
1046 2           AV *avp = (AV *)SvRV (*svp);
1047 2 50         if (avp && av_len (avp) >= n)
    50          
1048 2           qm = avp;
1049             }
1050             }
1051              
1052 75481 100         for (i = 0; i <= n; i++) {
1053             SV *sv;
1054 53845           STRLEN len = 0;
1055 53845           char *ptr = NULL;
1056              
1057 53845 100         if (i > 0) {
1058 32206 50         CSV_PUT (csv, dst, CH_SEP);
    0          
1059 32199 100         if (csv->sep_len) {
1060             int x;
1061 30 100         for (x = 1; x < (int)csv->sep_len; x++)
1062 20 50         CSV_PUT (csv, dst, csv->sep[x]);
    0          
1063             }
1064             }
1065              
1066 53845 100         if (bound)
1067 14           sv = bound_field (csv, i, 1);
1068             else {
1069 53831           SV **svp = av_fetch (fields, i, FALSE);
1070 53831 50         sv = svp && *svp ? *svp : NULL;
    50          
1071             }
1072              
1073 53845 50         if (sv && (SvOK (sv) || (
    100          
    50          
    50          
    50          
1074 53779 0         (SvGMAGICAL (sv) && (mg_get (sv), 1) && SvOK (sv))))) {
    0          
    0          
1075              
1076             int quoteMe;
1077              
1078 53792 100         ptr = SvPV (sv, len);
1079              
1080 53792 100         if (*ptr == '=' && csv->formula) {
    100          
1081 10 100         unless (ptr = _formula (csv, sv, &len, i))
1082 2           continue;
1083             }
1084 53786 100         if (len == 0)
1085 1404 100         quoteMe = aq ? 1 : qe ? 1 : qm ? was_quoted (qm, i) : 0;
    100          
    100          
1086             else {
1087              
1088 52382 100         if (SvUTF8 (sv)) {
1089 20041           csv->utf8 = 1;
1090 20041           csv->binary = 1;
1091             }
1092              
1093 52382 100         quoteMe = aq ? 1 : qm ? was_quoted (qm, i) : 0;
    100          
1094              
1095             /* Do we need quoting? We do quote, if the user requested
1096             * (always_quote), if binary or blank characters are found
1097             * and if the string contains quote or escape characters.
1098             */
1099 99136 100         if (!quoteMe &&
    100          
1100 46754 100         ( quoteMe = (!SvIOK (sv) && !SvNOK (sv) && CH_QUOTE))) {
    100          
    100          
1101             char *ptr2;
1102             STRLEN l;
1103              
1104             #if MAINT_DEBUG > 4
1105             (void)fprintf (stderr, "# Combine:\n");
1106             sv_dump (sv);
1107             #endif
1108 85816 100         for (ptr2 = ptr, l = len; l; ++ptr2, --l) {
1109 83767           byte c = *ptr2;
1110             #ifdef IS_EBCDIC
1111             byte x = ebcdic2ascii[c];
1112             #if MAINT_DEBUG > 4
1113             (void)fprintf (stderr, " %02x", x);
1114             #endif
1115             #else
1116 83767           byte x = c;
1117             #endif
1118              
1119 166851 50         if ((CH_QUOTE && c == CH_QUOTE) ||
    100          
    100          
    100          
1120 83459 100         (CH_SEP && c == CH_SEP) ||
    100          
1121 166388 100         (csv->escape_char && c == csv->escape_char) ||
    100          
    100          
1122 83074 100         (csv->quote_binary ? (x >= 0x7f && x <= 0xa0) ||
    100          
    100          
1123 63053           x < csv->first_safe_char
1124 15 50         : c == CH_NL || c == CH_CR ||
    50          
    100          
1125 5 100         (csv->quote_space && (
1126 3 50         c == CH_SPACE || c == CH_TAB)))) {
1127             /* Binary character */
1128             break;
1129             }
1130             }
1131             #if defined(IS_EBCDIC) && MAINT_DEBUG > 4
1132             (void)fprintf (stderr, "\n");
1133             #endif
1134 25179           quoteMe = (l > 0);
1135             }
1136             }
1137 53786 100         if (quoteMe) {
1138 29412 50         CSV_PUT (csv, dst, CH_QUOTE);
    0          
1139 29412 100         if (csv->quo_len) {
1140             int x;
1141 51 100         for (x = 1; x < (int)csv->quo_len; x++)
1142 34 50         CSV_PUT (csv, dst, csv->quo[x]);
    0          
1143             }
1144             }
1145 950415231 100         while (len-- > 0) {
1146 950361452           char c = *ptr++;
1147 950361452           int e = 0;
1148              
1149 950361452 100         if (!csv->binary && is_csv_binary (c)) {
    100          
    50          
    100          
1150 7           SvREFCNT_inc (sv);
1151 7           csv->has_error_input = 1;
1152 7 50         unless (hv_store (csv->self, "_ERROR_INPUT", 12, sv, 0))
1153 0           SvREFCNT_dec (sv); /* uncoverable statement memory fail */
1154 7           (void)SetDiag (csv, 2110);
1155 7           return FALSE;
1156             }
1157 950361445 100         if (CH_QUOTE && (byte)c == CH_QUOTE && (csv->quo_len == 0 ||
    100          
    100          
    100          
1158 9           memcmp (ptr, csv->quo +1, csv->quo_len - 1) == 0))
1159 3217           e = 1;
1160             else
1161 950358228 100         if (c == csv->escape_char && csv->escape_char)
    100          
1162 2163           e = 1;
1163             else
1164 950356065 100         if (c == (char)0 && csv->escape_null) {
    100          
1165 29           e = 1;
1166 29           c = '0';
1167             }
1168 950361445 100         if (e && csv->escape_char)
    50          
1169 5409 50         CSV_PUT (csv, dst, csv->escape_char);
    0          
1170 950361445 100         CSV_PUT (csv, dst, c);
    50          
1171             }
1172 53779 100         if (quoteMe) {
1173 29405 50         CSV_PUT (csv, dst, CH_QUOTE);
    0          
1174 29405 100         if (csv->quo_len) {
1175             int x;
1176 51 100         for (x = 1; x < (int)csv->quo_len; x++)
1177 34 50         CSV_PUT (csv, dst, csv->quo[x]);
    0          
1178             }
1179             }
1180             }
1181             else {
1182 53 100         if (csv->undef_str) {
1183 8           byte *ptr = csv->undef_str;
1184 8           STRLEN len = strlen ((char *)ptr);
1185              
1186 8 100         if (csv->undef_flg) {
1187 3           csv->utf8 = 1;
1188 3           csv->binary = 1;
1189             }
1190              
1191 53852 100         while (len--)
1192 20 50         CSV_PUT (csv, dst, *ptr++);
    0          
1193             }
1194             }
1195             }
1196 21636 100         if (csv->eol_len) {
1197 249           STRLEN len = csv->eol_len;
1198 249           byte *ptr = csv->eol;
1199              
1200 696 100         while (len--)
1201 447 50         CSV_PUT (csv, dst, *ptr++);
    0          
1202             }
1203 21636 100         if (csv->used)
1204 21634           return Print (csv, dst);
1205 2           return TRUE;
1206             } /* Combine */
1207              
1208             #define ParseError(csv,xse,pos) cx_ParseError (aTHX_ csv, xse, pos)
1209 299           static void cx_ParseError (pTHX_ csv_t *csv, int xse, STRLEN pos) {
1210 299           (void)hv_store (csv->self, "_ERROR_POS", 10, newSViv (pos), 0);
1211 299           (void)hv_store (csv->self, "_ERROR_FLD", 10, newSViv (csv->fld_idx), 0);
1212 299 50         if (csv->tmp) {
1213 299           csv->has_error_input = 1;
1214 299 50         if (hv_store (csv->self, "_ERROR_INPUT", 12, csv->tmp, 0))
1215 299           SvREFCNT_inc (csv->tmp);
1216             }
1217 299           (void)SetDiag (csv, xse);
1218 296           } /* ParseError */
1219              
1220             #define CsvGet(csv,src) cx_CsvGet (aTHX_ csv, src)
1221 4868           static int cx_CsvGet (pTHX_ csv_t *csv, SV *src) {
1222 4868 100         unless (csv->useIO)
1223 1518           return EOF;
1224              
1225 3350 100         if (csv->tmp && csv->eol_pos >= 0) {
    100          
1226 348           csv->eol_pos = -2;
1227 348           sv_setpvn (csv->tmp, (char *)csv->eol, csv->eol_len);
1228 348 50         csv->bptr = SvPV (csv->tmp, csv->size);
1229 348           csv->used = 0;
1230 348           return CH_EOLX;
1231             }
1232              
1233             { STRLEN result;
1234 3002           dSP;
1235              
1236 3002 50         PUSHMARK (sp);
1237 3002 50         EXTEND (sp, 1);
1238 3002           PUSHs (src);
1239 3002           PUTBACK;
1240 3002           result = call_sv (m_getline, G_METHOD);
1241 3002           SPAGAIN;
1242 3002           csv->eol_pos = -1;
1243 3002 50         csv->tmp = result ? POPs : NULL;
1244 3002           PUTBACK;
1245              
1246             #if MAINT_DEBUG > 4
1247             (void)fprintf (stderr, "getline () returned:\n");
1248             sv_dump (csv->tmp);
1249             #endif
1250             }
1251 3002 50         if (csv->tmp && SvOK (csv->tmp)) {
    100          
    50          
    50          
1252             STRLEN tmp_len;
1253 2453 50         csv->bptr = SvPV (csv->tmp, tmp_len);
1254 2453           csv->used = 0;
1255 2453           csv->size = tmp_len;
1256 2453 100         if (csv->eolx && csv->size >= csv->eol_len) {
    50          
1257 358           int i, match = 1;
1258 1817 100         for (i = 1; i <= (int)csv->eol_len; i++) {
1259 1463 100         unless (csv->bptr[csv->size - i] == csv->eol[csv->eol_len - i]) {
1260 4           match = 0;
1261 4           break;
1262             }
1263             }
1264 358 100         if (match) {
1265             #if MAINT_DEBUG > 4
1266             (void)fprintf (stderr, "# EOLX match, size: %d\n", csv->size);
1267             #endif
1268 354           csv->size -= csv->eol_len;
1269 354 100         unless (csv->verbatim)
1270 351           csv->eol_pos = csv->size;
1271 354           csv->bptr[csv->size] = (char)0;
1272 354           SvCUR_set (csv->tmp, csv->size);
1273 354 100         unless (csv->verbatim || csv->size)
    100          
1274 2453           return CH_EOLX;
1275             }
1276             }
1277 2447 100         if (SvUTF8 (csv->tmp)) csv->utf8 = 1;
1278 2447 50         if (tmp_len)
1279 2447           return ((byte)csv->bptr[csv->used++]);
1280             }
1281 549           csv->useIO |= useIO_EOF;
1282 549           return EOF;
1283             } /* CsvGet */
1284              
1285             #define ERROR_INSIDE_QUOTES(diag_code) { \
1286             unless (csv->is_bound) SvREFCNT_dec (sv); \
1287             ParseError (csv, diag_code, csv->used - 1); \
1288             return FALSE; \
1289             }
1290             #define ERROR_INSIDE_FIELD(diag_code) { \
1291             unless (csv->is_bound) SvREFCNT_dec (sv); \
1292             ParseError (csv, diag_code, csv->used - 1); \
1293             return FALSE; \
1294             }
1295              
1296             #if MAINT_DEBUG > 4
1297             #define PUT_RPT (void)fprintf (stderr, "# CSV_PUT @ %4d: 0x%02x '%c'\n", __LINE__, c, isprint (c) ? c : '?')
1298             #define PUT_SEPX_RPT1 (void)fprintf (stderr, "# PUT SEPX @ %4d\n", __LINE__)
1299             #define PUT_SEPX_RPT2 (void)fprintf (stderr, "# Done putting SEPX\n")
1300             #define PUT_QUOX_RPT1 (void)fprintf (stderr, "# PUT QUOX @ %4d\n", __LINE__)
1301             #define PUT_QUOX_RPT2 (void)fprintf (stderr, "# Done putting QUOX\n")
1302             #define PUT_EOLX_RPT1 (void)fprintf (stderr, "# PUT EOLX @ %4d\n", __LINE__)
1303             #define PUT_EOLX_RPT2 (void)fprintf (stderr, "# Done putting EOLX\n")
1304             #define PUSH_RPT (void)fprintf (stderr, "# AV_PUSHd @ %4d\n", __LINE__); sv_dump (sv)
1305             #else
1306             #define PUT_RPT
1307             #define PUT_SEPX_RPT1
1308             #define PUT_SEPX_RPT2
1309             #define PUT_QUOX_RPT1
1310             #define PUT_QUOX_RPT2
1311             #define PUT_EOLX_RPT1
1312             #define PUT_EOLX_RPT2
1313             #define PUSH_RPT
1314             #endif
1315             #define CSV_PUT_SV1(c) { \
1316             len = SvCUR ((sv)); \
1317             SvGROW ((sv), len + 2); \
1318             *SvEND ((sv)) = c; \
1319             PUT_RPT; \
1320             SvCUR_set ((sv), len + 1); \
1321             }
1322             #define CSV_PUT_SV(c) { \
1323             if (c == CH_EOLX) { \
1324             int x; PUT_EOLX_RPT1; \
1325             if (csv->eol_pos == -2) \
1326             csv->size = 0; \
1327             for (x = 0; x < (int)csv->eol_len; x++) \
1328             CSV_PUT_SV1 (csv->eol[x]); \
1329             csv->eol_pos = -1; \
1330             PUT_EOLX_RPT2; \
1331             } \
1332             else if (c == CH_SEPX) { \
1333             int x; PUT_SEPX_RPT1; \
1334             for (x = 0; x < (int)csv->sep_len; x++) \
1335             CSV_PUT_SV1 (csv->sep[x]); \
1336             PUT_SEPX_RPT2; \
1337             } \
1338             else if (c == CH_QUOTEX) { \
1339             int x; PUT_QUOX_RPT1; \
1340             for (x = 0; x < (int)csv->quo_len; x++) \
1341             CSV_PUT_SV1 (csv->quo[x]); \
1342             PUT_QUOX_RPT2; \
1343             } \
1344             else \
1345             CSV_PUT_SV1 (c); \
1346             }
1347              
1348             #define CSV_GET1 \
1349             (csv->used < csv->size ? (byte)csv->bptr[csv->used++] : CsvGet (csv, src))
1350              
1351             #if MAINT_DEBUG > 3
1352             int CSV_GET_ (pTHX_ csv_t *csv, SV *src, int l) {
1353             int c;
1354             (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);
1355             c = CSV_GET1;
1356             (void)fprintf (stderr, "# 2-CSV_GET @ %4d: 0x%02x '%c'\n", l, c, isprint (c) ? c : '?');
1357             return (c);
1358             } /* CSV_GET_ */
1359             #define CSV_GET CSV_GET_ (aTHX_ csv, src, __LINE__)
1360             #else
1361             #define CSV_GET CSV_GET1
1362             #endif
1363              
1364             #define AV_PUSH { \
1365             int svc; \
1366             *SvEND (sv) = (char)0; \
1367             svc = SvCUR (sv); \
1368             SvUTF8_off (sv); \
1369             if (svc && csv->formula && *(SvPV_nolen (sv)) == '=') \
1370             (void)_formula (csv, sv, NULL, fnum); \
1371             if (svc == 0 && ( \
1372             csv->empty_is_undef || \
1373             (!(f & CSV_FLAGS_QUO) && csv->blank_is_undef))) \
1374             SvSetUndef (sv); \
1375             else { \
1376             if (csv->allow_whitespace && ! (f & CSV_FLAGS_QUO)) \
1377             strip_trail_whitespace (sv); \
1378             if (f & CSV_FLAGS_BIN && csv->decode_utf8 \
1379             && (csv->utf8 || is_utf8_sv (sv))) \
1380             SvUTF8_on (sv); \
1381             } \
1382             SvSETMAGIC (sv); \
1383             unless (csv->is_bound) av_push (fields, sv); \
1384             PUSH_RPT; \
1385             sv = NULL; \
1386             if (csv->keep_meta_info && fflags) \
1387             av_push (fflags, newSViv (f)); \
1388             waitingForField = 1; \
1389             }
1390              
1391             #define strip_trail_whitespace(sv) cx_strip_trail_whitespace (aTHX_ sv)
1392 1723           static void cx_strip_trail_whitespace (pTHX_ SV *sv) {
1393             STRLEN len;
1394 1723 50         char *s = SvPV (sv, len);
1395 1723 50         unless (s && len) return;
    50          
1396 1899 100         while (s[len - 1] == CH_SPACE || s[len - 1] == CH_TAB)
    50          
1397 176           s[--len] = (char)0;
1398 1723           SvCUR_set (sv, len);
1399             } /* strip_trail_whitespace */
1400              
1401             #define NewField \
1402             unless (sv) { \
1403             if (csv->is_bound) \
1404             sv = bound_field (csv, fnum, 0); \
1405             else \
1406             sv = newSVpvs (""); \
1407             fnum++; \
1408             unless (sv) return FALSE; \
1409             f = 0; csv->fld_idx++; \
1410             }
1411              
1412             #if MAINT_DEBUG
1413             static char str_parsed[40];
1414             #endif
1415              
1416             #if MAINT_DEBUG > 1
1417             static char *_sep_string (csv_t *csv) {
1418             char sep[64];
1419             if (csv->sep_len) {
1420             int x;
1421             for (x = 0; x < csv->sep_len; x++)
1422             (void)sprintf (sep + x * x, "%02x ", csv->sep[x]);
1423             }
1424             else
1425             (void)sprintf (sep, "'%c' (0x%02x)", CH_SEP, CH_SEP);
1426             return sep;
1427             } /* _sep_string */
1428             #endif
1429              
1430             #define Parse(csv,src,fields,fflags) cx_Parse (aTHX_ csv, src, fields, fflags)
1431 4554           static int cx_Parse (pTHX_ csv_t *csv, SV *src, AV *fields, AV *fflags) {
1432 4554           int c, f = 0;
1433 4554           int waitingForField = 1;
1434 4554           SV *sv = NULL;
1435             STRLEN len;
1436 4554           int seenSomething = FALSE;
1437 4554           int fnum = 0;
1438 4554           int spl = -1;
1439             #if MAINT_DEBUG
1440             (void)memset (str_parsed, 0, 40);
1441             #endif
1442              
1443 4554           csv->fld_idx = 0;
1444              
1445 186728 100         while ((c = CSV_GET) != EOF) {
    100          
1446              
1447 185991 100         NewField;
    100          
    100          
1448              
1449 185987           seenSomething = TRUE;
1450 185987           spl++;
1451             #if MAINT_DEBUG
1452             if (spl < 39) str_parsed[spl] = c;
1453             #endif
1454             restart:
1455             #if MAINT_DEBUG > 9
1456             (void)fprintf (stderr, "# at restart: %d/%d/%03x pos %d = 0x%02x\n",
1457             waitingForField ? 1 : 0, sv ? 1 : 0, f, spl, c);
1458             #endif
1459 196721 100         if (is_SEP (c)) {
    100          
    50          
    100          
    50          
1460             #if MAINT_DEBUG > 1
1461             (void)fprintf (stderr, "# %d/%d/%03x pos %d = SEP %s\t%s\n",
1462             waitingForField ? 1 : 0, sv ? 1 : 0, f, spl,
1463             _sep_string (csv), _pretty_strl (csv->bptr + csv->used));
1464             #endif
1465 23640 100         if (waitingForField) {
1466             /* ,1,"foo, 3",,bar,
1467             * ^ ^
1468             */
1469 1173 100         if (csv->blank_is_undef || csv->empty_is_undef)
    100          
1470 50           SvSetUndef (sv);
1471             else
1472 1123           SvSetEmpty (sv);
1473 1173 50         unless (csv->is_bound)
1474 1173           av_push (fields, sv);
1475 1173           sv = NULL;
1476 1173 100         if (csv->keep_meta_info && fflags)
    50          
1477 1173           av_push (fflags, newSViv (f));
1478             }
1479             else
1480 10648 100         if (f & CSV_FLAGS_QUO) {
1481             /* ,1,"foo, 3",,bar,
1482             * ^
1483             */
1484 2194 50         CSV_PUT_SV (c)
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    100          
1485             }
1486             else {
1487             /* ,1,"foo, 3",,bar,
1488             * ^ ^ ^
1489             */
1490 8454 100         AV_PUSH;
    100          
    50          
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    100          
    100          
    100          
    50          
1491             }
1492             } /* SEP char */
1493             else
1494 184900 100         if (is_QUOTE (c)) {
    100          
    100          
    50          
    100          
    50          
1495             #if MAINT_DEBUG > 1
1496             (void)fprintf (stderr, "# %d/%d/%03x pos %d = QUO '%c'\t\t%s\n",
1497             waitingForField ? 1 : 0, sv ? 1 : 0, f, spl, c,
1498             _pretty_strl (csv->bptr + csv->used));
1499             #endif
1500 22820 100         if (waitingForField) {
1501             /* ,1,"foo, 3",,bar,\r\n
1502             * ^
1503             */
1504 10904           f |= CSV_FLAGS_QUO;
1505 10904           waitingForField = 0;
1506 10904           continue;
1507             }
1508              
1509 11916 100         if (f & CSV_FLAGS_QUO) {
1510              
1511             /* ,1,"foo, 3",,bar,\r\n
1512             * ^
1513             */
1514              
1515 11850           int quoesc = 0;
1516 11850 100         int c2 = CSV_GET;
1517              
1518 11850 100         if (csv->allow_whitespace) {
1519             /* , 1 , "foo, 3" , , bar , \r\n
1520             * ^
1521             */
1522 4330 100         while (is_whitespace (c2)) {
    100          
    50          
    100          
    100          
1523 90 100         if (csv->allow_loose_quotes &&
    50          
1524 0 0         !(csv->escape_char && c2 == csv->escape_char)) {
1525             /* This feels like a brittle fix for RT115953, where
1526             * ["foo "bar" baz"] got parsed as [foo "bar"baz]
1527             * when both allow_whitespace and allow_loose_quotes
1528             * are true and escape does not equal quote
1529             */
1530 1 50         CSV_PUT_SV (c);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
1531 1           c = c2;
1532             }
1533 90 100         c2 = CSV_GET;
1534             }
1535             }
1536              
1537 11850 100         if (is_SEP (c2)) {
    100          
    50          
    50          
    50          
1538             /* ,1,"foo, 3",,bar,\r\n
1539             * ^
1540             */
1541 9011 100         AV_PUSH;
    50          
    0          
    0          
    100          
    100          
    50          
    0          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
1542 9011           continue;
1543             }
1544              
1545 2839 100         if (c2 == CH_NL || c2 == CH_EOLX) {
    100          
1546             /* ,1,"foo, 3",,"bar"\n
1547             * ^
1548             */
1549 195 100         AV_PUSH;
    50          
    0          
    0          
    100          
    50          
    50          
    0          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
1550 195           return TRUE;
1551             }
1552              
1553             /* ---
1554             * if QUOTE eq ESCAPE
1555             * AND ( c2 eq QUOTE 1,"abc""def",2
1556             * OR c2 eq ESCAPE 1,"abc""def",2 (QUO eq ESC)
1557             * OR c2 eq NULL ) 1,"abc"0def",2
1558             * ---
1559             */
1560 2644 100         if (csv->escape_char && c == csv->escape_char) {
    100          
1561              
1562 1547           quoesc = 1;
1563 1547 100         if (c2 == '0') {
1564             /* ,1,"foo, 3"056",,bar,\r\n
1565             * ^
1566             */
1567 25 50         CSV_PUT_SV (0)
    50          
1568 25           continue;
1569             }
1570              
1571 1522 50         if (is_QUOTE (c2)) {
    100          
    50          
    0          
    0          
    0          
1572             /* ,1,"foo, 3""56",,bar,\r\n
1573             * ^
1574             */
1575 1056 100         if (csv->utf8)
1576 1           f |= CSV_FLAGS_BIN;
1577 1056 50         CSV_PUT_SV (c2)
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    100          
1578 1056           continue;
1579             }
1580              
1581 466 100         if (csv->allow_loose_escapes && c2 != CH_CR) {
    100          
1582             /* ,1,"foo, 3"56",,bar,\r\n
1583             * ^
1584             */
1585 2 50         CSV_PUT_SV (c);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
1586 2           c = c2;
1587 2           goto restart;
1588             }
1589             }
1590              
1591 1561 100         if (c2 == CH_CR) {
1592             int c3;
1593              
1594 200 100         if (csv->eol_is_cr) {
1595             /* ,1,"foo, 3"\r
1596             * ^
1597             */
1598 102 100         AV_PUSH;
    50          
    0          
    0          
    100          
    50          
    50          
    0          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
1599 102           return TRUE;
1600             }
1601              
1602 98 100         c3 = CSV_GET;
1603              
1604 98 100         if (c3 == CH_NL) { /* \r is not optional before EOLX! */
1605             /* ,1,"foo, 3"\r\n
1606             * ^
1607             */
1608 84 100         AV_PUSH;
    50          
    0          
    0          
    100          
    50          
    50          
    0          
    100          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    0          
1609 84           return TRUE;
1610             }
1611              
1612 14 100         if (csv->useIO && csv->eol_len == 0) {
    50          
1613 1 50         if (c3 == CH_CR) { /* \r followed by an empty line */
1614             /* ,1,"foo, 3"\r\r
1615             * ^
1616             */
1617 0           set_eol_is_cr (csv);
1618 0           goto EOLX;
1619             }
1620              
1621 1 50         if (!is_csv_binary (c3)) {
    50          
    0          
1622             /* ,1,"foo\n 3",,"bar"\r
1623             * baz,4
1624             * ^
1625             */
1626 1           set_eol_is_cr (csv);
1627 1           csv->used--;
1628 1           csv->has_ahead++;
1629 1 50         AV_PUSH;
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
1630 1           return TRUE;
1631             }
1632             }
1633              
1634 13 100         ParseError (csv, quoesc ? 2023 : 2010, csv->used - 2);
1635 13           return FALSE;
1636             }
1637              
1638 1361 100         if (c2 == EOF) {
1639             /* ,1,"foo, 3"
1640             * ^
1641             */
1642 1304 100         AV_PUSH;
    50          
    0          
    0          
    100          
    50          
    50          
    0          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    50          
    100          
    50          
1643 1304           return TRUE;
1644             }
1645              
1646 57 100         if (csv->allow_loose_quotes && !quoesc) {
    100          
1647             /* ,1,"foo, 3"456",,bar,\r\n
1648             * ^
1649             */
1650 10 50         CSV_PUT_SV (c);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    100          
1651 10           c = c2;
1652 10           goto restart;
1653             }
1654              
1655             /* 1,"foo" ",3
1656             * ^
1657             */
1658 47 100         if (quoesc) {
1659 39           csv->used--;
1660 39 50         ERROR_INSIDE_QUOTES (2023);
1661             }
1662              
1663 8 50         ERROR_INSIDE_QUOTES (2011);
1664             }
1665              
1666             /* !waitingForField, !InsideQuotes */
1667 82 100         if (csv->allow_loose_quotes) { /* 1,foo "boo" d'uh,1 */
1668 16           f |= CSV_FLAGS_EIF; /* Mark as error-in-field */
1669 16 50         CSV_PUT_SV (c);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
1670             }
1671             else
1672 50 100         ERROR_INSIDE_FIELD (2034);
1673             } /* QUO char */
1674             else
1675 162080 100         if (c == csv->escape_char && csv->escape_char) {
    100          
1676             #if MAINT_DEBUG > 1
1677             (void)fprintf (stderr, "# %d/%d/%03x pos %d = ESC '%c'\t%s\n",
1678             waitingForField ? 1 : 0, sv ? 1 : 0, f, spl, c,
1679             _pretty_strl (csv->bptr + csv->used));
1680             #endif
1681             /* This means quote_char != escape_char */
1682 9268 100         if (waitingForField) {
1683 33           waitingForField = 0;
1684 33 100         if (csv->allow_unquoted_escape) {
1685             /* The escape character is the first character of an
1686             * unquoted field */
1687             /* ... get and store next character */
1688 3 100         int c2 = CSV_GET;
1689              
1690 3           SvSetEmpty (sv);
1691              
1692 3 100         if (c2 == EOF) {
1693 1           csv->used--;
1694 1 50         ERROR_INSIDE_FIELD (2035);
1695             }
1696              
1697 2 100         if (c2 == '0')
1698 1 50         CSV_PUT_SV (0)
    50          
1699             else
1700 1 50         if ( is_QUOTE (c2) || is_SEP (c2) ||
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
1701 0 0         c2 == csv->escape_char || csv->allow_loose_escapes) {
1702 1 50         if (csv->utf8)
1703 0           f |= CSV_FLAGS_BIN;
1704 1 50         CSV_PUT_SV (c2)
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
1705             }
1706             else {
1707 0           csv->used--;
1708 32 0         ERROR_INSIDE_QUOTES (2025);
1709             }
1710             }
1711             }
1712             else
1713 4618 100         if (f & CSV_FLAGS_QUO) {
1714 4610 100         int c2 = CSV_GET;
1715              
1716 4610 100         if (c2 == EOF) {
1717 3           csv->used--;
1718 3 50         ERROR_INSIDE_QUOTES (2024);
1719             }
1720              
1721 4607 100         if (c2 == '0')
1722 2 50         CSV_PUT_SV (0)
    50          
1723             else
1724 4605 50         if ( is_QUOTE (c2) || is_SEP (c2) ||
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    0          
    0          
    0          
    100          
1725 28 100         c2 == csv->escape_char || csv->allow_loose_escapes) {
1726 4579 100         if (csv->utf8)
1727 1           f |= CSV_FLAGS_BIN;
1728 4582 50         CSV_PUT_SV (c2)
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    100          
    50          
    50          
    100          
    50          
    100          
1729             }
1730             else {
1731 26           csv->used--;
1732 4607 50         ERROR_INSIDE_QUOTES (2025);
1733             }
1734             }
1735             else
1736 8 50         if (sv) {
1737 8 100         int c2 = CSV_GET;
1738              
1739 8 100         if (c2 == EOF) {
1740 4           csv->used--;
1741 4 50         ERROR_INSIDE_FIELD (2035);
1742             }
1743              
1744 4 50         CSV_PUT_SV (c2);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
1745             }
1746             else
1747 0 0         ERROR_INSIDE_FIELD (2036); /* uncoverable statement I think there's no way to get here */
1748             } /* ESC char */
1749             else
1750 157429 100         if (c == CH_NL || is_EOL (c)) {
    100          
1751             EOLX:
1752             #if MAINT_DEBUG > 1
1753             (void)fprintf (stderr, "# %d/%d/%03x pos %d = NL\t%s\n",
1754             waitingForField ? 1 : 0, sv ? 1 : 0, f, spl,
1755             _pretty_strl (csv->bptr + csv->used));
1756             #endif
1757 2635 100         if (fnum == 1 && f == 0 && SvCUR (sv) == 0 && csv->skip_empty_rows) {
    100          
    100          
    100          
1758 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          
1759 37           goto restart;
1760             }
1761              
1762 2576 100         if (waitingForField) {
1763             /* ,1,"foo, 3",,bar,
1764             * ^
1765             */
1766 223 100         if (csv->blank_is_undef || csv->empty_is_undef)
    100          
1767 16           SvSetUndef (sv);
1768             else
1769 207           SvSetEmpty (sv);
1770 223 50         unless (csv->is_bound)
1771 223           av_push (fields, sv);
1772 223 100         if (csv->keep_meta_info && fflags)
    50          
1773 14           av_push (fflags, newSViv (f));
1774 223           return TRUE;
1775             }
1776              
1777 3086 100         if (f & CSV_FLAGS_QUO) {
1778             /* ,1,"foo\n 3",,bar,
1779             * ^
1780             */
1781 744           f |= CSV_FLAGS_BIN;
1782 744 100         unless (csv->binary)
1783 19 50         ERROR_INSIDE_QUOTES (2021);
1784              
1785 799 100         CSV_PUT_SV (c);
    100          
    50          
    50          
    100          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
1786             }
1787             else
1788 1609 100         if (csv->verbatim) {
1789             /* ,1,foo\n 3,,bar,
1790             * This feature should be deprecated
1791             */
1792 9           f |= CSV_FLAGS_BIN;
1793 9 100         unless (csv->binary)
1794 1 50         ERROR_INSIDE_FIELD (2030);
1795              
1796 14 100         CSV_PUT_SV (c);
    50          
    50          
    100          
    100          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
1797             }
1798             else {
1799             /* sep=,
1800             * ^
1801             */
1802 1600 100         if (csv->recno == 0 && csv->fld_idx == 1 && csv->useIO &&
    100          
    50          
    100          
1803 28 50         (csv->bptr[0] == 's' || csv->bptr[0] == 'S') &&
    50          
1804 5 0         (csv->bptr[1] == 'e' || csv->bptr[1] == 'E') &&
    50          
1805 5 0         (csv->bptr[2] == 'p' || csv->bptr[2] == 'P') &&
    50          
1806 5           csv->bptr[3] == '=') {
1807 5           char *sep = csv->bptr + 4;
1808 5           int lnu = csv->used - 5;
1809 5 100         if (lnu <= MAX_ATTR_LEN) {
1810 4           sep[lnu] = (char)0;
1811 4           (void)memcpy (csv->sep, sep, lnu);
1812 4 100         csv->sep_len = lnu == 1 ? 0 : lnu;
1813 4           return Parse (csv, src, fields, fflags);
1814             }
1815             }
1816              
1817             /* ,1,"foo\n 3",,bar
1818             * ^
1819             */
1820 1596 100         AV_PUSH;
    100          
    50          
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    100          
    100          
    100          
    50          
1821 1596           return TRUE;
1822             }
1823             } /* CH_NL */
1824             else
1825 155254 100         if (c == CH_CR && !(csv->verbatim)) {
    100          
1826             #if MAINT_DEBUG > 1
1827             (void)fprintf (stderr, "# %d/%d/%03x pos %d = CR\n",
1828             waitingForField ? 1 : 0, sv ? 1 : 0, f, spl);
1829             #endif
1830 1103 100         if (waitingForField) {
1831             int c2;
1832              
1833 114 100         if (csv->eol_is_cr) {
1834             /* ,1,"foo\n 3",,bar,\r
1835             * ^
1836             */
1837 29           c = CH_NL;
1838 29           goto EOLX;
1839             }
1840              
1841 85 100         c2 = CSV_GET;
1842              
1843 85 100         if (c2 == EOF) {
1844             /* ,1,"foo\n 3",,bar,\r
1845             * ^
1846             */
1847 5           c = EOF;
1848              
1849             #if MAINT_DEBUG > 9
1850             (void)fprintf (stderr, "# (%d) ... CR EOF 0x%x\n",
1851             seenSomething, c);
1852             #endif
1853 5 50         unless (seenSomething)
1854 0           break;
1855 5           goto restart;
1856             }
1857              
1858 80 100         if (c2 == CH_NL) { /* \r is not optional before EOLX! */
1859             /* ,1,"foo\n 3",,bar,\r\n
1860             * ^
1861             */
1862 70           c = c2;
1863 70           goto EOLX;
1864             }
1865              
1866 10 100         if (csv->useIO && csv->eol_len == 0) {
    50          
1867 5 50         if (c2 == CH_CR) { /* \r followed by an empty line */
1868             /* ,1,"foo\n 3",,bar,\r\r
1869             * ^
1870             */
1871 0           set_eol_is_cr (csv);
1872 0           goto EOLX;
1873             }
1874              
1875 5           waitingForField = 0;
1876              
1877 5 100         if (!is_csv_binary (c2)) {
    50          
    50          
1878             /* ,1,"foo\n 3",,bar,\r
1879             * baz,4
1880             * ^
1881             */
1882 2           set_eol_is_cr (csv);
1883 2           csv->used--;
1884 2           csv->has_ahead++;
1885 2 100         if (fnum == 1 && f == 0 && SvCUR (sv) == 0 && csv->skip_empty_rows) {
    50          
    50          
    50          
1886 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          
1887 1           goto restart;
1888             }
1889 1 50         AV_PUSH;
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
1890 1           return TRUE;
1891             }
1892             }
1893              
1894             /* ,1,"foo\n 3",,bar,\r\t
1895             * ^
1896             */
1897 8           csv->used--;
1898 8 50         ERROR_INSIDE_FIELD (2031);
1899             }
1900              
1901 1539 100         if (f & CSV_FLAGS_QUO) {
1902             /* ,1,"foo\r 3",,bar,\r\t
1903             * ^
1904             */
1905 620           f |= CSV_FLAGS_BIN;
1906 620 100         unless (csv->binary)
1907 70 50         ERROR_INSIDE_QUOTES (2022);
1908              
1909 550 50         CSV_PUT_SV (c);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    100          
1910             }
1911             else {
1912             int c2;
1913              
1914 369 100         if (csv->eol_is_cr) {
1915             /* ,1,"foo\n 3",,bar\r
1916             * ^
1917             */
1918 181           goto EOLX;
1919             }
1920              
1921 188 100         c2 = CSV_GET;
1922              
1923 188 100         if (c2 == CH_NL) { /* \r is not optional before EOLX! */
1924             /* ,1,"foo\n 3",,bar\r\n
1925             * ^
1926             */
1927 172           goto EOLX;
1928             }
1929              
1930 16 100         if (csv->useIO && csv->eol_len == 0) {
    50          
1931 11 100         if (!is_csv_binary (c2)
    50          
    50          
1932             /* ,1,"foo\n 3",,bar\r
1933             * baz,4
1934             * ^
1935             */
1936 7 100         || c2 == CH_CR) {
1937             /* ,1,"foo\n 3",,bar,\r\r
1938             * ^
1939             */
1940 5           set_eol_is_cr (csv);
1941 5           csv->used--;
1942 5           csv->has_ahead++;
1943 5 50         if (fnum == 1 && f == 0 && SvCUR (sv) == 0 && csv->skip_empty_rows) {
    0          
    0          
    0          
1944 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          
1945 0           goto restart;
1946             }
1947 5 50         AV_PUSH;
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
1948 5           return TRUE;
1949             }
1950             }
1951              
1952             /* ,1,"foo\n 3",,bar\r\t
1953             * ^
1954             */
1955 11 50         ERROR_INSIDE_FIELD (2032);
1956             }
1957             } /* CH_CR */
1958             else {
1959             #if MAINT_DEBUG > 1
1960             (void)fprintf (stderr, "# %d/%d/%03x pos %d = CCC '%c'\t\t%s\n",
1961             waitingForField ? 1 : 0, sv ? 1 : 0, f, spl, c,
1962             _pretty_strl (csv->bptr + csv->used));
1963             #endif
1964             /* Needed for non-IO parse, where EOL is not set during read */
1965 154151 100         if (csv->eolx && c == CH_EOL &&
    100          
    50          
1966 8 50         csv->size - csv->used >= (STRLEN)csv->eol_len - 1 &&
1967 8 50         !memcmp (csv->bptr + csv->used, csv->eol + 1, csv->eol_len - 1) &&
1968 8           (csv->used += csv->eol_len - 1)) {
1969 8           c = CH_EOLX;
1970             #if MAINT_DEBUG > 5
1971             (void)fprintf (stderr, "# -> EOLX (0x%x)\n", c);
1972             #endif
1973 8           goto EOLX;
1974             }
1975              
1976 154143 100         if (waitingForField) {
1977 10680 100         if (csv->comment_str && !f && !spl && c == *csv->comment_str) {
    50          
    100          
    100          
1978 24           STRLEN cl = strlen ((char *)csv->comment_str);
1979              
1980             #if MAINT_DEBUG > 5
1981             (void)fprintf (stderr,
1982             "COMMENT? cl = %d, size = %d, used = %d\n",
1983             cl, csv->size, csv->used);
1984             #endif
1985 24 100         if (cl == 1 || (
    50          
1986 18 50         (csv->size - csv->used >= cl - 1 &&
1987 18 50         !memcmp (csv->bptr + csv->used, csv->comment_str + 1, cl - 1) &&
1988 18           (csv->used += cl - 1)))) {
1989 24           csv->used = csv->size;
1990 24           csv->fld_idx = 0;
1991 24 50         c = CSV_GET;
1992             #if MAINT_DEBUG > 5
1993             (void)fprintf (stderr, "# COMMENT, SKIPPED\n");
1994             #endif
1995 24           goto restart;
1996             }
1997             }
1998              
1999 10656 100         if (csv->allow_whitespace && is_whitespace (c)) {
    50          
    50          
    50          
    100          
    50          
2000             do {
2001 311 100         c = CSV_GET;
2002             #if MAINT_DEBUG > 5
2003             (void)fprintf (stderr, "# WS next got (0x%x)\n", c);
2004             #endif
2005 311 100         } while (is_whitespace (c));
    100          
    50          
    100          
    50          
2006 201 100         if (c == EOF)
2007 1           break;
2008 200           goto restart;
2009             }
2010 10455           waitingForField = 0;
2011 10455           goto restart;
2012             }
2013              
2014             #if MAINT_DEBUG > 5
2015             (void)fprintf (stderr, "# %sc 0x%x is%s binary %s utf8\n",
2016             f & CSV_FLAGS_QUO ? "quoted " : "", c,
2017             is_csv_binary (c) ? "" : " not",
2018             csv->utf8 ? "is" : "not");
2019             #endif
2020 143463 100         if (f & CSV_FLAGS_QUO) {
2021 111032 100         if (is_csv_binary (c)) {
    100          
    100          
2022 3454           f |= CSV_FLAGS_BIN;
2023 3454 100         unless (csv->binary || csv->utf8)
    100          
2024 5 50         ERROR_INSIDE_QUOTES (2026);
2025             }
2026 111027 50         CSV_PUT_SV (c);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    100          
2027             }
2028             else {
2029 32431 100         if (is_csv_binary (c)) {
    100          
    100          
2030 453 100         if (csv->useIO && c == EOF)
    100          
2031 3           break;
2032 450           f |= CSV_FLAGS_BIN;
2033 450 100         unless (csv->binary || csv->utf8)
    50          
2034 9 50         ERROR_INSIDE_FIELD (2037);
2035             }
2036 32419 50         CSV_PUT_SV (c);
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    50          
    100          
2037             }
2038             }
2039              
2040             /* continue */
2041 161181 100         if (csv->verbatim && csv->useIO && csv->used == csv->size)
    100          
    100          
2042 3           break;
2043             }
2044              
2045 746 100         if (waitingForField) {
2046 366 100         if (seenSomething || !csv->useIO) {
    100          
2047 34 100         NewField;
    100          
    50          
2048 34 100         if (csv->blank_is_undef || csv->empty_is_undef)
    100          
2049 8           SvSetUndef (sv);
2050             else
2051 26           SvSetEmpty (sv);
2052 34 100         unless (csv->is_bound)
2053 33           av_push (fields, sv);
2054 34 100         if (csv->keep_meta_info && fflags)
    50          
2055 3           av_push (fflags, newSViv (f));
2056 34           return TRUE;
2057             }
2058              
2059 332           (void)SetDiag (csv, 2012);
2060 332           return FALSE;
2061             }
2062              
2063 380 100         if (f & CSV_FLAGS_QUO)
2064 24 50         ERROR_INSIDE_QUOTES (2027);
2065              
2066 356 100         if (sv) {
2067 354 100         AV_PUSH;
    100          
    50          
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    100          
    100          
    100          
    100          
    50          
2068             }
2069 2 50         else if (f == 0 && fnum == 1 && csv->skip_empty_rows == 1)
    50          
    50          
2070 2           return FALSE;
2071 354           return TRUE;
2072             } /* Parse */
2073              
2074 125           static int hook (pTHX_ HV *hv, char *cb_name, AV *av) {
2075             SV **svp;
2076             HV *cb;
2077             int res;
2078              
2079             #if MAINT_DEBUG > 1
2080             (void)fprintf (stderr, "# HOOK %s %x\n", cb_name, av);
2081             #endif
2082 125 50         unless ((svp = hv_fetchs (hv, "callbacks", FALSE)) && _is_hashref (*svp))
    50          
    50          
    0          
    50          
    50          
2083 0           return 0; /* uncoverable statement defensive programming */
2084              
2085 125           cb = (HV *)SvRV (*svp);
2086 125           svp = hv_fetch (cb, cb_name, strlen (cb_name), FALSE);
2087 125 50         unless (svp && _is_coderef (*svp))
    50          
    50          
    0          
    50          
    50          
2088 0           return 0;
2089              
2090 125           { dSP;
2091 125           ENTER;
2092 125           SAVETMPS;
2093 125 50         PUSHMARK (SP);
2094 125 50         mXPUSHs (newRV_inc ((SV *)hv));
2095 125 50         mXPUSHs (newRV_inc ((SV *)av));
2096 125           PUTBACK;
2097 125           res = call_sv (*svp, G_SCALAR);
2098 125           SPAGAIN;
2099 125 50         if (res) {
2100 125           SV *rv = POPs;
2101 125 100         if (SvROK (rv) && (rv = SvRV (rv)) && SvPOK (rv)) {
    50          
    50          
2102 64 50         if (strcmp (SvPV_nolen (rv), "skip") == 0)
    50          
2103 64           res = 0;
2104             }
2105             }
2106 125           PUTBACK;
2107 125 50         FREETMPS;
2108 125           LEAVE;
2109             }
2110 125           return res;
2111             } /* hook */
2112              
2113             #define c_xsParse(csv,hv,av,avf,src,useIO) cx_c_xsParse (aTHX_ csv, hv, av, avf, src, useIO)
2114 4550           static int cx_c_xsParse (pTHX_ csv_t csv, HV *hv, AV *av, AV *avf, SV *src, bool useIO) {
2115 4550           int result, ahead = 0;
2116 4550           SV *pos = NULL;
2117              
2118 4550           ENTER;
2119 4550 100         if (csv.eolx || csv.eol_is_cr) {
    100          
2120             /* local $/ = $eol */
2121 849           SAVEGENERICSV (PL_rs);
2122 849           PL_rs = newSVpvn ((char *)csv.eol, csv.eol_len);
2123             }
2124              
2125 4550 100         if ((csv.useIO = useIO)) {
2126 2622           csv.tmp = NULL;
2127              
2128 2622 100         if ((ahead = csv.has_ahead)) {
2129             SV **svp;
2130 176 50         if ((svp = hv_fetchs (hv, "_AHEAD", FALSE)) && *svp) {
    50          
2131 176 100         csv.bptr = SvPV (csv.tmp = *svp, csv.size);
2132 176           csv.used = 0;
2133 176 50         if (pos && SvIV (pos) > (IV)csv.size)
    0          
    0          
2134 2622 0         sv_setiv (pos, SvIV (pos) - csv.size);
2135             }
2136             }
2137             }
2138             else {
2139 1928           csv.tmp = src;
2140 1928           csv.utf8 = SvUTF8 (src) ? 1 : 0;
2141 1928 50         csv.bptr = SvPV (src, csv.size);
2142             }
2143 4550 100         if (csv.has_error_input) {
2144 217           (void)hv_store (hv, "_ERROR_INPUT", 12, &PL_sv_undef, 0);
2145 217           csv.has_error_input = 0;
2146             }
2147              
2148 4550           result = Parse (&csv, src, av, avf);
2149 4539           (void)hv_store (hv, "_RECNO", 6, newSViv (++csv.recno), 0);
2150 4539           (void)hv_store (hv, "_EOF", 4, &PL_sv_no, 0);
2151              
2152 4539 100         if (csv.strict) {
2153 27 100         unless (csv.strict_n) csv.strict_n = (short)csv.fld_idx;
2154 27 100         if (csv.fld_idx != csv.strict_n) {
2155 12 100         unless (csv.useIO & useIO_EOF)
2156 8           ParseError (&csv, 2014, csv.used);
2157 12 100         if (last_error) /* an error callback can reset and accept */
2158 8           result = FALSE;
2159             }
2160             }
2161              
2162 4539 100         if (csv.useIO) {
2163 2651 50         if (csv.tmp && csv.used < csv.size && csv.has_ahead) {
    100          
    100          
2164 37           SV *sv = newSVpvn (csv.bptr + csv.used, csv.size - csv.used);
2165 37           (void)hv_store (hv, "_AHEAD", 6, sv, 0);
2166             }
2167             else {
2168 2577           csv.has_ahead = 0;
2169 2577 100         if (csv.useIO & useIO_EOF)
2170 549           (void)hv_store (hv, "_EOF", 4, &PL_sv_yes, 0);
2171             }
2172             /* csv.cache[CACHE_ID__has_ahead] = csv.has_ahead; */
2173 2614           (void)memcpy (csv.cache, &csv, sizeof (csv_t));
2174              
2175 2614 100         if (avf) {
2176 1580 100         if (csv.keep_meta_info)
2177 11           (void)hv_store (hv, "_FFLAGS", 7, newRV_noinc ((SV *)avf), 0);
2178             else {
2179 1569           av_undef (avf);
2180 2614           sv_free ((SV *)avf);
2181             }
2182             }
2183             }
2184             else /* just copy the cache */
2185 1925           (void)memcpy (csv.cache, &csv, sizeof (csv_t));
2186              
2187 4539 100         if (result && csv.types) {
    100          
2188             STRLEN i;
2189 2           STRLEN len = av_len (av);
2190             SV **svp;
2191              
2192 8 100         for (i = 0; i <= len && i <= csv.types_len; i++) {
    50          
2193 6 50         if ((svp = av_fetch (av, i, FALSE)) && *svp && SvOK (*svp)) {
    50          
    50          
    0          
    0          
2194 6           switch (csv.types[i]) {
2195             case CSV_XS_TYPE_IV:
2196             #ifdef CSV_XS_TYPE_WARN
2197 2 50         sv_setiv (*svp, SvIV (*svp));
2198             #else
2199             if (SvTRUE (*svp))
2200             sv_setiv (*svp, SvIV (*svp));
2201             else
2202             sv_setiv (*svp, 0);
2203             #endif
2204 2           break;
2205              
2206             case CSV_XS_TYPE_NV:
2207             #ifdef CSV_XS_TYPE_WARN
2208 2 50         sv_setnv (*svp, SvNV (*svp));
2209             #else
2210             if (SvTRUE (*svp))
2211             sv_setnv (*svp, SvNV (*svp));
2212             else
2213             sv_setnv (*svp, 0.0);
2214             #endif
2215 2           break;
2216              
2217             default:
2218 2           break;
2219             }
2220             }
2221             }
2222             }
2223              
2224 4539           LEAVE;
2225              
2226 4539           return result;
2227             } /* c_xsParse */
2228              
2229             #define xsParse(self,hv,av,avf,src,useIO) cx_xsParse (aTHX_ self, hv, av, avf, src, useIO)
2230 3510           static int cx_xsParse (pTHX_ SV *self, HV *hv, AV *av, AV *avf, SV *src, bool useIO) {
2231             csv_t csv;
2232             int state;
2233 3510           SetupCsv (&csv, hv, self);
2234 3510           state = c_xsParse (csv, hv, av, avf, src, useIO);
2235 3505 100         if (state && csv.has_hooks & HOOK_AFTER_PARSE)
    100          
2236 5           (void)hook (aTHX_ hv, "after_parse", av);
2237 3505 100         return (state || !last_error);
    100          
2238             } /* xsParse */
2239              
2240             /* API also offers av_clear and av_undef, but they have more overhead */
2241             #define av_empty(av) cx_av_empty (aTHX_ av)
2242 83           static void cx_av_empty (pTHX_ AV *av) {
2243 333 100         while (av_len (av) >= 0)
2244 250           sv_free (av_pop (av));
2245 83           } /* av_empty */
2246              
2247             #define xsParse_all(self,hv,io,off,len) cx_xsParse_all (aTHX_ self, hv, io, off, len)
2248 334           static SV *cx_xsParse_all (pTHX_ SV *self, HV *hv, SV *io, SV *off, SV *len) {
2249             csv_t csv;
2250 334           int n = 0, skip = 0, length = MAXINT, tail = MAXINT;
2251 334           AV *avr = newAV ();
2252 334           AV *row = newAV ();
2253              
2254 334           SetupCsv (&csv, hv, self);
2255              
2256 334 100         if (SvOK (off)) {
    50          
    50          
2257 56 100         skip = SvIV (off);
2258 56 100         if (skip < 0) {
2259 12           tail = -skip;
2260 12           skip = -1;
2261             }
2262             }
2263 334 100         if (SvOK (len))
    50          
    50          
2264 44 100         length = SvIV (len);
2265              
2266 1040 100         while (c_xsParse (csv, hv, row, NULL, io, 1)) {
2267              
2268 738           SetupCsv (&csv, hv, self);
2269              
2270 738 100         if (skip > 0) {
2271 20           skip--;
2272 20           av_empty (row); /* re-use */
2273 20           continue;
2274             }
2275              
2276 718 100         if (n++ >= tail) {
2277 12           SvREFCNT_dec (av_shift (avr));
2278 12           n--;
2279             }
2280              
2281 718 100         if (csv.has_hooks & HOOK_AFTER_PARSE) {
2282 117 100         unless (hook (aTHX_ hv, "after_parse", row)) {
2283 63           av_empty (row); /* re-use */
2284 63           continue;
2285             }
2286             }
2287 655           av_push (avr, newRV_noinc ((SV *)row));
2288              
2289 655 100         if (n >= length && skip >= 0)
    100          
2290 32           break; /* We have enough */
2291              
2292 623           row = newAV ();
2293             }
2294 336 100         while (n > length) {
2295 8           SvREFCNT_dec (av_pop (avr));
2296 8           n--;
2297             }
2298              
2299 328           return (SV *)sv_2mortal (newRV_noinc ((SV *)avr));
2300             } /* xsParse_all */
2301              
2302             #define xsCombine(self,hv,av,io,useIO) cx_xsCombine (aTHX_ self, hv, av, io, useIO)
2303 21647           static int cx_xsCombine (pTHX_ SV *self, HV *hv, AV *av, SV *io, bool useIO) {
2304             csv_t csv;
2305             int result;
2306             #if (PERL_BCDVERSION >= 0x5008000)
2307 21647           SV *ors = PL_ors_sv;
2308             #endif
2309              
2310 21647           SetupCsv (&csv, hv, self);
2311 21647           csv.useIO = useIO;
2312             #if (PERL_BCDVERSION >= 0x5008000)
2313 21647 100         if (*csv.eol)
2314 260           PL_ors_sv = NULL;
2315             #endif
2316 21647 100         if (useIO && csv.has_hooks & HOOK_BEFORE_PRINT)
    100          
2317 3           (void)hook (aTHX_ hv, "before_print", av);
2318 21647           result = Combine (&csv, io, av);
2319             #if (PERL_BCDVERSION >= 0x5008000)
2320 21643           PL_ors_sv = ors;
2321             #endif
2322 21643 100         if (result && !useIO && csv.utf8)
    100          
    100          
2323 25           sv_utf8_upgrade (io);
2324 21643           return result;
2325             } /* xsCombine */
2326              
2327             MODULE = Text::CSV_XS PACKAGE = Text::CSV_XS
2328              
2329             PROTOTYPES: DISABLE
2330              
2331             BOOT:
2332 32           m_getline = newSVpvs ("getline");
2333 32           m_print = newSVpvs ("print");
2334 32           Perl_load_module (aTHX_ PERL_LOADMOD_NOIMPORT, newSVpvs ("IO::Handle"), NULL, NULL, NULL);
2335              
2336             void
2337             SetDiag (SV *self, int xse, ...)
2338              
2339             PPCODE:
2340             HV *hv;
2341             csv_t csv;
2342              
2343 2940 50         if (SvOK (self) && SvROK (self)) {
    0          
    0          
    100          
2344 1047 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2345 1047           SetupCsv (&csv, hv, self);
2346 1047           ST (0) = SetDiag (&csv, xse);
2347             }
2348             else {
2349 1893           last_error = xse;
2350 1893           ST (0) = sv_2mortal (SvDiag (xse));
2351             }
2352              
2353 2940 100         if (xse && items > 2 && SvPOK (ST (2))) {
    100          
    50          
2354 941           sv_setpvn (ST (0), SvPVX (ST (2)), SvCUR (ST (2)));
2355 941           SvIOK_on (ST (0));
2356             }
2357              
2358 2940           XSRETURN (1);
2359             /* XS SetDiag */
2360              
2361             void
2362             error_input (SV *self)
2363              
2364             PPCODE:
2365 12 50         if (self && SvOK (self) && SvROK (self) && SvTYPE (SvRV (self)) == SVt_PVHV) {
    100          
    50          
    50          
    100          
    100          
2366 4           HV *hv = (HV *)SvRV (self);
2367 4           SV **sv = hv_fetchs (hv, "_ERROR_INPUT", FALSE);
2368 4 100         if (SvOK (*sv))
    50          
    50          
2369 3           ST (0) = *sv;
2370             else
2371 1           ST (0) = newSV (0);
2372             }
2373             else
2374 4           ST (0) = newSV (0);
2375              
2376 8           XSRETURN (1);
2377             /* XS error_input */
2378              
2379             void
2380             Combine (SV *self, SV *dst, SV *fields, bool useIO)
2381              
2382             PPCODE:
2383             HV *hv;
2384             AV *av;
2385              
2386 1396 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2387 1396           av = (AV *)SvRV (fields);
2388 1396 100         ST (0) = xsCombine (self, hv, av, dst, useIO) ? &PL_sv_yes : &PL_sv_undef;
2389 1392           XSRETURN (1);
2390             /* XS Combine */
2391              
2392             void
2393             Parse (SV *self, SV *src, SV *fields, SV *fflags)
2394              
2395             PPCODE:
2396             HV *hv;
2397             AV *av;
2398             AV *avf;
2399              
2400 1928 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2401 1928           av = (AV *)SvRV (fields);
2402 1928           avf = (AV *)SvRV (fflags);
2403              
2404 1928 100         ST (0) = xsParse (self, hv, av, avf, src, 0) ? &PL_sv_yes : &PL_sv_no;
2405 1925           XSRETURN (1);
2406             /* XS Parse */
2407              
2408             void
2409             print (SV *self, SV *io, SV *fields)
2410              
2411             PPCODE:
2412             HV *hv;
2413             AV *av;
2414              
2415 20256 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2416 20256 100         if (fields == &PL_sv_undef)
2417 5           av = newAV ();
2418             else {
2419 20251 50         unless (_is_arrayref (fields))
    100          
    50          
    100          
    100          
2420 5           croak ("Expected fields to be an array ref");
2421              
2422 20246           av = (AV *)SvRV (fields);
2423             }
2424              
2425 20251 100         ST (0) = xsCombine (self, hv, av, io, 1) ? &PL_sv_yes : &PL_sv_no;
2426 20251           XSRETURN (1);
2427             /* XS print */
2428              
2429             void
2430             getline (SV *self, SV *io)
2431              
2432             PPCODE:
2433             HV *hv;
2434             AV *av;
2435             AV *avf;
2436              
2437 1582 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2438 1582           av = newAV ();
2439 1582           avf = newAV ();
2440 1582           ST (0) = xsParse (self, hv, av, avf, io, 1)
2441 1443           ? sv_2mortal (newRV_noinc ((SV *)av))
2442 3023 100         : &PL_sv_undef;
2443 1580           XSRETURN (1);
2444             /* XS getline */
2445              
2446             void
2447             getline_all (SV *self, SV *io, ...)
2448              
2449             PPCODE:
2450             HV *hv;
2451             SV *offset, *length;
2452              
2453 334 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2454              
2455 334 100         offset = items > 2 ? ST (2) : &PL_sv_undef;
2456 334 100         length = items > 3 ? ST (3) : &PL_sv_undef;
2457              
2458 334           ST (0) = xsParse_all (self, hv, io, offset, length);
2459 328           XSRETURN (1);
2460             /* XS getline_all */
2461              
2462             void
2463             _cache_set (SV *self, int idx, SV *val)
2464              
2465             PPCODE:
2466             HV *hv;
2467              
2468 23241 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2469 23241           xs_cache_set (hv, idx, val);
2470 23241           XSRETURN (1);
2471             /* XS _cache_set */
2472              
2473             void
2474             _cache_diag (SV *self)
2475              
2476             PPCODE:
2477             HV *hv;
2478              
2479 2 50         CSV_XS_SELF;
    50          
    0          
    0          
    50          
    50          
2480 2           xs_cache_diag (hv);
2481 2           XSRETURN (1);
2482             /* XS _cache_diag */