summaryrefslogtreecommitdiff
path: root/ext/standard/string.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/standard/string.c')
-rw-r--r--ext/standard/string.c1716
1 files changed, 742 insertions, 974 deletions
diff --git a/ext/standard/string.c b/ext/standard/string.c
index 9139906653..ebd667956a 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -127,23 +127,20 @@ static MUTEX_T locale_mutex = NULL;
/* {{{ php_bin2hex
*/
-static char *php_bin2hex(const unsigned char *old, const size_t oldlen, size_t *newlen)
+static zend_string *php_bin2hex(const unsigned char *old, const size_t oldlen)
{
- register unsigned char *result = NULL;
+ zend_string *result;
size_t i, j;
- result = (unsigned char *) safe_emalloc(oldlen, 2 * sizeof(char), 1);
+ result = STR_SAFE_ALLOC(oldlen, 2 * sizeof(char), 0, 0);
for (i = j = 0; i < oldlen; i++) {
- result[j++] = hexconvtab[old[i] >> 4];
- result[j++] = hexconvtab[old[i] & 15];
+ result->val[j++] = hexconvtab[old[i] >> 4];
+ result->val[j++] = hexconvtab[old[i] & 15];
}
- result[j] = '\0';
+ result->val[j] = '\0';
- if (newlen)
- *newlen = oldlen * 2 * sizeof(char);
-
- return (char *)result;
+ return result;
}
/* }}} */
@@ -237,21 +234,21 @@ PHP_MSHUTDOWN_FUNCTION(localeconv)
Converts the binary representation of data to hex */
PHP_FUNCTION(bin2hex)
{
- char *result, *data;
- size_t newlen;
+ zend_string *result;
+ char *data;
int datalen;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &datalen) == FAILURE) {
return;
}
- result = php_bin2hex((unsigned char *)data, datalen, &newlen);
+ result = php_bin2hex((unsigned char *)data, datalen);
if (!result) {
RETURN_FALSE;
}
- RETURN_STRINGL(result, newlen, 0);
+ RETURN_STR(result);
}
/* }}} */
@@ -279,7 +276,9 @@ PHP_FUNCTION(hex2bin)
RETURN_FALSE;
}
- RETURN_STRINGL(result, newlen, 0);
+ // TODO: avoid reallocation ???
+ RETVAL_STRINGL(result, newlen);
+ efree(result);
}
/* }}} */
@@ -706,7 +705,7 @@ PHP_FUNCTION(nl_langinfo)
if (value == NULL) {
RETURN_FALSE;
} else {
- RETURN_STRING(value, 1);
+ RETURN_STRING(value);
}
}
#endif
@@ -818,7 +817,7 @@ PHPAPI char *php_trim(char *c, int len, char *what, int what_len, zval *return_v
}
if (return_value) {
- RETVAL_STRINGL(c, len, 1);
+ RETVAL_STRINGL(c, len);
} else {
return estrndup(c, len);
}
@@ -872,12 +871,12 @@ PHP_FUNCTION(ltrim)
PHP_FUNCTION(wordwrap)
{
const char *text, *breakchar = "\n";
- char *newtext;
int textlen, breakcharlen = 1, newtextlen, chk;
size_t alloced;
long current = 0, laststart = 0, lastspace = 0;
long linelength = 75;
zend_bool docut = 0;
+ zend_string *newtext;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lsb", &text, &textlen, &linelength, &breakchar, &breakcharlen, &docut) == FAILURE) {
return;
@@ -900,7 +899,7 @@ PHP_FUNCTION(wordwrap)
/* Special case for a single-character break as it needs no
additional storage space */
if (breakcharlen == 1 && !docut) {
- newtext = estrndup(text, textlen);
+ newtext = STR_INIT(text, textlen, 0);
laststart = lastspace = 0;
for (current = 0; current < textlen; current++) {
@@ -908,27 +907,27 @@ PHP_FUNCTION(wordwrap)
laststart = lastspace = current + 1;
} else if (text[current] == ' ') {
if (current - laststart >= linelength) {
- newtext[current] = breakchar[0];
+ newtext->val[current] = breakchar[0];
laststart = current + 1;
}
lastspace = current;
} else if (current - laststart >= linelength && laststart != lastspace) {
- newtext[lastspace] = breakchar[0];
+ newtext->val[lastspace] = breakchar[0];
laststart = lastspace + 1;
}
}
- RETURN_STRINGL(newtext, textlen, 0);
+ RETURN_NEW_STR(newtext);
} else {
/* Multiple character line break or forced cut */
if (linelength > 0) {
chk = (int)(textlen/linelength + 1);
- newtext = safe_emalloc(chk, breakcharlen, textlen + 1);
+ newtext = STR_ALLOC(chk * breakcharlen + textlen, 0);
alloced = textlen + chk * breakcharlen + 1;
} else {
chk = textlen;
alloced = textlen * (breakcharlen + 1) + 1;
- newtext = safe_emalloc(textlen, (breakcharlen + 1), 1);
+ newtext = STR_ALLOC(textlen * (breakcharlen + 1), 0);
}
/* now keep track of the actual new text length */
@@ -938,7 +937,7 @@ PHP_FUNCTION(wordwrap)
for (current = 0; current < textlen; current++) {
if (chk <= 0) {
alloced += (int) (((textlen - current + 1)/linelength + 1) * breakcharlen) + 1;
- newtext = erealloc(newtext, alloced);
+ newtext = STR_REALLOC(newtext, alloced, 0);
chk = (int) ((textlen - current)/linelength) + 1;
}
/* when we hit an existing break, copy to new buffer, and
@@ -946,8 +945,8 @@ PHP_FUNCTION(wordwrap)
if (text[current] == breakchar[0]
&& current + breakcharlen < textlen
&& !strncmp(text+current, breakchar, breakcharlen)) {
- memcpy(newtext+newtextlen, text+laststart, current-laststart+breakcharlen);
- newtextlen += current-laststart+breakcharlen;
+ memcpy(newtext->val + newtextlen, text + laststart, current - laststart + breakcharlen);
+ newtextlen += current - laststart + breakcharlen;
current += breakcharlen - 1;
laststart = lastspace = current + 1;
chk--;
@@ -956,9 +955,9 @@ PHP_FUNCTION(wordwrap)
* copy and insert a break, or just keep track of it */
else if (text[current] == ' ') {
if (current - laststart >= linelength) {
- memcpy(newtext+newtextlen, text+laststart, current-laststart);
+ memcpy(newtext->val + newtextlen, text + laststart, current - laststart);
newtextlen += current - laststart;
- memcpy(newtext+newtextlen, breakchar, breakcharlen);
+ memcpy(newtext->val + newtextlen, breakchar, breakcharlen);
newtextlen += breakcharlen;
laststart = current + 1;
chk--;
@@ -970,9 +969,9 @@ PHP_FUNCTION(wordwrap)
* copy and insert a break. */
else if (current - laststart >= linelength
&& docut && laststart >= lastspace) {
- memcpy(newtext+newtextlen, text+laststart, current-laststart);
+ memcpy(newtext->val + newtextlen, text + laststart, current - laststart);
newtextlen += current - laststart;
- memcpy(newtext+newtextlen, breakchar, breakcharlen);
+ memcpy(newtext->val + newtextlen, breakchar, breakcharlen);
newtextlen += breakcharlen;
laststart = lastspace = current;
chk--;
@@ -982,9 +981,9 @@ PHP_FUNCTION(wordwrap)
* up the laststart */
else if (current - laststart >= linelength
&& laststart < lastspace) {
- memcpy(newtext+newtextlen, text+laststart, lastspace-laststart);
+ memcpy(newtext->val + newtextlen, text + laststart, lastspace - laststart);
newtextlen += lastspace - laststart;
- memcpy(newtext+newtextlen, breakchar, breakcharlen);
+ memcpy(newtext->val + newtextlen, breakchar, breakcharlen);
newtextlen += breakcharlen;
laststart = lastspace = lastspace + 1;
chk--;
@@ -993,15 +992,15 @@ PHP_FUNCTION(wordwrap)
/* copy over any stragglers */
if (laststart != current) {
- memcpy(newtext+newtextlen, text+laststart, current-laststart);
+ memcpy(newtext->val + newtextlen, text + laststart, current - laststart);
newtextlen += current - laststart;
}
- newtext[newtextlen] = '\0';
+ newtext->val[newtextlen] = '\0';
/* free unused memory */
- newtext = erealloc(newtext, newtextlen+1);
+ newtext = STR_REALLOC(newtext, newtextlen, 0);
- RETURN_STRINGL(newtext, newtextlen, 0);
+ RETURN_NEW_STR(newtext);
}
}
/* }}} */
@@ -1015,19 +1014,19 @@ PHPAPI void php_explode(zval *delim, zval *str, zval *return_value, long limit)
endp = Z_STRVAL_P(str) + Z_STRLEN_P(str);
p1 = Z_STRVAL_P(str);
- p2 = php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp);
+ p2 = (char*)php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp);
if (p2 == NULL) {
- add_next_index_stringl(return_value, p1, Z_STRLEN_P(str), 1);
+ add_next_index_stringl(return_value, p1, Z_STRLEN_P(str));
} else {
do {
- add_next_index_stringl(return_value, p1, p2 - p1, 1);
+ add_next_index_stringl(return_value, p1, p2 - p1);
p1 = p2 + Z_STRLEN_P(delim);
- } while ((p2 = php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL &&
+ } while ((p2 = (char*)php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL &&
--limit > 1);
if (p1 <= endp)
- add_next_index_stringl(return_value, p1, endp-p1, 1);
+ add_next_index_stringl(return_value, p1, endp-p1);
}
}
/* }}} */
@@ -1042,7 +1041,7 @@ PHPAPI void php_explode_negative_limit(zval *delim, zval *str, zval *return_valu
endp = Z_STRVAL_P(str) + Z_STRLEN_P(str);
p1 = Z_STRVAL_P(str);
- p2 = php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp);
+ p2 = (char*)php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp);
if (p2 == NULL) {
/*
@@ -1061,15 +1060,13 @@ PHPAPI void php_explode_negative_limit(zval *delim, zval *str, zval *return_valu
positions = erealloc(positions, allocated*sizeof(char *));
}
positions[found++] = p1 = p2 + Z_STRLEN_P(delim);
- } while ((p2 = php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL);
+ } while ((p2 = (char*)php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL);
to_return = limit + found;
/* limit is at least -1 therefore no need of bounds checking : i will be always less than found */
for (i = 0;i < to_return;i++) { /* this checks also for to_return > 0 */
add_next_index_stringl(return_value, positions[i],
- (positions[i+1] - Z_STRLEN_P(delim)) - positions[i],
- 1
- );
+ (positions[i+1] - Z_STRLEN_P(delim)) - positions[i]);
}
efree(positions);
}
@@ -1081,37 +1078,36 @@ PHPAPI void php_explode_negative_limit(zval *delim, zval *str, zval *return_valu
Splits a string on string separator and return array of components. If limit is positive only limit number of components is returned. If limit is negative all components except the last abs(limit) are returned. */
PHP_FUNCTION(explode)
{
- char *str, *delim;
- int str_len = 0, delim_len = 0;
+ zend_string *str, *delim;
long limit = LONG_MAX; /* No limit */
zval zdelim, zstr;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &delim, &delim_len, &str, &str_len, &limit) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "SS|l", &delim, &str, &limit) == FAILURE) {
return;
}
- if (delim_len == 0) {
+ if (delim->len == 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
RETURN_FALSE;
}
array_init(return_value);
- if (str_len == 0) {
+ if (str->len == 0) {
if (limit >= 0) {
- add_next_index_stringl(return_value, "", sizeof("") - 1, 1);
+ add_next_index_stringl(return_value, "", sizeof("") - 1);
}
return;
}
- ZVAL_STRINGL(&zstr, str, str_len, 0);
- ZVAL_STRINGL(&zdelim, delim, delim_len, 0);
+ ZVAL_STR(&zstr, str);
+ ZVAL_STR(&zdelim, delim);
if (limit > 1) {
php_explode(&zdelim, &zstr, return_value, limit);
} else if (limit < 0) {
php_explode_negative_limit(&zdelim, &zstr, return_value, limit);
} else {
- add_index_stringl(return_value, 0, str, str_len, 1);
+ add_index_stringl(return_value, 0, str->val, str->len);
}
}
/* }}} */
@@ -1124,8 +1120,7 @@ PHP_FUNCTION(explode)
*/
PHPAPI void php_implode(zval *delim, zval *arr, zval *return_value TSRMLS_DC)
{
- zval **tmp;
- HashPosition pos;
+ zval *tmp;
smart_str implstr = {0};
int numelems, i = 0;
zval tmp_val;
@@ -1137,33 +1132,31 @@ PHPAPI void php_implode(zval *delim, zval *arr, zval *return_value TSRMLS_DC)
RETURN_EMPTY_STRING();
}
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
-
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **) &tmp, &pos) == SUCCESS) {
- switch ((*tmp)->type) {
+ ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), tmp) {
+again:
+ switch (Z_TYPE_P(tmp)) {
case IS_STRING:
- smart_str_appendl(&implstr, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+ smart_str_appendl(&implstr, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
break;
case IS_LONG: {
char stmp[MAX_LENGTH_OF_LONG + 1];
- str_len = slprintf(stmp, sizeof(stmp), "%ld", Z_LVAL_PP(tmp));
+ str_len = slprintf(stmp, sizeof(stmp), "%ld", Z_LVAL_P(tmp));
smart_str_appendl(&implstr, stmp, str_len);
}
break;
- case IS_BOOL:
- if (Z_LVAL_PP(tmp) == 1) {
- smart_str_appendl(&implstr, "1", sizeof("1")-1);
- }
+ case IS_TRUE:
+ smart_str_appendl(&implstr, "1", sizeof("1")-1);
break;
case IS_NULL:
+ case IS_FALSE:
break;
case IS_DOUBLE: {
char *stmp;
- str_len = spprintf(&stmp, 0, "%.*G", (int) EG(precision), Z_DVAL_PP(tmp));
+ str_len = spprintf(&stmp, 0, "%.*G", (int) EG(precision), Z_DVAL_P(tmp));
smart_str_appendl(&implstr, stmp, str_len);
efree(stmp);
}
@@ -1172,17 +1165,18 @@ PHPAPI void php_implode(zval *delim, zval *arr, zval *return_value TSRMLS_DC)
case IS_OBJECT: {
int copy;
zval expr;
- zend_make_printable_zval(*tmp, &expr, &copy);
+ zend_make_printable_zval(tmp, &expr, &copy);
smart_str_appendl(&implstr, Z_STRVAL(expr), Z_STRLEN(expr));
if (copy) {
zval_dtor(&expr);
}
}
break;
-
+ case IS_REFERENCE:
+ tmp = Z_REFVAL_P(tmp);
+ goto again;
default:
- tmp_val = **tmp;
- zval_copy_ctor(&tmp_val);
+ ZVAL_DUP(&tmp_val, tmp);
convert_to_string(&tmp_val);
smart_str_appendl(&implstr, Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
zval_dtor(&tmp_val);
@@ -1193,12 +1187,12 @@ PHPAPI void php_implode(zval *delim, zval *arr, zval *return_value TSRMLS_DC)
if (++i != numelems) {
smart_str_appendl(&implstr, Z_STRVAL_P(delim), Z_STRLEN_P(delim));
}
- zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
- }
+ } ZEND_HASH_FOREACH_END();
+
smart_str_0(&implstr);
- if (implstr.len) {
- RETURN_STRINGL(implstr.c, implstr.len, 0);
+ if (implstr.s) {
+ RETURN_STR(implstr.s);
} else {
smart_str_free(&implstr);
RETURN_EMPTY_STRING();
@@ -1210,33 +1204,32 @@ PHPAPI void php_implode(zval *delim, zval *arr, zval *return_value TSRMLS_DC)
Joins array elements placing glue string between items and return one string */
PHP_FUNCTION(implode)
{
- zval **arg1 = NULL, **arg2 = NULL, *delim, *arr;
+ zval *arg1 = NULL, *arg2 = NULL, *delim, *arr, tmp;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|Z", &arg1, &arg2) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &arg1, &arg2) == FAILURE) {
return;
}
if (arg2 == NULL) {
- if (Z_TYPE_PP(arg1) != IS_ARRAY) {
+ if (Z_TYPE_P(arg1) != IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument must be an array");
return;
}
- MAKE_STD_ZVAL(delim);
-#define _IMPL_EMPTY ""
- ZVAL_STRINGL(delim, _IMPL_EMPTY, sizeof(_IMPL_EMPTY) - 1, 0);
+ ZVAL_EMPTY_STRING(&tmp);
+ delim = &tmp;
SEPARATE_ZVAL(arg1);
- arr = *arg1;
+ arr = arg1;
} else {
- if (Z_TYPE_PP(arg1) == IS_ARRAY) {
- arr = *arg1;
+ if (Z_TYPE_P(arg1) == IS_ARRAY) {
+ arr = arg1;
convert_to_string_ex(arg2);
- delim = *arg2;
- } else if (Z_TYPE_PP(arg2) == IS_ARRAY) {
- arr = *arg2;
+ delim = arg2;
+ } else if (Z_TYPE_P(arg2) == IS_ARRAY) {
+ arr = arg2;
convert_to_string_ex(arg1);
- delim = *arg1;
+ delim = arg1;
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid arguments passed");
return;
@@ -1244,10 +1237,6 @@ PHP_FUNCTION(implode)
}
php_implode(delim, arr, return_value TSRMLS_CC);
-
- if (arg2 == NULL) {
- FREE_ZVAL(delim);
- }
}
/* }}} */
@@ -1259,8 +1248,6 @@ PHP_FUNCTION(strtok)
{
char *str, *tok = NULL;
int str_len, tok_len = 0;
- zval *zv;
-
char *token;
char *token_end;
char *p;
@@ -1275,14 +1262,9 @@ PHP_FUNCTION(strtok)
tok = str;
tok_len = str_len;
} else {
- if (BG(strtok_zval)) {
- zval_ptr_dtor(&BG(strtok_zval));
- }
- MAKE_STD_ZVAL(zv);
- ZVAL_STRINGL(zv, str, str_len, 1);
-
- BG(strtok_zval) = zv;
- BG(strtok_last) = BG(strtok_string) = Z_STRVAL_P(zv);
+ zval_ptr_dtor(&BG(strtok_zval));
+ ZVAL_STRINGL(&BG(strtok_zval), str, str_len);
+ BG(strtok_last) = BG(strtok_string) = Z_STRVAL(BG(strtok_zval));
BG(strtok_len) = str_len;
}
@@ -1320,7 +1302,7 @@ PHP_FUNCTION(strtok)
if (p - BG(strtok_last)) {
return_token:
- RETVAL_STRINGL(BG(strtok_last) + skipped, (p - BG(strtok_last)) - skipped, 1);
+ RETVAL_STRINGL(BG(strtok_last) + skipped, (p - BG(strtok_last)) - skipped);
BG(strtok_last) = p + 1;
} else {
RETVAL_FALSE;
@@ -1360,14 +1342,15 @@ PHP_FUNCTION(strtoupper)
{
char *arg;
int arglen;
+ zend_string *result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arglen) == FAILURE) {
return;
}
- arg = estrndup(arg, arglen);
- php_strtoupper(arg, arglen);
- RETURN_STRINGL(arg, arglen, 0);
+ result = STR_INIT(arg, arglen, 0);
+ php_strtoupper(result->val, result->len);
+ RETURN_NEW_STR(result);
}
/* }}} */
@@ -1394,24 +1377,26 @@ PHP_FUNCTION(strtolower)
{
char *str;
int arglen;
+ zend_string *result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &arglen) == FAILURE) {
return;
}
- str = estrndup(str, arglen);
- php_strtolower(str, arglen);
- RETURN_STRINGL(str, arglen, 0);
+ result = STR_INIT(str, arglen, 0);
+ php_strtolower(result->val, result->len);
+ RETURN_NEW_STR(result);
}
/* }}} */
/* {{{ php_basename
*/
-PHPAPI void php_basename(const char *s, size_t len, char *suffix, size_t sufflen, char **p_ret, size_t *p_len TSRMLS_DC)
+PHPAPI zend_string *php_basename(const char *s, size_t len, char *suffix, size_t sufflen TSRMLS_DC)
{
- char *ret = NULL, *c, *comp, *cend;
+ char *c, *comp, *cend;
size_t inc_len, cnt;
int state;
+ zend_string *ret;
c = comp = cend = (char*)s;
cnt = len;
@@ -1479,15 +1464,8 @@ quit_loop:
len = cend - comp;
- if (p_ret) {
- ret = emalloc(len + 1);
- memcpy(ret, comp, len);
- ret[len] = '\0';
- *p_ret = ret;
- }
- if (p_len) {
- *p_len = len;
- }
+ ret = STR_INIT(comp, len, 0);
+ return ret;
}
/* }}} */
@@ -1495,16 +1473,14 @@ quit_loop:
Returns the filename component of the path */
PHP_FUNCTION(basename)
{
- char *string, *suffix = NULL, *ret;
+ char *string, *suffix = NULL;
int string_len, suffix_len = 0;
- size_t ret_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &string, &string_len, &suffix, &suffix_len) == FAILURE) {
return;
}
- php_basename(string, string_len, suffix, suffix_len, &ret, &ret_len TSRMLS_CC);
- RETURN_STRINGL(ret, (int)ret_len, 0);
+ RETURN_STR(php_basename(string, string_len, suffix, suffix_len TSRMLS_CC));
}
/* }}} */
@@ -1521,18 +1497,17 @@ PHPAPI size_t php_dirname(char *path, size_t len)
PHP_FUNCTION(dirname)
{
char *str;
- char *ret;
+ zend_string *ret;
int str_len;
- size_t ret_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
return;
}
- ret = estrndup(str, str_len);
- ret_len = php_dirname(ret, str_len);
+ ret = STR_INIT(str, str_len, 0);
+ ret->len = zend_dirname(ret->val, str_len);
- RETURN_STRINGL(ret, ret_len, 0);
+ RETURN_NEW_STR(ret);
}
/* }}} */
@@ -1540,11 +1515,11 @@ PHP_FUNCTION(dirname)
Returns information about a certain string */
PHP_FUNCTION(pathinfo)
{
- zval *tmp;
- char *path, *ret = NULL;
+ zval tmp;
+ char *path, *dirname;
int path_len, have_basename;
- size_t ret_len;
long opt = PHP_PATHINFO_ALL;
+ zend_string *ret = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &path, &path_len, &opt) == FAILURE) {
return;
@@ -1552,22 +1527,20 @@ PHP_FUNCTION(pathinfo)
have_basename = ((opt & PHP_PATHINFO_BASENAME) == PHP_PATHINFO_BASENAME);
- MAKE_STD_ZVAL(tmp);
- array_init(tmp);
+ array_init(&tmp);
if ((opt & PHP_PATHINFO_DIRNAME) == PHP_PATHINFO_DIRNAME) {
- ret = estrndup(path, path_len);
- php_dirname(ret, path_len);
- if (*ret) {
- add_assoc_string(tmp, "dirname", ret, 1);
+ dirname = estrndup(path, path_len);
+ php_dirname(dirname, path_len);
+ if (*dirname) {
+ add_assoc_string(&tmp, "dirname", dirname);
}
- efree(ret);
- ret = NULL;
+ efree(dirname);
}
if (have_basename) {
- php_basename(path, path_len, NULL, 0, &ret, &ret_len TSRMLS_CC);
- add_assoc_stringl(tmp, "basename", ret, ret_len, 0);
+ ret = php_basename(path, path_len, NULL, 0 TSRMLS_CC);
+ add_assoc_str(&tmp, "basename", STR_COPY(ret));
}
if ((opt & PHP_PATHINFO_EXTENSION) == PHP_PATHINFO_EXTENSION) {
@@ -1575,14 +1548,14 @@ PHP_FUNCTION(pathinfo)
int idx;
if (!have_basename) {
- php_basename(path, path_len, NULL, 0, &ret, &ret_len TSRMLS_CC);
+ ret = php_basename(path, path_len, NULL, 0 TSRMLS_CC);
}
- p = zend_memrchr(ret, '.', ret_len);
+ p = zend_memrchr(ret->val, '.', ret->len);
if (p) {
- idx = p - ret;
- add_assoc_stringl(tmp, "extension", ret + idx + 1, ret_len - idx - 1, 1);
+ idx = p - ret->val;
+ add_assoc_stringl(&tmp, "extension", ret->val + idx + 1, ret->len - idx - 1);
}
}
@@ -1592,25 +1565,25 @@ PHP_FUNCTION(pathinfo)
/* Have we already looked up the basename? */
if (!have_basename && !ret) {
- php_basename(path, path_len, NULL, 0, &ret, &ret_len TSRMLS_CC);
+ ret = php_basename(path, path_len, NULL, 0 TSRMLS_CC);
}
- p = zend_memrchr(ret, '.', ret_len);
+ p = zend_memrchr(ret->val, '.', ret->len);
- idx = p ? (p - ret) : ret_len;
- add_assoc_stringl(tmp, "filename", ret, idx, 1);
+ idx = p ? (p - ret->val) : ret->len;
+ add_assoc_stringl(&tmp, "filename", ret->val, idx);
}
- if (!have_basename && ret) {
- efree(ret);
+ if (ret) {
+ STR_RELEASE(ret);
}
if (opt == PHP_PATHINFO_ALL) {
- RETURN_ZVAL(tmp, 0, 1);
+ RETURN_ZVAL(&tmp, 0, 1);
} else {
- zval **element;
- if (zend_hash_get_current_data(Z_ARRVAL_P(tmp), (void **) &element) == SUCCESS) {
- RETVAL_ZVAL(*element, 1, 0);
+ zval *element;
+ if ((element = zend_hash_get_current_data(Z_ARRVAL(tmp))) != NULL) {
+ RETVAL_ZVAL(element, 1, 0);
} else {
ZVAL_EMPTY_STRING(return_value);
}
@@ -1626,7 +1599,7 @@ PHPAPI char *php_stristr(char *s, char *t, size_t s_len, size_t t_len)
{
php_strtolower(s, s_len);
php_strtolower(t, t_len);
- return php_memnstr(s, t, t_len, s + s_len);
+ return (char*)php_memnstr(s, t, t_len, s + s_len);
}
/* }}} */
@@ -1674,12 +1647,15 @@ static int php_needle_char(zval *needle, char *target TSRMLS_DC)
{
switch (Z_TYPE_P(needle)) {
case IS_LONG:
- case IS_BOOL:
*target = (char)Z_LVAL_P(needle);
return SUCCESS;
case IS_NULL:
+ case IS_FALSE:
*target = '\0';
return SUCCESS;
+ case IS_TRUE:
+ *target = '\1';
+ return SUCCESS;
case IS_DOUBLE:
*target = (char)(int)Z_DVAL_P(needle);
return SUCCESS;
@@ -1744,9 +1720,9 @@ PHP_FUNCTION(stristr)
if (found) {
found_offset = found - haystack_dup;
if (part) {
- RETVAL_STRINGL(haystack, found_offset, 1);
+ RETVAL_STRINGL(haystack, found_offset);
} else {
- RETVAL_STRINGL(haystack + found_offset, haystack_len - found_offset, 1);
+ RETVAL_STRINGL(haystack + found_offset, haystack_len - found_offset);
}
} else {
RETVAL_FALSE;
@@ -1778,22 +1754,22 @@ PHP_FUNCTION(strstr)
RETURN_FALSE;
}
- found = php_memnstr(haystack, Z_STRVAL_P(needle), Z_STRLEN_P(needle), haystack + haystack_len);
+ found = (char*)php_memnstr(haystack, Z_STRVAL_P(needle), Z_STRLEN_P(needle), haystack + haystack_len);
} else {
if (php_needle_char(needle, needle_char TSRMLS_CC) != SUCCESS) {
RETURN_FALSE;
}
needle_char[1] = 0;
- found = php_memnstr(haystack, needle_char, 1, haystack + haystack_len);
+ found = (char*)php_memnstr(haystack, needle_char, 1, haystack + haystack_len);
}
if (found) {
found_offset = found - haystack;
if (part) {
- RETURN_STRINGL(haystack, found_offset, 1);
+ RETURN_STRINGL(haystack, found_offset);
} else {
- RETURN_STRINGL(found, haystack_len - found_offset, 1);
+ RETURN_STRINGL(found, haystack_len - found_offset);
}
}
RETURN_FALSE;
@@ -1830,7 +1806,7 @@ PHP_FUNCTION(strpos)
RETURN_FALSE;
}
- found = php_memnstr(haystack + offset,
+ found = (char*)php_memnstr(haystack + offset,
Z_STRVAL_P(needle),
Z_STRLEN_P(needle),
haystack + haystack_len);
@@ -1840,7 +1816,7 @@ PHP_FUNCTION(strpos)
}
needle_char[1] = 0;
- found = php_memnstr(haystack + offset,
+ found = (char*)php_memnstr(haystack + offset,
needle_char,
1,
haystack + haystack_len);
@@ -1890,7 +1866,7 @@ PHP_FUNCTION(stripos)
needle_dup = estrndup(Z_STRVAL_P(needle), Z_STRLEN_P(needle));
php_strtolower(needle_dup, Z_STRLEN_P(needle));
- found = php_memnstr(haystack_dup + offset, needle_dup, Z_STRLEN_P(needle), haystack_dup + haystack_len);
+ found = (char*)php_memnstr(haystack_dup + offset, needle_dup, Z_STRLEN_P(needle), haystack_dup + haystack_len);
} else {
if (php_needle_char(needle, needle_char TSRMLS_CC) != SUCCESS) {
efree(haystack_dup);
@@ -1898,7 +1874,7 @@ PHP_FUNCTION(stripos)
}
needle_char[0] = tolower(needle_char[0]);
needle_char[1] = '\0';
- found = php_memnstr(haystack_dup + offset,
+ found = (char*)php_memnstr(haystack_dup + offset,
needle_char,
sizeof(needle_char) - 1,
haystack_dup + haystack_len);
@@ -2121,7 +2097,7 @@ PHP_FUNCTION(strrchr)
if (found) {
found_offset = found - haystack;
- RETURN_STRINGL(found, haystack_len - found_offset, 1);
+ RETURN_STRINGL(found, haystack_len - found_offset);
} else {
RETURN_FALSE;
}
@@ -2130,33 +2106,33 @@ PHP_FUNCTION(strrchr)
/* {{{ php_chunk_split
*/
-static char *php_chunk_split(char *src, int srclen, char *end, int endlen, int chunklen, int *destlen)
+static zend_string *php_chunk_split(char *src, int srclen, char *end, int endlen, int chunklen)
{
- char *dest;
char *p, *q;
int chunks; /* complete chunks! */
int restlen;
int out_len;
+ zend_string *dest;
chunks = srclen / chunklen;
restlen = srclen - chunks * chunklen; /* srclen % chunklen */
- if(chunks > INT_MAX - 1) {
+ if (chunks > INT_MAX - 1) {
return NULL;
}
out_len = chunks + 1;
- if(endlen !=0 && out_len > INT_MAX/endlen) {
+ if (endlen !=0 && out_len > INT_MAX/endlen) {
return NULL;
}
out_len *= endlen;
- if(out_len > INT_MAX - srclen - 1) {
+ if (out_len > INT_MAX - srclen - 1) {
return NULL;
}
out_len += srclen + 1;
- dest = safe_emalloc((int)out_len, sizeof(char), 0);
+ dest = STR_ALLOC(out_len * sizeof(char), 0);
- for (p = src, q = dest; p < (src + srclen - chunklen + 1); ) {
+ for (p = src, q = dest->val; p < (src + srclen - chunklen + 1); ) {
memcpy(q, p, chunklen);
q += chunklen;
memcpy(q, end, endlen);
@@ -2172,11 +2148,9 @@ static char *php_chunk_split(char *src, int srclen, char *end, int endlen, int c
}
*q = '\0';
- if (destlen) {
- *destlen = q - dest;
- }
+ dest->len = q - dest->val;
- return(dest);
+ return dest;
}
/* }}} */
@@ -2185,12 +2159,11 @@ static char *php_chunk_split(char *src, int srclen, char *end, int endlen, int c
PHP_FUNCTION(chunk_split)
{
char *str;
- char *result;
char *end = "\r\n";
int endlen = 2;
long chunklen = 76;
- int result_len;
int str_len;
+ zend_string *result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls", &str, &str_len, &chunklen, &end, &endlen) == FAILURE) {
return;
@@ -2203,22 +2176,21 @@ PHP_FUNCTION(chunk_split)
if (chunklen > str_len) {
/* to maintain BC, we must return original string + ending */
- result_len = endlen + str_len;
- result = emalloc(result_len + 1);
- memcpy(result, str, str_len);
- memcpy(result + str_len, end, endlen);
- result[result_len] = '\0';
- RETURN_STRINGL(result, result_len, 0);
+ result = STR_ALLOC(endlen + str_len, 0);
+ memcpy(result->val, str, str_len);
+ memcpy(result->val + str_len, end, endlen);
+ result->val[result->len] = '\0';
+ RETURN_NEW_STR(result);
}
if (!str_len) {
RETURN_EMPTY_STRING();
}
- result = php_chunk_split(str, str_len, end, endlen, chunklen, &result_len);
+ result = php_chunk_split(str, str_len, end, endlen, chunklen);
if (result) {
- RETURN_STRINGL(result, result_len, 0);
+ RETURN_STR(result);
} else {
RETURN_FALSE;
}
@@ -2286,7 +2258,7 @@ PHP_FUNCTION(substr)
l = str_len - f;
}
- RETURN_STRINGL(str + f, l, 1);
+ RETURN_STRINGL(str + f, l);
}
/* }}} */
@@ -2294,177 +2266,164 @@ PHP_FUNCTION(substr)
Replaces part of a string with another string */
PHP_FUNCTION(substr_replace)
{
- zval **str;
- zval **from;
- zval **len = NULL;
- zval **repl;
- char *result;
- int result_len;
+ zval *str;
+ zval *from;
+ zval *len = NULL;
+ zval *repl;
int l = 0;
int f;
int argc = ZEND_NUM_ARGS();
+ zend_string *result;
- HashPosition pos_str, pos_from, pos_repl, pos_len;
- zval **tmp_str = NULL, **tmp_from = NULL, **tmp_repl = NULL, **tmp_len= NULL;
+ HashPosition pos_from, pos_repl, pos_len;
+ zval *tmp_str = NULL, *tmp_from = NULL, *tmp_repl = NULL, *tmp_len= NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ|Z", &str, &repl, &from, &len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzz|z", &str, &repl, &from, &len) == FAILURE) {
return;
}
- if (Z_TYPE_PP(str) != IS_ARRAY) {
- if (Z_ISREF_PP(str)) {
- SEPARATE_ZVAL(str);
- }
+ if (Z_TYPE_P(str) != IS_ARRAY) {
+ SEPARATE_ZVAL_IF_REF(str);
convert_to_string_ex(str);
}
- if (Z_TYPE_PP(repl) != IS_ARRAY) {
- if (Z_ISREF_PP(repl)) {
- SEPARATE_ZVAL(repl);
- }
+ if (Z_TYPE_P(repl) != IS_ARRAY) {
+ SEPARATE_ZVAL_IF_REF(repl);
convert_to_string_ex(repl);
}
- if (Z_TYPE_PP(from) != IS_ARRAY) {
- if (Z_ISREF_PP(from)) {
- SEPARATE_ZVAL(from);
- }
+ if (Z_TYPE_P(from) != IS_ARRAY) {
+ SEPARATE_ZVAL_IF_REF(from);
convert_to_long_ex(from);
}
if (argc > 3) {
SEPARATE_ZVAL(len);
- if (Z_TYPE_PP(len) != IS_ARRAY) {
- convert_to_long_ex(len);
- l = Z_LVAL_PP(len);
+ if (Z_TYPE_P(len) != IS_ARRAY) {
+ l = zval_get_long(len);
}
} else {
- if (Z_TYPE_PP(str) != IS_ARRAY) {
- l = Z_STRLEN_PP(str);
+ if (Z_TYPE_P(str) != IS_ARRAY) {
+ l = Z_STRLEN_P(str);
}
}
- if (Z_TYPE_PP(str) == IS_STRING) {
+ if (Z_TYPE_P(str) == IS_STRING) {
if (
- (argc == 3 && Z_TYPE_PP(from) == IS_ARRAY) ||
- (argc == 4 && Z_TYPE_PP(from) != Z_TYPE_PP(len))
+ (argc == 3 && Z_TYPE_P(from) == IS_ARRAY) ||
+ (argc == 4 && Z_TYPE_P(from) != Z_TYPE_P(len))
) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "'from' and 'len' should be of same type - numerical or array ");
- RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
+ RETURN_STR(STR_COPY(Z_STR_P(str)));
}
- if (argc == 4 && Z_TYPE_PP(from) == IS_ARRAY) {
- if (zend_hash_num_elements(Z_ARRVAL_PP(from)) != zend_hash_num_elements(Z_ARRVAL_PP(len))) {
+ if (argc == 4 && Z_TYPE_P(from) == IS_ARRAY) {
+ if (zend_hash_num_elements(Z_ARRVAL_P(from)) != zend_hash_num_elements(Z_ARRVAL_P(len))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "'from' and 'len' should have the same number of elements");
- RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
+ RETURN_STR(STR_COPY(Z_STR_P(str)));
}
}
}
- if (Z_TYPE_PP(str) != IS_ARRAY) {
- if (Z_TYPE_PP(from) != IS_ARRAY) {
+ if (Z_TYPE_P(str) != IS_ARRAY) {
+ if (Z_TYPE_P(from) != IS_ARRAY) {
int repl_len = 0;
- f = Z_LVAL_PP(from);
+ f = Z_LVAL_P(from);
/* if "from" position is negative, count start position from the end
* of the string
*/
if (f < 0) {
- f = Z_STRLEN_PP(str) + f;
+ f = Z_STRLEN_P(str) + f;
if (f < 0) {
f = 0;
}
- } else if (f > Z_STRLEN_PP(str)) {
- f = Z_STRLEN_PP(str);
+ } else if (f > Z_STRLEN_P(str)) {
+ f = Z_STRLEN_P(str);
}
/* if "length" position is negative, set it to the length
* needed to stop that many chars from the end of the string
*/
if (l < 0) {
- l = (Z_STRLEN_PP(str) - f) + l;
+ l = (Z_STRLEN_P(str) - f) + l;
if (l < 0) {
l = 0;
}
}
- if (f > Z_STRLEN_PP(str) || (f < 0 && -f > Z_STRLEN_PP(str))) {
+ if (f > Z_STRLEN_P(str) || (f < 0 && -f > Z_STRLEN_P(str))) {
RETURN_FALSE;
- } else if (l > Z_STRLEN_PP(str) || (l < 0 && -l > Z_STRLEN_PP(str))) {
- l = Z_STRLEN_PP(str);
+ } else if (l > Z_STRLEN_P(str) || (l < 0 && -l > Z_STRLEN_P(str))) {
+ l = Z_STRLEN_P(str);
}
- if ((f + l) > Z_STRLEN_PP(str)) {
- l = Z_STRLEN_PP(str) - f;
+ if ((f + l) > Z_STRLEN_P(str)) {
+ l = Z_STRLEN_P(str) - f;
}
- if (Z_TYPE_PP(repl) == IS_ARRAY) {
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(repl), &pos_repl);
- if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(repl), (void **) &tmp_repl, &pos_repl)) {
+ if (Z_TYPE_P(repl) == IS_ARRAY) {
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(repl), &pos_repl);
+ if (NULL != (tmp_repl = zend_hash_get_current_data_ex(Z_ARRVAL_P(repl), &pos_repl))) {
convert_to_string_ex(tmp_repl);
- repl_len = Z_STRLEN_PP(tmp_repl);
+ repl_len = Z_STRLEN_P(tmp_repl);
}
} else {
- repl_len = Z_STRLEN_PP(repl);
+ repl_len = Z_STRLEN_P(repl);
}
- result_len = Z_STRLEN_PP(str) - l + repl_len;
- result = emalloc(result_len + 1);
- memcpy(result, Z_STRVAL_PP(str), f);
+ result = STR_ALLOC(Z_STRLEN_P(str) - l + repl_len, 0);
+
+ memcpy(result->val, Z_STRVAL_P(str), f);
if (repl_len) {
- memcpy((result + f), (Z_TYPE_PP(repl) == IS_ARRAY ? Z_STRVAL_PP(tmp_repl) : Z_STRVAL_PP(repl)), repl_len);
+ memcpy((result->val + f), (Z_TYPE_P(repl) == IS_ARRAY ? Z_STRVAL_P(tmp_repl) : Z_STRVAL_P(repl)), repl_len);
}
- memcpy((result + f + repl_len), Z_STRVAL_PP(str) + f + l, Z_STRLEN_PP(str) - f - l);
- result[result_len] = '\0';
- RETURN_STRINGL(result, result_len, 0);
+ memcpy((result->val + f + repl_len), Z_STRVAL_P(str) + f + l, Z_STRLEN_P(str) - f - l);
+ result->val[result->len] = '\0';
+ RETURN_NEW_STR(result);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Functionality of 'from' and 'len' as arrays is not implemented");
- RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
+ RETURN_STR(STR_COPY(Z_STR_P(str)));
}
} else { /* str is array of strings */
- char *str_index = NULL;
- uint str_index_len;
+ zend_string *str_index = NULL;
ulong num_index;
+ int result_len;
array_init(return_value);
- if (Z_TYPE_PP(from) == IS_ARRAY) {
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(from), &pos_from);
+ if (Z_TYPE_P(from) == IS_ARRAY) {
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(from), &pos_from);
}
- if (argc > 3 && Z_TYPE_PP(len) == IS_ARRAY) {
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(len), &pos_len);
+ if (argc > 3 && Z_TYPE_P(len) == IS_ARRAY) {
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(len), &pos_len);
}
- if (Z_TYPE_PP(repl) == IS_ARRAY) {
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(repl), &pos_repl);
+ if (Z_TYPE_P(repl) == IS_ARRAY) {
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(repl), &pos_repl);
}
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(str), &pos_str);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(str), (void **) &tmp_str, &pos_str) == SUCCESS) {
+ ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(str), num_index, str_index, tmp_str) {
zval *orig_str;
zval dummy;
- ulong refcount;
- int was_ref;
- if(Z_TYPE_PP(tmp_str) != IS_STRING) {
- dummy = **tmp_str;
+ if (Z_ISREF_P(tmp_str)) {
+ /* see bug #55871 */
+ ZVAL_DUP(&dummy, Z_REFVAL_P(tmp_str));
+ convert_to_string(&dummy);
+ orig_str = &dummy;
+ } else if (Z_TYPE_P(tmp_str) != IS_STRING) {
+ ZVAL_DUP(&dummy, tmp_str);
+ convert_to_string(&dummy);
orig_str = &dummy;
- zval_copy_ctor(orig_str);
- convert_to_string(orig_str);
} else {
- orig_str = *tmp_str;
+ orig_str = tmp_str;
}
- was_ref = Z_ISREF_P(orig_str);
- Z_UNSET_ISREF_P(orig_str);
+
+ /*
refcount = Z_REFCOUNT_P(orig_str);
+ */
- if (Z_TYPE_PP(from) == IS_ARRAY) {
- if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(from), (void **) &tmp_from, &pos_from)) {
- if(Z_TYPE_PP(tmp_from) != IS_LONG) {
- zval dummy = **tmp_from;
- zval_copy_ctor(&dummy);
- convert_to_long(&dummy);
- f = Z_LVAL(dummy);
- } else {
- f = Z_LVAL_PP(tmp_from);
- }
+ if (Z_TYPE_P(from) == IS_ARRAY) {
+ if (NULL != (tmp_from = zend_hash_get_current_data_ex(Z_ARRVAL_P(from), &pos_from))) {
+ f = zval_get_long(tmp_from);
if (f < 0) {
f = Z_STRLEN_P(orig_str) + f;
@@ -2474,12 +2433,12 @@ PHP_FUNCTION(substr_replace)
} else if (f > Z_STRLEN_P(orig_str)) {
f = Z_STRLEN_P(orig_str);
}
- zend_hash_move_forward_ex(Z_ARRVAL_PP(from), &pos_from);
+ zend_hash_move_forward_ex(Z_ARRVAL_P(from), &pos_from);
} else {
f = 0;
}
} else {
- f = Z_LVAL_PP(from);
+ f = Z_LVAL_P(from);
if (f < 0) {
f = Z_STRLEN_P(orig_str) + f;
if (f < 0) {
@@ -2490,22 +2449,15 @@ PHP_FUNCTION(substr_replace)
}
}
- if (argc > 3 && Z_TYPE_PP(len) == IS_ARRAY) {
- if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(len), (void **) &tmp_len, &pos_len)) {
- if(Z_TYPE_PP(tmp_len) != IS_LONG) {
- zval dummy = **tmp_len;
- zval_copy_ctor(&dummy);
- convert_to_long(&dummy);
- l = Z_LVAL(dummy);
- } else {
- l = Z_LVAL_PP(tmp_len);
- }
- zend_hash_move_forward_ex(Z_ARRVAL_PP(len), &pos_len);
+ if (argc > 3 && Z_TYPE_P(len) == IS_ARRAY) {
+ if (NULL != (tmp_len = zend_hash_get_current_data_ex(Z_ARRVAL_P(len), &pos_len))) {
+ l = zval_get_long(tmp_len);
+ zend_hash_move_forward_ex(Z_ARRVAL_P(len), &pos_len);
} else {
l = Z_STRLEN_P(orig_str);
}
} else if (argc > 3) {
- l = Z_LVAL_PP(len);
+ l = Z_LVAL_P(len);
} else {
l = Z_STRLEN_P(orig_str);
}
@@ -2523,68 +2475,72 @@ PHP_FUNCTION(substr_replace)
result_len = Z_STRLEN_P(orig_str) - l;
- if (Z_TYPE_PP(repl) == IS_ARRAY) {
- if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(repl), (void **) &tmp_repl, &pos_repl)) {
+ if (Z_TYPE_P(repl) == IS_ARRAY) {
+ if (NULL != (tmp_repl = zend_hash_get_current_data_ex(Z_ARRVAL_P(repl), &pos_repl))) {
zval *repl_str;
zval zrepl;
- if(Z_TYPE_PP(tmp_repl) != IS_STRING) {
- zrepl = **tmp_repl;
+
+ ZVAL_DEREF(tmp_repl);
+ if (Z_TYPE_P(tmp_repl) != IS_STRING) {
+ ZVAL_DUP(&zrepl, tmp_repl);
+ convert_to_string(&zrepl);
repl_str = &zrepl;
- zval_copy_ctor(repl_str);
- convert_to_string(repl_str);
} else {
- repl_str = *tmp_repl;
+ repl_str = tmp_repl;
}
-
- if(Z_REFCOUNT_P(orig_str) != refcount) {
+ /*
+ if (Z_REFCOUNT_P(orig_str) != refcount) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument was modified while replacing");
- if(Z_TYPE_PP(tmp_repl) != IS_STRING) {
+ if (Z_TYPE_P(tmp_repl) != IS_STRING) {
zval_dtor(repl_str);
}
break;
}
+ */
result_len += Z_STRLEN_P(repl_str);
- zend_hash_move_forward_ex(Z_ARRVAL_PP(repl), &pos_repl);
- result = emalloc(result_len + 1);
+ zend_hash_move_forward_ex(Z_ARRVAL_P(repl), &pos_repl);
+ result = STR_ALLOC(result_len, 0);
- memcpy(result, Z_STRVAL_P(orig_str), f);
- memcpy((result + f), Z_STRVAL_P(repl_str), Z_STRLEN_P(repl_str));
- memcpy((result + f + Z_STRLEN_P(repl_str)), Z_STRVAL_P(orig_str) + f + l, Z_STRLEN_P(orig_str) - f - l);
- if(Z_TYPE_PP(tmp_repl) != IS_STRING) {
+ memcpy(result->val, Z_STRVAL_P(orig_str), f);
+ memcpy((result->val + f), Z_STRVAL_P(repl_str), Z_STRLEN_P(repl_str));
+ memcpy((result->val + f + Z_STRLEN_P(repl_str)), Z_STRVAL_P(orig_str) + f + l, Z_STRLEN_P(orig_str) - f - l);
+ if(Z_TYPE_P(tmp_repl) != IS_STRING) {
zval_dtor(repl_str);
}
} else {
- result = emalloc(result_len + 1);
+ result = STR_ALLOC(result_len, 0);
- memcpy(result, Z_STRVAL_P(orig_str), f);
- memcpy((result + f), Z_STRVAL_P(orig_str) + f + l, Z_STRLEN_P(orig_str) - f - l);
+ memcpy(result->val, Z_STRVAL_P(orig_str), f);
+ memcpy((result->val + f), Z_STRVAL_P(orig_str) + f + l, Z_STRLEN_P(orig_str) - f - l);
}
} else {
- result_len += Z_STRLEN_PP(repl);
+ result_len += Z_STRLEN_P(repl);
- result = emalloc(result_len + 1);
+ result = STR_ALLOC(result_len, 0);
- memcpy(result, Z_STRVAL_P(orig_str), f);
- memcpy((result + f), Z_STRVAL_PP(repl), Z_STRLEN_PP(repl));
- memcpy((result + f + Z_STRLEN_PP(repl)), Z_STRVAL_P(orig_str) + f + l, Z_STRLEN_P(orig_str) - f - l);
+ memcpy(result->val, Z_STRVAL_P(orig_str), f);
+ memcpy((result->val + f), Z_STRVAL_P(repl), Z_STRLEN_P(repl));
+ memcpy((result->val + f + Z_STRLEN_P(repl)), Z_STRVAL_P(orig_str) + f + l, Z_STRLEN_P(orig_str) - f - l);
}
- result[result_len] = '\0';
+ result->val[result->len] = '\0';
+
+ if (str_index) {
+ zval tmp;
- if (zend_hash_get_current_key_ex(Z_ARRVAL_PP(str), &str_index, &str_index_len, &num_index, 0, &pos_str) == HASH_KEY_IS_STRING) {
- add_assoc_stringl_ex(return_value, str_index, str_index_len, result, result_len, 0);
+ ZVAL_STR(&tmp, result);
+ zend_symtable_update(Z_ARRVAL_P(return_value), str_index, &tmp);
} else {
- add_index_stringl(return_value, num_index, result, result_len, 0);
+ add_index_str(return_value, num_index, result);
}
- if(Z_TYPE_PP(tmp_str) != IS_STRING) {
+ if(Z_TYPE_P(tmp_str) != IS_STRING) {
zval_dtor(orig_str);
} else {
- Z_SET_ISREF_TO_P(orig_str, was_ref);
+//??? Z_SET_ISREF_TO_P(orig_str, was_ref);
}
- zend_hash_move_forward_ex(Z_ARRVAL_PP(str), &pos_str);
- } /*while*/
+ } ZEND_HASH_FOREACH_END();
} /* if */
}
/* }}} */
@@ -2593,11 +2549,12 @@ PHP_FUNCTION(substr_replace)
Quotes meta characters */
PHP_FUNCTION(quotemeta)
{
- char *str, *old;
+ char *old;
char *old_end;
char *p, *q;
char c;
int old_len;
+ zend_string *str;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &old, &old_len) == FAILURE) {
return;
@@ -2609,9 +2566,9 @@ PHP_FUNCTION(quotemeta)
RETURN_FALSE;
}
- str = safe_emalloc(2, old_len, 1);
+ str = STR_ALLOC(2 * old_len, 0);
- for (p = old, q = str; p != old_end; p++) {
+ for (p = old, q = str->val; p != old_end; p++) {
c = *p;
switch (c) {
case '.':
@@ -2631,9 +2588,10 @@ PHP_FUNCTION(quotemeta)
*q++ = c;
}
}
- *q = 0;
- RETURN_STRINGL(erealloc(str, q - str + 1), q - str, 0);
+ *q = '\0';
+
+ RETURN_NEW_STR(STR_REALLOC(str, q - str->val, 0));
}
/* }}} */
@@ -2670,7 +2628,7 @@ PHP_FUNCTION(chr)
temp[0] = (char)c;
temp[1] = '\0';
- RETURN_STRINGL(temp, 1, 1);
+ RETURN_STRINGL(temp, 1);
}
/* }}} */
@@ -2699,7 +2657,7 @@ PHP_FUNCTION(ucfirst)
RETURN_EMPTY_STRING();
}
- ZVAL_STRINGL(return_value, str, str_len, 1);
+ ZVAL_STRINGL(return_value, str, str_len);
php_ucfirst(Z_STRVAL_P(return_value));
}
/* }}} */
@@ -2729,7 +2687,7 @@ PHP_FUNCTION(lcfirst)
RETURN_EMPTY_STRING();
}
- ZVAL_STRINGL(return_value, str, str_len, 1);
+ ZVAL_STRINGL(return_value, str, str_len);
php_lcfirst(Z_STRVAL_P(return_value));
}
/* }}} */
@@ -2750,7 +2708,7 @@ PHP_FUNCTION(ucwords)
RETURN_EMPTY_STRING();
}
- ZVAL_STRINGL(return_value, str, str_len, 1);
+ ZVAL_STRINGL(return_value, str, str_len);
r = Z_STRVAL_P(return_value);
*r = toupper((unsigned char) *r);
@@ -2787,333 +2745,174 @@ PHPAPI char *php_strtr(char *str, int len, char *str_from, char *str_to, int trl
}
/* }}} */
-/* {{{ Definitions for php_strtr_array */
-typedef size_t STRLEN; /* STRLEN should be unsigned */
-typedef uint16_t HASH;
-typedef struct {
- HASH table_mask;
- STRLEN entries[1];
-} SHIFT_TAB;
-typedef struct {
- HASH table_mask;
- int entries[1];
-} HASH_TAB;
-typedef struct {
- const char *s;
- STRLEN l;
-} STR;
-typedef struct _pat_and_repl {
- STR pat;
- STR repl;
-} PATNREPL;
-
-#define S(a) ((a)->s)
-#define L(a) ((a)->l)
-
-#define SHIFT_TAB_BITS 13
-#define HASH_TAB_BITS 10 /* should be less than sizeof(HASH) * 8 */
-#define SHIFT_TAB_SIZE (1U << SHIFT_TAB_BITS)
-#define HASH_TAB_SIZE (1U << HASH_TAB_BITS)
-
-typedef struct {
- int B; /* size of suffixes */
- int Bp; /* size of prefixes */
- STRLEN m; /* minimum pattern length */
- int patnum; /* number of patterns */
- SHIFT_TAB *shift; /* table mapping hash to allowed shift */
- HASH_TAB *hash; /* table mapping hash to int (pair of pointers) */
- HASH *prefix; /* array of hashes of prefixes by pattern suffix hash order */
- PATNREPL *patterns; /* array of prefixes by pattern suffix hash order */
-} PPRES;
-/* }}} */
-
-/* {{{ php_strtr_hash */
-static inline HASH php_strtr_hash(const char *str, int len)
+static int php_strtr_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */
{
- HASH res = 0;
- int i;
- for (i = 0; i < len; i++) {
- res = res * 33 + (unsigned char)str[i];
- }
+ Bucket *f = (Bucket *) a;
+ Bucket *s = (Bucket *) b;
- return res;
+ return f->h > s->h ? -1 : 1;
}
/* }}} */
-/* {{{ php_strtr_populate_shift */
-static inline void php_strtr_populate_shift(PATNREPL *patterns, int patnum, int B, STRLEN m, SHIFT_TAB *shift)
-{
- int i;
- STRLEN j,
- max_shift;
-
- max_shift = m - B + 1;
- for (i = 0; i < SHIFT_TAB_SIZE; i++) {
- shift->entries[i] = max_shift;
- }
- for (i = 0; i < patnum; i++) {
- for (j = 0; j < m - B + 1; j++) {
- HASH h = php_strtr_hash(&S(&patterns[i].pat)[j], B) & shift->table_mask;
- assert((long long) m - (long long) j - B >= 0);
- shift->entries[h] = MIN(shift->entries[h], m - j - B);
- }
- }
-}
-/* }}} */
-/* {{{ php_strtr_compare_hash_suffix */
-static int php_strtr_compare_hash_suffix(const void *a, const void *b TSRMLS_DC, void *ctx_g)
+
+/* {{{ php_strtr_array */
+static void php_strtr_array(zval *return_value, char *str, int slen, HashTable *pats TSRMLS_DC)
{
- const PPRES *res = ctx_g;
- const PATNREPL *pnr_a = a,
- *pnr_b = b;
- HASH hash_a = php_strtr_hash(&S(&pnr_a->pat)[res->m - res->B], res->B)
- & res->hash->table_mask,
- hash_b = php_strtr_hash(&S(&pnr_b->pat)[res->m - res->B], res->B)
- & res->hash->table_mask;
- /* TODO: don't recalculate the hashes all the time */
- if (hash_a > hash_b) {
- return 1;
- } else if (hash_a < hash_b) {
- return -1;
- } else {
- /* longer patterns must be sorted first */
- if (L(&pnr_a->pat) > L(&pnr_b->pat)) {
- return -1;
- } else if (L(&pnr_a->pat) < L(&pnr_b->pat)) {
- return 1;
+ ulong num_key;
+ zend_string *str_key;
+ int len, pos, found;
+ int num_keys = 0;
+ int minlen = 128*1024;
+ int maxlen = 0;
+ HashTable str_hash, num_hash;
+ zval *entry, tmp, dummy;
+ char *key;
+ smart_str result = {0};
+
+ /* we will collect all possible key lenghts */
+ ZVAL_NULL(&dummy);
+ zend_hash_init(&num_hash, 8, NULL, NULL, 0);
+
+ /* check if original array has numeric keys */
+ ZEND_HASH_FOREACH_KEY(pats, num_key, str_key) {
+ if (UNEXPECTED(!str_key)) {
+ num_keys = 1;
} else {
- return 0;
- }
- }
-}
-/* }}} */
-/* {{{ php_strtr_free_strp */
-static void php_strtr_free_strp(void *strp)
-{
- STR_FREE(*(char**)strp);
-}
-/* }}} */
-/* {{{ php_strtr_array_prepare_repls */
-static PATNREPL *php_strtr_array_prepare_repls(int slen, HashTable *pats, zend_llist **allocs, int *outsize)
-{
- PATNREPL *patterns;
- HashPosition hpos;
- zval **entry;
- int num_pats = zend_hash_num_elements(pats),
- i;
-
- patterns = safe_emalloc(num_pats, sizeof(*patterns), 0);
- *allocs = emalloc(sizeof **allocs);
- zend_llist_init(*allocs, sizeof(void*), &php_strtr_free_strp, 0);
-
- for (i = 0, zend_hash_internal_pointer_reset_ex(pats, &hpos);
- zend_hash_get_current_data_ex(pats, (void **)&entry, &hpos) == SUCCESS;
- zend_hash_move_forward_ex(pats, &hpos)) {
- char *string_key;
- uint string_key_len;
- ulong num_key;
- zval *tzv = NULL;
-
- switch (zend_hash_get_current_key_ex(pats, &string_key, &string_key_len, &num_key, 0, &hpos)) {
- case HASH_KEY_IS_LONG:
- string_key_len = 1 + zend_spprintf(&string_key, 0, "%ld", (long)num_key);
- zend_llist_add_element(*allocs, &string_key);
- /* break missing intentionally */
-
- case HASH_KEY_IS_STRING:
- string_key_len--; /* exclude final '\0' */
- if (string_key_len == 0) { /* empty string given as pattern */
- efree(patterns);
- zend_llist_destroy(*allocs);
- efree(*allocs);
- *allocs = NULL;
- return NULL;
- }
- if (string_key_len > slen) { /* this pattern can never match */
+ len = str_key->len;
+ if (UNEXPECTED(len < 1)) {
+ RETURN_FALSE;
+ } else if (UNEXPECTED(len > slen)) {
+ /* skip long patterns */
continue;
}
-
- if (Z_TYPE_PP(entry) != IS_STRING) {
- tzv = *entry;
- zval_addref_p(tzv);
- SEPARATE_ZVAL(&tzv);
- convert_to_string(tzv);
- entry = &tzv;
- zend_llist_add_element(*allocs, &Z_STRVAL_PP(entry));
- }
-
- S(&patterns[i].pat) = string_key;
- L(&patterns[i].pat) = string_key_len;
- S(&patterns[i].repl) = Z_STRVAL_PP(entry);
- L(&patterns[i].repl) = Z_STRLEN_PP(entry);
- i++;
-
- if (tzv) {
- efree(tzv);
+ if (len > maxlen) {
+ maxlen = len;
}
- }
- }
-
- *outsize = i;
- return patterns;
-}
-/* }}} */
-
-/* {{{ PPRES *php_strtr_array_prepare(STR *text, PATNREPL *patterns, int patnum, int B, int Bp) */
-static PPRES *php_strtr_array_prepare(STR *text, PATNREPL *patterns, int patnum, int B, int Bp)
-{
- int i;
- PPRES *res = emalloc(sizeof *res);
-
- res->m = (STRLEN)-1;
- for (i = 0; i < patnum; i++) {
- if (L(&patterns[i].pat) < res->m) {
- res->m = L(&patterns[i].pat);
- }
- }
- assert(res->m > 0);
- res->B = B = MIN(B, res->m);
- res->Bp = Bp = MIN(Bp, res->m);
-
- res->shift = safe_emalloc(SHIFT_TAB_SIZE, sizeof(*res->shift->entries), sizeof(*res->shift));
- res->shift->table_mask = SHIFT_TAB_SIZE - 1;
- php_strtr_populate_shift(patterns, patnum, B, res->m, res->shift);
-
- res->hash = safe_emalloc(HASH_TAB_SIZE, sizeof(*res->hash->entries), sizeof(*res->hash));
- res->hash->table_mask = HASH_TAB_SIZE - 1;
-
- res->patterns = safe_emalloc(patnum, sizeof(*res->patterns), 0);
- memcpy(res->patterns, patterns, sizeof(*patterns) * patnum);
-#ifdef ZTS
- zend_qsort_r(res->patterns, patnum, sizeof(*res->patterns),
- php_strtr_compare_hash_suffix, res, NULL); /* tsrmls not needed */
-#else
- zend_qsort_r(res->patterns, patnum, sizeof(*res->patterns),
- php_strtr_compare_hash_suffix, res);
-#endif
-
- res->prefix = safe_emalloc(patnum, sizeof(*res->prefix), 0);
- for (i = 0; i < patnum; i++) {
- res->prefix[i] = php_strtr_hash(S(&res->patterns[i].pat), Bp);
- }
-
- /* Initialize the rest of ->hash */
- for (i = 0; i < HASH_TAB_SIZE; i++) {
- res->hash->entries[i] = -1;
- }
- {
- HASH last_h = -1; /* assumes not all bits are used in res->hash */
- /* res->patterns is already ordered by hash.
- * Make res->hash->entries[h] de index of the first pattern in
- * res->patterns that has hash h */
- for (i = 0; i < patnum; i++) {
- HASH h = php_strtr_hash(&S(&res->patterns[i].pat)[res->m - res->B], res->B)
- & res->hash->table_mask;
- if (h != last_h) {
- res->hash->entries[h] = i;
- last_h = h;
+ if (len < minlen) {
+ minlen = len;
}
- }
- }
- res->hash->entries[HASH_TAB_SIZE] = patnum; /* OK, we effectively allocated SIZE+1 */
- for (i = HASH_TAB_SIZE - 1; i >= 0; i--) {
- if (res->hash->entries[i] == -1) {
- res->hash->entries[i] = res->hash->entries[i + 1];
- }
- }
-
- res->patnum = patnum;
-
- return res;
-}
-/* }}} */
-/* {{{ php_strtr_array_destroy_ppres(PPRES *d) */
-static void php_strtr_array_destroy_ppres(PPRES *d)
-{
- efree(d->shift);
- efree(d->hash);
- efree(d->prefix);
- efree(d->patterns);
- efree(d);
-}
-/* }}} */
-
-/* {{{ php_strtr_array_do_repl(STR *text, PPRES *d, zval *return_value) */
-static void php_strtr_array_do_repl(STR *text, PPRES *d, zval *return_value)
-{
- STRLEN pos = 0,
- nextwpos = 0,
- lastpos = L(text) - d->m;
- smart_str result = {0};
-
- while (pos <= lastpos) {
- HASH h = php_strtr_hash(&S(text)[pos + d->m - d->B], d->B) & d->shift->table_mask;
- STRLEN shift = d->shift->entries[h];
-
- if (shift > 0) {
- pos += shift;
- } else {
- HASH h2 = h & d->hash->table_mask,
- prefix_h = php_strtr_hash(&S(text)[pos], d->Bp);
-
- int offset_start = d->hash->entries[h2],
- offset_end = d->hash->entries[h2 + 1], /* exclusive */
- i = 0;
-
- for (i = offset_start; i < offset_end; i++) {
- PATNREPL *pnr;
- if (d->prefix[i] != prefix_h)
+ /* remember possible key lenght */
+ zend_hash_index_add(&num_hash, len, &dummy);
+ }
+ } ZEND_HASH_FOREACH_END();
+
+ if (num_keys) {
+ /* we have to rebuild HashTable with numeric keys */
+ zend_hash_init(&str_hash, zend_hash_num_elements(pats), NULL, NULL, 0);
+ ZEND_HASH_FOREACH_KEY_VAL(pats, num_key, str_key, entry) {
+ if (UNEXPECTED(!str_key)) {
+ ZVAL_LONG(&tmp, num_key);
+ convert_to_string(&tmp);
+ str_key = Z_STR(tmp);
+ len = str_key->len;
+ if (UNEXPECTED(len > slen)) {
+ /* skip long patterns */
+ zval_dtor(&tmp);
continue;
-
- pnr = &d->patterns[i];
- if (L(&pnr->pat) > L(text) - pos ||
- memcmp(S(&pnr->pat), &S(text)[pos], L(&pnr->pat)) != 0)
+ }
+ if (len > maxlen) {
+ maxlen = len;
+ }
+ if (len < minlen) {
+ minlen = len;
+ }
+ /* remember possible key lenght */
+ zend_hash_index_add(&num_hash, len, &dummy);
+ } else {
+ len = str_key->len;
+ if (UNEXPECTED(len > slen)) {
+ /* skip long patterns */
continue;
-
- smart_str_appendl(&result, &S(text)[nextwpos], pos - nextwpos);
- smart_str_appendl(&result, S(&pnr->repl), L(&pnr->repl));
- pos += L(&pnr->pat);
- nextwpos = pos;
- goto end_outer_loop;
+ }
+ }
+ zend_hash_add(&str_hash, str_key, entry);
+ if (str_key == Z_STR(tmp)) {
+ zval_dtor(&tmp);
+ }
+ } ZEND_HASH_FOREACH_END();
+ pats = &str_hash;
+ }
+
+ if (UNEXPECTED(minlen > maxlen)) {
+ /* return the original string */
+ if (pats == &str_hash) {
+ zend_hash_destroy(&str_hash);
+ }
+ zend_hash_destroy(&num_hash);
+ RETURN_STRINGL(str, slen);
+ }
+ /* select smart or simple algorithm */
+ // TODO: tune the condition ???
+ len = zend_hash_num_elements(&num_hash);
+ if ((maxlen - (minlen - 1) - len > 0) &&
+ /* smart algorithm, sort key lengths first */
+ zend_hash_sort(&num_hash, zend_qsort, php_strtr_key_compare, 0 TSRMLS_CC) == SUCCESS) {
+
+ pos = 0;
+ while (pos <= slen - minlen) {
+ found = 0;
+ key = str + pos;
+ ZEND_HASH_FOREACH_NUM_KEY(&num_hash, len) {
+ if (len > slen - pos) continue;
+ entry = zend_hash_str_find(pats, key, len);
+ if (entry != NULL) {
+ if (UNEXPECTED(Z_TYPE_P(entry) != IS_STRING)) {
+ ZVAL_DUP(&tmp, entry);
+ convert_to_string(&tmp);
+ entry = &tmp;
+ }
+ smart_str_appendl(&result, Z_STRVAL_P(entry), Z_STRLEN_P(entry));
+ pos += len;
+ if (entry == &tmp) {
+ zval_dtor(&tmp);
+ }
+ found = 1;
+ break;
+ }
+ } ZEND_HASH_FOREACH_END();
+ if (!found) {
+ smart_str_appendc(&result, str[pos++]);
}
-
- pos++;
-end_outer_loop: ;
}
- }
-
- smart_str_appendl(&result, &S(text)[nextwpos], L(text) - nextwpos);
-
- if (result.c != NULL) {
- smart_str_0(&result);
- RETVAL_STRINGL(result.c, result.len, 0);
+ smart_str_appendl(&result, str + pos, slen - pos);
} else {
- RETURN_EMPTY_STRING();
+ /* use simple algorithm */
+ pos = 0;
+ while (pos <= slen - minlen) {
+ if (maxlen > slen - pos) {
+ maxlen = slen - pos;
+ }
+ found = 0;
+ key = str + pos;
+ for (len = maxlen; len >= minlen; len--) {
+ entry = zend_hash_str_find(pats, key, len);
+ if (entry != NULL) {
+ if (UNEXPECTED(Z_TYPE_P(entry) != IS_STRING)) {
+ ZVAL_DUP(&tmp, entry);
+ convert_to_string(&tmp);
+ entry = &tmp;
+ }
+ smart_str_appendl(&result, Z_STRVAL_P(entry), Z_STRLEN_P(entry));
+ pos += len;
+ if (entry == &tmp) {
+ zval_dtor(&tmp);
+ }
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ smart_str_appendc(&result, str[pos++]);
+ }
+ }
+ smart_str_appendl(&result, str + pos, slen - pos);
}
-}
-/* }}} */
-
-/* {{{ php_strtr_array */
-static void php_strtr_array(zval *return_value, char *str, int slen, HashTable *pats)
-{
- PPRES *data;
- STR text;
- PATNREPL *patterns;
- int patterns_len;
- zend_llist *allocs;
-
- S(&text) = str;
- L(&text) = slen;
- patterns = php_strtr_array_prepare_repls(slen, pats, &allocs, &patterns_len);
- if (patterns == NULL) {
- RETURN_FALSE;
+ if (pats == &str_hash) {
+ zend_hash_destroy(&str_hash);
}
- data = php_strtr_array_prepare(&text, patterns, patterns_len, 2, 2);
- efree(patterns);
- php_strtr_array_do_repl(&text, data, return_value);
- php_strtr_array_destroy_ppres(data);
- zend_llist_destroy(allocs);
- efree(allocs);
+ zend_hash_destroy(&num_hash);
+ smart_str_0(&result);
+ RETURN_STR(result.s);
}
/* }}} */
@@ -3121,16 +2920,16 @@ static void php_strtr_array(zval *return_value, char *str, int slen, HashTable *
Translates characters in str using given translation tables */
PHP_FUNCTION(strtr)
{
- zval **from;
+ zval *from;
char *str, *to = NULL;
int str_len, to_len = 0;
int ac = ZEND_NUM_ARGS();
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sZ|s", &str, &str_len, &from, &to, &to_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|s", &str, &str_len, &from, &to, &to_len) == FAILURE) {
return;
}
- if (ac == 2 && Z_TYPE_PP(from) != IS_ARRAY) {
+ if (ac == 2 && Z_TYPE_P(from) != IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second argument is not an array");
RETURN_FALSE;
}
@@ -3141,17 +2940,17 @@ PHP_FUNCTION(strtr)
}
if (ac == 2) {
- php_strtr_array(return_value, str, str_len, HASH_OF(*from));
+ php_strtr_array(return_value, str, str_len, HASH_OF(from) TSRMLS_CC);
} else {
convert_to_string_ex(from);
- ZVAL_STRINGL(return_value, str, str_len, 1);
+ ZVAL_STRINGL(return_value, str, str_len);
php_strtr(Z_STRVAL_P(return_value),
Z_STRLEN_P(return_value),
- Z_STRVAL_PP(from),
+ Z_STRVAL_P(from),
to,
- MIN(Z_STRLEN_PP(from),
+ MIN(Z_STRLEN_P(from),
to_len));
}
}
@@ -3162,15 +2961,16 @@ PHP_FUNCTION(strtr)
PHP_FUNCTION(strrev)
{
char *str;
- char *e, *n, *p;
+ char *e, *p;
int str_len;
+ zend_string *n;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
return;
}
- n = emalloc(str_len+1);
- p = n;
+ n = STR_ALLOC(str_len, 0);
+ p = n->val;
e = str + str_len;
@@ -3180,7 +2980,7 @@ PHP_FUNCTION(strrev)
*p = '\0';
- RETVAL_STRINGL(n, str_len, 0);
+ RETVAL_NEW_STR(n);
}
/* }}} */
@@ -3235,22 +3035,23 @@ static int php_similar_char(const char *txt1, int len1, const char *txt2, int le
PHP_FUNCTION(similar_text)
{
char *t1, *t2;
- zval **percent = NULL;
+ zval *percent = NULL;
int ac = ZEND_NUM_ARGS();
int sim;
int t1_len, t2_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|Z", &t1, &t1_len, &t2, &t2_len, &percent) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|z", &t1, &t1_len, &t2, &t2_len, &percent) == FAILURE) {
return;
}
if (ac > 2) {
+ percent = Z_REFVAL_P(percent);
convert_to_double_ex(percent);
}
if (t1_len + t2_len == 0) {
if (ac > 2) {
- Z_DVAL_PP(percent) = 0;
+ Z_DVAL_P(percent) = 0;
}
RETURN_LONG(0);
@@ -3259,7 +3060,7 @@ PHP_FUNCTION(similar_text)
sim = php_similar_char(t1, t1_len, t2, t2_len);
if (ac > 2) {
- Z_DVAL_PP(percent) = sim * 200.0 / (t1_len + t2_len);
+ Z_DVAL_P(percent) = sim * 200.0 / (t1_len + t2_len);
}
RETURN_LONG(sim);
@@ -3325,11 +3126,10 @@ PHP_FUNCTION(addcslashes)
}
if (what_len == 0) {
- RETURN_STRINGL(str, str_len, 1);
+ RETURN_STRINGL(str, str_len);
}
- Z_STRVAL_P(return_value) = php_addcslashes(str, str_len, &Z_STRLEN_P(return_value), 0, what, what_len TSRMLS_CC);
- RETURN_STRINGL(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value), 0);
+ RETURN_STR(php_addcslashes(str, str_len, 0, what, what_len TSRMLS_CC));
}
/* }}} */
@@ -3348,10 +3148,7 @@ PHP_FUNCTION(addslashes)
RETURN_EMPTY_STRING();
}
- RETURN_STRING(php_addslashes(str,
- str_len,
- &Z_STRLEN_P(return_value), 0
- TSRMLS_CC), 0);
+ RETURN_STR(php_addslashes(str, str_len, 0 TSRMLS_CC));
}
/* }}} */
@@ -3366,7 +3163,7 @@ PHP_FUNCTION(stripcslashes)
return;
}
- ZVAL_STRINGL(return_value, str, str_len, 1);
+ ZVAL_STRINGL(return_value, str, str_len);
php_stripcslashes(Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value));
}
/* }}} */
@@ -3382,7 +3179,7 @@ PHP_FUNCTION(stripslashes)
return;
}
- ZVAL_STRINGL(return_value, str, str_len, 1);
+ ZVAL_STRINGL(return_value, str, str_len);
php_stripslashes(Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value) TSRMLS_CC);
}
/* }}} */
@@ -3471,14 +3268,14 @@ PHPAPI void php_stripcslashes(char *str, int *len)
/* {{{ php_addcslashes
*/
-PHPAPI char *php_addcslashes(const char *str, int length, int *new_length, int should_free, char *what, int wlength TSRMLS_DC)
+PHPAPI zend_string *php_addcslashes(const char *str, int length, int should_free, char *what, int wlength TSRMLS_DC)
{
char flags[256];
- char *new_str = safe_emalloc(4, (length?length:(length=strlen(str))), 1);
char *source, *target;
char *end;
char c;
int newlen;
+ zend_string *new_str = STR_ALLOC(4 * (length? length : (length = strlen(str))), 0);
if (!wlength) {
wlength = strlen(what);
@@ -3486,7 +3283,7 @@ PHPAPI char *php_addcslashes(const char *str, int length, int *new_length, int s
php_charmask((unsigned char *)what, wlength, flags TSRMLS_CC);
- for (source = (char*)str, end = source + length, target = new_str; source < end; source++) {
+ for (source = (char*)str, end = source + length, target = new_str->val; source < end; source++) {
c = *source;
if (flags[(unsigned char)c]) {
if ((unsigned char) c < 32 || (unsigned char) c > 126) {
@@ -3508,15 +3305,12 @@ PHPAPI char *php_addcslashes(const char *str, int length, int *new_length, int s
*target++ = c;
}
*target = 0;
- newlen = target - new_str;
- if (target - new_str < length * 4) {
- new_str = erealloc(new_str, newlen + 1);
- }
- if (new_length) {
- *new_length = newlen;
+ newlen = target - new_str->val;
+ if (newlen < length * 4) {
+ new_str = STR_REALLOC(new_str, newlen, 0);
}
if (should_free) {
- STR_FREE((char*)str);
+//??? STR_FREE((char*)str);
}
return new_str;
}
@@ -3524,25 +3318,21 @@ PHPAPI char *php_addcslashes(const char *str, int length, int *new_length, int s
/* {{{ php_addslashes
*/
-PHPAPI char *php_addslashes(char *str, int length, int *new_length, int should_free TSRMLS_DC)
+PHPAPI zend_string *php_addslashes(char *str, int length, int should_free TSRMLS_DC)
{
/* maximum string length, worst case situation */
- char *new_str;
char *source, *target;
char *end;
- int local_new_length;
+ zend_string *new_str;
- if (!new_length) {
- new_length = &local_new_length;
- }
if (!str) {
- *new_length = 0;
- return str;
+ return STR_EMPTY_ALLOC();
}
- new_str = (char *) safe_emalloc(2, (length ? length : (length = strlen(str))), 1);
+
+ new_str = STR_ALLOC(2 * (length ? length : (length = strlen(str))), 0);
source = str;
end = source + length;
- target = new_str;
+ target = new_str->val;
while (source < end) {
switch (*source) {
@@ -3564,11 +3354,11 @@ PHPAPI char *php_addslashes(char *str, int length, int *new_length, int should_f
}
*target = 0;
- *new_length = target - new_str;
if (should_free) {
- STR_FREE(str);
+//??? STR_FREE(str);
}
- new_str = (char *) erealloc(new_str, *new_length + 1);
+ new_str = STR_REALLOC(new_str, target - new_str->val, 0);
+
return new_str;
}
/* }}} */
@@ -3602,13 +3392,16 @@ PHPAPI int php_char_to_str_ex(char *str, uint len, char from, char *to, int to_l
}
if (char_count == 0 && case_sensitivity) {
- ZVAL_STRINGL(result, str, len, 1);
+ ZVAL_STRINGL(result, str, len);
return 0;
}
- Z_STRLEN_P(result) = len + (char_count * (to_len - 1));
- Z_STRVAL_P(result) = target = safe_emalloc(char_count, to_len, len + 1);
- Z_TYPE_P(result) = IS_STRING;
+ if (to_len > 0) {
+ ZVAL_NEW_STR(result, STR_SAFE_ALLOC(char_count, to_len - 1, len, 0));
+ } else {
+ ZVAL_NEW_STR(result, STR_ALLOC(len - char_count, 0));
+ }
+ target = Z_STRVAL_P(result);
if (case_sensitivity) {
char *p = str, *e = p + len, *s = str;
@@ -3659,22 +3452,21 @@ PHPAPI int php_char_to_str(char *str, uint len, char from, char *to, int to_len,
/* {{{ php_str_to_str_ex
*/
-PHPAPI char *php_str_to_str_ex(char *haystack, int length,
- char *needle, int needle_len, char *str, int str_len, int *_new_length, int case_sensitivity, int *replace_count)
+PHPAPI zend_string *php_str_to_str_ex(char *haystack, int length,
+ char *needle, int needle_len, char *str, int str_len, int case_sensitivity, int *replace_count)
{
- char *new_str;
+ zend_string *new_str;
if (needle_len < length) {
char *end, *haystack_dup = NULL, *needle_dup = NULL;
char *e, *s, *p, *r;
if (needle_len == str_len) {
- new_str = estrndup(haystack, length);
- *_new_length = length;
+ new_str = STR_INIT(haystack, length, 0);
if (case_sensitivity) {
- end = new_str + length;
- for (p = new_str; (r = php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
+ end = new_str->val + length;
+ for (p = new_str->val; (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
memcpy(r, str, str_len);
if (replace_count) {
(*replace_count)++;
@@ -3686,8 +3478,8 @@ PHPAPI char *php_str_to_str_ex(char *haystack, int length,
php_strtolower(haystack_dup, length);
php_strtolower(needle_dup, needle_len);
end = haystack_dup + length;
- for (p = haystack_dup; (r = php_memnstr(p, needle_dup, needle_len, end)); p = r + needle_len) {
- memcpy(new_str + (r - haystack_dup), str, str_len);
+ for (p = haystack_dup; (r = (char*)php_memnstr(p, needle_dup, needle_len, end)); p = r + needle_len) {
+ memcpy(new_str->val + (r - haystack_dup), str, str_len);
if (replace_count) {
(*replace_count)++;
}
@@ -3705,7 +3497,7 @@ PHPAPI char *php_str_to_str_ex(char *haystack, int length,
}
if (str_len < needle_len) {
- new_str = emalloc(length + 1);
+ new_str = STR_ALLOC(length, 0);
} else {
int count = 0;
char *o, *n, *endp;
@@ -3719,7 +3511,7 @@ PHPAPI char *php_str_to_str_ex(char *haystack, int length,
}
endp = o + length;
- while ((o = php_memnstr(o, n, needle_len, endp))) {
+ while ((o = (char*)php_memnstr(o, n, needle_len, endp))) {
o += needle_len;
count++;
}
@@ -3731,21 +3523,18 @@ PHPAPI char *php_str_to_str_ex(char *haystack, int length,
if (needle_dup) {
efree(needle_dup);
}
- new_str = estrndup(haystack, length);
- if (_new_length) {
- *_new_length = length;
- }
+ new_str = STR_INIT(haystack, length, 0);
return new_str;
} else {
- new_str = safe_emalloc(count, str_len - needle_len, length + 1);
+ new_str = STR_ALLOC(count * (str_len - needle_len) + length, 0);
}
}
- e = s = new_str;
+ e = s = new_str->val;
if (case_sensitivity) {
end = haystack + length;
- for (p = haystack; (r = php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
+ for (p = haystack; (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
memcpy(e, p, r - p);
e += r - p;
memcpy(e, str, str_len);
@@ -3762,7 +3551,7 @@ PHPAPI char *php_str_to_str_ex(char *haystack, int length,
} else {
end = haystack_dup + length;
- for (p = haystack_dup; (r = php_memnstr(p, needle_dup, needle_len, end)); p = r + needle_len) {
+ for (p = haystack_dup; (r = (char*)php_memnstr(p, needle_dup, needle_len, end)); p = r + needle_len) {
memcpy(e, haystack + (p - haystack_dup), r - p);
e += r - p;
memcpy(e, str, str_len);
@@ -3786,15 +3575,13 @@ PHPAPI char *php_str_to_str_ex(char *haystack, int length,
}
*e = '\0';
- *_new_length = e - s;
- new_str = erealloc(new_str, *_new_length + 1);
+ new_str = STR_REALLOC(new_str, e - s, 0);
return new_str;
}
} else if (needle_len > length) {
nothing_todo:
- *_new_length = length;
- new_str = estrndup(haystack, length);
+ new_str = STR_INIT(haystack, length, 0);
return new_str;
} else {
if (case_sensitivity && memcmp(haystack, needle, length)) {
@@ -3817,8 +3604,7 @@ nothing_todo:
efree(l_needle);
}
- *_new_length = str_len;
- new_str = estrndup(str, str_len);
+ new_str = STR_INIT(str, str_len, 0);
if (replace_count) {
(*replace_count)++;
@@ -3831,37 +3617,44 @@ nothing_todo:
/* {{{ php_str_to_str
*/
-PHPAPI char *php_str_to_str(char *haystack, int length,
- char *needle, int needle_len, char *str, int str_len, int *_new_length)
+PHPAPI zend_string *php_str_to_str(char *haystack, int length, char *needle, int needle_len, char *str, int str_len)
{
- return php_str_to_str_ex(haystack, length, needle, needle_len, str, str_len, _new_length, 1, NULL);
+ return php_str_to_str_ex(haystack, length, needle, needle_len, str, str_len, 1, NULL);
}
/* }}} */
/* {{{ php_str_replace_in_subject
*/
-static void php_str_replace_in_subject(zval *search, zval *replace, zval **subject, zval *result, int case_sensitivity, int *replace_count)
+static void php_str_replace_in_subject(zval *search, zval *replace, zval *subject, zval *result, int case_sensitivity, int *replace_count TSRMLS_DC)
{
- zval **search_entry,
- **replace_entry = NULL,
- temp_result;
+ zval *search_entry,
+ *replace_entry = NULL,
+ temp_result,
+ tmp_subject;
char *replace_value = NULL;
int replace_len = 0;
/* Make sure we're dealing with strings. */
- convert_to_string_ex(subject);
- Z_TYPE_P(result) = IS_STRING;
- if (Z_STRLEN_PP(subject) == 0) {
- ZVAL_STRINGL(result, "", 0, 1);
+ if (Z_ISREF_P(subject)) {
+ subject = Z_REFVAL_P(subject);
+ }
+ ZVAL_UNDEF(&tmp_subject);
+ if (Z_TYPE_P(subject) != IS_STRING) {
+ ZVAL_DUP(&tmp_subject, subject);
+ convert_to_string_ex(&tmp_subject);
+ subject = &tmp_subject;
+ }
+ if (Z_STRLEN_P(subject) == 0) {
+ zval_ptr_dtor(&tmp_subject);
+ ZVAL_EMPTY_STRING(result);
return;
}
+//??? Z_TYPE_P(result) = IS_STRING;
/* If search is an array */
if (Z_TYPE_P(search) == IS_ARRAY) {
/* Duplicate subject string for repeated replacement */
- MAKE_COPY_ZVAL(subject, result);
-
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(search));
+ ZVAL_DUP(result, subject);
if (Z_TYPE_P(replace) == IS_ARRAY) {
zend_hash_internal_pointer_reset(Z_ARRVAL_P(replace));
@@ -3872,12 +3665,11 @@ static void php_str_replace_in_subject(zval *search, zval *replace, zval **subje
}
/* For each entry in the search array, get the entry */
- while (zend_hash_get_current_data(Z_ARRVAL_P(search), (void **) &search_entry) == SUCCESS) {
+ ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(search), search_entry) {
/* Make sure we're dealing with strings. */
SEPARATE_ZVAL(search_entry);
- convert_to_string(*search_entry);
- if (Z_STRLEN_PP(search_entry) == 0) {
- zend_hash_move_forward(Z_ARRVAL_P(search));
+ convert_to_string(search_entry);
+ if (Z_STRLEN_P(search_entry) == 0) {
if (Z_TYPE_P(replace) == IS_ARRAY) {
zend_hash_move_forward(Z_ARRVAL_P(replace));
}
@@ -3887,13 +3679,13 @@ static void php_str_replace_in_subject(zval *search, zval *replace, zval **subje
/* If replace is an array. */
if (Z_TYPE_P(replace) == IS_ARRAY) {
/* Get current entry */
- if (zend_hash_get_current_data(Z_ARRVAL_P(replace), (void **)&replace_entry) == SUCCESS) {
+ if ((replace_entry = zend_hash_get_current_data(Z_ARRVAL_P(replace))) != NULL) {
/* Make sure we're dealing with strings. */
convert_to_string_ex(replace_entry);
/* Set replacement value to the one we got from array */
- replace_value = Z_STRVAL_PP(replace_entry);
- replace_len = Z_STRLEN_PP(replace_entry);
+ replace_value = Z_STRVAL_P(replace_entry);
+ replace_len = Z_STRLEN_P(replace_entry);
zend_hash_move_forward(Z_ARRVAL_P(replace));
} else {
@@ -3903,35 +3695,34 @@ static void php_str_replace_in_subject(zval *search, zval *replace, zval **subje
}
}
- if (Z_STRLEN_PP(search_entry) == 1) {
+ if (Z_STRLEN_P(search_entry) == 1) {
php_char_to_str_ex(Z_STRVAL_P(result),
Z_STRLEN_P(result),
- Z_STRVAL_PP(search_entry)[0],
+ Z_STRVAL_P(search_entry)[0],
replace_value,
replace_len,
&temp_result,
case_sensitivity,
replace_count);
- } else if (Z_STRLEN_PP(search_entry) > 1) {
- Z_STRVAL(temp_result) = php_str_to_str_ex(Z_STRVAL_P(result), Z_STRLEN_P(result),
- Z_STRVAL_PP(search_entry), Z_STRLEN_PP(search_entry),
- replace_value, replace_len, &Z_STRLEN(temp_result), case_sensitivity, replace_count);
+ } else if (Z_STRLEN_P(search_entry) > 1) {
+ ZVAL_STR(&temp_result, php_str_to_str_ex(Z_STRVAL_P(result), Z_STRLEN_P(result),
+ Z_STRVAL_P(search_entry), Z_STRLEN_P(search_entry),
+ replace_value, replace_len, case_sensitivity, replace_count));
}
- str_efree(Z_STRVAL_P(result));
- Z_STRVAL_P(result) = Z_STRVAL(temp_result);
- Z_STRLEN_P(result) = Z_STRLEN(temp_result);
+ STR_FREE(Z_STR_P(result));
+ Z_STR_P(result) = Z_STR(temp_result);
+ Z_TYPE_INFO_P(result) = Z_TYPE_INFO(temp_result);
if (Z_STRLEN_P(result) == 0) {
+ zval_ptr_dtor(&tmp_subject);
return;
}
-
- zend_hash_move_forward(Z_ARRVAL_P(search));
- }
+ } ZEND_HASH_FOREACH_END();
} else {
if (Z_STRLEN_P(search) == 1) {
- php_char_to_str_ex(Z_STRVAL_PP(subject),
- Z_STRLEN_PP(subject),
+ php_char_to_str_ex(Z_STRVAL_P(subject),
+ Z_STRLEN_P(subject),
Z_STRVAL_P(search)[0],
Z_STRVAL_P(replace),
Z_STRLEN_P(replace),
@@ -3939,13 +3730,14 @@ static void php_str_replace_in_subject(zval *search, zval *replace, zval **subje
case_sensitivity,
replace_count);
} else if (Z_STRLEN_P(search) > 1) {
- Z_STRVAL_P(result) = php_str_to_str_ex(Z_STRVAL_PP(subject), Z_STRLEN_PP(subject),
- Z_STRVAL_P(search), Z_STRLEN_P(search),
- Z_STRVAL_P(replace), Z_STRLEN_P(replace), &Z_STRLEN_P(result), case_sensitivity, replace_count);
+ ZVAL_STR(result, php_str_to_str_ex(Z_STRVAL_P(subject), Z_STRLEN_P(subject),
+ Z_STRVAL_P(search), Z_STRLEN_P(search),
+ Z_STRVAL_P(replace), Z_STRLEN_P(replace), case_sensitivity, replace_count));
} else {
- MAKE_COPY_ZVAL(subject, result);
+ ZVAL_DUP(result, subject);
}
}
+ zval_ptr_dtor(&tmp_subject);
}
/* }}} */
@@ -3953,67 +3745,55 @@ static void php_str_replace_in_subject(zval *search, zval *replace, zval **subje
*/
static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, int case_sensitivity)
{
- zval **subject, **search, **replace, **subject_entry, **zcount = NULL;
- zval *result;
- char *string_key;
- uint string_key_len;
+ zval *subject, *search, *replace, *subject_entry, *zcount = NULL;
+ zval result;
+ zend_string *string_key;
ulong num_key;
int count = 0;
int argc = ZEND_NUM_ARGS();
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ|Z", &search, &replace, &subject, &zcount) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzz|z", &search, &replace, &subject, &zcount) == FAILURE) {
return;
}
- SEPARATE_ZVAL(search);
- SEPARATE_ZVAL(replace);
- SEPARATE_ZVAL(subject);
-
/* Make sure we're dealing with strings and do the replacement. */
- if (Z_TYPE_PP(search) != IS_ARRAY) {
+ if (Z_TYPE_P(search) != IS_ARRAY) {
+ SEPARATE_ZVAL(search);
convert_to_string_ex(search);
- convert_to_string_ex(replace);
- } else if (Z_TYPE_PP(replace) != IS_ARRAY) {
+ if (Z_TYPE_P(replace) != IS_STRING) {
+ convert_to_string_ex(replace);
+ SEPARATE_ZVAL(replace);
+ }
+ } else if (Z_TYPE_P(replace) != IS_ARRAY) {
+ SEPARATE_ZVAL(replace);
convert_to_string_ex(replace);
}
/* if subject is an array */
- if (Z_TYPE_PP(subject) == IS_ARRAY) {
+ if (Z_TYPE_P(subject) == IS_ARRAY) {
array_init(return_value);
- zend_hash_internal_pointer_reset(Z_ARRVAL_PP(subject));
/* For each subject entry, convert it to string, then perform replacement
and add the result to the return_value array. */
- while (zend_hash_get_current_data(Z_ARRVAL_PP(subject), (void **)&subject_entry) == SUCCESS) {
- if (Z_TYPE_PP(subject_entry) != IS_ARRAY && Z_TYPE_PP(subject_entry) != IS_OBJECT) {
- MAKE_STD_ZVAL(result);
- SEPARATE_ZVAL(subject_entry);
- php_str_replace_in_subject(*search, *replace, subject_entry, result, case_sensitivity, (argc > 3) ? &count : NULL);
+ ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(subject), num_key, string_key, subject_entry) {
+ if (Z_TYPE_P(subject_entry) != IS_ARRAY && Z_TYPE_P(subject_entry) != IS_OBJECT) {
+ php_str_replace_in_subject(search, replace, subject_entry, &result, case_sensitivity, (argc > 3) ? &count : NULL TSRMLS_CC);
} else {
- ALLOC_ZVAL(result);
- Z_ADDREF_P(*subject_entry);
- COPY_PZVAL_TO_ZVAL(*result, *subject_entry);
+ ZVAL_COPY(&result, subject_entry);
}
/* Add to return array */
- switch (zend_hash_get_current_key_ex(Z_ARRVAL_PP(subject), &string_key,
- &string_key_len, &num_key, 0, NULL)) {
- case HASH_KEY_IS_STRING:
- add_assoc_zval_ex(return_value, string_key, string_key_len, result);
- break;
-
- case HASH_KEY_IS_LONG:
- add_index_zval(return_value, num_key, result);
- break;
+ if (string_key) {
+ zend_hash_update(Z_ARRVAL_P(return_value), string_key, &result);
+ } else {
+ add_index_zval(return_value, num_key, &result);
}
-
- zend_hash_move_forward(Z_ARRVAL_PP(subject));
- }
+ } ZEND_HASH_FOREACH_END();
} else { /* if subject is not an array */
- php_str_replace_in_subject(*search, *replace, subject, return_value, case_sensitivity, (argc > 3) ? &count : NULL);
+ php_str_replace_in_subject(search, replace, subject, return_value, case_sensitivity, (argc > 3) ? &count : NULL TSRMLS_CC);
}
if (argc > 3) {
- zval_dtor(*zcount);
- ZVAL_LONG(*zcount, count);
+ zval_dtor(Z_REFVAL_P(zcount));
+ ZVAL_LONG(Z_REFVAL_P(zcount), count);
}
}
/* }}} */
@@ -4042,11 +3822,12 @@ PHP_FUNCTION(str_ireplace)
static void php_hebrev(INTERNAL_FUNCTION_PARAMETERS, int convert_newlines)
{
char *str;
- char *heb_str, *tmp, *target, *broken_str;
+ char *heb_str, *tmp, *target;
int block_start, block_end, block_type, block_length, i;
long max_chars=0;
int begin, end, char_count, orig_begin;
int str_len;
+ zend_string *broken_str;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &str, &str_len, &max_chars) == FAILURE) {
return;
@@ -4138,9 +3919,9 @@ static void php_hebrev(INTERNAL_FUNCTION_PARAMETERS, int convert_newlines)
} while (block_end < str_len-1);
- broken_str = (char *) emalloc(str_len+1);
- begin=end=str_len-1;
- target = broken_str;
+ broken_str = STR_ALLOC(str_len, 0);
+ begin = end = str_len-1;
+ target = broken_str->val;
while (1) {
char_count=0;
@@ -4197,12 +3978,10 @@ static void php_hebrev(INTERNAL_FUNCTION_PARAMETERS, int convert_newlines)
efree(heb_str);
if (convert_newlines) {
- php_char_to_str(broken_str, str_len,'\n', "<br />\n", 7, return_value);
- efree(broken_str);
+ php_char_to_str(broken_str->val, broken_str->len,'\n', "<br />\n", 7, return_value);
+ STR_FREE(broken_str);
} else {
- Z_STRVAL_P(return_value) = broken_str;
- Z_STRLEN_P(return_value) = str_len;
- Z_TYPE_P(return_value) = IS_STRING;
+ RETURN_NEW_STR(broken_str);
}
}
/* }}} */
@@ -4228,12 +4007,12 @@ PHP_FUNCTION(hebrevc)
PHP_FUNCTION(nl2br)
{
/* in brief this inserts <br /> or <br> before matched regexp \n\r?|\r\n? */
- char *tmp, *str;
- int new_length;
- char *end, *target;
+ char *tmp, *str;
+ char *end, *target;
int repl_cnt = 0;
int str_len;
zend_bool is_xhtml = 1;
+ zend_string *result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &str, &str_len, &is_xhtml) == FAILURE) {
return;
@@ -4261,14 +4040,14 @@ PHP_FUNCTION(nl2br)
}
if (repl_cnt == 0) {
- RETURN_STRINGL(str, str_len, 1);
+ RETURN_STRINGL(str, str_len);
}
{
size_t repl_len = is_xhtml ? (sizeof("<br />") - 1) : (sizeof("<br>") - 1);
- new_length = str_len + repl_cnt * repl_len;
- tmp = target = safe_emalloc(repl_cnt, repl_len, str_len + 1);
+ result = STR_ALLOC(repl_cnt * repl_len + str_len, 0);
+ target = result->val;
}
while (str < end) {
@@ -4299,7 +4078,7 @@ PHP_FUNCTION(nl2br)
*target = '\0';
- RETURN_STRINGL(tmp, new_length, 0);
+ RETURN_NEW_STR(result);
}
/* }}} */
@@ -4307,28 +4086,38 @@ PHP_FUNCTION(nl2br)
Strips HTML and PHP tags from a string */
PHP_FUNCTION(strip_tags)
{
- char *buf;
+ zend_string *buf;
char *str;
- zval **allow=NULL;
+ zval *allow=NULL;
char *allowed_tags=NULL;
int allowed_tags_len=0;
int str_len;
- size_t retval_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|Z", &str, &str_len, &allow) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &str, &str_len, &allow) == FAILURE) {
return;
}
/* To maintain a certain BC, we allow anything for the second parameter and return original string */
if (allow != NULL) {
convert_to_string_ex(allow);
- allowed_tags = Z_STRVAL_PP(allow);
- allowed_tags_len = Z_STRLEN_PP(allow);
+// TODO: reimplement to avoid reallocation ???
+ if (IS_INTERNED(Z_STR_P(allow))) {
+ allowed_tags = estrndup(Z_STRVAL_P(allow), Z_STRLEN_P(allow));
+ allowed_tags_len = Z_STRLEN_P(allow);
+ } else {
+ allowed_tags = Z_STRVAL_P(allow);
+ allowed_tags_len = Z_STRLEN_P(allow);
+ }
}
- buf = estrndup(str, str_len);
- retval_len = php_strip_tags_ex(buf, str_len, NULL, allowed_tags, allowed_tags_len, 0);
- RETURN_STRINGL(buf, retval_len, 0);
+ buf = STR_INIT(str, str_len, 0);
+ buf->len = php_strip_tags_ex(buf->val, str_len, NULL, allowed_tags, allowed_tags_len, 0);
+
+// TODO: reimplement to avoid reallocation ???
+ if (allow && IS_INTERNED(Z_STR_P(allow))) {
+ efree(allowed_tags);
+ }
+ RETURN_STR(buf);
}
/* }}} */
@@ -4336,27 +4125,28 @@ PHP_FUNCTION(strip_tags)
Set locale information */
PHP_FUNCTION(setlocale)
{
- zval ***args = NULL;
- zval **pcategory, **plocale;
+ zval *args = NULL;
+ zval *pcategory, *plocale;
int num_args, cat, i = 0;
char *loc, *retval;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z+", &pcategory, &args, &num_args) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z+", &pcategory, &args, &num_args) == FAILURE) {
return;
}
#ifdef HAVE_SETLOCALE
- if (Z_TYPE_PP(pcategory) == IS_LONG) {
- convert_to_long_ex(pcategory);
- cat = Z_LVAL_PP(pcategory);
+ if (Z_TYPE_P(pcategory) == IS_LONG) {
+ cat = Z_LVAL_P(pcategory);
} else {
/* FIXME: The following behaviour should be removed. */
char *category;
+ zval tmp;
php_error_docref(NULL TSRMLS_CC, E_DEPRECATED, "Passing locale category name as string is deprecated. Use the LC_* -constants instead");
- convert_to_string_ex(pcategory);
- category = Z_STRVAL_PP(pcategory);
+ ZVAL_DUP(&tmp, pcategory);
+ convert_to_string_ex(&tmp);
+ category = Z_STRVAL(tmp);
if (!strcasecmp("LC_ALL", category)) {
cat = LC_ALL;
@@ -4377,35 +4167,39 @@ PHP_FUNCTION(setlocale)
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid locale category name %s, must be one of LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, or LC_TIME", category);
- if (args) {
- efree(args);
- }
+ zval_dtor(&tmp);
RETURN_FALSE;
}
+ zval_dtor(&tmp);
}
- if (Z_TYPE_PP(args[0]) == IS_ARRAY) {
- zend_hash_internal_pointer_reset(Z_ARRVAL_PP(args[0]));
+ if (Z_TYPE(args[0]) == IS_ARRAY) {
+ zend_hash_internal_pointer_reset(Z_ARRVAL(args[0]));
}
while (1) {
- if (Z_TYPE_PP(args[0]) == IS_ARRAY) {
- if (!zend_hash_num_elements(Z_ARRVAL_PP(args[0]))) {
+ zval tmp;
+ if (Z_TYPE(args[0]) == IS_ARRAY) {
+ if (!zend_hash_num_elements(Z_ARRVAL(args[0]))) {
+ break;
+ }
+ if ((plocale = zend_hash_get_current_data(Z_ARRVAL(args[0]))) == NULL) {
break;
}
- zend_hash_get_current_data(Z_ARRVAL_PP(args[0]), (void **)&plocale);
} else {
- plocale = args[i];
+ plocale = &args[i];
}
- convert_to_string_ex(plocale);
+ ZVAL_DUP(&tmp, plocale);
+ convert_to_string(&tmp);
- if (!strcmp ("0", Z_STRVAL_PP(plocale))) {
+ if (!strcmp ("0", Z_STRVAL(tmp))) {
loc = NULL;
} else {
- loc = Z_STRVAL_PP(plocale);
- if (Z_STRLEN_PP(plocale) >= 255) {
+ loc = Z_STRVAL(tmp);
+ if (Z_STRLEN(tmp) >= 255) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Specified locale name is too long");
+ zval_dtor(&tmp);
break;
}
}
@@ -4415,27 +4209,26 @@ PHP_FUNCTION(setlocale)
if (retval) {
/* Remember if locale was changed */
if (loc) {
- STR_FREE(BG(locale_string));
+//??? STR_FREE(BG(locale_string));
+ if (BG(locale_string)) {
+ efree(BG(locale_string));
+ }
BG(locale_string) = estrdup(retval);
}
- if (args) {
- efree(args);
- }
- RETURN_STRING(retval, 1);
+ zval_dtor(&tmp);
+ RETURN_STRING(retval);
}
+ zval_dtor(&tmp);
- if (Z_TYPE_PP(args[0]) == IS_ARRAY) {
- if (zend_hash_move_forward(Z_ARRVAL_PP(args[0])) == FAILURE) break;
+ if (Z_TYPE(args[0]) == IS_ARRAY) {
+ if (zend_hash_move_forward(Z_ARRVAL(args[0])) == FAILURE) break;
} else {
if (++i >= num_args) break;
}
}
#endif
- if (args) {
- efree(args);
- }
RETURN_FALSE;
}
/* }}} */
@@ -4461,7 +4254,7 @@ PHP_FUNCTION(parse_str)
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
}
- Z_ARRVAL(tmp) = EG(active_symbol_table);
+ ZVAL_ARR(&tmp, EG(active_symbol_table));
sapi_module.treat_data(PARSE_STRING, res, &tmp TSRMLS_CC);
} else {
zval ret;
@@ -4469,6 +4262,7 @@ PHP_FUNCTION(parse_str)
array_init(&ret);
sapi_module.treat_data(PARSE_STRING, res, &ret TSRMLS_CC);
/* Clear out the array that was passed in. */
+ ZVAL_DEREF(arrayArg);
zval_dtor(arrayArg);
ZVAL_COPY_VALUE(arrayArg, &ret);
}
@@ -4584,12 +4378,12 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow,
rp = rbuf;
br = 0;
if (allow) {
- if (IS_INTERNED(allow)) {
- allow_free = allow = zend_str_tolower_dup(allow, allow_len);
- } else {
+//??? if (IS_INTERNED(allow)) {
+//??? allow_free = allow = zend_str_tolower_dup(allow, allow_len);
+//??? } else {
allow_free = NULL;
php_strtolower(allow, allow_len);
- }
+//??? }
tbuf = emalloc(PHP_TAG_BUF_SIZE + 1);
tp = tbuf;
} else {
@@ -4869,7 +4663,7 @@ PHP_FUNCTION(str_repeat)
char *input_str; /* Input string */
int input_len;
long mult; /* Multiplier */
- char *result; /* Resulting string */
+ zend_string *result; /* Resulting string */
size_t result_len; /* Length of the resulting string */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &input_str, &input_len, &mult) == FAILURE) {
@@ -4887,19 +4681,19 @@ PHP_FUNCTION(str_repeat)
RETURN_EMPTY_STRING();
/* Initialize the result string */
+ result = STR_SAFE_ALLOC(input_len, mult, 0, 0);
result_len = input_len * mult;
- result = (char *)safe_emalloc(input_len, mult, 1);
/* Heavy optimization for situations where input string is 1 byte long */
if (input_len == 1) {
- memset(result, *(input_str), mult);
+ memset(result->val, *(input_str), mult);
} else {
char *s, *e, *ee;
int l=0;
- memcpy(result, input_str, input_len);
- s = result;
- e = result + input_len;
- ee = result + result_len;
+ memcpy(result->val, input_str, input_len);
+ s = result->val;
+ e = result->val + input_len;
+ ee = result->val + result_len;
while (e<ee) {
l = (e-s) < (ee-e) ? (e-s) : (ee-e);
@@ -4908,9 +4702,9 @@ PHP_FUNCTION(str_repeat)
}
}
- result[result_len] = '\0';
+ result->val[result_len] = '\0';
- RETURN_STRINGL(result, result_len, 0);
+ RETURN_NEW_STR(result);
}
/* }}} */
@@ -4977,7 +4771,7 @@ PHP_FUNCTION(count_chars)
}
if (mymode >= 3 && mymode <= 4) {
- RETURN_STRINGL(retstr, retlen, 1);
+ RETURN_STRINGL(retstr, retlen);
}
}
/* }}} */
@@ -5001,31 +4795,13 @@ static void php_strnatcmp(INTERNAL_FUNCTION_PARAMETERS, int fold_case)
PHPAPI int string_natural_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive TSRMLS_DC) /* {{{ */
{
- zval op1_copy, op2_copy;
- int use_copy1 = 0, use_copy2 = 0;
-
- if (Z_TYPE_P(op1) != IS_STRING) {
- zend_make_printable_zval(op1, &op1_copy, &use_copy1);
- }
- if (Z_TYPE_P(op2) != IS_STRING) {
- zend_make_printable_zval(op2, &op2_copy, &use_copy2);
- }
-
- if (use_copy1) {
- op1 = &op1_copy;
- }
- if (use_copy2) {
- op2 = &op2_copy;
- }
+ zend_string *str1 = zval_get_string(op1);
+ zend_string *str2 = zval_get_string(op2);
- ZVAL_LONG(result, strnatcmp_ex(Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2), case_insensitive));
+ ZVAL_LONG(result, strnatcmp_ex(str1->val, str1->len, str2->val, str2->len, case_insensitive));
- if (use_copy1) {
- zval_dtor(op1);
- }
- if (use_copy2) {
- zval_dtor(op2);
- }
+ STR_RELEASE(str1);
+ STR_RELEASE(str2);
return SUCCESS;
}
/* }}} */
@@ -5054,7 +4830,7 @@ PHP_FUNCTION(strnatcmp)
Returns numeric formatting information based on the current locale */
PHP_FUNCTION(localeconv)
{
- zval *grouping, *mon_grouping;
+ zval grouping, mon_grouping;
int len, i;
/* We don't need no stinkin' parameters... */
@@ -5062,12 +4838,9 @@ PHP_FUNCTION(localeconv)
return;
}
- MAKE_STD_ZVAL(grouping);
- MAKE_STD_ZVAL(mon_grouping);
-
array_init(return_value);
- array_init(grouping);
- array_init(mon_grouping);
+ array_init(&grouping);
+ array_init(&mon_grouping);
#ifdef HAVE_LOCALECONV
{
@@ -5079,60 +4852,60 @@ PHP_FUNCTION(localeconv)
len = strlen(currlocdata.grouping);
for (i = 0; i < len; i++) {
- add_index_long(grouping, i, currlocdata.grouping[i]);
+ add_index_long(&grouping, i, currlocdata.grouping[i]);
}
/* Grab the monetary grouping data out of the array */
len = strlen(currlocdata.mon_grouping);
for (i = 0; i < len; i++) {
- add_index_long(mon_grouping, i, currlocdata.mon_grouping[i]);
- }
-
- add_assoc_string(return_value, "decimal_point", currlocdata.decimal_point, 1);
- add_assoc_string(return_value, "thousands_sep", currlocdata.thousands_sep, 1);
- add_assoc_string(return_value, "int_curr_symbol", currlocdata.int_curr_symbol, 1);
- add_assoc_string(return_value, "currency_symbol", currlocdata.currency_symbol, 1);
- add_assoc_string(return_value, "mon_decimal_point", currlocdata.mon_decimal_point, 1);
- add_assoc_string(return_value, "mon_thousands_sep", currlocdata.mon_thousands_sep, 1);
- add_assoc_string(return_value, "positive_sign", currlocdata.positive_sign, 1);
- add_assoc_string(return_value, "negative_sign", currlocdata.negative_sign, 1);
- add_assoc_long( return_value, "int_frac_digits", currlocdata.int_frac_digits );
- add_assoc_long( return_value, "frac_digits", currlocdata.frac_digits );
- add_assoc_long( return_value, "p_cs_precedes", currlocdata.p_cs_precedes );
- add_assoc_long( return_value, "p_sep_by_space", currlocdata.p_sep_by_space );
- add_assoc_long( return_value, "n_cs_precedes", currlocdata.n_cs_precedes );
- add_assoc_long( return_value, "n_sep_by_space", currlocdata.n_sep_by_space );
- add_assoc_long( return_value, "p_sign_posn", currlocdata.p_sign_posn );
- add_assoc_long( return_value, "n_sign_posn", currlocdata.n_sign_posn );
+ add_index_long(&mon_grouping, i, currlocdata.mon_grouping[i]);
+ }
+
+ add_assoc_string(return_value, "decimal_point", currlocdata.decimal_point);
+ add_assoc_string(return_value, "thousands_sep", currlocdata.thousands_sep);
+ add_assoc_string(return_value, "int_curr_symbol", currlocdata.int_curr_symbol);
+ add_assoc_string(return_value, "currency_symbol", currlocdata.currency_symbol);
+ add_assoc_string(return_value, "mon_decimal_point", currlocdata.mon_decimal_point);
+ add_assoc_string(return_value, "mon_thousands_sep", currlocdata.mon_thousands_sep);
+ add_assoc_string(return_value, "positive_sign", currlocdata.positive_sign);
+ add_assoc_string(return_value, "negative_sign", currlocdata.negative_sign);
+ add_assoc_long( return_value, "int_frac_digits", currlocdata.int_frac_digits);
+ add_assoc_long( return_value, "frac_digits", currlocdata.frac_digits);
+ add_assoc_long( return_value, "p_cs_precedes", currlocdata.p_cs_precedes);
+ add_assoc_long( return_value, "p_sep_by_space", currlocdata.p_sep_by_space);
+ add_assoc_long( return_value, "n_cs_precedes", currlocdata.n_cs_precedes);
+ add_assoc_long( return_value, "n_sep_by_space", currlocdata.n_sep_by_space);
+ add_assoc_long( return_value, "p_sign_posn", currlocdata.p_sign_posn);
+ add_assoc_long( return_value, "n_sign_posn", currlocdata.n_sign_posn);
}
#else
/* Ok, it doesn't look like we have locale info floating around, so I guess it
wouldn't hurt to just go ahead and return the POSIX locale information? */
- add_index_long(grouping, 0, -1);
- add_index_long(mon_grouping, 0, -1);
-
- add_assoc_string(return_value, "decimal_point", "\x2E", 1);
- add_assoc_string(return_value, "thousands_sep", "", 1);
- add_assoc_string(return_value, "int_curr_symbol", "", 1);
- add_assoc_string(return_value, "currency_symbol", "", 1);
- add_assoc_string(return_value, "mon_decimal_point", "\x2E", 1);
- add_assoc_string(return_value, "mon_thousands_sep", "", 1);
- add_assoc_string(return_value, "positive_sign", "", 1);
- add_assoc_string(return_value, "negative_sign", "", 1);
- add_assoc_long( return_value, "int_frac_digits", CHAR_MAX );
- add_assoc_long( return_value, "frac_digits", CHAR_MAX );
- add_assoc_long( return_value, "p_cs_precedes", CHAR_MAX );
- add_assoc_long( return_value, "p_sep_by_space", CHAR_MAX );
- add_assoc_long( return_value, "n_cs_precedes", CHAR_MAX );
- add_assoc_long( return_value, "n_sep_by_space", CHAR_MAX );
- add_assoc_long( return_value, "p_sign_posn", CHAR_MAX );
- add_assoc_long( return_value, "n_sign_posn", CHAR_MAX );
+ add_index_long(&grouping, 0, -1);
+ add_index_long(&mon_grouping, 0, -1);
+
+ add_assoc_string(return_value, "decimal_point", "\x2E");
+ add_assoc_string(return_value, "thousands_sep", "");
+ add_assoc_string(return_value, "int_curr_symbol", "");
+ add_assoc_string(return_value, "currency_symbol", "");
+ add_assoc_string(return_value, "mon_decimal_point", "\x2E");
+ add_assoc_string(return_value, "mon_thousands_sep", "");
+ add_assoc_string(return_value, "positive_sign", "");
+ add_assoc_string(return_value, "negative_sign", "");
+ add_assoc_long( return_value, "int_frac_digits", CHAR_MAX);
+ add_assoc_long( return_value, "frac_digits", CHAR_MAX);
+ add_assoc_long( return_value, "p_cs_precedes", CHAR_MAX);
+ add_assoc_long( return_value, "p_sep_by_space", CHAR_MAX);
+ add_assoc_long( return_value, "n_cs_precedes", CHAR_MAX);
+ add_assoc_long( return_value, "n_sep_by_space", CHAR_MAX);
+ add_assoc_long( return_value, "p_sign_posn", CHAR_MAX);
+ add_assoc_long( return_value, "n_sign_posn", CHAR_MAX);
#endif
- zend_hash_update(Z_ARRVAL_P(return_value), "grouping", 9, &grouping, sizeof(zval *), NULL);
- zend_hash_update(Z_ARRVAL_P(return_value), "mon_grouping", 13, &mon_grouping, sizeof(zval *), NULL);
+ zend_hash_str_update(Z_ARRVAL_P(return_value), "grouping", sizeof("grouping")-1, &grouping);
+ zend_hash_str_update(Z_ARRVAL_P(return_value), "mon_grouping", sizeof("mon_grouping")-1, &mon_grouping);
}
/* }}} */
@@ -5199,7 +4972,7 @@ PHP_FUNCTION(substr_count)
p++;
}
} else {
- while ((p = php_memnstr(p, needle, needle_len, endp))) {
+ while ((p = (char*)php_memnstr(p, needle, needle_len, endp))) {
p += needle_len;
count++;
}
@@ -5219,13 +4992,12 @@ PHP_FUNCTION(str_pad)
long pad_length; /* Length to pad to */
/* Helper variables */
- size_t num_pad_chars; /* Number of padding characters (total - input size) */
- char *result = NULL; /* Resulting string */
- int result_len = 0; /* Length of the resulting string */
+ size_t num_pad_chars; /* Number of padding characters (total - input size) */
char *pad_str_val = " "; /* Pointer to padding string */
int pad_str_len = 1; /* Length of the padding string */
long pad_type_val = STR_PAD_RIGHT; /* The padding type value */
int i, left_pad=0, right_pad=0;
+ zend_string *result = NULL; /* Resulting string */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|sl", &input, &input_len, &pad_length,
&pad_str_val, &pad_str_len, &pad_type_val) == FAILURE) {
@@ -5235,7 +5007,7 @@ PHP_FUNCTION(str_pad)
/* If resulting string turns out to be shorter than input string,
we simply copy the input and return. */
if (pad_length <= 0 || (pad_length - input_len) <= 0) {
- RETURN_STRINGL(input, input_len, 1);
+ RETURN_STRINGL(input, input_len);
}
if (pad_str_len == 0) {
@@ -5253,7 +5025,9 @@ PHP_FUNCTION(str_pad)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Padding length is too long");
return;
}
- result = (char *)emalloc(input_len + num_pad_chars + 1);
+
+ result = STR_ALLOC(input_len + num_pad_chars, 0);
+ result->len = 0;
/* We need to figure out the left/right padding lengths. */
switch (pad_type_val) {
@@ -5275,19 +5049,19 @@ PHP_FUNCTION(str_pad)
/* First we pad on the left. */
for (i = 0; i < left_pad; i++)
- result[result_len++] = pad_str_val[i % pad_str_len];
+ result->val[result->len++] = pad_str_val[i % pad_str_len];
/* Then we copy the input string. */
- memcpy(result + result_len, input, input_len);
- result_len += input_len;
+ memcpy(result->val + result->len, input, input_len);
+ result->len += input_len;
/* Finally, we pad on the right. */
for (i = 0; i < right_pad; i++)
- result[result_len++] = pad_str_val[i % pad_str_len];
+ result->val[result->len++] = pad_str_val[i % pad_str_len];
- result[result_len] = '\0';
+ result->val[result->len] = '\0';
- RETURN_STRINGL(result, result_len, 0);
+ RETURN_NEW_STR(result);
}
/* }}} */
@@ -5295,7 +5069,7 @@ PHP_FUNCTION(str_pad)
Implements an ANSI C compatible sscanf */
PHP_FUNCTION(sscanf)
{
- zval ***args = NULL;
+ zval *args = NULL;
char *str, *format;
int str_len, format_len, result, num_args = 0;
@@ -5304,11 +5078,7 @@ PHP_FUNCTION(sscanf)
return;
}
- result = php_sscanf_internal(str, format, num_args, args, 0, &return_value TSRMLS_CC);
-
- if (args) {
- efree(args);
- }
+ result = php_sscanf_internal(str, format, num_args, args, 0, return_value TSRMLS_CC);
if (SCAN_ERROR_WRONG_PARAM_COUNT == result) {
WRONG_PARAM_COUNT;
@@ -5330,7 +5100,7 @@ PHP_FUNCTION(str_rot13)
return;
}
- RETVAL_STRINGL(arg, arglen, 1);
+ RETVAL_STRINGL(arg, arglen);
php_strtr(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value), rot13_from, rot13_to, 52);
}
@@ -5373,7 +5143,7 @@ PHP_FUNCTION(str_shuffle)
return;
}
- RETVAL_STRINGL(arg, arglen, 1);
+ RETVAL_STRINGL(arg, arglen);
if (Z_STRLEN_P(return_value) > 1) {
php_string_shuffle(Z_STRVAL_P(return_value), (long) Z_STRLEN_P(return_value) TSRMLS_CC);
}
@@ -5393,7 +5163,7 @@ PHP_FUNCTION(str_shuffle)
*/
PHP_FUNCTION(str_word_count)
{
- char *buf, *str, *char_list = NULL, *p, *e, *s, ch[256];
+ char *str, *char_list = NULL, *p, *e, *s, ch[256];
int str_len, char_list_len = 0, word_count = 0;
long type = 0;
@@ -5445,12 +5215,10 @@ PHP_FUNCTION(str_word_count)
switch (type)
{
case 1:
- buf = estrndup(s, (p-s));
- add_next_index_stringl(return_value, buf, (p-s), 0);
+ add_next_index_stringl(return_value, s, p - s);
break;
case 2:
- buf = estrndup(s, (p-s));
- add_index_stringl(return_value, (s - str), buf, p-s, 0);
+ add_index_stringl(return_value, (s - str), s, p - s);
break;
default:
word_count++;
@@ -5472,10 +5240,11 @@ PHP_FUNCTION(str_word_count)
Convert monetary value(s) to string */
PHP_FUNCTION(money_format)
{
- int format_len = 0, str_len;
- char *format, *str, *p, *e;
+ int format_len = 0;
+ char *format, *p, *e;
double value;
zend_bool check = 0;
+ zend_string *str;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sd", &format, &format_len, &value) == FAILURE) {
return;
@@ -5495,15 +5264,14 @@ PHP_FUNCTION(money_format)
}
}
- str_len = format_len + 1024;
- str = emalloc(str_len);
- if ((str_len = strfmon(str, str_len, format, value)) < 0) {
- efree(str);
+ str = STR_ALLOC(format_len + 1024, 0);
+ if ((str->len = strfmon(str->val, str->len, format, value)) < 0) {
+ STR_FREE(str);
RETURN_FALSE;
}
- str[str_len] = 0;
+ str->val[str->len] = '\0';
- RETURN_STRINGL(erealloc(str, str_len + 1), str_len, 0);
+ RETURN_NEW_STR(STR_REALLOC(str, str->len, 0));
}
/* }}} */
#endif
@@ -5530,7 +5298,7 @@ PHP_FUNCTION(str_split)
array_init_size(return_value, ((str_len - 1) / split_length) + 1);
if (split_length >= str_len) {
- add_next_index_stringl(return_value, str, str_len, 1);
+ add_next_index_stringl(return_value, str, str_len);
return;
}
@@ -5538,12 +5306,12 @@ PHP_FUNCTION(str_split)
p = str;
while (n_reg_segments-- > 0) {
- add_next_index_stringl(return_value, p, split_length, 1);
+ add_next_index_stringl(return_value, p, split_length);
p += split_length;
}
if (p != (str + str_len)) {
- add_next_index_stringl(return_value, p, (str + str_len - p), 1);
+ add_next_index_stringl(return_value, p, (str + str_len - p));
}
}
/* }}} */
@@ -5568,7 +5336,7 @@ PHP_FUNCTION(strpbrk)
for (haystack_ptr = haystack; haystack_ptr < (haystack + haystack_len); ++haystack_ptr) {
for (cl_ptr = char_list; cl_ptr < (char_list + char_list_len); ++cl_ptr) {
if (*cl_ptr == *haystack_ptr) {
- RETURN_STRINGL(haystack_ptr, (haystack + haystack_len - haystack_ptr), 1);
+ RETURN_STRINGL(haystack_ptr, (haystack + haystack_len - haystack_ptr));
}
}
}