@@ -6916,7 +6916,7 @@ PHP_FUNCTION(array_key_exists)
69166916/* }}} */
69176917
69186918/* {{{ Helper function to get a nested value from array using an array of segments */
6919- static zval * array_get_nested (HashTable * ht , HashTable * segments )
6919+ static zval * array_get_nested_from_hash (HashTable * ht , HashTable * segments )
69206920{
69216921 zval * segment_val ;
69226922 zval * current ;
@@ -6966,14 +6966,65 @@ static zval* array_get_nested(HashTable *ht, HashTable *segments)
69666966}
69676967/* }}} */
69686968
6969+ /* {{{ Helper function to get a nested value from array using dot notation string */
6970+ static zval * array_get_nested_from_string (HashTable * ht , const char * key , size_t key_len )
6971+ {
6972+ const char * segment_start ;
6973+ const char * dot ;
6974+ size_t segment_len ;
6975+ size_t remaining_len ;
6976+ zval * current ;
6977+ HashTable * current_ht ;
6978+ zend_string * segment ;
6979+
6980+ current_ht = ht ;
6981+ segment_start = key ;
6982+ remaining_len = key_len ;
6983+
6984+ /* Iterate through each dot-separated segment */
6985+ while (remaining_len > 0 ) {
6986+ /* Find the next dot */
6987+ dot = memchr (segment_start , '.' , remaining_len );
6988+
6989+ if (dot == NULL ) {
6990+ /* Last segment */
6991+ segment_len = remaining_len ;
6992+ } else {
6993+ segment_len = dot - segment_start ;
6994+ }
6995+
6996+ /* Look up the current segment */
6997+ segment = zend_string_init (segment_start , segment_len , 0 );
6998+ current = zend_symtable_find (current_ht , segment );
6999+ zend_string_release (segment );
7000+
7001+ /* If this is the last segment, return the result */
7002+ if (dot == NULL ) {
7003+ return current ;
7004+ }
7005+
7006+ /* Check if the segment exists and is an array for next iteration */
7007+ if (current == NULL || Z_TYPE_P (current ) != IS_ARRAY ) {
7008+ return NULL ;
7009+ }
7010+
7011+ /* Move to the next segment */
7012+ current_ht = Z_ARRVAL_P (current );
7013+ segment_start = dot + 1 ;
7014+ remaining_len = remaining_len - segment_len - 1 ;
7015+ }
7016+
7017+ return NULL ;
7018+ }
7019+ /* }}} */
7020+
69697021/* {{{ Retrieves a value from a deeply nested array using "dot" notation */
69707022PHP_FUNCTION (array_get )
69717023{
69727024 zval * array ;
69737025 zval * key = NULL ;
69747026 zval * default_value = NULL ;
69757027 zval * result ;
6976- zval segments_array ;
69777028 HashTable * ht ;
69787029
69797030 ZEND_PARSE_PARAMETERS_START (2 , 3 )
@@ -6990,41 +7041,42 @@ PHP_FUNCTION(array_get)
69907041
69917042 ht = Z_ARRVAL_P (array );
69927043
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 ));
7044+ switch (Z_TYPE_P (key )) {
7045+ case IS_ARRAY :
7046+ /* Handle array keys (array of segments) */
7047+ result = array_get_nested_from_hash (ht , Z_ARRVAL_P (key ));
69967048
6997- if (result != NULL ) {
6998- RETURN_COPY (result );
6999- }
7000- }
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 );
7049+ if (result != NULL ) {
7050+ RETURN_COPY_DEREF (result );
7051+ }
7052+ break ;
70077053
7008- result = array_get_nested (ht , Z_ARRVAL (segments_array ));
7054+ case IS_STRING :
7055+ /* Handle string keys with dot notation */
7056+ result = array_get_nested_from_string (ht , Z_STRVAL_P (key ), Z_STRLEN_P (key ));
70097057
7010- zval_ptr_dtor (& segments_array );
7058+ if (result != NULL ) {
7059+ RETURN_COPY_DEREF (result );
7060+ }
7061+ break ;
70117062
7012- if (result != NULL ) {
7013- RETURN_COPY (result );
7014- }
7015- }
7016- /* Handle integer keys (simple lookup) */
7017- else if (Z_TYPE_P (key ) == IS_LONG ) {
7018- result = zend_hash_index_find (ht , Z_LVAL_P (key ));
7063+ case IS_LONG :
7064+ /* Handle integer keys (simple lookup) */
7065+ result = zend_hash_index_find (ht , Z_LVAL_P (key ));
70197066
7020- if (result != NULL ) {
7021- RETURN_COPY (result );
7022- }
7067+ if (result != NULL ) {
7068+ RETURN_COPY_DEREF (result );
7069+ }
7070+ break ;
7071+
7072+ default :
7073+ zend_argument_type_error (2 , "must be of type string|int|array, %s given" , zend_zval_value_name (key ));
7074+ RETURN_THROWS ();
70237075 }
70247076
70257077 /* Key not found, return default value */
70267078 if (default_value != NULL ) {
7027- RETURN_COPY (default_value );
7079+ RETURN_COPY_DEREF (default_value );
70287080 }
70297081}
70307082/* }}} */
@@ -7035,7 +7087,6 @@ PHP_FUNCTION(array_has)
70357087 zval * array ;
70367088 zval * key ;
70377089 zval * result ;
7038- zval segments_array ;
70397090 HashTable * ht ;
70407091
70417092 ZEND_PARSE_PARAMETERS_START (2 , 2 )
@@ -7045,27 +7096,25 @@ PHP_FUNCTION(array_has)
70457096
70467097 ht = Z_ARRVAL_P (array );
70477098
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 ));
7051- RETURN_BOOL (result != NULL );
7052- }
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 );
7099+ switch (Z_TYPE_P (key )) {
7100+ case IS_ARRAY :
7101+ /* Handle array keys (array of segments) */
7102+ result = array_get_nested_from_hash (ht , Z_ARRVAL_P (key ));
7103+ RETURN_BOOL (result != NULL );
70597104
7060- result = array_get_nested (ht , Z_ARRVAL (segments_array ));
7105+ case IS_STRING :
7106+ /* Handle string keys with dot notation */
7107+ result = array_get_nested_from_string (ht , Z_STRVAL_P (key ), Z_STRLEN_P (key ));
7108+ RETURN_BOOL (result != NULL );
70617109
7062- zval_ptr_dtor ( & segments_array );
7063- RETURN_BOOL ( result != NULL );
7064- }
7110+ case IS_LONG :
7111+ /* Handle integer keys (simple lookup) */
7112+ RETURN_BOOL ( zend_hash_index_exists ( ht , Z_LVAL_P ( key )));
70657113
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 )));
7114+ default :
7115+ zend_argument_type_error (2 , "must be of type string|int|array, %s given" , zend_zval_value_name (key ));
7116+ RETURN_THROWS ();
7117+ }
70697118}
70707119/* }}} */
70717120
0 commit comments