|
|
|
@ -240,6 +240,318 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_ASSIGN_DIM) |
|
|
|
#endif |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
SPL_CLASS_FUNCTION(array, __construct); |
|
|
|
SPL_CLASS_FUNCTION(array, rewind); |
|
|
|
SPL_CLASS_FUNCTION(array, current); |
|
|
|
SPL_CLASS_FUNCTION(array, key); |
|
|
|
SPL_CLASS_FUNCTION(array, next); |
|
|
|
SPL_CLASS_FUNCTION(array, has_more); |
|
|
|
|
|
|
|
static zend_function_entry spl_array_class_functions[] = { |
|
|
|
SPL_CLASS_FE(array, __construct, NULL) |
|
|
|
SPL_CLASS_FE(array, rewind, NULL) |
|
|
|
SPL_CLASS_FE(array, current, NULL) |
|
|
|
SPL_CLASS_FE(array, key, NULL) |
|
|
|
SPL_CLASS_FE(array, next, NULL) |
|
|
|
SPL_CLASS_FE(array, has_more, NULL) |
|
|
|
{NULL, NULL, NULL} |
|
|
|
}; |
|
|
|
|
|
|
|
static zend_object_handlers spl_array_handlers; |
|
|
|
static zend_class_entry *spl_ce_array; |
|
|
|
|
|
|
|
typedef struct _spl_array_object { |
|
|
|
zend_object std; |
|
|
|
zval *array; |
|
|
|
HashPosition pos; |
|
|
|
} spl_array_object; |
|
|
|
|
|
|
|
/* {{{ spl_array_object_dtor */ |
|
|
|
static void spl_array_object_dtor(void *object, zend_object_handle handle TSRMLS_DC) |
|
|
|
{ |
|
|
|
spl_array_object *intern = (spl_array_object *)object; |
|
|
|
|
|
|
|
zend_hash_destroy(intern->std.properties); |
|
|
|
FREE_HASHTABLE(intern->std.properties); |
|
|
|
|
|
|
|
if (!ZVAL_DELREF(intern->array)) { |
|
|
|
zval_dtor(intern->array); |
|
|
|
FREE_ZVAL(intern->array); |
|
|
|
} |
|
|
|
|
|
|
|
efree(object); |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ spl_array_object_new */ |
|
|
|
static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, spl_array_object **obj, spl_array_object *orig TSRMLS_DC) |
|
|
|
{ |
|
|
|
zend_object_value retval; |
|
|
|
spl_array_object *intern; |
|
|
|
zval *tmp; |
|
|
|
|
|
|
|
intern = emalloc(sizeof(spl_array_object)); |
|
|
|
memset(intern, 0, sizeof(spl_array_object)); |
|
|
|
intern->std.ce = class_type; |
|
|
|
*obj = intern; |
|
|
|
|
|
|
|
ALLOC_HASHTABLE(intern->std.properties); |
|
|
|
zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0); |
|
|
|
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); |
|
|
|
|
|
|
|
if (orig) { |
|
|
|
intern->array = orig->array; |
|
|
|
ZVAL_ADDREF(intern->array); |
|
|
|
} else { |
|
|
|
MAKE_STD_ZVAL(intern->array); |
|
|
|
array_init(intern->array); |
|
|
|
} |
|
|
|
zend_hash_internal_pointer_reset_ex(HASH_OF(intern->array), &intern->pos); |
|
|
|
|
|
|
|
retval.handle = zend_objects_store_put(intern, spl_array_object_dtor, NULL TSRMLS_CC); |
|
|
|
retval.handlers = &spl_array_handlers; |
|
|
|
return retval; |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ spl_array_object_new */ |
|
|
|
static zend_object_value spl_array_object_new(zend_class_entry *class_type TSRMLS_DC) |
|
|
|
{ |
|
|
|
spl_array_object *tmp; |
|
|
|
return spl_array_object_new_ex(class_type, &tmp, NULL TSRMLS_CC); |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ spl_array_object_clone */ |
|
|
|
static zend_object_value spl_array_object_clone(zval *zobject TSRMLS_DC) |
|
|
|
{ |
|
|
|
zend_object_value new_obj_val; |
|
|
|
zend_object *old_object; |
|
|
|
zend_object *new_object; |
|
|
|
zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); |
|
|
|
spl_array_object *intern; |
|
|
|
|
|
|
|
old_object = zend_objects_get_address(zobject TSRMLS_CC); |
|
|
|
new_obj_val = spl_array_object_new_ex(old_object->ce, &intern, (spl_array_object*)old_object TSRMLS_CC); |
|
|
|
new_object = &intern->std; |
|
|
|
|
|
|
|
zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC); |
|
|
|
|
|
|
|
return new_obj_val; |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ spl_array_get_ce */ |
|
|
|
static zend_class_entry *spl_array_get_ce(zval *object TSRMLS_DC) |
|
|
|
{ |
|
|
|
return spl_ce_array; |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ spl_array_read_dimension */ |
|
|
|
zval *spl_array_read_dimension(zval *object, zval *offset TSRMLS_DC) |
|
|
|
{ |
|
|
|
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); |
|
|
|
zval **retval; |
|
|
|
long index; |
|
|
|
|
|
|
|
switch(Z_TYPE_P(offset)) { |
|
|
|
case IS_STRING: |
|
|
|
if (!zend_is_numeric_key(offset, &index)) { |
|
|
|
if (zend_hash_find(HASH_OF(intern->array), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) &retval) == FAILURE) { |
|
|
|
zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset)); |
|
|
|
return EG(uninitialized_zval_ptr); |
|
|
|
} else { |
|
|
|
return *retval; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
/* NO break */ |
|
|
|
case IS_DOUBLE: |
|
|
|
case IS_RESOURCE: |
|
|
|
case IS_BOOL: |
|
|
|
case IS_LONG: |
|
|
|
if (offset->type == IS_DOUBLE) { |
|
|
|
index = (long)Z_DVAL_P(offset); |
|
|
|
} else if (offset->type != IS_STRING) { |
|
|
|
index = Z_LVAL_P(offset); |
|
|
|
} |
|
|
|
if (zend_hash_index_find(HASH_OF(intern->array), index, (void **) &retval) == FAILURE) { |
|
|
|
zend_error(E_NOTICE,"Undefined offset: %d", Z_LVAL_P(offset)); |
|
|
|
return EG(uninitialized_zval_ptr); |
|
|
|
} else { |
|
|
|
return *retval; |
|
|
|
} |
|
|
|
break; |
|
|
|
default: |
|
|
|
zend_error(E_WARNING, "Illegal offset type"); |
|
|
|
return EG(uninitialized_zval_ptr); |
|
|
|
} |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ spl_array_write_dimension */ |
|
|
|
void spl_array_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) |
|
|
|
{ |
|
|
|
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); |
|
|
|
long index; |
|
|
|
|
|
|
|
switch(Z_TYPE_P(offset)) { |
|
|
|
case IS_STRING: |
|
|
|
if (!zend_is_numeric_key(offset, &index)) { |
|
|
|
add_assoc_zval(intern->array, Z_STRVAL_P(offset), value); |
|
|
|
return; |
|
|
|
} |
|
|
|
/* NO break */ |
|
|
|
case IS_DOUBLE: |
|
|
|
case IS_RESOURCE: |
|
|
|
case IS_BOOL: |
|
|
|
case IS_LONG: |
|
|
|
if (offset->type == IS_DOUBLE) { |
|
|
|
index = (long)Z_DVAL_P(offset); |
|
|
|
} else if (offset->type != IS_STRING) { |
|
|
|
index = Z_LVAL_P(offset); |
|
|
|
} |
|
|
|
add_index_zval(intern->array, index, value); |
|
|
|
return; |
|
|
|
default: |
|
|
|
zend_error(E_WARNING, "Illegal offset type"); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{*/ |
|
|
|
HashTable *spl_array_get_properties(zval *object TSRMLS_DC) |
|
|
|
{ |
|
|
|
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); |
|
|
|
|
|
|
|
return HASH_OF(intern->array); |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ PHP_MINIT_FUNCTION(spl_array) */ |
|
|
|
PHP_MINIT_FUNCTION(spl_array) |
|
|
|
{ |
|
|
|
REGISTER_SPL_STD_CLASS_EX(array, spl_array_object_new, spl_array_class_functions); |
|
|
|
REGISTER_SPL_IMPLEMENT(array, sequence_assoc); |
|
|
|
memcpy(&spl_array_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); |
|
|
|
spl_array_handlers.clone_obj = spl_array_object_clone; |
|
|
|
spl_array_handlers.get_class_entry = spl_array_get_ce; |
|
|
|
spl_array_handlers.read_dimension = spl_array_read_dimension; |
|
|
|
spl_array_handlers.write_dimension = spl_array_write_dimension; |
|
|
|
spl_array_handlers.get_properties = spl_array_get_properties; |
|
|
|
|
|
|
|
return SUCCESS; |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ proto void __construct(array ar = array()) |
|
|
|
Cronstructs a new array iterator from a path. */ |
|
|
|
SPL_CLASS_FUNCTION(array, __construct) |
|
|
|
{ |
|
|
|
zval *object = getThis(); |
|
|
|
spl_array_object *intern; |
|
|
|
zval **array; |
|
|
|
|
|
|
|
if (ZEND_NUM_ARGS() == 0) { |
|
|
|
return; /* nothing to do */ |
|
|
|
} |
|
|
|
/* exceptions do not work yet |
|
|
|
php_set_error_handling(EH_THROW, zend_exception_get_default() TSRMLS_CC);*/ |
|
|
|
|
|
|
|
if (ZEND_NUM_ARGS() > 1 || zend_get_parameters_ex(1, &array) == FAILURE) { |
|
|
|
WRONG_PARAM_COUNT; |
|
|
|
} |
|
|
|
if (!HASH_OF(*array)) { |
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed variable is not an array or object, using empty array instead"); |
|
|
|
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); |
|
|
|
return; |
|
|
|
} |
|
|
|
intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); |
|
|
|
zval_dtor(intern->array); |
|
|
|
FREE_ZVAL(intern->array); |
|
|
|
intern->array = *array; |
|
|
|
ZVAL_ADDREF(intern->array); |
|
|
|
|
|
|
|
zend_hash_internal_pointer_reset_ex(HASH_OF(intern->array), &intern->pos); |
|
|
|
|
|
|
|
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ proto void rewind() |
|
|
|
Rewind array back to the start */ |
|
|
|
SPL_CLASS_FUNCTION(array, rewind) |
|
|
|
{ |
|
|
|
zval *object = getThis(); |
|
|
|
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); |
|
|
|
|
|
|
|
zend_hash_internal_pointer_reset_ex(HASH_OF(intern->array), &intern->pos); |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ proto string current() |
|
|
|
Return current array entry */ |
|
|
|
SPL_CLASS_FUNCTION(array, current) |
|
|
|
{ |
|
|
|
zval *object = getThis(); |
|
|
|
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); |
|
|
|
zval **entry; |
|
|
|
|
|
|
|
if (zend_hash_get_current_data_ex(HASH_OF(intern->array), (void **) &entry, &intern->pos) == FAILURE) { |
|
|
|
RETURN_FALSE; |
|
|
|
} |
|
|
|
*return_value = **entry; |
|
|
|
zval_copy_ctor(return_value); |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ proto string key() |
|
|
|
Return current array key */ |
|
|
|
SPL_CLASS_FUNCTION(array, key) |
|
|
|
{ |
|
|
|
zval *object = getThis(); |
|
|
|
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); |
|
|
|
char *string_key; |
|
|
|
uint string_length; |
|
|
|
ulong num_key; |
|
|
|
|
|
|
|
switch (zend_hash_get_current_key_ex(HASH_OF(intern->array), &string_key, &string_length, &num_key, 0, &intern->pos)) { |
|
|
|
case HASH_KEY_IS_STRING: |
|
|
|
RETVAL_STRINGL(string_key, string_length - 1, 1); |
|
|
|
break; |
|
|
|
case HASH_KEY_IS_LONG: |
|
|
|
RETVAL_LONG(num_key); |
|
|
|
break; |
|
|
|
case HASH_KEY_NON_EXISTANT: |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ proto void next() |
|
|
|
Move to next entry */ |
|
|
|
SPL_CLASS_FUNCTION(array, next) |
|
|
|
{ |
|
|
|
zval *object = getThis(); |
|
|
|
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); |
|
|
|
|
|
|
|
zend_hash_move_forward_ex(HASH_OF(intern->array), &intern->pos); |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ proto string has_more() |
|
|
|
Check whether array contains more entries */ |
|
|
|
SPL_CLASS_FUNCTION(array, has_more) |
|
|
|
{ |
|
|
|
zval *object = getThis(); |
|
|
|
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); |
|
|
|
|
|
|
|
RETURN_BOOL(zend_hash_has_more_elements_ex(HASH_OF(intern->array), &intern->pos) == SUCCESS); |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* |
|
|
|
* Local variables: |
|
|
|
* tab-width: 4 |
|
|
|
|