@@ -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
103103zend_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的长度
118118zend_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时销毁
121130void 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 
153163zval array;
@@ -157,7 +167,104 @@ ZVAL_NEW_ARR(&array);
157167zend_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