Skip to content

Commit 6b9ffaf

Browse files
committed
Simplify string management in RecursiveTreeIterator
Make use of zend_string rather than zval to clean up the implementation.
1 parent ac80aeb commit 6b9ffaf

File tree

1 file changed

+47
-69
lines changed

1 file changed

+47
-69
lines changed

ext/spl/spl_iterators.c

Lines changed: 47 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,7 @@ static zend_object *spl_RecursiveTreeIterator_new(zend_class_entry *class_type)
976976
}
977977
/* }}} */
978978

979-
static void spl_recursive_tree_iterator_get_prefix(spl_recursive_it_object *object, zval *return_value)
979+
static zend_string *spl_recursive_tree_iterator_get_prefix(spl_recursive_it_object *object)
980980
{
981981
smart_str str = {0};
982982
zval has_next;
@@ -1008,31 +1008,28 @@ static void spl_recursive_tree_iterator_get_prefix(spl_recursive_it_object *obje
10081008
smart_str_appendl(&str, ZSTR_VAL(object->prefix[5].s), ZSTR_LEN(object->prefix[5].s));
10091009
smart_str_0(&str);
10101010

1011-
RETURN_NEW_STR(str.s);
1011+
return str.s;
10121012
}
10131013

1014-
static void spl_recursive_tree_iterator_get_entry(spl_recursive_it_object *object, zval *return_value)
1014+
static zend_string *spl_recursive_tree_iterator_get_entry(spl_recursive_it_object *object)
10151015
{
1016-
zend_object_iterator *iterator = object->iterators[object->level].iterator;
1017-
zval *data;
1016+
zend_object_iterator *iterator = object->iterators[object->level].iterator;
1017+
zval *data = iterator->funcs->get_current_data(iterator);
1018+
if (!data) {
1019+
return NULL;
1020+
}
10181021

1019-
data = iterator->funcs->get_current_data(iterator);
1020-
if (data) {
1021-
ZVAL_DEREF(data);
1022+
ZVAL_DEREF(data);
1023+
if (Z_TYPE_P(data) == IS_ARRAY) {
10221024
/* TODO: Remove this special case? */
1023-
if (Z_TYPE_P(data) == IS_ARRAY) {
1024-
RETVAL_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED));
1025-
} else {
1026-
ZVAL_COPY(return_value, data);
1027-
convert_to_string(return_value);
1028-
}
1025+
return ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED);
10291026
}
1027+
return zval_get_string(data);
10301028
}
10311029

1032-
static void spl_recursive_tree_iterator_get_postfix(spl_recursive_it_object *object, zval *return_value)
1030+
static zend_string *spl_recursive_tree_iterator_get_postfix(spl_recursive_it_object *object)
10331031
{
1034-
RETVAL_STR(object->postfix[0].s);
1035-
Z_ADDREF_P(return_value);
1032+
return zend_string_copy(object->postfix[0].s);
10361033
}
10371034

10381035
/* {{{ RecursiveIteratorIterator to generate ASCII graphic trees for the entries in a RecursiveIterator */
@@ -1076,7 +1073,7 @@ PHP_METHOD(RecursiveTreeIterator, getPrefix)
10761073
RETURN_THROWS();
10771074
}
10781075

1079-
spl_recursive_tree_iterator_get_prefix(object, return_value);
1076+
RETURN_STR(spl_recursive_tree_iterator_get_prefix(object));
10801077
} /* }}} */
10811078

10821079
/* {{{ Sets postfix as used in getPostfix() */
@@ -1108,7 +1105,12 @@ PHP_METHOD(RecursiveTreeIterator, getEntry)
11081105
RETURN_THROWS();
11091106
}
11101107

1111-
spl_recursive_tree_iterator_get_entry(object, return_value);
1108+
zend_string *entry = spl_recursive_tree_iterator_get_entry(object);
1109+
if (!entry) {
1110+
// TODO: Can this happen? It's not in the stubs.
1111+
RETURN_NULL();
1112+
}
1113+
RETURN_STR(entry);
11121114
} /* }}} */
11131115

11141116
/* {{{ Returns the string to place after the current element */
@@ -1125,16 +1127,13 @@ PHP_METHOD(RecursiveTreeIterator, getPostfix)
11251127
RETURN_THROWS();
11261128
}
11271129

1128-
spl_recursive_tree_iterator_get_postfix(object, return_value);
1130+
RETURN_STR(spl_recursive_tree_iterator_get_postfix(object));
11291131
} /* }}} */
11301132

11311133
/* {{{ Returns the current element prefixed and postfixed */
11321134
PHP_METHOD(RecursiveTreeIterator, current)
11331135
{
1134-
spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(ZEND_THIS);
1135-
zval prefix, entry, postfix;
1136-
char *ptr;
1137-
zend_string *str;
1136+
spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(ZEND_THIS);
11381137

11391138
if (zend_parse_parameters_none() == FAILURE) {
11401139
RETURN_THROWS();
@@ -1159,43 +1158,32 @@ PHP_METHOD(RecursiveTreeIterator, current)
11591158
}
11601159
}
11611160

1162-
ZVAL_NULL(&prefix);
1163-
ZVAL_NULL(&entry);
1164-
spl_recursive_tree_iterator_get_prefix(object, &prefix);
1165-
spl_recursive_tree_iterator_get_entry(object, &entry);
1166-
if (Z_TYPE(entry) != IS_STRING) {
1167-
zval_ptr_dtor(&prefix);
1168-
zval_ptr_dtor(&entry);
1161+
zend_string *entry = spl_recursive_tree_iterator_get_entry(object);
1162+
if (!entry) {
11691163
RETURN_NULL();
11701164
}
1171-
spl_recursive_tree_iterator_get_postfix(object, &postfix);
11721165

1173-
str = zend_string_alloc(Z_STRLEN(prefix) + Z_STRLEN(entry) + Z_STRLEN(postfix), 0);
1174-
ptr = ZSTR_VAL(str);
1166+
zend_string *prefix = spl_recursive_tree_iterator_get_prefix(object);
1167+
zend_string *postfix = spl_recursive_tree_iterator_get_postfix(object);
11751168

1176-
memcpy(ptr, Z_STRVAL(prefix), Z_STRLEN(prefix));
1177-
ptr += Z_STRLEN(prefix);
1178-
memcpy(ptr, Z_STRVAL(entry), Z_STRLEN(entry));
1179-
ptr += Z_STRLEN(entry);
1180-
memcpy(ptr, Z_STRVAL(postfix), Z_STRLEN(postfix));
1181-
ptr += Z_STRLEN(postfix);
1182-
*ptr = 0;
1169+
zend_string *result = zend_string_concat3(
1170+
ZSTR_VAL(prefix), ZSTR_LEN(prefix),
1171+
ZSTR_VAL(entry), ZSTR_LEN(entry),
1172+
ZSTR_VAL(postfix), ZSTR_LEN(postfix));
11831173

1184-
zval_ptr_dtor(&prefix);
1185-
zval_ptr_dtor(&entry);
1186-
zval_ptr_dtor(&postfix);
1174+
zend_string_release(entry);
1175+
zend_string_release(prefix);
1176+
zend_string_release(postfix);
11871177

1188-
RETURN_NEW_STR(str);
1178+
RETURN_NEW_STR(result);
11891179
} /* }}} */
11901180

11911181
/* {{{ Returns the current key prefixed and postfixed */
11921182
PHP_METHOD(RecursiveTreeIterator, key)
11931183
{
11941184
spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(ZEND_THIS);
11951185
zend_object_iterator *iterator;
1196-
zval prefix, key, postfix, key_copy;
1197-
char *ptr;
1198-
zend_string *str;
1186+
zval key;
11991187

12001188
if (zend_parse_parameters_none() == FAILURE) {
12011189
RETURN_THROWS();
@@ -1213,31 +1201,21 @@ PHP_METHOD(RecursiveTreeIterator, key)
12131201
RETURN_COPY_VALUE(&key);
12141202
}
12151203

1216-
if (Z_TYPE(key) != IS_STRING) {
1217-
if (zend_make_printable_zval(&key, &key_copy)) {
1218-
key = key_copy;
1219-
}
1220-
}
1221-
1222-
spl_recursive_tree_iterator_get_prefix(object, &prefix);
1223-
spl_recursive_tree_iterator_get_postfix(object, &postfix);
1224-
1225-
str = zend_string_alloc(Z_STRLEN(prefix) + Z_STRLEN(key) + Z_STRLEN(postfix), 0);
1226-
ptr = ZSTR_VAL(str);
1204+
zend_string *key_str = zval_get_string(&key);
1205+
zend_string *prefix = spl_recursive_tree_iterator_get_prefix(object);
1206+
zend_string *postfix = spl_recursive_tree_iterator_get_postfix(object);
12271207

1228-
memcpy(ptr, Z_STRVAL(prefix), Z_STRLEN(prefix));
1229-
ptr += Z_STRLEN(prefix);
1230-
memcpy(ptr, Z_STRVAL(key), Z_STRLEN(key));
1231-
ptr += Z_STRLEN(key);
1232-
memcpy(ptr, Z_STRVAL(postfix), Z_STRLEN(postfix));
1233-
ptr += Z_STRLEN(postfix);
1234-
*ptr = 0;
1208+
zend_string *result = zend_string_concat3(
1209+
ZSTR_VAL(prefix), ZSTR_LEN(prefix),
1210+
ZSTR_VAL(key_str), ZSTR_LEN(key_str),
1211+
ZSTR_VAL(postfix), ZSTR_LEN(postfix));
12351212

1236-
zval_ptr_dtor(&prefix);
1213+
zend_string_release(key_str);
1214+
zend_string_release(prefix);
1215+
zend_string_release(postfix);
12371216
zval_ptr_dtor(&key);
1238-
zval_ptr_dtor(&postfix);
12391217

1240-
RETURN_NEW_STR(str);
1218+
RETURN_NEW_STR(result);
12411219
} /* }}} */
12421220

12431221
static zend_function *spl_dual_it_get_method(zend_object **object, zend_string *method, const zval *key)

0 commit comments

Comments
 (0)