@@ -46,6 +46,181 @@ PHONGO_API zend_class_entry *php_phongo_cursor_ce;
46
46
47
47
zend_object_handlers php_phongo_handler_cursor ;
48
48
49
+ static void php_phongo_cursor_free_current (php_phongo_cursor_t * cursor ) /* {{{ */
50
+ {
51
+ if (!Z_ISUNDEF (cursor -> visitor_data .zchild )) {
52
+ zval_ptr_dtor (& cursor -> visitor_data .zchild );
53
+ #if PHP_VERSION_ID >= 70000
54
+ ZVAL_UNDEF (& cursor -> visitor_data .zchild );
55
+ #else
56
+ cursor -> visitor_data .zchild = NULL ;
57
+ #endif
58
+ }
59
+ } /* }}} */
60
+
61
+ void php_phongo_cursor_free (php_phongo_cursor_t * cursor ) /* {{{ */
62
+ {
63
+ if (cursor -> cursor ) {
64
+ mongoc_cursor_destroy (cursor -> cursor );
65
+ cursor -> cursor = NULL ;
66
+ }
67
+
68
+ php_phongo_cursor_free_current (cursor );
69
+ } /* }}} */
70
+
71
+ /* {{{ Iterator handlers */
72
+ static void php_phongo_cursor_iterator_dtor (zend_object_iterator * iter TSRMLS_DC ) /* {{{ */
73
+ {
74
+ php_phongo_cursor_iterator * cursor_it = (php_phongo_cursor_iterator * )iter ;
75
+
76
+ if (!Z_ISUNDEF (cursor_it -> intern .data )) {
77
+ #if PHP_VERSION_ID >= 70000
78
+ zval_ptr_dtor (& cursor_it -> intern .data );
79
+ #else
80
+ zval_ptr_dtor ((zval * * )& cursor_it -> intern .data );
81
+ cursor_it -> intern .data = NULL ;
82
+ #endif
83
+ }
84
+
85
+ #if PHP_VERSION_ID < 70000
86
+ efree (cursor_it );
87
+ #endif
88
+ } /* }}} */
89
+
90
+ static int php_phongo_cursor_iterator_valid (zend_object_iterator * iter TSRMLS_DC ) /* {{{ */
91
+ {
92
+ php_phongo_cursor_t * cursor = ((php_phongo_cursor_iterator * )iter )-> cursor ;
93
+
94
+ if (!Z_ISUNDEF (cursor -> visitor_data .zchild )) {
95
+ return SUCCESS ;
96
+ }
97
+
98
+ return FAILURE ;
99
+ } /* }}} */
100
+
101
+ #if PHP_VERSION_ID < 50500
102
+ static int php_phongo_cursor_iterator_get_current_key (zend_object_iterator * iter , char * * str_key , uint * str_key_len , ulong * int_key TSRMLS_DC ) /* {{{ */
103
+ {
104
+ php_phongo_cursor_t * cursor = ((php_phongo_cursor_iterator * )iter )-> cursor ;
105
+
106
+ * int_key = (ulong ) cursor -> current ;
107
+ return HASH_KEY_IS_LONG ;
108
+ } /* }}} */
109
+ #else
110
+ static void php_phongo_cursor_iterator_get_current_key (zend_object_iterator * iter , zval * key TSRMLS_DC ) /* {{{ */
111
+ {
112
+ php_phongo_cursor_t * cursor = ((php_phongo_cursor_iterator * )iter )-> cursor ;
113
+
114
+ ZVAL_LONG (key , cursor -> current );
115
+ } /* }}} */
116
+ #endif
117
+
118
+ #if PHP_VERSION_ID < 70000
119
+ static void php_phongo_cursor_iterator_get_current_data (zend_object_iterator * iter , zval * * * data TSRMLS_DC ) /* {{{ */
120
+ {
121
+ php_phongo_cursor_t * cursor = ((php_phongo_cursor_iterator * )iter )-> cursor ;
122
+
123
+ * data = & cursor -> visitor_data .zchild ;
124
+ } /* }}} */
125
+ #else
126
+ static zval * php_phongo_cursor_iterator_get_current_data (zend_object_iterator * iter ) /* {{{ */
127
+ {
128
+ php_phongo_cursor_t * cursor = ((php_phongo_cursor_iterator * )iter )-> cursor ;
129
+
130
+ return & cursor -> visitor_data .zchild ;
131
+ } /* }}} */
132
+ #endif
133
+
134
+ static void php_phongo_cursor_iterator_move_forward (zend_object_iterator * iter TSRMLS_DC ) /* {{{ */
135
+ {
136
+ php_phongo_cursor_iterator * cursor_it = (php_phongo_cursor_iterator * )iter ;
137
+ php_phongo_cursor_t * cursor = cursor_it -> cursor ;
138
+ const bson_t * doc ;
139
+
140
+ php_phongo_cursor_free_current (cursor );
141
+ cursor -> current ++ ;
142
+
143
+ if (mongoc_cursor_next (cursor -> cursor , & doc )) {
144
+ phongo_bson_to_zval_ex (bson_get_data (doc ), doc -> len , & cursor -> visitor_data );
145
+ } else {
146
+ bson_error_t error ;
147
+
148
+ if (mongoc_cursor_error (cursor -> cursor , & error )) {
149
+ /* Intentionally not destroying the cursor as it will happen
150
+ * naturally now that there are no more results */
151
+ phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
152
+ }
153
+ }
154
+ } /* }}} */
155
+
156
+ static void php_phongo_cursor_iterator_rewind (zend_object_iterator * iter TSRMLS_DC ) /* {{{ */
157
+ {
158
+ php_phongo_cursor_iterator * cursor_it = (php_phongo_cursor_iterator * )iter ;
159
+ php_phongo_cursor_t * cursor = cursor_it -> cursor ;
160
+ const bson_t * doc ;
161
+
162
+ if (cursor -> current > 0 ) {
163
+ phongo_throw_exception (PHONGO_ERROR_LOGIC TSRMLS_CC , "Cursors cannot rewind after starting iteration" );
164
+ return ;
165
+ }
166
+
167
+ php_phongo_cursor_free_current (cursor );
168
+
169
+ doc = mongoc_cursor_current (cursor -> cursor );
170
+
171
+ if (doc ) {
172
+ phongo_bson_to_zval_ex (bson_get_data (doc ), doc -> len , & cursor -> visitor_data );
173
+ }
174
+ } /* }}} */
175
+
176
+ /* iterator handler table */
177
+ zend_object_iterator_funcs php_phongo_cursor_iterator_funcs = {
178
+ php_phongo_cursor_iterator_dtor ,
179
+ php_phongo_cursor_iterator_valid ,
180
+ php_phongo_cursor_iterator_get_current_data ,
181
+ php_phongo_cursor_iterator_get_current_key ,
182
+ php_phongo_cursor_iterator_move_forward ,
183
+ php_phongo_cursor_iterator_rewind ,
184
+ NULL /* invalidate_current is not used */
185
+ };
186
+
187
+ zend_object_iterator * php_phongo_cursor_get_iterator (zend_class_entry * ce , zval * object , int by_ref TSRMLS_DC ) /* {{{ */
188
+ {
189
+ php_phongo_cursor_iterator * cursor_it = NULL ;
190
+ php_phongo_cursor_t * cursor = Z_CURSOR_OBJ_P (object );
191
+
192
+ if (by_ref ) {
193
+ zend_error (E_ERROR , "An iterator cannot be used with foreach by reference" );
194
+ }
195
+
196
+ if (cursor -> got_iterator ) {
197
+ phongo_throw_exception (PHONGO_ERROR_LOGIC TSRMLS_CC , "Cursors cannot yield multiple iterators" );
198
+ return NULL ;
199
+ }
200
+
201
+ cursor -> got_iterator = 1 ;
202
+
203
+ cursor_it = ecalloc (1 , sizeof (php_phongo_cursor_iterator ));
204
+ #if PHP_VERSION_ID >= 70000
205
+ zend_iterator_init (& cursor_it -> intern );
206
+ #endif
207
+
208
+ #if PHP_VERSION_ID >= 70000
209
+ ZVAL_COPY (& cursor_it -> intern .data , object );
210
+ #else
211
+ Z_ADDREF_P (object );
212
+ cursor_it -> intern .data = (void * )object ;
213
+ #endif
214
+ cursor_it -> intern .funcs = & php_phongo_cursor_iterator_funcs ;
215
+ cursor_it -> cursor = cursor ;
216
+ /* cursor_it->current should already be allocated to zero */
217
+
218
+ php_phongo_cursor_free_current (cursor_it -> cursor );
219
+
220
+ return & cursor_it -> intern ;
221
+ } /* }}} */
222
+ /* }}} */
223
+
49
224
/* {{{ proto void Cursor::setTypeMap(array $typemap)
50
225
Sets a type map to use for BSON unserialization */
51
226
PHP_METHOD (Cursor , setTypeMap )
0 commit comments