@@ -240,6 +240,318 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_ASSIGN_DIM)
240240#endif
241241/* }}} */
242242
243+ SPL_CLASS_FUNCTION (array , __construct );
244+ SPL_CLASS_FUNCTION (array , rewind );
245+ SPL_CLASS_FUNCTION (array , current );
246+ SPL_CLASS_FUNCTION (array , key );
247+ SPL_CLASS_FUNCTION (array , next );
248+ SPL_CLASS_FUNCTION (array , has_more );
249+
250+ static zend_function_entry spl_array_class_functions [] = {
251+ SPL_CLASS_FE (array , __construct , NULL )
252+ SPL_CLASS_FE (array , rewind , NULL )
253+ SPL_CLASS_FE (array , current , NULL )
254+ SPL_CLASS_FE (array , key , NULL )
255+ SPL_CLASS_FE (array , next , NULL )
256+ SPL_CLASS_FE (array , has_more , NULL )
257+ {NULL , NULL , NULL }
258+ };
259+
260+ static zend_object_handlers spl_array_handlers ;
261+ static zend_class_entry * spl_ce_array ;
262+
263+ typedef struct _spl_array_object {
264+ zend_object std ;
265+ zval * array ;
266+ HashPosition pos ;
267+ } spl_array_object ;
268+
269+ /* {{{ spl_array_object_dtor */
270+ static void spl_array_object_dtor (void * object , zend_object_handle handle TSRMLS_DC )
271+ {
272+ spl_array_object * intern = (spl_array_object * )object ;
273+
274+ zend_hash_destroy (intern -> std .properties );
275+ FREE_HASHTABLE (intern -> std .properties );
276+
277+ if (!ZVAL_DELREF (intern -> array )) {
278+ zval_dtor (intern -> array );
279+ FREE_ZVAL (intern -> array );
280+ }
281+
282+ efree (object );
283+ }
284+ /* }}} */
285+
286+ /* {{{ spl_array_object_new */
287+ static zend_object_value spl_array_object_new_ex (zend_class_entry * class_type , spl_array_object * * obj , spl_array_object * orig TSRMLS_DC )
288+ {
289+ zend_object_value retval ;
290+ spl_array_object * intern ;
291+ zval * tmp ;
292+
293+ intern = emalloc (sizeof (spl_array_object ));
294+ memset (intern , 0 , sizeof (spl_array_object ));
295+ intern -> std .ce = class_type ;
296+ * obj = intern ;
297+
298+ ALLOC_HASHTABLE (intern -> std .properties );
299+ zend_hash_init (intern -> std .properties , 0 , NULL , ZVAL_PTR_DTOR , 0 );
300+ zend_hash_copy (intern -> std .properties , & class_type -> default_properties , (copy_ctor_func_t ) zval_add_ref , (void * ) & tmp , sizeof (zval * ));
301+
302+ if (orig ) {
303+ intern -> array = orig -> array ;
304+ ZVAL_ADDREF (intern -> array );
305+ } else {
306+ MAKE_STD_ZVAL (intern -> array );
307+ array_init (intern -> array );
308+ }
309+ zend_hash_internal_pointer_reset_ex (HASH_OF (intern -> array ), & intern -> pos );
310+
311+ retval .handle = zend_objects_store_put (intern , spl_array_object_dtor , NULL TSRMLS_CC );
312+ retval .handlers = & spl_array_handlers ;
313+ return retval ;
314+ }
315+ /* }}} */
316+
317+ /* {{{ spl_array_object_new */
318+ static zend_object_value spl_array_object_new (zend_class_entry * class_type TSRMLS_DC )
319+ {
320+ spl_array_object * tmp ;
321+ return spl_array_object_new_ex (class_type , & tmp , NULL TSRMLS_CC );
322+ }
323+ /* }}} */
324+
325+ /* {{{ spl_array_object_clone */
326+ static zend_object_value spl_array_object_clone (zval * zobject TSRMLS_DC )
327+ {
328+ zend_object_value new_obj_val ;
329+ zend_object * old_object ;
330+ zend_object * new_object ;
331+ zend_object_handle handle = Z_OBJ_HANDLE_P (zobject );
332+ spl_array_object * intern ;
333+
334+ old_object = zend_objects_get_address (zobject TSRMLS_CC );
335+ new_obj_val = spl_array_object_new_ex (old_object -> ce , & intern , (spl_array_object * )old_object TSRMLS_CC );
336+ new_object = & intern -> std ;
337+
338+ zend_objects_clone_members (new_object , new_obj_val , old_object , handle TSRMLS_CC );
339+
340+ return new_obj_val ;
341+ }
342+ /* }}} */
343+
344+ /* {{{ spl_array_get_ce */
345+ static zend_class_entry * spl_array_get_ce (zval * object TSRMLS_DC )
346+ {
347+ return spl_ce_array ;
348+ }
349+ /* }}} */
350+
351+ /* {{{ spl_array_read_dimension */
352+ zval * spl_array_read_dimension (zval * object , zval * offset TSRMLS_DC )
353+ {
354+ spl_array_object * intern = (spl_array_object * )zend_object_store_get_object (object TSRMLS_CC );
355+ zval * * retval ;
356+ long index ;
357+
358+ switch (Z_TYPE_P (offset )) {
359+ case IS_STRING :
360+ if (!zend_is_numeric_key (offset , & index )) {
361+ if (zend_hash_find (HASH_OF (intern -> array ), Z_STRVAL_P (offset ), Z_STRLEN_P (offset )+ 1 , (void * * ) & retval ) == FAILURE ) {
362+ zend_error (E_NOTICE ,"Undefined index: %s" , Z_STRVAL_P (offset ));
363+ return EG (uninitialized_zval_ptr );
364+ } else {
365+ return * retval ;
366+ }
367+ break ;
368+ }
369+ /* NO break */
370+ case IS_DOUBLE :
371+ case IS_RESOURCE :
372+ case IS_BOOL :
373+ case IS_LONG :
374+ if (offset -> type == IS_DOUBLE ) {
375+ index = (long )Z_DVAL_P (offset );
376+ } else if (offset -> type != IS_STRING ) {
377+ index = Z_LVAL_P (offset );
378+ }
379+ if (zend_hash_index_find (HASH_OF (intern -> array ), index , (void * * ) & retval ) == FAILURE ) {
380+ zend_error (E_NOTICE ,"Undefined offset: %d" , Z_LVAL_P (offset ));
381+ return EG (uninitialized_zval_ptr );
382+ } else {
383+ return * retval ;
384+ }
385+ break ;
386+ default :
387+ zend_error (E_WARNING , "Illegal offset type" );
388+ return EG (uninitialized_zval_ptr );
389+ }
390+ }
391+ /* }}} */
392+
393+ /* {{{ spl_array_write_dimension */
394+ void spl_array_write_dimension (zval * object , zval * offset , zval * value TSRMLS_DC )
395+ {
396+ spl_array_object * intern = (spl_array_object * )zend_object_store_get_object (object TSRMLS_CC );
397+ long index ;
398+
399+ switch (Z_TYPE_P (offset )) {
400+ case IS_STRING :
401+ if (!zend_is_numeric_key (offset , & index )) {
402+ add_assoc_zval (intern -> array , Z_STRVAL_P (offset ), value );
403+ return ;
404+ }
405+ /* NO break */
406+ case IS_DOUBLE :
407+ case IS_RESOURCE :
408+ case IS_BOOL :
409+ case IS_LONG :
410+ if (offset -> type == IS_DOUBLE ) {
411+ index = (long )Z_DVAL_P (offset );
412+ } else if (offset -> type != IS_STRING ) {
413+ index = Z_LVAL_P (offset );
414+ }
415+ add_index_zval (intern -> array , index , value );
416+ return ;
417+ default :
418+ zend_error (E_WARNING , "Illegal offset type" );
419+ return ;
420+ }
421+ }
422+ /* }}} */
423+
424+ /* {{{*/
425+ HashTable * spl_array_get_properties (zval * object TSRMLS_DC )
426+ {
427+ spl_array_object * intern = (spl_array_object * )zend_object_store_get_object (object TSRMLS_CC );
428+
429+ return HASH_OF (intern -> array );
430+ }
431+ /* }}} */
432+
433+ /* {{{ PHP_MINIT_FUNCTION(spl_array) */
434+ PHP_MINIT_FUNCTION (spl_array )
435+ {
436+ REGISTER_SPL_STD_CLASS_EX (array , spl_array_object_new , spl_array_class_functions );
437+ REGISTER_SPL_IMPLEMENT (array , sequence_assoc );
438+ memcpy (& spl_array_handlers , zend_get_std_object_handlers (), sizeof (zend_object_handlers ));
439+ spl_array_handlers .clone_obj = spl_array_object_clone ;
440+ spl_array_handlers .get_class_entry = spl_array_get_ce ;
441+ spl_array_handlers .read_dimension = spl_array_read_dimension ;
442+ spl_array_handlers .write_dimension = spl_array_write_dimension ;
443+ spl_array_handlers .get_properties = spl_array_get_properties ;
444+
445+ return SUCCESS ;
446+ }
447+ /* }}} */
448+
449+ /* {{{ proto void __construct(array ar = array())
450+ Cronstructs a new array iterator from a path. */
451+ SPL_CLASS_FUNCTION (array , __construct )
452+ {
453+ zval * object = getThis ();
454+ spl_array_object * intern ;
455+ zval * * array ;
456+
457+ if (ZEND_NUM_ARGS () == 0 ) {
458+ return ; /* nothing to do */
459+ }
460+ /* exceptions do not work yet
461+ php_set_error_handling(EH_THROW, zend_exception_get_default() TSRMLS_CC);*/
462+
463+ if (ZEND_NUM_ARGS () > 1 || zend_get_parameters_ex (1 , & array ) == FAILURE ) {
464+ WRONG_PARAM_COUNT ;
465+ }
466+ if (!HASH_OF (* array )) {
467+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Passed variable is not an array or object, using empty array instead" );
468+ php_set_error_handling (EH_NORMAL , NULL TSRMLS_CC );
469+ return ;
470+ }
471+ intern = (spl_array_object * )zend_object_store_get_object (object TSRMLS_CC );
472+ zval_dtor (intern -> array );
473+ FREE_ZVAL (intern -> array );
474+ intern -> array = * array ;
475+ ZVAL_ADDREF (intern -> array );
476+
477+ zend_hash_internal_pointer_reset_ex (HASH_OF (intern -> array ), & intern -> pos );
478+
479+ php_set_error_handling (EH_NORMAL , NULL TSRMLS_CC );
480+ }
481+ /* }}} */
482+
483+ /* {{{ proto void rewind()
484+ Rewind array back to the start */
485+ SPL_CLASS_FUNCTION (array , rewind )
486+ {
487+ zval * object = getThis ();
488+ spl_array_object * intern = (spl_array_object * )zend_object_store_get_object (object TSRMLS_CC );
489+
490+ zend_hash_internal_pointer_reset_ex (HASH_OF (intern -> array ), & intern -> pos );
491+ }
492+ /* }}} */
493+
494+ /* {{{ proto string current()
495+ Return current array entry */
496+ SPL_CLASS_FUNCTION (array , current )
497+ {
498+ zval * object = getThis ();
499+ spl_array_object * intern = (spl_array_object * )zend_object_store_get_object (object TSRMLS_CC );
500+ zval * * entry ;
501+
502+ if (zend_hash_get_current_data_ex (HASH_OF (intern -> array ), (void * * ) & entry , & intern -> pos ) == FAILURE ) {
503+ RETURN_FALSE ;
504+ }
505+ * return_value = * * entry ;
506+ zval_copy_ctor (return_value );
507+ }
508+ /* }}} */
509+
510+ /* {{{ proto string key()
511+ Return current array key */
512+ SPL_CLASS_FUNCTION (array , key )
513+ {
514+ zval * object = getThis ();
515+ spl_array_object * intern = (spl_array_object * )zend_object_store_get_object (object TSRMLS_CC );
516+ char * string_key ;
517+ uint string_length ;
518+ ulong num_key ;
519+
520+ switch (zend_hash_get_current_key_ex (HASH_OF (intern -> array ), & string_key , & string_length , & num_key , 0 , & intern -> pos )) {
521+ case HASH_KEY_IS_STRING :
522+ RETVAL_STRINGL (string_key , string_length - 1 , 1 );
523+ break ;
524+ case HASH_KEY_IS_LONG :
525+ RETVAL_LONG (num_key );
526+ break ;
527+ case HASH_KEY_NON_EXISTANT :
528+ return ;
529+ }
530+ }
531+ /* }}} */
532+
533+ /* {{{ proto void next()
534+ Move to next entry */
535+ SPL_CLASS_FUNCTION (array , next )
536+ {
537+ zval * object = getThis ();
538+ spl_array_object * intern = (spl_array_object * )zend_object_store_get_object (object TSRMLS_CC );
539+
540+ zend_hash_move_forward_ex (HASH_OF (intern -> array ), & intern -> pos );
541+ }
542+ /* }}} */
543+
544+ /* {{{ proto string has_more()
545+ Check whether array contains more entries */
546+ SPL_CLASS_FUNCTION (array , has_more )
547+ {
548+ zval * object = getThis ();
549+ spl_array_object * intern = (spl_array_object * )zend_object_store_get_object (object TSRMLS_CC );
550+
551+ RETURN_BOOL (zend_hash_has_more_elements_ex (HASH_OF (intern -> array ), & intern -> pos ) == SUCCESS );
552+ }
553+ /* }}} */
554+
243555/*
244556 * Local variables:
245557 * tab-width: 4
0 commit comments