From: Marcus Boerger Date: Thu, 9 Mar 2006 23:03:08 +0000 (+0000) Subject: - Add read ahead ability X-Git-Tag: RELEASE_1_3~478 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b7f6e116f75af3b925f8e28b41051efd39923b80;p=php - Add read ahead ability - Add skipping empty lines - Add ability to read lines as csv --- diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 85998d8be5..7b13b4c582 100755 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1368,19 +1368,89 @@ static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent TS return SUCCESS; } /* }}} */ -static int spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object *intern, int silent TSRMLS_DC) /* {{{ */ +static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function *func_ptr, int pass_num_args, zval *return_value, zval *arg2 TSRMLS_DC) /* {{{ */ +{ + zend_fcall_info fci; + zend_fcall_info_cache fcic; + zval z_fname; + zval * zresource_ptr = &intern->u.file.zresource, *retval; + int result; + int num_args = pass_num_args + (arg2 ? 2 : 1); + + zval ***params = (zval***)safe_emalloc(num_args, sizeof(zval**), 0); + + params[0] = &zresource_ptr; + + if (arg2) { + params[1] = &arg2; + } + + zend_get_parameters_array_ex(pass_num_args, params+(arg2 ? 2 : 1)); + + ZVAL_STRING(&z_fname, func_ptr->common.function_name.s, 0); + + fci.size = sizeof(fci); + fci.function_table = EG(function_table); + fci.object_pp = NULL; + fci.function_name = &z_fname; + fci.retval_ptr_ptr = &retval; + fci.param_count = num_args; + fci.params = params; + fci.no_separation = 1; + fci.symbol_table = NULL; + + fcic.initialized = 1; + fcic.function_handler = func_ptr; + fcic.calling_scope = NULL; + fcic.object_pp = NULL; + + result = zend_call_function(&fci, &fcic TSRMLS_CC); + + ZVAL_ZVAL(return_value, retval, 1, 1); + + efree(params); + return result; +} /* }}} */ + +#define FileFunctionCall(func_name, pass_num_args, arg2) \ +{ \ + zend_function *func_ptr; \ + zend_hash_find(EG(function_table), #func_name, sizeof(#func_name), (void **) &func_ptr); \ + spl_filesystem_file_call(intern, func_ptr, pass_num_args, return_value, arg2 TSRMLS_CC); \ +} + +static void spl_filesystem_file_read_csv(zval * this_ptr, spl_filesystem_object *intern, int pass_num_args, zval *return_value TSRMLS_DC) /* {{{ */ +{ + zval *arg2 = NULL; + MAKE_STD_ZVAL(arg2); + ZVAL_LONG(arg2, intern->u.file.max_line_len); + + spl_filesystem_file_free_line(intern TSRMLS_CC); + + FileFunctionCall(fgetcsv, pass_num_args, arg2); + + zval_ptr_dtor(&arg2); +} +/* }}} */ + +static int spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_object *intern, int silent TSRMLS_DC) /* {{{ */ { zval *retval; - /* if overloaded call the function, otherwise do it directly */ - if (intern->u.file.func_getCurr->common.scope != spl_ce_SplFileObject) { + /* 1) use fgetcsv? 2) overloaded call the function, 3) do it directly */ + if (intern->flags & SPL_FILE_OBJECT_READ_CSV || intern->u.file.func_getCurr->common.scope != spl_ce_SplFileObject) { if (php_stream_eof(intern->u.file.stream)) { if (!silent) { zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot read from file %s", intern->file_name); } return FAILURE; } - zend_call_method_with_0_params(&getThis(), Z_OBJCE_P(getThis()), &intern->u.file.func_getCurr, "getCurrentLine", &retval); + if (intern->flags & SPL_FILE_OBJECT_READ_CSV) { + MAKE_STD_ZVAL(retval); + spl_filesystem_file_read_csv(this_ptr, intern, 0, retval TSRMLS_CC); + } else { + zend_call_method_with_0_params(&this_ptr, Z_OBJCE_P(getThis()), &intern->u.file.func_getCurr, "getCurrentLine", &retval); + } if (retval) { if (intern->u.file.current_line || intern->u.file.current_zval) { intern->u.file.current_line_num++; @@ -1403,7 +1473,49 @@ static int spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object } } /* }}} */ -static void spl_filesystem_file_rewind(spl_filesystem_object *intern TSRMLS_DC) /* {{{ */ +static int spl_filesystem_file_is_empty_line(spl_filesystem_object *intern TSRMLS_DC) /* {{{ */ +{ + if (intern->u.file.current_line) { + return intern->u.file.current_line_len == 0; + } else if (intern->u.file.current_zval) { + switch(Z_TYPE_P(intern->u.file.current_zval)) { + case IS_STRING: + case IS_UNICODE: + return Z_STRLEN_P(intern->u.file.current_zval) == 0; + case IS_ARRAY: + if ((intern->flags & SPL_FILE_OBJECT_READ_CSV) + && zend_hash_num_elements(Z_ARRVAL_P(intern->u.file.current_zval)) == 1) { + zval ** first = Z_ARRVAL_P(intern->u.file.current_zval)->pListHead->pData; + + return (Z_TYPE_PP(first) == IS_STRING || Z_TYPE_PP(first) == IS_UNICODE) + && Z_STRLEN_PP(first) == 0; + } + return zend_hash_num_elements(Z_ARRVAL_P(intern->u.file.current_zval)) == 0; + case IS_NULL: + return 1; + default: + return 0; + } + } else { + return 1; + } +} +/* }}} */ + +static int spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object *intern, int silent TSRMLS_DC) /* {{{ */ +{ + int ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent TSRMLS_CC); + + while ((intern->flags & SPL_FILE_OBJECT_SKIP_EMPTY) && ret == SUCCESS && spl_filesystem_file_is_empty_line(intern TSRMLS_CC)) { + spl_filesystem_file_free_line(intern TSRMLS_CC); + ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent TSRMLS_CC); + } + + return ret; +} +/* }}} */ + +static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *intern TSRMLS_DC) /* {{{ */ { if (-1 == php_stream_rewind(intern->u.file.stream)) { zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot rewind file %s", intern->file_name); @@ -1411,6 +1523,9 @@ static void spl_filesystem_file_rewind(spl_filesystem_object *intern TSRMLS_DC) spl_filesystem_file_free_line(intern TSRMLS_CC); intern->u.file.current_line_num = 0; } + if (intern->flags & SPL_FILE_OBJECT_READ_AHEAD) { + spl_filesystem_file_read_line(this_ptr, intern, 1 TSRMLS_CC); + } } /* }}} */ /* {{{ proto void SplFileObject::__construct(string filename [, string mode = 'r' [, bool use_include_path [, resource context]]]]) @@ -1495,7 +1610,7 @@ SPL_METHOD(SplFileObject, rewind) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - spl_filesystem_file_rewind(intern TSRMLS_CC); + spl_filesystem_file_rewind(getThis(), intern TSRMLS_CC); } /* }}} */ /* {{{ proto string SplFileObject::getFilename() @@ -1522,7 +1637,11 @@ SPL_METHOD(SplFileObject, valid) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - RETVAL_BOOL(!php_stream_eof(intern->u.file.stream)); + if (intern->flags & SPL_FILE_OBJECT_READ_AHEAD) { + RETURN_BOOL(intern->u.file.current_line || intern->u.file.current_zval); + } else { + RETVAL_BOOL(!php_stream_eof(intern->u.file.stream)); + } } /* }}} */ /* {{{ proto string SplFileObject::fgets() @@ -1543,7 +1662,7 @@ SPL_METHOD(SplFileObject, current) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - if (!intern->u.file.current_line) { + if (!intern->u.file.current_line && !intern->u.file.current_zval) { spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC); } if (intern->u.file.current_line) { @@ -1574,6 +1693,9 @@ SPL_METHOD(SplFileObject, next) spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); spl_filesystem_file_free_line(intern TSRMLS_CC); + if (intern->flags & SPL_FILE_OBJECT_READ_AHEAD) { + spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC); + } intern->u.file.current_line_num++; } /* }}} */ @@ -1638,62 +1760,12 @@ SPL_METHOD(SplFileObject, getChildren) /* return NULL */ } /* }}} */ -static int spl_filesystem_file_call(INTERNAL_FUNCTION_PARAMETERS, spl_filesystem_object *intern, zend_function *func_ptr, zval *arg2) /* {{{ */ -{ - zend_fcall_info fci; - zend_fcall_info_cache fcic; - zval z_fname; - zval * zresource_ptr = &intern->u.file.zresource, *retval; - int result; - - zval ***params = (zval***)safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval**), (arg2 ? 2 : 1) * sizeof(zval**)); - - params[0] = &zresource_ptr; - - if (arg2) { - params[1] = &arg2; - } - - zend_get_parameters_array_ex(ZEND_NUM_ARGS(), params+(arg2 ? 2 : 1)); - - ZVAL_STRING(&z_fname, func_ptr->common.function_name.s, 0); - - fci.size = sizeof(fci); - fci.function_table = EG(function_table); - fci.object_pp = NULL; - fci.function_name = &z_fname; - fci.retval_ptr_ptr = &retval; - fci.param_count = ZEND_NUM_ARGS() + (arg2 ? 2 : 1); - fci.params = params; - fci.no_separation = 1; - fci.symbol_table = NULL; - - fcic.initialized = 1; - fcic.function_handler = func_ptr; - fcic.calling_scope = NULL; - fcic.object_pp = NULL; - - result = zend_call_function(&fci, &fcic TSRMLS_CC); - - ZVAL_ZVAL(return_value, retval, 1, 1); - - efree(params); - return result; -} /* }}} */ - -#define FileFunctionCall(func_name, arg2) \ -{ \ - zend_function *func_ptr; \ - zend_hash_find(EG(function_table), #func_name, sizeof(#func_name), (void **) &func_ptr); \ - spl_filesystem_file_call(INTERNAL_FUNCTION_PARAM_PASSTHRU, intern, func_ptr, arg2); \ -} - /* {{{ FileFunction */ #define FileFunction(func_name) \ SPL_METHOD(SplFileObject, func_name) \ { \ spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \ - FileFunctionCall(func_name, NULL); \ + FileFunctionCall(func_name, ZEND_NUM_ARGS(), NULL); \ } /* }}} */ @@ -1702,16 +1774,9 @@ SPL_METHOD(SplFileObject, func_name) \ SPL_METHOD(SplFileObject, fgetcsv) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - zval *arg2 = NULL; - MAKE_STD_ZVAL(arg2); - ZVAL_LONG(arg2, intern->u.file.max_line_len); - - spl_filesystem_file_free_line(intern TSRMLS_CC); + + spl_filesystem_file_read_csv(getThis(), intern, ZEND_NUM_ARGS(), return_value TSRMLS_CC); intern->u.file.current_line_num++; - - FileFunctionCall(fgetcsv, arg2); - - zval_ptr_dtor(&arg2); } /* }}} */ @@ -1796,7 +1861,7 @@ SPL_METHOD(SplFileObject, fgetss) spl_filesystem_file_free_line(intern TSRMLS_CC); intern->u.file.current_line_num++; - FileFunctionCall(fgetss, arg2); + FileFunctionCall(fgetss, ZEND_NUM_ARGS(), arg2); zval_ptr_dtor(&arg2); } /* }}} */ @@ -1819,7 +1884,7 @@ SPL_METHOD(SplFileObject, fscanf) spl_filesystem_file_free_line(intern TSRMLS_CC); intern->u.file.current_line_num++; - FileFunctionCall(fscanf, NULL); + FileFunctionCall(fscanf, ZEND_NUM_ARGS(), NULL); } /* }}} */ @@ -1885,7 +1950,7 @@ SPL_METHOD(SplFileObject, seek) RETURN_FALSE; } - spl_filesystem_file_rewind(intern TSRMLS_CC); + spl_filesystem_file_rewind(getThis(), intern TSRMLS_CC); while(intern->u.file.current_line_num < line_pos) { spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC); @@ -2036,7 +2101,9 @@ PHP_MINIT_FUNCTION(spl_directory) REGISTER_SPL_SUB_CLASS_EX(SplTempFileObject, SplFileObject, spl_filesystem_object_new, spl_SplTempFileObject_functions); REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "DROP_NEW_LINE", SPL_FILE_OBJECT_DROP_NEW_LINE); - + REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "READ_AHEAD", SPL_FILE_OBJECT_READ_AHEAD); + REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "SKIP_EMPTY", SPL_FILE_OBJECT_SKIP_EMPTY); + REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "READ_CSV", SPL_FILE_OBJECT_READ_CSV); return SUCCESS; } /* }}} */ diff --git a/ext/spl/spl_directory.h b/ext/spl/spl_directory.h index 5a72bb6c24..319f4eb52d 100755 --- a/ext/spl/spl_directory.h +++ b/ext/spl/spl_directory.h @@ -82,11 +82,15 @@ struct _spl_filesystem_object { long current_line_num; zval zresource; zend_function *func_getCurr; + zend_function *func_fgetcsv; } file; } u; }; #define SPL_FILE_OBJECT_DROP_NEW_LINE 0x00000001 /* drop new lines */ +#define SPL_FILE_OBJECT_READ_AHEAD 0x00000002 /* read on rewind/next */ +#define SPL_FILE_OBJECT_SKIP_EMPTY 0x00000006 /* skip empty lines */ +#define SPL_FILE_OBJECT_READ_CSV 0x00000008 /* read via fgetcsv */ #define SPL_FILE_DIR_CURRENT_AS_FILEINFO 0x00000010 /* make RecursiveDirectoryTree::current() return SplFileInfo */ #define SPL_FILE_DIR_CURRENT_AS_PATHNAME 0x00000020 /* make RecursiveDirectoryTree::current() return getPathname() */