void zend_collection_add_item(zend_object *object, zval *offset, zval *value)
{
zend_class_entry *ce = object->ce;
zval rv;
zval *value_prop;
ZEND_ASSERT(ce->ce_flags & ZEND_ACC_COLLECTION);
if (!zend_check_type(&ce->collection_item_type, value, NULL, ce, 0, false)) {
zend_string *type_str = zend_type_to_string(ce->collection_item_type);
zend_type_error(
"Value type %s does not match collection item type %s",
zend_zval_type_name(value), ZSTR_VAL(type_str));
zend_string_release(type_str);
return;
}
if (!offset && ce->collection_key_type == IS_LONG) {
create_array_if_needed(ce, object);
value_prop = zend_read_property_ex(ce, object, ZSTR_KNOWN(ZEND_STR_VALUE), true, &rv);
Z_ADDREF_P(value);
add_next_index_zval(value_prop, value);
} else if (offset && ce->collection_key_type == IS_LONG && Z_TYPE_P(offset) == IS_LONG) {
create_array_if_needed(ce, object);
value_prop = zend_read_property_ex(ce, object, ZSTR_KNOWN(ZEND_STR_VALUE), true, &rv);
Z_ADDREF_P(value);
add_index_zval(value_prop, Z_LVAL_P(offset), value);
} else if (offset && ce->collection_key_type == IS_STRING && Z_TYPE_P(offset) == IS_STRING) {
create_array_if_needed(ce, object);
value_prop = zend_read_property_ex(ce, object, ZSTR_KNOWN(ZEND_STR_VALUE), true, &rv);
Z_ADDREF_P(value);
add_assoc_zval_ex(value_prop, Z_STRVAL_P(offset), Z_STRLEN_P(offset), value);
} else {
zend_type_error(
"Key type %s of element does not match collection key type %s",
offset ? zend_zval_type_name(offset) : zend_get_type_by_const(IS_NULL),
zend_get_type_by_const(ce->collection_key_type));
}
}