summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlia Alshanetsky <iliaa@php.net>2005-03-08 21:13:03 +0000
committerIlia Alshanetsky <iliaa@php.net>2005-03-08 21:13:03 +0000
commit0dbe348d1d9a6ffc9df8f6b5f624cc8693d2fed8 (patch)
tree54b720e23e2a28f225018834f68207f371c3b194
parent83dfcbf3f611001c6b21115bbe49ad57e3ea538e (diff)
downloadphp-git-0dbe348d1d9a6ffc9df8f6b5f624cc8693d2fed8.tar.gz
Improve the performance of htmlspecialchars_decode() by 20-30%.
-rw-r--r--ext/standard/html.c69
1 files changed, 45 insertions, 24 deletions
diff --git a/ext/standard/html.c b/ext/standard/html.c
index fa50b5928d..1b9761cbca 100644
--- a/ext/standard/html.c
+++ b/ext/standard/html.c
@@ -469,6 +469,12 @@ static const struct {
{ 0, NULL, 0, 0 }
};
+struct basic_entities_dec {
+ unsigned short charcode;
+ char entity[8];
+ int entitylen;
+};
+
#define MB_RETURN { \
*newpos = pos; \
mbseq[mbpos] = '\0'; \
@@ -1211,8 +1217,9 @@ PHP_FUNCTION(htmlspecialchars)
PHP_FUNCTION(htmlspecialchars_decode)
{
char *str, *new_str, *e, *p;
- int len, i, new_len;
+ int len, j, i, new_len;
long quote_style = ENT_COMPAT;
+ struct basic_entities_dec basic_entities_dec[8];
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &str, &len, &quote_style) == FAILURE) {
return;
@@ -1220,37 +1227,51 @@ PHP_FUNCTION(htmlspecialchars_decode)
new_str = estrndup(str, len);
new_len = len;
+ e = new_str + new_len;
+
+ if (!(p = memchr(new_str, '&', new_len))) {
+ RETURN_STRINGL(new_str, new_len, 0);
+ }
- for (i = 0; basic_entities[i].charcode != 0; i++) {
+ for (j = 0, i = 0; basic_entities[i].charcode != 0; i++) {
if (basic_entities[i].flags && !(quote_style & basic_entities[i].flags)) {
continue;
}
-
- e = new_str + new_len;
- p = new_str;
-
- while ((p = php_memnstr(p, basic_entities[i].entity, basic_entities[i].entitylen, e))) {
- int e_len = basic_entities[i].entitylen - 1;
+ basic_entities_dec[j].charcode = basic_entities[i].charcode;
+ memcpy(basic_entities_dec[j].entity, basic_entities[i].entity, basic_entities[i].entitylen + 1);
+ basic_entities_dec[j].entitylen = basic_entities[i].entitylen;
+ j++;
+ }
+ basic_entities_dec[j].charcode = '&';
+ basic_entities_dec[j].entitylen = sizeof("&amp;") - 1;
+ memcpy(basic_entities_dec[j].entity, "&amp;", sizeof("&amp;"));
+ i = j + 1;
+
+ do {
+ int l = e - p;
+
+ for (j = 0; j < i; j++) {
+ if (basic_entities_dec[j].entitylen > l) {
+ continue;
+ }
+ if (!memcmp(p, basic_entities_dec[j].entity, basic_entities_dec[j].entitylen)) {
+ int e_len = basic_entities_dec[j].entitylen - 1;
- *p++ = basic_entities[i].charcode;
- memmove(p, p + e_len, (e - p - e_len));
-
- new_len -= e_len;
- e -= e_len;
+ *p++ = basic_entities_dec[j].charcode;
+ memmove(p, p + e_len, (e - p - e_len));
+ e -= e_len;
+ goto done;
+ }
}
- }
-
- e = new_str + new_len;
- p = new_str;
- while ((p = php_memnstr(p, "&amp;", sizeof("&amp;") - 1, e))) {
- int e_len = sizeof("&amp;") - 2;
-
p++;
- memmove(p, p + e_len, (e - p - e_len));
- new_len -= e_len;
- e -= e_len;
- }
+done:
+ if (p >= e) {
+ break;
+ }
+ } while ((p = memchr(p, '&', (e - p))));
+
+ new_len = e - new_str;
new_str[new_len] = '\0';
RETURN_STRINGL(new_str, new_len, 0);