@@ -92,6 +92,67 @@ static void php_phongo_iterator_build_current(php_phongo_iterator_t* intern)
92
92
phongo_bson_value_to_zval (bson_iter_value (& intern -> iter ), & intern -> current );
93
93
}
94
94
95
+ static zval * php_phongo_iterator_get_current (php_phongo_iterator_t * intern )
96
+ {
97
+ if (!intern -> valid ) {
98
+ phongo_throw_exception (PHONGO_ERROR_LOGIC , "Cannot call current() on an exhausted iterator" );
99
+ return NULL ;
100
+ }
101
+
102
+ if (Z_ISUNDEF (intern -> current )) {
103
+ php_phongo_iterator_build_current (intern );
104
+ }
105
+
106
+ return & intern -> current ;
107
+ }
108
+
109
+ static void php_phongo_iterator_next (php_phongo_iterator_t * intern )
110
+ {
111
+ intern -> valid = bson_iter_next (& intern -> iter );
112
+ intern -> key ++ ;
113
+ php_phongo_iterator_free_current (intern );
114
+ }
115
+
116
+ static bool php_phongo_iterator_key (php_phongo_iterator_t * intern , zval * key )
117
+ {
118
+ const char * ckey ;
119
+
120
+ if (!intern -> valid ) {
121
+ phongo_throw_exception (PHONGO_ERROR_LOGIC , "Cannot call key() on an exhausted iterator" );
122
+ return false;
123
+ }
124
+
125
+ if (intern -> is_array ) {
126
+ ZVAL_LONG (key , intern -> key );
127
+
128
+ return true;
129
+ }
130
+
131
+ ckey = bson_iter_key (& intern -> iter );
132
+ if (!bson_utf8_validate (ckey , strlen (ckey ), false)) {
133
+ phongo_throw_exception (PHONGO_ERROR_UNEXPECTED_VALUE , "Detected corrupt BSON data at offset %d" , intern -> iter .off );
134
+ return false;
135
+ }
136
+
137
+ ZVAL_STRING (key , ckey );
138
+
139
+ return true;
140
+ }
141
+
142
+ static void php_phongo_iterator_rewind (php_phongo_iterator_t * intern )
143
+ {
144
+ /* Don't re-initialise iterator if we're still on the first item */
145
+ if (intern -> key == 0 ) {
146
+ return ;
147
+ }
148
+
149
+ php_phongo_iterator_free_current (intern );
150
+
151
+ bson_iter_init (& intern -> iter , php_phongo_iterator_get_bson_from_zval (& intern -> bson ));
152
+ intern -> key = 0 ;
153
+ intern -> valid = bson_iter_next (& intern -> iter );
154
+ }
155
+
95
156
static HashTable * php_phongo_iterator_get_properties_hash (phongo_compat_object_handler_type * object , bool is_temp )
96
157
{
97
158
php_phongo_iterator_t * intern ;
@@ -113,48 +174,33 @@ PHONGO_DISABLED_WAKEUP(MongoDB_BSON_Iterator)
113
174
static PHP_METHOD (MongoDB_BSON_Iterator , current )
114
175
{
115
176
php_phongo_iterator_t * intern = Z_ITERATOR_OBJ_P (getThis ());
177
+ zval * data ;
116
178
117
179
PHONGO_PARSE_PARAMETERS_NONE ();
118
180
119
- if (!intern -> valid ) {
120
- phongo_throw_exception (PHONGO_ERROR_LOGIC , "Cannot call current() on an exhausted iterator" );
121
- return ;
122
- }
123
-
124
- if (Z_ISUNDEF (intern -> current )) {
125
- php_phongo_iterator_build_current (intern );
181
+ data = php_phongo_iterator_get_current (intern );
182
+ if (!data ) {
183
+ // Exception already thrown
184
+ RETURN_NULL ();
126
185
}
127
186
128
- if (Z_ISUNDEF ( intern -> current )) {
187
+ if (Z_ISUNDEF_P ( data )) {
129
188
RETURN_NULL ();
130
189
} else {
131
- ZVAL_COPY_DEREF (return_value , & intern -> current );
190
+ ZVAL_COPY_DEREF (return_value , data );
132
191
}
133
192
}
134
193
135
194
static PHP_METHOD (MongoDB_BSON_Iterator , key )
136
195
{
137
- const char * key ;
138
196
php_phongo_iterator_t * intern = Z_ITERATOR_OBJ_P (getThis ());
139
197
140
198
PHONGO_PARSE_PARAMETERS_NONE ();
141
199
142
- if (!intern -> valid ) {
143
- phongo_throw_exception ( PHONGO_ERROR_LOGIC , "Cannot call key() on an exhausted iterator" );
200
+ if (!php_phongo_iterator_key ( intern , return_value ) ) {
201
+ // Exception already thrown
144
202
return ;
145
203
}
146
-
147
- if (intern -> is_array ) {
148
- RETURN_LONG (intern -> key );
149
- }
150
-
151
- key = bson_iter_key (& intern -> iter );
152
- if (!bson_utf8_validate (key , strlen (key ), false)) {
153
- phongo_throw_exception (PHONGO_ERROR_UNEXPECTED_VALUE , "Detected corrupt BSON data at offset %d" , intern -> iter .off );
154
- return ;
155
- }
156
-
157
- RETURN_STRING (key );
158
204
}
159
205
160
206
static PHP_METHOD (MongoDB_BSON_Iterator , next )
@@ -163,9 +209,7 @@ static PHP_METHOD(MongoDB_BSON_Iterator, next)
163
209
164
210
PHONGO_PARSE_PARAMETERS_NONE ();
165
211
166
- intern -> valid = bson_iter_next (& intern -> iter );
167
- intern -> key ++ ;
168
- php_phongo_iterator_free_current (intern );
212
+ php_phongo_iterator_next (intern );
169
213
}
170
214
171
215
static PHP_METHOD (MongoDB_BSON_Iterator , valid )
@@ -183,16 +227,7 @@ static PHP_METHOD(MongoDB_BSON_Iterator, rewind)
183
227
184
228
PHONGO_PARSE_PARAMETERS_NONE ();
185
229
186
- /* Don't re-initialise iterator if we're still on the first item */
187
- if (intern -> key == 0 ) {
188
- return ;
189
- }
190
-
191
- php_phongo_iterator_free_current (intern );
192
-
193
- bson_iter_init (& intern -> iter , php_phongo_iterator_get_bson_from_zval (& intern -> bson ));
194
- intern -> key = 0 ;
195
- intern -> valid = bson_iter_next (& intern -> iter );
230
+ php_phongo_iterator_rewind (intern );
196
231
}
197
232
198
233
void phongo_iterator_init (zval * return_value , zval * document_or_packedarray )
@@ -263,10 +298,93 @@ static HashTable* php_phongo_iterator_get_properties(phongo_compat_object_handle
263
298
return php_phongo_iterator_get_properties_hash (object , false);
264
299
}
265
300
301
+ /* Iterator handlers */
302
+ static void php_phongo_iterator_it_dtor (zend_object_iterator * iter )
303
+ {
304
+ zval_ptr_dtor (& iter -> data );
305
+ }
306
+
307
+ static int php_phongo_iterator_it_valid (zend_object_iterator * iter )
308
+ {
309
+ php_phongo_iterator_t * intern = Z_ITERATOR_OBJ_P (& iter -> data );
310
+
311
+ return intern -> valid ? SUCCESS : FAILURE ;
312
+ }
313
+
314
+ static zval * php_phongo_iterator_it_get_current_data (zend_object_iterator * iter )
315
+ {
316
+ php_phongo_iterator_t * intern = Z_ITERATOR_OBJ_P (& iter -> data );
317
+
318
+ return php_phongo_iterator_get_current (intern );
319
+ }
320
+
321
+ static void php_phongo_iterator_it_get_current_key (zend_object_iterator * iter , zval * key )
322
+ {
323
+ php_phongo_iterator_t * intern = Z_ITERATOR_OBJ_P (& iter -> data );
324
+
325
+ if (!php_phongo_iterator_key (intern , key )) {
326
+ // Exception already thrown
327
+ return ;
328
+ }
329
+ }
330
+
331
+ static void php_phongo_iterator_it_move_forward (zend_object_iterator * iter )
332
+ {
333
+ php_phongo_iterator_t * intern = Z_ITERATOR_OBJ_P (& iter -> data );
334
+
335
+ php_phongo_iterator_next (intern );
336
+ }
337
+
338
+ static void php_phongo_iterator_it_rewind (zend_object_iterator * iter )
339
+ {
340
+ php_phongo_iterator_t * intern = Z_ITERATOR_OBJ_P (& iter -> data );
341
+
342
+ php_phongo_iterator_rewind (intern );
343
+ }
344
+
345
+ #if PHP_VERSION_ID >= 80000
346
+ static HashTable * php_phongo_iterator_it_get_gc (zend_object_iterator * iter , zval * * table , int * n )
347
+ {
348
+ * n = 1 ;
349
+ * table = & iter -> data ;
350
+ return NULL ;
351
+ }
352
+ #endif
353
+
354
+ static const zend_object_iterator_funcs php_phongo_iterator_it_funcs = PHONGO_ITERATOR_FUNCS (
355
+ php_phongo_iterator_it_dtor ,
356
+ php_phongo_iterator_it_valid ,
357
+ php_phongo_iterator_it_get_current_data ,
358
+ php_phongo_iterator_it_get_current_key ,
359
+ php_phongo_iterator_it_move_forward ,
360
+ php_phongo_iterator_it_rewind ,
361
+ NULL , /* invalidate_current */
362
+ php_phongo_iterator_it_get_gc );
363
+
364
+ static zend_object_iterator * php_phongo_iterator_get_iterator (zend_class_entry * ce , zval * object , int by_ref )
365
+ {
366
+ zend_object_iterator * iterator ;
367
+
368
+ if (by_ref ) {
369
+ phongo_throw_exception (PHONGO_ERROR_LOGIC , "An iterator cannot be used with foreach by reference" );
370
+ return NULL ;
371
+ }
372
+
373
+ iterator = emalloc (sizeof (zend_object_iterator ));
374
+ zend_iterator_init (iterator );
375
+
376
+ ZVAL_OBJ_COPY (& iterator -> data , Z_OBJ_P (object ));
377
+
378
+ iterator -> funcs = & php_phongo_iterator_it_funcs ;
379
+
380
+ return iterator ;
381
+ }
382
+
266
383
void php_phongo_iterator_init_ce (INIT_FUNC_ARGS )
267
384
{
268
385
php_phongo_iterator_ce = register_class_MongoDB_BSON_Iterator (zend_ce_iterator );
269
386
php_phongo_iterator_ce -> create_object = php_phongo_iterator_create_object ;
387
+ php_phongo_iterator_ce -> get_iterator = php_phongo_iterator_get_iterator ;
270
388
PHONGO_CE_DISABLE_SERIALIZATION (php_phongo_iterator_ce );
271
389
272
390
memcpy (& php_phongo_handler_iterator , phongo_get_std_object_handlers (), sizeof (zend_object_handlers ));
0 commit comments