[svn:PHP-Sandwich] rev 985 - in PHP-Sandwich/trunk: . t

[email protected] 14 Apr 2005 19:48:46 -0000
Newsgroups perl.php.sandwich.dev
Message-ID <[email protected]>
Author: gschlossnagle
Date: Thu Apr 14 12:48:45 2005
New Revision: 985

Added:
   PHP-Sandwich/trunk/t/6.pl   (contents, props changed)
   PHP-Sandwich/trunk/t/7.pl   (contents, props changed)
Modified:
   PHP-Sandwich/trunk/PHP.xs
   PHP-Sandwich/trunk/t/3.pl
Log:
add ability to return arrays (assoc and indexed) from
PHP to Perl.  If I return $arr in PHP it's returned as
an array ref to Perl.  This seems like a natural semantic.

See examples 6 and 7 for details.




Modified: PHP-Sandwich/trunk/PHP.xs
==============================================================================
--- PHP-Sandwich/trunk/PHP.xs	(original)
+++ PHP-Sandwich/trunk/PHP.xs	Thu Apr 14 12:48:45 2005
@@ -24,6 +24,25 @@
 #define PHP_Interpreter sandwich_per_interp *
 #define PHP_Var_Scalar zval *
 
+
+static int zval_is_assoc(zval *zptr)
+{
+  zval **entry;
+  HashPosition pos;
+  char *sk;
+  uint skl;
+  ulong nk;
+
+  zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(zptr), &pos);
+  while(zend_hash_get_current_data_ex(Z_ARRVAL_P(zptr), (void **)&entry, &pos) == SUCCESS) {
+    if(zend_hash_get_current_key_ex(Z_ARRVAL_P(zptr), &sk, &skl, &nk, 1, &pos) == HASH_KEY_IS_STRING) {
+      return 1;
+    }
+    zend_hash_move_forward_ex(Z_ARRVAL_P(zptr), &pos);
+  }
+  return 0;
+}
+
 zval *SvZval(SV *sv)
 {
   zval *retval;
@@ -43,7 +62,6 @@
         STRLEN strlen;
         char *str = SvPV(sv, strlen);
         ZVAL_STRINGL(retval, str, strlen, 1);
-        fprintf(stderr, "SvPV %s\n", str);
       }
       break;
     case SVt_RV:    /* reference */
@@ -88,93 +106,90 @@
   return retval;
 }
 
-void assign_to_zval(zval *zptr, SV *sv)
-{
-  zval_dtor(zptr);
-  switch(SvTYPE(sv)) {
-    case SVt_IV:   /* int */
-      ZVAL_LONG(zptr, SvIV(sv));
-      break;
-    case SVt_NV:   /* double */
-      ZVAL_DOUBLE(zptr, SvNV(sv));
-      break;
-    case SVt_PV:    /* string */
-      {
-        STRLEN strlen;
-        char *str = SvPV(sv, strlen);
-        ZVAL_STRINGL(zptr, str, strlen, 1);
-        fprintf(stderr, "SvPV %s\n", str);
-      }
-      break;
-    case SVt_RV:    /* reference */
-      break;
-    case SVt_PVAV: /* indexed array */
-      break;
-    case SVt_PVHV: /* assoc. array */
-      break;
-    case SVt_PVCV: /* code */
-      break;
-    case SVt_PVGV: /* glob */
-      break;
-    case SVt_PVMG: /* magic */
-      break;
-    default:
-      break;
-  }
-}
-
 SV *newSVzval(zval *zptr)
 {
+  SV *retval;
   switch( zptr->type) {
     case IS_NULL:
-      fprintf(stderr, "IS_NULL\n");
-      return &PL_sv_undef;
+      retval = &PL_sv_undef;
       break;
     case IS_LONG:
-      fprintf(stderr, "IS_LONG\n");
-      return newSViv(Z_LVAL_P(zptr));
+      retval =  newSViv(Z_LVAL_P(zptr));
       break;
     case IS_DOUBLE:
-      fprintf(stderr, "IS_ODUBLE\n");
-      return newSVnv(Z_DVAL_P(zptr));
+      retval =  newSVnv(Z_DVAL_P(zptr));
       break;
     case IS_BOOL:
-      fprintf(stderr, "IS_BOOL\n");
-      return Z_BVAL_P(zptr) ? &PL_sv_yes : &PL_sv_no;
+      retval = Z_BVAL_P(zptr) ? &PL_sv_yes : &PL_sv_no;
       break;
     case IS_ARRAY:
-      /* FIXME: return by copy, not by reference */
-      fprintf(stderr, "IS_ARRAY\n");
-      return &PL_sv_undef;
+      {
+        zval **entry;
+        HashPosition pos;
+        char *sk;
+        uint skl;
+        ulong nk;
+        int is_assoc = 0;
+        if(zval_is_assoc(zptr)) {
+          retval = (SV *) newHV();
+          is_assoc = 1;
+        } else {
+          retval = (SV *) newAV();
+          is_assoc = 0;
+        }
+        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(zptr), &pos);
+        while(zend_hash_get_current_data_ex(Z_ARRVAL_P(zptr), (void **)&entry, &pos) == SUCCESS) {
+          switch(zend_hash_get_current_key_ex(Z_ARRVAL_P(zptr), &sk, &skl, &nk, 1, &pos)) {
+            case HASH_KEY_IS_STRING:
+              if(!is_assoc) { 
+                /* something bad has happened here */ 
+              }
+              else {
+                hv_store((HV *) retval, sk, skl, newSVzval(*entry), 0);
+              }
+              break;
+            case HASH_KEY_IS_LONG:
+              if(is_assoc) {
+                char buf[32];
+                snprintf(buf, sizeof(buf), "%d", nk);
+                hv_store((HV *) retval, buf, strlen(buf), newSVzval(*entry), 0);
+              } else {
+                av_store((AV *) retval, nk, newSVzval(*entry));
+              }
+              break;
+          }
+          zend_hash_move_forward_ex(Z_ARRVAL_P(zptr), &pos);
+        }
+        retval = newRV_noinc(retval);
+      }
       break;
     case IS_OBJECT:
       /* FIXME: return by reference as a PHP::DataType::Object, not by copy */
-      fprintf(stderr, "IS_OBJECT\n");
-      return &PL_sv_undef;
+      fprintf(stderr, "Unimplemented type: IS_OBJECT\n");
+      retval = &PL_sv_undef;
       break;
     case IS_STRING:
-      fprintf(stderr, "IS_STRING\n");
-      return newSVpv(Z_STRVAL_P(zptr), Z_STRLEN_P(zptr));
+      retval = newSVpv(Z_STRVAL_P(zptr), Z_STRLEN_P(zptr));
       break;
     case IS_RESOURCE:
       /* FIXME: return by reference as a PHP::DataType::Reference, not by copy */
-      fprintf(stderr, "IS_RESOURCE\n");
-      return &PL_sv_undef;
+      fprintf(stderr, "Unimplemented type: IS_RESOURCE\n");
+      retval = &PL_sv_undef;
       break;
     case IS_CONSTANT:
-      fprintf(stderr, "IS_CONSTANT\n");
-      return newSVpv(Z_STRVAL_P(zptr), Z_STRLEN_P(zptr));
+      retval = newSVpv(Z_STRVAL_P(zptr), Z_STRLEN_P(zptr));
       break;
     case IS_CONSTANT_ARRAY:
-      fprintf(stderr, "IS_CONSTANT_ARRAY\n");
+      fprintf(stderr, "Unimplemented type: IS_CONSTANT_ARRAY\n");
       /* FIXME: return by copy, not by reference */
-      return &PL_sv_undef;
+      retval = &PL_sv_undef;
       break;
     default:
       fprintf(stderr, "Unknown type in newSVzval()\n");
-      return &PL_sv_undef;
+      retval = &PL_sv_undef;
       break;
   }
+  return retval;
 }
 
 MODULE = PHP PACKAGE = PHP::Interpreter PREFIX=SAND_
@@ -248,9 +263,17 @@
           case IS_BOOL:
           case IS_DOUBLE:
           case IS_STRING:
+            RETVAL = newSVzval(retval);
+            /*
+
             RETVAL = NEWSV(0,0);
             sv_setref_pv(c1, "PHP::Var::Scalar", (void *) retval);
             sv_magic(RETVAL, c1, PERL_MAGIC_tiedscalar, NULL, 0);
+
+            */
+            break;
+          case IS_ARRAY:
+            RETVAL = newSVzval(retval);
             break;
           default:
             fprintf(stderr, "unsupported return type in PHP_Interpreter_call\n");

Modified: PHP-Sandwich/trunk/t/3.pl
==============================================================================
--- PHP-Sandwich/trunk/t/3.pl	(original)
+++ PHP-Sandwich/trunk/t/3.pl	Thu Apr 14 12:48:45 2005
@@ -8,7 +8,7 @@
 
 print "# Testing passing Perl AVs to PHP functions.\n";
 
-$p = new PHP::Interpreter();
-$p->eval('function dump($a) { ; }');
-@list = ('I', 'AM', 'AN', 'ARRAY');
-$arg = $p->dump(\@list);
+my $p = new PHP::Interpreter();
+$p->eval('function dump($a) { var_dump($a); }');
+my @list = ('I', 'AM', 'AN', 'ARRAY');
+$p->dump(\@list);

Added: PHP-Sandwich/trunk/t/6.pl
==============================================================================
--- (empty file)
+++ PHP-Sandwich/trunk/t/6.pl	Thu Apr 14 12:48:45 2005
@@ -0,0 +1,11 @@
+#!/opt/ecelerity/3rdParty/bin/perl 
+use PHP;
+use PHP::Interpreter;
+
+$p = new PHP::Interpreter();
+$p->eval('function pass($a) { return $a; }');
+@list = ('I', 'AM', 'AN', 'ARRAY');
+$arg = $p->pass(\@list);
+
+use Data::Dumper;
+print Dumper($arg);

Added: PHP-Sandwich/trunk/t/7.pl
==============================================================================
--- (empty file)
+++ PHP-Sandwich/trunk/t/7.pl	Thu Apr 14 12:48:45 2005
@@ -0,0 +1,11 @@
+#!/opt/ecelerity/3rdParty/bin/perl 
+use PHP;
+use PHP::Interpreter;
+
+$p = new PHP::Interpreter();
+$p->eval('function pass($a) { return $a; }');
+$hash = { 'a' => 'alpha', 'b' => 'beta', 'c' => 'charlie' };
+$arg = $p->pass($hash);
+
+use Data::Dumper;
+print Dumper $arg;