Skip to content

Commit 5b880ce

Browse files
author
wxxiong6
authored
Update arraylist.c
1 parent f8e27ac commit 5b880ce

File tree

1 file changed

+155
-65
lines changed

1 file changed

+155
-65
lines changed

arraylist.c

Lines changed: 155 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ typedef struct _arraylist { /* {{{ */
5252

5353
typedef 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)
7476
ZEND_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

117123
static 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
*/
179229
PHP_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

218262
PHP_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

258301
static 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[] = {
313354
static 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

Comments
 (0)