static ZEND_INI_DISP(zend_gc_enabled_displayer_cb) /* {{{ */ { if (gc_enabled()) { ZEND_PUTS("On"); } else { ZEND_PUTS("Off"); } }
ZEND_HASH_FOREACH_KEY_VAL_IND(ht, num_key, string_key, tmp) { if (i++ > 0) { ZEND_PUTS(","); } ZEND_PUTS("["); if (string_key) { ZEND_WRITE(string_key->val, string_key->len); } else { zend_printf(ZEND_ULONG_FMT, num_key); } ZEND_PUTS("] => "); zend_print_flat_zval_r(tmp TSRMLS_CC); } ZEND_HASH_FOREACH_END();
ZEND_API void zend_print_flat_zval_r(zval *expr) /* {{{ */ { switch (Z_TYPE_P(expr)) { case IS_ARRAY: ZEND_PUTS("Array ("); if (Z_REFCOUNTED_P(expr)) { if (Z_IS_RECURSIVE_P(expr)) { ZEND_PUTS(" *RECURSION*"); return; } Z_PROTECT_RECURSION_P(expr); } print_flat_hash(Z_ARRVAL_P(expr)); ZEND_PUTS(")"); if (Z_REFCOUNTED_P(expr)) { Z_UNPROTECT_RECURSION_P(expr); } break; case IS_OBJECT: { HashTable *properties = NULL; zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr)); zend_printf("%s Object (", ZSTR_VAL(class_name)); zend_string_release(class_name); if (Z_IS_RECURSIVE_P(expr)) { ZEND_PUTS(" *RECURSION*"); return; } if (Z_OBJ_HANDLER_P(expr, get_properties)) { properties = Z_OBJPROP_P(expr); } if (properties) { Z_PROTECT_RECURSION_P(expr); print_flat_hash(properties); Z_UNPROTECT_RECURSION_P(expr); } ZEND_PUTS(")"); break; } case IS_REFERENCE: zend_print_flat_zval_r(Z_REFVAL_P(expr)); break; default: zend_print_variable(expr); break; } }
ZEND_API void zend_print_flat_zval_r(zval *expr) /* {{{ */ { switch (Z_TYPE_P(expr)) { case IS_ARRAY: ZEND_PUTS("Array ("); if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr)) && ++Z_ARRVAL_P(expr)->u.v.nApplyCount>1) { ZEND_PUTS(" *RECURSION*"); Z_ARRVAL_P(expr)->u.v.nApplyCount--; return; } print_flat_hash(Z_ARRVAL_P(expr)); ZEND_PUTS(")"); if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr))) { Z_ARRVAL_P(expr)->u.v.nApplyCount--; } break; case IS_OBJECT: { HashTable *properties = NULL; zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr)); zend_printf("%s Object (", ZSTR_VAL(class_name)); zend_string_release(class_name); if (Z_OBJ_APPLY_COUNT_P(expr) > 0) { ZEND_PUTS(" *RECURSION*"); return; } if (Z_OBJ_HANDLER_P(expr, get_properties)) { properties = Z_OBJPROP_P(expr); } if (properties) { Z_OBJ_INC_APPLY_COUNT_P(expr); print_flat_hash(properties); Z_OBJ_DEC_APPLY_COUNT_P(expr); } ZEND_PUTS(")"); break; } case IS_REFERENCE: zend_print_flat_zval_r(Z_REFVAL_P(expr)); break; default: zend_print_variable(expr); break; } }
static void php_object_property_dump(zval *zv, zend_ulong index, zend_string *key, int level) /* {{{ */ { const char *prop_name, *class_name; if (key == NULL) { /* numeric key */ php_printf("%*c[" ZEND_LONG_FMT "]=>\n", level + 1, ' ', index); } else { /* string key */ int unmangle = zend_unmangle_property_name(key, &class_name, &prop_name); php_printf("%*c[", level + 1, ' '); if (class_name && unmangle == SUCCESS) { if (class_name[0] == '*') { php_printf("\"%s\":protected", prop_name); } else { php_printf("\"%s\":\"%s\":private", prop_name, class_name); } } else { php_printf("\""); PHPWRITE(ZSTR_VAL(key), ZSTR_LEN(key)); php_printf("\""); } ZEND_PUTS("]=>\n"); } php_var_dump(zv, level + 2); }
static void print_flat_hash(HashTable *ht) /* {{{ */ { zval *tmp; zend_string *string_key; zend_ulong num_key; int i = 0; ZEND_HASH_FOREACH_KEY_VAL_IND(ht, num_key, string_key, tmp) { if (i++ > 0) { ZEND_PUTS(","); } ZEND_PUTS("["); if (string_key) { ZEND_WRITE(ZSTR_VAL(string_key), ZSTR_LEN(string_key)); } else { zend_printf(ZEND_ULONG_FMT, num_key); } ZEND_PUTS("] => "); zend_print_flat_zval_r(tmp); } ZEND_HASH_FOREACH_END(); }
ZEND_API void zend_html_putc(char c) { switch (c) { case '\n': ZEND_PUTS("<br />"); break; case '<': ZEND_PUTS("<"); break; case '>': ZEND_PUTS(">"); break; case '&': ZEND_PUTS("&"); break; case ' ': ZEND_PUTS(" "); break; case '\t': ZEND_PUTS(" "); break; default: ZEND_PUTC(c); break; } }
static void php_object_property_dump(zend_property_info *prop_info, zval *zv, zend_ulong index, zend_string *key, int level) /* {{{ */ { const char *prop_name, *class_name; if (key == NULL) { /* numeric key */ php_printf("%*c[" ZEND_LONG_FMT "]=>\n", level + 1, ' ', index); } else { /* string key */ int unmangle = zend_unmangle_property_name(key, &class_name, &prop_name); php_printf("%*c[", level + 1, ' '); if (class_name && unmangle == SUCCESS) { if (class_name[0] == '*') { php_printf("\"%s\":protected", prop_name); } else { php_printf("\"%s\":\"%s\":private", prop_name, class_name); } } else { php_printf("\""); PHPWRITE(ZSTR_VAL(key), ZSTR_LEN(key)); php_printf("\""); } ZEND_PUTS("]=>\n"); } if (Z_TYPE_P(zv) == IS_UNDEF) { ZEND_ASSERT(prop_info->type); php_printf("%*cuninitialized(%s%s)\n", level + 1, ' ', ZEND_TYPE_ALLOW_NULL(prop_info->type) ? "?" : "", ZEND_TYPE_IS_CLASS(prop_info->type) ? ZSTR_VAL(ZEND_TYPE_IS_CE(prop_info->type) ? ZEND_TYPE_CE(prop_info->type)->name : ZEND_TYPE_NAME(prop_info->type)) : zend_get_type_by_const(ZEND_TYPE_CODE(prop_info->type))); } else { php_var_dump(zv, level + 2); } }
ZEND_API void zend_indent() { zval token; int token_type; int in_string=0; int nest_level=0; int emit_whitespace[256]; int i; TSRMLS_FETCH(); memset(emit_whitespace, 0, sizeof(int)*256); /* highlight stuff coming back from zendlex() */ token.type = 0; while ((token_type=lex_scan(&token TSRMLS_CC))) { switch (token_type) { case T_INLINE_HTML: zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng)); break; case T_WHITESPACE: { token.type = 0; /* eat whitespace, emit newlines */ for (i=0; i<LANG_SCNG(yy_leng); i++) { emit_whitespace[(unsigned char) LANG_SCNG(yy_text)[i]]++; } continue; } break; case '"': in_string = !in_string; /* break missing intentionally */ default: if (token.type==0) { /* keyword */ switch (token_type) { case ',': ZEND_PUTS(", "); goto dflt_printout; break; case '{': nest_level++; if (emit_whitespace['\n']>0) { ZEND_PUTS(" {\n"); memset(emit_whitespace, 0, sizeof(int)*256); } else { ZEND_PUTS("{"); } break; case '}': nest_level--; if (emit_whitespace['\n']==0) { ZEND_PUTS("\n"); } for (i=0; i<nest_level; i++) { ZEND_PUTS(" "); } goto dflt_printout; break; dflt_printout: default: if (emit_whitespace['\n']>0) { for (i=0; i<emit_whitespace['\n']; i++) { ZEND_PUTS("\n"); } memset(emit_whitespace, 0, sizeof(int)*256); for (i=0; i<nest_level; i++) { ZEND_PUTS(" "); } } else { handle_whitespace(emit_whitespace); } zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng)); break; } } else { handle_whitespace(emit_whitespace); if (in_string) { zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng)); /* a part of a string */ } else { zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng)); } } break; } if (token.type == IS_STRING) { switch (token_type) { case T_OPEN_TAG: case T_CLOSE_TAG: case T_WHITESPACE: break; default: efree(token.value.str.val); break; } } token.type = 0; } }
ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) { uint nIndex; Bucket *p; #ifdef ZEND_SIGNALS TSRMLS_FETCH(); #endif IS_CONSISTENT(ht); CHECK_INIT(ht); if (flag & HASH_NEXT_INSERT) { h = ht->nNextFreeElement; } nIndex = h & ht->nTableMask; p = ht->arBuckets[nIndex]; while (p != NULL) { if ((p->nKeyLength == 0) && (p->h == h)) { if (flag & HASH_NEXT_INSERT || flag & HASH_ADD) { return FAILURE; } HANDLE_BLOCK_INTERRUPTIONS(); #if ZEND_DEBUG if (p->pData == pData) { ZEND_PUTS("Fatal error in zend_hash_index_update: p->pData == pData\n"); HANDLE_UNBLOCK_INTERRUPTIONS(); return FAILURE; } #endif if (ht->pDestructor) { ht->pDestructor(p->pData); } UPDATE_DATA(ht, p, pData, nDataSize); HANDLE_UNBLOCK_INTERRUPTIONS(); if ((long)h >= (long)ht->nNextFreeElement) { ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX; } if (pDest) { *pDest = p->pData; } return SUCCESS; } p = p->pNext; } p = (Bucket *) pemalloc_rel(sizeof(Bucket), ht->persistent); if (!p) { return FAILURE; } p->arKey = NULL; p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */ p->h = h; INIT_DATA(ht, p, pData, nDataSize); if (pDest) { *pDest = p->pData; } CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]); HANDLE_BLOCK_INTERRUPTIONS(); ht->arBuckets[nIndex] = p; CONNECT_TO_GLOBAL_DLLIST(p, ht); HANDLE_UNBLOCK_INTERRUPTIONS(); if ((long)h >= (long)ht->nNextFreeElement) { ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX; } ht->nNumOfElements++; ZEND_HASH_IF_FULL_DO_RESIZE(ht); return SUCCESS; }
ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) { uint nIndex; Bucket *p; #ifdef ZEND_SIGNALS TSRMLS_FETCH(); #endif IS_CONSISTENT(ht); if (nKeyLength == 0) { return zend_hash_index_update(ht, h, pData, nDataSize, pDest); } CHECK_INIT(ht); nIndex = h & ht->nTableMask; p = ht->arBuckets[nIndex]; while (p != NULL) { if (p->arKey == arKey || ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) { if (flag & HASH_ADD) { return FAILURE; } HANDLE_BLOCK_INTERRUPTIONS(); #if ZEND_DEBUG if (p->pData == pData) { ZEND_PUTS("Fatal error in zend_hash_update: p->pData == pData\n"); HANDLE_UNBLOCK_INTERRUPTIONS(); return FAILURE; } #endif if (ht->pDestructor) { ht->pDestructor(p->pData); } UPDATE_DATA(ht, p, pData, nDataSize); if (pDest) { *pDest = p->pData; } HANDLE_UNBLOCK_INTERRUPTIONS(); return SUCCESS; } p = p->pNext; } if (IS_INTERNED(arKey)) { p = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent); if (!p) { return FAILURE; } p->arKey = arKey; } else { p = (Bucket *) pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent); if (!p) { return FAILURE; } p->arKey = (const char*)(p + 1); memcpy((char*)p->arKey, arKey, nKeyLength); } p->nKeyLength = nKeyLength; INIT_DATA(ht, p, pData, nDataSize); p->h = h; CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]); if (pDest) { *pDest = p->pData; } HANDLE_BLOCK_INTERRUPTIONS(); ht->arBuckets[nIndex] = p; CONNECT_TO_GLOBAL_DLLIST(p, ht); HANDLE_UNBLOCK_INTERRUPTIONS(); ht->nNumOfElements++; ZEND_HASH_IF_FULL_DO_RESIZE(ht); /* If the Hash table is full, resize it */ return SUCCESS; }
/* 数字键值的插入修改 */ ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) { uint nIndex; Bucket *p; #ifdef ZEND_SIGNALS TSRMLS_FETCH(); #endif IS_CONSISTENT(ht); // 调试信息 CHECK_INIT(ht); // 如果是新增元素,则h等于下一个数字索引的位置 if (flag & HASH_NEXT_INSERT) { h = ht->nNextFreeElement; } // 计算键值在HashTable中的存储位置为nIndex nIndex = h & ht->nTableMask; p = ht->arBuckets[nIndex]; /* 取得索引对应的Bucket的指针 */ // 循环Bucket中含有nIndex键值的链表 while (p != NULL) { // p 不为NULL说明Bucket中存在键值为nIndex的元素 if ((p->nKeyLength == 0) && (p->h == h)) { // 如果是数字键值且键值相同 if (flag & HASH_NEXT_INSERT || flag & HASH_ADD) { // 如果是新增元素,则插入失败 return FAILURE; } HANDLE_BLOCK_INTERRUPTIONS(); #if ZEND_DEBUG if (p->pData == pData) { ZEND_PUTS("Fatal error in " "zend_hash_index_update: p->pData == " "pData\n"); HANDLE_UNBLOCK_INTERRUPTIONS(); return FAILURE; } #endif // 上面的代码return ,说明是更新Bucket中已有键值元素值 if (ht->pDestructor) { // 如果数据元素存在,则将原来的数据销毁 ht->pDestructor(p->pData); } UPDATE_DATA(ht, p, pData, nDataSize); // 更新数据值 HANDLE_UNBLOCK_INTERRUPTIONS(); if ((long)h >= (long)ht->nNextFreeElement) { ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX; } // 如果需要返回更新值,则将返回值赋值给pDest if (pDest) { *pDest = p->pData; } return SUCCESS; } // 移动到链表的下一个元素 p = p->pNext; } // 如果是新增,为新增元素分配一个Bucket空间 p = (Bucket *)pemalloc_rel(sizeof(Bucket), ht->persistent); if (!p) { return FAILURE; } // 赋值 p->arKey = NULL; p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */ p->h = h; INIT_DATA(ht, p, pData, nDataSize); // 如果需要返回更新值,则将返回值赋值给pDest if (pDest) { *pDest = p->pData; } CONNECT_TO_BUCKET_DLLIST( p, ht->arBuckets[nIndex]); // 将Bucket加入到对应的桶双向链表中 HANDLE_BLOCK_INTERRUPTIONS(); ht->arBuckets[nIndex] = p; CONNECT_TO_GLOBAL_DLLIST( p, ht); // 将新的Bucket元素添加到哈希表的双向链表中 HANDLE_UNBLOCK_INTERRUPTIONS(); if ((long)h >= (long)ht->nNextFreeElement) { ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX; } ht->nNumOfElements++; ZEND_HASH_IF_FULL_DO_RESIZE( ht); /* 如果此时数组的容量满了,则重新分配空间。*/ return SUCCESS; }
/* 插入新值到哈希表中 */ ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) { ulong h; uint nIndex; Bucket *p; #ifdef ZEND_SIGNALS TSRMLS_FETCH(); #endif IS_CONSISTENT(ht); /* 键值不能为空字符串 */ if (nKeyLength <= 0) { #if ZEND_DEBUG ZEND_PUTS("zend_hash_update: Can't put in empty key\n"); #endif return FAILURE; } /* 检查哈希表是否以及初始化,如果没有初始化则进行初始化 */ CHECK_INIT(ht); /* 计算key代表的哈希值以及获取其在arBuckets数组中的下标 */ h = zend_inline_hash_func(arKey, nKeyLength); nIndex = h & ht->nTableMask; p = ht->arBuckets[nIndex]; while (p != NULL) { if (p->arKey == arKey || ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) { /* 需要更新 */ if (flag & HASH_ADD) { /* 如果是插入的话就返回,不能插入具有相同键值的元素 */ return FAILURE; } HANDLE_BLOCK_INTERRUPTIONS(); #if ZEND_DEBUG if (p->pData == pData) { ZEND_PUTS("Fatal error in zend_hash_update: " "p->pData == pData\n"); HANDLE_UNBLOCK_INTERRUPTIONS(); return FAILURE; } #endif if (ht->pDestructor) { /* 如果有析构函数,则将指向数据的指针释放掉 */ ht->pDestructor(p->pData); } /* 更新数据 */ UPDATE_DATA(ht, p, pData, nDataSize); if (pDest) { *pDest = p->pData; } HANDLE_UNBLOCK_INTERRUPTIONS(); return SUCCESS; } /* 移动到具有相同hash值的bucket链表中的下一个bucket */ p = p->pNext; } if (IS_INTERNED(arKey)) { p = (Bucket *)pemalloc(sizeof(Bucket), ht->persistent); if (!p) { return FAILURE; } p->arKey = arKey; } else { p = (Bucket *)pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent); if (!p) { return FAILURE; } p->arKey = (const char *)(p + 1); memcpy((char *)p->arKey, arKey, nKeyLength); } /* 设置新的bucket的属性值及添加到哈希表中 */ p->nKeyLength = nKeyLength; INIT_DATA(ht, p, pData, nDataSize); p->h = h; CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]); if (pDest) { *pDest = p->pData; } HANDLE_BLOCK_INTERRUPTIONS(); CONNECT_TO_GLOBAL_DLLIST(p, ht); ht->arBuckets[nIndex] = p; HANDLE_UNBLOCK_INTERRUPTIONS(); ht->nNumOfElements++; ZEND_HASH_IF_FULL_DO_RESIZE( ht); /* If the Hash table is full, resize it */ return SUCCESS; }
ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) { ulong h; uint nIndex; Bucket *p; IS_CONSISTENT(ht); if (nKeyLength <= 0) { #if ZEND_DEBUG ZEND_PUTS("zend_hash_update: Can't put in empty key\n"); #endif return FAILURE; } h = zend_inline_hash_func(arKey, nKeyLength); nIndex = h & ht->nTableMask; p = ht->arBuckets[nIndex]; while (p != NULL) { if ((p->h == h) && (p->nKeyLength == nKeyLength)) { if (!memcmp(p->arKey, arKey, nKeyLength)) { if (flag & HASH_ADD) { return FAILURE; } HANDLE_BLOCK_INTERRUPTIONS(); #if ZEND_DEBUG if (p->pData == pData) { ZEND_PUTS("Fatal error in zend_hash_update: p->pData == pData\n"); HANDLE_UNBLOCK_INTERRUPTIONS(); return FAILURE; } #endif if (ht->pDestructor) { ht->pDestructor(p->pData); } UPDATE_DATA(ht, p, pData, nDataSize); if (pDest) { *pDest = p->pData; } HANDLE_UNBLOCK_INTERRUPTIONS(); return SUCCESS; } } p = p->pNext; } p = (Bucket *) pemalloc(sizeof(Bucket) - 1 + nKeyLength, ht->persistent); if (!p) { return FAILURE; } memcpy(p->arKey, arKey, nKeyLength); p->nKeyLength = nKeyLength; INIT_DATA(ht, p, pData, nDataSize); p->h = h; CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]); if (pDest) { *pDest = p->pData; } HANDLE_BLOCK_INTERRUPTIONS(); CONNECT_TO_GLOBAL_DLLIST(p, ht); ht->arBuckets[nIndex] = p; HANDLE_UNBLOCK_INTERRUPTIONS(); ht->nNumOfElements++; ZEND_HASH_IF_FULL_DO_RESIZE(ht); /* If the Hash table is full, resize it */ return SUCCESS; }
static void print_hash(HashTable *ht, int indent, zend_bool is_object TSRMLS_DC) { zval **tmp; char *string_key; HashPosition iterator; ulong num_key; uint str_len; int i; for (i=0; i<indent; i++) { ZEND_PUTS(" "); } ZEND_PUTS("(\n"); indent += PRINT_ZVAL_INDENT; zend_hash_internal_pointer_reset_ex(ht, &iterator); while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) { for (i=0; i<indent; i++) { ZEND_PUTS(" "); } ZEND_PUTS("["); switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) { case HASH_KEY_IS_STRING: if (is_object) { char *prop_name, *class_name; zend_unmangle_property_name(string_key, &class_name, &prop_name); ZEND_PUTS(prop_name); if (class_name) { if (class_name[0]=='*') { ZEND_PUTS(":protected"); } else { ZEND_PUTS(":private"); } } } else { ZEND_WRITE(string_key, str_len-1); } break; case HASH_KEY_IS_LONG: zend_printf("%ld", num_key); break; } ZEND_PUTS("] => "); zend_print_zval_r(*tmp, indent+PRINT_ZVAL_INDENT TSRMLS_CC); ZEND_PUTS("\n"); zend_hash_move_forward_ex(ht, &iterator); } indent -= PRINT_ZVAL_INDENT; for (i=0; i<indent; i++) { ZEND_PUTS(" "); } ZEND_PUTS(")\n"); }