typedef struct {size_t len;u_char *data;
} ngx_str_t;
从代码里可以看到,ngx str 的结构非常简单,只是用成员变量 len和data 标记了 一块内存区域,并不实际持有 个字符串内容,非常的轻量级。 data 成员的类型是 u_char 而不是 char 意味着它不 定必须 以’/0"结尾 ,任何数据都可以当作字符串来使用。
当然这种设计也有缺点 因为 ngx_str_t 只是引用内存,所以我们应尽量以“只读”的方 式去使用它 在多个 ngx_str_t 共享 块内存时要小心,如果擅自修改字符串内容很有可能 影响其他的 ngx str 引用,导致错误发生。另一种危险是引用的内存地址可能会失效 访问到错误的内存区域 Nginx提供两个初始化函数宏:ngx_string()使用字符串初始化,ngx_null_string ()初始化为一个空字符串,因为它们使用了{...}的形式,所以只能用于赋值初始化:
#define ngx_string(str) { sizeof(str) - 1, (u_char *) str }
#define ngx_null_string { 0, NULL }
设置内容:
运行时设置字符串内容可以使用下面两个函数宏,功能是相同的,注意参数str必须是指针:
#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 ()和 ngx_str_set()内部使用了sizeof计算字符串长度,所以参数必须是一个编译期的字符串“字面值”,而不能是一个字符串指针,否则sizeof 会计算得到指针的长度(8字节),而不是字符串的实际长度。
用法示例:
ngx_str_t s1=ngx_null_string;
ngx_str_t s2=ngx_string("matrix");ngx_str_set(&s1,"reload");
ngx_str_null(&s2);
转化大小写
#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)
大小比较
ngx_str_t 只是个普通的字符串,所以标准的c字符串函数都能够使用(需要转型为const char*),处理它的data成员就可以了,但Nginx也实现了一些特有的操作函数。
下面是一些常用的字符串操作函数,但需要注意有的参数类型不是ngx_str_t,而是u _char* :
#define ngx_strncmp(s1, s2, n) strncmp((const char *) s1, (const char *) s2, n)/* msvc and icc7 compile strcmp() to inline loop */
#define ngx_strcmp(s1, s2) strcmp((const char *) s1, (const char *) s2)#define ngx_strstr(s1, s2) strstr((const char *) s1, (const char *) s2)
格式化函数
_char * ngx_cdecl
ngx_sprintf(u_char *buf, const char *fmt, ...)
{u_char *p;va_list args;va_start(args, fmt);p = ngx_vslprintf(buf, (void *) -1, fmt, args);va_end(args);return p;
}
u_char * ngx_cdecl
ngx_snprintf(u_char *buf, size_t max, const char *fmt, ...)
{u_char *p;va_list args;va_start(args, fmt);p = ngx_vslprintf(buf, buf + max, fmt, args);va_end(args);return p;
}u_char * ngx_cdecl
ngx_slprintf(u_char *buf, u_char *last, const char *fmt, ...)
{u_char *p;va_list args;va_start(args, fmt);p = ngx_vslprintf(buf, last, fmt, args);va_end(args);return p;
}
ngx_sprintf ( )直接向buf输出格式化内容,不检查缓冲区的有效性,存在缓冲区溢出危险,通常不建议使用。后两个函数比较安全,参数max和 last指明了缓冲区的结束位置,所以格式化的结果只会填满缓冲区为止。
#define typed_ngx_string(str) ngx_str_t ngx_string(str)
#define typed_ngx_null_string ngx_str_t ngx_null_stringpublic:typedef NgxWrapper super_type;typedef NgxString this_type;typedef boost::string_ref string_ref_type;public:NgxString(ngx_str_t& str):super_type(str){}// enable convert const objectNgxString(const ngx_str_t& str):super_type(const_cast(str)){}// disable temporary objectNgxString(ngx_str_t&& str) = delete;~NgxString() = default;
1.NgxWrapper相当于一个基本的模块类型(封装各种各样的数据结构)
2.有一个新特性 const_cast
:const_cast
该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。
一、常量指针被转化成非常量的指针,并且仍然指向原来的对象;
二、常量引用被转换成非常量的引用,并且仍然指向原来的对象;
三、const_cast一般用于修改底指针。如const char *p形式。
3. 有一个巧妙设计 NgxString(ngx_str_t&& str) = delete;
将对象转化成str!!!
public:const char* data() const{return reinterpret_cast(get()->data);}std::size_t size() const{return get()->len;}bool empty() const{return !get()->data || !get()->len;}string_ref_type str() const{return string_ref_type(data(), size());}}
public:// nagetive means erroroperator ngx_int_t () const{return ngx_atoi(get()->data, get()->len);}
1.首先提供data()和size()提供访问
2.判断空和转换char-》int
public:// range concepttypedef u_char char_type;typedef u_char* iterator;typedef iterator const_iterator;typedef boost::iterator_difference difference_type;
public:const_iterator begin() const{return get()->data;}const_iterator end() const{return get()->data + get()->len;}public:const char_type& front() const{return *begin();}const char_type& back() const{//return *std::prev(end());return *boost::prior(end());}
public:bool contains(const this_type& x) const{return boost::contains(*this, x);}
1.理解u_char 和u_char*
1.指针传递,就是把改变的地址传过去了,你在第一个函数里修改里地址里的内容,所以a改变了
2.值传递,值传递只是拷贝了一份,作为参数,不影响原来的值
3.引用是原变量的一个别名,跟原来的变量实质上是同一个东西。
int a = 996;
int *p = &a; // p是指针, &在此是求地址运算
int &r = a; // r是引用, &在此起标识作用
总结就是一个是返回变量值,一个是内存值
public:templatefriend T& operator<<(T& o, const this_type& s){o.write(s.data(), s.size());return o;}public:templatefriend T& operator<<(T& o, const this_type& s){o.write(s.data(), s.size());return o;}templatefriend T& operator<<(T& o, const ngx_str_t& s){o.write(reinterpret_cast(s.data), s.len);return o;}templatefriend T& operator<<(T& o, const volatile ngx_str_t& s){o.write(reinterpret_cast(s.data), s.len);return o;}public:templatevoid printf(const Args& ... args) const{auto p = ngx_snprintf(get()->data, get()->len, args ...);get()->len = static_cast(p - get()->data);}
};
1.重载<<(c++cin<<)相似
2.重载两种类型
volatile的本意是“易变的”,volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。
const就不多说啦
3.printf相同!!!借鉴啦上面的ngx_snprintf
上一篇:测试基础——数据库及数据库表的SQL操作(了解即可)
下一篇:《调试九法》阅读笔记