@@ -52,7 +52,9 @@ typedef struct _arraylist { /* {{{ */
5252
5353typedef struct _arraylist_object { /* {{{ */
5454 arraylist array ;
55- zend_object std ;
55+ zend_object std ;
56+ int current ;
57+ int flags ;
5658} arraylist_object ;
5759/* }}} */
5860
@@ -69,7 +71,7 @@ static inline arraylist_object *arraylist_from_obj(zend_object *obj) /* {{{ */ {
6971
7072/* {{{ arginfo
7173 */
72- ZEND_BEGIN_ARG_INFO_EX (arginfo_arraylist__construct , 0 , 0 , 1 )
74+ ZEND_BEGIN_ARG_INFO_EX (arginfo_arraylist__construct , 0 , 0 , 0 )
7375 ZEND_ARG_INFO (0 , size )
7476ZEND_END_ARG_INFO ()
7577
@@ -89,9 +91,9 @@ static void arraylist_init(arraylist *array, zend_long size) /* {{{ */
8991{
9092 array -> elements = NULL ;
9193 array -> elements = (zval * )ecalloc (size , sizeof (zval ));
92- array -> nNumUsed = 0 ;
93- array -> nNextIndex = 0 ;
9494 array -> nSize = size ;
95+ array -> nNextIndex = 0 ;
96+ // array->nNumUsed = 0;
9597}
9698/* }}} */
9799
@@ -108,15 +110,19 @@ PHP_METHOD(arraylist, __construct)
108110 Z_PARAM_OPTIONAL
109111 Z_PARAM_LONG (size )
110112 ZEND_PARSE_PARAMETERS_END ();
111-
113+
114+ if (intern -> array .nSize > 0 ) {
115+ /* called __construct() twice, bail out */
116+ return ;
117+ }
112118 arraylist_init (& intern -> array , size );
113119
114120}
115121/* }}} */
116122
117123static void arraylist_resize (arraylist * array ) /* {{{ */
118124{
119- if (array -> nNumUsed == array -> nSize )
125+ if (array -> nNextIndex == array -> nSize )
120126 {
121127 size_t i = 0 ;
122128 size_t oldSize = array -> nSize == 1 ? 2 : array -> nSize ;
@@ -136,22 +142,35 @@ static void arraylist_resize(arraylist *array) /* {{{ */
136142}
137143/* }}} */
138144
139- static void arraylist_add ( arraylist * array , zval * val ) /* {{{ */
145+ static inline void arraylist_object_write_dimension_helper ( arraylist_object * intern , zval * offset , zval * value ) /* {{{ */
140146{
141- if (array == NULL )
142- {
143- php_error_docref (NULL , E_NOTICE , "array cann't be empty." );
144- return ;
145- }
146- // arraylist_resize(array);
147- // php_printf("nNextIndex=%zu,nSize=%zu \n", array->nNextIndex, array->nSize);
148- // php_debug_zval_dump(&array->elements[array->nNextIndex], 1);
149- Z_TRY_ADDREF (array -> elements [array -> nNextIndex ]);
150- ZVAL_ZVAL (& array -> elements [array -> nNextIndex ], val , 1 , 1 );
151-
152- array -> nNextIndex ++ ;
153- array -> nNumUsed ++ ;
147+ zend_long index ;
148+
149+ if (!offset ) {
150+ php_error_docref (NULL , E_NOTICE , "Index invalid or out of range" );
151+ return ;
152+ }
153+
154+ if (Z_TYPE_P (offset ) != IS_LONG ) {
155+ convert_to_long (offset );
156+ index = Z_LVAL_P (offset );
157+ } else {
158+ index = Z_LVAL_P (offset );
159+ }
160+
161+ if (index < 0 || index >= intern -> array .nSize ) {
162+ php_error_docref (NULL , E_NOTICE , "Index invalid or out of range" );
163+ return ;
164+ } else {
165+ if (!Z_ISUNDEF (intern -> array .elements [index ])) {
166+ zval_ptr_dtor (& (intern -> array .elements [index ]));
167+ }
168+ ZVAL_DEREF (value );
169+ ZVAL_COPY (& intern -> array .elements [index ], value );
170+ Z_TRY_ADDREF_P (value );
171+ }
154172}
173+ /* }}} */
155174
156175
157176/* {{{ string arraylist::add( [ $val ] )
@@ -160,47 +179,72 @@ PHP_METHOD(arraylist, add)
160179{
161180 zval * object = getThis ();
162181 arraylist_object * intern ;
163- zval * val ;
182+ zval * val , offset ;
164183
165184 ZEND_PARSE_PARAMETERS_START (1 , 1 )
166185 Z_PARAM_ZVAL (val )
167186 ZEND_PARSE_PARAMETERS_END ();
168187
169-
170188 intern = Z_ARRAYLIST_P (object );
189+ if (intern -> array .nSize > 0 && intern -> array .nNextIndex < intern -> array .nSize ) {
190+ ZVAL_LONG (& offset , intern -> array .nNextIndex );
191+ arraylist_object_write_dimension_helper (intern , & offset , val );
192+ intern -> array .nNextIndex ++ ;
193+ // intern->array.nNumUsed++;
194+ RETURN_TRUE ;
195+ } else {
196+ RETURN_FALSE ;
197+ }
198+ }
171199
172- arraylist_add (& intern -> array , val );
173-
174- RETURN_TRUE ;
200+ static inline zval * arraylist_object_read_dimension_helper (arraylist_object * intern , zval * offset ) /* {{{ */
201+ {
202+ zend_long index ;
203+ if (!offset ) {
204+ php_error_docref (NULL , E_NOTICE , "Index invalid or out of range 0" );
205+ return NULL ;
206+ }
207+
208+ if (Z_TYPE_P (offset ) != IS_LONG ) {
209+ convert_to_long (offset );
210+ index = Z_LVAL_P (offset );
211+ } else {
212+ index = Z_LVAL_P (offset );
213+ }
214+
215+ if (index < 0 || index >= intern -> array .nSize ) {
216+ php_error_docref (NULL , E_NOTICE ,"Index invalid or out of range '%ld'" , index );
217+ return NULL ;
218+ } else if (Z_ISUNDEF (intern -> array .elements [index ])) {
219+ return NULL ;
220+ } else {
221+ return & intern -> array .elements [index ];
222+ }
175223}
224+ /* }}} */
225+
176226
177227/* {{{ zval arraylist::get(int $i)
178228 */
179229PHP_METHOD (arraylist , get )
180230{
181231 zval * object = getThis ();
182232 arraylist_object * intern ;
183- zend_long key ;
233+ zval * offset , * retval ;
184234
185235 ZEND_PARSE_PARAMETERS_START (1 , 1 )
186- Z_PARAM_LONG ( key )
236+ Z_PARAM_ZVAL ( offset )
187237 ZEND_PARSE_PARAMETERS_END ();
188238
189239 intern = Z_ARRAYLIST_P (object );
190-
191- if (key >= intern -> array .nSize )
192- {
193- php_error_docref (NULL , E_NOTICE , "Undefined offset:%ld" , key );
194- RETURN_NULL ();
195- }
196-
197- if (& intern -> array .elements [key ] != NULL )
198- {
199- Z_TRY_ADDREF (intern -> array .elements [key ]);
200- RETURN_ZVAL (& intern -> array .elements [key ], 1 , 0 );
201- } else {
202- RETURN_NULL ();
203- }
240+
241+ retval = arraylist_object_read_dimension_helper (intern , offset );
242+ if (retval != NULL ) {
243+ Z_TRY_ADDREF_P (retval );
244+ RETURN_ZVAL (retval , 0 , 0 );
245+ } else {
246+ RETURN_FALSE ;
247+ }
204248}
205249
206250
@@ -212,7 +256,7 @@ PHP_METHOD(arraylist, count)
212256 return ;
213257 }
214258 intern = Z_ARRAYLIST_P (object );
215- RETURN_LONG (intern -> array .nNumUsed );
259+ RETURN_LONG (intern -> array .nNextIndex );
216260}
217261
218262PHP_METHOD (arraylist , getSize )
@@ -222,7 +266,6 @@ PHP_METHOD(arraylist, getSize)
222266 if (zend_parse_parameters_none () == FAILURE ) {
223267 return ;
224268 }
225- intern = Z_ARRAYLIST_P (object );
226269 RETURN_LONG (intern -> array .nSize );
227270}
228271
@@ -237,10 +280,10 @@ PHP_METHOD(arraylist, toArray)
237280 }
238281
239282 intern = Z_ARRAYLIST_P (getThis ());
240- if (intern -> array .nNumUsed > 0 ) {
283+ if (intern -> array .nNextIndex > 0 ) {
241284 int i = 0 ;
242- array_init_size (return_value , intern -> array .nNumUsed );
243- for (; i < intern -> array .nNumUsed ; i ++ ) {
285+ array_init_size (return_value , intern -> array .nNextIndex );
286+ for (; i < intern -> array .nNextIndex ; i ++ ) {
244287 if (!Z_ISUNDEF (intern -> array .elements [i ])) {
245288 zend_hash_index_update (Z_ARRVAL_P (return_value ), i , & intern -> array .elements [i ]);
246289 Z_TRY_ADDREF (intern -> array .elements [i ]);
@@ -257,24 +300,22 @@ PHP_METHOD(arraylist, toArray)
257300
258301static void arraylist_destruct (arraylist_object * intern )/* {{{ */
259302{
260- // arraylist_object *intern = arraylist_from_obj(object);
261- arraylist * array = & intern -> array ;
262- if (array -> elements )
263- {
264- int i = 0 ;
265- for (; i < array -> nNumUsed ; i ++ )
266- {
267- if (& array -> elements [i ]) {
268- zval_ptr_dtor (& array -> elements [i ]);
269- }
303+
304+ zend_long i ;
305+ printf ("size=%zu\n" , intern -> array .nSize );
306+ if (intern -> array .nSize > 0 ) {
307+ for (i = 0 ; i < intern -> array .nSize ; i ++ ) {
308+ if (!Z_ISUNDEF (intern -> array .elements [i ])) {
309+ zval_ptr_dtor (& (intern -> array .elements [i ]));
310+ }
311+
270312 }
271- efree (array -> elements );
272- array -> elements = NULL ;
273- array -> nNumUsed = 0 ;
274- array -> nSize = 0 ;
275- array -> nNextIndex = 0 ;
276- }
277-
313+
314+ if (intern -> array .elements ) {
315+ efree (intern -> array .elements );
316+ intern -> array .elements = NULL ;
317+ }
318+ }
278319}
279320/* }}} */
280321
@@ -313,12 +354,56 @@ static const zend_function_entry arraylist_methods[] = {
313354static void arraylist_object_free_storage (zend_object * object )/* {{{ */
314355{
315356 arraylist_object * intern = arraylist_from_obj (object );
316- arraylist * array = & intern -> array ;
317357 arraylist_destruct (intern );
318358 zend_object_std_dtor (& intern -> std );
319359}
320360/* }}} */
321361
362+ static zend_object * arraylist_object_new_ex (zend_class_entry * class_type , zval * orig , int clone_orig ) /* {{{ */
363+ {
364+ arraylist_object * intern ;
365+ zend_class_entry * parent = class_type ;
366+ int inherited = 0 ;
367+
368+ intern = ecalloc (1 , sizeof (arraylist_object ) + zend_object_properties_size (parent ));
369+
370+ zend_object_std_init (& intern -> std , class_type );
371+ object_properties_init (& intern -> std , class_type );
372+
373+ intern -> current = 0 ;
374+ intern -> flags = 0 ;
375+
376+ if (orig && clone_orig ) {
377+ arraylist_object * other = Z_ARRAYLIST_P (orig );
378+ // intern->ce_get_iterator = other->ce_get_iterator;
379+ arraylist_init (& intern -> array , other -> array .nSize );
380+ // spl_fixedarray_copy(&intern->array, &other->array);
381+ }
382+
383+ while (parent ) {
384+ if (parent == array_list_ce ) {
385+ intern -> std .handlers = & handler_array_list ;
386+ // class_type->get_iterator = spl_fixedarray_get_iterator;
387+ break ;
388+ }
389+
390+ parent = parent -> parent ;
391+ inherited = 1 ;
392+ }
393+
394+ if (!parent ) { /* this must never happen */
395+ php_error_docref (NULL , E_COMPILE_ERROR , "Internal compiler error, Class is not child of ArrayList" );
396+ }
397+
398+ return & intern -> std ;
399+ }
400+ /* }}} */
401+
402+ static zend_object * arraylist_new (zend_class_entry * class_type ) /* {{{ */
403+ {
404+ return arraylist_object_new_ex (class_type , NULL , 0 );
405+ }
406+ /* }}} */
322407
323408/* {{{ PHP_MSHUTDOWN_FUNCTION
324409 */
@@ -377,13 +462,18 @@ PHP_MINIT_FUNCTION(arraylist) /* {{{ */ {
377462 );
378463 INIT_CLASS_ENTRY (ce , "ArrayList" , arraylist_methods ); //注册类及类方法
379464 array_list_ce = zend_register_internal_class (& ce );
380-
465+ array_list_ce -> create_object = arraylist_new ;
381466 memcpy (& handler_array_list , zend_get_std_object_handlers (), sizeof (zend_object_handlers ));
382467 handler_array_list .offset = XtOffsetOf (arraylist_object , std );
383468
469+ /* 通用对象功能 */
384470 handler_array_list .clone_obj = zend_objects_clone_obj ;
385471 handler_array_list .free_obj = arraylist_object_free_storage ;
386472 handler_array_list .dtor_obj = zend_objects_destroy_object ;
473+
474+
475+ /* 单个对象的功能 */
476+
387477 return SUCCESS ;
388478}
389479/* }}} */
0 commit comments