@@ -73,7 +73,27 @@ static const unsigned char tolower_map[256] = {
73
73
0xf0 ,0xf1 ,0xf2 ,0xf3 ,0xf4 ,0xf5 ,0xf6 ,0xf7 ,0xf8 ,0xf9 ,0xfa ,0xfb ,0xfc ,0xfd ,0xfe ,0xff
74
74
};
75
75
76
- #define zend_tolower_ascii (c ) (tolower_map[(unsigned char)(c)])
76
+ static const unsigned char toupper_map [256 ] = {
77
+ 0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07 ,0x08 ,0x09 ,0x0a ,0x0b ,0x0c ,0x0d ,0x0e ,0x0f ,
78
+ 0x10 ,0x11 ,0x12 ,0x13 ,0x14 ,0x15 ,0x16 ,0x17 ,0x18 ,0x19 ,0x1a ,0x1b ,0x1c ,0x1d ,0x1e ,0x1f ,
79
+ 0x20 ,0x21 ,0x22 ,0x23 ,0x24 ,0x25 ,0x26 ,0x27 ,0x28 ,0x29 ,0x2a ,0x2b ,0x2c ,0x2d ,0x2e ,0x2f ,
80
+ 0x30 ,0x31 ,0x32 ,0x33 ,0x34 ,0x35 ,0x36 ,0x37 ,0x38 ,0x39 ,0x3a ,0x3b ,0x3c ,0x3d ,0x3e ,0x3f ,
81
+ 0x40 ,0x41 ,0x42 ,0x43 ,0x44 ,0x45 ,0x46 ,0x47 ,0x48 ,0x49 ,0x4a ,0x4b ,0x4c ,0x4d ,0x4e ,0x4f ,
82
+ 0x50 ,0x51 ,0x52 ,0x53 ,0x54 ,0x55 ,0x56 ,0x57 ,0x58 ,0x59 ,0x5a ,0x5b ,0x5c ,0x5d ,0x5e ,0x5f ,
83
+ 0x60 ,0x41 ,0x42 ,0x43 ,0x44 ,0x45 ,0x46 ,0x47 ,0x48 ,0x49 ,0x4a ,0x4b ,0x4c ,0x4d ,0x4e ,0x4f ,
84
+ 0x50 ,0x51 ,0x52 ,0x53 ,0x54 ,0x55 ,0x56 ,0x57 ,0x58 ,0x59 ,0x5a ,0x7b ,0x7c ,0x7d ,0x7e ,0x7f ,
85
+ 0x80 ,0x81 ,0x82 ,0x83 ,0x84 ,0x85 ,0x86 ,0x87 ,0x88 ,0x89 ,0x8a ,0x8b ,0x8c ,0x8d ,0x8e ,0x8f ,
86
+ 0x90 ,0x91 ,0x92 ,0x93 ,0x94 ,0x95 ,0x96 ,0x97 ,0x98 ,0x99 ,0x9a ,0x9b ,0x9c ,0x9d ,0x9e ,0x9f ,
87
+ 0xa0 ,0xa1 ,0xa2 ,0xa3 ,0xa4 ,0xa5 ,0xa6 ,0xa7 ,0xa8 ,0xa9 ,0xaa ,0xab ,0xac ,0xad ,0xae ,0xaf ,
88
+ 0xb0 ,0xb1 ,0xb2 ,0xb3 ,0xb4 ,0xb5 ,0xb6 ,0xb7 ,0xb8 ,0xb9 ,0xba ,0xbb ,0xbc ,0xbd ,0xbe ,0xbf ,
89
+ 0xc0 ,0xc1 ,0xc2 ,0xc3 ,0xc4 ,0xc5 ,0xc6 ,0xc7 ,0xc8 ,0xc9 ,0xca ,0xcb ,0xcc ,0xcd ,0xce ,0xcf ,
90
+ 0xd0 ,0xd1 ,0xd2 ,0xd3 ,0xd4 ,0xd5 ,0xd6 ,0xd7 ,0xd8 ,0xd9 ,0xda ,0xdb ,0xdc ,0xdd ,0xde ,0xdf ,
91
+ 0xe0 ,0xe1 ,0xe2 ,0xe3 ,0xe4 ,0xe5 ,0xe6 ,0xe7 ,0xe8 ,0xe9 ,0xea ,0xeb ,0xec ,0xed ,0xee ,0xef ,
92
+ 0xf0 ,0xf1 ,0xf2 ,0xf3 ,0xf4 ,0xf5 ,0xf6 ,0xf7 ,0xf8 ,0xf9 ,0xfa ,0xfb ,0xfc ,0xfd ,0xfe ,0xff
93
+ };
94
+
95
+ #define i_zend_tolower_ascii (c ) (tolower_map[(unsigned char)(c)])
96
+ #define i_zend_toupper_ascii (c ) (toupper_map[(unsigned char)(c)])
77
97
78
98
/**
79
99
* Functions using locale lowercase:
@@ -2686,11 +2706,51 @@ static zend_always_inline void zend_str_tolower_impl(char *dest, const char *str
2686
2706
}
2687
2707
#endif
2688
2708
while (p < end ) {
2689
- * q ++ = zend_tolower_ascii (* p ++ );
2709
+ * q ++ = i_zend_tolower_ascii (* p ++ );
2690
2710
}
2691
2711
}
2692
2712
/* }}} */
2693
2713
2714
+ static zend_always_inline void zend_str_toupper_impl (char * dest , const char * str , size_t length ) /* {{{ */ {
2715
+ unsigned char * p = (unsigned char * )str ;
2716
+ unsigned char * q = (unsigned char * )dest ;
2717
+ unsigned char * end = p + length ;
2718
+ #ifdef __SSE2__
2719
+ if (length >= 16 ) {
2720
+ const __m128i _a = _mm_set1_epi8 ('a' - 1 );
2721
+ const __m128i z_ = _mm_set1_epi8 ('z' + 1 );
2722
+ const __m128i delta = _mm_set1_epi8 ('a' - 'A' );
2723
+ do {
2724
+ __m128i op = _mm_loadu_si128 ((__m128i * )p );
2725
+ __m128i gt = _mm_cmpgt_epi8 (op , _a );
2726
+ __m128i lt = _mm_cmplt_epi8 (op , z_ );
2727
+ __m128i mingle = _mm_and_si128 (gt , lt );
2728
+ __m128i sub = _mm_and_si128 (mingle , delta );
2729
+ __m128i upper = _mm_sub_epi8 (op , sub );
2730
+ _mm_storeu_si128 ((__m128i * )q , upper );
2731
+ p += 16 ;
2732
+ q += 16 ;
2733
+ } while (p + 16 <= end );
2734
+ }
2735
+ #endif
2736
+ while (p < end ) {
2737
+ * q ++ = i_zend_toupper_ascii (* p ++ );
2738
+ }
2739
+ }
2740
+ /* }}} */
2741
+
2742
+ ZEND_API int ZEND_FASTCALL zend_tolower_ascii (int c ) /* {{{ */
2743
+ {
2744
+ return i_zend_tolower_ascii (c );
2745
+ }
2746
+ /* }}} */
2747
+
2748
+ ZEND_API int ZEND_FASTCALL zend_toupper_ascii (int c ) /* {{{ */
2749
+ {
2750
+ return i_zend_toupper_ascii (c );
2751
+ }
2752
+ /* }}} */
2753
+
2694
2754
ZEND_API char * ZEND_FASTCALL zend_str_tolower_copy (char * dest , const char * source , size_t length ) /* {{{ */
2695
2755
{
2696
2756
zend_str_tolower_impl (dest , source , length );
@@ -2699,25 +2759,46 @@ ZEND_API char* ZEND_FASTCALL zend_str_tolower_copy(char *dest, const char *sourc
2699
2759
}
2700
2760
/* }}} */
2701
2761
2762
+ ZEND_API char * ZEND_FASTCALL zend_str_toupper_copy (char * dest , const char * source , size_t length ) /* {{{ */
2763
+ {
2764
+ zend_str_toupper_impl (dest , source , length );
2765
+ dest [length ] = '\0' ;
2766
+ return dest ;
2767
+ }
2768
+ /* }}} */
2769
+
2702
2770
ZEND_API char * ZEND_FASTCALL zend_str_tolower_dup (const char * source , size_t length ) /* {{{ */
2703
2771
{
2704
2772
return zend_str_tolower_copy ((char * )emalloc (length + 1 ), source , length );
2705
2773
}
2706
2774
/* }}} */
2707
2775
2776
+ ZEND_API char * ZEND_FASTCALL zend_str_toupper_dup (const char * source , size_t length ) /* {{{ */
2777
+ {
2778
+ return zend_str_toupper_copy ((char * )emalloc (length + 1 ), source , length );
2779
+ }
2780
+ /* }}} */
2781
+
2708
2782
ZEND_API void ZEND_FASTCALL zend_str_tolower (char * str , size_t length ) /* {{{ */
2709
2783
{
2710
2784
zend_str_tolower_impl (str , (const char * )str , length );
2711
2785
}
2712
2786
/* }}} */
2713
2787
2788
+ ZEND_API void ZEND_FASTCALL zend_str_toupper (char * str , size_t length ) /* {{{ */
2789
+ {
2790
+ zend_str_toupper_impl (str , (const char * )str , length );
2791
+ }
2792
+ /* }}} */
2793
+
2794
+
2714
2795
ZEND_API char * ZEND_FASTCALL zend_str_tolower_dup_ex (const char * source , size_t length ) /* {{{ */
2715
2796
{
2716
2797
const unsigned char * p = (const unsigned char * )source ;
2717
2798
const unsigned char * end = p + length ;
2718
2799
2719
2800
while (p < end ) {
2720
- if (* p != zend_tolower_ascii (* p )) {
2801
+ if (* p != i_zend_tolower_ascii (* p )) {
2721
2802
char * res = (char * )emalloc (length + 1 );
2722
2803
unsigned char * r ;
2723
2804
@@ -2735,6 +2816,30 @@ ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup_ex(const char *source, size_t
2735
2816
}
2736
2817
/* }}} */
2737
2818
2819
+ ZEND_API char * ZEND_FASTCALL zend_str_toupper_dup_ex (const char * source , size_t length ) /* {{{ */
2820
+ {
2821
+ const unsigned char * p = (const unsigned char * )source ;
2822
+ const unsigned char * end = p + length ;
2823
+
2824
+ while (p < end ) {
2825
+ if (* p != i_zend_toupper_ascii (* p )) {
2826
+ char * res = (char * )emalloc (length + 1 );
2827
+ unsigned char * r ;
2828
+
2829
+ if (p != (const unsigned char * )source ) {
2830
+ memcpy (res , source , p - (const unsigned char * )source );
2831
+ }
2832
+ r = (unsigned char * )p + (res - source );
2833
+ zend_str_toupper_impl ((char * )r , (const char * )p , end - p );
2834
+ res [length ] = '\0' ;
2835
+ return res ;
2836
+ }
2837
+ p ++ ;
2838
+ }
2839
+ return NULL ;
2840
+ }
2841
+ /* }}} */
2842
+
2738
2843
ZEND_API zend_string * ZEND_FASTCALL zend_string_tolower_ex (zend_string * str , bool persistent ) /* {{{ */
2739
2844
{
2740
2845
size_t length = ZSTR_LEN (str );
@@ -2771,13 +2876,67 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, boo
2771
2876
#endif
2772
2877
2773
2878
while (p < end ) {
2774
- if (* p != zend_tolower_ascii (* p )) {
2879
+ if (* p != i_zend_tolower_ascii (* p )) {
2880
+ zend_string * res = zend_string_alloc (length , persistent );
2881
+ memcpy (ZSTR_VAL (res ), ZSTR_VAL (str ), p - (unsigned char * ) ZSTR_VAL (str ));
2882
+
2883
+ unsigned char * q = p + (ZSTR_VAL (res ) - ZSTR_VAL (str ));
2884
+ while (p < end ) {
2885
+ * q ++ = i_zend_tolower_ascii (* p ++ );
2886
+ }
2887
+ ZSTR_VAL (res )[length ] = '\0' ;
2888
+ return res ;
2889
+ }
2890
+ p ++ ;
2891
+ }
2892
+
2893
+ return zend_string_copy (str );
2894
+ }
2895
+ /* }}} */
2896
+
2897
+ ZEND_API zend_string * ZEND_FASTCALL zend_string_toupper_ex (zend_string * str , bool persistent ) /* {{{ */
2898
+ {
2899
+ size_t length = ZSTR_LEN (str );
2900
+ unsigned char * p = (unsigned char * ) ZSTR_VAL (str );
2901
+ unsigned char * end = p + length ;
2902
+
2903
+ #ifdef __SSE2__
2904
+ while (p + 16 <= end ) {
2905
+ const __m128i _a = _mm_set1_epi8 ('a' - 1 );
2906
+ const __m128i z_ = _mm_set1_epi8 ('z' + 1 );
2907
+ __m128i op = _mm_loadu_si128 ((__m128i * )p );
2908
+ __m128i gt = _mm_cmpgt_epi8 (op , _a );
2909
+ __m128i lt = _mm_cmplt_epi8 (op , z_ );
2910
+ __m128i mingle = _mm_and_si128 (gt , lt );
2911
+ if (_mm_movemask_epi8 (mingle )) {
2912
+ zend_string * res = zend_string_alloc (length , persistent );
2913
+ memcpy (ZSTR_VAL (res ), ZSTR_VAL (str ), p - (unsigned char * ) ZSTR_VAL (str ));
2914
+ unsigned char * q = p + (ZSTR_VAL (res ) - ZSTR_VAL (str ));
2915
+
2916
+ /* Uppercase the chunk we already compared. */
2917
+ const __m128i delta = _mm_set1_epi8 ('a' - 'A' );
2918
+ __m128i add = _mm_and_si128 (mingle , delta );
2919
+ __m128i upper = _mm_sub_epi8 (op , add );
2920
+ _mm_storeu_si128 ((__m128i * ) q , upper );
2921
+
2922
+ /* Uppercase the rest of the string. */
2923
+ p += 16 ; q += 16 ;
2924
+ zend_str_toupper_impl ((char * ) q , (const char * ) p , end - p );
2925
+ ZSTR_VAL (res )[length ] = '\0' ;
2926
+ return res ;
2927
+ }
2928
+ p += 16 ;
2929
+ }
2930
+ #endif
2931
+
2932
+ while (p < end ) {
2933
+ if (* p != i_zend_toupper_ascii (* p )) {
2775
2934
zend_string * res = zend_string_alloc (length , persistent );
2776
2935
memcpy (ZSTR_VAL (res ), ZSTR_VAL (str ), p - (unsigned char * ) ZSTR_VAL (str ));
2777
2936
2778
2937
unsigned char * q = p + (ZSTR_VAL (res ) - ZSTR_VAL (str ));
2779
2938
while (p < end ) {
2780
- * q ++ = zend_tolower_ascii (* p ++ );
2939
+ * q ++ = i_zend_toupper_ascii (* p ++ );
2781
2940
}
2782
2941
ZSTR_VAL (res )[length ] = '\0' ;
2783
2942
return res ;
@@ -2832,8 +2991,8 @@ ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp(const char *s1, size_t len1, c
2832
2991
2833
2992
len = MIN (len1 , len2 );
2834
2993
while (len -- ) {
2835
- c1 = zend_tolower_ascii (* (unsigned char * )s1 ++ );
2836
- c2 = zend_tolower_ascii (* (unsigned char * )s2 ++ );
2994
+ c1 = i_zend_tolower_ascii (* (unsigned char * )s1 ++ );
2995
+ c2 = i_zend_tolower_ascii (* (unsigned char * )s2 ++ );
2837
2996
if (c1 != c2 ) {
2838
2997
return c1 - c2 ;
2839
2998
}
@@ -2853,8 +3012,8 @@ ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp(const char *s1, size_t len1,
2853
3012
}
2854
3013
len = MIN (length , MIN (len1 , len2 ));
2855
3014
while (len -- ) {
2856
- c1 = zend_tolower_ascii (* (unsigned char * )s1 ++ );
2857
- c2 = zend_tolower_ascii (* (unsigned char * )s2 ++ );
3015
+ c1 = i_zend_tolower_ascii (* (unsigned char * )s1 ++ );
3016
+ c2 = i_zend_tolower_ascii (* (unsigned char * )s2 ++ );
2858
3017
if (c1 != c2 ) {
2859
3018
return c1 - c2 ;
2860
3019
}
0 commit comments