PHP extension development-array usage and HashTable introduction _ PHP Tutorial

Source: Internet
Author: User
PHP extension development-array usage and HashTable introduction. 1 array This section describes php arrays. in php, arrays are implemented using HashTable. This section describes HashTable in detail, and then how to use the HastTable1.1 1 array.

This section describes php arrays. in php, arrays are implemented using HashTable. This section describes HashTable in detail, and then describes how to use HastTable.

1.1 Variable-length struct

The so-called variable length struct is actually a special usage of the C language struct, and there is no novelty. Let's take a look at a general definition method of the variable length struct.

Typedef struct bucket {

Int n;

Char key [30];

Char value [1];

} Bucket;

We have defined a struct Bucket. we want to use this struct to store the student's profile. The key is used to store the student's name, and the value is used to store the student's profile. You may be curious. our value declares how much information can be stored in 1. 1 char?

In fact, for variable-length struct, we cannot directly define variables in use, for example, Bucket bucket. if you use them like this, the value certainly cannot store much information. For a variable-length struct, we need to declare a pointer to the variable-length struct before allocating the function space through the malloc function. what is the length of the space we need, we can use malloc. The general usage is as follows:

Bucket * pBucket;

PBucket = malloc (sizeof (Bucket) + n * sizeof (char ));

N indicates the length of the value. If this is used, will the string pointed to by value become longer soon!

1.2 Introduction to Hashtable

Let's take a look at the definition of HashTable.

Struct _ hashtable;

Typedef struct bucket {

Ulong h; // used when the element is a digital index

Uint nKeyLength; // when a string index is used, this variable indicates the index length, and the index (string) is stored in the last element aKey.

Void * pData; // used to point to the stored data. if the stored data is a pointer, pDataPtr points to the data, and pData points to pDataPtr.

Void * pDataPtr;

Struct bucket * pListNext; // previous element

Struct bucket * pListLast; // The next element

Struct bucket * pNext; // pointer to the next bucket

Struct bucket * pLast; // pointer to the previous bucket

Char arKey [1]; // it must be placed at the end to implement a variable-length struct.

} Bucket;

Typedef struct _ hashtable {

Uint nTableSize; // The size of the hash table

Uint nTableMask; // The value is equal to nTableSize-1.

Uint nNumOfElements; // records the number of records saved in the current HashTable

Ulong nNextFreeElement; // point to the next idle Bucket

Bucket * pInternalPointer; // This variable is used for array inversion.

Bucket * pListHead; // The header pointing to the Bucket

Bucket * pListTail; // point to the end of the Bucket

Bucket ** arBuckets;

Dtor_func_t pDestructor; // Function pointer, which is automatically called during addition, deletion, modification, and query of arrays for some cleanup operations

Zend_bool persistent; // whether it is persistent

Unsigned char nApplyCount;

Zend_bool bApplyProtection; // Works with nApplyCount to prevent infinite recursion of array traversal

# If ZEND_DEBUG

Int inconsistent;

# Endif

} HashTable;

I hope you can take a good look at the above definition. I will not understand some things when I come out. it is better to see the code clearly. PHP arrays are actually two-way linked lists with header nodes. HashTable is the header, and the Bucket stores the specific node information.

1.3 HashTable internal function analysis

1.3.1 macro HASH_PROTECT_RECURSION

# DefineHASH_PROTECT_RECURSION (ht )\

If (ht)-> bApplyProtection ){\

If (ht)-> nApplyCount ++> = 3 ){\

Zend_error (E_ERROR, "Nestinglevel too deep-recursive dependency? ");\

}\

}

This macro is mainly used to prevent circular references.

1.3.2 macro ZEND_HASH_IF_FULL_DO_RESIZE

# DefineZEND_HASH_IF_FULL_DO_RESIZE (ht )\

If (ht)-> nNumOfElements> (ht)-> nTableSize ){\

Zend_hash_do_resize (ht );\

}

This macro is used to check whether the number of elements in HashTable is greater than the total size of HashTable. if the number is greater than the size of HashTable, we will re-allocate the space. Let's take a look at zend_hash_do_resize.

Static int zend_hash_do_resize (HashTable * ht)

{

Bucket ** t;

IS_CONSISTENT (ht );

If (ht-> nTableSize <1)> 0) {/* Let's double the table size */

T = (Bucket **) perealloc_recoverable (ht-> arBuckets,

(Ht-> nTableSize <1) * sizeof (Bucket *), ht-> persistent );

If (t ){

HANDLE_BLOCK_INTERRUPTIONS ();

Ht-> arBuckets = t;

Ht-> nTableSize = (ht-> nTableSize <1 );

Ht-> nTableMask = ht-> nTableSize-1;

Zend_hash_rehash (ht );

HANDLE_UNBLOCK_INTERRUPTIONS ();

Return SUCCESS;

}

Return FAILURE;

}

Return SUCCESS;

}

From the code above, we can see that when HashTable allocates space, the newly allocated space is twice the original space.

1.3.3 function _ zend_hash_init

This function is used to initialize HashTable. let's take a look at the code:

ZEND_API int _ zend_hash_init (HashTable * ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)

{

Uint I = 3; // The HashTable size defaults to no power 3 of 2

Bucket ** tmp;

SET_INCONSISTENT (HT_ OK );

If (nSize> = 0x80000000 ){

Ht-> nTableSize = 0x80000000;

} Else {

While (1U <I) <nSize ){

I ++;

}

Ht-> nTableSize = 1 <I;

}

Ht-> nTableMask = ht-> nTableSize-1;

Ht-> pDestructor = pDestructor;

Ht-> arBuckets = NULL;

Ht-> pListHead = NULL;

Ht-> pListTail = NULL;

Ht-> nNumOfElements = 0;

Ht-> nNextFreeElement = 0;

Ht-> pInternalPointer = NULL;

Ht-> persistent = persistent;

Ht-> nApplyCount = 0;

Ht-> bApplyProtection = 1;

/* Uses ecalloc () so that Bucket * = NULL */

If (persistent ){

Tmp = (Bucket **) calloc (ht-> nTableSize, sizeof (Bucket *));

If (! Tmp ){

Return FAILURE;

}

Ht-> arBuckets = tmp;

} Else {

Tmp = (Bucket **) ecalloc_rel (ht-> nTableSize, sizeof (Bucket *));

If (tmp ){

Ht-> arBuckets = tmp;

}

}

Return SUCCESS;

}

We can see that the HashTable size is initialized to the npower of 2. In addition, we can see two memory modes: calloc and ecalloc_rel, the memory allocation methods are described in detail. if you are interested, you can check them by yourself.

1.3.4 function _ zend_hash_add_or_update

This function adds or modifies element information to HashTable.

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 inempty 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;

}

1.3.5 macro CONNECT_TO_BUCKET_DLLIST

# Define CONNECT_TO_BUCKET_DLLIST (element, list_head )\

(Element)-> pNext = (list_head );\

(Element)-> pLast = NULL ;\

If (element)-> pNext ){\

(Element)-> pNext-> pLast = (element );\

}

This macro adds the bucket to the bucket linked list.

1.3.6 Other functions or macro definitions

We will just briefly introduce HashTable. if you want to learn more about HashTable, we suggest you look at the php source code. the HashTable code is in Zend/zend_hash.h and Zend/zend_hash.c.

Zend_hash_add_empty_element adds an empty element to the function.

Zend_hash_del_key_or_index deletes elements based on the index.

Zend_hash_reverse_apply reverse traversal HashTable

Zend_hash_copy copy

_ Zend_hash_merge merge

Zend_hash_find string index lookup

Zend_hash_index_find numeric index method

Encapsulation of the two functions above zend_hash_quick_find

Zend_hash_exists index

Zend_hash_index_exists index

Encapsulation of the two methods above zend_hash_quick_exists

1.4 C extension commonly used HashTable functions

Although HashTable looks a little complicated, it is very convenient to use. we can use the following function to initialize and assign values to HashTable.

Number of local students enrolled in 2005

PHP syntax

C syntax

Meaning

$ Arr = array ()

Array_init (arr );

Initialize an array

$ Arr [] = NULL;

Add_next_index_null (arr );

$ Arr [] = 42;

Add_next_index_long (arr, 42 );

$ Arr [] = true;

Add_next_index_bool (arr, 1 );

$ Arr [] = 3.14;

Add_next_index_double (3.14 );

$ Arr [] = 'foo ';

Add_next_index_string (arr, "foo", 1 );

1 indicates copying strings.

$ Arr [] = $ myvar;

Add_next_index_zval (arr, myvar );

$ Arr [0] = NULL;

Add_index_null (arr, 0 );

$ Arr [1] = 42;

Add_index_long (arr, 1, 42 );

$ Arr [2] = true;

Add_index_bool (arr, 2, 1 );

$ Arr [3] = 3.14;

Add_index_double (arr, 3, 3, 14 );

$ Arr [4] = 'foo ';

Add_index_string (arr, 4, "foo", 1 );

$ Arr [5] = $ myvar;

Add_index_zval (arr, 5, myvar );

$ Arr ["abc"] = NULL;

Add_assoc_null (arr, "abc ");

$ Arr ["def"] = 711;

Add_assoc_long (arr, "def", 711 );

$ Arr ["ghi"] = true;

Add_assoc_bool (arr, ghi ", 1 );

$ Arr ["jkl"] = 1.44;

Add_assoc_double (arr, "jkl", 1.44 );

$ Arr ["mno"] = 'Baz ';

Add_assoc_string (arr, "mno", "baz", 1 );

$ Arr ['pqr '] = $ myvar;

Add_assoc_zval (arr, "pqr", myvar );

1.5 tasks and labs

Let's experiment with it.

Task: returns an array with the following data:

Array

(

[0] => for test

[42] = & gt; 123

[For test. for test.] => 1

[Array] => Array

(

[0] = & gt; 3.34

)

)

Code implementation:

PHP_FUNCTION (test)

{

Zval * t;

Array_init (return_value );

Add_next_index_string (return_value, "for test", 1 );

Add_index_long (return_value, 42,123 );

Add_assoc_double (return_value, "for test. for test.", 1.0 );

ALLOC_INIT_ZVAL (t );

Array_init (t );

Add_next_index_double (TB, 3.34 );

Add_assoc_zval (return_value, "array", t );

}

Simple, remember return_value?

Http://www.bkjia.com/PHPjc/477779.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/477779.htmlTechArticle1 array in this section we will talk about the php array, in php, the array is implemented using HashTable. This section describes HashTable in detail, and then describes how to use HastTable 1. 1...

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.