我们来看一下wildcard初始化函数。
 
//函数ngx_int_t
 
//ngx_array_s结构体
 
 
 
//elts是指向内存池中的存储元素的指针。内存池pool需要进行元素对齐等,所以这个值不等于pool
//nelts是当前有的元素个数
//size是每个元素大小
//nalloc是元素的多少
//pool是内存池的指针
 
 
struct ngx_array_s {
    void        *elts;
    ngx_uint_t   nelts;
    size_t       size;
    ngx_uint_t   nalloc;
    ngx_pool_t  *pool;
}; 
 
 
 
 
 
//内联函数,进行数组初始化,其实是分配某个数量的元素的内存,以便于压栈等操作
 
 
//参数,数组管理结构体、内存池、元素多少,每个元素大小
 
 
static ngx_inline ngx_int_t
ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size)
{
    /*
     * set "array->nelts" before "array->elts", otherwise MSVC thinks
     * that "array->nelts" may be used without having been initialized
     */

    array->nelts = 0;
    array->size = size;
    array->nalloc = n;
    array->pool = pool;

    array->elts = ngx_palloc(pool, n * size);
    if (array->elts == NULL) {
        return NGX_ERROR;
    }

    return NGX_OK;
} 
 
 
 
 
 
 
 
 
//函数ngx_hash_wildcard_init
//这段代码,由于我从来没看过wildcard的相关代码,所以另我相当恶心
 
//一起看看吧
 
 
ngx_int_t
ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
    ngx_uint_t nelts)
{
    size_t                len, dot_len;
    ngx_uint_t            i, n, dot;
    ngx_array_t           curr_names, next_names;
    ngx_hash_key_t       *name, *next_name;
    ngx_hash_init_t       h;
    ngx_hash_wildcard_t  *wdc; 
    //在hinit->temp_pool中开辟内存,并分配nelts个大小为ngx_hash_key_t的元素的内存空间,对齐后,将指针赋给curr_names
    //该元素数组指针即 curr_names
 
 
    if (ngx_array_init(&curr_names, hinit->temp_pool, nelts,
                       sizeof(ngx_hash_key_t))
        != NGX_OK)
    {
        return NGX_ERROR;
    } 
    //同样在hinit->temp_pool中开辟内存,分配nelts个大小为ngx_hash_key_t的元素的内存空间,对齐后,将指针赋给next_names
    //该元素数组指针即 next_names
    if (ngx_array_init(&next_names, hinit->temp_pool, nelts,
                       sizeof(ngx_hash_key_t))
        != NGX_OK)
    {
        return NGX_ERROR;
    } 
 
 
   //对于整个数组
 
    for (n = 0; n < nelts; n = i) {

#if 0
        ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
                      "wc0: /"%V/"", &names[n].key);
#endif 
        //标识
        dot = 0;
        //如果这个数组的元素中,有dot则,赋dot为1,并跳出这个检测数组元素中是否有dot的循环,当前的len则是从数组开始到数组中的           //dot。
        for (len = 0; len < names[n].key.len; len++) {
            if (names[n].key.data[len] == '.') {
                dot = 1;
                break;
            }
        }        //curr_names的指针发生移动,以便于给当前元素赋值。也就是“压栈”操作
        name = ngx_array_push(&curr_names);
        if (name == NULL) {
            return NGX_ERROR;
        }
                 //压栈操作的赋值代码,将names这个数组,的当前元素的值填充到name这个数组中,包括计算这个当前元素的key_hash的值
        name->key.len = len;
        name->key.data = names[n].key.data;
        name->key_hash = hinit->key(name->key.data, name->key.len);
        name->value = names[n].value;

#if 0
        ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
                      "wc1: /"%V/" %ui", &name->key, dot);
#endif 
        //数组中dot后其余部分的开始
        dot_len = len + 1;
        //如果dot==1,则说明数组其余部分第一个是dot,应该将len+1指向dot后第一个字符
        if (dot) {
            len++;
        } 
 
       //初始化next_names指向的元素的实际个数为0
 
        next_names.nelts = 0;
 
        //如果names中的元素长度与当前长度不等,说明确实有dot。
        if (names[n].key.len != len) {
              //把这个压入next_names栈中
            next_name = ngx_array_push(&next_names);
            if (next_name == NULL) {
                return NGX_ERROR;
            }           //得到新的字串的长度
            next_name->key.len = names[n].key.len - len;
           //新的字串的指针            next_name->key.data = names[n].key.data + len;
           //新的字串的hash值            next_name->key_hash = 0;
            //新的字串的值
           next_name->value = names[n].value;

#if 0
            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
                          "wc2: /"%V/"", &next_name->key);
#endif
        } 
        //比较当前names[n]的值的数据是否有和n+1到nelts的元素的值相同的
        for (i = n + 1; i < nelts; i++) {            //如果names[n]的key值的数据和names[i]的key的数据相同不相同,则跳出循环。
            if (ngx_strncmp(names[n].key.data, names[i].key.data, len) != 0) {
                break;
            }             //到这,意味着key数据值相同
              //如果dot==0并且names[i]的key的长度大于len并且names[i]的key的数据不是dot(.)则退出循环
            if (!dot
                && names[i].key.len > len
                && names[i].key.data[len] != '.')
            {
                break;
            }            //到这意味着dot==1,并且names[i]的后边也有字符。则将next_names压入栈,即names[i]与names[n]处理相同
            next_name = ngx_array_push(&next_names);
            if (next_name == NULL) {
                return NGX_ERROR;
            }
             //进行赋值与names[n]的相同            next_name->key.len = names[i].key.len - dot_len;
            next_name->key.data = names[i].key.data + dot_len;
            next_name->key_hash = 0;
            next_name->value = names[i].value;

#if 0
            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
                          "wc3: /"%V/"", &next_name->key);
#endif
        } 
 
 
 
        //如果当前没有执行过push_array_push操作,也就是dot后边没有元素
       //则意味着curr_names中已经不含有dot。
 
       //递归调用,对next_names进行
 
        if (next_names.nelts) {

            h = *hinit;
            h.hash = NULL;

            if (ngx_hash_wildcard_init(&h, (ngx_hash_key_t *) next_names.elts,
                                       next_names.nelts)
                != NGX_OK)
            {
                return NGX_ERROR;
            } 
             //没看明白。。。。。。。。。。。。。。。。。。。。。。。。。。。。
 
            wdc = (ngx_hash_wildcard_t *) h.hash;

            if (names[n].key.len == len) {
                wdc->value = names[n].value;
            }

            name->value = (void *) ((uintptr_t) wdc | (dot ? 3 : 2));

        } else if (dot) {
            name->value = (void *) ((uintptr_t) name->value | 1);
        }
    } 
 
  //最后,所有不含dot的元素都在curr_names中了,进行初始化hinit。
    if (ngx_hash_init(hinit, (ngx_hash_key_t *) curr_names.elts,
                      curr_names.nelts)
        != NGX_OK)
    {
        return NGX_ERROR;
    }

    return NGX_OK;
}