Skip to content

Commit 724ae5d

Browse files
committed
update hash
1 parent 7b66791 commit 724ae5d

File tree

1 file changed

+110
-3
lines changed

1 file changed

+110
-3
lines changed

7/var.md

Lines changed: 110 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ zval的类型通过`Z_TYPE(zval)`、`Z_TYPE_P(zval*)`两个宏获取,这个值
9797
#define Z_TRY_DELREF(z) Z_TRY_DELREF_P(&(z))
9898
```
9999
### 7.7.4 字符串操作
100-
zend_string常用的宏及函数
100+
PHP中字符串(即:zend_string)操作相关的宏及函数
101101
```c
102102
//创建zend_string
103103
zend_string *zend_string_init(const char *str, size_t len, int persistent);
@@ -117,6 +117,15 @@ zend_string *zend_string_extend(zend_string *s, size_t len, int persistent);
117117
//截断字符串,与zend_string_realloc()类似,不同的是len不能大于s的长度
118118
zend_string *zend_string_truncate(zend_string *s, size_t len, int persistent);
119119

120+
//获取字符串refcount
121+
uint32_t zend_string_refcount(const zend_string *s);
122+
123+
//增加字符串refcount
124+
uint32_t zend_string_addref(zend_string *s);
125+
126+
//减少字符串refcount
127+
uint32_t zend_string_delref(zend_string *s);
128+
120129
//释放字符串,减少refcount,为0时销毁
121130
void zend_string_release(zend_string *s);
122131

@@ -146,8 +155,9 @@ zend_bool zend_string_equals(zend_string *s1, zend_string *s2);
146155
* __ht:__ 数组地址HashTable*,如果内部使用可以直接通过emalloc分配
147156
* __nSize:__ 初始化大小,只是参考值,这个值会被对齐到2^n,最小为8
148157
* __pHashFunction:__ 无用,设置为NULL即可
149-
* __pDestructor:__ 销毁或更新数组元素时会回调这个函数处理,比如在函数中创建一个数组返回给PHP用户空间作为变量使用,则需要将这个值设为ZVAL_PTR_DTOR,当变量销毁时将调用此函数进行清理,如果不设置的话可能会造成内存泄漏
158+
* __pDestructor:__ 删除或更新数组元素时会调用这个函数对操作的元素进行处理,比如将一个字符串插入数组,字符串的refcount增加,删除时不是简单的将元素的Bucket删除就可以了,还需要对其refcount进行处理,这个函数就是进行清理工作的
150159
* __persistent:__ 是否持久化
160+
151161
示例:
152162
```c
153163
zval array;
@@ -157,7 +167,104 @@ ZVAL_NEW_ARR(&array);
157167
zend_hash_init(Z_ARRVAL(array), size, NULL, ZVAL_PTR_DTOR, 0);
158168
```
159169
#### 7.7.5.2 插入、更新元素
170+
数组元素的插入、更新主要有三种情况:key为zend_string、key为普通字符串、key为数值索引,相关的宏及函数:
171+
```c
172+
// 1) key为zend_string
173+
174+
//插入或更新元素,会增加key的refcount
175+
#define zend_hash_update(ht, key, pData) \
176+
_zend_hash_update(ht, key, pData ZEND_FILE_LINE_CC)
177+
178+
//插入或更新元素,当Bucket类型为indirect时,将pData更新至indirect的值,而不是更新Bucket
179+
#define zend_hash_update_ind(ht, key, pData) \
180+
_zend_hash_update_ind(ht, key, pData ZEND_FILE_LINE_CC)
181+
182+
//添加元素,与zend_hash_update()类似,不同的地方在于如果元素已经存在则不会更新
183+
#define zend_hash_add(ht, key, pData) \
184+
_zend_hash_add(ht, key, pData ZEND_FILE_LINE_CC)
185+
186+
//直接插入元素,不管key存在与否,如果存在也不覆盖原来元素,而是当做哈希冲突处理,所有会出现一个数组中key相同的情况,慎用!!!
187+
#define zend_hash_add_new(ht, key, pData) \
188+
_zend_hash_add_new(ht, key, pData ZEND_FILE_LINE_CC)
189+
190+
// 2) key为普通字符串:char*
191+
192+
//与上面几个对应,这里的key为普通字符串,会自动生成zend_string的key
193+
#define zend_hash_str_update(ht, key, len, pData) \
194+
_zend_hash_str_update(ht, key, len, pData ZEND_FILE_LINE_CC)
195+
#define zend_hash_str_update_ind(ht, key, len, pData) \
196+
_zend_hash_str_update_ind(ht, key, len, pData ZEND_FILE_LINE_CC)
197+
#define zend_hash_str_add(ht, key, len, pData) \
198+
_zend_hash_str_add(ht, key, len, pData ZEND_FILE_LINE_CC)
199+
#define zend_hash_str_add_new(ht, key, len, pData) \
200+
_zend_hash_str_add_new(ht, key, len, pData ZEND_FILE_LINE_CC)
201+
202+
// 3) key为数值索引
203+
204+
//插入元素,h为数值
205+
#define zend_hash_index_add(ht, h, pData) \
206+
_zend_hash_index_add(ht, h, pData ZEND_FILE_LINE_CC)
207+
208+
//与zend_hash_add_new()类似
209+
#define zend_hash_index_add_new(ht, h, pData) \
210+
_zend_hash_index_add_new(ht, h, pData ZEND_FILE_LINE_CC)
211+
212+
//更新第h个元素
213+
#define zend_hash_index_update(ht, h, pData) \
214+
_zend_hash_index_update(ht, h, pData ZEND_FILE_LINE_CC)
215+
216+
//使用自动索引值
217+
#define zend_hash_next_index_insert(ht, pData) \
218+
_zend_hash_next_index_insert(ht, pData ZEND_FILE_LINE_CC)
160219
220+
#define zend_hash_next_index_insert_new(ht, pData) \
221+
_zend_hash_next_index_insert_new(ht, pData ZEND_FILE_LINE_CC)
222+
```
161223
#### 7.7.5.3 查找元素
224+
```c
225+
//根据zend_string key查找数组元素
226+
ZEND_API zval* ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key);
227+
228+
//根据普通字符串key查找元素
229+
ZEND_API zval* ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *key, size_t len);
230+
231+
//获取数值索引元素
232+
ZEND_API zval* ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h);
233+
234+
//判断元素是否存在
235+
ZEND_API zend_bool ZEND_FASTCALL zend_hash_exists(const HashTable *ht, zend_string *key);
236+
ZEND_API zend_bool ZEND_FASTCALL zend_hash_str_exists(const HashTable *ht, const char *str, size_t len);
237+
ZEND_API zend_bool ZEND_FASTCALL zend_hash_index_exists(const HashTable *ht, zend_ulong h);
238+
239+
//获取数组元素数
240+
#define zend_hash_num_elements(ht) \
241+
(ht)->nNumOfElements
242+
//与zend_hash_num_elements()类似,会有一些特殊处理
243+
ZEND_API uint32_t zend_array_count(HashTable *ht);
244+
```
245+
#### 7.7.5.4 删除元素
246+
```c
247+
//删除key
248+
ZEND_API int ZEND_FASTCALL zend_hash_del(HashTable *ht, zend_string *key);
249+
250+
//与zend_hash_del()类似,不同地方是如果元素类型为indirect则同时销毁indirect的值
251+
ZEND_API int ZEND_FASTCALL zend_hash_del_ind(HashTable *ht, zend_string *key);
252+
ZEND_API int ZEND_FASTCALL zend_hash_str_del(HashTable *ht, const char *key, size_t len);
253+
ZEND_API int ZEND_FASTCALL zend_hash_str_del_ind(HashTable *ht, const char *key, size_t len);
254+
ZEND_API int ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong h);
255+
ZEND_API void ZEND_FASTCALL zend_hash_del_bucket(HashTable *ht, Bucket *p);
256+
```
257+
#### 7.7.5.5 数组遍历
258+
259+
260+
#### 7.7.5.6 其它操作
261+
```c
262+
#define zend_hash_merge(target, source, pCopyConstructor, overwrite) \
263+
_zend_hash_merge(target, source, pCopyConstructor, overwrite ZEND_FILE_LINE_CC)
264+
265+
#define zend_hash_sort(ht, compare_func, renumber) \
266+
zend_hash_sort_ex(ht, zend_sort, compare_func, renumber)
267+
```
268+
269+
#### 7.7.5.5 销毁数组
162270
163-
#### 7.7.5.4 销毁数组

0 commit comments

Comments
 (0)