if (!EG(active_symbol_table)) {
ZVAL_NULL(¶ms[4]);
} else {
- array_init_size(¶ms[4], zend_hash_num_elements(&EG(active_symbol_table)->ht));
- zend_hash_copy(Z_ARRVAL(params[4]), &EG(active_symbol_table)->ht, zval_add_ref);
+ ZVAL_NEW_ARR(¶ms[4]);
+ zend_array_dup(Z_ARRVAL(params[4]), &EG(active_symbol_table)->ht);
}
ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler));
zend_rebuild_symbol_table(TSRMLS_C);
}
- array_init_size(return_value, zend_hash_num_elements(&EG(active_symbol_table)->ht));
-
- zend_hash_copy(Z_ARRVAL_P(return_value), &EG(active_symbol_table)->ht, zval_add_ref);
+ ZVAL_NEW_ARR(return_value);
+ zend_array_dup(Z_ARRVAL_P(return_value), &EG(active_symbol_table)->ht);
}
/* }}} */
if (closure->debug_info->u.v.nApplyCount == 0) {
if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) {
HashTable *static_variables = closure->func.op_array.static_variables;
- array_init(&val);
- zend_hash_copy(Z_ARRVAL(val), static_variables, zval_add_ref);
+ ZVAL_NEW_ARR(&val);
+ zend_array_dup(Z_ARRVAL(val), static_variables);
zend_hash_str_update(closure->debug_info, "static", sizeof("static")-1, &val);
}
HashTable *static_variables = op_array->static_variables;
ALLOC_HASHTABLE(op_array->static_variables);
- zend_hash_init(op_array->static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(op_array->static_variables, static_variables, zval_add_ref);
+ zend_array_dup(op_array->static_variables, static_variables);
}
op_array->run_time_cache = NULL;
} else if (function->type == ZEND_INTERNAL_FUNCTION) {
}
+ZEND_API void zend_array_dup(HashTable *target, HashTable *source)
+{
+ uint idx, target_idx;
+ uint nIndex;
+ Bucket *p, *q;
+ zval *data;
+
+ IS_CONSISTENT(source);
+
+ target->nTableMask = source->nTableMask;
+ target->nTableSize = source->nTableSize;
+ target->pDestructor = source->pDestructor;
+ target->nInternalPointer = INVALID_IDX;
+ target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT);
+
+ target_idx = 0;
+ if (target->nTableMask) {
+ if (target->u.flags & HASH_FLAG_PACKED) {
+ target->nNumUsed = source->nNumUsed;
+ target->nNumOfElements = source->nNumOfElements;
+ target->nNextFreeElement = source->nNextFreeElement;
+ target->arData = (Bucket *) safe_pemalloc(target->nTableSize, sizeof(Bucket), 0, 0);
+ target->arHash = (zend_uint*)&uninitialized_bucket;
+ target->nInternalPointer = source->nInternalPointer;
+
+ for (idx = 0; idx < source->nNumUsed; idx++) {
+ p = source->arData + idx;
+ q = target->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) {
+ q->h = 0;
+ q->key = NULL;
+ ZVAL_UNDEF(&q->val);
+ continue;
+ }
+ /* INDIRECT element may point to UNDEF-ined slots */
+ data = &p->val;
+ if (Z_TYPE_P(data) == IS_INDIRECT) {
+ data = Z_INDIRECT_P(data);
+ if (Z_TYPE_P(data) == IS_UNDEF) {
+ q->h = 0;
+ q->key = NULL;
+ ZVAL_UNDEF(&q->val);
+ continue;
+ }
+ }
+
+ q->h = p->h;
+ q->key = NULL;
+ if (Z_OPT_REFCOUNTED_P(data)) {
+ if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1) {
+ ZVAL_DUP(&q->val, Z_REFVAL_P(data));
+ } else {
+ ZVAL_COPY(&q->val, data);
+ }
+ } else {
+ ZVAL_COPY_VALUE(&q->val, data);
+ }
+ }
+ if (target->nNumOfElements > 0 &&
+ target->nInternalPointer == INVALID_IDX) {
+ idx = 0;
+ while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
+ idx++;
+ }
+ target->nInternalPointer = idx;
+ }
+ } else {
+ target->nNextFreeElement = source->nNextFreeElement;
+ target->arData = (Bucket *) safe_pemalloc(target->nTableSize, sizeof(Bucket) + sizeof(zend_uint), 0, 0);
+ target->arHash = (zend_uint*)(target->arData + target->nTableSize);
+ memset(target->arHash, INVALID_IDX, target->nTableSize * sizeof(zend_uint));
+
+ for (idx = 0; idx < source->nNumUsed; idx++) {
+ p = source->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ /* INDIRECT element may point to UNDEF-ined slots */
+ data = &p->val;
+ if (Z_TYPE_P(data) == IS_INDIRECT) {
+ data = Z_INDIRECT_P(data);
+ if (Z_TYPE_P(data) == IS_UNDEF) {
+ continue;
+ }
+ }
+
+ if (source->nInternalPointer == idx) {
+ target->nInternalPointer = target_idx;
+ }
+
+ q = target->arData + target_idx;
+ q->h = p->h;
+ q->key = p->key;
+ if (q->key) {
+ STR_ADDREF(q->key);
+ }
+ nIndex = q->h & target->nTableMask;
+ Z_NEXT(q->val) = target->arHash[nIndex];
+ target->arHash[nIndex] = target_idx;
+ if (Z_OPT_REFCOUNTED_P(data)) {
+ if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1) {
+ ZVAL_DUP(&q->val, Z_REFVAL_P(data));
+ } else {
+ ZVAL_COPY(&q->val, data);
+ }
+ } else {
+ ZVAL_COPY_VALUE(&q->val, data);
+ }
+ target_idx++;
+ }
+ target->nNumUsed = target_idx;
+ target->nNumOfElements = target_idx;
+ if (target->nNumOfElements > 0 &&
+ target->nInternalPointer == INVALID_IDX) {
+ target->nInternalPointer = 0;
+ }
+ }
+ } else {
+ target->nNumUsed = 0;
+ target->nNumOfElements = 0;
+ target->nNextFreeElement = 0;
+ target->arData = NULL;
+ target->arHash = (zend_uint*)&uninitialized_bucket;
+ }
+}
+
+
ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, int overwrite ZEND_FILE_LINE_DC)
{
uint idx;
}
-ZEND_API int zend_hash_num_elements(const HashTable *ht)
-{
- IS_CONSISTENT(ht);
-
- return ht->nNumOfElements;
-}
-
-
ZEND_API int zend_hash_get_pointer(const HashTable *ht, HashPointer *ptr)
{
ptr->pos = ht->nInternalPointer;
return &res->val;
}
-ZEND_API ulong zend_hash_next_free_element(const HashTable *ht)
-{
- IS_CONSISTENT(ht);
-
- return ht->nNextFreeElement;
-
-}
-
/*
* Local variables:
* tab-width: 4
ZEND_API int zend_hash_exists(const HashTable *ht, zend_string *key);
ZEND_API int zend_hash_str_exists(const HashTable *ht, const char *str, int len);
ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h);
-ZEND_API ulong zend_hash_next_free_element(const HashTable *ht);
/* traversing */
#define zend_hash_has_more_elements_ex(ht, pos) \
#define zend_hash_merge(target, source, pCopyConstructor, overwrite) \
_zend_hash_merge(target, source, pCopyConstructor, overwrite ZEND_FILE_LINE_CC)
-ZEND_API int zend_hash_num_elements(const HashTable *ht);
+#define zend_hash_num_elements(ht) \
+ (ht)->nNumOfElements
+
+#define zend_hash_next_free_element(ht) \
+ (ht)->nNextFreeElement
ZEND_API int zend_hash_rehash(HashTable *ht);
+ZEND_API void zend_array_dup(HashTable *target, HashTable *source);
+
#if ZEND_DEBUG
/* debug */
void zend_hash_display_pListTail(const HashTable *ht);
if (obj_ht) {
zval arr;
ZVAL_NEW_ARR(&arr);
- zend_hash_init(Z_ARRVAL(arr), zend_hash_num_elements(obj_ht), NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(Z_ARRVAL(arr), obj_ht, zval_add_ref);
+ zend_array_dup(Z_ARRVAL(arr), obj_ht);
zval_dtor(op);
ZVAL_COPY_VALUE(op, &arr);
return;
}
ht = Z_ARRVAL_P(zvalue);
ZVAL_NEW_ARR(zvalue);
- zend_hash_init(Z_ARRVAL_P(zvalue), zend_hash_num_elements(ht), NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(Z_ARRVAL_P(zvalue), ht, zval_add_ref);
+ zend_array_dup(Z_ARRVAL_P(zvalue), ht);
}
break;
case IS_CONSTANT_AST: {
*is_temp = 1;
ALLOC_HASHTABLE(debug_info);
- ZEND_INIT_SYMTABLE_EX(debug_info, 32, 0);
std_props = zend_std_get_properties(object TSRMLS_CC);
- zend_hash_copy(debug_info, std_props, (copy_ctor_func_t) zval_add_ref);
+ zend_array_dup(debug_info, std_props);
if (!prop_handlers) {
return debug_info;
*is_temp = 1;
ALLOC_HASHTABLE(ht);
- ZEND_INIT_SYMTABLE_EX(ht, zend_hash_num_elements(props) + 1, 0);
- zend_hash_copy(ht, props, (copy_ctor_func_t) zval_add_ref);
+ zend_array_dup(ht, props);
gmp_strval(&zv, gmpnum, 10);
zend_hash_str_update(ht, "num", sizeof("num")-1, &zv);
if ((tmp = zend_hash_str_find(ht, "classmap", sizeof("classmap")-1)) != NULL &&
Z_TYPE_P(tmp) == IS_ARRAY) {
ALLOC_HASHTABLE(service->class_map);
- zend_hash_init(service->class_map, zend_hash_num_elements(Z_ARRVAL_P(tmp)), NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(service->class_map, Z_ARRVAL_P(tmp), zval_add_ref);
+ zend_array_dup(service->class_map, Z_ARRVAL_P(tmp));
}
if ((tmp = zend_hash_str_find(ht, "typemap", sizeof("typemap")-1)) != NULL &&
if (soap_headers) {
if (!free_soap_headers) {
HashTable *t = emalloc(sizeof(HashTable));
- zend_hash_init(t, 0, NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(t, soap_headers, zval_add_ref);
+ zend_array_dup(t, soap_headers);
soap_headers = t;
free_soap_headers = 1;
}
if (clone_orig) {
intern->array = other->array;
if (Z_OBJ_HT_P(orig) == &spl_handler_ArrayObject) {
- array_init(&intern->array);
- zend_hash_copy(HASH_OF(&intern->array), HASH_OF(&other->array), (copy_ctor_func_t) zval_add_ref);
+ ZVAL_NEW_ARR(&intern->array);
+ zend_array_dup(Z_ARRVAL(intern->array), HASH_OF(&other->array));
}
if (Z_OBJ_HT_P(orig) == &spl_handler_ArrayIterator) {
Z_ADDREF_P(&other->array);
zval *object = getThis();
spl_array_object *intern = Z_SPLARRAY_P(object);
- array_init(return_value);
- zend_hash_copy(Z_ARRVAL_P(return_value), spl_array_get_hash_table(intern, 0 TSRMLS_CC), (copy_ctor_func_t) zval_add_ref);
+ ZVAL_NEW_ARR(return_value);
+ zend_array_dup(Z_ARRVAL_P(return_value), spl_array_get_hash_table(intern, 0 TSRMLS_CC));
} /* }}} */
static HashTable *spl_array_get_properties(zval *object TSRMLS_DC) /* {{{ */
zval *object = getThis(), *array;
spl_array_object *intern = Z_SPLARRAY_P(object);
- array_init(return_value);
- zend_hash_copy(HASH_OF(return_value), spl_array_get_hash_table(intern, 0 TSRMLS_CC), (copy_ctor_func_t)zval_add_ref);
+ ZVAL_NEW_ARR(return_value);
+ zend_array_dup(Z_ARRVAL_P(return_value), spl_array_get_hash_table(intern, 0 TSRMLS_CC));
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &array) == FAILURE) {
return;
}
rebuild_object_properties(&intern->std);
}
- array_init(&members);
- zend_hash_copy(Z_ARRVAL(members), intern->std.properties, (copy_ctor_func_t)zval_add_ref);
+ ZVAL_NEW_ARR(&members);
+ zend_array_dup(Z_ARRVAL(members), intern->std.properties);
php_var_serialize(&buf, &members, &var_hash TSRMLS_CC); /* finishes the string */
}
ALLOC_HASHTABLE(rv);
- ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 3, 0);
- zend_hash_copy(rv, intern->std.properties, (copy_ctor_func_t) zval_add_ref);
+ zend_array_dup(rv, intern->std.properties);
pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "pathName", sizeof("pathName")-1 TSRMLS_CC);
path = spl_filesystem_object_get_pathname(intern, &path_len TSRMLS_CC);
/* members */
smart_str_appendl(&buf, "m:", 2);
- array_init(&members);
- zend_hash_copy(Z_ARRVAL(members), zend_std_get_properties(getThis() TSRMLS_CC), (copy_ctor_func_t) zval_add_ref);
+ ZVAL_NEW_ARR(&members);
+ zend_array_dup(Z_ARRVAL(members), zend_std_get_properties(getThis() TSRMLS_CC));
php_var_serialize(&buf, &members, &var_hash TSRMLS_CC); /* finishes the string */
zval_ptr_dtor(&members);
php_set_compare_func(sort_type TSRMLS_CC);
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
- zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_P(array), zval_add_ref);
+ ZVAL_NEW_ARR(return_value);
+ zend_array_dup(Z_ARRVAL_P(return_value), Z_ARRVAL_P(array));
if (Z_ARRVAL_P(array)->nNumOfElements <= 1) { /* nothing to do */
return;
HashTable *old_ht = Z_ARRVAL_P(return_value);
ZVAL_NEW_ARR(return_value);
- zend_hash_init(Z_ARRVAL_P(return_value), zend_hash_num_elements(old_ht), NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(Z_ARRVAL_P(return_value), old_ht, zval_add_ref);
+ zend_array_dup(Z_ARRVAL_P(return_value), old_ht);
}
/* go through the lists and look for common values */
HashTable *old_ht = Z_ARRVAL_P(return_value);
ZVAL_NEW_ARR(return_value);
- zend_hash_init(Z_ARRVAL_P(return_value), zend_hash_num_elements(old_ht), NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(Z_ARRVAL_P(return_value), old_ht, zval_add_ref);
+ zend_array_dup(Z_ARRVAL_P(return_value), old_ht);
}
/* go through the lists and look for values of ptr[0] that are not in the others */
/* Restructure the arrays based on sorted indirect - this is mostly taken from zend_hash_sort() function. */
HANDLE_BLOCK_INTERRUPTIONS();
for (i = 0; i < num_arrays; i++) {
+ int repack;
+
hash = Z_ARRVAL_P(arrays[i]);
hash->nNumUsed = array_size;
hash->nInternalPointer = 0;
+ repack = !(hash->u.flags & HASH_FLAG_PACKED);
for (n = 0, k = 0; k < array_size; k++) {
hash->arData[k] = indirect[k][i];
- if (hash->arData[k].key == NULL)
+ if (hash->arData[k].key == NULL) {
hash->arData[k].h = n++;
+ } else {
+ repack = 0;
+ }
}
hash->nNextFreeElement = array_size;
- if (!(hash->u.flags & HASH_FLAG_PACKED)) {
+ if (repack) {
zend_hash_to_packed(hash);
}
}
}
if (return_array) {
- array_init(return_value);
- zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_P(agent), (copy_ctor_func_t) browscap_zval_copy_ctor);
+ ZVAL_NEW_ARR(return_value);
+ zend_array_dup(Z_ARRVAL_P(return_value), Z_ARRVAL_P(agent));
}
else {
object_init(return_value);