HashTable使用手册篇

书上的开篇是简单介绍链表和数组了,想起自己当年,c语言数据结构敲起来手到拈来,各种随便姿势敲,php弄久了,相当生涩。找时间且切题,数据结构敲一遍,应该很快回暖吧。(没人教,自己探索了这么久,才慢慢理解这东西的进阶路线,如果有会的人带,不至于想现在这样,再重拾c语言,这晃,就1年光景)

zend内核的核心存储结构,就是HashTable了。

初始化并创建一个hashtable: zend_hash_init(

HashTable *ht,

uint nSize,//大小会自动被更改成最接近的,并且大于nSize的2的幂的值

hash_func_t pHashFunction,//NULL

dtor_func_t pDestructor,

/*回调函数,当删除hashtable中的一个元素时候,就会调用,函数原型void method_name(voidpElement);pElment指向你要删除的元素

zend_bool persistent //这是标记是否持久化内存,引擎会传递给pemalloc。有一个使用的例子:在php在请求最开始,初始化全局变量时候:

zend_hash_init(&EG(symbol_table),50,NULL,ZVAL_PTR_DTOR,0),50不是2的幂,会被更改成64(zend/zend_execute_API.c)

#define ZVAL_PTR_DTOR (void (*)(void *)) zval_ptr_dtor_wrapper  (zend/zend_variables.h)

由此可见,如果删除hashtable的元素,比如unset(),时候,就会调用这个ZVAL_PTR_DTOR

*/

)

添加||修改

常用的有4个函数

int zend_hash_add(

HashTable *ht, //待操作的ht

char *arKey, //索引,如"my_key"

uint nKeyLen, //字符串索引的长度,如6

void **pData, //要插入的数据,注意它是void **类型的。int *p,i=1;p=&i,pData=&p;。

uint nDataSize,

void pDest //如果操作成功,则pDest=pData;

);

int zend_hash_update(

HashTable *ht,

char *arKey,

uint nKeyLen,

void *pData,

uint nDataSize,

void **pDest

);

int zend_hash_index_update(

HashTable *ht,

ulong h,

void *pData,

uint nDataSize,

void **pDest

);

int zend_hash_next_index_insert(

HashTable *ht,

void *pData,

uint nDataSize,

void **pDest

);

前两个是关联数组的,后两个是普通数组(就是字符串索引或者数字的顺序索引)

前两个 :update和add的区别呢,就是如果add发现已经存在的数据,直接return,但是update会修改

使用例子: $foo['bar'] = "xxx";

zend_hash_add(ht,"bar",sizeof("bar"),"xxx",sizeof("xxx"),NULL);

后两个: zend_hash_next_index_insert会自己计算出下一个index的索引值,因此不需要索引参数。如果需要下一个的索引值,可以用ulong nextid = zend_hash_next_free_element(ht); 配合zend_hash_index_update(ht,nextid,&data,sizeof(data),NULL);

查找索引值:

int zend_hash_find(HashTable *ht,char *arKey,unit nKeyLen,void **pData);


void  hash_sample(HashTable *ht, sample_data *data1){//往hashtable内添加一个新值,并且提取出来
  sample_data *data2;
  ulong targetID = zend_hash_next_free_element(ht);
  if(zend_hash_index_update(ht,targetID,data1,sizeof(sample_data),NULL)  == FAILURE){
     return; //理论不发生
  }
  if(zend_hash_index_find(ht,targetID,(void **)&data2) == FAILURE){
    return; //理论不可能  
  }
  此处的data1 != data2,但*data1 == *data2。即他们的值相同,但是地址不同,因为hashtable的更新值,是把要插入的数据(data1)copy一份。所以hash桶存的指针与data1穿来的指针分别是两个独立的空间
}

检查数据是否存在:
int zend_hash_exists(HashTable *ht,char *arKey,uint nKeyLen);
int zend_hash_index_exists(HashTable *ht,ulong h);
这两个函数都不会返回SUCCESS/FAILURE ,只有0和1

if(zend_hash_exists(EG(active_symbol_table,"foo",sizeof("foo")))){
}
else{
}
这段代码等价与 isset($foo)    所以这里是当前符号表active_symbol_table

拷贝和合并

void zend_hash_copy(HashTable *a,HashTabel *b,copy_ctor_func_t pCopyConstructor,void *tmp,unit size);

tmp 在4.3以后为NULL,size是成员占的字节数,对于用户空间的hash变量,则为sizeof(zval *)。b中的每个元素会拷贝到a中去,并且由pCopyConstructor函数进行处理。对于数组变量这种类型的数据,是用引用计数的方式,不是直接销毁。

zend_hash_merge和zend_hash_copy的唯一区别是,多一个int overwrite参数,表示是否覆盖

void *tmp, uint size, int overwrite);

还有一种方式,是选择性拷贝,自定义一个函数进行选择性拷贝:zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam);

typedef zend_bool (*merge_checker_func_t)(HashTable *target_ht, void *source_data, zend_hash_key *hash_key, void *pParam);//这是函数原型 

zend_bool  choice(HashTable *ht,void *pData,zend_hash_key *hash_key,void *pPrama){ //这里进行选择
    return (hash_key->arKey && hash_key->nKeyLength); //通过一个key和长度确定一个元素(可以看看hash_key的结构)
}

void merge_func(HashTable *a,HashTable *b){
  zend_hash_merge_ex(HashTable *a,HashTable *b,zval_add_ref,sizeof(zval *),choice,NULL);
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容