惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
IT之家
IT之家
Microsoft Security Blog
Microsoft Security Blog
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
D
DataBreaches.Net
B
Blog RSS Feed
博客园_首页
The GitHub Blog
The GitHub Blog
I
InfoQ
L
LangChain Blog
G
Google Developers Blog
M
MIT News - Artificial intelligence
美团技术团队
腾讯CDC
V
Visual Studio Blog
aimingoo的专栏
aimingoo的专栏
博客园 - 聂微东
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Apple Machine Learning Research
Apple Machine Learning Research
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
博客园 - 叶小钗

博客园 - bqrm_521(小奎)

.net连接eDirectory,需要安全连接的解决方案 ObDereferenceObjectDeferDelete routine ObDereferenceObject routine ObCloseHandle routine InitializeObjectAttributes 宏 Driver Support Routines(驱动程序开发支持例程) AdapterControl routine Standard Driver Routines(标准驱动程序) DriverEntry 文件系统过滤驱动的DriverEntry PHP扩展的加载流程 PHP扩展中定义一个类 PHP的HashTable(二) PHP扩展中访问全局变量$_POST,$_GET,$_SERVER等 开发PHP扩展(一) 要搬家了,全部书籍10元转让 scribe2.2 ssh 使用技巧 安装scribe
PHP的HashTable(一)
bqrm_521(小奎) · 2012-10-01 · via 博客园 - bqrm_521(小奎)

数据定义 :

/*zend_hash.h */

typedef struct bucket {
    ulong h;                        /* Used for numeric indexing */
    uint nKeyLength;  
    void *pData; /* 这里是array里面item对对应的数据,有点特殊的是,若存的是指针,这是指向下一个成员pDataPtr的指针,pDataPtr才是真正存放指针value的地方,有点不明白 */
    void *pDataPtr;
    struct bucket *pListNext;
    struct bucket *pListLast;
    struct bucket *pNext;
    struct bucket *pLast;
    char arKey[1]; /* Must be last element 这是柔性数组成员或者叫伸缩性数组成员 */
} Bucket;

typedef struct _hashtable {
    uint nTableSize; 
    uint nTableMask; /* nTableSize-1,用来给key的hash值取模决定key最终落在哪个槽内 */
    uint nNumOfElements;
    ulong nNextFreeElement;
    Bucket *pInternalPointer;    /* Used for element traversal */
    Bucket *pListHead;
    Bucket *pListTail;
    Bucket **arBuckets;
    dtor_func_t pDestructor;
    zend_bool persistent;
    unsigned char nApplyCount;
    zend_bool bApplyProtection;
#if ZEND_DEBUG
    int inconsistent;
#endif

} HashTable;  

 #define UPDATE_DATA(ht, p, pData, nDataSize)                                            \

    

if (nDataSize == sizeof(void*)) { /* 若value所占字节数 == sizeof(void*) */              \
        if ((p)->pData != &(p)->pDataPtr) {                                               \
            pefree_rel((p)->pData, (ht)->persistent);                                     \
        }                                                                                 \
        memcpy(&(p)->pDataPtr, pData, sizeof(void *));   /* 把pData存入pDataPtr */          \
        (p)->pData = &(p)->pDataPtr;                     /* pData指向 pDataPtr */           \
    } else {                                                                            \
        if ((p)->pData == &(p)->pDataPtr) {                                                \
            (p)->pData = (void *) pemalloc_rel(nDataSize, (ht)->persistent);            \
            (p)->pDataPtr=NULL;                                                            \
        } else {                                                                        \
            (p)->pData = (void *) perealloc_rel((p)->pData, nDataSize, (ht)->persistent);    \
            /* (p)->pDataPtr is already NULL so no need to initialize it */                \
        }                                                                                \
        memcpy((p)->pData, pData, nDataSize);          /* pData 存入 Bucket->pData */     \
    }

#define INIT_DATA(ht, p, pData, nDataSize);                                \
    if (nDataSize == sizeof(void*)) {                                    \
        memcpy(&(p)->pDataPtr, pData, sizeof(void *));                    \
        (p)->pData = &(p)->pDataPtr;                                    \
    } else {                                                            \
        (p)->pData = (void *) pemalloc_rel(nDataSize, (ht)->persistent);\
        if (!(p)->pData) {                                                \
            pefree_rel(p, (ht)->persistent);                            \
            return FAILURE;                                                \
        }                                                                \
        memcpy((p)->pData, pData, nDataSize);                            \
        (p)->pDataPtr=NULL;                                                \
    }

/* zend_hash_add_or_update */
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; /* key的hash值 */
    uint nIndex; /*  hash 值 对应的槽的 索引 */
    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);  /*  计算key的hash值 */
    nIndex = h & ht->nTableMask;  /* 通过取模计算key的hash值所对应的槽的索引 */

    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; /* 槽头指向这个新的Bucket */
    HANDLE_UNBLOCK_INTERRUPTIONS();

    ht->nNumOfElements++;
    ZEND_HASH_IF_FULL_DO_RESIZE(ht);        /* If the Hash table is full, resize it */
    return SUCCESS;
}

/* end */