From ecdff3b563d58b8f7a503a51fe2370d900b9f454 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 8 Jul 2025 14:54:23 -0700 Subject: [PATCH] gen_stub: add StringBuilder class for managing known strings Split out from the PropertyInfo class so that known strings can also be used for attributes in a follow-up commit. --- build/gen_stub.php | 138 ++++++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 63 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 8f2ddf10a8b..a578af414dc 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2955,14 +2955,7 @@ class ConstInfo extends VariableLike } } -class PropertyInfo extends VariableLike -{ - private /* readonly */ int $classFlags; - public /* readonly */ PropertyName $name; - private /* readonly */ ?Expr $defaultValue; - private /* readonly */ ?string $defaultValueString; - private /* readonly */ bool $isDocReadonly; - private /* readonly */ bool $isVirtual; +class StringBuilder { // Map possible variable names to the known string constant, see // ZEND_KNOWN_STRINGS @@ -3067,6 +3060,75 @@ class PropertyInfo extends VariableLike "clone" => "ZEND_STR_CLONE", ]; + /** + * Get an array of three strings: + * - declaration of zend_string, if needed, or empty otherwise + * - usage of that zend_string, or usage with ZSTR_KNOWN() + * - freeing the zend_string, if needed + * + * @param string $varName + * @param string $strContent + * @param ?int $minPHPCompatibility + * @return string[] + */ + public static function getString( + string $varName, + string $content, + ?int $minPHPCompatibility + ): array { + // Generally strings will not be known + $result = [ + "\tzend_string *$varName = zend_string_init(\"$content\", sizeof(\"$content\") - 1, 1);\n", + $varName, + "\tzend_string_release($varName);\n" + ]; + // If not set, use the current latest version + $allVersions = ALL_PHP_VERSION_IDS; + $minPhp = $minPHPCompatibility ?? end($allVersions); + if ($minPhp < PHP_80_VERSION_ID) { + // No known strings in 7.0 + return $result; + } + $include = self::PHP_80_KNOWN; + switch ($minPhp) { + case PHP_85_VERSION_ID: + $include = array_merge($include, self::PHP_85_KNOWN); + // Intentional fall through + + case PHP_84_VERSION_ID: + $include = array_merge($include, self::PHP_84_KNOWN); + // Intentional fall through + + case PHP_83_VERSION_ID: + case PHP_82_VERSION_ID: + $include = array_merge($include, self::PHP_82_KNOWN); + // Intentional fall through + + case PHP_81_VERSION_ID: + $include = array_merge($include, self::PHP_81_KNOWN); + break; + } + if (array_key_exists($content, $include)) { + $knownStr = $include[$content]; + return [ + '', + "ZSTR_KNOWN($knownStr)", + '', + ]; + } + return $result; + } +} + +class PropertyInfo extends VariableLike +{ + private /* readonly */ int $classFlags; + public /* readonly */ PropertyName $name; + private /* readonly */ ?Expr $defaultValue; + private /* readonly */ ?string $defaultValueString; + private /* readonly */ bool $isDocReadonly; + private /* readonly */ bool $isVirtual; + /** * @param AttributeInfo[] $attributes */ @@ -3147,7 +3209,11 @@ class PropertyInfo extends VariableLike $code .= $defaultValue->initializeZval($zvalName); } - [$stringInit, $nameCode, $stringRelease] = $this->getString($propertyName); + [$stringInit, $nameCode, $stringRelease] = StringBuilder::getString( + "property_{$propertyName}_name", + $propertyName, + $this->phpVersionIdMinimumCompatibility + ); $code .= $stringInit; if ($this->exposedDocComment) { @@ -3182,60 +3248,6 @@ class PropertyInfo extends VariableLike return $code; } - /** - * Get an array of three strings: - * - declaration of zend_string, if needed, or empty otherwise - * - usage of that zend_string, or usage with ZSTR_KNOWN() - * - freeing the zend_string, if needed - * - * @param string $propName - * @return string[] - */ - private function getString(string $propName): array { - // Generally strings will not be known - $nameCode = "property_{$propName}_name"; - $result = [ - "\tzend_string *$nameCode = zend_string_init(\"$propName\", sizeof(\"$propName\") - 1, 1);\n", - $nameCode, - "\tzend_string_release($nameCode);\n" - ]; - // If not set, use the current latest version - $allVersions = ALL_PHP_VERSION_IDS; - $minPhp = $this->phpVersionIdMinimumCompatibility ?? end($allVersions); - if ($minPhp < PHP_80_VERSION_ID) { - // No known strings in 7.0 - return $result; - } - $include = self::PHP_80_KNOWN; - switch ($minPhp) { - case PHP_85_VERSION_ID: - $include = array_merge($include, self::PHP_85_KNOWN); - // Intentional fall through - - case PHP_84_VERSION_ID: - $include = array_merge($include, self::PHP_84_KNOWN); - // Intentional fall through - - case PHP_83_VERSION_ID: - case PHP_82_VERSION_ID: - $include = array_merge($include, self::PHP_82_KNOWN); - // Intentional fall through - - case PHP_81_VERSION_ID: - $include = array_merge($include, self::PHP_81_KNOWN); - break; - } - if (array_key_exists($propName, $include)) { - $knownStr = $include[$propName]; - return [ - '', - "ZSTR_KNOWN($knownStr)", - '', - ]; - } - return $result; - } - /** * @return array */