rendered paste bodyReproduce code:
---------------
<?php
$colour;
$num;
echo "Test 1: zend_hash_apply with stop colour red \n";
init_array();
iterate_until_red($colour);
check_array(1);
echo "Test 2: zend_hash_apply_with_argument with stop colour prurple \n";
init_array();
iterate_until($colour, "purple");
check_array(2);
echo "Test 3: zend_hash_apply_with_arguments with stop colours yellow and black \n";
init_array();
iterate_until_either($colour, "yellow", "black");
check_array(3);
function init_array()
{
global $colour, $num;
$colour = array("orange", "green", "blue", "red", "yellow", "purple", "indigo");
$num = count($colour);
}
function check_array($test)
{
global $colour, $num;
echo "Array contents after test: ";
foreach ($colour as $val) {
$i++;
echo "$val ";
}
if ($num == count($colour)) {
echo "\nTEST $test PASSED\n\n\n";
} else {
echo "\nTEST $test FAILED\n\n\n";
}
}
?>
which uses the following simple extension
---------------- hashapitest.h --------------
#ifndef PHP_HASHAPITEST_H
/* Prevent double inclusion */
#define PHP_HASHAPITEST_H
/* Define Extension Properties */
#define PHP_HASHAPITEST_EXTNAME "hashapitest"
#define PHP_HASHAPITEST_EXTVER "1.0"
#define PHP_HASHAPITEST_DESCRIPTOR_RES_NAME "File Descriptor"
/* Import configure options
when building outside of
the PHP source tree */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* Include PHP Standard Header */
#include "php.h"
#include "stdio.h"
/* Define the entry point symbol
* Zend will use when loading this module
*/
extern zend_module_entry hashapitest_module_entry;
#define phpext_hashapitest_ptr &hashapitest_module_entry
#endif /* PHP_HASHAPITEST_H */
------------- end of hashapitest.h -------------------
and
-------------- hashapitest.c ---------------------
#include "hashapitest.h"
int stop_on_red(zval **val TSRMLS_DC)
{
int ret = ZEND_HASH_APPLY_KEEP;
zval tmpcopy = **val;
zval_copy_ctor(&tmpcopy);
INIT_PZVAL(&tmpcopy);
convert_to_string(&tmpcopy);
php_printf("Stop_on_red called for element: ");
PHPWRITE(Z_STRVAL(tmpcopy), Z_STRLEN(tmpcopy));
php_printf("\n");
/* Check for STOP condition */
if (!strcmp(Z_STRVAL(tmpcopy), "red")) {
return ZEND_HASH_APPLY_STOP;
}
zval_dtor(&tmpcopy);
return ret;
}
int stop_on_colour(zval **val, char *colour TSRMLS_DC)
{
int ret = ZEND_HASH_APPLY_KEEP;
zval tmpcopy = **val;
zval_copy_ctor(&tmpcopy);
INIT_PZVAL(&tmpcopy);
convert_to_string(&tmpcopy);
php_printf("Stop_on_colour called for element:");
PHPWRITE(Z_STRVAL(tmpcopy), Z_STRLEN(tmpcopy));
php_printf("\n");
/* Check for STOP condition */
if (!strcmp(Z_STRVAL(tmpcopy), colour)) {
ret = ZEND_HASH_APPLY_STOP;
}
zval_dtor(&tmpcopy);
return ret;
}
int stop_on_either_colour(zval **val, int num_args, va_list args, zend_hash_key *hash_key)
{
int ret = ZEND_HASH_APPLY_KEEP;
char *colour1= va_arg(args, char*);
char *colour2= va_arg(args, char*);
TSRMLS_FETCH();
zval tmpcopy = **val;
zval_copy_ctor(&tmpcopy);
INIT_PZVAL(&tmpcopy);
convert_to_string(&tmpcopy);
php_printf("Stop_on_either_colour called for element: ");
PHPWRITE(Z_STRVAL(tmpcopy), Z_STRLEN(tmpcopy));
php_printf("\n");
/* Check for STOP condition */
if (!strcmp(Z_STRVAL(tmpcopy), colour1)|| !strcmp(Z_STRVAL(tmpcopy), colour2)) {
ret = ZEND_HASH_APPLY_STOP;
}
zval_dtor(&tmpcopy);
return ret;
}
PHP_FUNCTION(iterate_until_red)
{
zval *array;
HashTable *arrayht = NULL;
int arg1 = 99;
char *arg2 = "red";
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &array) == FAILURE) {
RETURN_NULL();
}
if (Z_TYPE_P(array) != IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE,
"<p>iterate_until_red called on non-array zval<p/>");
return;
}
arrayht = Z_ARRVAL_P(array);
zend_hash_apply(arrayht, stop_on_red TSRMLS_CC);
return;
}
PHP_FUNCTION(iterate_until)
{
zval *array;
HashTable *arrayht = NULL;
char *stop_colour;
int stop_colour_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &array, &stop_colour, &stop_colour_len) == FAILURE) {
RETURN_NULL();
}
if (Z_TYPE_P(array) != IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE,
"<p>iterate_until called on non-array zval<p/>");
return;
}
arrayht = Z_ARRVAL_P(array);
zend_hash_apply_with_argument(arrayht, stop_on_colour, stop_colour TSRMLS_CC);
return;
}
PHP_FUNCTION(iterate_until_either)
{
zval *array;
HashTable *arrayht = NULL;
char *stop_colour1, *stop_colour2;
int stop_colour1_len, stop_colour2_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zss", &array, &stop_colour1, &stop_colour1_len, &stop_colour2, &stop_colour2_len) == FAILURE) {
RETURN_NULL();
}
if (Z_TYPE_P(array) != IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE,
"<p>iterate_until_either called on non-array zval<p/>");
return;
}
arrayht = Z_ARRVAL_P(array);
zend_hash_apply_with_arguments(arrayht, stop_on_either_colour, 2, stop_colour1, stop_colour2);
return;
}
static function_entry php_hashapitest_functions[] = {
PHP_FE(iterate_until_red, NULL)
PHP_FE(iterate_until, NULL)
PHP_FE(iterate_until_either, NULL)
{ NULL, NULL, NULL }
};
zend_module_entry hashapitest_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
PHP_HASHAPITEST_EXTNAME,
php_hashapitest_functions, /* Functions */
NULL, /* MINIT */
NULL, /* MSHUTDOWN */
NULL, /* RINIT */
NULL, /* RSHUTDOWN */
NULL, /* MINFO */
#if ZEND_MODULE_API_NO >= 20010901
PHP_HASHAPITEST_EXTVER,
#endif
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_HASHAPITEST
ZEND_GET_MODULE(hashapitest)
#endif
-------------- end of hashapitest.c ------------------