nginx数据结构之ngx_str_t

位置:nginx/src/core/ngx_string.h中

typedef struct {
    size_t      len;
    u_char     *data;
} ngx_str_t;

data指针指向字符串的起始地址

len表示字符串的有效长度

注意:data指针指向的字符串不会以\0结尾,所以使用时必须根据长度len来使用data成员

这样定义的好处是什么?

首先,通过储存字符串长度,可以减少计算字符串长度的次数,其次nginx可以重复引用一段字符串的内存,data可以指向任何内存,长度表示结束,而不用去copy一份自己的字符串,这样可以减少很多不必要的内存分配与拷贝

这样定义的坏处是什么?

正是基于上述的好处,所以在nginx中,必须谨慎的去修改一个字符串,在修改字符串时需要认真考虑:是否可以修改,修改后是否会对其他的引用产生影响,并且glibc提供的很多系统api都是通过\0表示字符串结束的,所以不能直接传入

如何修改才能调用glibc的系统api?

通常方法是创建一段str->len+1大小的内存,然后copy字符串,最后一个字节置为\0,也有比较hack的做法,将字符串的最后一个字符的后一个字符backup(后备)一个,然后设置为\0,在做完调用后,再由backup改回来,但前提是需要确定这个字符是可以修改的,而且是内存分配,不会越界,一般不建议这么做

初始化赋值函数:

#define ngx_string(str)     { sizeof(str) - 1, (u_char *) str }
#define ngx_null_string     { 0, NULL }
#define ngx_str_set(str, text)                                               \
    (str)->len = sizeof(text) - 1; (str)->data = (u_char *) text
#define ngx_str_null(str)   (str)->len = 0; (str)->data = NULL

ngx_string(str)用于接受一个常量字符串数据,然后将该字符串的长度以及首地址传给ngx_str_t的结构体。
ngx_null_string定义一个字符长度为0的结构体
ngx_str_set用于将结构体ngx_str_t的长度以及首地址赋值为text的长度以及首地址。
ngx_str_null(null)用于将结构体ngx_str_t初始化为长度为0,首地址为空的初始序列。
ngx_str_set传入的是结构体的地址,因为下面的引用成员变量的方式是以指针的方式进行的,ngx_str_null亦是如此。

样例:

/* 例如:*/
/* 正确写法*/
ngx_str_t str1 = ngx_string("hello nginx");
ngx_str_t str2 = ngx_null_string;

/* 错误写法*/
ngx_str_t str1, str2;
str1 = ngx_string("hello nginx");   /* 编译出错 */
str2 = ngx_null_string;             /* 编译出错 */

/* 正确写法*/
ngx_str_t str1, str2;
ngx_str_set(&str1, "hello nginx");
ngx_str_null(&str2);
/* 注意:ngx_string 和 ngx_str_set 字符串参数必须是常量字符串,不能是变量字符串 */

字符处理函数

很多都封装的c中string.h中的函数

#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)  //转大写字符
void ngx_strlow(u_char *dst, u_char *src, size_t n);           //从src复制n个字符到dst中,同时将相应的字符转为小写字符
#define ngx_strncmp(s1, s2, n)  strncmp((const char *) s1, (const char *) s2, n)  //字符比较函数,只比较前面n个字符,大小写敏感
#define ngx_strcmp(s1, s2)  strcmp((const char *) s1, (const char *) s2)            //字符比较函数,一直到某个字符的终止位置,大小写敏感
#define ngx_strstr(s1, s2)  strstr((const char *) s1, (const char *) s2)             //查找子串
#define ngx_strlen(s)       strlen((const char *) s)                               //计算字符穿长度
#define ngx_strchr(s1, c)   strchr((const char *) s1, (int) c)                      //第一次出现c的位置

大小写转换函数比较有意思,就是对第6位进行处理,大小写字母差是32,而0x20刚好是32


上一篇:实战篇-OpenSSL之AES加密算法-CBC模式


下一篇:Nginx(三):Linux环境(Ubuntu)下Nginx的安装