这两个很简单,放在一起介绍。
1. 二进制安全字符串
保存长度,可以不以'\0'结尾,字符串中可以包含任何字符。
之所以列出,是因为nginx中大部分字符串都是使用 ngx_str_t 保存,使用频率非常高。
点击(此处)折叠或打开
-
typedef struct {
-
size_t len;
-
u_char *data;
-
} ngx_str_t;
-
// 定义并初始化一个 ngx_str_t 变量,注意 由于使用sizeof,故str 应为常量字符串
-
#define ngx_string(str) { sizeof(str) - 1, (u_char *) str }
-
-
// 定义并初始化一个 ngx_str_t 变量,值为空串
-
#define ngx_null_string { 0, NULL }
-
-
// 修改一个 ngx_str_t 变量,注意 由于使用sizeof,故str 应为常量字符串
-
#define ngx_str_set(str, text) \
-
(str)->len = sizeof(text) - 1; (str)->data = (u_char *) text
-
-
// 修改一个 ngx_str_t 变量为空串
- #define ngx_str_null(str) (str)->len = 0; (str)->data = NULL
类似linux内核中的 list_head ,仅有链接指针,无数据,不负责内存分配,一般嵌入其他结构使用。
nginx_queue.h
点击(此处)折叠或打开
-
/*
-
* Copyright (C) Igor Sysoev
-
* Copyright (C) Nginx, Inc.
-
*/
-
-
-
#include <ngx_config.h>
-
#include <ngx_core.h>
-
-
-
#ifndef _NGX_QUEUE_H_INCLUDED_
-
#define _NGX_QUEUE_H_INCLUDED_
-
-
-
-
typedef struct ngx_queue_s ngx_queue_t;
-
-
struct ngx_queue_s {
-
ngx_queue_t *prev;
-
ngx_queue_t *next;
-
};
-
-
-
// 初始化队列,前向、后向指针都指到队列的头部本身
-
#define ngx_queue_init(q) \
-
(q)->prev = q; \
-
(q)->next = q
-
-
// 置空队列
-
#define ngx_queue_empty(h) \
-
(h == (h)->prev)
-
-
// 在头节点后插入节点x
-
#define ngx_queue_insert_head(h, x) \
-
(x)->next = (h)->next; \
-
(x)->next->prev = x; \
-
(x)->prev = h; \
-
(h)->next = x
-
-
-
#define ngx_queue_insert_after ngx_queue_insert_head
-
-
// 插入队尾x
-
#define ngx_queue_insert_tail(h, x) \
-
(x)->prev = (h)->prev; \
-
(x)->prev->next = x; \
-
(x)->next = h; \
-
(h)->prev = x
-
-
// 获取队列的第一关元素
-
#define ngx_queue_head(h) \
-
(h)->next
-
-
// 获取队列的最后一个元素
-
#define ngx_queue_last(h) \
-
(h)->prev
-
-
// 获取哨兵,即头节点
-
#define ngx_queue_sentinel(h) \
-
(h)
-
-
// 获取下一个元素
-
#define ngx_queue_next(q) \
-
(q)->next
-
-
// 获取前一个元素
-
#define ngx_queue_prev(q) \
-
(q)->prev
-
-
-
// 从队列中移除x元素
-
#if (NGX_DEBUG)
-
-
#define ngx_queue_remove(x) \
-
(x)->next->prev = (x)->prev; \
-
(x)->prev->next = (x)->next; \
-
(x)->prev = NULL; \
-
(x)->next = NULL
-
-
#else
-
-
#define ngx_queue_remove(x) \
-
(x)->next->prev = (x)->prev; \
-
(x)->prev->next = (x)->next
-
-
#endif
-
-
// 把以h为队头的队列分割为2个队列,其中分割点q,另一个队列的头为n,q节点属于n为头的队列
-
#define ngx_queue_split(h, q, n) \
-
(n)->prev = (h)->prev; \
-
(n)->prev->next = n; \
-
(n)->next = q; \
-
(h)->prev = (q)->prev; \
-
(h)->prev->next = h; \
-
(q)->prev = n;
-
-
// 合并队列h,n
-
#define ngx_queue_add(h, n) \
-
(h)->prev->next = (n)->next; \
-
(n)->next->prev = (h)->prev; \
-
(h)->prev = (n)->prev; \
-
(h)->prev->next = h;
-
-
// 获取节点的数据指针,即宿主结构的指针。 q是队列中的节点,type队列类型,link是队列类型中ngx_queue_t的元素名
-
#define ngx_queue_data(q, type, link) \
-
(type *) ((u_char *) q - offsetof(type, link))
-
-
-
ngx_queue_t *ngx_queue_middle(ngx_queue_t *queue);
-
void ngx_queue_sort(ngx_queue_t *queue,
-
ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *));
-
-
- #endif /* _NGX_QUEUE_H_INCLUDED_ */
点击(此处)折叠或打开
-
/*
-
* find the middle queue element if the queue has odd number of elements
-
* or the first element of the queue's second part otherwise
-
*/
-
// 获取队列的中间节点的指针
-
ngx_queue_t *
-
ngx_queue_middle(ngx_queue_t *queue)
-
{
-
ngx_queue_t *middle, *next;
-
-
// middle、next 都指向队列的第一个元素
-
middle = ngx_queue_head(queue);
-
-
if (middle == ngx_queue_last(queue)) {
-
// 只有一个元素,返回该元素
-
return middle;
-
}
-
-
next = ngx_queue_head(queue);
-
-
/*
-
* 循环中 middle前进一步, next前进2步,当next达到队尾,middle即为队列的中间节点
-
*/
-
for ( ;; ) {
-
// middle前进一步
-
middle = ngx_queue_next(middle);
-
-
// next前进一步
-
next = ngx_queue_next(next);
-
-
// next到达队列尾部
-
if (next == ngx_queue_last(queue)) {
-
return middle;
-
}
-
-
// next再前进一步
-
next = ngx_queue_next(next);
-
-
// next到达队列尾部
-
if (next == ngx_queue_last(queue)) {
-
return middle;
-
}
-
}
-
}
-
-
-
// 稳定的插入排序
-
/* the stable insertion sort */
-
-
void
-
ngx_queue_sort(ngx_queue_t *queue,
-
ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *))
-
{
-
ngx_queue_t *q, *prev, *next;
-
-
q = ngx_queue_head(queue);
-
-
if (q == ngx_queue_last(queue)) {
-
return;
-
}
-
-
for (q = ngx_queue_next(q); q != ngx_queue_sentinel(queue); q = next) {
-
-
prev = ngx_queue_prev(q);
-
next = ngx_queue_next(q);
-
-
ngx_queue_remove(q);
-
-
do {
-
if (cmp(prev, q) <= 0) {
-
break;
-
}
-
-
prev = ngx_queue_prev(prev);
-
-
} while (prev != ngx_queue_sentinel(queue));
-
-
ngx_queue_insert_after(prev, q);
-
}
- }