位置: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