diff options
author | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-03-10 10:39:22 +0100 |
---|---|---|
committer | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-03-10 10:39:22 +0100 |
commit | d2e10c764d1b8860dd798eda3055fc957ff556ad (patch) | |
tree | 10e6d19cdc71f27e08e0134ad30fe34cd05b7046 /src | |
parent | 49d88d98a0656233f15923d31ea67a1ed229e514 (diff) |
fixed iterators for php 5.3 + updated documentation about iterators
Diffstat (limited to 'src')
-rw-r--r-- | src/classbase.cpp | 2 | ||||
-rw-r--r-- | src/iterator.cpp | 100 | ||||
-rw-r--r-- | src/value.cpp | 79 |
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 |