@@ -6915,111 +6915,157 @@ PHP_FUNCTION(array_key_exists)
69156915}
69166916/* }}} */
69176917
6918- /* {{{ Helper function to get a nested value from array using dot notation */
6919- static zval * array_get_nested (HashTable * ht , const char * key , size_t key_len )
6918+ /* {{{ Helper function to get a nested value from array using an array of segments */
6919+ static zval * array_get_nested (HashTable * ht , HashTable * segments )
69206920{
6921- const char * dot ;
6921+ zval * segment_val ;
69226922 zval * current ;
6923+ HashTable * current_ht ;
6924+ uint32_t idx ;
6925+ uint32_t num_segments ;
69236926
6924- /* Find the first dot in the key */
6925- dot = memchr ( key , '.' , key_len );
6927+ current_ht = ht ;
6928+ num_segments = zend_hash_num_elements ( segments );
69266929
6927- if (dot == NULL ) {
6928- /* No dot found, this is a simple key lookup */
6929- zend_string * zkey = zend_string_init (key , key_len , 0 );
6930- current = zend_symtable_find (ht , zkey );
6931- zend_string_release (zkey );
6932- return current ;
6933- }
6930+ /* Iterate through each segment in the array */
6931+ for (idx = 0 ; idx < num_segments ; idx ++ ) {
6932+ /* Get the segment at the current index */
6933+ segment_val = zend_hash_index_find (segments , idx );
6934+
6935+ if (segment_val == NULL ) {
6936+ /* Missing segment in array */
6937+ return NULL ;
6938+ }
6939+
6940+ /* Segment must be a string or int */
6941+ if (Z_TYPE_P (segment_val ) == IS_STRING ) {
6942+ current = zend_symtable_find (current_ht , Z_STR_P (segment_val ));
6943+ } else if (Z_TYPE_P (segment_val ) == IS_LONG ) {
6944+ current = zend_hash_index_find (current_ht , Z_LVAL_P (segment_val ));
6945+ } else {
6946+ /* Invalid segment type */
6947+ return NULL ;
6948+ }
6949+
6950+ /* If this is the last segment, return the result */
6951+ if (idx == num_segments - 1 ) {
6952+ return current ;
6953+ }
69346954
6935- /* We have a dot, so we need to recurse */
6936- size_t segment_len = dot - key ;
6937- zend_string * segment = zend_string_init (key , segment_len , 0 );
6938- current = zend_symtable_find (ht , segment );
6939- zend_string_release (segment );
6955+ /* Check if the segment exists and is an array for next iteration */
6956+ if (current == NULL || Z_TYPE_P (current ) != IS_ARRAY ) {
6957+ return NULL ;
6958+ }
69406959
6941- if ( current == NULL || Z_TYPE_P ( current ) != IS_ARRAY ) {
6942- return NULL ;
6960+ /* Move to the next level */
6961+ current_ht = Z_ARRVAL_P ( current ) ;
69436962 }
69446963
6945- /* Recurse into the nested array with the remaining key */
6946- return array_get_nested ( Z_ARRVAL_P ( current ), dot + 1 , key_len - segment_len - 1 ) ;
6964+ /* Empty segments array */
6965+ return NULL ;
69476966}
69486967/* }}} */
69496968
69506969/* {{{ Retrieves a value from a deeply nested array using "dot" notation */
69516970PHP_FUNCTION (array_get )
69526971{
6953- HashTable * ht ;
6972+ zval * array ;
69546973 zval * key = NULL ;
69556974 zval * default_value = NULL ;
69566975 zval * result ;
6976+ zval segments_array ;
6977+ HashTable * ht ;
69576978
69586979 ZEND_PARSE_PARAMETERS_START (2 , 3 )
6959- Z_PARAM_ARRAY_HT ( ht )
6980+ Z_PARAM_ARRAY ( array )
69606981 Z_PARAM_ZVAL_OR_NULL (key )
69616982 Z_PARAM_OPTIONAL
69626983 Z_PARAM_ZVAL (default_value )
69636984 ZEND_PARSE_PARAMETERS_END ();
69646985
69656986 /* If key is null, return the whole array */
69666987 if (key == NULL || Z_TYPE_P (key ) == IS_NULL ) {
6967- ZVAL_ARR (return_value , zend_array_dup (ht ));
6968- return ;
6988+ RETURN_COPY (array );
69696989 }
69706990
6971- /* Handle string keys with dot notation */
6972- if (Z_TYPE_P (key ) == IS_STRING ) {
6973- result = array_get_nested (ht , Z_STRVAL_P (key ), Z_STRLEN_P (key ));
6991+ ht = Z_ARRVAL_P (array );
6992+
6993+ /* Handle array keys (array of segments) */
6994+ if (Z_TYPE_P (key ) == IS_ARRAY ) {
6995+ result = array_get_nested (ht , Z_ARRVAL_P (key ));
69746996
69756997 if (result != NULL ) {
6976- ZVAL_COPY (return_value , result );
6977- return ;
6998+ RETURN_COPY (result );
69786999 }
69797000 }
6980- /* Handle integer keys (no dot notation support) */
7001+ /* Handle string keys with dot notation - convert to array of segments */
7002+ else if (Z_TYPE_P (key ) == IS_STRING ) {
7003+ /* Use php_explode to split the string by '.' */
7004+ zend_string * delim = ZSTR_CHAR ('.' );
7005+ array_init (& segments_array );
7006+ php_explode (delim , Z_STR_P (key ), & segments_array , ZEND_LONG_MAX );
7007+
7008+ result = array_get_nested (ht , Z_ARRVAL (segments_array ));
7009+
7010+ zval_ptr_dtor (& segments_array );
7011+
7012+ if (result != NULL ) {
7013+ RETURN_COPY (result );
7014+ }
7015+ }
7016+ /* Handle integer keys (simple lookup) */
69817017 else if (Z_TYPE_P (key ) == IS_LONG ) {
69827018 result = zend_hash_index_find (ht , Z_LVAL_P (key ));
69837019
69847020 if (result != NULL ) {
6985- ZVAL_COPY (return_value , result );
6986- return ;
7021+ RETURN_COPY (result );
69877022 }
69887023 }
69897024
69907025 /* Key not found, return default value */
69917026 if (default_value != NULL ) {
6992- ZVAL_COPY (return_value , default_value );
6993- } else {
6994- RETVAL_NULL ();
7027+ RETURN_COPY (default_value );
69957028 }
69967029}
69977030/* }}} */
69987031
69997032/* {{{ Checks whether a given item exists in an array using "dot" notation */
70007033PHP_FUNCTION (array_has )
70017034{
7002- HashTable * ht ;
7035+ zval * array ;
70037036 zval * key ;
70047037 zval * result ;
7038+ zval segments_array ;
7039+ HashTable * ht ;
70057040
70067041 ZEND_PARSE_PARAMETERS_START (2 , 2 )
7007- Z_PARAM_ARRAY_HT ( ht )
7042+ Z_PARAM_ARRAY ( array )
70087043 Z_PARAM_ZVAL (key )
70097044 ZEND_PARSE_PARAMETERS_END ();
70107045
7011- /* Handle string keys with dot notation */
7012- if (Z_TYPE_P (key ) == IS_STRING ) {
7013- result = array_get_nested (ht , Z_STRVAL_P (key ), Z_STRLEN_P (key ));
7046+ ht = Z_ARRVAL_P (array );
7047+
7048+ /* Handle array keys (array of segments) */
7049+ if (Z_TYPE_P (key ) == IS_ARRAY ) {
7050+ result = array_get_nested (ht , Z_ARRVAL_P (key ));
70147051 RETURN_BOOL (result != NULL );
70157052 }
7016- /* Handle integer keys (no dot notation support) */
7017- else if (Z_TYPE_P (key ) == IS_LONG ) {
7018- RETURN_BOOL (zend_hash_index_exists (ht , Z_LVAL_P (key )));
7053+ /* Handle string keys with dot notation - convert to array of segments */
7054+ if (Z_TYPE_P (key ) == IS_STRING ) {
7055+ /* Use php_explode to split the string by '.' */
7056+ zend_string * delim = ZSTR_CHAR ('.' );
7057+ array_init (& segments_array );
7058+ php_explode (delim , Z_STR_P (key ), & segments_array , ZEND_LONG_MAX );
7059+
7060+ result = array_get_nested (ht , Z_ARRVAL (segments_array ));
7061+
7062+ zval_ptr_dtor (& segments_array );
7063+ RETURN_BOOL (result != NULL );
70197064 }
70207065
7021- /* Invalid key type */
7022- RETURN_FALSE ;
7066+ /* Handle integer keys (simple lookup) */
7067+ ZEND_ASSERT (Z_TYPE_P (key ) == IS_LONG );
7068+ RETURN_BOOL (zend_hash_index_exists (ht , Z_LVAL_P (key )));
70237069}
70247070/* }}} */
70257071
0 commit comments