栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

nginx之string

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

nginx之string

一、简介

​ 对于C语言而言,没有String类型,只有char * 和 char [],对于一些操作不便。

字符串是二进制不安全的

在C语言中,操作字符串的API函数都是以’’来作为结束符,而图片或在其他二进制数据中经常会出现’’,这样将导致出现被截断等错误。

获取字符串长度时间复杂度O(N)

​ 在C语言中,获取字符串的长度需要遍历整个字符串。

因此nginx自己实现了String类型,对字符串的封装。相比于redis的SDS,nginx的String更简单一些,毕竟不是将所有数据都存储在内存中,不用对内存的使用精打细算。

涉及到的文件ngx_string.h, ngx_string.c

二、数据结构
typedef struct {
    size_t      len;
    u_char     *data;
} ngx_str_t;

len 表示字符串的长度data表示实际的数据

与redis对比:

    len的类型是固定的size_t类型,这样更简单;而redis根据字符串的长度的不同而使用不同的类型,这样不浪费一点内存,精打细算,减少不必要的内存开销相比与redis的SDS,String中只有一个len字段;而redis还有free,alloc等字段,可以预分配等操作减少向操作系统申请内存的次数;但是nginx使用的是内存池,相比redis直接向操作系统申请资源更有优势
三、相关API 3.1 定义并初始化str
#define ngx_string(str)     { sizeof(str) - 1, (u_char *) str }

比如:

static ngx_str_t ngx_http_gzip_no_cache = ngx_string("no-cache");

3.2 定义空的str

声明并初始化一个空的str

#define ngx_null_string     { 0, NULL }
3.3 对str赋值

首先被赋值的str必须先定义,才能被这里赋值。

#define ngx_str_set(str, text)                                               
    (str)->len = sizeof(text) - 1; (str)->data = (u_char *) text
3.4 清空str

首先被清空的str必须先定义,才能被清空。清空只是设置了空置,并未作释放的操作,看样子是需要调用方处理,或是使用的内存池方式,不需要释放空间。

#define ngx_str_null(str)   (str)->len = 0; (str)->data = NULL
3.5 字符串转小写
#define ngx_tolower(c)      (u_char) ((c >= 'A' && c <= 'Z') ? (c | 0x20) : c)
#define ngx_toupper(c)      (u_char) ((c >= 'a' && c <= 'z') ? (c & ~0x20) : c)

英文大小写字符之间相差32,一般自己实现都是加减32,这里使用了位运算,更高效。32 = 2^6 ,刚好是第6个比特位。

void
ngx_strlow(u_char *dst, u_char *src, size_t n)
{
    while (n) {
        *dst = ngx_tolower(*src);
        dst++;
        src++;
        n--;
    }
}
3.6 字符串比较
#define ngx_strncmp(s1, s2, n)  strncmp((const char *) s1, (const char *) s2, n)

#define ngx_strcmp(s1, s2)  strcmp((const char *) s1, (const char *) s2)

实际上使用的是系统的strncmp/strcmp函数。

3.7 字符串长度
#define ngx_strlen(s)       strlen((const char *) s)

看这里还是使用的是系统的strlen函数,并没有使用ngx_str_t类型。

3.8 字符串子串
#define ngx_strstr(s1, s2)  strstr((const char *) s1, (const char *) s2)
3.9 字符串中某个字符位置
#define ngx_strchr(s1, c)   strchr((const char *) s1, (int) c)
3.10 字符串指定范围内的字符位置
static ngx_inline u_char *
ngx_strlchr(u_char *p, u_char *last, u_char c)
{
    while (p < last) {

        if (*p == c) {
            return p;
        }

        p++;
    }

    return NULL;
}

在[p,last)之间查找字符c,并返回地址,如果没有找到则返回NULL。

3.11 字符串中NULL结尾的长度
size_t
ngx_strnlen(u_char *p, size_t n)
{
    size_t  i;

    for (i = 0; i < n; i++) {

        if (p[i] == '') {
            return i;
        }
    }

    return n;
}

给定长度n,如果在[0,n) 范围内找到’’则范围当前位置,否则返回n。

3.12 总结

对于字符串的操作大部分都是简单的对C的API进行了一个宏的封装,这样在nginx中使用的API都统一,好维护,后期替换更简单。而对于ngx_str_t的使用,更多的是直接使用var.len/var->len,这样减少了对字符串求长度的操作。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/779876.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号