Home Backend Development PHP Tutorial PHP extension and embedding--Arrays and hash tables in PHP extension 1_PHP tutorial

PHP extension and embedding--Arrays and hash tables in PHP extension 1_PHP tutorial

Jul 13, 2016 am 10:42 AM
Embed Expand

In PHP, the underlying implementation of arrays is hash tables, which appear in the form of key-value. In the Zend engine of PHP, there are special APIs for operating hash tables for different hash table operations.


Creation

For hash tables, the initialization method is the same every time, and is completed by the following function zend_hash_init:

1

2

3

int zend_hash_init(HashTable *ht, uint nSize,

    hash_func_t pHashFunction,

    dtor_func_t pDestructor, zend_bool persistent)

Copy after login
where ht is a pointer to the hash table, which can refer to an existing hashtable variable. You can also apply for memory for a new hashtable. The general method is:

ALLOC_HASHTABLE(ht), equivalent to ht = emalloc(sizeof(HashTable));.

nSize is the maximum number of elements in the hash table, which is considered to apply for memory in advance. If it is not an exponential multiple of 2, it will grow according to the following formula nSize = pow(2, ceil(log(nSize, 2)));, for example, if 5 is given, it will grow to 8. This should be for memory management comparison Convenience mechanism employed.

pHashFunction belongs to the zend eigine function of the previous version and can always be set to NULL in the new version.

pDestructor points to the entrance of the method called when an element in the hash table is deleted (zend_hash_del() zend_hash_update()), which is a corresponding callback function. If the method_name function is given, then when the function is implemented:

void method_name(void *pElement)
pElement points to the deleted element

persistent is a flag indicating whether it is a persistent hash table. Persistent data is independent of the request and will not be logged out during RSHUTDOWN. But if set to 1, ht must use pemalloc() when applying for memory.

For example: when initializing symbol_table in each php request life cycle, you will see zend_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0);
Whenever unset, the corresponding zval* stored in the hash table is sent to zval_ptr_dtor() for destruction.


Population:

There are four main functions for inserting and updating data in a hash table:

1

2

3

4

5

6

7

8

int zend_hash_add(HashTable *ht, char *arKey, uint nKeyLen,

                void *pData, uint nDataSize, void **pDest);

int zend_hash_update(HashTable *ht, char *arKey, uint nKeyLen,

                void *pData, uint nDataSize, void **pDest);

int zend_hash_index_update(HashTable *ht, ulong h,

                void *pData, uint nDataSize, void **pDest);

int zend_hash_next_index_insert(HashTable *ht,

                void *pData, uint nDataSize, void **pDest);

Copy after login
The first two functions add data with string index to the hashtable, such as $foo['bar'] = 'barvalue' in php, then in the extension:

zend_hash_add(fooHashTbl, "bar", sizeof("bar"), &barZval, sizeof(zval*), NULL);

Add the corresponding key value and corresponding table value to the hashtable.

The only difference between add and update is that if the key already exists, add will fail.

The last two functions are to add numerical index data to ht.

The zend_hash_next_index_insert() function does not require an index value parameter, but directly calculates the next numeric index value by itself.

If you want to get the numeric index value of the next element yourself, you can also get the index through zend_hash_next_free_element().
ulong nextid = zend_hash_next_free_element(ht);
zend_hash_index_update(ht, nextid, &data, sizeof(data), NULL);
The above code is equivalent to:

zend_hash_next_index_insert(HashTable *ht, &data,sizeof(data),NULL).

The pDest parameter can be used to store the address value of the newly added element.



Recall: Find

Generally speaking, there are two ways to obtain data in a hash table:

1

2

3

int zend_hash_find(HashTable *ht, char *arKey, uint nKeyLength,

                                        void **pData);

int zend_hash_index_find(HashTable *ht, ulong h, void **pData);

Copy after login

This can be seen more clearly in the example below:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

void hash_sample(HashTable *ht, sample_data *data1)

{

   sample_data *data2;

   ulong targetID = zend_hash_next_free_element(ht);//获取下一个索引的位置

   if (zend_hash_index_update(ht, targetID,

           data1, sizeof(sample_data), NULL) == FAILURE) {//把数据data1插入到哈希表的下一个索引的位置中去

       /* Should never happen */

       return;

   }

   if(zend_hash_index_find(ht, targetID, (void **)&data2) == FAILURE) {//利用id去寻找哈希表中的值,如果找到的话把值放在data2中。

       /* Very unlikely since we just added this element */

       return;

   }

   /* data1 != data2, however *data1 == *data2 */

}

Copy after login
In addition to obtaining the value in the hash table, sometimes it is more important to know the existence of some elements:

1

2

int zend_hash_exists(HashTable *ht, char *arKey, uint nKeyLen);

int zend_hash_index_exists(HashTable *ht, ulong h);

Copy after login
分别针对字符串索引和数字的索引。返回的是1和0.

1

2

3

4

5

6

if (zend_hash_exists(EG(active_symbol_table),

                                "foo", sizeof("foo"))) {//确定活动的符号表中是否存在foo变量

    /* $foo is set */

} else {

    /* $foo does not exist */

}

Copy after login


Quick Population and Recall 当需要对同一个字符串的key进行许多操作的时候比如先检测有没有,然后插入再修改之类的,可以使用zend_get_hash_value来进行提速。这个函数的返回值可以和quick系列的函数使用,从而达到加速的目的。因为不需要再重复计算字符串的散列值,而是直接使用已有的散列值

1

ulong zend_get_hash_value(char *arKey, uint nKeyLen);

Copy after login
用这个返回值传给下面的quick系列函数就可以达到加速的目的:

1

2

3

4

5

6

7

8

9

10

int zend_hash_quick_add(HashTable *ht,

    char *arKey, uint nKeyLen, ulong hashval,

    void *pData, uint nDataSize, void **pDest);

int zend_hash_quick_update(HashTable *ht,

    char *arKey, uint nKeyLen, ulong hashval,

    void *pData, uint nDataSize, void **pDest);

int zend_hash_quick_find(HashTable *ht,

    char *arKey, uint nKeyLen, ulong hashval, void **pData);

int zend_hash_quick_exists(HashTable *ht,

    char *arKey, uint nKeyLen, ulong hashval);

Copy after login

下面给出了一个在两个哈希表之间进行数据拷贝的例子:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

void php_sample_hash_copy(HashTable *hta, HashTable *htb,

                    char *arKey, uint nKeyLen TSRMLS_DC)

{

    ulong hashval = zend_get_hash_value(arKey, nKeyLen);//获得用来加速的散列值hashval

    zval **copyval;

    if (zend_hash_quick_find(hta, arKey, nKeyLen,

                hashval, (void**)©val) == FAILURE) {//首先要在hta table里面找到相应的元素,并且存储在copyval中。

        /* arKey doesn't actually exist */

        return;

    }

    /* The zval* is about to be owned by another hash table */

    (*copyval)->refcount__gc++;//相应zval*变量的引用次数+1

    zend_hash_quick_update(htb, arKey, nKeyLen, hashval,

                copyval, sizeof(zval*), NULL);//把从hta中拿来的copyval放在htb里面。

}

Copy after login

注意并没有zend_hash_del函数。

Copy and Merging 有三个方法可以进行数据的拷贝,先来看第一个:

1

2

3

4

typedef void (*copy_ctor_func_t)(void *pElement);

void zend_hash_copy(HashTable *target, HashTable *source,

            copy_ctor_func_t pCopyConstructor,

            void *tmp, uint size);

Copy after login
在source中的每个元素都会被拷贝到target中.通过pCopyConstructor的处理可以使得在拷贝变量的时候对这些变量的ref_count进行加一的操作。target中原有的与source中索引位置相同的元素会被替换掉,而其他的元素则会被保留。
tmp这里放NULL,低版本才会用到。
size的话代表每个元素的大小,一般是sizeof(zval *)。

1

2

3

void zend_hash_merge(HashTable *target, HashTable *source,

            copy_ctor_func_t pCopyConstructor,

            void *tmp, uint size, int overwrite);

Copy after login
主要是多了一个overwrite的参数,如果非0,那就跟copy一样,如果是0,那就对于已经存在的元素就不会进行复制了。

下面的这一组函数允许使用一个归并的检查进行选择性的复制:

1

2

3

4

5

typedef zend_bool (*merge_checker_func_t)(HashTable *target_ht,

    void *source_data, zend_hash_key *hash_key, void *pParam);

void zend_hash_merge_ex(HashTable *target, HashTable *source,

            copy_ctor_func_t pCopyConstructor, uint size,

            merge_checker_func_t pMergeSource, void *pParam);

Copy after login
pMergeSource回调函数使得可以选择性的进行合并,而不是全部合并,这个给人的感觉有点像c语言里面快速排序函数所留的函数入口,可以决定排序的方式。
下面给出了一个应用的例子:

1

2

3

4

5

6

7

8

9

10

11

zend_bool associative_only(HashTable *ht, void *pData,

            zend_hash_key *hash_key, void *pParam)

{

    /* True if there's a key, false if there's not */

    return (hash_key->arKey && hash_key->nKeyLength);//字符串类型的key,因为存在nKeyLength

}

void merge_associative(HashTable *target, HashTable *source)

{

    zend_hash_merge_ex(target, source, zval_add_ref,

                sizeof(zval*), associative_only, NULL);

}

Copy after login





















www.bkjia.comtruehttp://www.bkjia.com/PHPjc/635039.htmlTechArticle在php中,数组的底层实现就是哈希表,都是以key-value的形式出现的。在php的Zend引擎中,针对不同的哈希表操作,都有着专门的对哈希表进行...
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
1 months ago By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to use PHP's SNMP extension? How to use PHP's SNMP extension? Jun 02, 2023 am 10:22 AM

The SNMP extension for PHP is an extension that enables PHP to communicate with network devices through the SNMP protocol. Using this extension, you can easily obtain and modify the configuration information of network devices, such as CPU, memory, network interface and other information of routers, switches, etc. You can also perform control operations such as switching device ports. This article will introduce the basic knowledge of the SNMP protocol, how to install the SNMP extension of PHP, and how to use the SNMP extension in PHP to monitor and control network devices. 1. SN

Combining PHP with HTML: three techniques for embedding code Combining PHP with HTML: three techniques for embedding code Mar 06, 2024 am 08:09 AM

The combination of PHP and HTML is a common technology in web development. PHP can embed dynamic content in HTML files and implement auxiliary functions, which greatly improves the interactivity and customizability of the website. This article will introduce three techniques for embedding code and provide specific code examples for reference. 1. Use PHP tags to embed code. The most common way is to use PHP tags () to embed PHP code into HTML files to display dynamic content. For example, you can use PHP

Extensions and third-party modules for PHP functions Extensions and third-party modules for PHP functions Apr 13, 2024 pm 02:12 PM

To extend PHP function functionality, you can use extensions and third-party modules. Extensions provide additional functions and classes that can be installed and enabled through the pecl package manager. Third-party modules provide specific functionality and can be installed through the Composer package manager. Practical examples include using extensions to parse complex JSON data and using modules to validate data.

From start to finish: How to use php extension cURL to make HTTP requests From start to finish: How to use php extension cURL to make HTTP requests Jul 29, 2023 pm 05:07 PM

From start to finish: How to use php extension cURL for HTTP requests Introduction: In web development, it is often necessary to communicate with third-party APIs or other remote servers. Using cURL to make HTTP requests is a common and powerful way. This article will introduce how to use PHP to extend cURL to perform HTTP requests, and provide some practical code examples. 1. Preparation First, make sure that php has the cURL extension installed. You can execute php-m|grepcurl on the command line to check

How to install mbstring extension under CENTOS7? How to install mbstring extension under CENTOS7? Jan 06, 2024 pm 09:59 PM

1.UncaughtError:Calltoundefinedfunctionmb_strlen(); When the above error occurs, it means that we have not installed the mbstring extension; 2. Enter the PHP installation directory cd/temp001/php-7.1.0/ext/mbstring 3. Start phpize(/usr/local/bin /phpize or /usr/local/php7-abel001/bin/phpize) command to install php extension 4../configure--with-php-config=/usr/local/php7-abel

How to use the Aurora Push extension to implement batch message push function in PHP applications How to use the Aurora Push extension to implement batch message push function in PHP applications Jul 25, 2023 pm 08:07 PM

How to use the Aurora Push extension to implement batch message push function in PHP applications. In the development of mobile applications, message push is a very important function. Jiguang Push is a commonly used message push service that provides rich functions and interfaces. This article will introduce how to use the Aurora Push extension to implement batch message push functionality in PHP applications. Step 1: Register a Jiguang Push account and obtain an API key. First, we need to register on the Jiguang Push official website (https://www.jiguang.cn/push)

How to use PHP's ZipArchive extension? How to use PHP's ZipArchive extension? Jun 02, 2023 am 08:13 AM

PHP is a popular server-side language that can be used to develop web applications and process files. The ZipArchive extension for PHP is a powerful tool for manipulating zip files in PHP. In this article, we’ll cover how to use PHP’s ZipArchive extension to create, read, and modify zip files. 1. Install the ZipArchive extension. Before using the ZipArchive extension, you need to ensure that the extension has been installed. The installation method is as follows: 1. Install

Reasons and solutions why D drive cannot be expanded in win11 system Reasons and solutions why D drive cannot be expanded in win11 system Jan 08, 2024 pm 12:30 PM

Some users feel that their d drive space is not enough and want to expand the d drive space. However, during the operation, they find that their win11d drive cannot be expanded and the extended volume is gray. In fact, this may be due to insufficient disk space. Let’s take a look at the solutions below. Why the win11d disk cannot be expanded: 1. Insufficient space 1. First of all, to expand the d disk, you need to ensure that your disk has "available space", as shown in the figure. 2. If there is no available space like this, then there is naturally no way to expand. 3. If you want to expand the D drive at this time, you can find other disks, right-click and select "Compress Volume" 4. Enter the space you want to expand to compress, and then click "OK" to obtain the available space. 2. The disks are not adjacent 1. To expand a disk, you can

See all articles