summaryrefslogtreecommitdiff
path: root/zend/iteratorimpl.h
blob: 2199e6f49aa992496551b7b873d0e7899dc57ef5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/**
 *  Iterator.h
 *
 *  Base class for iterators. Extension writers that want to create traversable
 *  classes, should override the Php::Traversable base class. This base class
 *  forces you to implement a getIterator() method that returns an instance of
 *  a Php::Iterator class.
 *
 *  In this file you find the signature of the Php::Iterator class. It mostly has
 *  pure virtual methods, which means that you should create a derived class
 *  that implements all these methods.
 *
 *  @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
 *  @copyright 2014 Copernica BV
 */

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

/**
 *  Class definition
 */
class IteratorImpl
{
private:
    /**
     *  Unique pointer to the iterator that is returned by the extension
     *  @var    std::unique_ptr
     */
    std::unique_ptr<Iterator> _iterator;

    /**
     *  The current() method that is called by the Zend engine wants a
     *  pointer-to-pointer-to-a-zval. Because of this, we have to keep the
     *  current value in memory after the current() method returns because
     *  the pointer would otherwise fall out of scope. This is (once again)
     *  odd behavior of the Zend engine, but we'll have to live with that
     *  @var    Value
     */
    Value _current;

    /**
     *  The object iterator as is needed by the Zend engine
     *  @var    zend_object_iterator
     */
    zend_object_iterator _impl;

    /**
     *  Get access to all iterator functions
     *  @return zend_object_iterator_funcs
     */
    static zend_object_iterator_funcs *functions();

    /**
     *  Is the iterator on a valid position
     *  @return bool
     */
    bool valid()
    {
        return _iterator->valid();
    }

    /**
     *  The value at the current position
     *  @return Value
     */
    Value current()
    {
        return _iterator->current();
    }

    /**
     *  The key at the current position
     *  @return Value
     */
    Value key()
    {
        return _iterator->key();
    }

    /**
     *  Move to the next position
     */
    void next()
    {
        return _iterator->next();
    }

    /**
     *  Rewind the iterator to the front position
     */
    void rewind()
    {
        return _iterator->rewind();
    }

    /**
     *  Iterator destructor method
     *  @param  iter
     *  @param  tsrm_ls
     */
    static void destructor(zend_object_iterator *iter TSRMLS_DC);

    /**
     *  Iterator valid function
     *  Returns FAILURE or SUCCESS
     *  @param  iter
     *  @param  tsrm_ls
     *  @return int
     */
    static int valid(zend_object_iterator *iter TSRMLS_DC);

    /**
     *  Fetch the current item
     *
     *  @param  iter    The iterator used to retrieve the value from
     *  @param  tsrm_ls Thread safety variable
     *  @return The current value of the iterator
     */
    static zval *current(zend_object_iterator *iter TSRMLS_DC);

    /**
     *  Fetch the key for the current element (optional, may be NULL). The key
     *  should be written into the provided zval* using the ZVAL_* macros. If
     *  this handler is not provided auto-incrementing integer keys will be
     *  used.
     *  @param  iter
     *  @param  data
     *  @param  tsrm_ls
     */
    static void key(zend_object_iterator *iter, zval *data TSRMLS_DC);

    /**
     *  Function to retrieve the current key, php 5.3 style
     *  @param  iter
     *  @param  str_key
     *  @param  str_key_len
     *  @param  int_key
     *  @param  tsrm_ls
     *  @return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG
     */
    static int key(zend_object_iterator *iter, char **str_key, unsigned int *str_key_len, unsigned long *int_key TSRMLS_DC);

    /**
     *  Step forwards to the next element
     *  @param  iter
     *  @param  tsrm_ls
     */
    static void next(zend_object_iterator *iter TSRMLS_DC);

    /**
     *  Rewind the iterator back to the start
     *  @param  iter
     *  @param  tsrm_ls
     */
    static void rewind(zend_object_iterator *iter TSRMLS_DC);

public:
    /**
     *  Constructor
     *  @param  iterator        The iterator that is implemented by the extension
     */
    IteratorImpl(Iterator *iterator) : _iterator(iterator)
    {
        // wrap it in a zval
        ZVAL_PTR(&_impl.data, this);

        // initialize impl object
        _impl.index = 0;
        _impl.funcs = functions();
    }

    /**
     *  Destructor
     */
    virtual ~IteratorImpl() {}

    /**
     *  Internal method that returns the implementation object
     *  @return zend_object_iterator
     */
    zend_object_iterator *implementation()
    {
        return &_impl;
    }
};

/**
 *  End namespace
 */
}