[svn:PHP-Sandwich] rev 1074 - PHP-Sandwich/trunk
[email protected] 7 Jun 2005 18:16:54 -0000
| Newsgroups | perl.php.sandwich.dev |
|---|---|
| Message-ID | <[email protected]> |
Author: gschlossnagle
Date: Tue Jun 7 11:16:54 2005
New Revision: 1074
Modified:
PHP-Sandwich/trunk/PHP.xs
PHP-Sandwich/trunk/phpfuncs.c
Log:
fixes galore to perl object passing, implement iterator interface
for wrapped SVs
Modified: PHP-Sandwich/trunk/PHP.xs
==============================================================================
--- PHP-Sandwich/trunk/PHP.xs (original)
+++ PHP-Sandwich/trunk/PHP.xs Tue Jun 7 11:16:54 2005
@@ -121,6 +121,9 @@ zval *SvZval(SV *sv TSRMLS_DC)
// handle non-PHP classes
}
}
+ else if(sv_isobject(orig_sv)) {
+ plsv_wrap_sv(retval, orig_sv TSRMLS_CC);
+ }
else {
int i = 0;
SV *element;
Modified: PHP-Sandwich/trunk/phpfuncs.c
==============================================================================
--- PHP-Sandwich/trunk/phpfuncs.c (original)
+++ PHP-Sandwich/trunk/phpfuncs.c Tue Jun 7 11:16:54 2005
@@ -4,6 +4,8 @@
#include "phpinterp.h"
#include "phpfuncs.h"
+#include "zend_interfaces.h"
+
ZEND_DECLARE_MODULE_GLOBALS(sandwich);
zend_class_entry *pl_ce;
@@ -360,6 +362,115 @@ PHP_METHOD(perl, eval)
}
}
+
+static zval *
+sv_prop_read(zval *obj, zval *member, int type TSRMLS_DC)
+{
+ SV *sv, **value;
+ HV *hash;
+ zval *return_value;
+ struct plsv *pl;
+ char *key;
+ long keylen;
+ pTHX;
+
+ pl = zend_object_store_get_object(obj TSRMLS_CC);
+#ifdef USE_ITHREADS
+ aTHX = pl->perl;
+#endif
+ value = NULL;
+ sv = pl->sv;
+ if(!SvROK(sv)) RETURN_FALSE;
+ sv = SvRV(sv);
+ if(SvTYPE(sv) == SVt_PVHV) {
+ hash = (HV *) sv;
+ } else if(SvTYPE(sv) == SVt_PVGV) {
+ hash = SvSTASH(sv);
+ } else {
+ goto err_out;
+ }
+ key = Z_STRVAL_P(member);
+ keylen = Z_STRLEN_P(member);
+
+ value = hv_fetch(hash, key, keylen, 1);
+ if (!value) {
+ goto err_out;
+ }
+ if(SvMAGICAL(*value)){
+ mg_get(*value);
+ }
+ return_value = SvZval(*value TSRMLS_CC);
+ return return_value;
+
+err_out:
+ MAKE_STD_ZVAL(return_value);
+ ZVAL_NULL(return_value);
+ return return_value;
+}
+
+static void
+sv_prop_write(zval *object, zval *member, zval *value TSRMLS_DC)
+{
+ SV *sv, **svpp;
+ HV *hash;
+ zval *return_value;
+ struct plsv *pl;
+ char *key;
+ long keylen;
+ pTHX;
+
+ pl = zend_object_store_get_object(object TSRMLS_CC);
+#ifdef USE_ITHREADS
+ aTHX = pl->perl;
+#endif
+ value = NULL;
+ sv = pl->sv;
+ if(!SvROK(sv)) RETURN_FALSE;
+ sv = SvRV(sv);
+ if(SvTYPE(sv) == SVt_PVHV) {
+ hash = (HV *) sv;
+ } else if(SvTYPE(sv) == SVt_PVGV) {
+ hash = SvSTASH(sv);
+ } else {
+ return;
+ }
+ key = Z_STRVAL_P(member);
+ keylen = Z_STRLEN_P(member);
+ svpp = hv_store(hash, key, keylen, newSVzval(value, SandwichG(php)), 0);
+ if(svpp && SvMAGICAL(*svpp)) {
+ mg_set(*svpp);
+ }
+}
+
+static int
+sv_prop_exists(zval *object, zval *member, int has_set_exists TSRMLS_DC)
+{
+ SV *sv, **value;
+ HV *hash;
+ zval *return_value;
+ struct plsv *pl;
+ char *key;
+ long keylen;
+ pTHX;
+
+ pl = zend_object_store_get_object(object TSRMLS_CC);
+#ifdef USE_ITHREADS
+ aTHX = pl->perl;
+#endif
+ value = NULL;
+ sv = pl->sv;
+ if(!SvROK(sv)) RETURN_FALSE;
+ sv = SvRV(sv);
+ if(SvTYPE(sv) == SVt_PVHV) {
+ hash = (HV *) sv;
+ } else {
+ return FAILURE;
+ }
+ key = Z_STRVAL_P(member);
+ keylen = Z_STRLEN_P(member);
+ return hv_exists(hash, key, keylen);
+}
+
static int _sv_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS, int offset)
{
struct plsv *pl;
@@ -380,7 +491,7 @@ static int _sv_call_method(char *method,
#endif
{
dSP;
-
+
argc = ZEND_NUM_ARGS();
args = (zval ***) safe_emalloc(sizeof(zval **), argc, 0);
if(zend_get_parameters_array_ex(argc, args) == FAILURE) {
@@ -464,7 +575,8 @@ static union _zend_function *sv_get_meth
return func;
}
-int sv_get_class_name(zval *obj, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC) {
+int sv_get_class_name(zval *obj, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
+{
if(parent) {
*class_name_len = strlen("PerlSV") + 1;
*class_name = estrndup("PerlSV", *class_name_len);
@@ -482,6 +594,143 @@ int sv_get_class_name(zval *obj, char **
}
}
+struct plsv_iterator {
+ zend_object_iterator iter;
+ SV *sv;
+ HV *hv;
+ char *key;
+ uint keylen;
+ zval *fetch_ahead;
+};
+
+static void plsv_iter_dtor(zend_object_iterator *iter TSRMLS_DC)
+{
+ dTHX;
+ struct plsv_iterator *I = (struct plsv_iterator*)iter->data;
+ if (I->fetch_ahead) {
+ ZVAL_DELREF(I->fetch_ahead);
+ I->fetch_ahead = NULL;
+ }
+ if (I->key) {
+ efree(I->key);
+ }
+ if(I->sv) {
+ SvREFCNT_dec(I->sv);
+ }
+ efree(I);
+}
+
+static int plsv_iter_valid(zend_object_iterator *iter TSRMLS_DC)
+{
+ struct plsv_iterator *I = (struct plsv_iterator*)iter->data;
+ if(!I->hv) return FAILURE;
+ return I->fetch_ahead ? SUCCESS : FAILURE;
+}
+
+static void plsv_iter_get_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
+{
+ struct plsv_iterator *I = (struct plsv_iterator*)iter->data;
+ zval **ptr_ptr;
+
+ /* sanity */
+ if (!I->fetch_ahead) {
+ *data = NULL;
+ return;
+ }
+
+ ptr_ptr = emalloc(sizeof(*ptr_ptr)); /* leaks somewhere */
+ *ptr_ptr = I->fetch_ahead;
+ ZVAL_ADDREF(I->fetch_ahead);
+ *data = ptr_ptr;
+}
+
+static int plsv_iter_get_key(zend_object_iterator *iter, char **str_key, uint *str_key_len,
+ ulong *int_key TSRMLS_DC)
+{
+ struct plsv_iterator *I = (struct plsv_iterator*)iter->data;
+
+ if (!I->key) {
+ return HASH_KEY_NON_EXISTANT;
+ }
+ *str_key_len = I->keylen;
+ *str_key = estrndup(I->key, I->keylen);
+ return HASH_KEY_IS_STRING;
+}
+
+static void plsv_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
+{
+ struct plsv_iterator *I = (struct plsv_iterator*)iter->data;
+ SV *value;
+ char *key;
+ long keylen;
+ pTHX;
+ if(!I->hv) return;
+ if (I->fetch_ahead) {
+ ZVAL_DELREF(I->fetch_ahead);
+ I->fetch_ahead = NULL;
+ }
+ if(I->key) {
+ efree(I->key);
+ I->key = NULL;
+ I->keylen = 0;
+ }
+ if((value = hv_iternextsv(I->hv, &key, &keylen)) != NULL) {
+ zval *foo;
+ MAKE_STD_ZVAL(foo);
+ ZVAL_STRING(foo, "test", 1);
+ I->key = estrndup(key, keylen);
+ I->keylen = keylen + 1;
+ I->fetch_ahead = foo; // SvZval(value TSRMLS_CC);
+ }
+}
+
+static void plsv_iter_rewind(zend_object_iterator *iter TSRMLS_DC)
+{
+ pTHX;
+ struct plsv_iterator *I = (struct plsv_iterator*)iter->data;
+ if(!I->hv) return;
+ hv_iterinit(I->hv);
+ plsv_iter_move_forwards(iter TSRMLS_CC);
+}
+
+static zend_object_iterator_funcs plsv_iter_funcs = {
+ plsv_iter_dtor,
+ plsv_iter_valid,
+ plsv_iter_get_data,
+ plsv_iter_get_key,
+ plsv_iter_move_forwards,
+ plsv_iter_rewind,
+ NULL
+};
+
+static zend_object_iterator *plsv_iter_get(zend_class_entry *ce, zval *object TSRMLS_DC)
+{
+ struct plsv *pl;
+ struct plsv_iterator *I;
+ SV *sv;
+ pTHX;
+
+ pl = (struct plsv *) zend_object_store_get_object(object TSRMLS_CC);
+
+ I = ecalloc(1, sizeof(*I));
+ I->iter.funcs = &plsv_iter_funcs;
+ I->iter.data = I;
+ SvREFCNT_inc(pl->sv);
+ sv = pl->sv;
+ I->sv = pl->sv;
+ if(SvROK(sv)) { sv = SvRV(sv); }
+ if(SvTYPE(sv) == SVt_PVHV) {
+ I->hv = (HV *) sv;
+ } else {
+ I->hv = NULL;
+ I->fetch_ahead = NULL;
+ I->key = NULL;
+ SvREFCNT_dec(pl->sv);
+ return &I->iter;
+ }
+ return &I->iter;
+}
+
static function_entry pl_functions[] = {
PHP_ME(perl, getinstance, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
{NULL, NULL, NULL}
@@ -688,21 +937,23 @@ PHP_MINIT_FUNCTION(sandwich)
plobj_handlers.call_method = sandwich_call_method;
INIT_CLASS_ENTRY(plsv, "PerlSV", plsv_functions);
-
- plsv.create_object = plsv_create_object;
plsv_ce = zend_register_internal_class(&plsv TSRMLS_CC);
+ plsv_ce->create_object = plsv_create_object;
+ plsv_ce->get_iterator = plsv_iter_get;
+ zend_class_implements(plsv_ce TSRMLS_CC, 1, zend_ce_traversable);
if (!plsv_ce) {
return FAILURE;
}
-
memcpy(&plsv_handlers, zend_get_std_object_handlers(),
sizeof(plsv_handlers));
- plsv_handlers.read_dimension = sandwich_dim_read;
- plsv_handlers.write_dimension = sandwich_dim_write;
+ plsv_handlers.read_property = sv_prop_read;
+ plsv_handlers.write_property = sv_prop_write;
+ plsv_handlers.has_property = sv_prop_exists;
plsv_handlers.get_method = sv_get_method;
plsv_handlers.call_method = sv_call_method;
plsv_handlers.get_class_name = sv_get_class_name;
+
return SUCCESS;
}