Hi,
I'm facing an issue I don't know how to overcome.
Short story:
I've an object which properties are connected to the internal struct
whith get_property() and write_property() object handlers.
Now if BP_VAR_W is used to access a property with read_prop() the
following works fine:
// $this->body is a string
$this->body{0} = 'X';
... but the following does nothing than producing a memleak:
$body = &$this->body;
$body = 'X';
Also, it seems impossible to connect values (longs or string lengths for instance) through
that interface, because I cannot tell the zval that the value should point elsewhere...
Any advice very much appreciated :)
Do I have to disallow referenced writing access?
Long story (sorry):
static zval *_http_message_object_read_prop(zval *object, zval *member, int type TSRMLS_DC)
{
getObjectEx(http_message_object, obj, object);
http_message *msg = obj->message;
zval *return_value;
#ifdef WONKY
ulong h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member)+1);
#else
zend_property_info *pinfo = zend_get_property_info(obj->zo.ce, member, 1 TSRMLS_CC);
if (!pinfo || ACC_PROP_PUBLIC(pinfo->flags)) {
return zend_get_std_object_handlers()->read_property(object, member, type TSRMLS_CC);
}
#endif
if (type == BP_VAR_W) {
return_value = &EG(uninitialized_zval);
return_value->refcount = 1;
return_value->is_ref = 1;
} else {
ALLOC_ZVAL(return_value);
return_value->refcount = 0;
return_value->is_ref = 0;
}
#ifdef WONKY
switch (h)
#else
switch (pinfo->h)
#endif
{
case HTTP_MSG_PROPHASH_TYPE:
case HTTP_MSG_CHILD_PROPHASH_TYPE:
RETVAL_LONG(msg->type);
break;
case HTTP_MSG_PROPHASH_HTTP_VERSION:
case HTTP_MSG_CHILD_PROPHASH_HTTP_VERSION:
RETVAL_DOUBLE(msg->http.version);
break;
case HTTP_MSG_PROPHASH_BODY:
case HTTP_MSG_CHILD_PROPHASH_BODY:
phpstr_fix(PHPSTR(msg));
RETVAL_PHPSTR(PHPSTR(msg), 0, !return_value->is_ref);
break;
case HTTP_MSG_PROPHASH_HEADERS:
case HTTP_MSG_CHILD_PROPHASH_HEADERS:
if (return_value->is_ref) {
Z_TYPE_P(return_value) = IS_ARRAY;
Z_ARRVAL_P(return_value) = &msg->hdrs;
} else {
array_init(return_value);
zend_hash_copy(Z_ARRVAL_P(return_value), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
}
break;
case HTTP_MSG_PROPHASH_PARENT_MESSAGE:
case HTTP_MSG_CHILD_PROPHASH_PARENT_MESSAGE:
if (msg->parent) {
RETVAL_OBJVAL(obj->parent);
} else {
RETVAL_NULL();
}
break;
case HTTP_MSG_PROPHASH_REQUEST_METHOD:
case HTTP_MSG_CHILD_PROPHASH_REQUEST_METHOD:
if (HTTP_MSG_TYPE(REQUEST, msg) && msg->http.info.request.method) {
RETVAL_STRING(msg->http.info.request.method, 1);
} else {
RETVAL_NULL();
}
break;
case HTTP_MSG_PROPHASH_REQUEST_URI:
if (HTTP_MSG_TYPE(REQUEST, msg) && msg->http.info.request.URI) {
RETVAL_STRING(msg->http.info.request.URI, !return_value->is_ref);
} else {
RETVAL_NULL();
}
break;
case HTTP_MSG_PROPHASH_RESPONSE_CODE:
case HTTP_MSG_CHILD_PROPHASH_RESPONSE_CODE:
if (HTTP_MSG_TYPE(RESPONSE, msg)) {
RETVAL_LONG(msg->http.info.response.code);
} else {
RETVAL_NULL();
}
break;
case HTTP_MSG_PROPHASH_RESPONSE_STATUS:
case HTTP_MSG_CHILD_PROPHASH_RESPONSE_STATUS:
if (HTTP_MSG_TYPE(RESPONSE, msg) && msg->http.info.response.status) {
RETVAL_STRING(msg->http.info.response.status, !return_value->is_ref);
} else {
RETVAL_NULL();
}
break;
default:
#ifdef WONKY
return zend_get_std_object_handlers()->read_property(object, member, type TSRMLS_CC);
#else
RETVAL_NULL();
#endif
break;
}
return return_value;
}
--
Michael - <mike(@)php.net> http://dev.iworks.at/ext-http/http-functions.html.gz
Hi Michael,
You should define get_property_ptr_ptr() callback to support such
assignments.
Thanks. Dmitry.
-----Original Message-----
From: Michael Wallner [mailto:mike@php.net]
Sent: Friday, October 28, 2005 7:06 PM
To: internals@lists.php.net
Subject: [PHP-DEV] Internal class, read_property() and type
== BP_VAR_WHi,
I'm facing an issue I don't know how to overcome.
Short story:
I've an object which properties are connected to the internal
struct whith get_property() and write_property() object handlers.Now if BP_VAR_W is used to access a property with read_prop()
the following works fine:// $this->body is a string
$this->body{0} = 'X';... but the following does nothing than producing a memleak:
$body = &$this->body;
$body = 'X';Also, it seems impossible to connect values (longs or
string lengths for instance) through
that interface, because I cannot tell the zval that the value
should point elsewhere...Any advice very much appreciated :)
Do I have to disallow referenced writing access?Long story (sorry):
static zval *_http_message_object_read_prop(zval *object,
zval *member, int type TSRMLS_DC) {
getObjectEx(http_message_object, obj, object);
http_message *msg = obj->message;
zval *return_value;
#ifdef WONKY
ulong h = zend_get_hash_value(Z_STRVAL_P(member),
Z_STRLEN_P(member)+1); #else
zend_property_info *pinfo =
zend_get_property_info(obj->zo.ce, member, 1 TSRMLS_CC);if (!pinfo || ACC_PROP_PUBLIC(pinfo->flags)) {
return
zend_get_std_object_handlers()->read_property(object, member,
type TSRMLS_CC);
}
#endifif (type == BP_VAR_W) {
return_value = &EG(uninitialized_zval);
return_value->refcount = 1;
return_value->is_ref = 1;
} else {
ALLOC_ZVAL(return_value);
return_value->refcount = 0;
return_value->is_ref = 0;
}#ifdef WONKY
switch (h)
#else
switch (pinfo->h)
#endif
{
case HTTP_MSG_PROPHASH_TYPE:
case HTTP_MSG_CHILD_PROPHASH_TYPE:
RETVAL_LONG(msg->type);
break;case HTTP_MSG_PROPHASH_HTTP_VERSION: case HTTP_MSG_CHILD_PROPHASH_HTTP_VERSION: RETVAL_DOUBLE(msg->http.version); break; case HTTP_MSG_PROPHASH_BODY: case HTTP_MSG_CHILD_PROPHASH_BODY: phpstr_fix(PHPSTR(msg)); RETVAL_PHPSTR(PHPSTR(msg), 0,
!return_value->is_ref);
break;case HTTP_MSG_PROPHASH_HEADERS: case HTTP_MSG_CHILD_PROPHASH_HEADERS: if (return_value->is_ref) { Z_TYPE_P(return_value) = IS_ARRAY; Z_ARRVAL_P(return_value) = &msg->hdrs; } else { array_init(return_value);
zend_hash_copy(Z_ARRVAL_P(return_value), &msg->hdrs,
(copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
}
break;case HTTP_MSG_PROPHASH_PARENT_MESSAGE: case HTTP_MSG_CHILD_PROPHASH_PARENT_MESSAGE: if (msg->parent) { RETVAL_OBJVAL(obj->parent); } else { RETVAL_NULL(); } break; case HTTP_MSG_PROPHASH_REQUEST_METHOD: case HTTP_MSG_CHILD_PROPHASH_REQUEST_METHOD: if (HTTP_MSG_TYPE(REQUEST, msg) &&
msg->http.info.request.method) {
RETVAL_STRING(msg->http.info.request.method, 1);
} else {
RETVAL_NULL();
}
break;case HTTP_MSG_PROPHASH_REQUEST_URI: if (HTTP_MSG_TYPE(REQUEST, msg) &&
msg->http.info.request.URI) {
RETVAL_STRING(msg->http.info.request.URI, !return_value->is_ref);
} else {
RETVAL_NULL();
}
break;case HTTP_MSG_PROPHASH_RESPONSE_CODE: case HTTP_MSG_CHILD_PROPHASH_RESPONSE_CODE: if (HTTP_MSG_TYPE(RESPONSE, msg)) {
RETVAL_LONG(msg->http.info.response.code);
} else {
RETVAL_NULL();
}
break;case HTTP_MSG_PROPHASH_RESPONSE_STATUS: case HTTP_MSG_CHILD_PROPHASH_RESPONSE_STATUS: if (HTTP_MSG_TYPE(RESPONSE, msg) &&
msg->http.info.response.status) {
RETVAL_STRING(msg->http.info.response.status, !return_value->is_ref);
} else {
RETVAL_NULL();
}
break;default:
#ifdef WONKY
return
zend_get_std_object_handlers()->read_property(object, member,
type TSRMLS_CC); #else
RETVAL_NULL();
#endif
break;
}return return_value;
}--
Michael - <mike(@)php.net>
http://dev.iworks.at/ext-http/http-functions.html.gz
Hi Dmitry Stogov, you wrote:
Hi Michael,
You should define get_property_ptr_ptr() callback to support such
assignments.
Yeah, I looked at that, but what do I gain? get_property_ptr_ptr() will
be used for both described cases and instead of returning a zval* I'd have
to return a zval**, but I could miss the obvious, and if that's the case,
don't hesitate to drop me a quick pointer in the right direction!
Thanks a lot Dmitry,
Michael - <mike(@)php.net> http://dev.iworks.at/ext-http/http-functions.html.gz