Commit 60aab0fb13f for php.net
commit 60aab0fb13f2902f787762738d1ad93fd370522a
Author: Nora Dossche <7771979+ndossche@users.noreply.github.com>
Date: Wed Jun 24 10:52:16 2026 +0200
Implement zend_enum_get_case_by_id() (#22402)
Avoid hash-based lookup if we already know the offset in the table
anyway.
diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS
index 1f24fb82fcf..2f0d016a99c 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -65,6 +65,7 @@ PHP 8.6 INTERNALS UPGRADE NOTES
zend_enum_RoundingMode parameter.
. Added Z_PARAM_ENUM().
. Added zend_enum_fetch_case_id().
+ . Added zend_enum_get_case_by_id().
. ZEND_INI_GET_ADDR() is now a void* pointer instead of a char* pointer. This
more correctly represents the generic nature of the returned pointer and
allows to remove explicit casts, but possibly breaks pointer arithmetic
diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c
index 7f0b5857538..ecebe7a5d51 100644
--- a/Zend/zend_enum.c
+++ b/Zend/zend_enum.c
@@ -673,6 +673,11 @@ ZEND_API zend_object *zend_enum_get_case_cstr(zend_class_entry *ce, const char *
return zend_enum_case_from_class_constant(c);
}
+ZEND_API zend_object *zend_enum_get_case_by_id(zend_class_entry *ce, int id) {
+ zend_class_constant *c = Z_PTR(CE_CONSTANTS_TABLE(ce)->arData[id - 1].val);
+ return zend_enum_case_from_class_constant(c);
+}
+
void zend_enum_startup(void)
{
for (size_t i = 0; i < sizeof(zarginfo_class_UnitEnum_cases)/sizeof(zend_arg_info); i++) {
diff --git a/Zend/zend_enum.h b/Zend/zend_enum.h
index 6bffb886650..f252c938eb8 100644
--- a/Zend/zend_enum.h
+++ b/Zend/zend_enum.h
@@ -55,6 +55,7 @@ ZEND_API void zend_enum_add_case(zend_class_entry *ce, zend_string *case_name, z
ZEND_API void zend_enum_add_case_cstr(zend_class_entry *ce, const char *name, zval *value);
ZEND_API zend_object *zend_enum_get_case(zend_class_entry *ce, zend_string *name);
ZEND_API zend_object *zend_enum_get_case_cstr(zend_class_entry *ce, const char *name);
+ZEND_API zend_object *zend_enum_get_case_by_id(zend_class_entry *ce, int id);
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_from);
static zend_always_inline int zend_enum_fetch_case_id(zend_object *zobj)
diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c
index 2ba732c4540..794e75a1716 100644
--- a/ext/pcntl/pcntl.c
+++ b/ext/pcntl/pcntl.c
@@ -152,6 +152,7 @@ typedef psetid_t cpu_set_t;
#include "Zend/zend_max_execution_timer.h"
#include "pcntl_arginfo.h"
+#include "pcntl_decl.h"
static zend_class_entry *QosClass_ce;
ZEND_DECLARE_MODULE_GLOBALS(pcntl)
@@ -1839,28 +1840,28 @@ static qos_class_t qos_enum_to_pthread(zend_enum_Pcntl_QosClass entry)
static zend_object *qos_lval_to_zval(qos_class_t qos_class)
{
- const char *entryname;
+ int entry_id;
switch (qos_class)
{
case QOS_CLASS_USER_INTERACTIVE:
- entryname = "UserInteractive";
+ entry_id = ZEND_ENUM_Pcntl_QosClass_UserInteractive;
break;
case QOS_CLASS_USER_INITIATED:
- entryname = "UserInitiated";
+ entry_id = ZEND_ENUM_Pcntl_QosClass_UserInitiated;
break;
case QOS_CLASS_UTILITY:
- entryname = "Utility";
+ entry_id = ZEND_ENUM_Pcntl_QosClass_Utility;
break;
case QOS_CLASS_BACKGROUND:
- entryname = "Background";
+ entry_id = ZEND_ENUM_Pcntl_QosClass_Background;
break;
case QOS_CLASS_DEFAULT:
default:
- entryname = "Default";
+ entry_id = ZEND_ENUM_Pcntl_QosClass_Default;
break;
}
- return zend_enum_get_case_cstr(QosClass_ce, entryname);
+ return zend_enum_get_case_by_id(QosClass_ce, entry_id);
}
PHP_FUNCTION(pcntl_getqos_class)
diff --git a/ext/standard/io_poll.c b/ext/standard/io_poll.c
index b1eb7513f1c..837470a9f75 100644
--- a/ext/standard/io_poll.c
+++ b/ext/standard/io_poll.c
@@ -18,6 +18,7 @@
#include "php_network.h"
#include "php_poll.h"
#include "io_poll_arginfo.h"
+#include "io_poll_decl.h"
/* Class entries */
static zend_class_entry *php_io_poll_backend_class_entry;
@@ -118,38 +119,31 @@ static zend_result php_io_poll_events_to_event_enums(uint32_t events, zval *even
array_init(event_enums);
if (events & PHP_POLL_READ) {
- ZVAL_OBJ(&enum_case, zend_enum_get_case_cstr(php_io_poll_event_class_entry, "Read"));
- GC_ADDREF(Z_OBJ(enum_case));
+ ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_Read));
add_next_index_zval(event_enums, &enum_case);
}
if (events & PHP_POLL_WRITE) {
- ZVAL_OBJ(&enum_case, zend_enum_get_case_cstr(php_io_poll_event_class_entry, "Write"));
- GC_ADDREF(Z_OBJ(enum_case));
+ ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_Write));
add_next_index_zval(event_enums, &enum_case);
}
if (events & PHP_POLL_ERROR) {
- ZVAL_OBJ(&enum_case, zend_enum_get_case_cstr(php_io_poll_event_class_entry, "Error"));
- GC_ADDREF(Z_OBJ(enum_case));
+ ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_Error));
add_next_index_zval(event_enums, &enum_case);
}
if (events & PHP_POLL_HUP) {
- ZVAL_OBJ(&enum_case, zend_enum_get_case_cstr(php_io_poll_event_class_entry, "HangUp"));
- GC_ADDREF(Z_OBJ(enum_case));
+ ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_HangUp));
add_next_index_zval(event_enums, &enum_case);
}
if (events & PHP_POLL_RDHUP) {
- ZVAL_OBJ(&enum_case, zend_enum_get_case_cstr(php_io_poll_event_class_entry, "ReadHangUp"));
- GC_ADDREF(Z_OBJ(enum_case));
+ ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_ReadHangUp));
add_next_index_zval(event_enums, &enum_case);
}
if (events & PHP_POLL_ONESHOT) {
- ZVAL_OBJ(&enum_case, zend_enum_get_case_cstr(php_io_poll_event_class_entry, "OneShot"));
- GC_ADDREF(Z_OBJ(enum_case));
+ ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_OneShot));
add_next_index_zval(event_enums, &enum_case);
}
if (events & PHP_POLL_ET) {
- ZVAL_OBJ(&enum_case, zend_enum_get_case_cstr(php_io_poll_event_class_entry, "EdgeTriggered"));
- GC_ADDREF(Z_OBJ(enum_case));
+ ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_EdgeTriggered));
add_next_index_zval(event_enums, &enum_case);
}
diff --git a/ext/uri/uri_parser_rfc3986.c b/ext/uri/uri_parser_rfc3986.c
index 123f244a51d..b8a14a31c10 100644
--- a/ext/uri/uri_parser_rfc3986.c
+++ b/ext/uri/uri_parser_rfc3986.c
@@ -125,19 +125,19 @@ ZEND_ATTRIBUTE_NONNULL void php_uri_parser_rfc3986_uri_type_read(php_uri_parser_
{
const UriUriA *uriparser_uri = get_uri_for_reading(uri, PHP_URI_COMPONENT_READ_MODE_RAW);
- const char *type;
+ zend_object *value;
if (has_text_range(&uriparser_uri->scheme)) {
- type = "Uri";
+ value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_type, ZEND_ENUM_Uri_Rfc3986_UriType_Uri);
} else if (has_text_range(&uriparser_uri->hostText)) {
- type = "NetworkPathReference";
+ value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_type, ZEND_ENUM_Uri_Rfc3986_UriType_NetworkPathReference);
} else if (uriparser_uri->absolutePath) {
- type = "AbsolutePathReference";
+ value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_type, ZEND_ENUM_Uri_Rfc3986_UriType_AbsolutePathReference);
} else {
- type = "RelativePathReference";
+ value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_type, ZEND_ENUM_Uri_Rfc3986_UriType_RelativePathReference);
}
- ZVAL_OBJ_COPY(retval, zend_enum_get_case_cstr(php_uri_ce_rfc3986_uri_type, type));
+ ZVAL_OBJ_COPY(retval, value);
}
ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_scheme_read(void *uri, const php_uri_component_read_mode read_mode, zval *retval)
@@ -290,19 +290,19 @@ ZEND_ATTRIBUTE_NONNULL void php_uri_parser_rfc3986_host_type_read(php_uri_parser
return;
}
- const char *type;
+ zend_object *value;
if (uriparser_uri->hostData.ip4 != NULL) {
- type = "IPv4";
+ value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_host_type, ZEND_ENUM_Uri_Rfc3986_UriHostType_IPv4);
} else if (uriparser_uri->hostData.ip6 != NULL) {
- type = "IPv6";
+ value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_host_type, ZEND_ENUM_Uri_Rfc3986_UriHostType_IPv6);
} else if (has_text_range(&uriparser_uri->hostData.ipFuture)) {
- type = "IPvFuture";
+ value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_host_type, ZEND_ENUM_Uri_Rfc3986_UriHostType_IPvFuture);
} else {
- type = "RegisteredName";
+ value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_host_type, ZEND_ENUM_Uri_Rfc3986_UriHostType_RegisteredName);
}
- ZVAL_OBJ_COPY(retval, zend_enum_get_case_cstr(php_uri_ce_rfc3986_uri_host_type, type));
+ ZVAL_OBJ_COPY(retval, value);
}
static zend_result php_uri_parser_rfc3986_host_write(void *uri, const zval *value, zval *errors)
diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c
index 8cb3fe6cba0..d1875c4946d 100644
--- a/ext/zend_test/test.c
+++ b/ext/zend_test/test.c
@@ -39,6 +39,7 @@
#include "zend_mm_custom_handlers.h"
#include "ext/uri/php_uri.h"
#include "zend_observer.h"
+#include "test_decl.h"
#if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
# include <libxml/globals.h>
@@ -622,7 +623,7 @@ static ZEND_FUNCTION(zend_get_unit_enum)
{
ZEND_PARSE_PARAMETERS_NONE();
- RETURN_OBJ_COPY(zend_enum_get_case_cstr(zend_test_unit_enum, "Foo"));
+ RETURN_OBJ_COPY(zend_enum_get_case_by_id(zend_test_unit_enum, ZEND_ENUM_ZendTestUnitEnum_Foo));
}
static ZEND_FUNCTION(zend_test_zend_ini_parse_quantity)
diff --git a/main/streams/stream_errors.c b/main/streams/stream_errors.c
index 72f7428594c..87de69c35c0 100644
--- a/main/streams/stream_errors.c
+++ b/main/streams/stream_errors.c
@@ -45,6 +45,7 @@ static void php_stream_error_create_object(zval *zv, php_stream_error_entry *ent
case_name = "Generic";
}
+ /* TODO: migrate to zend_enum_get_case_by_id() */
zend_object *enum_obj = zend_enum_get_case_cstr(php_ce_stream_error_code, case_name);
ZEND_ASSERT(enum_obj != NULL);