2525#include "php.h"
2626#include "ext/standard/info.h"
2727#include "zend_exceptions.h"
28-
2928#include "php_arraylist.h"
3029
3130#ifndef ARRAY_LIST_SIZE
32- #define ARRAY_LIST_SIZE 16
31+ #define ARRAY_LIST_SIZE 8
3332#endif
3433
3534/* For compatibility with older PHP versions */
4039#endif
4140
4241zend_class_entry * array_list_ce ;
42+ zend_object_handlers handler_ArrayList ;
4343
4444typedef struct _arraylist { /* {{{ */
45- zend_long size ; //数组大小
46- zend_long key ; //数组当前使用key
47- zval * elements ; //数组元素
45+ size_t nSize ;
46+ size_t nNumUsed ;
47+ size_t nNextIndex ;
48+ zval * elements ;
4849} arraylist ;
4950/* }}} */
5051
@@ -65,67 +66,6 @@ static inline arraylist_object *arraylist_from_obj(zend_object *obj) /* {{{ */ {
6566#define Z_ARRAYLIST_P (zv ) arraylist_from_obj(Z_OBJ_P((zv)))
6667
6768
68-
69-
70-
71-
72- static void destruct (arraylist * array )/* {{{ */
73- {
74- if (array -> size > 0 )
75- {
76- efree (array -> elements );
77- array -> elements = NULL ;
78- array -> size = 0 ;
79- array -> key = 0 ;
80- }
81- }
82- /* }}} */
83-
84- static void arraylist_init (arraylist * array , zend_long size ) /* {{{ */
85- {
86-
87- array -> size = 0 ; /* reset size in case ecalloc() fails */
88- array -> key = 0 ;
89- array -> elements = NULL ;
90- array -> elements = (zval * )ecalloc (size , sizeof (zval ));
91- array -> size = size ;
92- }
93- /* }}} */
94-
95- static void resize (arraylist * array )
96- {
97- if (array -> key == array -> size )
98- {
99- zend_long oldSize = array -> size == 1 ? 2 : array -> size ;
100- zend_long newSize = oldSize + (oldSize >> 1 );
101- zval * elements ;
102- elements = (zval * )ecalloc (newSize , sizeof (zval ));
103- zend_long i = 0 ;
104- for (; i < array -> size ; i ++ )
105- {
106- elements [i ] = array -> elements [i ];
107- }
108- efree (array -> elements );
109- array -> elements = NULL ;
110- array -> elements = elements ;
111- array -> size = newSize ;
112-
113- }
114- }
115-
116- static void arraylist_add (arraylist * array , zval * val ) /* {{{ */
117- {
118- if (!array )
119- {
120- return ;
121- }
122- resize (array );
123- ZVAL_COPY (& array -> elements [array -> key ], val );
124- array -> key ++ ;
125- }
126- /* }}} */
127-
128-
12969/* {{{ arginfo
13070 */
13171ZEND_BEGIN_ARG_INFO_EX (arginfo_arraylist__construct , 0 , 0 , 1 )
@@ -144,13 +84,21 @@ ZEND_BEGIN_ARG_INFO(arginfo_arraylist_void, 0)
14484ZEND_END_ARG_INFO ()
14585/* }}} */
14686
87+ static void arraylist_init (arraylist * array , zend_long size ) /* {{{ */
88+ {
89+ array -> elements = NULL ;
90+ array -> elements = (zval * )ecalloc (size , sizeof (zval ));
91+ array -> nSize = size ;
92+ array -> nNumUsed = 0 ;
93+ array -> nNextIndex = 0 ;
94+ }
95+ /* }}} */
14796
14897/* {{{ void arraylist::__construct()
14998 */
15099PHP_METHOD (arraylist , __construct )
151100{
152101 zend_long size = ARRAY_LIST_SIZE ;
153-
154102 zval * object = getThis ();
155103 arraylist_object * intern ;
156104 intern = Z_ARRAYLIST_P (object );
@@ -160,28 +108,62 @@ PHP_METHOD(arraylist, __construct)
160108 Z_PARAM_LONG (size )
161109 ZEND_PARSE_PARAMETERS_END ();
162110
163-
164-
165111 arraylist_init (& intern -> array , size );
112+
113+ }
114+ /* }}} */
166115
116+ static void arraylist_resize (arraylist * array ) /* {{{ */
117+ {
118+ if (array -> nNumUsed == array -> nSize )
119+ {
120+ zend_long oldSize = array -> nSize == 1 ? 2 : array -> nSize ;
121+ zend_long newSize = oldSize + (oldSize >> 1 );
122+ zval * elements ;
123+ elements = (zval * )ecalloc (newSize , sizeof (zval ));
124+ zend_long i = 0 ;
125+ for (; i < array -> nSize ; i ++ )
126+ {
127+ elements [i ] = array -> elements [i ];
128+ }
129+ efree (array -> elements );
130+ array -> elements = NULL ;
131+ array -> elements = elements ;
132+ array -> nSize = newSize ;
133+ }
167134}
168135/* }}} */
169136
137+ static void arraylist_add (arraylist * array , zval * val ) /* {{{ */
138+ {
139+ if (!array )
140+ {
141+ return ;
142+ }
143+
144+ // if (&array->elements[array->nNextIndex] != NULL) {
145+ // printf("ptr = %p, size=%zu \n", intern, intern->array.nSize);
146+ php_debug_zval_dump (& array -> elements [array -> nNextIndex ], 1 );
147+ ZVAL_COPY (& array -> elements [array -> nNextIndex ], val );
148+ Z_TRY_ADDREF (array -> elements [array -> nNextIndex ]);
149+ array -> nNextIndex ++ ;
150+ array -> nNumUsed ++ ;
151+ // }
152+ }
153+
154+
170155/* {{{ string arraylist::add( [ $val ] )
171156 */
172157PHP_METHOD (arraylist , add )
173158{
174-
175159 zval * object = getThis ();
176160 arraylist_object * intern ;
177- size_t var_len ;
178161 zval * val ;
179162
180163 ZEND_PARSE_PARAMETERS_START (1 , 1 )
181164 Z_PARAM_ZVAL (val )
182165 ZEND_PARSE_PARAMETERS_END ();
183166
184-
185167 intern = Z_ARRAYLIST_P (object );
186168 arraylist_add (& intern -> array , val );
187169
@@ -200,12 +182,16 @@ PHP_METHOD(arraylist, get)
200182 Z_PARAM_LONG (key )
201183 ZEND_PARSE_PARAMETERS_END ();
202184
203-
204185 intern = Z_ARRAYLIST_P (object );
205186
206- if (key <= intern -> array .size )
187+ if (key <= intern -> array .nSize )
207188 {
208- RETURN_ZVAL (& intern -> array .elements [key ], 0 , 1 );
189+ if (& intern -> array .elements [key ] != NULL )
190+ {
191+ RETURN_ZVAL (& intern -> array .elements [key ], 1 , 1 );
192+ } else {
193+ RETURN_NULL ();
194+ }
209195 }
210196 else
211197 {
@@ -217,26 +203,22 @@ PHP_METHOD(arraylist, count)
217203{
218204 zval * object = getThis ();
219205 arraylist_object * intern ;
220-
221206 if (zend_parse_parameters_none () == FAILURE ) {
222207 return ;
223208 }
224-
225209 intern = Z_ARRAYLIST_P (object );
226- RETURN_LONG (intern -> array .key );
210+ RETURN_LONG (intern -> array .nNumUsed );
227211}
228212
229213PHP_METHOD (arraylist , getSize )
230214{
231215 zval * object = getThis ();
232216 arraylist_object * intern ;
233-
234217 if (zend_parse_parameters_none () == FAILURE ) {
235218 return ;
236219 }
237-
238220 intern = Z_ARRAYLIST_P (object );
239- RETURN_LONG (intern -> array .size );
221+ RETURN_LONG (intern -> array .nSize );
240222}
241223
242224/* {{{ proto object arraylist::toArray()
@@ -250,12 +232,10 @@ PHP_METHOD(arraylist, toArray)
250232 }
251233
252234 intern = Z_ARRAYLIST_P (getThis ());
253-
254- if (intern -> array .size > 0 ) {
235+ if (intern -> array .nNumUsed > 0 ) {
255236 int i = 0 ;
256-
257- array_init_size (return_value , intern -> array .size );
258- for (; i < intern -> array .size ; i ++ ) {
237+ array_init_size (return_value , intern -> array .nNumUsed );
238+ for (; i < intern -> array .nNumUsed ; i ++ ) {
259239 if (!Z_ISUNDEF (intern -> array .elements [i ])) {
260240 zend_hash_index_update (Z_ARRVAL_P (return_value ), i , & intern -> array .elements [i ]);
261241 Z_TRY_ADDREF (intern -> array .elements [i ]);
@@ -269,17 +249,56 @@ PHP_METHOD(arraylist, toArray)
269249}
270250/* }}} */
271251
252+ static void arraylist_object_free_storage (zend_object * object )/* {{{ */
253+ {
254+ arraylist_object * intern = arraylist_from_obj (object );
255+ arraylist * array = & intern -> array ;
256+ if (array -> nSize > 0 )
257+ {
258+ int i = 0 ;
259+ for (; i < array -> nSize ; i ++ )
260+ {
261+ zval_ptr_dtor (& array -> elements [i ]);
262+ }
263+ efree (array -> elements );
264+ array -> elements = NULL ;
265+ array -> nNumUsed = 0 ;
266+ array -> nNextIndex = 0 ;
267+ }
268+ zend_object_std_dtor (& intern -> std );
269+ }
270+ /* }}} */
271+
272+ static void arraylist_destruct (arraylist_object * intern )/* {{{ */
273+ {
274+ // arraylist_object *intern = arraylist_from_obj(object);
275+ arraylist * array = & intern -> array ;
276+ if (array -> nSize > 0 )
277+ {
278+ int i = 0 ;
279+ for (; i < array -> nSize ; i ++ )
280+ {
281+ zval_ptr_dtor (& array -> elements [i ]);
282+ }
283+ efree (array -> elements );
284+ array -> elements = NULL ;
285+ array -> nNumUsed = 0 ;
286+ array -> nNextIndex = 0 ;
287+ }
288+ zend_object_std_dtor (& intern -> std );
289+ }
290+ /* }}} */
291+
272292PHP_METHOD (arraylist , __destruct )
273293{
274294 zval * object = getThis ();
275295 arraylist_object * intern ;
276-
277296 if (zend_parse_parameters_none () == FAILURE ) {
278297 return ;
279298 }
280-
281299 intern = Z_ARRAYLIST_P (object );
282- destruct (& intern -> array );
300+
301+ arraylist_destruct (intern );
283302}
284303
285304/* {{{ arraylist_functions[] 扩展函数
@@ -292,13 +311,13 @@ static const zend_function_entry arraylist_functions[] = {
292311/* {{{ arraylist__methods[] 扩展类方法
293312 */
294313static const zend_function_entry arraylist_methods [] = {
295- PHP_ME (arraylist , __construct , arginfo_arraylist__construct , ZEND_ACC_PUBLIC | ZEND_ACC_CTOR )
296- PHP_ME (arraylist , add , arginfo_arraylist_add , ZEND_ACC_PUBLIC )
297- PHP_ME (arraylist , get , arginfo_arraylist_get , ZEND_ACC_PUBLIC )
298- PHP_ME (arraylist , count , arginfo_arraylist_void , ZEND_ACC_PUBLIC )
299- PHP_ME (arraylist , toArray , arginfo_arraylist_void , ZEND_ACC_PUBLIC )
300- PHP_ME (arraylist , getSize , arginfo_arraylist_void , ZEND_ACC_PUBLIC )
301- PHP_ME (arraylist , __destruct , arginfo_arraylist_void , ZEND_ACC_PUBLIC )
314+ PHP_ME (arraylist , __construct , arginfo_arraylist__construct , ZEND_ACC_PUBLIC )
315+ PHP_ME (arraylist , add , arginfo_arraylist_add , ZEND_ACC_PUBLIC )
316+ PHP_ME (arraylist , get , arginfo_arraylist_get , ZEND_ACC_PUBLIC )
317+ PHP_ME (arraylist , count , arginfo_arraylist_void , ZEND_ACC_PUBLIC )
318+ PHP_ME (arraylist , toArray , arginfo_arraylist_void , ZEND_ACC_PUBLIC )
319+ PHP_ME (arraylist , getSize , arginfo_arraylist_void , ZEND_ACC_PUBLIC )
320+ PHP_ME (arraylist , __destruct , arginfo_arraylist_void , ZEND_ACC_PUBLIC )
302321 PHP_FE_END
303322};
304323/* }}} */
@@ -358,10 +377,15 @@ PHP_MINIT_FUNCTION(arraylist) /* {{{ */ {
358377 sizeof (PHP_ARRAYLIST_VERSION )- 1 ,
359378 CONST_CS |CONST_PERSISTENT
360379 );
361-
362380 INIT_CLASS_ENTRY (ce , "ArrayList" , arraylist_methods ); //注册类及类方法
363381 array_list_ce = zend_register_internal_class (& ce );
364382
383+ memcpy (& handler_ArrayList , zend_get_std_object_handlers (), sizeof (zend_object_handlers ));
384+ handler_ArrayList .offset = XtOffsetOf (arraylist_object , std );
385+ handler_ArrayList .free_obj = arraylist_object_free_storage ;
386+
387+
388+
365389 return SUCCESS ;
366390}
367391/* }}} */
0 commit comments