Lighttpd1.4.30源码分析之array.c
来源:互联网 发布:期货下单软件 编辑:程序博客网 时间:2024/04/30 09:01
Lighttpd提供了一个通用数组,这个数组与程序的其他部分练习较少,因此可以单独进行分析。
首先要说一下Lighttpd中的定义的一些数据结构。
在array.h中有下面的定义:
Lighttpd在定义数据类型的时候使用了面向对象的思想,因此,程序具有很好的扩展性和适应性。这些类型中,最重要的是UNSET类型,这个类型在所有的数据类型中,起到了父类型的作用。在array.h中,UNSET类型的定义如下:
至于各个类型的用处以及各个类型中个成员变量的含义,暂且不用关心,只要知道这七个类型之间的关系即可,除了UNSET类型,其他类型的操作函数的实现都在文件data_XXXXX.c中。这些函数的实现都很简单,不在一一介绍,读者可自己看看。这七个类型构成了通用数组所要处理的类型,其中,在数组的定义和实现中只使用UNSET类型,利用上面的定义,通用数组可以不用关心数组中存储的到底是哪种具体的类型,只需将其按照UNSET类型来处理就可以了。这就实现了通用数组。
下面这个定义是通用数组的核心定义,就是定义了数组。
array.h中还有一个定义:
typedef struct {
DATA_UNSET;
array *value;
} data_array;
DATA_UNSET;
array *value;
} data_array;
这个定义了一个array类型的数据,也就是说,通用数组中存放的数据可以数通用数组,这样可以形成多维的通用数组。
在array.h中定义了如下的通用数组操作函数:
1、array *array_init(void);
初始化数组,分配空间。
2、array *array_init_array(array * a);
用数组a来初始化一个数组。也就是得到一个a的深拷贝。
3、void array_free(array * a);
释放数组。释放所有空间。
4、void array_reset(array * a);
重置data中的所有数据(调用UNSET类型数据中的reset函数),并将used设为0。相当于清空数组。
5、int array_insert_unique(array * a, data_unset * str);
将str插入到数组中。
6、data_unset *array_pop(array * a);
弹出data中的最后一个元素,返回奇指针,data中的最后一个位置设为NULL。
7、int array_print(array * a, int depth);
打印数组中的内容。depth参数用于在打印多维数组时,实现缩进。
8、a_unset *array_get_unused_element(array * a, data_type_t t);
返回第一个未使用的数据,也就是used位置的数据,这个数据不在数组中,返回这个数据指针后,将data[unsed]设为NULL。可能返回NULL。
9、data_unset *array_get_element(array * a, const char *key);
根据key值,返回数组中key值与之相同的数据
10、data_unset *array_replace(array * a, data_unset * du);
如果数组中有与du的key值相同的数据,则用du替换那个数据,并返回那个数据的指针。如果不存在,则把du插入到数组中。(调用data_insert_unique函数)
11、 int array_strcasecmp(const char *a, size_t a_len, const char *b, size_t b_len);
这个函数并没用实现,仅仅给出了上面的定义。也许这个是用来比较两个字符串,并且可能会忽略大小写。
12、void array_print_indent(int depth);
根据depth打印空白,实现缩进。
13、size_t array_get_max_key_length(array * a);
返回数组中最长的key的长度。
另外,在array.c中定义了一个辅助函数static intarray_get_index(array *a, const char *key, size_t keylen, int *rndx)。这个函数的作用是通过key值,查找数据,返回其在数组data中的下标位置,并通过参数rndx返回其下标在数组sorted中的位置。
函数的定义如下:
在上面列出的函数中,还有一个函数要重点讲解一下,也是最复杂的一个函数:int array_insert_unique(array *a, data_unset *str)。这个函数将数据str插入到数组中,当并不是单纯的插入,如果数组中存在key于str相同的数据,则把str的内容拷贝到这个数据中。
int array_insert_unique(array *a, data_unset *str) { int ndx = -1; int pos = 0; size_t j; /* generate unique index if neccesary */ if (str->key->used == 0 || str->is_index_key) { buffer_copy_long(str->key, a->unique_ndx++); str->is_index_key = 1; } /* 在数组中查找与str具有相同key的数据 */ if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) { /* 找到,复制 */ if (a->data[ndx]->type == str->type) { str->insert_dup(a->data[ndx], str); } else { fprintf(stderr, "a\n"); } return 0; } /* 当数组的长度大于最大值时,不进行插入,并返回-1 */ if (a->used+1 > INT_MAX) { /* we can't handle more then INT_MAX entries: see array_get_index() */ return -1; } if (a->size == 0) { /* 数组为空 */ /* 初始data的长度为16 */ a->size = 16; a->data = malloc(sizeof(*a->data) * a->size); a->sorted = malloc(sizeof(*a->sorted) * a->size); assert(a->data); assert(a->sorted); for (j = a->used; j < a->size; j++) a->data[j] = NULL; } else if (a->size == a->used) { /* data已经满了,对data进行扩容,增加16个空间。 */ /* 这就是为什么size一定是16的倍数 */ a->size += 16; a->data = realloc(a->data, sizeof(*a->data) * a->size); a->sorted = realloc(a->sorted, sizeof(*a->sorted) * a->size); assert(a->data); assert(a->sorted); for (j = a->used; j < a->size; j++) a->data[j] = NULL; } ndx = (int) a->used; a->data[a->used++] = str; /* 在上面调用函数array_get_index的时候, 已将str应该在数组sorted中位置存放在了pos中。 */ if (pos != ndx /* 要插入的位置在中部 */&&((pos < 0) /* 在开始位置插入 */ ||buffer_caseless_compare(str->key->ptr , str->key->used , a->data[a->sorted[pos]]->key->ptr , a->data[a->sorted[pos]]->key->used ) > 0)) { /* 判断当前pos所对应的元素是否比str小,若是,这pos后移一位 */ pos++; } /* 移动sorted数组中后面的数据,腾出位置。 */ if (pos != ndx) { memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted)); } /* insert */ a->sorted[pos] = ndx; /* 如果used==next_power_of_2时,扩展next_power_of_2 */ if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1; return 0; }
- Lighttpd1.4.30源码分析之array.c
- Lighttpd1.4.20源码分析 笔记 通用数组array.c(h)
- Lighttpd1.4.20源码分析 笔记 状态机之请求处理
- Lighttpd1.4.20源码分析 笔记 状态机之response
- Lighttpd1.4.20源码分析之状态机(1)---状态机总览
- Lighttpd1.4.20源码分析之插件系统(1)---plugin结构体和插件接口
- Lighttpd1.4.20源码分析之插件系统(2)---插件的加载和初始化
- Lighttpd1.4.20源码分析之插件系统(3)---PLUGIN_TO_SLOT宏
- Lighttpd1.4.20源码分析 笔记 状态机之错误处理和连接关闭
- Lighttpd1.4.20源码分析 笔记 网络服务主模型
- Lighttpd1.4.20源码分析 笔记 数据结构的组织
- Lighttpd1.4.20源码分析 笔记 fdevent系统-初始化
- Lighttpd1.4.20源码分析 笔记 fdevent系统-事件处理
- Lighttpd1.4.20源码分析 笔记 状态机与插件
- Lighttpd1.4.20源码分析之fdevent系统(1)---fdevents结构体和fdevent系统对外接口
- lighttpd1.4.18代码分析
- Lighttpd1.4.20源码分析 笔记 fdevent系统-结构体及对外接口
- Lighttpd1.4.20源码分析 笔记 fdevent系统-连接socket及超时处理
- static解析
- 本星期的一些总结
- chrome涉及开源项目
- Ubuntu 12.04 锁定Guest账户
- Android动画效果
- Lighttpd1.4.30源码分析之array.c
- 连接池与不稳定网络
- Java Web Start 入门(一)
- C++标准程序库 学习笔记 第九章 STL算法
- 确定比赛名次(谢庆皇)
- ucos-ii中内存块的建立
- Clairewd’s message&&http://acm.hdu.edu.cn/showproblem.php?pid=4300
- 一个操作数据库的类,大家评价一下
- Java Web Start 入门(二)