3030#include "zend_exceptions.h"
3131#include "zend_closures.h"
3232
33+ #ifdef __SSE2__
34+ #include <emmintrin.h>
35+ #endif
36+
3337#if ZEND_USE_TOLOWER_L
3438#include <locale.h>
3539static _locale_t current_locale = NULL ;
@@ -2456,17 +2460,38 @@ ZEND_API void zend_update_current_locale(void) /* {{{ */
24562460/* }}} */
24572461#endif
24582462
2459- ZEND_API char * ZEND_FASTCALL zend_str_tolower_copy (char * dest , const char * source , size_t length ) /* {{{ */
2460- {
2461- register unsigned char * str = (unsigned char * )source ;
2462- register unsigned char * result = (unsigned char * )dest ;
2463- register unsigned char * end = str + length ;
2464-
2465- while (str < end ) {
2466- * result ++ = zend_tolower_ascii (* str ++ );
2463+ static zend_always_inline void zend_str_tolower_impl (char * dest , const char * str , size_t length ) /* {{{ */ {
2464+ register unsigned char * p = (unsigned char * )str ;
2465+ register unsigned char * q = (unsigned char * )dest ;
2466+ unsigned char * end = p + length ;
2467+ #ifdef __SSE2__
2468+ if (length >= 16 ) {
2469+ const __m128i _A = _mm_set1_epi8 ('A' - 1 );
2470+ const __m128i Z_ = _mm_set1_epi8 ('Z' + 1 );
2471+ const __m128i delta = _mm_set1_epi8 ('a' - 'A' );
2472+ do {
2473+ __m128i op = _mm_loadu_si128 ((__m128i * )p );
2474+ __m128i gt = _mm_cmpgt_epi8 (op , _A );
2475+ __m128i lt = _mm_cmplt_epi8 (op , Z_ );
2476+ __m128i mingle = _mm_and_si128 (gt , lt );
2477+ __m128i add = _mm_and_si128 (mingle , delta );
2478+ __m128i lower = _mm_add_epi8 (op , add );
2479+ _mm_storeu_si128 ((__m128i * )q , lower );
2480+ p += 16 ;
2481+ q += 16 ;
2482+ } while (p + 16 <= end );
24672483 }
2468- * result = '\0' ;
2484+ #endif
2485+ while (p < end ) {
2486+ * q ++ = zend_tolower_ascii (* p ++ );
2487+ }
2488+ }
2489+ /* }}} */
24692490
2491+ ZEND_API char * ZEND_FASTCALL zend_str_tolower_copy (char * dest , const char * source , size_t length ) /* {{{ */
2492+ {
2493+ zend_str_tolower_impl (dest , source , length );
2494+ dest [length ] = '\0' ;
24702495 return dest ;
24712496}
24722497/* }}} */
@@ -2479,13 +2504,7 @@ ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup(const char *source, size_t len
24792504
24802505ZEND_API void ZEND_FASTCALL zend_str_tolower (char * str , size_t length ) /* {{{ */
24812506{
2482- register unsigned char * p = (unsigned char * )str ;
2483- register unsigned char * end = p + length ;
2484-
2485- while (p < end ) {
2486- * p = zend_tolower_ascii (* p );
2487- p ++ ;
2488- }
2507+ zend_str_tolower_impl (str , (const char * )str , length );
24892508}
24902509/* }}} */
24912510
@@ -2503,12 +2522,8 @@ ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup_ex(const char *source, size_t
25032522 memcpy (res , source , p - (const unsigned char * )source );
25042523 }
25052524 r = (unsigned char * )p + (res - source );
2506- while (p < end ) {
2507- * r = zend_tolower_ascii (* p );
2508- p ++ ;
2509- r ++ ;
2510- }
2511- * r = '\0' ;
2525+ zend_str_tolower_impl ((char * )r , (const char * )p , end - p );
2526+ res [length ] = '\0' ;
25122527 return res ;
25132528 }
25142529 p ++ ;
@@ -2521,7 +2536,6 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, int
25212536{
25222537 register unsigned char * p = (unsigned char * )ZSTR_VAL (str );
25232538 register unsigned char * end = p + ZSTR_LEN (str );
2524-
25252539 while (p < end ) {
25262540 if (* p != zend_tolower_ascii (* p )) {
25272541 zend_string * res = zend_string_alloc (ZSTR_LEN (str ), persistent );
@@ -2531,12 +2545,8 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, int
25312545 memcpy (ZSTR_VAL (res ), ZSTR_VAL (str ), p - (unsigned char * )ZSTR_VAL (str ));
25322546 }
25332547 r = p + (ZSTR_VAL (res ) - ZSTR_VAL (str ));
2534- while (p < end ) {
2535- * r = zend_tolower_ascii (* p );
2536- p ++ ;
2537- r ++ ;
2538- }
2539- * r = '\0' ;
2548+ zend_str_tolower_impl ((char * )r , (const char * )p , end - p );
2549+ ZSTR_VAL (res )[ZSTR_LEN (res )] = '\0' ;
25402550 return res ;
25412551 }
25422552 p ++ ;
0 commit comments