Skip to content

Commit 978a44c

Browse files
committed
Simplify iconv_strpos implementation
Use a separate "reverse" flag to determine search direction, using offset == -1 to indicate this is is confusing. I initially thought the code was trying to handle negative offsets. Also deduplicate the forward and reverse cases, they really only differ in one place.
1 parent 6dd8401 commit 978a44c

File tree

1 file changed

+17
-53
lines changed

1 file changed

+17
-53
lines changed

ext/iconv/iconv.c

Lines changed: 17 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,6 @@ static php_iconv_err_t _php_iconv_strlen(size_t *pretval, const char *str, size_
117117

118118
static php_iconv_err_t _php_iconv_substr(smart_str *pretval, const char *str, size_t nbytes, zend_long offset, zend_long len, const char *enc);
119119

120-
static php_iconv_err_t _php_iconv_strpos(size_t *pretval, const char *haystk, size_t haystk_nbytes, const char *ndl, size_t ndl_nbytes, zend_long offset, const char *enc);
121-
122120
static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fname, size_t fname_nbytes, const char *fval, size_t fval_nbytes, size_t max_line_len, const char *lfchars, php_iconv_enc_scheme_t enc_scheme, const char *out_charset, const char *enc);
123121

124122
static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *str, size_t str_nbytes, const char *enc, const char **next_pos, int mode);
@@ -748,7 +746,7 @@ static php_iconv_err_t _php_iconv_substr(smart_str *pretval,
748746
static php_iconv_err_t _php_iconv_strpos(size_t *pretval,
749747
const char *haystk, size_t haystk_nbytes,
750748
const char *ndl, size_t ndl_nbytes,
751-
zend_long offset, const char *enc)
749+
size_t offset, const char *enc, bool reverse)
752750
{
753751
char buf[GENERIC_SUPERSET_NBYTES];
754752

@@ -829,49 +827,7 @@ static php_iconv_err_t _php_iconv_strpos(size_t *pretval,
829827
break;
830828
}
831829
}
832-
if (offset >= 0) {
833-
if (cnt >= (size_t)offset) {
834-
if (_php_iconv_memequal(buf, ndl_buf_p, sizeof(buf))) {
835-
if (match_ofs == (size_t)-1) {
836-
match_ofs = cnt;
837-
}
838-
ndl_buf_p += GENERIC_SUPERSET_NBYTES;
839-
ndl_buf_left -= GENERIC_SUPERSET_NBYTES;
840-
if (ndl_buf_left == 0) {
841-
*pretval = match_ofs;
842-
break;
843-
}
844-
} else {
845-
size_t i, j, lim;
846-
847-
i = 0;
848-
j = GENERIC_SUPERSET_NBYTES;
849-
lim = (size_t)(ndl_buf_p - ZSTR_VAL(ndl_buf));
850-
851-
while (j < lim) {
852-
if (_php_iconv_memequal(&ZSTR_VAL(ndl_buf)[j], &ZSTR_VAL(ndl_buf)[i],
853-
GENERIC_SUPERSET_NBYTES)) {
854-
i += GENERIC_SUPERSET_NBYTES;
855-
} else {
856-
j -= i;
857-
i = 0;
858-
}
859-
j += GENERIC_SUPERSET_NBYTES;
860-
}
861-
862-
if (_php_iconv_memequal(buf, &ZSTR_VAL(ndl_buf)[i], sizeof(buf))) {
863-
match_ofs += (lim - i) / GENERIC_SUPERSET_NBYTES;
864-
i += GENERIC_SUPERSET_NBYTES;
865-
ndl_buf_p = &ZSTR_VAL(ndl_buf)[i];
866-
ndl_buf_left = ZSTR_LEN(ndl_buf) - i;
867-
} else {
868-
match_ofs = (size_t)-1;
869-
ndl_buf_p = ZSTR_VAL(ndl_buf);
870-
ndl_buf_left = ZSTR_LEN(ndl_buf);
871-
}
872-
}
873-
}
874-
} else {
830+
if (cnt >= offset) {
875831
if (_php_iconv_memequal(buf, ndl_buf_p, sizeof(buf))) {
876832
if (match_ofs == (size_t)-1) {
877833
match_ofs = cnt;
@@ -880,9 +836,15 @@ static php_iconv_err_t _php_iconv_strpos(size_t *pretval,
880836
ndl_buf_left -= GENERIC_SUPERSET_NBYTES;
881837
if (ndl_buf_left == 0) {
882838
*pretval = match_ofs;
883-
ndl_buf_p = ZSTR_VAL(ndl_buf);
884-
ndl_buf_left = ZSTR_LEN(ndl_buf);
885-
match_ofs = -1;
839+
if (reverse) {
840+
/* If searching backward, continue trying to find a later match. */
841+
ndl_buf_p = ZSTR_VAL(ndl_buf);
842+
ndl_buf_left = ZSTR_LEN(ndl_buf);
843+
match_ofs = -1;
844+
} else {
845+
/* If searching forward, stop at first match. */
846+
break;
847+
}
886848
}
887849
} else {
888850
size_t i, j, lim;
@@ -1928,8 +1890,9 @@ PHP_FUNCTION(iconv_strpos)
19281890
RETURN_FALSE;
19291891
}
19301892

1931-
err = _php_iconv_strpos(&retval, ZSTR_VAL(haystk), ZSTR_LEN(haystk), ZSTR_VAL(ndl), ZSTR_LEN(ndl),
1932-
offset, charset);
1893+
err = _php_iconv_strpos(
1894+
&retval, ZSTR_VAL(haystk), ZSTR_LEN(haystk), ZSTR_VAL(ndl), ZSTR_LEN(ndl),
1895+
offset, charset, /* reverse */ false);
19331896
_php_iconv_show_error(err, GENERIC_SUPERSET_NAME, charset);
19341897

19351898
if (err == PHP_ICONV_ERR_SUCCESS && retval != (size_t)-1) {
@@ -1969,8 +1932,9 @@ PHP_FUNCTION(iconv_strrpos)
19691932
RETURN_FALSE;
19701933
}
19711934

1972-
err = _php_iconv_strpos(&retval, ZSTR_VAL(haystk), ZSTR_LEN(haystk), ZSTR_VAL(ndl), ZSTR_LEN(ndl),
1973-
-1, charset);
1935+
err = _php_iconv_strpos(
1936+
&retval, ZSTR_VAL(haystk), ZSTR_LEN(haystk), ZSTR_VAL(ndl), ZSTR_LEN(ndl),
1937+
/* offset */ 0, charset, /* reserve */ true);
19741938
_php_iconv_show_error(err, GENERIC_SUPERSET_NAME, charset);
19751939

19761940
if (err == PHP_ICONV_ERR_SUCCESS && retval != (size_t)-1) {

0 commit comments

Comments
 (0)