最快的重新实现PHP的htmlspecialchars在C中起作用

时间:2015-04-13 07:05:01

标签: php c

我需要C中PHP函数ENT_COMPAT | ENT_HTML401的默认行为(即htmlspecialchars()),这在C中如何做得最好(这意味着最快)?

我不需要输入字符串,因此可以使用就地解决方案。

这是一个非常简单的功能,它只是转换这些字符:

'&' -> '&'
'"' -> '"'
'<' -> '&lt;'
'>' -> '&gt;'

哪种策略最快?单独循环每个字符并逐字节创建输出缓冲区,就地覆盖输入字符串或其他解决方案?

3 个答案:

答案 0 :(得分:1)

此代码假定输入和输出是缓冲区,并且该输入包含输入字符串。它还假设输出缓冲区足够大以容纳输出(如果没有输出被截断):

long i = 0;
long j = 0;

while (input[i])
{
    if (input[i] == '<')
    {
        memcpy(&output[j], "&lt;", 4);
        j += 4;
    } else if (input[i] == '>')
    {
        memcpy(&output[j], "&gt;", 4);
        j += 4;
    } else if (input[i] == '"')
    {
        memcpy(&output[j], "&quot;", 6);
        j += 6;
    } else if (input[i] == '&')
    {
        memcpy(&output[j], "&amp;", 5);
        j += 5;
    } else
    {
        output[j++] = input[i];
    }
    if (j > sizeof(output)-7)
    {
        break;
    }
    i++;
}
output[j] = 0;

在C中,丑陋的代码通常是最快的。

如果要交换的字符非常非常罕见,那么就地解决方案只会产生性能优势,因此整个字符串可以在检测到的每个字符上重新排序(非常昂贵)。对于普通的HTML数据,这些4个字符经常出现,就地解决方案会慢得多。

答案 1 :(得分:1)

您可以构建适用于这两种情况的解决方案:

计算所需的空间并在传递NULL时返回已分配的字符串,否则填充传递的字符串:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static size_t encode_len(const char *str)
{
    size_t len = 0;

    while (*str) {
        if (*str == '"' || *str == '&' || *str == '<' || *str == '>') {
            len += 5;
        } else {
            len += 1;
        }
        str++;
    }
    return len;
}

static char *encode(const char *str, char *dest)
{
    char *ptr;

    if (dest == NULL) {
        dest = malloc(encode_len(str) + 1);
        if (dest == NULL) return NULL;
    }
    ptr = dest; 
    while (*str) {
        switch (*str) {
            case '"': memcpy(ptr, "&#34;", 5); ptr += 5; break;
            case '&': memcpy(ptr, "&#38;", 5); ptr += 5; break;
            case '<': memcpy(ptr, "&#60;", 5); ptr += 5; break;
            case '>': memcpy(ptr, "&#62;", 5); ptr += 5; break;
            default: *ptr++ = *str;
        }
        str++;
    }
    *ptr = *str;
    return dest;
}

int main(void)
{
    /* Returns an allocated string */
    char *str = encode("testing & <> \"", NULL);
    if (str) {
        printf("%s\n", str);
        free(str);
    }

    /* Fills a passed string */
    char str2[128];
    encode("testing & <> \"", str2);
    printf("%s\n", str2);

    return 0;
}

答案 2 :(得分:0)

这是 INT8 函数安全实现。


信息

  • htmlspecialchars 是结果。

  • char *_output 是允许写入 size_t outlen 的最大字节数。

  • _output 是要进行 HTML 转义的字符串。

  • char *_input 是要转义的字符串长度(不包括空终止符)。

此函数返回写入 size_t inlen 的字节数,包括空终止符。

注意:此函数始终将空终止符放在 _output 中。


代码

_output