@@ -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