spdy_header: 一个工具类,代表着http header的数据结构。
<1> 因为http header本身的key-value特性,因此使用了hashMap来保存httpheader, key是header的名称,而value是header的内容。
对于碰撞,则采用了拉链法来解决,hashMap的bucket的尺寸由HTABLE_SIZE来编译期决定。
<2> 采用的hash算法比较简单,简单的字符串尺寸不断位移,在得到hval以后,和HTABLE_SIZE取余来得到bucket位置,其中,取余操作直接使用了为操作 havl&(HTABLE_SIZE-1), 效率上高一点。
<3> 每个单独的header作为Node存在, Node保存了此header的名称(key)和内容(value), 因为Node本身不在外边使用,因此直接作为了Headers的一个内部类,其只存在与本模块内供内部使用。
<4>于Node类似,Headers自己的iterator作为一个内部实现类存在,继承实现于spdy_header.h文件(也就是向外部开放的接口)的HeaderIterotor类,HeaderIterotor其实是一个接口类,本身是一个虚类,所有的方法都是纯虚汗数(virtual XXmethod() = 0)。
<5>因为实际的Node被保存在Headers类中,因此HeaderIterator的key和value都只是指向相应Node的key和value的引用(指针)罢了。
<6>因为Iterator会直接操作Headers中的成员,因此Headers内部的Iterator类是Headers的友元,但因为iterator本身是在Headers内部实现定义的,因此还是可以视为封装的。
<7>Headers对象本身维护一个HeaderIterator的引用(指针),这样在对Headers对象进行有关iterator的操作时,才有的放矢,比如:
get_iterator(), reset_iterator(), HeaderIterator对象 和 Headers对象是一种互相引用的关系,严格说,应该是Headers包含了一个HeaderIterator对象(在code中也有体现,iterator实际是在Headers的get_iterator()中new出来的)。
<8>Iterator的几个外部方法:next(), erase(),reset()。
<9>Headers的几个内部操作方法:
find() 单纯的查找key
find_add() 查找key,如果不存在,那么添加一个。
free_node(), 名称应该是free_node_list,因为其实现是递归的将某个node及其之后的所有通过next链接的node都删掉。
几个外部操作方法:
<10>Headers内部的Iterator类:
insert( Node *n ), 直接将此node插入到hash拉链的第一个
add(const Headers *), 将另外一个Headers的所有内容加入
add(const std::string &key, const std::string &val, char delim = '\0')
为http header量身定制,因为header内容其实容许存在多个值,用delim隔开,内部先使用find_add, 如果之前此key不存在,那么直接添加,否则,在已有的基础上加上delim和新的内容
add_first( const std::string &key, const std::string &val, char delim = '\0' )
同上,不同的是,这次的内容加在原来内容的前边,利用string的insert实现
remove( const std::string &key ):
删除某个key对应的所有node(其实就是某个header), 在进行删除操作时,
采用了修改指向next的指针的内容的方法:
Node **pn = &htable[hval & (HTABLE_SIZE-1)];
while(Node * curNodep = *pn) {
if ( curNodep->hval == hval && curNodep->key == key) {
*pn = curNodep->next;
delete curNodep;
_nelems--;
break;
}
pn = &curNodep->next;
// pn是指向Node的next的指针,在进行删除以后,
//将后面的元素重新链接起来时,只需把当前的pn所指的next指针 修改为指向 next指向的对象的next即可.
}
get_iterator(bool split)
获取Headers所属的iterator, split表示是否将某个header的多个值当成单独的成员看待。
因为Headers没有将Iterator暴露,并且Headers本身有一些修改iterator的方法,因此Headers也作为Iterator的一个friend class,
iterator在构造时就要传入一个Headers的指针来表示绑定关系。
<11>Iterator类有两个next方法:
next(): 表示前进到下一个Node(Header),如果某个hashbucket的node全部遍历完,那么就到下一个hash bucket,iterator的off变量标示当前的bucket位置。
next_sub():表示前进到header的下一个value(前面说过,一个header可能是多值的), last_pos标示上一个值结束的位置+1,每次从last_pos开始查找下一个值, 将iterator的value指针指向此值,Iterator内部有一个string类的substr,其内部保存的就是当前的header的当前遍历到的值,value实际指向的是substr。
<12>Iterator的reset():
其实就是将此iterator无效化,将current设为NULL,表示此iterator没有依附于任何的Node上,因此也无从取值和修改。
<13>Iterator的erase():
同Headers的remove(), 将current所指向的Node从Headers中拿去,因为都是指针,所以直接用某个Node的地址是否和current指针的值相同做判断,因为只保存了当前指向的Node,而Node的上一个成员并没有保存,因此在删除时还是需要遍历某个buckey的Node链。