File Coverage

CSV_XS.xs
Criterion Covered Total %
statement 1110 1147 96.7
branch 1570 2808 55.9
condition n/a
subroutine n/a
pod n/a
total 2680 3955 67.7


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