


PHP extension and embedding--Arrays and hash tables in PHP extension 1_PHP tutorial
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:
int zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent)
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:
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);
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:
int zend_hash_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData); int zend_hash_index_find(HashTable *ht, ulong h, void **pData);
This can be seen more clearly in the example below:
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 */ }
int zend_hash_exists(HashTable *ht, char *arKey, uint nKeyLen); int zend_hash_index_exists(HashTable *ht, ulong h);
if (zend_hash_exists(EG(active_symbol_table), "foo", sizeof("foo"))) {//确定活动的符号表中是否存在foo变量 /* $foo is set */ } else { /* $foo does not exist */ }
Quick Population and Recall 当需要对同一个字符串的key进行许多操作的时候比如先检测有没有,然后插入再修改之类的,可以使用zend_get_hash_value来进行提速。这个函数的返回值可以和quick系列的函数使用,从而达到加速的目的。因为不需要再重复计算字符串的散列值,而是直接使用已有的散列值。
ulong zend_get_hash_value(char *arKey, uint nKeyLen);
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);
下面给出了一个在两个哈希表之间进行数据拷贝的例子:
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里面。 }
注意并没有zend_hash_del函数。
Copy and Merging 有三个方法可以进行数据的拷贝,先来看第一个:
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);
tmp这里放NULL,低版本才会用到。
size的话代表每个元素的大小,一般是sizeof(zval *)。
void zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite);
下面的这一组函数允许使用一个归并的检查进行选择性的复制:
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);
下面给出了一个应用的例子:
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); }

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

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

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

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.

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

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

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

The POSIX extensions for PHP are a set of functions and constants that allow PHP to interact with POSIX-compliant operating systems. POSIX (PortableOperatingSystemInterface) is a set of operating system interface standards designed to allow software developers to write applications that can run on various UNIX or UNIX-like operating systems. This article will introduce how to use POSIX extensions for PHP, including installation and use. 1. Install the POSIX extension of PHP in

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)
