PHP7ããæååã®ç¡é§ãªã³ãã¼ãæ¸ã£ã話
ãã®ã¨ã³ããªã¯闇PHP Advent Calendar 2015ã®14æ¥ç®ã§ãã
æ¬ç¨¿ã§ã¯ãPHP7ã®zend_string
æ§é ä½å°å
¥ã«ããã¡ãªããã®è©±ããã¾ãã
PHP5ã¨PHP7ã®æåååã®æ±ã
PHP5ã§ã¯ãæåååã®å¤æ°ã¯æ¬¡ã®ããã«ã¡ã¢ãªã«å²ãå½ã¦ããã¾ãï¼æ¨ªå¹ ãã£ã±ãã8ãã¤ãï¼ã
æååã®æ¬ä½ä»¥å¤ã¯zval
æ§é ä½ã§ç®¡çããæååã®æ¬ä½ã¯å¥éã¡ã¢ãªç¢ºä¿ããã¨ããå½¢ã«ãªã£ã¦ãã¾ããä¸æ¹ãPHP7ã§ã¯æ¬¡ã®ããã«ãªãã¾ãã
1ã¤ã®æååå¤æ°ããzval
æ§é ä½ã¨zend_string
æ§é ä½ã®çµã¿åããã§å®ç¾ããã¦ãã¾ãã
ããã ãè¦ãã¨ãPHP7ã§ã¯æååé·ã¨åç
§ã«ã¦ã³ã¿refconunt
ãzval
ãã追ãåºããã¦zend_string
ã«ç§»åãããããã§ãPHP5ã¨PHP7ã®ã¡ã¢ãªæ¶è²»éã«å¤§ããªéãã¯ç¡ãããã«æããããããã¾ããï¼ãããã¯PHP7ã®æ¹ãä¸å©ã«è¦ããããããã¾ããï¼ãããããå®éã«ã¯åç
§ã«ã¦ã³ã¿ãzend_string
ã«ç§»åãããã¨ã§æååã®ã³ãã¼åæ°ãæãããã¨ãã§ããã¡ã¢ãªã®ç¯ç´ãå®ç¾ã§ãã¦ãã¾ãã
以ä¸ãå®ä¾ã2ã¤ç´¹ä»ãã¦ããã¾ãã
æååæä½é¢æ°ã§ã®æååã³ãã¼ãæ¸ã£ã
ã¾ãã¯PHPã®é¢æ°strtolower()
ã®æåã«ã¤ãã¦è¦ã¦ã¿ã¾ããããä¸è¨ã®ã³ã¼ããå®è¡ããã¨ã$a
ã¨$b
ã®å¤ã¯ã©ã¡ãã"a"
ã«ãªãã¾ãã
<?php $a = chr(0x61); // "a" $b = strtolower($a); // "a"
ã¨ããã§ãPHP5ã§ä¸è¨ããã°ã©ã ãå®è¡ããã¨ã$a
ã¨$b
ã¨ã®æååã®å®ä½ã¯2ã¤ã«åããã¦ãã¾ãã
ä¸æ¹ãPHP7ã§åãããå ´åã¯$a
ã¨$b
ã¨ã®æååã®å®ä½ã¯åãã«ãªãã¾ãã
ãªããã®ãããªå·®ãçã¾ããã®ã§ãããããPHP5ã®strtolower
é¢æ°ã®å®ä½ã¯æ¬¡ã®ãããªã³ã¼ãã«ãªã£ã¦ãã¾ãã
/* ext/standard/string.c */ PHP_FUNCTION(strtolower) { char *str; int arglen; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &arglen) == FAILURE) { return; } str = estrndup(str, arglen); php_strtolower(str, arglen); RETURN_STRINGL(str, arglen, 0); }
å
ã®æååãè¤è£½ãã¦ãããphp_strtolower()
ã§å°æåã«ããã¨ããå¦çã«ãªã£ã¦ãã¾ãããã®å®è£
ã ã¨æååã®å®ä½ãå¥ã«ãªã£ã¦ãã¾ãã®ã¯å¿
ç¶ã§ããPHP7ã®æ¹ã¯ã©ãã§ãããããå¦çã®å®ä½ã§ããphp_string_tolower()
ãè¦ã¦ã¿ã¾ãããã
/* ext/standard/string.c */ PHPAPI zend_string *php_string_tolower(zend_string *s) { unsigned char *c, *e; c = (unsigned char *)ZSTR_VAL(s); e = c + ZSTR_LEN(s); while (c < e) { if (!islower(*c)) { register unsigned char *r; zend_string *res = zend_string_alloc(ZSTR_LEN(s), 0); if (c != (unsigned char*)ZSTR_VAL(s)) { memcpy(ZSTR_VAL(res), ZSTR_VAL(s), c - (unsigned char*)ZSTR_VAL(s)); } r = c + (ZSTR_VAL(res) - ZSTR_VAL(s)); while (c < e) { *r = tolower(*c); r++; c++; } *r = '\0'; return res; } c++; } return zend_string_copy(s); } /* Zend/zend_string.h */ static zend_always_inline zend_string *zend_string_copy(zend_string *s) { if (!ZSTR_IS_INTERNED(s)) { GC_REFCOUNT(s)++; } return s; }
php_string_tolower()
ã®å¼æ°zend_string *s
ãå
ã
å
¨ã¦å°æåãªãåç
§ã«ã¦ã³ã¿ã1å¢ããã¦åãæååãè¿ãããã以å¤ã®ã¨ãã¯æ°ãã«ã¡ã¢ãªã確ä¿ãã¦å°æååããæååãè¿ãã¨ããå¦çã«ãªã£ã¦ãããããç¡é§ãªæååã³ãã¼ãæ¸ãããã¨ãã§ãã¦ãã¾ãã
éã«ãPHP5ã§ã³ãã¼ãè¡ããã¦ãã¾ãçç±ã¯php_strtolower()
ã®å¼æ°ãchar *
åã§ããããã ã¨ãè¨ãã¾ããchar *
ã«ã¯åç
§ã«ã¦ã³ã¿ã®ãããªæ¦å¿µã¯ç¡ãã®ã§ãåããã¤ã³ã¿ããã®ã¾ã¾è¿ãã¨ããããã«ã¯ããã¾ããï¼åç
§ã«ã¦ã³ã¿ç¡ãã«æååãå
±æãã¦ãã¾ãã¨ã誰ããã¤ã¡ã¢ãªã解æ¾ãã¦ãããããããªããªãã¾ãï¼ããã¨ãã£ã¦ãæååãå
¥ã£ã¦ããã¨ã¯éããªãzval *
ã渡ãããã«ãããã¾ãããããPHP5ã®ãã¼ã¿æ§é ã®ã¾ã¾ã§ã¯æ¹åãã«ããç¹ã ã¨è¨ããã§ããããä¸æ¹ãPHP7ã§ã¯å
é¨çãªæååæä½é¢æ°ã«zend_string
ã渡ããããã«ãªã£ãã®ã§ãåç
§ã«ã¦ã³ã¿ãæ´»ç¨ãã¦ç¡é§ãªã³ãã¼ãé¿ããå®è£
ãç¾å®çã«ãªã£ãã¨ããããã§ãã
ããã·ã¥ãã¼ã§ã®æååã³ãã¼ãæ¸ã£ã
ä»åº¦ã¯é
åã®ãã¼ã«æååã使ã£ãå ´åã«æ³¨ç®ãã¦ã¿ã¾ãããããã¦ã次ã®ã³ã¼ãã®$k
ã¨$v
ã¨ã§ã¯æååã®ã³ãã¼ãçºçããã§ããããï¼
<?php $a = chr(0x61); // "a" $b = strtolower($a); // "a" foreach ([$a => $b] as $k => $v) { var_dump($k, $v); }
PHP5ã§ãã$v
ã¯$b
ã¨åãå®ä½ã¨ãªããã³ãã¼ã¯çºçãã¾ãããä¸æ¹ã$k
ã¯$a
ã¨å¥ã®å®ä½ã«ãªãã¾ããPHP5ã®ããã·ã¥å®è£
ã§ã¯æååãã¼ãzval *
ã§ãªãchar *
ã§ç®¡çãã¦ãããããæååã®ã³ãã¼ãé¿ãããã¾ãããæååæä½é¢æ°ã®ã¨ãã¨åãåé¡ãããã§ãèµ·ãã£ã¦ããããã§ãã
PHP7ã®å ´åã¯$a,$b,$k,$v
å
¨ã¦ã®æååã®å®ä½ãåä¸ã«ãªãã¾ããPHP7ã§ã¯ããã·ã¥ã®æååãã¼ãzend_string
ã§ç®¡çãããããã«ãªã£ãã®ã§ãåç
§ã«ã¦ã³ã¿ã使ã£ã¦æååãå
±æãããã¨ãã§ããã®ã§ãã
ãã¾ã
ãã®è¨äºãæ¸ãã¦ãã¦strtolower()/strtoupper()
ã®æååã³ãã¼ãããå°ãåæ¸ã§ãããã¨ã«æ°ä»ããã®ã§Pull Requestãæããã¨ãããç¡äºæ¡ç¨ãããããã§ãï¼ãOptimize strtolower()/strtoupper()ãï¼ã誤差ç¨åº¦ã ããã¨æãã¾ãããPHP 7.1.0ããPHPãæ´ã«éããªãããããã¾ããã
ã¾ã¨ã
PHP7ã§ã¯å
é¨çãªæååã®ç®¡çãzend_string
æ§é ä½ã«çµ±ä¸ããã¾ãããzend_string
ã¯ã¡ã³ãå¤æ°ã¨ãã¦åç
§ã«ã¦ã³ã¿ãæã£ã¦ããããããå©ç¨ãã¦æååã³ãã¼ã®åæ°ãæ¸ããã¦ãããã¨ãç´¹ä»ãã¾ãããzval
ãªã©ä»ã®ãã¼ã¿æ§é ã®å¤æ´ã¨åæ§ãé«éåããã³çã¡ã¢ãªåãæèããå¤æ´ã ã¨è¨ããã§ãããã