@@ -605,6 +605,7 @@ make_bloom_mask(int kind, void* ptr, Py_ssize_t len)
605605#include "stringlib/split.h"
606606#include "stringlib/count.h"
607607#include "stringlib/find.h"
608+ #include "stringlib/replace.h"
608609#include "stringlib/find_max_char.h"
609610#include "stringlib/localeutil.h"
610611#include "stringlib/undef.h"
@@ -615,6 +616,7 @@ make_bloom_mask(int kind, void* ptr, Py_ssize_t len)
615616#include "stringlib/split.h"
616617#include "stringlib/count.h"
617618#include "stringlib/find.h"
619+ #include "stringlib/replace.h"
618620#include "stringlib/find_max_char.h"
619621#include "stringlib/localeutil.h"
620622#include "stringlib/undef.h"
@@ -625,6 +627,7 @@ make_bloom_mask(int kind, void* ptr, Py_ssize_t len)
625627#include "stringlib/split.h"
626628#include "stringlib/count.h"
627629#include "stringlib/find.h"
630+ #include "stringlib/replace.h"
628631#include "stringlib/find_max_char.h"
629632#include "stringlib/localeutil.h"
630633#include "stringlib/undef.h"
@@ -9927,6 +9930,31 @@ anylib_count(int kind, PyObject *sstr, void* sbuf, Py_ssize_t slen,
99279930 return 0 ;
99289931}
99299932
9933+ static void
9934+ replace_1char_inplace (PyObject * u , Py_ssize_t pos ,
9935+ Py_UCS4 u1 , Py_UCS4 u2 , Py_ssize_t maxcount )
9936+ {
9937+ int kind = PyUnicode_KIND (u );
9938+ void * data = PyUnicode_DATA (u );
9939+ Py_ssize_t len = PyUnicode_GET_LENGTH (u );
9940+ if (kind == PyUnicode_1BYTE_KIND ) {
9941+ ucs1lib_replace_1char_inplace ((Py_UCS1 * )data + pos ,
9942+ (Py_UCS1 * )data + len ,
9943+ u1 , u2 , maxcount );
9944+ }
9945+ else if (kind == PyUnicode_2BYTE_KIND ) {
9946+ ucs2lib_replace_1char_inplace ((Py_UCS2 * )data + pos ,
9947+ (Py_UCS2 * )data + len ,
9948+ u1 , u2 , maxcount );
9949+ }
9950+ else {
9951+ assert (kind == PyUnicode_4BYTE_KIND );
9952+ ucs4lib_replace_1char_inplace ((Py_UCS4 * )data + pos ,
9953+ (Py_UCS4 * )data + len ,
9954+ u1 , u2 , maxcount );
9955+ }
9956+ }
9957+
99309958static PyObject *
99319959replace (PyObject * self , PyObject * str1 ,
99329960 PyObject * str2 , Py_ssize_t maxcount )
@@ -9943,7 +9971,7 @@ replace(PyObject *self, PyObject *str1,
99439971 Py_ssize_t len1 = PyUnicode_GET_LENGTH (str1 );
99449972 Py_ssize_t len2 = PyUnicode_GET_LENGTH (str2 );
99459973 int mayshrink ;
9946- Py_UCS4 maxchar , maxchar_str2 ;
9974+ Py_UCS4 maxchar , maxchar_str1 , maxchar_str2 ;
99479975
99489976 if (maxcount < 0 )
99499977 maxcount = PY_SSIZE_T_MAX ;
@@ -9952,15 +9980,16 @@ replace(PyObject *self, PyObject *str1,
99529980
99539981 if (str1 == str2 )
99549982 goto nothing ;
9955- if (skind < kind1 )
9956- /* substring too wide to be present */
9957- goto nothing ;
99589983
99599984 maxchar = PyUnicode_MAX_CHAR_VALUE (self );
9985+ maxchar_str1 = PyUnicode_MAX_CHAR_VALUE (str1 );
9986+ if (maxchar < maxchar_str1 )
9987+ /* substring too wide to be present */
9988+ goto nothing ;
99609989 maxchar_str2 = PyUnicode_MAX_CHAR_VALUE (str2 );
99619990 /* Replacing str1 with str2 may cause a maxchar reduction in the
99629991 result string. */
9963- mayshrink = (maxchar_str2 < maxchar );
9992+ mayshrink = (maxchar_str2 < maxchar_str1 ) && ( maxchar == maxchar_str1 );
99649993 maxchar = MAX_MAXCHAR (maxchar , maxchar_str2 );
99659994
99669995 if (len1 == len2 ) {
@@ -9970,36 +9999,19 @@ replace(PyObject *self, PyObject *str1,
99709999 if (len1 == 1 ) {
997110000 /* replace characters */
997210001 Py_UCS4 u1 , u2 ;
9973- int rkind ;
9974- Py_ssize_t index , pos ;
9975- char * src , * rbuf ;
10002+ Py_ssize_t pos ;
997610003
997710004 u1 = PyUnicode_READ (kind1 , buf1 , 0 );
9978- pos = findchar (sbuf , PyUnicode_KIND ( self ) , slen , u1 , 1 );
10005+ pos = findchar (sbuf , skind , slen , u1 , 1 );
997910006 if (pos < 0 )
998010007 goto nothing ;
998110008 u2 = PyUnicode_READ (kind2 , buf2 , 0 );
998210009 u = PyUnicode_New (slen , maxchar );
998310010 if (!u )
998410011 goto error ;
9985- _PyUnicode_FastCopyCharacters (u , 0 , self , 0 , slen );
9986- rkind = PyUnicode_KIND (u );
9987- rbuf = PyUnicode_DATA (u );
998810012
9989- PyUnicode_WRITE (rkind , rbuf , pos , u2 );
9990- index = 0 ;
9991- src = sbuf ;
9992- while (-- maxcount )
9993- {
9994- pos ++ ;
9995- src += pos * PyUnicode_KIND (self );
9996- slen -= pos ;
9997- index += pos ;
9998- pos = findchar (src , PyUnicode_KIND (self ), slen , u1 , 1 );
9999- if (pos < 0 )
10000- break ;
10001- PyUnicode_WRITE (rkind , rbuf , index + pos , u2 );
10002- }
10013+ _PyUnicode_FastCopyCharacters (u , 0 , self , 0 , slen );
10014+ replace_1char_inplace (u , pos , u1 , u2 , maxcount );
1000310015 }
1000410016 else {
1000510017 int rkind = skind ;
0 commit comments