@@ -42,7 +42,7 @@ $after = preg_replace_callback('/a/', fn($m) => 'x', $before, -1, $count, PREG_R
4242show ("callback_change " , $ before , $ after , $ count );
4343echo "callback_change: " . $ after . "\n" ;
4444
45- /* Edge case: replacements change locally but cancel out globally */
45+ /* Replacements change locally but cancel out globally */
4646function cancel_out_callback ($ arr ) {
4747 return match ($ arr [0 ]) {
4848 'a ' => 'ab ' ,
@@ -53,6 +53,43 @@ $before3 = "abba";
5353$ after = preg_replace_callback ('/^a|bba/ ' , 'cancel_out_callback ' , $ before3 , -1 , $ count , PREG_REPLACE_COUNT_CHANGES );
5454show ("callback_cancel_out " , $ before3 , $ after , $ count );
5555
56+ /* Cancel out would happen, but limit prevents it */
57+ $ after = preg_replace_callback ('/^a|bba/ ' , 'cancel_out_callback ' , $ before3 , 1 , $ count , PREG_REPLACE_COUNT_CHANGES );
58+ show ("callback_cancel_out_limit_1 " , $ before3 , $ after , $ count );
59+ echo "callback_cancel_out_limit_1: " . $ after . "\n" ;
60+
61+ /* Zero length match inside the string */
62+ $ before4 = "ab " ;
63+ $ after = preg_replace ('/(?=b)/ ' , '' , $ before4 , -1 , $ count , PREG_REPLACE_COUNT_CHANGES );
64+ show ("empty_lookahead_identity " , $ before4 , $ after , $ count );
65+
66+ $ after = preg_replace ('/(?=b)/ ' , 'X ' , $ before4 , -1 , $ count , PREG_REPLACE_COUNT_CHANGES );
67+ show ("empty_lookahead_change " , $ before4 , $ after , $ count );
68+ echo "empty_lookahead_change: " . $ after . "\n" ;
69+
70+ /* Zero length match at every position */
71+ $ after = preg_replace ('/(?=)/ ' , '' , $ before4 , -1 , $ count , PREG_REPLACE_COUNT_CHANGES );
72+ show ("empty_everywhere_identity " , $ before4 , $ after , $ count );
73+
74+ $ after = preg_replace ('/(?=)/ ' , '- ' , $ before4 , -1 , $ count , PREG_REPLACE_COUNT_CHANGES );
75+ show ("empty_everywhere_change " , $ before4 , $ after , $ count );
76+ echo "empty_everywhere_change: " . $ after . "\n" ;
77+
78+ /* Subject array should count per element */
79+ $ subjects = ["abba " , "abca " ];
80+ $ after = preg_replace_callback ('/^a|bba/ ' , 'cancel_out_callback ' , $ subjects , -1 , $ count , PREG_REPLACE_COUNT_CHANGES );
81+ echo "array_subject_after: " . var_export ($ after , true ) . "\n" ;
82+ echo "array_subject_count: " . $ count . "\n" ;
83+
84+ /* UTF 8, ensure byte comparison is correct */
85+ $ before5 = "éaé " ;
86+ $ after = preg_replace ('/é/u ' , 'é ' , $ before5 , -1 , $ count , PREG_REPLACE_COUNT_CHANGES );
87+ show ("utf8_identity " , $ before5 , $ after , $ count );
88+
89+ $ after = preg_replace ('/é/u ' , 'e ' , $ before5 , -1 , $ count , PREG_REPLACE_COUNT_CHANGES );
90+ show ("utf8_change " , $ before5 , $ after , $ count );
91+ echo "utf8_change: " . $ after . "\n" ;
92+
5693/* Empty string match behavior */
5794$ before2 = "abc " ;
5895$ after = preg_replace ('/^/ ' , '' , $ before2 , -1 , $ count , PREG_REPLACE_COUNT_CHANGES );
@@ -80,6 +117,29 @@ callback_change: 2 REPLACEMENTS
80117callback_change: xbcx
81118callback_cancel_out: NO REPLACEMENTS
82119callback_cancel_out: 0 REPLACEMENTS
120+ callback_cancel_out_limit_1: CHANGED
121+ callback_cancel_out_limit_1: 1 REPLACEMENTS
122+ callback_cancel_out_limit_1: abbba
123+ empty_lookahead_identity: NO REPLACEMENTS
124+ empty_lookahead_identity: 0 REPLACEMENTS
125+ empty_lookahead_change: CHANGED
126+ empty_lookahead_change: 1 REPLACEMENTS
127+ empty_lookahead_change: aXb
128+ empty_everywhere_identity: NO REPLACEMENTS
129+ empty_everywhere_identity: 0 REPLACEMENTS
130+ empty_everywhere_change: CHANGED
131+ empty_everywhere_change: 3 REPLACEMENTS
132+ empty_everywhere_change: -a-b-
133+ array_subject_after: array (
134+ 0 => 'abba',
135+ 1 => 'abbca',
136+ )
137+ array_subject_count: 1
138+ utf8_identity: NO REPLACEMENTS
139+ utf8_identity: 0 REPLACEMENTS
140+ utf8_change: CHANGED
141+ utf8_change: 2 REPLACEMENTS
142+ utf8_change: eae
83143empty_match_identity: NO REPLACEMENTS
84144empty_match_identity: 0 REPLACEMENTS
85145empty_match_change: CHANGED
0 commit comments