summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-09 18:21:12 +0100
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-09 18:21:12 +0100
commitb2a054d0b01fc6fbf00dd93efed8f2e19426a02a (patch)
tree9d23854ec117c151934daaec9141bf4e36e49e13
parent8e9d929a752775883e3a7379bb7372299d40255d (diff)
parent5a186cc932524d85ce602e152a79d5201a4eb3b5 (diff)
Merge branch 'issue23' of https://github.com/valmat/PHP-CPP
-rw-r--r--Examples/CppClassesInPhp/check_map.php86
-rw-r--r--Examples/CppClassesInPhp/cppclassinphp.cpp18
-rw-r--r--src/value.cpp81
3 files changed, 164 insertions, 21 deletions
diff --git a/Examples/CppClassesInPhp/check_map.php b/Examples/CppClassesInPhp/check_map.php
new file mode 100644
index 0000000..2103bac
--- /dev/null
+++ b/Examples/CppClassesInPhp/check_map.php
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * For functionality testing. You can then delete.
+ *
+ */
+
+class cl0 {
+ public $cl0_float = 3.14;
+ public $cl0_str1 = 'public str1';
+ private $cl0_str2 = 'private str2';
+ protected $cl0_str3 = 'protected str3';
+}
+
+class cl1 extends cl0 implements arrayaccess
+{
+ static $cl1_static = 'static prop';
+
+ const CL1_CONST = 'const prop';
+
+ public $cl1_num = 45615;
+ public $cl1_str = "Public Prop";
+
+ private $cl1_pp1 = "Private Prop1";
+ private $cl1_pp2 = "Private Prop2";
+
+ protected $cl1_prp1 = "Protected Prop1";
+ protected $cl1_prp2 = "Protected Prop2";
+
+ public function fn($a) {
+ echo $a;
+ }
+
+ function __toString() {
+ return 'I\'m class cl1';
+ }
+
+ public function offsetSet($offset, $value) {
+ if (!is_null($offset)) {
+ $this->$offset = $value;
+ }
+ }
+ public function offsetExists($offset) {
+ return isset($this->$offset);
+ }
+ public function offsetUnset($offset) {
+ unset($this->$offset);
+ }
+ public function offsetGet($offset) {
+ return isset($this->$offset) ? $this->$offset : null;
+ }
+
+}
+
+class emptyClass {}
+
+$arr = array(
+ 'qwe' => 'qweqweqweqw',
+ 'asd' => 'Привет!', // check UTF-8 chars
+ 'zxccvx' => 'sdfsecvyh6bug6yfty',
+ 1=>2,
+ '2'=>2,
+ 44,
+ new cl1(),
+ '%'=>'%$%$%',
+ );
+
+$arr = new cl1();
+
+$arr[5] = 55;
+$arr['strstr'] = 'strstrstrstrstrstr';
+
+//$arr = new emptyClass();
+//$arr = array();
+
+
+$q = new MyClass();
+
+var_export($arr);
+
+//$q->loopArray($arr);
+
+// Works for objects and arrays
+$q->loopObject($arr);
+//$q->loopObject($arr);
+
diff --git a/Examples/CppClassesInPhp/cppclassinphp.cpp b/Examples/CppClassesInPhp/cppclassinphp.cpp
index 400d942..9a4e130 100644
--- a/Examples/CppClassesInPhp/cppclassinphp.cpp
+++ b/Examples/CppClassesInPhp/cppclassinphp.cpp
@@ -51,6 +51,17 @@ public:
{
return 33;
}
+
+ void loop(Php::Parameters &params)
+ {
+ std::cout << "Array/Object contains " << params[0].size() << " items" << std::endl;
+ auto m = params[0].mapValue();
+
+ std::cout << "map contains " << m.size() << " items" << std::endl;
+ for(auto &i: m) {
+ std::cout << "key: " << i.first << " \t\tval: " << i.second << std::endl;
+ }
+ }
Php::Value myMethod(Php::Parameters &params)
{
@@ -124,6 +135,13 @@ extern "C"
customClass.method("myMethod2", &MyCustomClass::myMethod);
customClass.property("property1", "prop1");
customClass.property("property2", "prop2", Php::Protected);
+
+ customClass.method("loopArray", &MyCustomClass::loop, {
+ Php::ByVal("arr", Php::Type::Array)
+ });
+ customClass.method("loopObject", &MyCustomClass::loop, {
+ Php::ByVal("obj", Php::Type::Object)
+ });
// add the class to the extension
extension.add(customClass);
diff --git a/src/value.cpp b/src/value.cpp
index 2afb750..752d77e 100644
--- a/src/value.cpp
+++ b/src/value.cpp
@@ -1467,32 +1467,71 @@ int Value::size() const
*/
std::map<std::string,Php::Value> Value::mapValue() const
{
+ // loop through the zval key/value pairs, and return a map
+ // result variable
+ std::map<std::string,Php::Value> result;
+
// check type
- if (isArray())
+ if (isArray() || isObject())
{
- // result variable
- std::map<std::string,Php::Value> result;
-
- // @todo loop through the zval key/value pairs, and return a map
+ zval **value;
+ char *key;
+ unsigned long ind;
- // done
- return result;
- }
- else if (isObject())
- {
- // result variable
- std::map<std::string,Php::Value> result;
-
- // @todo convert the properties to a map
+ // get access to the internal hash table of _val
+ // see Zend/zend_API.h 723: HASH_OF(_val)
+ HashTable *arr = isArray() ? Z_ARRVAL_P(_val) : Z_OBJ_HT_P(_val)->get_properties((_val) TSRMLS_CC);
- // done
- return result;
- }
- else
- {
- // return an empty map
- return std::map<std::string,Php::Value>();
+
+ // similarly php: reset($array):
+ // The definition of this and the following functions can be found in Zend/zend_hash.h 174
+ // Maybe make it optional?
+ // If the following line to remove, then repeated calling the Value::mapValue() will return an empty map
+ zend_hash_internal_pointer_reset(arr);
+
+ if (isArray())
+ {
+ unsigned int hash_key_type;
+ while( (hash_key_type = zend_hash_get_current_key(arr, &key, &ind, 0)) != HASH_KEY_NON_EXISTENT )
+ {
+ zend_hash_get_current_data(arr, (void **) &value);
+
+ if(HASH_KEY_IS_LONG == hash_key_type)
+ {
+ result[std::to_string(ind)] = Value(*value);
+ }
+ else // hash_key_type == HASH_KEY_IS_STRING
+ {
+ result[key] = Value(*value);
+ }
+
+ // next iteration
+ zend_hash_move_forward(arr);
+ }
+ }
+ else
+ {
+ // For obtaining a hashtable of the object meets function void rebuild_object_properties(zend_object *zobj)
+ // Zend/zend_object_handlers.c 66
+ // hashtable of object's properties always has string (no integer) keys
+ while( zend_hash_get_current_key(arr, &key, &ind, 0) != HASH_KEY_NON_EXISTENT )
+ {
+ // if propertie is accessible (i.e. propertie access type is public. See rebuild_object_properties )
+ if('\0' != *key)
+ {
+ zend_hash_get_current_data(arr, (void **) &value);
+ result[key] = Value(*value);
+ }
+
+ // next iteration
+ zend_hash_move_forward(arr);
+ }
+ }
+
}
+
+ // done
+ return result;
}
/**