On Tue, May 21, 2002 at 05:32:10PM +0200, Stig S. Bakken wrote: > > I wasn't sure if I could just attach my file.c.patch file to this email > > or not? > > That's fine, but make sure the MIME type for the attachment is > text/plain or the mailing list software will remove it.
Ok, here is my first try! :) (please let me know if its ok). TIA - Dean
? file.c.patch
Index: file.c
===================================================================
RCS file: /repository/php4/ext/standard/file.c,v
retrieving revision 1.229
diff -u -r1.229 file.c
--- file.c 12 May 2002 15:59:42 -0000 1.229
+++ file.c 21 May 2002 15:24:42 -0000
@@ -1928,168 +1928,196 @@
Get line from file pointer and parse for CSV fields */
PHP_FUNCTION(fgetcsv)
{
- char *temp, *tptr, *bptr, *lineEnd;
- char delimiter = ','; /* allow this to be set as parameter */
-
- /* first section exactly as php_fgetss */
-
- zval **fd, **bytes, **p_delim;
- int len, type;
- char *buf;
- php_stream *stream;
-
- switch(ZEND_NUM_ARGS()) {
- case 2:
- if (zend_get_parameters_ex(2, &fd, &bytes) == FAILURE) {
- WRONG_PARAM_COUNT;
- }
- break;
-
- case 3:
- if (zend_get_parameters_ex(3, &fd, &bytes, &p_delim) == FAILURE) {
- WRONG_PARAM_COUNT;
- }
- convert_to_string_ex(p_delim);
- /* Make sure that there is at least one character in string */
- if (Z_STRLEN_PP(p_delim) < 1) {
- WRONG_PARAM_COUNT;
- }
- /* use first character from string */
- delimiter = Z_STRVAL_PP(p_delim)[0];
- break;
-
- default:
- WRONG_PARAM_COUNT;
- /* NOTREACHED */
- break;
- }
-
- stream = (php_stream*)zend_fetch_resource(fd TSRMLS_CC,-1, "File-Handle",
&type, 1, le_stream);
- ZEND_VERIFY_RESOURCE(stream);
-
- convert_to_long_ex(bytes);
- len = Z_LVAL_PP(bytes);
- if (len < 0) {
- php_error(E_WARNING, "length parameter to fgetcsv() may not be
negative");
- RETURN_FALSE;
- }
-
- buf = emalloc(len + 1);
- /*needed because recv/read/gzread doesnt set null char at end*/
- memset(buf, 0, len + 1);
-
- if (php_stream_gets(stream, buf, len) == NULL) {
- efree(buf);
- RETURN_FALSE;
- }
-
- /* Now into new section that parses buf for comma/quote delimited fields */
-
- /* Strip trailing space from buf, saving end of line in case required for
quoted field */
-
- lineEnd = emalloc(len + 1);
- bptr = buf;
- tptr = buf + strlen(buf) -1;
- while ( isspace((int) *tptr) && (*tptr!=delimiter) && (tptr > bptr) ) tptr--;
- tptr++;
- strcpy(lineEnd, tptr);
-
- /* add single space - makes it easier to parse trailing null field */
- *tptr++ = ' ';
- *tptr = 0;
-
- /* reserve workspace for building each individual field */
-
- temp = emalloc(len); /* unlikely but possible! */
- tptr = temp;
-
- /* Initialize return array */
- array_init(return_value);
-
- /* Main loop to read CSV fields */
- /* NB this routine will return a single null entry for a blank line */
-
- do {
- /* 1. Strip any leading space */
- while(isspace((int) *bptr) && (*bptr!=delimiter)) bptr++;
- /* 2. Read field, leaving bptr pointing at start of next field */
- if (*bptr == '"') {
- /* 2A. handle quote delimited field */
- bptr++; /* move on to first character in field */
- while (*bptr) {
- if (*bptr == '"') {
- /* handle the double-quote */
- if ( *(bptr+1) == '"') {
- /* embedded double quotes */
- *tptr++ = *bptr; bptr +=2;
- } else {
- /* must be end of string - skip to start of
next field or end */
- while ( (*bptr != delimiter) && *bptr
) bptr++;
- if (*bptr == delimiter) bptr++;
- *tptr=0; /* terminate temporary
string */
- break; /* .. from handling this field
- resumes at 3. */
- }
- } else {
- /* normal character */
- *tptr++ = *bptr++;
-
- if (*bptr == 0) { /* embedded line end?
*/
- *(tptr-1)=0; /* remove
space character added on reading line */
- strcat(temp, lineEnd); /* add the
embedded line end to the field */
-
- /* read a new line from input, as at
start of routine */
- memset(buf, 0, len+1);
-
- if (php_stream_gets(stream, buf, len)
== NULL) {
- efree(lineEnd);
- efree(temp);
- efree(buf);
- zval_ptr_dtor(&return_value);
- RETURN_FALSE;
- }
-
- bptr = buf;
- tptr = buf + strlen(buf) -1;
- while (isspace((int) *tptr) &&
(*tptr!=delimiter) && (tptr > bptr))
- tptr--;
- tptr++;
- strcpy(lineEnd, tptr);
- *tptr++ = ' ';
- *tptr = 0;
-
- tptr = temp; /* reset temp
pointer to end of field as read so far */
- while (*tptr)
- tptr++;
- }
- }
- }
- } else {
- /* 2B. Handle non-quoted field */
- while ((*bptr != delimiter) && *bptr)
- *tptr++ = *bptr++;
- *tptr=0; /* terminate temporary string */
-
- if (strlen(temp)) {
- tptr--;
- while (isspace((int)*tptr) && (*tptr!=delimiter))
- *tptr-- = 0; /* strip any trailing spaces */
- }
-
- if (*bptr == delimiter)
- bptr++;
- }
-
- /* 3. Now pass our field back to php */
- add_next_index_string(return_value, temp, 1);
- tptr = temp;
- } while (*bptr);
-
- efree(lineEnd);
- efree(temp);
- efree(buf);
+ char *temp, *tptr, *bptr, *lineEnd;
+ char delimiter = ','; /* allow this to be set as parameter */
+ char enclosure = '"'; /* allow this to be set as parameter */
+
+ /* first section exactly as php_fgetss */
+
+ zval **fd, **bytes, **p_delim, **p_enclosure;
+ int len, type;
+ char *buf;
+ int issock=0;
+ int socketd=0;
+ void *what;
+
+ switch(ZEND_NUM_ARGS()) {
+ case 2:
+ if (zend_get_parameters_ex(2, &fd, &bytes) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ break;
+
+ case 3:
+ if (zend_get_parameters_ex(3, &fd, &bytes, &p_delim) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string_ex(p_delim);
+ /* Make sure that there is at least one character in string */
+ if (Z_STRLEN_PP(p_delim) < 1) {
+ WRONG_PARAM_COUNT;
+ }
+ /* use first character from string */
+ delimiter = Z_STRVAL_PP(p_delim)[0];
+ break;
+
+ case 4:
+ if (zend_get_parameters_ex(4, &fd, &bytes, &p_delim, &p_enclosure) ==
+FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string_ex(p_delim);
+ /* Make sure that there is at least one character in string */
+ if (Z_STRLEN_PP(p_delim) < 1) {
+ WRONG_PARAM_COUNT;
+ }
+ /* use first character from string */
+ delimiter = Z_STRVAL_PP(p_delim)[0];
+
+ convert_to_string_ex(p_enclosure);
+ /* Make sure that there is at least one character in string */
+ if (Z_STRLEN_PP(p_enclosure) < 1) {
+ WRONG_PARAM_COUNT;
+ }
+ /* use first character from string */
+ enclosure = Z_STRVAL_PP(p_enclosure)[0];
+
+ break;
+
+ default:
+ WRONG_PARAM_COUNT;
+ /* NOTREACHED */
+ break;
+ }
+ /* XXX: add stream support --Wez. */
+
+ what = zend_fetch_resource(fd TSRMLS_CC,-1, "File-Handle", &type, 3,
+le_fopen, le_popen, le_socket);
+ ZEND_VERIFY_RESOURCE(what);
+
+ if (type == le_socket) {
+ issock = 1;
+ socketd = *(int *) what;
+ }
+
+ convert_to_long_ex(bytes);
+ len = Z_LVAL_PP(bytes);
+ if (len < 0) {
+ php_error(E_WARNING, "length parameter to fgetcsv() may not be
+negative");
+ RETURN_FALSE;
+ }
+
+ buf = emalloc(len + 1);
+ /*needed because recv doesnt set null char at end*/
+ memset(buf, 0, len + 1);
+ if (FP_FGETS(buf, len, socketd, (FILE *) what, issock) == NULL) {
+ efree(buf);
+ RETURN_FALSE;
+ }
+
+ /* Now into new section that parses buf for delimiter/enclosure fields */
+
+ /* Strip trailing space from buf, saving end of line in case required for
+enclosure field */
+
+ lineEnd = emalloc(len + 1);
+ bptr = buf;
+ tptr = buf + strlen(buf) -1;
+ while ( isspace((int) *tptr) && (*tptr!=delimiter) && (tptr > bptr) ) tptr--;
+ tptr++;
+ strcpy(lineEnd, tptr);
+
+ /* add single space - makes it easier to parse trailing null field */
+ *tptr++ = ' ';
+ *tptr = 0;
+
+ /* reserve workspace for building each individual field */
+
+ temp = emalloc(len); /* unlikely but possible! */
+ tptr = temp;
+
+ /* Initialize return array */
+ array_init(return_value);
+
+ /* Main loop to read CSV fields */
+ /* NB this routine will return a single null entry for a blank line */
+
+ do {
+ /* 1. Strip any leading space */
+ while(isspace((int) *bptr) && (*bptr!=delimiter)) bptr++;
+ /* 2. Read field, leaving bptr pointing at start of next field */
+ if (*bptr == enclosure) {
+ /* 2A. handle enclosure delimited field */
+ bptr++; /* move on to first character in field */
+ while (*bptr) {
+ if (*bptr == enclosure) {
+ /* handle the enclosure */
+ if ( *(bptr+1) == enclosure) {
+ /* embedded enclosure */
+ *tptr++ = *bptr; bptr +=2;
+ } else {
+ /* must be end of string - skip to start of
+next field or end */
+ while ( (*bptr != delimiter) && *bptr
+) bptr++;
+ if (*bptr == delimiter) bptr++;
+ *tptr=0; /* terminate
+temporary string */
+ break; /* .. from handling this
+field - resumes at 3. */
+ }
+ } else {
+ /* normal character */
+ *tptr++ = *bptr++;
+
+ if (*bptr == 0) { /* embedded line end?
+*/
+ *(tptr-1)=0; /* remove
+space character added on reading line */
+ strcat(temp, lineEnd); /* add the
+embedded line end to the field */
+
+ /* read a new line from input, as at
+start of routine */
+ memset(buf, 0, len+1);
+ if (FP_FGETS(buf, len, socketd, (FILE
+*) what, issock) == NULL) {
+ efree(lineEnd);
+ efree(temp);
+ efree(buf);
+ zval_ptr_dtor(&return_value);
+ RETURN_FALSE;
+ }
+
+ bptr = buf;
+ tptr = buf + strlen(buf) -1;
+ while (isspace((int) *tptr) &&
+(*tptr!=delimiter) && (tptr > bptr))
+ tptr--;
+ tptr++;
+ strcpy(lineEnd, tptr);
+ *tptr++ = ' ';
+ *tptr = 0;
+
+ tptr = temp; /* reset temp
+pointer to end of field as read so far */
+ while (*tptr)
+ tptr++;
+ }
+ }
+ }
+ } else {
+ /* 2B. Handle non-enclosure field */
+ while ((*bptr != delimiter) && *bptr)
+ *tptr++ = *bptr++;
+ *tptr=0; /* terminate temporary string */
+
+ if (strlen(temp)) {
+ tptr--;
+ while (isspace((int)*tptr) && (*tptr!=delimiter))
+ *tptr-- = 0; /* strip any trailing spaces
+*/
+ }
+
+ if (*bptr == delimiter)
+ bptr++;
+ }
+
+ /* 3. Now pass our field back to php */
+ add_next_index_string(return_value, temp, 1);
+ tptr = temp;
+ } while (*bptr);
+
+ efree(lineEnd);
+ efree(temp);
+ efree(buf);
}
/* }}} */
-
#if (!defined(PHP_WIN32) && !defined(__BEOS__) && HAVE_REALPATH) || defined(ZTS)
/* {{{ proto string realpath(string path)
msg38303/pgp00000.pgp
Description: PGP signature
