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