@@ -6913,111 +6913,157 @@ PHP_FUNCTION(array_key_exists)
69136913}
69146914/* }}} */
69156915
6916- /* {{{ Helper function to get a nested value from array using dot notation */
6917- static zval * array_get_nested (HashTable * ht , const char * key , size_t key_len )
6916+ /* {{{ Helper function to get a nested value from array using an array of segments */
6917+ static zval * array_get_nested (HashTable * ht , HashTable * segments )
69186918{
6919- const char * dot ;
6919+ zval * segment_val ;
69206920 zval * current ;
6921+ HashTable * current_ht ;
6922+ uint32_t idx ;
6923+ uint32_t num_segments ;
69216924
6922- /* Find the first dot in the key */
6923- dot = memchr ( key , '.' , key_len );
6925+ current_ht = ht ;
6926+ num_segments = zend_hash_num_elements ( segments );
69246927
6925- if (dot == NULL ) {
6926- /* No dot found, this is a simple key lookup */
6927- zend_string * zkey = zend_string_init (key , key_len , 0 );
6928- current = zend_symtable_find (ht , zkey );
6929- zend_string_release (zkey );
6930- return current ;
6931- }
6928+ /* Iterate through each segment in the array */
6929+ for (idx = 0 ; idx < num_segments ; idx ++ ) {
6930+ /* Get the segment at the current index */
6931+ segment_val = zend_hash_index_find (segments , idx );
6932+
6933+ if (segment_val == NULL ) {
6934+ /* Missing segment in array */
6935+ return NULL ;
6936+ }
6937+
6938+ /* Segment must be a string or int */
6939+ if (Z_TYPE_P (segment_val ) == IS_STRING ) {
6940+ current = zend_symtable_find (current_ht , Z_STR_P (segment_val ));
6941+ } else if (Z_TYPE_P (segment_val ) == IS_LONG ) {
6942+ current = zend_hash_index_find (current_ht , Z_LVAL_P (segment_val ));
6943+ } else {
6944+ /* Invalid segment type */
6945+ return NULL ;
6946+ }
6947+
6948+ /* If this is the last segment, return the result */
6949+ if (idx == num_segments - 1 ) {
6950+ return current ;
6951+ }
69326952
6933- /* We have a dot, so we need to recurse */
6934- size_t segment_len = dot - key ;
6935- zend_string * segment = zend_string_init (key , segment_len , 0 );
6936- current = zend_symtable_find (ht , segment );
6937- zend_string_release (segment );
6953+ /* Check if the segment exists and is an array for next iteration */
6954+ if (current == NULL || Z_TYPE_P (current ) != IS_ARRAY ) {
6955+ return NULL ;
6956+ }
69386957
6939- if ( current == NULL || Z_TYPE_P ( current ) != IS_ARRAY ) {
6940- return NULL ;
6958+ /* Move to the next level */
6959+ current_ht = Z_ARRVAL_P ( current ) ;
69416960 }
69426961
6943- /* Recurse into the nested array with the remaining key */
6944- return array_get_nested ( Z_ARRVAL_P ( current ), dot + 1 , key_len - segment_len - 1 ) ;
6962+ /* Empty segments array */
6963+ return NULL ;
69456964}
69466965/* }}} */
69476966
69486967/* {{{ Retrieves a value from a deeply nested array using "dot" notation */
69496968PHP_FUNCTION (array_get )
69506969{
6951- HashTable * ht ;
6970+ zval * array ;
69526971 zval * key = NULL ;
69536972 zval * default_value = NULL ;
69546973 zval * result ;
6974+ zval segments_array ;
6975+ HashTable * ht ;
69556976
69566977 ZEND_PARSE_PARAMETERS_START (2 , 3 )
6957- Z_PARAM_ARRAY_HT ( ht )
6978+ Z_PARAM_ARRAY ( array )
69586979 Z_PARAM_ZVAL_OR_NULL (key )
69596980 Z_PARAM_OPTIONAL
69606981 Z_PARAM_ZVAL (default_value )
69616982 ZEND_PARSE_PARAMETERS_END ();
69626983
69636984 /* If key is null, return the whole array */
69646985 if (key == NULL || Z_TYPE_P (key ) == IS_NULL ) {
6965- ZVAL_ARR (return_value , zend_array_dup (ht ));
6966- return ;
6986+ RETURN_COPY (array );
69676987 }
69686988
6969- /* Handle string keys with dot notation */
6970- if (Z_TYPE_P (key ) == IS_STRING ) {
6971- result = array_get_nested (ht , Z_STRVAL_P (key ), Z_STRLEN_P (key ));
6989+ ht = Z_ARRVAL_P (array );
6990+
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 ));
69726994
69736995 if (result != NULL ) {
6974- ZVAL_COPY (return_value , result );
6975- return ;
6996+ RETURN_COPY (result );
69766997 }
69776998 }
6978- /* Handle integer keys (no dot notation support) */
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 );
7005+
7006+ result = array_get_nested (ht , Z_ARRVAL (segments_array ));
7007+
7008+ zval_ptr_dtor (& segments_array );
7009+
7010+ if (result != NULL ) {
7011+ RETURN_COPY (result );
7012+ }
7013+ }
7014+ /* Handle integer keys (simple lookup) */
69797015 else if (Z_TYPE_P (key ) == IS_LONG ) {
69807016 result = zend_hash_index_find (ht , Z_LVAL_P (key ));
69817017
69827018 if (result != NULL ) {
6983- ZVAL_COPY (return_value , result );
6984- return ;
7019+ RETURN_COPY (result );
69857020 }
69867021 }
69877022
69887023 /* Key not found, return default value */
69897024 if (default_value != NULL ) {
6990- ZVAL_COPY (return_value , default_value );
6991- } else {
6992- RETVAL_NULL ();
7025+ RETURN_COPY (default_value );
69937026 }
69947027}
69957028/* }}} */
69967029
69977030/* {{{ Checks whether a given item exists in an array using "dot" notation */
69987031PHP_FUNCTION (array_has )
69997032{
7000- HashTable * ht ;
7033+ zval * array ;
70017034 zval * key ;
70027035 zval * result ;
7036+ zval segments_array ;
7037+ HashTable * ht ;
70037038
70047039 ZEND_PARSE_PARAMETERS_START (2 , 2 )
7005- Z_PARAM_ARRAY_HT ( ht )
7040+ Z_PARAM_ARRAY ( array )
70067041 Z_PARAM_ZVAL (key )
70077042 ZEND_PARSE_PARAMETERS_END ();
70087043
7009- /* Handle string keys with dot notation */
7010- if (Z_TYPE_P (key ) == IS_STRING ) {
7011- result = array_get_nested (ht , Z_STRVAL_P (key ), Z_STRLEN_P (key ));
7044+ ht = Z_ARRVAL_P (array );
7045+
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 ));
70127049 RETURN_BOOL (result != NULL );
70137050 }
7014- /* Handle integer keys (no dot notation support) */
7015- else if (Z_TYPE_P (key ) == IS_LONG ) {
7016- RETURN_BOOL (zend_hash_index_exists (ht , Z_LVAL_P (key )));
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 );
7057+
7058+ result = array_get_nested (ht , Z_ARRVAL (segments_array ));
7059+
7060+ zval_ptr_dtor (& segments_array );
7061+ RETURN_BOOL (result != NULL );
70177062 }
70187063
7019- /* Invalid key type */
7020- RETURN_FALSE ;
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 )));
70217067}
70227068/* }}} */
70237069
0 commit comments