diff options
author | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-03-16 14:55:51 +0100 |
---|---|---|
committer | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-03-16 14:55:51 +0100 |
commit | ec6d84016bec41b05e275641f990831572171969 (patch) | |
tree | ff76497cf1a000d96892dd9b2ed2ab6144a3bf89 /src/valueiterator.cpp | |
parent | a83e9b3af70f35400ec5d62a4b400d55b05c3492 (diff) |
added Value::begin() and Value::end() methods to make it possible to iterate over a value
Diffstat (limited to 'src/valueiterator.cpp')
-rw-r--r-- | src/valueiterator.cpp | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/valueiterator.cpp b/src/valueiterator.cpp new file mode 100644 index 0000000..a40ff81 --- /dev/null +++ b/src/valueiterator.cpp @@ -0,0 +1,135 @@ +/** + * ValueIterator.cpp + * + * Implementation of the value iterator + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2014 Copernica BV + */ +#include "includes.h" + +/** + * Set up namespace + */ +namespace Php { + +/** + * Constructor + * @param hashtable The hashtable to iterate over + * @param first Should it start at the first position? + */ +ValueIterator::ValueIterator(HashTable *hashtable, bool first) : _table(hashtable) +{ + // reset the hash pointer to the internal position + if (hashtable && first) + { + // move to first position + zend_hash_internal_pointer_reset_ex(_table, &_position); + + // read current data + read(); + } + else + { + // start with invalid data + invalidate(); + } +} + +/** + * Increment position + * @return ValueIterator + */ +ValueIterator &ValueIterator::operator++() +{ + // leap out if already on an invalid pos (behind the last pos) + if (!_position) return *this; + + // move the iterator forward + if (zend_hash_move_forward_ex(_table, &_position) == SUCCESS) + { + // read current key and value + return read(); + } + else + { + // invalidate current position + return invalidate(); + } +} + +/** + * Decrement position + * @return ValueIterator + */ +ValueIterator &ValueIterator::operator--() +{ + // leap out if we're not even iterating over a hash table + if (!_table) return *this; + + // if position is invalid, it is one position behind the last position + if (!_position) + { + // move to last position + zend_hash_internal_pointer_end_ex(_table, &_position); + } + else if (zend_hash_move_backwards_ex(_table, &_position) == FAILURE) + { + // invalidate current position + return invalidate(); + } + + // read current key and value + return read(); +} + +/** + * Read current key and value + * @return ValueIterator + */ +ValueIterator &ValueIterator::read() +{ + // zval to read the current key in + Value key; + + // read in the current key + zend_hash_get_current_key_zval_ex(_table, key._val, &_position); + + // if the key is set to NULL, it means that the object is not at a valid position + if (key.isNull()) return invalidate(); + + // iterator is at a valid position, go fetch the data + // this is the variable we need for fetching the data + zval **value; + + // retrieve data + zend_hash_get_current_data_ex(_table, (void **) &value, &_position); + + // we can now update the current data + _current = std::make_pair<Value,Value>(std::move(key), *value); + + // done + return *this; +} + +/** + * Invalidate the iterator + * @return ValueIterator + */ +ValueIterator &ValueIterator::invalidate() +{ + // forget current position + _position = nullptr; + + // make the data a pair of null ptrs + _current = std::make_pair<Value,Value>(nullptr,nullptr); + + // done + return *this; +} + +/** + * End namespace + */ +} + |