summaryrefslogtreecommitdiffstats
path: root/bindings/php5
diff options
context:
space:
mode:
authorBenjamin Dauvergne <bdauvergne@entrouvert.com>2008-08-05 14:52:56 +0000
committerBenjamin Dauvergne <bdauvergne@entrouvert.com>2008-08-05 14:52:56 +0000
commit115b18fc6f4a245d415584090734cd43b52a6f6a (patch)
treecd7c9629f3ddaabbbc5e2b240b72eabf35d77024 /bindings/php5
parent1fae093527f69de086934f5df750cf374eaa2f48 (diff)
downloadlasso-115b18fc6f4a245d415584090734cd43b52a6f6a.tar.gz
lasso-115b18fc6f4a245d415584090734cd43b52a6f6a.tar.xz
lasso-115b18fc6f4a245d415584090734cd43b52a6f6a.zip
Move all files related to the php5 binding inside
the php5 subdirectory.
Diffstat (limited to 'bindings/php5')
-rw-r--r--bindings/php5/__init__.py0
-rw-r--r--bindings/php5/lang.py44
-rw-r--r--bindings/php5/php_code.py477
-rw-r--r--bindings/php5/wrapper_header.py62
-rw-r--r--bindings/php5/wrapper_source.py468
-rw-r--r--bindings/php5/wrapper_source_top.c319
6 files changed, 1370 insertions, 0 deletions
diff --git a/bindings/php5/__init__.py b/bindings/php5/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/bindings/php5/__init__.py
diff --git a/bindings/php5/lang.py b/bindings/php5/lang.py
new file mode 100644
index 00000000..fbed5d47
--- /dev/null
+++ b/bindings/php5/lang.py
@@ -0,0 +1,44 @@
+# Lasso - A free implementation of the Liberty Alliance specifications.
+#
+# Copyright (C) 2004-2007 Entr'ouvert
+# http://lasso.entrouvert.org
+#
+# Authors: See AUTHORS file in top-level directory.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import os
+from wrapper_source import WrapperSource
+from wrapper_header import WrapperHeader
+from php_code import PhpCode
+
+class Binding:
+ def __init__(self, binding_data):
+ self.binding_data = binding_data
+
+ def generate(self):
+ fd = open('_lasso.c', 'w')
+ wrapper_source = WrapperSource(self.binding_data, fd)
+ wrapper_source.generate()
+ fd.close()
+
+ fd = open('php_lasso.h', 'w')
+ WrapperHeader(self.binding_data, fd, wrapper_source.functions_list).generate()
+ fd.close()
+
+ fd = open('lasso.php', 'w')
+ PhpCode(self.binding_data, fd).generate()
+ fd.close()
+
diff --git a/bindings/php5/php_code.py b/bindings/php5/php_code.py
new file mode 100644
index 00000000..8b8eef84
--- /dev/null
+++ b/bindings/php5/php_code.py
@@ -0,0 +1,477 @@
+# Lasso - A free implementation of the Liberty Alliance specifications.
+#
+# Copyright (C) 2004-2007 Entr'ouvert
+# http://lasso.entrouvert.org
+#
+# Authors: See AUTHORS file in top-level directory.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import re
+import sys
+
+import utils
+
+class PhpCode:
+ def __init__(self, binding_data, fd):
+ self.binding_data = binding_data
+ self.fd = fd
+
+ def is_object(self, t):
+ return t not in ['char*', 'const char*', 'gchar*', 'const gchar*', 'GList*', 'GHashTable*',
+ 'xmlNode*', 'int', 'gint', 'gboolean', 'const gboolean'] + self.binding_data.enums
+
+ def generate(self):
+ self.generate_header()
+ for klass in self.binding_data.structs:
+ self.generate_class(klass)
+ self.generate_exceptions()
+ self.generate_footer()
+
+ def generate_header(self):
+ print >> self.fd, '''\
+<?php
+
+/* this file has been generated automatically; do not edit */
+
+/**
+ * @package Lasso
+ */
+
+// Try to load Lasso extension if it's not already loaded.
+if (!extension_loaded('lasso')) {
+ die("Lasso extension is not loaded");
+}
+
+/*
+ * Convert a C object to a PHP object
+ */
+function cptrToPhp ($cptr) {
+ if (is_null($cptr) || !$cptr) return null;
+ $typename = lasso_get_object_typename($cptr);
+ $class_name = $typename . "NoInit";
+ $obj = new $class_name();
+ if (! is_null($obj)) {
+ $obj->_cptr = $cptr;
+ return $obj;
+ }
+ return null;
+}
+
+function lassoGetRequestTypeFromSoapMsg($mesg) {
+ return lasso_get_request_type_from_soap_msg($mesg);
+}
+
+function lassoRegisterIdWsf2DstService($prefix, $href) {
+ lasso_register_idwsf2_dst_service($prefix, $href);
+}
+'''
+
+ def generate_class(self, klass):
+ class_name = klass.name
+
+ if klass.parent != 'GObject':
+ inheritence = ' extends %s' % klass.parent
+ else:
+ inheritence = ''
+
+ print >> self.fd, '/**'
+ print >> self.fd, ' * @package Lasso'
+ print >> self.fd, ' */'
+ print >> self.fd, 'class %(class_name)s%(inheritence)s {' % locals()
+
+ if klass.members or klass.methods:
+ self.generate_constructors(klass)
+ self.generate_getters_and_setters(klass)
+ self.generate_methods(klass)
+
+ print >> self.fd, '}'
+ print >> self.fd, ''
+
+ # Add a special class to get an object instance without initialising
+ print >> self.fd, '/**'
+ print >> self.fd, ' * @package Lasso'
+ print >> self.fd, ' */'
+ print >> self.fd, 'class %(class_name)sNoInit extends %(class_name)s {' % locals()
+ print >> self.fd, ' public function __construct() {}'
+ print >> self.fd, '}'
+ print >> self.fd, ''
+
+ def generate_constructors(self, klass):
+ method_prefix = utils.format_as_underscored(klass.name) + '_'
+ for m in self.binding_data.functions:
+ if m.name == method_prefix + 'new':
+ php_args = []
+ c_args = []
+ for arg in m.args:
+ arg_type, arg_name, arg_options = arg
+ if arg_options.get('optional'):
+ php_args.append('$%s = null' % arg_name)
+ else:
+ php_args.append('$%s' % arg_name)
+
+ if self.is_object(arg_type):
+ c_args.append('$%s->_cptr' % arg_name)
+ else:
+ c_args.append('$%s' % arg_name)
+
+ php_args = ', '.join(php_args)
+ c_args = ', '.join(c_args)
+ # XXX: could check $this->_cptr->typename to see if it got the
+ # right class type
+ print >> self.fd, ' public $_cptr = null;'
+ print >> self.fd, ''
+ print >> self.fd, ' public function __construct(%s) {' % php_args
+ print >> self.fd, ' $this->_cptr = %s(%s);' % (m.name, c_args)
+ print >> self.fd, ' if (is_null($this->_cptr)) { throw new Exception("Constructor for ', klass.name, ' failed "); }'
+ print >> self.fd, ' }'
+ print >> self.fd, ''
+
+ if m.name == method_prefix + 'new_from_dump':
+ if len(m.args) == 1:
+ print >> self.fd, ' public static function newFromDump($dump) {'
+ print >> self.fd, ' return cptrToPhp(%s($dump));' % m.name
+ else:
+ print >> self.fd, ' public static function newFromDump($server, $dump) {'
+ print >> self.fd, ' return cptrToPhp(%s($server->_cptr, $dump));' % m.name
+ # XXX: Else throw an exception
+ print >> self.fd, ' }'
+ print >> self.fd, ''
+ elif m.name == method_prefix + 'new_full':
+ pass
+
+ def generate_getters_and_setters(self, klass):
+
+ # FIXME: handle objects and GLists
+
+ # Generic getter
+ print >> self.fd, ' /**'
+ print >> self.fd, ' * @return mixed'
+ print >> self.fd, ' */'
+ print >> self.fd, ' public function __get($attr) {'
+ print >> self.fd, ' $func = "get_" . $attr;'
+ print >> self.fd, ' if (method_exists($this, $func)) {'
+ print >> self.fd, ' return call_user_func(array($this, $func));'
+ print >> self.fd, ' }'
+ print >> self.fd, ' return null;'
+ print >> self.fd, ' }'
+ print >> self.fd, ''
+
+ # Generic setter
+ print >> self.fd, ' public function __set($attr, $value) {'
+ print >> self.fd, ' $func = "set_" . $attr;'
+ print >> self.fd, ' if (method_exists($this, $func)) {'
+ print >> self.fd, ' call_user_func(array($this, $func), $value);'
+ print >> self.fd, ' }'
+ print >> self.fd, ' }'
+ print >> self.fd, ''
+
+ for m in klass.members:
+ mtype = m[0]
+ mname = utils.format_as_camelcase(m[1])
+ options = m[2]
+
+ # Getters
+ print >> self.fd, ' /**'
+ print >> self.fd, ' * @return %s' % self.get_docstring_return_type(mtype)
+ print >> self.fd, ' */'
+ print >> self.fd, ' protected function get_%s() {' % mname
+ if self.is_object(mtype):
+ print >> self.fd, ' return cptrToPhp(%s_%s_get($this->_cptr));' % (
+ klass.name, mname)
+ elif mtype in ('GList*', 'GHashTable*'):
+ print >> self.fd, ' $array = %s_%s_get($this->_cptr);' % (klass.name, mname)
+ if self.is_object(options.get('elem_type')):
+ print >> self.fd, ' $obj_array = array();'
+ if mtype == 'GList*':
+ print >> self.fd, ' foreach ($array as $item) {'
+ print >> self.fd, ' $obj_array[] = cptrToPhp($item);'
+ else:
+ print >> self.fd, ' foreach ($array as $key => $item) {'
+ print >> self.fd, ' $obj_array[$key] = cptrToPhp($item);'
+ print >> self.fd, ' }'
+ print >> self.fd, ' $array = $obj_array;'
+ print >> self.fd, ' return $array;'
+ else:
+ print >> self.fd, ' return %s_%s_get($this->_cptr);' % (klass.name, mname)
+ print >> self.fd, ' }'
+
+ # Setters
+ print >> self.fd, ' protected function set_%s($value) {' % mname
+ if self.is_object(mtype):
+ print >> self.fd, ' %s_%s_set($this->_cptr, $value->_cptr);' % (klass.name, mname)
+ elif mtype in ('GList*', 'GHashTable*') and self.is_object(options.get('elem_type')):
+ print >> self.fd, ' $array = array();'
+ # FIXME: setting an array to NULL should really set it to NULL and not to an empty array
+ print >> self.fd, ' if (!is_null($value)) {'
+ if mtype == 'GList*':
+ print >> self.fd, ' foreach ($value as $item) {'
+ print >> self.fd, ' $array[] = $item->_cptr;'
+ else:
+ print >> self.fd, ' foreach ($value as $key => $item) {'
+ print >> self.fd, ' $array[$key] = $item->_cptr;'
+ print >> self.fd, ' }'
+ print >> self.fd, ' }'
+ print >> self.fd, ' %s_%s_set($this->_cptr, $array);' % (klass.name, mname)
+ else:
+ print >> self.fd, ' %s_%s_set($this->_cptr, $value);' % (klass.name, mname)
+ print >> self.fd, ' }'
+ print >> self.fd, ''
+
+
+ def generate_methods(self, klass):
+ methods = klass.methods[:]
+
+ # first pass on methods, removing accessors
+ for m in klass.methods:
+ if m.rename:
+ meth_name = m.rename
+ else:
+ meth_name = m.name
+ if not ('_get_' in meth_name and len(m.args) == 1):
+ continue
+ methods.remove(m)
+ try:
+ setter_name = meth_name.replace('_get_', '_set_')
+ setter = [x for x in methods if x.name == setter_name][0]
+ methods.remove(setter)
+ except IndexError:
+ setter = None
+ mname = re.match(r'lasso_.*_get_(\w+)', meth_name).group(1)
+ mname =utils.format_as_camelcase(mname)
+
+ print >> self.fd, ' /**'
+ print >> self.fd, ' * @return %s' % self.get_docstring_return_type(m.return_type)
+ print >> self.fd, ' */'
+ print >> self.fd, ' protected function get_%s() {' % mname
+ if self.is_object(m.return_type):
+ print >> self.fd, ' $cptr = %s($this->_cptr);' % meth_name
+ print >> self.fd, ' if (! is_null($cptr)) {'
+ print >> self.fd, ' return cptrToPhp($cptr);'
+ print >> self.fd, ' }'
+ print >> self.fd, ' return null;'
+ else:
+ print >> self.fd, ' return %s($this->_cptr);' % meth_name
+ print >> self.fd, ' }'
+ if setter:
+ print >> self.fd, ' protected function set_%s($value) {' % mname
+ if self.is_object(m.return_type):
+ print >> self.fd, ' %s($this->_cptr, $value->_cptr);' % setter.name
+ else:
+ print >> self.fd, ' %s($this->_cptr, $value);' % setter.name
+ print >> self.fd, ' }'
+ print >> self.fd, ''
+
+ # second pass on methods, real methods
+ method_prefix = utils.format_as_underscored(klass.name) + '_'
+ for m in methods:
+ if m.name.endswith('_new') or m.name.endswith('_new_from_dump') or \
+ m.name.endswith('_new_full'):
+ continue
+ if not m.name.startswith(method_prefix):
+ print >> sys.stderr, 'W:', m.name, 'vs', method_prefix
+ continue
+
+ if m.rename:
+ mname = m.rename
+ else:
+ mname = m.name
+ cname = mname
+ mname = mname[len(method_prefix):]
+ php_args = []
+ c_args = []
+ for arg in m.args[1:]:
+ arg_type, arg_name, arg_options = arg
+ arg_name = '$' + arg_name
+ if arg_options.get('optional'):
+ if arg_options.get('default'):
+ defval = arg_options.get('default')
+ if defval.startswith('c:'): # constant
+ php_args.append('%s = %s' % (arg_name, defval[2:]))
+ elif defval.startswith('b:'): # boolean
+ php_args.append('%s = %s' % (arg_name, defval[2:]))
+ else:
+ print >> sys.stderr, "E: don't know what to do with %s" % defval
+ sys.exit(1)
+ else:
+ php_args.append('%s = null' % arg_name)
+ else:
+ php_args.append(arg_name)
+ if arg_type in ('char*', 'const char*', 'gchar*', 'const gchar*') or \
+ arg_type in ['int', 'gint', 'gboolean', 'const gboolean'] or \
+ arg_type in self.binding_data.enums:
+ c_args.append(arg_name)
+ else:
+ c_args.append('%s._cptr' % arg_name)
+
+ if php_args:
+ php_args = ', '.join(php_args)
+ else:
+ php_args = ''
+ if c_args:
+ c_args = ', ' + ', '.join(c_args)
+ else:
+ c_args = ''
+
+ if m.docstring:
+ print >> self.fd, self.generate_docstring(m, mname, 4)
+ print >> self.fd, ' public function %s(%s) {' % (
+ utils.format_underscore_as_camelcase(mname), php_args)
+ if m.return_type == 'void':
+ print >> self.fd, ' %s($this->_cptr%s);' % (cname, c_args)
+ elif m.return_type in ('gint', 'int'):
+ print >> self.fd, ' $rc = %s($this->_cptr%s);' % (cname, c_args)
+ print >> self.fd, ' if ($rc == 0) {'
+ print >> self.fd, ' return 0;'
+ print >> self.fd, ' } else if ($rc > 0) {' # recoverable error
+ print >> self.fd, ' return $rc;'
+ print >> self.fd, ' } else if ($rc < 0) {' # unrecoverable error
+ print >> self.fd, ' LassoError::throw_on_rc($rc);'
+ print >> self.fd, ' }'
+ else:
+ print >> self.fd, ' return %s($this->_cptr%s);' % (cname, c_args)
+ print >> self.fd, ' }'
+ print >> self.fd, ''
+
+ print >> self.fd, ''
+
+ def generate_docstring(self, func, method_name, indent):
+ docstring = func.docstring.orig_docstring
+ if func.args:
+ first_arg_name = func.args[0][1]
+ else:
+ first_arg_name = None
+
+ def rep(s):
+ type = s.group(1)[0]
+ var = s.group(1)[1:]
+ if type == '#': # struct
+ return var
+ elif type == '%': # %TRUE, %FALSE
+ if var in ('TRUE', 'FALSE'):
+ return var
+ print >> sys.stderr, 'W: unknown docstring thingie: %s' % s.group(1)
+ elif type == '@':
+ if var == first_arg_name:
+ return '$this'
+ else:
+ return '$' + var
+ return s.group(1)
+
+ lines = []
+ for l in docstring.splitlines():
+ if l.strip() and not lines:
+ continue
+ lines.append(l)
+ s = indent * ' ' + '/**\n'
+ s += '\n'.join([indent * ' ' + ' * ' + x for x in lines[1:]])
+ s += '\n' + indent * ' ' + ' */'
+ regex = re.compile(r'([\#%@]\w+)', re.DOTALL)
+ s = regex.sub(rep, s)
+ s = s.replace('Return value: ', '@return %s ' % self.get_docstring_return_type(func.return_type))
+ return s
+
+ def get_docstring_return_type(self, return_type):
+ if return_type == None:
+ return ''
+ elif return_type == 'gboolean':
+ return 'boolean'
+ elif return_type in ['int', 'gint'] + self.binding_data.enums:
+ return 'int'
+ elif return_type in ('char*', 'gchar*', 'const char*', 'const gchar*', 'xmlNode*'):
+ return 'string'
+ elif return_type in ('GList*', 'GHashTable*'):
+ return 'array'
+ else:
+ # Objects
+ return return_type.replace('*', '')
+
+ def generate_exceptions(self):
+ done_cats = []
+
+ for exc_cat in self.binding_data.overrides.findall('exception/category'):
+ cat = exc_cat.attrib.get('name')
+ done_cats.append(cat)
+ parent_cat = exc_cat.attrib.get('parent', '')
+ print >> self.fd, '''\
+/**
+ * @package Lasso
+ */
+class Lasso%sError extends Lasso%sError {}
+''' % (cat, parent_cat)
+
+ exceptions_dict = {}
+
+ for c in self.binding_data.constants:
+ m = re.match(r'LASSO_(\w+)_ERROR_(.*)', c[1])
+ if not m:
+ continue
+ cat, detail = m.groups()
+ cat = cat.title().replace('_', '')
+ detail = (cat + '_' + detail).title().replace('_', '')
+ if not cat in done_cats:
+ done_cats.append(cat)
+ for exc_cat in self.binding_data.overrides.findall('exception/category'):
+ if exc_cat.attrib.get('name') == cat:
+ parent_cat = exc_cat.attrib.get('parent')
+ break
+ else:
+ parent_cat = ''
+
+ print >> self.fd, '''\
+/**
+ * @package Lasso
+ */
+class Lasso%sError extends Lasso%sError {}
+''' % (cat, parent_cat)
+
+ if detail not in exceptions_dict:
+ print >> self.fd, '''\
+/**
+ * @package Lasso
+ */
+class Lasso%sError extends Lasso%sError {
+ protected $code = %s;
+}
+''' % (detail, cat, c[1])
+ exceptions_dict[detail] = c[1]
+
+ print >> self.fd, '''\
+/**
+ * @package Lasso
+ */
+class LassoError extends Exception {
+ private static $exceptions_dict = array('''
+
+ for k, v in exceptions_dict.items():
+ print >> self.fd, ' %s => "Lasso%sError",' % (v, k)
+
+ print >> self.fd, '''\
+ );
+
+ public static function throw_on_rc($rc) {
+ $exception = self::$exceptions_dict[$rc];
+ if (! class_exists($exception)) {
+ $exception = "LassoError";
+ }
+ throw new $exception(strError($rc), $rc);
+ }
+}
+'''
+
+ def generate_footer(self):
+ print >> self.fd, '''\
+?>'''
+
diff --git a/bindings/php5/wrapper_header.py b/bindings/php5/wrapper_header.py
new file mode 100644
index 00000000..3cf895af
--- /dev/null
+++ b/bindings/php5/wrapper_header.py
@@ -0,0 +1,62 @@
+# Lasso - A free implementation of the Liberty Alliance specifications.
+#
+# Copyright (C) 2004-2007 Entr'ouvert
+# http://lasso.entrouvert.org
+#
+# Authors: See AUTHORS file in top-level directory.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+class WrapperHeader:
+ def __init__(self, binding_data, fd, functions_list):
+ self.binding_data = binding_data
+ self.fd = fd
+ self.functions_list = functions_list
+
+ def generate(self):
+ self.generate_header()
+ self.generate_functions_list()
+ self.generate_footer()
+
+ def generate_header(self):
+ # FIXME: Get the current version and name
+ print >> self.fd, '''\
+/* this file has been generated automatically; do not edit */
+
+#ifndef PHP_LASSO_H
+#define PHP_LASSO_H 1
+
+#define PHP_LASSO_EXTNAME "lasso"
+#define PHP_LASSO_VERSION "2.1.1"
+
+#define PHP_LASSO_SERVER_RES_NAME "Lasso Server"
+
+PHP_MINIT_FUNCTION(lasso);
+PHP_MSHUTDOWN_FUNCTION(lasso);
+'''
+
+ def generate_functions_list(self):
+ for m in self.functions_list:
+ print >> self.fd, 'PHP_FUNCTION(%s);' % m
+ print >> self.fd, ''
+
+ def generate_footer(self):
+ print >> self.fd, '''\
+extern zend_module_entry lasso_module_entry;
+#define phpext_lasso_ptr &lasso_module_entry
+
+#endif
+'''
+
diff --git a/bindings/php5/wrapper_source.py b/bindings/php5/wrapper_source.py
new file mode 100644
index 00000000..8279d3db
--- /dev/null
+++ b/bindings/php5/wrapper_source.py
@@ -0,0 +1,468 @@
+# Lasso - A free implementation of the Liberty Alliance specifications.
+#
+# Copyright (C) 2004-2007 Entr'ouvert
+# http://lasso.entrouvert.org
+#
+# Authors: See AUTHORS file in top-level directory.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import sys
+import os
+
+import utils
+
+class WrapperSource:
+ def __init__(self, binding_data, fd):
+ self.binding_data = binding_data
+ self.fd = fd
+ self.functions_list = []
+ self.src_dir = os.path.dirname(__file__)
+
+ def is_object(self, t):
+ return t not in ['char*', 'const char*', 'gchar*', 'const gchar*', 'GList*', 'GHashTable*',
+ 'xmlNode*', 'int', 'gint', 'gboolean', 'const gboolean'] + self.binding_data.enums
+
+ def generate(self):
+ self.generate_header()
+ self.generate_constants()
+ self.generate_middle()
+ for m in self.binding_data.functions:
+ self.generate_function(m)
+ for c in self.binding_data.structs:
+ self.generate_members(c)
+ for m in c.methods:
+ self.generate_function(m)
+ self.generate_functions_list()
+ self.generate_footer()
+
+ def generate_header(self):
+ self.functions_list.append('lasso_get_object_typename')
+ self.functions_list.append('lasso_init')
+ self.functions_list.append('lasso_shutdown')
+
+ print >> self.fd, '''\
+/* this file has been generated automatically; do not edit */
+'''
+
+ print >> self.fd, open(os.path.join(self.src_dir,'wrapper_source_top.c')).read()
+
+ for h in self.binding_data.headers:
+ print >> self.fd, '#include <%s>' % h
+ print >> self.fd, ''
+
+ print >> self.fd, '''\
+PHP_MINIT_FUNCTION(lasso)
+{
+ le_lasso_server = zend_register_list_destructors_ex(php_gobject_generic_destructor, NULL, PHP_LASSO_SERVER_RES_NAME, module_number);
+ lasso_init();
+'''
+
+ def generate_constants(self):
+ print >> self.fd, ' /* Constants (both enums and defines) */'
+ for c in self.binding_data.constants:
+ if c[0] == 'i':
+ print >> self.fd, ' REGISTER_LONG_CONSTANT("%s", %s, CONST_CS|CONST_PERSISTENT);' % (c[1], c[1])
+ elif c[0] == 's':
+ print >> self.fd, ' REGISTER_STRING_CONSTANT("%s", %s, CONST_CS|CONST_PERSISTENT);' % (c[1], c[1])
+ elif c[0] == 'b':
+ print >> self.fd, '''\
+#ifdef %s
+ REGISTER_LONG_CONSTANT("%s", 1, CONST_CS|CONST_PERSISTENT);
+#else
+ REGISTER_LONG_CONSTANT("%s", 0, CONST_CS|CONST_PERSISTENT);
+#endif''' % (c[1], c[1], c[1])
+ else:
+ print >> sys.stderr, 'E: unknown constant type: %r' % c[0]
+ print >> self.fd, ''
+
+ def generate_middle(self):
+ print >> self.fd, '''\
+ return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(lasso)
+{
+ lasso_shutdown();
+ return SUCCESS;
+}
+
+'''
+
+ def return_value(self, vtype, options, free = False):
+ if vtype is None:
+ return
+ elif vtype == 'gboolean':
+ print >> self.fd, ' RETVAL_BOOL(return_c_value);'
+ elif vtype in ['int', 'gint'] + self.binding_data.enums:
+ print >> self.fd, ' RETVAL_LONG(return_c_value);'
+ elif vtype in ('char*', 'gchar*'):
+ print >> self.fd, '''\
+ if (return_c_value) {
+ RETVAL_STRING(return_c_value, 1);
+ } else {
+ RETVAL_NULL();
+ }'''
+ if free:
+ print >> self.fd, ' free(return_c_value);'
+ elif vtype in ('const char*', 'const gchar*'):
+ print >> self.fd, '''\
+ if (return_c_value) {
+ RETVAL_STRING((char*)return_c_value, 1);
+ } else {
+ RETVAL_NULL();
+ }'''
+ elif vtype == 'xmlNode*':
+ print >> self.fd, '''\
+ {
+ char* xmlString = get_string_from_xml_node(return_c_value);
+ if (xmlString) {
+ RETVAL_STRING(xmlString, 0);
+ } else {
+ RETVAL_NULL();
+ }
+ }
+'''
+ elif vtype == 'GList*':
+ if options.get('elem_type') == 'char*':
+ print >> self.fd, '''\
+ set_array_from_list_of_strings(return_c_value, &return_value);
+'''
+ if free:
+ print >> self.fd, ' free_glist(&return_c_value, (GFunc)free);'
+ elif options.get('elem_type') == 'xmlNode*':
+ print >> self.fd, '''\
+ set_array_from_list_of_xmlnodes(return_c_value, &return_value);
+'''
+ if free:
+ print >> self.fd, ' free_glist(&return_c_value, (GFunc)efree);'
+ else:
+ print >> self.fd, '''\
+ set_array_from_list_of_objects(return_c_value, &return_value);
+'''
+ if free:
+ print >> self.fd, ' free_glist(&return_c_value, NULL);'
+ elif vtype == 'GHashTable*':
+ if options.get('elem_type') not in ('char*', 'xmlNode*'):
+ print >> self.fd, '''\
+ set_array_from_hashtable_of_objects(return_c_value, &return_value);
+'''
+ else:
+ print >> self.fd, '''\
+ if (return_c_value) {
+ self = PhpGObjectPtr_New(G_OBJECT(return_c_value));
+ ZEND_REGISTER_RESOURCE(return_value, self, le_lasso_server);
+ } else {
+ RETVAL_NULL();
+ }'''
+ if free:
+ print >> self.fd, ' if (return_c_value) {'
+ print >> self.fd, ' g_object_unref(return_c_value); // If constructor ref is off by one'
+ print >> self.fd, ' }'
+
+ def generate_function(self, m):
+ if m.name in ('lasso_init','lasso_shutdown'):
+ return
+ if m.rename:
+ name = m.rename
+ else:
+ name = m.name
+ self.functions_list.append(name)
+ print >> self.fd, '''PHP_FUNCTION(%s)
+{''' % name
+ parse_tuple_format = []
+ parse_tuple_args = []
+ for arg in m.args:
+ arg_type, arg_name, arg_options = arg
+ if arg_type in ('char*', 'const char*', 'gchar*', 'const gchar*'):
+ arg_type = arg_type.replace('const ', '')
+ parse_tuple_format.append('s!')
+ parse_tuple_args.append('&%s_str, &%s_len' % (arg_name, arg_name))
+ print >> self.fd, ' %s %s = NULL;' % ('char*', arg_name)
+ print >> self.fd, ' %s %s_str = NULL;' % ('char*', arg_name)
+ print >> self.fd, ' %s %s_len = 0;' % ('int', arg_name)
+ elif arg_type in ['int', 'gint', 'gboolean', 'const gboolean'] + self.binding_data.enums:
+ parse_tuple_format.append('l')
+ parse_tuple_args.append('&%s' % arg_name)
+ print >> self.fd, ' %s %s;' % ('long', arg_name)
+ elif arg_type == 'GList*':
+ parse_tuple_format.append('a!')
+ parse_tuple_args.append('&zval_%s' % arg_name)
+ print >> self.fd, ' %s zval_%s = NULL;' % ('zval*', arg_name)
+ print >> self.fd, ' %s %s = NULL;' % ('GList*', arg_name)
+ else:
+ parse_tuple_format.append('r')
+ parse_tuple_args.append('&zval_%s' % arg_name)
+ print >> self.fd, ' %s %s = NULL;' % (arg_type, arg_name)
+ print >> self.fd, ' %s zval_%s = NULL;' % ('zval*', arg_name)
+ print >> self.fd, ' %s cvt_%s = NULL;' % ('PhpGObjectPtr*', arg_name)
+
+ if m.return_type:
+ print >> self.fd, ' %s return_c_value;' % m.return_type
+ if m.return_type is not None and self.is_object(m.return_type):
+ print >> self.fd, ' PhpGObjectPtr *self;'
+ print >> self.fd, ''
+
+ parse_tuple_args = ', '.join(parse_tuple_args)
+ if parse_tuple_args:
+ parse_tuple_args = ', ' + parse_tuple_args
+
+ print >> self.fd, '''\
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "%s"%s) == FAILURE) {
+ RETURN_FALSE;
+ }
+''' % (''.join(parse_tuple_format), parse_tuple_args)
+
+ for f, arg in zip(parse_tuple_format, m.args):
+ if f.startswith('s'):
+ print >> self.fd, '''\
+ %(name)s = %(name)s_str;''' % {'name': arg[1]}
+ elif f.startswith('r'):
+ print >> self.fd, ' ZEND_FETCH_RESOURCE(cvt_%s, PhpGObjectPtr *, &zval_%s, -1, PHP_LASSO_SERVER_RES_NAME, le_lasso_server);' % (arg[1], arg[1])
+ print >> self.fd, ' %s = (%s)cvt_%s->obj;' % (arg[1], arg[0], arg[1])
+ elif f.startswith('a'):
+ elem_type = arg[2].get('elem_type')
+ if elem_type == 'char*':
+ print >> self.fd, ' %(name)s = get_list_from_array_of_strings(zval_%(name)s);' % {'name': arg[1]}
+ else:
+ print >> sys.stderr, 'E: In %(function)s arg %(name)s is of type GList<%(elem)s>' % { 'function': m.name, 'name': arg[1], 'elem': elem_type }
+ elif f == 'l':
+ pass
+ else:
+ raise Exception('%s format inconnu' % f)
+
+
+ if m.return_type is not None:
+ print >> self.fd, ' return_c_value = ',
+ if 'new' in m.name:
+ print >> self.fd, '(%s)' % m.return_type,
+ else:
+ print >> self.fd, ' ',
+ print >> self.fd, '%s(%s);' % (m.name, ', '.join([x[1] for x in m.args]))
+ # Free the converted arguments
+
+ for f, arg in zip(parse_tuple_format, m.args):
+ if f.startswith('a'):
+ elem_type = arg[2].get('elem_type')
+ if elem_type == 'char*':
+ print >> self.fd, ' if (%(name)s) {' % { 'name': arg[1] }
+ print >> self.fd, ' free_glist(&%(name)s,(GFunc)free);' % { 'name': arg[1] }
+ print >> self.fd, ' }'
+
+ self.return_value(m.return_type, {}, m.return_owner)
+
+ print >> self.fd, '}'
+ print >> self.fd, ''
+
+ def generate_members(self, c):
+ for m_type, m_name, m_options in c.members:
+ self.generate_getter(c.name, m_type, m_name, m_options)
+ self.generate_setter(c.name, m_type, m_name, m_options)
+
+ def generate_getter(self, klassname, m_type, m_name, m_options):
+ if m_type == 'GList*' and m_options.get('elem_type') not in ('char*', 'xmlNode*') \
+ and not self.is_object(m_options.get('elem_type')):
+ print >> sys.stderr, 'E: GList argument : %s of %s, with type : %s' % (m_name, klassname, m_options.get('elem_type'))
+ return
+
+ function_name = '%s_%s_get' % (klassname, utils.format_as_camelcase(m_name))
+ print >> self.fd, '''PHP_FUNCTION(%s)
+{''' % function_name
+ self.functions_list.append(function_name)
+
+
+ if self.is_object(m_type):
+ print >> self.fd, ' %s return_c_value = NULL;' % m_type
+ else:
+ print >> self.fd, ' %s return_c_value;' % m_type
+ print >> self.fd, ' %s* this;' % klassname
+ print >> self.fd, ' zval* zval_this;'
+ print >> self.fd, ' PhpGObjectPtr *cvt_this;'
+ if self.is_object(m_type):
+ print >> self.fd, ' PhpGObjectPtr *self;'
+ print >> self.fd, ''
+ print >> self.fd, '''\
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zval_this) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(cvt_this, PhpGObjectPtr *, &zval_this, -1, PHP_LASSO_SERVER_RES_NAME, le_lasso_server);
+ this = (%s*)cvt_this->obj;
+''' % (klassname)
+
+ if self.is_object(m_type):
+ print >> self.fd, ' if (this->%s != NULL) {' % m_name
+ print >> self.fd, ' return_c_value = this->%s;' % m_name
+ print >> self.fd, ' }'
+ else:
+ print >> self.fd, ' return_c_value = this->%s;' % m_name
+
+ self.return_value(m_type, m_options)
+
+ print >> self.fd, '}'
+ print >> self.fd, ''
+
+
+ def generate_setter(self, klassname, m_type, m_name, m_options):
+ if m_type == 'GList*' and m_options.get('elem_type') not in ('char*', 'xmlNode*') \
+ and not self.is_object(m_options.get('elem_type')):
+ print >> sys.stderr, 'E: GList argument : %s of %s, with type : %s' % (m_name, klassname, m_options.get('elem_type'))
+ return
+
+ function_name = '%s_%s_set' % (klassname, utils.format_as_camelcase(m_name))
+ print >> self.fd, '''PHP_FUNCTION(%s)
+{''' % function_name
+ self.functions_list.append(function_name)
+
+ print >> self.fd, ' %s* this;' % klassname
+ print >> self.fd, ' zval* zval_this;'
+ print >> self.fd, ' PhpGObjectPtr *cvt_this;'
+
+ # FIXME: This bloc should be factorised
+ parse_tuple_format = ''
+ parse_tuple_args = []
+ arg_type = m_type
+ arg_name = m_name
+ arg_options = m_options
+ if arg_type in ('char*', 'const char*', 'gchar*', 'const gchar*', 'xmlNode*'):
+ arg_type = arg_type.replace('const ', '')
+ parse_tuple_format += 's'
+ parse_tuple_args.append('&%s_str, &%s_len' % (arg_name, arg_name))
+ print >> self.fd, ' %s %s_str = NULL;' % ('char*', arg_name)
+ print >> self.fd, ' %s %s_len = 0;' % ('int', arg_name)
+ elif arg_type in ['int', 'gint', 'gboolean', 'const gboolean'] + self.binding_data.enums:
+ parse_tuple_format += 'l'
+ parse_tuple_args.append('&%s' % arg_name)
+ print >> self.fd, ' %s %s;' % ('long', arg_name)
+ # Must also handle lists of Objects
+ elif arg_type in ('GList*', 'GHashTable*'):
+ parse_tuple_format += 'a'
+ parse_tuple_args.append('&zval_%s' % arg_name)
+ print >> self.fd, ' %s zval_%s;' % ('zval*', arg_name)
+ else:
+ parse_tuple_format += 'r'
+ parse_tuple_args.append('&zval_%s' % arg_name)
+ print >> self.fd, ' %s zval_%s = NULL;' % ('zval*', arg_name)
+ print >> self.fd, ' %s cvt_%s = NULL;' % ('PhpGObjectPtr*', arg_name)
+
+ if parse_tuple_args:
+ parse_tuple_arg = parse_tuple_args[0]
+ else:
+ print >> self.fd, '}'
+ print >> self.fd, ''
+ return
+
+ print >> self.fd, ''
+ print >> self.fd, '''\
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r%s", &zval_this, %s) == FAILURE) {
+ return;
+ }
+''' % (parse_tuple_format, parse_tuple_arg)
+
+ # Get 'this' object
+ print >> self.fd, '''\
+ ZEND_FETCH_RESOURCE(cvt_this, PhpGObjectPtr *, &zval_this, -1, PHP_LASSO_SERVER_RES_NAME, le_lasso_server);
+ this = (%s*)cvt_this->obj;
+''' % klassname
+
+ # Set new value
+ if parse_tuple_format == 'l':
+ print >> self.fd, ' this->%s = %s;' % (m_name, m_name)
+ elif parse_tuple_format == 's':
+ print >> self.fd, ' if (this->%s) {' % m_name
+ print >> self.fd, ' g_free(this->%s);' % m_name
+ print >> self.fd, ' }'
+ print >> self.fd, ' if (%s_str && strcmp(%s_str, "") != 0) {' % (m_name, m_name)
+ if arg_type == 'xmlNode*':
+ print >> self.fd, ' this->%s = get_xml_node_from_string(%s_str);' % (m_name, m_name)
+ else:
+ print >> self.fd, ' this->%s = g_strndup(%s_str, %s_len);' % (m_name, m_name, m_name)
+ print >> self.fd, ' } else {'
+ print >> self.fd, ' this->%s = NULL;' % m_name
+ print >> self.fd, ' }'
+ elif arg_type == 'GList*':
+ if m_options.get('elem_type') == 'char*':
+ print >> self.fd, '''
+ if (this->%(name)s) {
+ /* free existing list */
+ g_list_foreach(this->%(name)s, (GFunc)g_free, NULL);
+ g_list_free(this->%(name)s);
+ }
+ this->%(name)s = get_list_from_array_of_strings(zval_%(name)s);
+''' % { 'name': m_name }
+ elif m_options.get('elem_type') == 'xmlNode*':
+ print >> self.fd, '''
+ if (this->%(name)s) {
+ /* free existing list */
+ g_list_foreach(this->%(name)s, (GFunc)xmlFreeNode, NULL);
+ g_list_free(this->%(name)s);
+ }
+ this->%(name)s = get_list_from_array_of_xmlnodes(zval_%(name)s);
+''' % { 'name': m_name }
+ else:
+ print >> self.fd, '''
+ free_glist(&this->%(name)s, (GFunc)g_object_unref);
+ this->%(name)s = get_list_from_array_of_objects(zval_%(name)s);
+''' % { 'name': m_name }
+ elif arg_type == 'GHashTable*' and arg_options.get('elem_type') != 'char*':
+ print >> self.fd, '''\
+ {
+ GHashTable *oldhash = this->%(name)s;
+ this->%(name)s = get_hashtable_from_array_of_objects(zval_%(name)s);
+ g_hash_table_destroy(oldhash);
+ }
+''' % { 'name': m_name }
+ elif parse_tuple_format == 'r':
+ print >> self.fd, ' ZEND_FETCH_RESOURCE(cvt_%s, PhpGObjectPtr*, &zval_%s, -1, PHP_LASSO_SERVER_RES_NAME, le_lasso_server);' % (m_name, m_name)
+ print >> self.fd, '''
+ g_object_ref(cvt_%(name)s->obj);
+ if (this->%(name)s)
+ g_object_unref(this->%(name)s);
+ this->%(name)s = (%(type)s)cvt_%(name)s->obj;
+''' % { 'name': m_name, 'type': m_type }
+
+ print >> self.fd, '}'
+ print >> self.fd, ''
+
+ def generate_functions_list(self):
+ print >> self.fd, '''\
+static function_entry lasso_functions[] = {'''
+ for m in self.functions_list:
+ print >> self.fd, ' PHP_FE(%s, NULL)' % m
+ print >> self.fd, '''\
+ {NULL, NULL, NULL}
+};
+'''
+
+ def generate_footer(self):
+ print >> self.fd, '''\
+zend_module_entry lasso_module_entry = {
+#if ZEND_MODULE_API_NO >= 20010901
+ STANDARD_MODULE_HEADER,
+#endif
+ PHP_LASSO_EXTNAME,
+ lasso_functions,
+ PHP_MINIT(lasso),
+ PHP_MSHUTDOWN(lasso),
+ NULL,
+ NULL,
+ NULL,
+#if ZEND_MODULE_API_NO >= 20010901
+ PHP_LASSO_VERSION,
+#endif
+ STANDARD_MODULE_PROPERTIES
+};
+'''
+
diff --git a/bindings/php5/wrapper_source_top.c b/bindings/php5/wrapper_source_top.c
new file mode 100644
index 00000000..ba7f1fe6
--- /dev/null
+++ b/bindings/php5/wrapper_source_top.c
@@ -0,0 +1,319 @@
+#include <php.h>
+#undef PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#include <lasso/lasso.h>
+#include "php_lasso.h"
+#include "../ghashtable.h"
+
+/* utility functions */
+static void free_glist(GList **list, GFunc free_function);
+
+/* Define the Lasso PHP module */
+
+int le_lasso_server;
+
+ZEND_GET_MODULE(lasso)
+
+/* Wrapper around GObject to get the dynamic typename */
+
+typedef struct {
+ GObject *obj;
+ char *typename;
+} PhpGObjectPtr;
+
+/** FIXME: implement caching of objects inside GObjects using a GQuark */
+static PhpGObjectPtr*
+PhpGObjectPtr_New(GObject *obj)
+{
+ PhpGObjectPtr *self;
+
+ if (obj == NULL) {
+ return NULL;
+ }
+
+ self = (PhpGObjectPtr *)malloc(sizeof(PhpGObjectPtr));
+ self->obj = g_object_ref(obj);
+ self->typename = strdup(G_OBJECT_TYPE_NAME(obj));
+ //printf("Allocating container %p for object %p of type %s with refcnt %i\n", self, obj, self->typename, obj->ref_count);
+
+ return self;
+}
+PHP_FUNCTION(lasso_init)
+{
+ RETURN_NULL();
+}
+PHP_FUNCTION(lasso_shutdown)
+{
+ RETURN_NULL();
+}
+PHP_FUNCTION(lasso_get_object_typename)
+{
+ PhpGObjectPtr *self;
+ zval *zval_self;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zval_self) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(self, PhpGObjectPtr *, &zval_self, -1, PHP_LASSO_SERVER_RES_NAME, le_lasso_server);
+ RETURN_STRING(self->typename, 1);
+}
+
+/* Generic destructor for PHP GObject */
+static void php_gobject_generic_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ PhpGObjectPtr* gobject = (PhpGObjectPtr*)rsrc->ptr;
+
+ if (gobject) {
+ if (gobject->obj) {
+ //printf("Deallocating container %p\n", gobject);
+ //printf("Deallocating %p that has %u refcounts\n", gobject->obj, gobject->obj->ref_count);
+ g_object_unref(G_OBJECT(gobject->obj));
+ //printf("now %u refcounts\n", gobject->obj->ref_count);
+ }
+ if (gobject->typename) {
+ free(gobject->typename);
+ }
+ free(gobject);
+ }
+}
+
+/* List handling */
+static void
+free_glist(GList **list, GFunc free_function) {
+ g_return_if_fail(list);
+ if (*list) {
+ if (free_function) {
+ g_list_foreach(*list, free_function, NULL);
+ }
+ g_list_free(*list);
+ }
+ *list = NULL;
+}
+/* Conversion functions */
+
+static char*
+get_string_from_xml_node(xmlNode *xmlnode)
+{
+ xmlOutputBufferPtr buf;
+ char *xmlString;
+
+ if (xmlnode == NULL) {
+ return NULL;
+ }
+
+ buf = xmlAllocOutputBuffer(NULL);
+ if (buf == NULL) {
+ xmlString = NULL;
+ } else {
+ xmlNodeDumpOutput(buf, NULL, xmlnode, 0, 1, NULL);
+ xmlOutputBufferFlush(buf);
+ if (buf->conv == NULL) {
+ xmlString = estrdup((char*)buf->buffer->content);
+ } else {
+ xmlString = estrdup((char*)buf->conv->content);
+ }
+ xmlOutputBufferClose(buf);
+ }
+
+ return xmlString;
+}
+
+static xmlNode*
+get_xml_node_from_string(char *string)
+{
+ xmlDoc *doc;
+ xmlNode *node;
+
+ doc = xmlReadDoc((xmlChar*)string, NULL, NULL, XML_PARSE_NONET);
+ node = xmlDocGetRootElement(doc);
+ if (node != NULL) {
+ node = xmlCopyNode(node, 1);
+ }
+ xmlFreeDoc(doc);
+
+ return node;
+}
+
+static GList*
+get_list_from_array_of_strings(zval* array)
+{
+ HashTable* hashtable;
+ HashPosition pointer;
+ int size;
+ zval** data;
+ zval temp;
+ GList* result = NULL;
+
+ hashtable = Z_ARRVAL_P(array);
+ size = zend_hash_num_elements(hashtable);
+ for (zend_hash_internal_pointer_reset_ex(hashtable, &pointer);
+ zend_hash_get_current_data_ex(hashtable, (void**) &data, &pointer) == SUCCESS;
+ zend_hash_move_forward_ex(hashtable, &pointer)) {
+ temp = **data;
+ zval_copy_ctor(&temp);
+ convert_to_string(&temp);
+ result = g_list_append(result, g_strndup(Z_STRVAL(temp), Z_STRLEN(temp)));
+ zval_dtor(&temp);
+ }
+ return result;
+}
+
+static void
+set_array_from_list_of_strings(GList* list, zval **array) {
+ GList* item;
+
+ array_init(*array);
+ for (item = g_list_first(list); item != NULL; item = g_list_next(item)) {
+ if (item->data != NULL) {
+ add_next_index_string(*array, item->data, 1);
+ } else {
+ add_next_index_null(*array);
+ }
+ }
+}
+
+static GList*
+get_list_from_array_of_xmlnodes(zval* array)
+{
+ HashTable* hashtable;
+ HashPosition pointer;
+ int size;
+ zval** data;
+ zval temp;
+ GList* result = NULL;
+
+ hashtable = Z_ARRVAL_P(array);
+ size = zend_hash_num_elements(hashtable);
+ for (zend_hash_internal_pointer_reset_ex(hashtable, &pointer);
+ zend_hash_get_current_data_ex(hashtable, (void**) &data, &pointer) == SUCCESS;
+ zend_hash_move_forward_ex(hashtable, &pointer)) {
+ temp = **data;
+ zval_copy_ctor(&temp);
+ convert_to_string(&temp);
+ result = g_list_append(result, get_xml_node_from_string(Z_STRVAL(temp)));
+ zval_dtor(&temp);
+ }
+ return result;
+}
+
+static void
+set_array_from_list_of_xmlnodes(GList* list, zval **array) {
+ GList* item;
+
+ array_init(*array);
+ for (item = g_list_first(list); item != NULL; item = g_list_next(item)) {
+ if (item->data != NULL) {
+ add_next_index_string(*array, get_string_from_xml_node(item->data), 0);
+ } else {
+ add_next_index_null(*array);
+ }
+ }
+}
+
+static GList*
+get_list_from_array_of_objects(zval *array)
+{
+ HashTable *hashtable;
+ HashPosition pointer;
+ int size;
+ zval **data;
+ PhpGObjectPtr *cvt_temp;
+ GList *result = NULL;
+
+ hashtable = Z_ARRVAL_P(array);
+ size = zend_hash_num_elements(hashtable);
+ for (zend_hash_internal_pointer_reset_ex(hashtable, &pointer);
+ zend_hash_get_current_data_ex(hashtable, (void**) &data, &pointer) == SUCCESS;
+ zend_hash_move_forward_ex(hashtable, &pointer)) {
+ cvt_temp = (PhpGObjectPtr*) zend_fetch_resource(data TSRMLS_CC, -1, PHP_LASSO_SERVER_RES_NAME, NULL, 1, le_lasso_server);
+ if (cvt_temp != NULL) {
+ g_object_ref(cvt_temp->obj);
+ result = g_list_append(result, cvt_temp->obj);
+ } else {
+ result = g_list_append(result, NULL);
+ }
+ }
+ return result;
+}
+
+static void
+set_array_from_list_of_objects(GList *list, zval **array)
+{
+ GList *item = NULL;
+ zval *zval_item = NULL;
+
+ array_init(*array);
+ for (item = g_list_first(list); item != NULL; item = g_list_next(item)) {
+ if (item->data != NULL) {
+ MAKE_STD_ZVAL(zval_item);
+ ZEND_REGISTER_RESOURCE(zval_item, PhpGObjectPtr_New(item->data), le_lasso_server);
+ add_next_index_zval(*array, zval_item);
+ } else {
+ add_next_index_null(*array);
+ }
+ }
+}
+
+/* FIXME: This function doesn't work yet */
+static GHashTable*
+get_hashtable_from_array_of_objects(zval *array)
+{
+ HashTable *hashtable = NULL;
+ HashPosition pointer;
+ int size;
+ char *key = NULL;
+ unsigned int key_len;
+ unsigned long index;
+ zval **data = NULL;
+ PhpGObjectPtr *cvt_temp = NULL;
+ GHashTable *result = NULL;
+
+ result = g_hash_table_new(g_str_hash, g_str_equal);
+ hashtable = Z_ARRVAL_P(array);
+ size = zend_hash_num_elements(hashtable);
+ for (zend_hash_internal_pointer_reset_ex(hashtable, &pointer);
+ zend_hash_get_current_data_ex(hashtable, (void**) &data, &pointer) == SUCCESS;
+ zend_hash_move_forward_ex(hashtable, &pointer)) {
+ cvt_temp = (PhpGObjectPtr*) zend_fetch_resource(data TSRMLS_CC, -1, PHP_LASSO_SERVER_RES_NAME, NULL, 1, le_lasso_server);
+ if (zend_hash_get_current_key_ex(hashtable, &key, &key_len, &index, 0, &pointer) == HASH_KEY_IS_STRING) {
+ if (cvt_temp != NULL) {
+ g_hash_table_insert(result, key, g_object_ref(cvt_temp->obj));
+ } else {
+ g_hash_table_insert(result, key, NULL);
+ }
+ } else {
+ if (cvt_temp != NULL) {
+ g_hash_table_insert(result, (gpointer)index, g_object_ref(cvt_temp->obj));
+ } else {
+ g_hash_table_insert(result, (gpointer)index, NULL);
+ }
+ }
+ }
+ return result;
+}
+
+static void
+set_array_from_hashtable_of_objects(GHashTable *hashtable, zval **array)
+{
+ GList *keys = NULL;
+ GObject *item = NULL;
+ zval *zval_item = NULL;
+
+ array_init(*array);
+ for (keys = g_hash_table_get_keys(hashtable); keys; keys = g_list_next(keys)) {
+ item = g_hash_table_lookup(hashtable, keys->data);
+ if (item) {
+ MAKE_STD_ZVAL(zval_item);
+ ZEND_REGISTER_RESOURCE(zval_item, PhpGObjectPtr_New(item), le_lasso_server);
+ add_assoc_zval(*array, (char*)keys->data, zval_item);
+ } else {
+ add_assoc_null(*array, (char*)keys->data);
+ }
+ }
+ g_list_free(keys);
+}
+