<commit_before>/**
 *  TraverseIterator.h
 *
 *  When an object from PHP userspace implements its own iterator methods,
 *  and the Php::Value object is used to iterate over its properties, this
 *  TraversableIterator class is used to iterate over the properties
 *
 *  @author <NAME> <<EMAIL>>
 *  @copyright 2014 Copernica BV
 */

/**
 *  Set up namespace
 */
namespace Php {

/**
 *  Class definition
 */
class TraverseIterator : public IteratorImpl
{
public:
    /**
     *  Constructor
     *  @param  object
     *  @param  begin
     */
    TraverseIterator(zval *object, bool begin) : _object(object)
    {
        // leap out if this iterator starts at the end
        if (!begin) return;
        
        // we need the class entry
        auto *entry = zend_get_class_entry(object);
        
        // create the iterator
        _iter = entry->get_iterator(entry, object, false);
        
        // rewind the iterator
        _iter->funcs->rewind(_iter);
        
        // is the iterator at a valid position?
        if (_iter->funcs->valid(_iter)) return;
        
        // reset the iterator
        _iter->funcs->dtor(_iter);
        
        // set back to null
        _iter = nullptr;
    }
    
    /**
     *  Copy constructor
     *  @param  that
     */
    TraverseIterator(const TraverseIterator &that) : TraverseIterator(that._object, that._iter != nullptr)
    {
        // @todo    this is a broken implementation, the copy is at the start
        //          position, while we'd like to be at the same position
    }
    
    /**
     *  Destructor
     */
    virtual ~TraverseIterator()
    {
        // call the iterator destructor
        if (_iter) _iter->funcs->dtor(_iter);
    }

    /**
     *  Clone the object
     *  @return IteratorImpl*
     */
    virtual IteratorImpl *clone() override
    {
        return new TraverseIterator(*this);
    }

    /**
     *  Increment position (pre-increment)
     *  @return bool
     */
    virtual bool increment() override
    {
        // do we still have an iterator?
        if (_iter) return false;
        
        // movw it forward
        _iter->funcs->move_forward(_iter);
        
        // and read current data
        read();
    }
    
    /**
     *  Decrement position (pre-decrement)
     *  @return bool
     */
    virtual bool decrement() override
    {
        // not possible with PHP iterators
    }

    /**
     *  Compare with other iterator
     *  @param  that
     *  @return bool
     */
    virtual bool equals(const IteratorImpl *that) const override
    {
        // of course if the objects are identical
        if (this == that) return true;
        
        // cast to traverse-iterator
        TraverseIterator *other = (TraverseIterator *)that;
        
        // if both objects are in an invalid state we consider them to be identical
        if (!_iter && !other->_iter) return true;
        
        // although the iterators could be at the same pos, for simplicity
        // we consider them different here
        return false;
    }

    /**
     *  Derefecence, this returns a std::pair with the current key and value
     *  @return std::pair
     */
    virtual const std::pair<Value,Value> &current() const
    {
        return _data;
    }

private:
    /**
     *  The object that is iterated over
     *  @var    _val
     */
    zval *_object = nullptr;
    
    /**
     *  The iterator from Zend
     *  @var    zend_object_iterator
     */
    struct _zend_object_iterator *_iter = nullptr;

    /**
     *  Current data
     *  @var    pair
     */
    std::pair<Value,Value> _data;


    /**
     *  Read current data
     *  @return bool
     */
    bool read()
    {
        // not possible when no iterator exists
        if (!_iter) return false;

        // is the iterator at a valid position?
        if (_iter->funcs->valid(_iter))
        {
            // we need to read the current key and value
            // @todo implementation for php 5.3 and php 5.4 and higher

#if PHP_VERSION_ID >= 50400

            // create a value object
            Value val;
            
            // call the function to get the key
            _iter->funcs->get_current_key(_iter, _val.

#else

            // variable we need for fetching the key, and that will be assigned by
            // the PHP engine
            char *str_key; unsigned int str_key_len; unsigned long int_key;

            // php 5.3 code, fetch the current key
            int type = _iter->funcs->get_current_key(_iter, &str_key, &str_key_len, &int_key);
            
            // what sort of key do we have?<commit_msg>fixed some issues with traverse iterators<commit_after>/**
 *  TraverseIterator.h
 *
 *  When an object from PHP userspace implements its own iterator methods,
 *  and the Php::Value object is used to iterate over its properties, this
 *  TraversableIterator class is used to iterate over the properties
 *
 *  @author <NAME> <<EMAIL>>
 *  @copyright 2014 Copernica BV
 */

/**
 *  Set up namespace
 */
namespace Php {

/**
 *  Class definition
 */
class TraverseIterator : public IteratorImpl
{
public:
    /**
     *  Constructor
     *  @param  object
     *  @param  begin
     */
    TraverseIterator(zval *object, bool begin) : _object(object)
    {
        // leap out if this iterator starts at the end
        if (!begin) return;
        
        // we need the class entry
        auto *entry = zend_get_class_entry(object);
        
        // create the iterator
        _iter = entry->get_iterator(entry, object, false);
        
        // rewind the iterator
        _iter->funcs->rewind(_iter);
        
        // is the iterator at a valid position?
        if (_iter->funcs->valid(_iter) != FAILURE) return;
        
        // reset the iterator
        _iter->funcs->dtor(_iter);
        
        // set back to null
        _iter = nullptr;
    }
    
    /**
     *  Copy constructor
     *  @param  that
     */
    TraverseIterator(const TraverseIterator &that) : TraverseIterator(that._object, that._iter != nullptr)
    {
        // @todo    this is a broken implementation, the copy is at the start
        //          position, while we'd like to be at the same position
    }
    
    /**
     *  Destructor
     */
    virtual ~TraverseIterator()
    {
        // call the iterator destructor
        if (_iter) _iter->funcs->dtor(_iter);
    }

    /**
     *  Clone the object
     *  @return IteratorImpl*
     */
    virtual IteratorImpl *clone() override
    {
        return new TraverseIterator(*this);
    }

    /**
     *  Increment position (pre-increment)
     *  @return bool
     */
    virtual bool increment() override
    {
        // do we still have an iterator?
        if (!_iter) return false;
        
        // movw it forward
        _iter->funcs->move_forward(_iter);
        
        // and read current data
        read();
    }
    
    /**
     *  Decrement position (pre-decrement)
     *  @return bool
     */
    virtual bool decrement() override
    {
        // not possible with PHP iterators
        throw Exception("Impossible to iterate backwards");
    }

    /**
     *  Compare with other iterator
     *  @param  that
     *  @return bool
     */
    virtual bool equals(const IteratorImpl *that) const override
    {
        // of course if the objects are identical
        if (this == that) return true;
        
        // cast to traverse-iterator
        TraverseIterator *other = (TraverseIterator *)that;
        
        // if both objects are in an invalid state we consider them to be identical
        if (!_iter && !other->_iter) return true;
        
        // although the iterators could be at the same pos, for simplicity
        // we consider them different here
        return false;
    }

    /**
     *  Derefecence, this returns a std::pair with the current key and value
     *  @return std::pair
     */
    virtual const std::pair<Value,Value> &current() const
    {
        return _data;
    }

private:
    /**
     *  The object that is iterated over
     *  @var    _val
     */
    zval *_object = nullptr;
    
    /**
     *  The iterator from Zend
     *  @var    zend_object_iterator
     */
    struct _zend_object_iterator *_iter = nullptr;

    /**
     *  Current data
     *  @var    pair
     */
    std::pair<Value,Value> _data;


    /**
     *  Read current data
     *  @return bool
     */
    bool read()
    {
        // not possible when no iterator exists
        if (!_iter) return false;

        // is the iterator at a valid position?
        if (_iter->funcs->valid(_iter) != FAILURE)
        {
            // we need to read the current key and value
            // @todo implementation for php 5.3 and php 5.4 and higher

#if PHP_VERSION_ID >= 50400

            // create a value object
            Value val;
            
            // call the function to get the key
            _iter->funcs->get_current_key(_iter, _val.

#else

            // variable we need for fetching the key, and that will be assigned by
            // the PHP engine
            char *str_key; unsigned int str_key_len; unsigned long int_key;

            // php 5.3 code, fetch the current key
            int type = _iter->funcs->get_current_key(_iter, &str_key, &str_key_len, &int_key);
            
            // what sort of key do we have?
{'fraction_non_alphanumeric': 0.09306278550940189, 'fraction_numerical': 0.003187081695527462, 'mean_word_length': 1.6997418984800687, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3182524', 'n_tokens_mistral': 2707, 'n_tokens_neox': 2630, 'n_words': 885}