summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-10 10:39:22 +0100
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-10 10:39:22 +0100
commitd2e10c764d1b8860dd798eda3055fc957ff556ad (patch)
tree10e6d19cdc71f27e08e0134ad30fe34cd05b7046 /src
parent49d88d98a0656233f15923d31ea67a1ed229e514 (diff)
fixed iterators for php 5.3 + updated documentation about iterators
Diffstat (limited to 'src')
-rw-r--r--src/classbase.cpp2
-rw-r--r--src/iterator.cpp100
-rw-r--r--src/value.cpp79
3 files changed, 102 insertions, 79 deletions
diff --git a/src/classbase.cpp b/src/classbase.cpp
index 8926b3e..2ea813f 100644
--- a/src/classbase.cpp
+++ b/src/classbase.cpp
@@ -367,8 +367,6 @@ zend_object_value ClassBase::createObject(zend_class_entry *entry TSRMLS_DC)
*/
zend_object_iterator *ClassBase::getIterator(zend_class_entry *entry, zval *object, int by_ref)
{
- std::cout << "call to getIterator" << std::endl;
-
// by-ref is not possible (copied from SPL)
if (by_ref) throw Php::Exception("Foreach by ref is not possible");
diff --git a/src/iterator.cpp b/src/iterator.cpp
index c0e9c3d..a6c7e01 100644
--- a/src/iterator.cpp
+++ b/src/iterator.cpp
@@ -19,8 +19,6 @@ namespace Php {
*/
void Iterator::destructor(zend_object_iterator *iter)
{
- std::cout << "destruct iterator" << std::endl;
-
// get the actual iterator
Iterator *iterator = (Iterator *)iter->data;
@@ -39,8 +37,6 @@ void Iterator::destructor(zend_object_iterator *iter)
*/
int Iterator::valid(zend_object_iterator *iter)
{
- std::cout << "Iterator::valid" << std::endl;
-
// get the actual iterator
Iterator *iterator = (Iterator *)iter->data;
@@ -55,20 +51,15 @@ int Iterator::valid(zend_object_iterator *iter)
*/
void Iterator::current(zend_object_iterator *iter, zval ***data)
{
- std::cout << "get current value " << std::endl;
-
// get the actual iterator
Iterator *iterator = (Iterator *)iter->data;
- // retrieve the value
- Value value(iterator->current());
+ // retrieve the value (and store it in a member so that it is not
+ // destructed when the function returns)
+ iterator->_current = iterator->current();
- std::cout << "detach value " << value << std::endl;
-
- zval *val = value.detach();
-
// copy the value
- *data = &val;
+ *data = &iterator->_current._val;
}
/**
@@ -77,50 +68,57 @@ void Iterator::current(zend_object_iterator *iter, zval ***data)
* this handler is not provided auto-incrementing integer keys will be
* used.
* @param iter
- * @param retval
+ * @param key
*/
-void Iterator::key(zend_object_iterator *iter, zval *retval)
+void Iterator::key(zend_object_iterator *iter, zval *key)
{
// get the actual iterator
Iterator *iterator = (Iterator *)iter->data;
- // wrap data into a result object
-// Value result(data);
-
-// ZVAL_LONG(data, 123);
-
-// return;
-// std::cout << "retrieve key " << result.refcount() << std::endl;
-
- // retrieve the key as key
- Value keyValue = iterator->key();
-
- std::cout << "got key " << keyValue << " " << keyValue.refcount() << std::endl;
+ // retrieve the key
+ Value retval(iterator->key());
-// zval *zval = key.detach();
+ // detach the underlying zval
+ zval *zval = retval.detach();
+
+ // copy it to the key
+ ZVAL_ZVAL(key, zval, 1, 1);
+}
+/**
+ * Function to retrieve the current key, php 5.3 style
+ * @param iter
+ * @param str_key
+ * @param str_key_len
+ * @param int_key
+ * @return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG
+ */
+int Iterator::key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key)
+{
+ // get the actual iterator
+ Iterator *iterator = (Iterator *)iter->data;
- std::cout << "ret key " << retval << " " << Z_REFCOUNT_P(retval) << std::endl;
-
- ZVAL_LONG(retval, rand());
-
-// ZVAL_ZVAL(data, zval, 1, 1);
-
- return;
-
- // copy the key into the other zval, but we use a string or numeric for
- // this operation, because we have looked at the implementation of Value
- // and assigning a full value to the result variable will cause the zval
- // to be destructed and re-allocated (which we do not need)
-// if (key.isString()) ZVAL_STRING(data, key.stringValue();
-// else ZVAL_LONG(data, key.numericValue());
-//
-// std::cout << "key is copied" << std::endl;
-//
-// // detach from result
-// result.detach();
-//
- std::cout << "detached" << std::endl;
+ // retrieve the key
+ Value retval(iterator->key());
+
+ // is this a numeric string?
+ if (retval.isString())
+ {
+ // copy the key and the from the value
+ *str_key = estrndup(retval.rawValue(), retval.size());
+ *str_key_len = retval.size() + 1;
+
+ // done
+ return HASH_KEY_IS_STRING;
+ }
+ else
+ {
+ // convert to a numeric
+ *int_key = retval.numericValue();
+
+ // done
+ return HASH_KEY_IS_LONG;
+ }
}
/**
@@ -129,8 +127,6 @@ void Iterator::key(zend_object_iterator *iter, zval *retval)
*/
void Iterator::next(zend_object_iterator *iter)
{
- std::cout << "Iterator::next" << std::endl;
-
// get the actual iterator
Iterator *iterator = (Iterator *)iter->data;
@@ -144,8 +140,6 @@ void Iterator::next(zend_object_iterator *iter)
*/
void Iterator::rewind(zend_object_iterator *iter)
{
- std::cout << "Iterator::rewind" << std::endl;
-
// get the actual iterator
Iterator *iterator = (Iterator *)iter->data;
diff --git a/src/value.cpp b/src/value.cpp
index f8ee3e9..a78c2d4 100644
--- a/src/value.cpp
+++ b/src/value.cpp
@@ -1479,25 +1479,43 @@ std::map<std::string,Php::Value> Value::mapValue() const
// reset iterator to beginning of the hash table
zend_hash_internal_pointer_reset(arr);
- // pointer that will be set to hash key and index
- char *key;
- unsigned long ind;
+ // loop through the records
+ while (true)
+ {
+ // pointer that will be set to hash key and index
+ char *key;
+ unsigned long ind;
- // key type
- int hash_key_type;
+ // get current key
+ int hash_key_type = zend_hash_get_current_key(arr, &key, &ind, 0);
- // loop through the recors
- while ((hash_key_type = zend_hash_get_current_key(arr, &key, &ind, 0)) != HASH_KEY_NON_EXISTENT)
- {
// required variable
zval **value;
- // retrieve data
- zend_hash_get_current_data(arr, (void **) &value);
+ // check the type
+ switch (hash_key_type) {
+
+ // was it a string?
+ case HASH_KEY_IS_STRING:
- // check the type of key
- if (HASH_KEY_IS_LONG != hash_key_type) result[key] = Value(*value);
- else result[std::to_string(ind)] = Value(*value);
+ // retrieve data, and add to result
+ zend_hash_get_current_data(arr, (void **) &value);
+ result[key] = Value(*value);
+ break;
+
+ // was it numeric?
+ case HASH_KEY_IS_LONG:
+
+ // retrieve data, and add to result
+ zend_hash_get_current_data(arr, (void **) &value);
+ result[std::to_string(ind)] = Value(*value);
+ break;
+
+ default:
+
+ // we're ready
+ return result;
+ }
// next iteration
zend_hash_move_forward(arr);
@@ -1511,24 +1529,37 @@ std::map<std::string,Php::Value> Value::mapValue() const
// reset iterator to beginning of the hash table
zend_hash_internal_pointer_reset(arr);
- // pointer that will be set to hash key and index
- char *key;
- unsigned long ind;
-
// loop through the records
- while( zend_hash_get_current_key(arr, &key, &ind, 0) != HASH_KEY_NON_EXISTENT )
+ while (true)
{
- // if property is accessible (i.e. propertie access type is public. See rebuild_object_properties )
- if('\0' != *key)
- {
+ // pointer that will be set to hash key and index
+ char *key;
+ unsigned long ind;
+
+ // get current key
+ int hash_key_type = zend_hash_get_current_key(arr, &key, &ind, 0);
+
+ // check the type
+ switch (hash_key_type) {
+
+ // was it a string?
+ case HASH_KEY_IS_STRING:
+
+ // inaccessible properties (privates) start with a null character
+ if (*key == '\0') break;
+
// required variable
zval **value;
- // retrieve property
+ // retrieve data, and add to result
zend_hash_get_current_data(arr, (void **) &value);
-
- // append to mape
result[key] = Value(*value);
+ break;
+
+ default:
+
+ // we're ready
+ return result;
}
// next iteration