2. nginx基本数据结构之ngx_str_t ngx_queue_t

1420阅读 0评论2015-06-01 mizhouli
分类:LINUX

欢迎讨论指正。

这两个很简单,放在一起介绍。

1. 二进制安全字符串
保存长度,可以不以'\0'结尾,字符串中可以包含任何字符。
之所以列出,是因为nginx中大部分字符串都是使用 ngx_str_t 保存,使用频率非常高。
  

点击(此处)折叠或打开

  1. typedef struct {
  2.     size_t len;
  3.     u_char *data;
  4. } ngx_str_t;
  5. // 定义并初始化一个 ngx_str_t 变量,注意 由于使用sizeof,故str 应为常量字符串
  6. #define ngx_string(str) { sizeof(str) - 1, (u_char *) str }

  7. // 定义并初始化一个 ngx_str_t 变量,值为空串
  8. #define ngx_null_string { 0, NULL }

  9. // 修改一个 ngx_str_t 变量,注意 由于使用sizeof,故str 应为常量字符串
  10. #define ngx_str_set(str, text) \
  11.     (str)->len = sizeof(text) - 1; (str)->data = (u_char *) text

  12. // 修改一个 ngx_str_t 变量为空串
  13. #define ngx_str_null(str) (str)->len = 0; (str)->data = NULL
2. 带有头节点的双向循环队列
类似linux内核中的 list_head ,仅有链接指针,无数据,不负责内存分配,一般嵌入其他结构使用。

nginx_queue.h

点击(此处)折叠或打开

  1. /*
  2.  * Copyright (C) Igor Sysoev
  3.  * Copyright (C) Nginx, Inc.
  4.  */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>


  7. #ifndef _NGX_QUEUE_H_INCLUDED_
  8. #define _NGX_QUEUE_H_INCLUDED_



  9. typedef struct ngx_queue_s ngx_queue_t;

  10. struct ngx_queue_s {
  11.     ngx_queue_t *prev;
  12.     ngx_queue_t *next;
  13. };


  14. // 初始化队列,前向、后向指针都指到队列的头部本身
  15. #define ngx_queue_init(q) \
  16.     (q)->prev = q; \
  17.     (q)->next = q

  18. // 置空队列
  19. #define ngx_queue_empty(h) \
  20.     (h == (h)->prev)

  21. // 在头节点后插入节点x
  22. #define ngx_queue_insert_head(h, x) \
  23.     (x)->next = (h)->next; \
  24.     (x)->next->prev = x; \
  25.     (x)->prev = h; \
  26.     (h)->next = x


  27. #define ngx_queue_insert_after ngx_queue_insert_head

  28. // 插入队尾x
  29. #define ngx_queue_insert_tail(h, x) \
  30.     (x)->prev = (h)->prev; \
  31.     (x)->prev->next = x; \
  32.     (x)->next = h; \
  33.     (h)->prev = x

  34. // 获取队列的第一关元素
  35. #define ngx_queue_head(h) \
  36.     (h)->next

  37. // 获取队列的最后一个元素
  38. #define ngx_queue_last(h) \
  39.     (h)->prev

  40. // 获取哨兵,即头节点
  41. #define ngx_queue_sentinel(h) \
  42.     (h)

  43. // 获取下一个元素
  44. #define ngx_queue_next(q) \
  45.     (q)->next

  46. // 获取前一个元素
  47. #define ngx_queue_prev(q) \
  48.     (q)->prev


  49. // 从队列中移除x元素
  50. #if (NGX_DEBUG)

  51. #define ngx_queue_remove(x) \
  52.     (x)->next->prev = (x)->prev; \
  53.     (x)->prev->next = (x)->next; \
  54.     (x)->prev = NULL; \
  55.     (x)->next = NULL

  56. #else

  57. #define ngx_queue_remove(x) \
  58.     (x)->next->prev = (x)->prev; \
  59.     (x)->prev->next = (x)->next

  60. #endif

  61. // 把以h为队头的队列分割为2个队列,其中分割点q,另一个队列的头为n,q节点属于n为头的队列
  62. #define ngx_queue_split(h, q, n) \
  63.     (n)->prev = (h)->prev; \
  64.     (n)->prev->next = n; \
  65.     (n)->next = q; \
  66.     (h)->prev = (q)->prev; \
  67.     (h)->prev->next = h; \
  68.     (q)->prev = n;

  69. // 合并队列h,n
  70. #define ngx_queue_add(h, n) \
  71.     (h)->prev->next = (n)->next; \
  72.     (n)->next->prev = (h)->prev; \
  73.     (h)->prev = (n)->prev; \
  74.     (h)->prev->next = h;

  75. // 获取节点的数据指针,即宿主结构的指针。 q是队列中的节点,type队列类型,link是队列类型中ngx_queue_t的元素名
  76. #define ngx_queue_data(q, type, link) \
  77.     (type *) ((u_char *) q - offsetof(type, link))


  78. ngx_queue_t *ngx_queue_middle(ngx_queue_t *queue);
  79. void ngx_queue_sort(ngx_queue_t *queue,
  80.     ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *));


  81. #endif /* _NGX_QUEUE_H_INCLUDED_ */
ngx_queue.c

点击(此处)折叠或打开

  1. /*
  2.  * find the middle queue element if the queue has odd number of elements
  3.  * or the first element of the queue's second part otherwise
  4.  */
  5. // 获取队列的中间节点的指针
  6. ngx_queue_t *
  7. ngx_queue_middle(ngx_queue_t *queue)
  8. {
  9.     ngx_queue_t *middle, *next;

  10.     // middle、next 都指向队列的第一个元素
  11.     middle = ngx_queue_head(queue);

  12.     if (middle == ngx_queue_last(queue)) {
  13.         // 只有一个元素,返回该元素
  14.         return middle;
  15.     }

  16.     next = ngx_queue_head(queue);

  17.     /*
  18.      * 循环中 middle前进一步, next前进2步,当next达到队尾,middle即为队列的中间节点
  19.      */
  20.     for ( ;; ) {
  21.         // middle前进一步
  22.         middle = ngx_queue_next(middle);

  23.         // next前进一步
  24.         next = ngx_queue_next(next);

  25.         // next到达队列尾部
  26.         if (next == ngx_queue_last(queue)) {
  27.             return middle;
  28.         }

  29.         // next再前进一步
  30.         next = ngx_queue_next(next);

  31.         // next到达队列尾部
  32.         if (next == ngx_queue_last(queue)) {
  33.             return middle;
  34.         }
  35.     }
  36. }


  37. // 稳定的插入排序
  38. /* the stable insertion sort */

  39. void
  40. ngx_queue_sort(ngx_queue_t *queue,
  41.     ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *))
  42. {
  43.     ngx_queue_t *q, *prev, *next;

  44.     q = ngx_queue_head(queue);

  45.     if (q == ngx_queue_last(queue)) {
  46.         return;
  47.     }

  48.     for (q = ngx_queue_next(q); q != ngx_queue_sentinel(queue); q = next) {

  49.         prev = ngx_queue_prev(q);
  50.         next = ngx_queue_next(q);

  51.         ngx_queue_remove(q);

  52.         do {
  53.             if (cmp(prev, q) <= 0) {
  54.                 break;
  55.             }

  56.             prev = ngx_queue_prev(prev);

  57.         } while (prev != ngx_queue_sentinel(queue));

  58.         ngx_queue_insert_after(prev, q);
  59.     }
  60. }




上一篇:1. nginx的编译及安装
下一篇:3. nginx基本数据结构之动态数组ngx_array_t