@@ -6914,7 +6914,7 @@ PHP_FUNCTION(array_key_exists)
69146914/* }}} */
69156915
69166916/* {{{ Helper function to get a nested value from array using an array of segments */
6917- static zval * array_get_nested (HashTable * ht , HashTable * segments )
6917+ static zval * array_get_nested_from_hash (HashTable * ht , HashTable * segments )
69186918{
69196919 zval * segment_val ;
69206920 zval * current ;
@@ -6964,14 +6964,65 @@ static zval* array_get_nested(HashTable *ht, HashTable *segments)
69646964}
69656965/* }}} */
69666966
6967+ /* {{{ Helper function to get a nested value from array using dot notation string */
6968+ static zval * array_get_nested_from_string (HashTable * ht , const char * key , size_t key_len )
6969+ {
6970+ const char * segment_start ;
6971+ const char * dot ;
6972+ size_t segment_len ;
6973+ size_t remaining_len ;
6974+ zval * current ;
6975+ HashTable * current_ht ;
6976+ zend_string * segment ;
6977+
6978+ current_ht = ht ;
6979+ segment_start = key ;
6980+ remaining_len = key_len ;
6981+
6982+ /* Iterate through each dot-separated segment */
6983+ while (remaining_len > 0 ) {
6984+ /* Find the next dot */
6985+ dot = memchr (segment_start , '.' , remaining_len );
6986+
6987+ if (dot == NULL ) {
6988+ /* Last segment */
6989+ segment_len = remaining_len ;
6990+ } else {
6991+ segment_len = dot - segment_start ;
6992+ }
6993+
6994+ /* Look up the current segment */
6995+ segment = zend_string_init (segment_start , segment_len , 0 );
6996+ current = zend_symtable_find (current_ht , segment );
6997+ zend_string_release (segment );
6998+
6999+ /* If this is the last segment, return the result */
7000+ if (dot == NULL ) {
7001+ return current ;
7002+ }
7003+
7004+ /* Check if the segment exists and is an array for next iteration */
7005+ if (current == NULL || Z_TYPE_P (current ) != IS_ARRAY ) {
7006+ return NULL ;
7007+ }
7008+
7009+ /* Move to the next segment */
7010+ current_ht = Z_ARRVAL_P (current );
7011+ segment_start = dot + 1 ;
7012+ remaining_len = remaining_len - segment_len - 1 ;
7013+ }
7014+
7015+ return NULL ;
7016+ }
7017+ /* }}} */
7018+
69677019/* {{{ Retrieves a value from a deeply nested array using "dot" notation */
69687020PHP_FUNCTION (array_get )
69697021{
69707022 zval * array ;
69717023 zval * key = NULL ;
69727024 zval * default_value = NULL ;
69737025 zval * result ;
6974- zval segments_array ;
69757026 HashTable * ht ;
69767027
69777028 ZEND_PARSE_PARAMETERS_START (2 , 3 )
@@ -6988,41 +7039,42 @@ PHP_FUNCTION(array_get)
69887039
69897040 ht = Z_ARRVAL_P (array );
69907041
6991- /* Handle array keys (array of segments) */
6992- if (Z_TYPE_P (key ) == IS_ARRAY ) {
6993- result = array_get_nested (ht , Z_ARRVAL_P (key ));
7042+ switch (Z_TYPE_P (key )) {
7043+ case IS_ARRAY :
7044+ /* Handle array keys (array of segments) */
7045+ result = array_get_nested_from_hash (ht , Z_ARRVAL_P (key ));
69947046
6995- if (result != NULL ) {
6996- RETURN_COPY (result );
6997- }
6998- }
6999- /* Handle string keys with dot notation - convert to array of segments */
7000- else if (Z_TYPE_P (key ) == IS_STRING ) {
7001- /* Use php_explode to split the string by '.' */
7002- zend_string * delim = ZSTR_CHAR ('.' );
7003- array_init (& segments_array );
7004- php_explode (delim , Z_STR_P (key ), & segments_array , ZEND_LONG_MAX );
7047+ if (result != NULL ) {
7048+ RETURN_COPY_DEREF (result );
7049+ }
7050+ break ;
70057051
7006- result = array_get_nested (ht , Z_ARRVAL (segments_array ));
7052+ case IS_STRING :
7053+ /* Handle string keys with dot notation */
7054+ result = array_get_nested_from_string (ht , Z_STRVAL_P (key ), Z_STRLEN_P (key ));
70077055
7008- zval_ptr_dtor (& segments_array );
7056+ if (result != NULL ) {
7057+ RETURN_COPY_DEREF (result );
7058+ }
7059+ break ;
70097060
7010- if (result != NULL ) {
7011- RETURN_COPY (result );
7012- }
7013- }
7014- /* Handle integer keys (simple lookup) */
7015- else if (Z_TYPE_P (key ) == IS_LONG ) {
7016- result = zend_hash_index_find (ht , Z_LVAL_P (key ));
7061+ case IS_LONG :
7062+ /* Handle integer keys (simple lookup) */
7063+ result = zend_hash_index_find (ht , Z_LVAL_P (key ));
70177064
7018- if (result != NULL ) {
7019- RETURN_COPY (result );
7020- }
7065+ if (result != NULL ) {
7066+ RETURN_COPY_DEREF (result );
7067+ }
7068+ break ;
7069+
7070+ default :
7071+ zend_argument_type_error (2 , "must be of type string|int|array, %s given" , zend_zval_value_name (key ));
7072+ RETURN_THROWS ();
70217073 }
70227074
70237075 /* Key not found, return default value */
70247076 if (default_value != NULL ) {
7025- RETURN_COPY (default_value );
7077+ RETURN_COPY_DEREF (default_value );
70267078 }
70277079}
70287080/* }}} */
@@ -7033,7 +7085,6 @@ PHP_FUNCTION(array_has)
70337085 zval * array ;
70347086 zval * key ;
70357087 zval * result ;
7036- zval segments_array ;
70377088 HashTable * ht ;
70387089
70397090 ZEND_PARSE_PARAMETERS_START (2 , 2 )
@@ -7043,27 +7094,25 @@ PHP_FUNCTION(array_has)
70437094
70447095 ht = Z_ARRVAL_P (array );
70457096
7046- /* Handle array keys (array of segments) */
7047- if (Z_TYPE_P (key ) == IS_ARRAY ) {
7048- result = array_get_nested (ht , Z_ARRVAL_P (key ));
7049- RETURN_BOOL (result != NULL );
7050- }
7051- /* Handle string keys with dot notation - convert to array of segments */
7052- if (Z_TYPE_P (key ) == IS_STRING ) {
7053- /* Use php_explode to split the string by '.' */
7054- zend_string * delim = ZSTR_CHAR ('.' );
7055- array_init (& segments_array );
7056- php_explode (delim , Z_STR_P (key ), & segments_array , ZEND_LONG_MAX );
7097+ switch (Z_TYPE_P (key )) {
7098+ case IS_ARRAY :
7099+ /* Handle array keys (array of segments) */
7100+ result = array_get_nested_from_hash (ht , Z_ARRVAL_P (key ));
7101+ RETURN_BOOL (result != NULL );
70577102
7058- result = array_get_nested (ht , Z_ARRVAL (segments_array ));
7103+ case IS_STRING :
7104+ /* Handle string keys with dot notation */
7105+ result = array_get_nested_from_string (ht , Z_STRVAL_P (key ), Z_STRLEN_P (key ));
7106+ RETURN_BOOL (result != NULL );
70597107
7060- zval_ptr_dtor ( & segments_array );
7061- RETURN_BOOL ( result != NULL );
7062- }
7108+ case IS_LONG :
7109+ /* Handle integer keys (simple lookup) */
7110+ RETURN_BOOL ( zend_hash_index_exists ( ht , Z_LVAL_P ( key )));
70637111
7064- /* Handle integer keys (simple lookup) */
7065- ZEND_ASSERT (Z_TYPE_P (key ) == IS_LONG );
7066- RETURN_BOOL (zend_hash_index_exists (ht , Z_LVAL_P (key )));
7112+ default :
7113+ zend_argument_type_error (2 , "must be of type string|int|array, %s given" , zend_zval_value_name (key ));
7114+ RETURN_THROWS ();
7115+ }
70677116}
70687117/* }}} */
70697118
0 commit comments