@@ -207,20 +207,59 @@ static ZEND_NAMED_FUNCTION(zend_enum_cases_func)
207207 } ZEND_HASH_FOREACH_END ();
208208}
209209
210+ ZEND_API zend_result zend_enum_get_case_by_value (zend_object * * result , zend_class_entry * ce , zend_long long_key , zend_string * string_key , bool try )
211+ {
212+ zval * case_name_zv ;
213+ if (ce -> enum_backing_type == IS_LONG ) {
214+ case_name_zv = zend_hash_index_find (ce -> backed_enum_table , long_key );
215+ } else {
216+ ZEND_ASSERT (ce -> enum_backing_type == IS_STRING );
217+ ZEND_ASSERT (string_key != NULL );
218+ case_name_zv = zend_hash_find (ce -> backed_enum_table , string_key );
219+ }
220+
221+ if (case_name_zv == NULL ) {
222+ if (try ) {
223+ * result = NULL ;
224+ return SUCCESS ;
225+ }
226+
227+ if (ce -> enum_backing_type == IS_LONG ) {
228+ zend_value_error (ZEND_LONG_FMT " is not a valid backing value for enum \"%s\"" , long_key , ZSTR_VAL (ce -> name ));
229+ } else {
230+ ZEND_ASSERT (ce -> enum_backing_type == IS_STRING );
231+ zend_value_error ("\"%s\" is not a valid backing value for enum \"%s\"" , ZSTR_VAL (string_key ), ZSTR_VAL (ce -> name ));
232+ }
233+ return FAILURE ;
234+ }
235+
236+ // TODO: We might want to store pointers to constants in backed_enum_table instead of names,
237+ // to make this lookup more efficient.
238+ ZEND_ASSERT (Z_TYPE_P (case_name_zv ) == IS_STRING );
239+ zend_class_constant * c = zend_hash_find_ptr (CE_CONSTANTS_TABLE (ce ), Z_STR_P (case_name_zv ));
240+ ZEND_ASSERT (c != NULL );
241+ zval * case_zv = & c -> value ;
242+ if (Z_TYPE_P (case_zv ) == IS_CONSTANT_AST ) {
243+ if (zval_update_constant_ex (case_zv , c -> ce ) == FAILURE ) {
244+ return FAILURE ;
245+ }
246+ }
247+
248+ * result = Z_OBJ_P (case_zv );
249+ return SUCCESS ;
250+ }
251+
210252static void zend_enum_from_base (INTERNAL_FUNCTION_PARAMETERS , bool try )
211253{
212254 zend_class_entry * ce = execute_data -> func -> common .scope ;
213255 bool release_string = false;
214- zend_string * string_key ;
215- zend_long long_key ;
256+ zend_string * string_key = NULL ;
257+ zend_long long_key = 0 ;
216258
217- zval * case_name_zv ;
218259 if (ce -> enum_backing_type == IS_LONG ) {
219260 ZEND_PARSE_PARAMETERS_START (1 , 1 )
220261 Z_PARAM_LONG (long_key )
221262 ZEND_PARSE_PARAMETERS_END ();
222-
223- case_name_zv = zend_hash_index_find (ce -> backed_enum_table , long_key );
224263 } else {
225264 ZEND_ASSERT (ce -> enum_backing_type == IS_STRING );
226265
@@ -242,40 +281,22 @@ static void zend_enum_from_base(INTERNAL_FUNCTION_PARAMETERS, bool try)
242281 string_key = zend_long_to_str (long_key );
243282 }
244283 }
245-
246- case_name_zv = zend_hash_find (ce -> backed_enum_table , string_key );
247284 }
248285
249- if (case_name_zv == NULL ) {
250- if (try ) {
251- goto return_null ;
252- }
253-
254- if (ce -> enum_backing_type == IS_LONG ) {
255- zend_value_error (ZEND_LONG_FMT " is not a valid backing value for enum \"%s\"" , long_key , ZSTR_VAL (ce -> name ));
256- } else {
257- ZEND_ASSERT (ce -> enum_backing_type == IS_STRING );
258- zend_value_error ("\"%s\" is not a valid backing value for enum \"%s\"" , ZSTR_VAL (string_key ), ZSTR_VAL (ce -> name ));
259- }
286+ zend_object * case_obj ;
287+ if (zend_enum_get_case_by_value (& case_obj , ce , long_key , string_key , try ) == FAILURE ) {
260288 goto throw ;
261289 }
262290
263- // TODO: We might want to store pointers to constants in backed_enum_table instead of names,
264- // to make this lookup more efficient.
265- ZEND_ASSERT (Z_TYPE_P (case_name_zv ) == IS_STRING );
266- zend_class_constant * c = zend_hash_find_ptr (CE_CONSTANTS_TABLE (ce ), Z_STR_P (case_name_zv ));
267- ZEND_ASSERT (c != NULL );
268- zval * case_zv = & c -> value ;
269- if (Z_TYPE_P (case_zv ) == IS_CONSTANT_AST ) {
270- if (zval_update_constant_ex (case_zv , c -> ce ) == FAILURE ) {
271- goto throw ;
272- }
291+ if (case_obj == NULL ) {
292+ ZEND_ASSERT (try );
293+ goto return_null ;
273294 }
274295
275296 if (release_string ) {
276297 zend_string_release (string_key );
277298 }
278- RETURN_COPY ( case_zv );
299+ RETURN_OBJ_COPY ( case_obj );
279300
280301throw :
281302 if (release_string ) {
0 commit comments