Nginx 对字符串编码函数解析

来源:互联网 发布:淘宝新店能做什么活动 编辑:程序博客网 时间:2024/06/05 22:59

Nginx 对字符串编码函数解析

Nginx函数ngx_escape_uri对非普通字符进行编码转换,源码如下:

ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type){    ngx_uint_t      n;    uint32_t       *escape;    static u_char   hex[] = "0123456789ABCDEF";                    /* " ", "#", "%", "?", %00-%1F, %7F-%FF */    static uint32_t   uri[] = {        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */                    /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */        0x80000029, /* 1000 0000 0000 0000  0000 0000 0010 1001 */                    /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */        0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */                    /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */        0x80000000, /* 1000 0000 0000 0000  0000 0000 0000 0000 */        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */        0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */    };    ...    ...    static uint32_t  *map[] =        { uri, args, uri_component, html, refresh, memcached, memcached };    escape = map[type];    if (dst == NULL) {        /* find the number of the characters to be escaped */        n = 0;        while (size) {            if (escape[*src >> 5] & (1U << (*src & 0x1f))) {                n++;            }            src++;            size--;        }        return (uintptr_t) n;    }    while (size) {        if (escape[*src >> 5] & (1U << (*src & 0x1f))) {            *dst++ = '%';            *dst++ = hex[*src >> 4];            *dst++ = hex[*src & 0xf];            src++;        } else {            *dst++ = *src++;        }        size--;    }    return (uintptr_t) dst;}

在上述函数中利用位图来判断是否需要编码,其中static uint32_t uri[]用0和1来表示ASCII码表中的字符是否需要编码,每一位表示一个符号,其中值为1表示此符号需要转换,值为0表示不需要转换。
然后利用(escape[*src >> 5] & (1U << (*src & 0x1f)))来判断字符是否需要编码,这个判断分为两步:一是利用escape[*src >> 5] 获取字符所在的分组,注意到uri[]把256个字符分为8组,每组32个字符,所以利用表示字符的ASCII码右移5位(相当于除以32)即可得到所在分组;二是利用1U << (*src & 0x1f)获取字符在分组中的位置,*src & 0x1f相当于利用表示字符的ASCII码对32取余,然后1左移该余数即可得到字符在分组中的位置,最后根据该位置是0还是1来判断是否需要编码。

0 0
原创粉丝点击