Permalink
Browse files

Support for class constants and static members for internal classes

  • Loading branch information...
1 parent 655cb3a commit 248345d9208ad1d506af8efc466c3ab614a349a3 Dmitry Stogov committed Sep 1, 2005
View
2 NEWS
@@ -1,6 +1,8 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? Aug 2005, PHP 5.1 Release Candidate 2
+- Implemented support for class constants and static members for internal
+ classes (Dmitry, Michael Wallner)
- Upgraded bundled SQLite library for PDO:SQLite to 3.2.5 (Ilia)
- Upgraded PCRE library to version 6.2. (Andrei)
- Updated bundled libraries in Windows distribution. (Edin)
View
@@ -331,6 +331,7 @@ struct _zend_class_entry {
HashTable function_table;
HashTable default_properties;
HashTable properties_info;
+ HashTable default_static_members;
HashTable *static_members;
HashTable constants_table;
struct _zend_function_entry *builtin_functions;
View
@@ -753,13 +753,53 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro
ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC)
{
- if (!class_type->constants_updated) {
+ if (!class_type->constants_updated || !class_type->static_members) {
zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
zend_class_entry *old_scope = *scope;
*scope = class_type;
zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
+
+ if (!class_type->static_members) {
+ HashPosition pos;
+ zval **p;
+
+ if (class_type->parent) {
+ zend_update_class_constants(class_type->parent TSRMLS_CC);
+ }
+ ALLOC_HASHTABLE(class_type->static_members);
+ zend_hash_init(class_type->static_members, 0, NULL, ZVAL_PTR_DTOR, 0);
+
+ zend_hash_internal_pointer_reset_ex(&class_type->default_static_members, &pos);
+ while (zend_hash_get_current_data_ex(&class_type->default_static_members, (void**)&p, &pos) == SUCCESS) {
+ char *str_index;
+ uint str_length;
+ ulong num_index;
+ zval **q;
+
+ zend_hash_get_current_key_ex(&class_type->default_static_members, &str_index, &str_length, &num_index, 0, &pos);
+ if ((*p)->is_ref &&
+ class_type->parent &&
+ zend_hash_find(&class_type->parent->default_static_members, str_index, str_length, (void**)&q) == SUCCESS &&
+ *p == *q &&
+ zend_hash_find(class_type->parent->static_members, str_index, str_length, (void**)&q) == SUCCESS) {
+ (*q)->refcount++;
+ (*q)->is_ref = 1;
+ zend_hash_add(class_type->static_members, str_index, str_length, (void**)q, sizeof(zval*), NULL);
+ } else {
+ zval *q;
+
+ ALLOC_ZVAL(q);
+ *q = **p;
+ INIT_PZVAL(q)
+ zval_copy_ctor(q);
+ zend_hash_add(class_type->static_members, str_index, str_length, (void**)&q, sizeof(zval*), NULL);
+ }
+ zend_hash_move_forward_ex(&class_type->default_static_members, &pos);
+ }
+ }
zend_hash_apply_with_argument(class_type->static_members, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
+
*scope = old_scope;
class_type->constants_updated = 1;
}
@@ -2126,7 +2166,7 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, char *name, int name
access_type |= ZEND_ACC_PUBLIC;
}
if (access_type & ZEND_ACC_STATIC) {
- target_symbol_table = ce->static_members;
+ target_symbol_table = &ce->default_static_members;
} else {
target_symbol_table = &ce->default_properties;
}
@@ -2274,6 +2314,73 @@ ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int
return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
}
+ZEND_API int zend_declare_class_constant(zend_class_entry *ce, char *name, size_t name_length, zval *value TSRMLS_DC)
+{
+ return zend_hash_update(&ce->constants_table, name, name_length+1, &value, sizeof(zval *), NULL);
+}
+
+ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, char *name, size_t name_length, long value TSRMLS_DC)
+{
+ zval *constant;
+
+ if (ce->type & ZEND_INTERNAL_CLASS) {
+ constant = malloc(sizeof(zval));
+ } else {
+ ALLOC_ZVAL(constant);
+ }
+ ZVAL_LONG(constant, value);
+ INIT_PZVAL(constant);
+ return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
+}
+
+ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, char *name, size_t name_length, zend_bool value TSRMLS_DC)
+{
+ zval *constant;
+
+ if (ce->type & ZEND_INTERNAL_CLASS) {
+ constant = malloc(sizeof(zval));
+ } else {
+ ALLOC_ZVAL(constant);
+ }
+ ZVAL_BOOL(constant, value);
+ INIT_PZVAL(constant);
+ return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
+}
+
+ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, char *name, size_t name_length, double value TSRMLS_DC)
+{
+ zval *constant;
+
+ if (ce->type & ZEND_INTERNAL_CLASS) {
+ constant = malloc(sizeof(zval));
+ } else {
+ ALLOC_ZVAL(constant);
+ }
+ ZVAL_DOUBLE(constant, value);
+ INIT_PZVAL(constant);
+ return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
+}
+
+ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, char *name, size_t name_length, char *value, size_t value_length TSRMLS_DC)
+{
+ zval *constant;
+
+ if (ce->type & ZEND_INTERNAL_CLASS) {
+ constant = malloc(sizeof(zval));
+ ZVAL_STRINGL(constant, zend_strndup(value, value_length), value_length, 0);
+ } else {
+ ALLOC_ZVAL(constant);
+ ZVAL_STRINGL(constant, value, value_length, 1);
+ }
+ INIT_PZVAL(constant);
+ return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
+}
+
+ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, char *name, size_t name_length, char *value TSRMLS_DC)
+{
+ return zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value) TSRMLS_CC);
+}
+
ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC)
{
zval property;
@@ -2361,6 +2468,106 @@ ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object
zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
}
+ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, int name_length, zval *value TSRMLS_DC)
+{
+ zval **property;
+ zend_class_entry *old_scope = EG(scope);
+
+ EG(scope) = scope;
+ property = zend_std_get_static_property(scope, name, name_length, 0 TSRMLS_CC);
+ EG(scope) = old_scope;
+ if (!property) {
+ return FAILURE;
+ } else {
+ if (*property != value) {
+ if (PZVAL_IS_REF(*property)) {
+ zval_dtor(*property);
+ (*property)->type = value->type;
+ (*property)->value = value->value;
+ if (value->refcount > 0) {
+ zval_copy_ctor(*property);
+ }
+ } else {
+ zval *garbage = *property;
+
+ value->refcount++;
+ if (PZVAL_IS_REF(value)) {
+ SEPARATE_ZVAL(&value);
+ }
+ *property = value;
+ zval_ptr_dtor(&garbage);
+ }
+ }
+ return SUCCESS;
+ }
+}
+
+ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *name, int name_length TSRMLS_DC)
+{
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ tmp->is_ref = 0;
+ tmp->refcount = 0;
+ ZVAL_NULL(tmp);
+ return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC)
+{
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ tmp->is_ref = 0;
+ tmp->refcount = 0;
+ ZVAL_BOOL(tmp, value);
+ return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC)
+{
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ tmp->is_ref = 0;
+ tmp->refcount = 0;
+ ZVAL_LONG(tmp, value);
+ return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, int name_length, double value TSRMLS_DC)
+{
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ tmp->is_ref = 0;
+ tmp->refcount = 0;
+ ZVAL_DOUBLE(tmp, value);
+ return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, int name_length, char *value TSRMLS_DC)
+{
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ tmp->is_ref = 0;
+ tmp->refcount = 0;
+ ZVAL_STRING(tmp, value, 1);
+ return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, int name_length, char *value, int value_len TSRMLS_DC)
+{
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ tmp->is_ref = 0;
+ tmp->refcount = 0;
+ ZVAL_STRINGL(tmp, value, value_len, 1);
+ return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC)
{
zval property, *value;
@@ -2382,6 +2589,18 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *n
return value;
}
+ZEND_API zval *zend_read_static_property(zend_class_entry *scope, char *name, int name_length, zend_bool silent TSRMLS_DC)
+{
+ zval **property;
+ zend_class_entry *old_scope = EG(scope);
+
+ EG(scope) = scope;
+ property = zend_std_get_static_property(scope, name, name_length, silent TSRMLS_CC);
+ EG(scope) = old_scope;
+
+ return property?*property:NULL;
+}
+
/*
* Local variables:
* tab-width: 4
View
@@ -212,6 +212,13 @@ ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int
ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC);
ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int name_length, char *value, int value_len, int access_type TSRMLS_DC);
+ZEND_API int zend_declare_class_constant(zend_class_entry *ce, char *name, size_t name_length, zval *value TSRMLS_DC);
+ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, char *name, size_t name_length, long value TSRMLS_DC);
+ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, char *name, size_t name_length, zend_bool value TSRMLS_DC);
+ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, char *name, size_t name_length, double value TSRMLS_DC);
+ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, char *name, size_t name_length, char *value, size_t value_length TSRMLS_DC);
+ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, char *name, size_t name_length, char *value TSRMLS_DC);
+
ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC);
ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC);
ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC);
@@ -221,8 +228,18 @@ ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object,
ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, char *name, int name_length, char *value TSRMLS_DC);
ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, char *value, int value_length TSRMLS_DC);
+ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, int name_length, zval *value TSRMLS_DC);
+ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *name, int name_length TSRMLS_DC);
+ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC);
+ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC);
+ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, int name_length, double value TSRMLS_DC);
+ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, int name_length, char *value TSRMLS_DC);
+ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, int name_length, char *value, int value_length TSRMLS_DC);
+
ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC);
+ZEND_API zval *zend_read_static_property(zend_class_entry *scope, char *name, int name_length, zend_bool silent TSRMLS_DC);
+
ZEND_API zend_class_entry *zend_get_class_entry(zval *zobject TSRMLS_DC);
ZEND_API int zend_get_object_classname(zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC);
@@ -737,6 +737,7 @@ ZEND_FUNCTION(get_class_vars)
} else {
array_init(return_value);
add_class_vars(*pce, &(*pce)->default_properties, return_value TSRMLS_CC);
+ zend_update_class_constants(*pce TSRMLS_CC);
add_class_vars(*pce, (*pce)->static_members, return_value TSRMLS_CC);
}
}
View
@@ -2039,9 +2039,17 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, child_info->name, child_info->name_length, ce->type & ZEND_INTERNAL_CLASS);
if (child_info->flags & ZEND_ACC_STATIC) {
zval **prop;
- if (zend_hash_find(parent_ce->static_members, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) {
+ HashTable *ht;
+
+ if (parent_ce->type != ce->type) {
+ /* User class extends internal class */
+ ht = parent_ce->static_members;
+ } else {
+ ht = &parent_ce->default_static_members;
+ }
+ if (zend_hash_find(ht, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) {
zval **new_prop;
- if (zend_hash_find(ce->static_members, child_info->name, child_info->name_length+1, (void**)&new_prop) == SUCCESS) {
+ if (zend_hash_find(ht, child_info->name, child_info->name_length+1, (void**)&new_prop) == SUCCESS) {
if (Z_TYPE_PP(new_prop) != IS_NULL && Z_TYPE_PP(prop) != IS_NULL) {
char *prop_name, *tmp;
zend_unmangle_property_name(child_info->name, &tmp, &prop_name);
@@ -2051,8 +2059,8 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
}
}
(*prop)->refcount++;
- zend_hash_update(ce->static_members, child_info->name, child_info->name_length+1, (void**)prop, sizeof(zval*), NULL);
- zend_hash_del(ce->static_members, prot_name, prot_name_length+1);
+ zend_hash_update(&ce->default_static_members, child_info->name, child_info->name_length+1, (void**)prop, sizeof(zval*), NULL);
+ zend_hash_del(&ce->default_static_members, prot_name, prot_name_length+1);
}
} else {
zend_hash_del(&ce->default_properties, prot_name, prot_name_length+1);
@@ -2138,7 +2146,13 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
/* Inherit properties */
zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0);
- zend_hash_merge(ce->static_members, parent_ce->static_members, (void (*)(void *)) inherit_static_prop, NULL, sizeof(zval *), 0);
+ if (parent_ce->type != ce->type) {
+ /* User class extends internal class */
+ zend_update_class_constants(parent_ce TSRMLS_CC);
+ zend_hash_merge(&ce->default_static_members, parent_ce->static_members, (void (*)(void *)) inherit_static_prop, NULL, sizeof(zval *), 0);
+ } else {
+ zend_hash_merge(&ce->default_static_members, &parent_ce->default_static_members, (void (*)(void *)) inherit_static_prop, NULL, sizeof(zval *), 0);
+ }
zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (copy_ctor_func_t) (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal : zend_duplicate_property_info), sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce);
zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0);
@@ -2268,7 +2282,7 @@ ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *c
zend_hash_destroy(&ce->function_table);
zend_hash_destroy(&ce->default_properties);
zend_hash_destroy(&ce->properties_info);
- zend_hash_destroy(ce->static_members);
+ zend_hash_destroy(&ce->default_static_members);
zend_hash_destroy(&ce->constants_table);
return NULL;
}
@@ -3932,17 +3946,12 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
zend_hash_init_ex(&ce->default_properties, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, 0);
-
- if (persistent_hashes) {
- ce->static_members = (HashTable *) malloc(sizeof(HashTable));
- } else {
- ALLOC_HASHTABLE(ce->static_members);
- }
-
- zend_hash_init_ex(ce->static_members, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
+ zend_hash_init_ex(&ce->default_static_members, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
zend_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
+ ce->static_members = (ce->type == ZEND_INTERNAL_CLASS) ? NULL : &ce->default_static_members;
+
if (nullify_handlers) {
ce->constructor = NULL;
ce->destructor = NULL;
Oops, something went wrong.

0 comments on commit 248345d

Please sign in to comment.