@@ -6910,111 +6910,157 @@ PHP_FUNCTION(array_key_exists)
69106910}
69116911/* }}} */
69126912
6913- /* {{{ Helper function to get a nested value from array using dot notation */
6914- static zval * array_get_nested (HashTable * ht , const char * key , size_t key_len )
6913+ /* {{{ Helper function to get a nested value from array using an array of segments */
6914+ static zval * array_get_nested (HashTable * ht , HashTable * segments )
69156915{
6916- const char * dot ;
6916+ zval * segment_val ;
69176917 zval * current ;
6918+ HashTable * current_ht ;
6919+ uint32_t idx ;
6920+ uint32_t num_segments ;
69186921
6919- /* Find the first dot in the key */
6920- dot = memchr ( key , '.' , key_len );
6922+ current_ht = ht ;
6923+ num_segments = zend_hash_num_elements ( segments );
69216924
6922- if (dot == NULL ) {
6923- /* No dot found, this is a simple key lookup */
6924- zend_string * zkey = zend_string_init (key , key_len , 0 );
6925- current = zend_symtable_find (ht , zkey );
6926- zend_string_release (zkey );
6927- return current ;
6928- }
6925+ /* Iterate through each segment in the array */
6926+ for (idx = 0 ; idx < num_segments ; idx ++ ) {
6927+ /* Get the segment at the current index */
6928+ segment_val = zend_hash_index_find (segments , idx );
6929+
6930+ if (segment_val == NULL ) {
6931+ /* Missing segment in array */
6932+ return NULL ;
6933+ }
6934+
6935+ /* Segment must be a string or int */
6936+ if (Z_TYPE_P (segment_val ) == IS_STRING ) {
6937+ current = zend_symtable_find (current_ht , Z_STR_P (segment_val ));
6938+ } else if (Z_TYPE_P (segment_val ) == IS_LONG ) {
6939+ current = zend_hash_index_find (current_ht , Z_LVAL_P (segment_val ));
6940+ } else {
6941+ /* Invalid segment type */
6942+ return NULL ;
6943+ }
6944+
6945+ /* If this is the last segment, return the result */
6946+ if (idx == num_segments - 1 ) {
6947+ return current ;
6948+ }
69296949
6930- /* We have a dot, so we need to recurse */
6931- size_t segment_len = dot - key ;
6932- zend_string * segment = zend_string_init (key , segment_len , 0 );
6933- current = zend_symtable_find (ht , segment );
6934- zend_string_release (segment );
6950+ /* Check if the segment exists and is an array for next iteration */
6951+ if (current == NULL || Z_TYPE_P (current ) != IS_ARRAY ) {
6952+ return NULL ;
6953+ }
69356954
6936- if ( current == NULL || Z_TYPE_P ( current ) != IS_ARRAY ) {
6937- return NULL ;
6955+ /* Move to the next level */
6956+ current_ht = Z_ARRVAL_P ( current ) ;
69386957 }
69396958
6940- /* Recurse into the nested array with the remaining key */
6941- return array_get_nested ( Z_ARRVAL_P ( current ), dot + 1 , key_len - segment_len - 1 ) ;
6959+ /* Empty segments array */
6960+ return NULL ;
69426961}
69436962/* }}} */
69446963
69456964/* {{{ Retrieves a value from a deeply nested array using "dot" notation */
69466965PHP_FUNCTION (array_get )
69476966{
6948- HashTable * ht ;
6967+ zval * array ;
69496968 zval * key = NULL ;
69506969 zval * default_value = NULL ;
69516970 zval * result ;
6971+ zval segments_array ;
6972+ HashTable * ht ;
69526973
69536974 ZEND_PARSE_PARAMETERS_START (2 , 3 )
6954- Z_PARAM_ARRAY_HT ( ht )
6975+ Z_PARAM_ARRAY ( array )
69556976 Z_PARAM_ZVAL_OR_NULL (key )
69566977 Z_PARAM_OPTIONAL
69576978 Z_PARAM_ZVAL (default_value )
69586979 ZEND_PARSE_PARAMETERS_END ();
69596980
69606981 /* If key is null, return the whole array */
69616982 if (key == NULL || Z_TYPE_P (key ) == IS_NULL ) {
6962- ZVAL_ARR (return_value , zend_array_dup (ht ));
6963- return ;
6983+ RETURN_COPY (array );
69646984 }
69656985
6966- /* Handle string keys with dot notation */
6967- if (Z_TYPE_P (key ) == IS_STRING ) {
6968- result = array_get_nested (ht , Z_STRVAL_P (key ), Z_STRLEN_P (key ));
6986+ ht = Z_ARRVAL_P (array );
6987+
6988+ /* Handle array keys (array of segments) */
6989+ if (Z_TYPE_P (key ) == IS_ARRAY ) {
6990+ result = array_get_nested (ht , Z_ARRVAL_P (key ));
69696991
69706992 if (result != NULL ) {
6971- ZVAL_COPY (return_value , result );
6972- return ;
6993+ RETURN_COPY (result );
69736994 }
69746995 }
6975- /* Handle integer keys (no dot notation support) */
6996+ /* Handle string keys with dot notation - convert to array of segments */
6997+ else if (Z_TYPE_P (key ) == IS_STRING ) {
6998+ /* Use php_explode to split the string by '.' */
6999+ zend_string * delim = ZSTR_CHAR ('.' );
7000+ array_init (& segments_array );
7001+ php_explode (delim , Z_STR_P (key ), & segments_array , ZEND_LONG_MAX );
7002+
7003+ result = array_get_nested (ht , Z_ARRVAL (segments_array ));
7004+
7005+ zval_ptr_dtor (& segments_array );
7006+
7007+ if (result != NULL ) {
7008+ RETURN_COPY (result );
7009+ }
7010+ }
7011+ /* Handle integer keys (simple lookup) */
69767012 else if (Z_TYPE_P (key ) == IS_LONG ) {
69777013 result = zend_hash_index_find (ht , Z_LVAL_P (key ));
69787014
69797015 if (result != NULL ) {
6980- ZVAL_COPY (return_value , result );
6981- return ;
7016+ RETURN_COPY (result );
69827017 }
69837018 }
69847019
69857020 /* Key not found, return default value */
69867021 if (default_value != NULL ) {
6987- ZVAL_COPY (return_value , default_value );
6988- } else {
6989- RETVAL_NULL ();
7022+ RETURN_COPY (default_value );
69907023 }
69917024}
69927025/* }}} */
69937026
69947027/* {{{ Checks whether a given item exists in an array using "dot" notation */
69957028PHP_FUNCTION (array_has )
69967029{
6997- HashTable * ht ;
7030+ zval * array ;
69987031 zval * key ;
69997032 zval * result ;
7033+ zval segments_array ;
7034+ HashTable * ht ;
70007035
70017036 ZEND_PARSE_PARAMETERS_START (2 , 2 )
7002- Z_PARAM_ARRAY_HT ( ht )
7037+ Z_PARAM_ARRAY ( array )
70037038 Z_PARAM_ZVAL (key )
70047039 ZEND_PARSE_PARAMETERS_END ();
70057040
7006- /* Handle string keys with dot notation */
7007- if (Z_TYPE_P (key ) == IS_STRING ) {
7008- result = array_get_nested (ht , Z_STRVAL_P (key ), Z_STRLEN_P (key ));
7041+ ht = Z_ARRVAL_P (array );
7042+
7043+ /* Handle array keys (array of segments) */
7044+ if (Z_TYPE_P (key ) == IS_ARRAY ) {
7045+ result = array_get_nested (ht , Z_ARRVAL_P (key ));
70097046 RETURN_BOOL (result != NULL );
70107047 }
7011- /* Handle integer keys (no dot notation support) */
7012- else if (Z_TYPE_P (key ) == IS_LONG ) {
7013- RETURN_BOOL (zend_hash_index_exists (ht , Z_LVAL_P (key )));
7048+ /* Handle string keys with dot notation - convert to array of segments */
7049+ if (Z_TYPE_P (key ) == IS_STRING ) {
7050+ /* Use php_explode to split the string by '.' */
7051+ zend_string * delim = ZSTR_CHAR ('.' );
7052+ array_init (& segments_array );
7053+ php_explode (delim , Z_STR_P (key ), & segments_array , ZEND_LONG_MAX );
7054+
7055+ result = array_get_nested (ht , Z_ARRVAL (segments_array ));
7056+
7057+ zval_ptr_dtor (& segments_array );
7058+ RETURN_BOOL (result != NULL );
70147059 }
70157060
7016- /* Invalid key type */
7017- RETURN_FALSE ;
7061+ /* Handle integer keys (simple lookup) */
7062+ ZEND_ASSERT (Z_TYPE_P (key ) == IS_LONG );
7063+ RETURN_BOOL (zend_hash_index_exists (ht , Z_LVAL_P (key )));
70187064}
70197065/* }}} */
70207066
0 commit comments