Line data Source code
1 : #if STRINGLIB_IS_UNICODE
2 : # error "transmogrify.h only compatible with byte-wise strings"
3 : #endif
4 :
5 : /* the more complicated methods. parts of these should be pulled out into the
6 : shared code in bytes_methods.c to cut down on duplicate code bloat. */
7 :
8 : /*[clinic input]
9 : class B "PyObject *" "&PyType_Type"
10 : [clinic start generated code]*/
11 : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=2935558188d97c76]*/
12 :
13 : #include "clinic/transmogrify.h.h"
14 :
15 : static inline PyObject *
16 160398 : return_self(PyObject *self)
17 : {
18 : #if !STRINGLIB_MUTABLE
19 99413 : if (STRINGLIB_CHECK_EXACT(self)) {
20 99367 : Py_INCREF(self);
21 99367 : return self;
22 : }
23 : #endif
24 61031 : return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
25 : }
26 :
27 : /*[clinic input]
28 : B.expandtabs as stringlib_expandtabs
29 :
30 : tabsize: int = 8
31 :
32 : Return a copy where all tab characters are expanded using spaces.
33 :
34 : If tabsize is not given, a tab size of 8 characters is assumed.
35 : [clinic start generated code]*/
36 :
37 : static PyObject *
38 24 : stringlib_expandtabs_impl(PyObject *self, int tabsize)
39 : /*[clinic end generated code: output=069cb7fae72e4c2b input=3c6d3b12aa3ccbea]*/
40 : {
41 : const char *e, *p;
42 : char *q;
43 : Py_ssize_t i, j;
44 : PyObject *u;
45 :
46 : /* First pass: determine size of output string */
47 24 : i = j = 0;
48 24 : e = STRINGLIB_STR(self) + STRINGLIB_LEN(self);
49 20900 : for (p = STRINGLIB_STR(self); p < e; p++) {
50 20876 : if (*p == '\t') {
51 1322 : if (tabsize > 0) {
52 1322 : Py_ssize_t incr = tabsize - (j % tabsize);
53 1322 : if (j > PY_SSIZE_T_MAX - incr)
54 0 : goto overflow;
55 1322 : j += incr;
56 : }
57 : }
58 : else {
59 19554 : if (j > PY_SSIZE_T_MAX - 1)
60 0 : goto overflow;
61 19554 : j++;
62 19554 : if (*p == '\n' || *p == '\r') {
63 54 : if (i > PY_SSIZE_T_MAX - j)
64 0 : goto overflow;
65 54 : i += j;
66 54 : j = 0;
67 : }
68 : }
69 : }
70 :
71 24 : if (i > PY_SSIZE_T_MAX - j)
72 0 : goto overflow;
73 :
74 : /* Second pass: create output string and fill it */
75 24 : u = STRINGLIB_NEW(NULL, i + j);
76 24 : if (!u)
77 0 : return NULL;
78 :
79 24 : j = 0;
80 24 : q = STRINGLIB_STR(u);
81 :
82 20900 : for (p = STRINGLIB_STR(self); p < e; p++) {
83 20876 : if (*p == '\t') {
84 1322 : if (tabsize > 0) {
85 1322 : i = tabsize - (j % tabsize);
86 1322 : j += i;
87 2772 : while (i--)
88 1450 : *q++ = ' ';
89 : }
90 : }
91 : else {
92 19554 : j++;
93 19554 : *q++ = *p;
94 19554 : if (*p == '\n' || *p == '\r')
95 54 : j = 0;
96 : }
97 : }
98 :
99 24 : return u;
100 0 : overflow:
101 0 : PyErr_SetString(PyExc_OverflowError, "result too long");
102 0 : return NULL;
103 : }
104 :
105 : static inline PyObject *
106 114 : pad(PyObject *self, Py_ssize_t left, Py_ssize_t right, char fill)
107 : {
108 : PyObject *u;
109 :
110 114 : if (left < 0)
111 0 : left = 0;
112 114 : if (right < 0)
113 0 : right = 0;
114 :
115 114 : if (left == 0 && right == 0) {
116 0 : return return_self(self);
117 : }
118 :
119 114 : u = STRINGLIB_NEW(NULL, left + STRINGLIB_LEN(self) + right);
120 114 : if (u) {
121 114 : if (left)
122 52 : memset(STRINGLIB_STR(u), fill, left);
123 114 : memcpy(STRINGLIB_STR(u) + left,
124 114 : STRINGLIB_STR(self),
125 114 : STRINGLIB_LEN(self));
126 114 : if (right)
127 74 : memset(STRINGLIB_STR(u) + left + STRINGLIB_LEN(self),
128 : fill, right);
129 : }
130 :
131 114 : return u;
132 : }
133 :
134 : /*[clinic input]
135 : B.ljust as stringlib_ljust
136 :
137 : width: Py_ssize_t
138 : fillchar: char = b' '
139 : /
140 :
141 : Return a left-justified string of length width.
142 :
143 : Padding is done using the specified fill character.
144 : [clinic start generated code]*/
145 :
146 : static PyObject *
147 69 : stringlib_ljust_impl(PyObject *self, Py_ssize_t width, char fillchar)
148 : /*[clinic end generated code: output=c79ca173c5ff8337 input=eff2d014bc7d80df]*/
149 : {
150 69 : if (STRINGLIB_LEN(self) >= width) {
151 7 : return return_self(self);
152 : }
153 :
154 62 : return pad(self, 0, width - STRINGLIB_LEN(self), fillchar);
155 : }
156 :
157 :
158 : /*[clinic input]
159 : B.rjust as stringlib_rjust
160 :
161 : width: Py_ssize_t
162 : fillchar: char = b' '
163 : /
164 :
165 : Return a right-justified string of length width.
166 :
167 : Padding is done using the specified fill character.
168 : [clinic start generated code]*/
169 :
170 : static PyObject *
171 47 : stringlib_rjust_impl(PyObject *self, Py_ssize_t width, char fillchar)
172 : /*[clinic end generated code: output=7df5d728a5439570 input=218b0bd31308955d]*/
173 : {
174 47 : if (STRINGLIB_LEN(self) >= width) {
175 19 : return return_self(self);
176 : }
177 :
178 28 : return pad(self, width - STRINGLIB_LEN(self), 0, fillchar);
179 : }
180 :
181 :
182 : /*[clinic input]
183 : B.center as stringlib_center
184 :
185 : width: Py_ssize_t
186 : fillchar: char = b' '
187 : /
188 :
189 : Return a centered string of length width.
190 :
191 : Padding is done using the specified fill character.
192 : [clinic start generated code]*/
193 :
194 : static PyObject *
195 19 : stringlib_center_impl(PyObject *self, Py_ssize_t width, char fillchar)
196 : /*[clinic end generated code: output=d8da2e055288b4c2 input=3776fd278765d89b]*/
197 : {
198 : Py_ssize_t marg, left;
199 :
200 19 : if (STRINGLIB_LEN(self) >= width) {
201 7 : return return_self(self);
202 : }
203 :
204 12 : marg = width - STRINGLIB_LEN(self);
205 12 : left = marg / 2 + (marg & width & 1);
206 :
207 12 : return pad(self, left, marg - left, fillchar);
208 : }
209 :
210 : /*[clinic input]
211 : B.zfill as stringlib_zfill
212 :
213 : width: Py_ssize_t
214 : /
215 :
216 : Pad a numeric string with zeros on the left, to fill a field of the given width.
217 :
218 : The original string is never truncated.
219 : [clinic start generated code]*/
220 :
221 : static PyObject *
222 34 : stringlib_zfill_impl(PyObject *self, Py_ssize_t width)
223 : /*[clinic end generated code: output=0b3c684a7f1b2319 input=2da6d7b8e9bcb19a]*/
224 : {
225 : Py_ssize_t fill;
226 : PyObject *s;
227 : char *p;
228 :
229 34 : if (STRINGLIB_LEN(self) >= width) {
230 22 : return return_self(self);
231 : }
232 :
233 12 : fill = width - STRINGLIB_LEN(self);
234 :
235 12 : s = pad(self, fill, 0, '0');
236 :
237 12 : if (s == NULL)
238 0 : return NULL;
239 :
240 12 : p = STRINGLIB_STR(s);
241 12 : if (p[fill] == '+' || p[fill] == '-') {
242 : /* move sign to beginning of string */
243 6 : p[0] = p[fill];
244 6 : p[fill] = '0';
245 : }
246 :
247 12 : return s;
248 : }
249 :
250 :
251 : /* find and count characters and substrings */
252 :
253 : #define findchar(target, target_len, c) \
254 : ((char *)memchr((const void *)(target), c, target_len))
255 :
256 :
257 : static Py_ssize_t
258 1439 : countchar(const char *target, Py_ssize_t target_len, char c,
259 : Py_ssize_t maxcount)
260 : {
261 1439 : Py_ssize_t count = 0;
262 1439 : const char *start = target;
263 1439 : const char *end = target + target_len;
264 :
265 7031 : while ((start = findchar(start, end - start, c)) != NULL) {
266 5612 : count++;
267 5612 : if (count >= maxcount)
268 20 : break;
269 5592 : start += 1;
270 : }
271 1439 : return count;
272 : }
273 :
274 :
275 : /* Algorithms for different cases of string replacement */
276 :
277 : /* len(self)>=1, from="", len(to)>=1, maxcount>=1 */
278 : static PyObject *
279 28 : stringlib_replace_interleave(PyObject *self,
280 : const char *to_s, Py_ssize_t to_len,
281 : Py_ssize_t maxcount)
282 : {
283 : const char *self_s;
284 : char *result_s;
285 : Py_ssize_t self_len, result_len;
286 : Py_ssize_t count, i;
287 : PyObject *result;
288 :
289 28 : self_len = STRINGLIB_LEN(self);
290 :
291 : /* 1 at the end plus 1 after every character;
292 : count = min(maxcount, self_len + 1) */
293 28 : if (maxcount <= self_len) {
294 6 : count = maxcount;
295 : }
296 : else {
297 : /* Can't overflow: self_len + 1 <= maxcount <= PY_SSIZE_T_MAX. */
298 22 : count = self_len + 1;
299 : }
300 :
301 : /* Check for overflow */
302 : /* result_len = count * to_len + self_len; */
303 28 : assert(count > 0);
304 28 : if (to_len > (PY_SSIZE_T_MAX - self_len) / count) {
305 0 : PyErr_SetString(PyExc_OverflowError,
306 : "replace bytes is too long");
307 0 : return NULL;
308 : }
309 28 : result_len = count * to_len + self_len;
310 28 : result = STRINGLIB_NEW(NULL, result_len);
311 28 : if (result == NULL) {
312 0 : return NULL;
313 : }
314 :
315 28 : self_s = STRINGLIB_STR(self);
316 28 : result_s = STRINGLIB_STR(result);
317 :
318 28 : if (to_len > 1) {
319 : /* Lay the first one down (guaranteed this will occur) */
320 18 : memcpy(result_s, to_s, to_len);
321 18 : result_s += to_len;
322 18 : count -= 1;
323 :
324 44 : for (i = 0; i < count; i++) {
325 26 : *result_s++ = *self_s++;
326 26 : memcpy(result_s, to_s, to_len);
327 26 : result_s += to_len;
328 : }
329 : }
330 : else {
331 10 : result_s[0] = to_s[0];
332 10 : result_s += to_len;
333 10 : count -= 1;
334 22 : for (i = 0; i < count; i++) {
335 12 : *result_s++ = *self_s++;
336 12 : result_s[0] = to_s[0];
337 12 : result_s += to_len;
338 : }
339 : }
340 :
341 : /* Copy the rest of the original string */
342 28 : memcpy(result_s, self_s, self_len - i);
343 :
344 28 : return result;
345 : }
346 :
347 : /* Special case for deleting a single character */
348 : /* len(self)>=1, len(from)==1, to="", maxcount>=1 */
349 : static PyObject *
350 1254 : stringlib_replace_delete_single_character(PyObject *self,
351 : char from_c, Py_ssize_t maxcount)
352 : {
353 : const char *self_s, *start, *next, *end;
354 : char *result_s;
355 : Py_ssize_t self_len, result_len;
356 : Py_ssize_t count;
357 : PyObject *result;
358 :
359 1254 : self_len = STRINGLIB_LEN(self);
360 1254 : self_s = STRINGLIB_STR(self);
361 :
362 1254 : count = countchar(self_s, self_len, from_c, maxcount);
363 1254 : if (count == 0) {
364 45 : return return_self(self);
365 : }
366 :
367 1209 : result_len = self_len - count; /* from_len == 1 */
368 1209 : assert(result_len>=0);
369 :
370 1209 : result = STRINGLIB_NEW(NULL, result_len);
371 1209 : if (result == NULL) {
372 0 : return NULL;
373 : }
374 1209 : result_s = STRINGLIB_STR(result);
375 :
376 1209 : start = self_s;
377 1209 : end = self_s + self_len;
378 6610 : while (count-- > 0) {
379 5401 : next = findchar(start, end - start, from_c);
380 5401 : if (next == NULL)
381 0 : break;
382 5401 : memcpy(result_s, start, next - start);
383 5401 : result_s += (next - start);
384 5401 : start = next + 1;
385 : }
386 1209 : memcpy(result_s, start, end - start);
387 :
388 1209 : return result;
389 : }
390 :
391 : /* len(self)>=1, len(from)>=2, to="", maxcount>=1 */
392 :
393 : static PyObject *
394 85429 : stringlib_replace_delete_substring(PyObject *self,
395 : const char *from_s, Py_ssize_t from_len,
396 : Py_ssize_t maxcount)
397 : {
398 : const char *self_s, *start, *next, *end;
399 : char *result_s;
400 : Py_ssize_t self_len, result_len;
401 : Py_ssize_t count, offset;
402 : PyObject *result;
403 :
404 85429 : self_len = STRINGLIB_LEN(self);
405 85429 : self_s = STRINGLIB_STR(self);
406 :
407 85429 : count = stringlib_count(self_s, self_len,
408 : from_s, from_len,
409 : maxcount);
410 :
411 85429 : if (count == 0) {
412 : /* no matches */
413 78671 : return return_self(self);
414 : }
415 :
416 6758 : result_len = self_len - (count * from_len);
417 6758 : assert (result_len>=0);
418 :
419 6758 : result = STRINGLIB_NEW(NULL, result_len);
420 6758 : if (result == NULL) {
421 0 : return NULL;
422 : }
423 6758 : result_s = STRINGLIB_STR(result);
424 :
425 6758 : start = self_s;
426 6758 : end = self_s + self_len;
427 14298 : while (count-- > 0) {
428 7540 : offset = stringlib_find(start, end - start,
429 : from_s, from_len,
430 : 0);
431 7540 : if (offset == -1)
432 0 : break;
433 7540 : next = start + offset;
434 :
435 7540 : memcpy(result_s, start, next - start);
436 :
437 7540 : result_s += (next - start);
438 7540 : start = next + from_len;
439 : }
440 6758 : memcpy(result_s, start, end - start);
441 6758 : return result;
442 : }
443 :
444 : /* len(self)>=1, len(from)==len(to)==1, maxcount>=1 */
445 : static PyObject *
446 38433 : stringlib_replace_single_character_in_place(PyObject *self,
447 : char from_c, char to_c,
448 : Py_ssize_t maxcount)
449 : {
450 : const char *self_s, *end;
451 : char *result_s, *start, *next;
452 : Py_ssize_t self_len;
453 : PyObject *result;
454 :
455 : /* The result string will be the same size */
456 38433 : self_s = STRINGLIB_STR(self);
457 38433 : self_len = STRINGLIB_LEN(self);
458 :
459 38433 : next = findchar(self_s, self_len, from_c);
460 :
461 38433 : if (next == NULL) {
462 : /* No matches; return the original bytes */
463 33919 : return return_self(self);
464 : }
465 :
466 : /* Need to make a new bytes */
467 4514 : result = STRINGLIB_NEW(NULL, self_len);
468 4514 : if (result == NULL) {
469 0 : return NULL;
470 : }
471 4514 : result_s = STRINGLIB_STR(result);
472 4514 : memcpy(result_s, self_s, self_len);
473 :
474 : /* change everything in-place, starting with this one */
475 4514 : start = result_s + (next - self_s);
476 4514 : *start = to_c;
477 4514 : start++;
478 4514 : end = result_s + self_len;
479 :
480 36808 : while (--maxcount > 0) {
481 36796 : next = findchar(start, end - start, from_c);
482 36796 : if (next == NULL)
483 4502 : break;
484 32294 : *next = to_c;
485 32294 : start = next + 1;
486 : }
487 :
488 4514 : return result;
489 : }
490 :
491 : /* len(self)>=1, len(from)==len(to)>=2, maxcount>=1 */
492 : static PyObject *
493 41 : stringlib_replace_substring_in_place(PyObject *self,
494 : const char *from_s, Py_ssize_t from_len,
495 : const char *to_s, Py_ssize_t to_len,
496 : Py_ssize_t maxcount)
497 : {
498 : const char *self_s, *end;
499 : char *result_s, *start;
500 : Py_ssize_t self_len, offset;
501 : PyObject *result;
502 :
503 : /* The result bytes will be the same size */
504 :
505 41 : self_s = STRINGLIB_STR(self);
506 41 : self_len = STRINGLIB_LEN(self);
507 :
508 41 : offset = stringlib_find(self_s, self_len,
509 : from_s, from_len,
510 : 0);
511 41 : if (offset == -1) {
512 : /* No matches; return the original bytes */
513 6 : return return_self(self);
514 : }
515 :
516 : /* Need to make a new bytes */
517 35 : result = STRINGLIB_NEW(NULL, self_len);
518 35 : if (result == NULL) {
519 0 : return NULL;
520 : }
521 35 : result_s = STRINGLIB_STR(result);
522 35 : memcpy(result_s, self_s, self_len);
523 :
524 : /* change everything in-place, starting with this one */
525 35 : start = result_s + offset;
526 35 : memcpy(start, to_s, from_len);
527 35 : start += from_len;
528 35 : end = result_s + self_len;
529 :
530 77 : while ( --maxcount > 0) {
531 71 : offset = stringlib_find(start, end - start,
532 : from_s, from_len,
533 : 0);
534 71 : if (offset == -1)
535 29 : break;
536 42 : memcpy(start + offset, to_s, from_len);
537 42 : start += offset + from_len;
538 : }
539 :
540 35 : return result;
541 : }
542 :
543 : /* len(self)>=1, len(from)==1, len(to)>=2, maxcount>=1 */
544 : static PyObject *
545 185 : stringlib_replace_single_character(PyObject *self,
546 : char from_c,
547 : const char *to_s, Py_ssize_t to_len,
548 : Py_ssize_t maxcount)
549 : {
550 : const char *self_s, *start, *next, *end;
551 : char *result_s;
552 : Py_ssize_t self_len, result_len;
553 : Py_ssize_t count;
554 : PyObject *result;
555 :
556 185 : self_s = STRINGLIB_STR(self);
557 185 : self_len = STRINGLIB_LEN(self);
558 :
559 185 : count = countchar(self_s, self_len, from_c, maxcount);
560 185 : if (count == 0) {
561 : /* no matches, return unchanged */
562 5 : return return_self(self);
563 : }
564 :
565 : /* use the difference between current and new, hence the "-1" */
566 : /* result_len = self_len + count * (to_len-1) */
567 180 : assert(count > 0);
568 180 : if (to_len - 1 > (PY_SSIZE_T_MAX - self_len) / count) {
569 0 : PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");
570 0 : return NULL;
571 : }
572 180 : result_len = self_len + count * (to_len - 1);
573 :
574 180 : result = STRINGLIB_NEW(NULL, result_len);
575 180 : if (result == NULL) {
576 0 : return NULL;
577 : }
578 180 : result_s = STRINGLIB_STR(result);
579 :
580 180 : start = self_s;
581 180 : end = self_s + self_len;
582 391 : while (count-- > 0) {
583 211 : next = findchar(start, end - start, from_c);
584 211 : if (next == NULL)
585 0 : break;
586 :
587 211 : if (next == start) {
588 : /* replace with the 'to' */
589 28 : memcpy(result_s, to_s, to_len);
590 28 : result_s += to_len;
591 28 : start += 1;
592 : } else {
593 : /* copy the unchanged old then the 'to' */
594 183 : memcpy(result_s, start, next - start);
595 183 : result_s += (next - start);
596 183 : memcpy(result_s, to_s, to_len);
597 183 : result_s += to_len;
598 183 : start = next + 1;
599 : }
600 : }
601 : /* Copy the remainder of the remaining bytes */
602 180 : memcpy(result_s, start, end - start);
603 :
604 180 : return result;
605 : }
606 :
607 : /* len(self)>=1, len(from)>=2, len(to)>=2, maxcount>=1 */
608 : static PyObject *
609 4177 : stringlib_replace_substring(PyObject *self,
610 : const char *from_s, Py_ssize_t from_len,
611 : const char *to_s, Py_ssize_t to_len,
612 : Py_ssize_t maxcount)
613 : {
614 : const char *self_s, *start, *next, *end;
615 : char *result_s;
616 : Py_ssize_t self_len, result_len;
617 : Py_ssize_t count, offset;
618 : PyObject *result;
619 :
620 4177 : self_s = STRINGLIB_STR(self);
621 4177 : self_len = STRINGLIB_LEN(self);
622 :
623 4177 : count = stringlib_count(self_s, self_len,
624 : from_s, from_len,
625 : maxcount);
626 :
627 4177 : if (count == 0) {
628 : /* no matches, return unchanged */
629 4125 : return return_self(self);
630 : }
631 :
632 : /* Check for overflow */
633 : /* result_len = self_len + count * (to_len-from_len) */
634 52 : assert(count > 0);
635 52 : if (to_len - from_len > (PY_SSIZE_T_MAX - self_len) / count) {
636 0 : PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");
637 0 : return NULL;
638 : }
639 52 : result_len = self_len + count * (to_len - from_len);
640 :
641 52 : result = STRINGLIB_NEW(NULL, result_len);
642 52 : if (result == NULL) {
643 0 : return NULL;
644 : }
645 52 : result_s = STRINGLIB_STR(result);
646 :
647 52 : start = self_s;
648 52 : end = self_s + self_len;
649 337 : while (count-- > 0) {
650 285 : offset = stringlib_find(start, end - start,
651 : from_s, from_len,
652 : 0);
653 285 : if (offset == -1)
654 0 : break;
655 285 : next = start + offset;
656 285 : if (next == start) {
657 : /* replace with the 'to' */
658 65 : memcpy(result_s, to_s, to_len);
659 65 : result_s += to_len;
660 65 : start += from_len;
661 : } else {
662 : /* copy the unchanged old then the 'to' */
663 220 : memcpy(result_s, start, next - start);
664 220 : result_s += (next - start);
665 220 : memcpy(result_s, to_s, to_len);
666 220 : result_s += to_len;
667 220 : start = next + from_len;
668 : }
669 : }
670 : /* Copy the remainder of the remaining bytes */
671 52 : memcpy(result_s, start, end - start);
672 :
673 52 : return result;
674 : }
675 :
676 :
677 : static PyObject *
678 173119 : stringlib_replace(PyObject *self,
679 : const char *from_s, Py_ssize_t from_len,
680 : const char *to_s, Py_ssize_t to_len,
681 : Py_ssize_t maxcount)
682 : {
683 173119 : if (STRINGLIB_LEN(self) < from_len) {
684 : /* nothing to do; return the original bytes */
685 43521 : return return_self(self);
686 : }
687 129598 : if (maxcount < 0) {
688 129465 : maxcount = PY_SSIZE_T_MAX;
689 133 : } else if (maxcount == 0) {
690 : /* nothing to do; return the original bytes */
691 34 : return return_self(self);
692 : }
693 :
694 : /* Handle zero-length special cases */
695 129564 : if (from_len == 0) {
696 45 : if (to_len == 0) {
697 : /* nothing to do; return the original bytes */
698 17 : return return_self(self);
699 : }
700 : /* insert the 'to' bytes everywhere. */
701 : /* >>> b"Python".replace(b"", b".") */
702 : /* b'.P.y.t.h.o.n.' */
703 28 : return stringlib_replace_interleave(self, to_s, to_len, maxcount);
704 : }
705 :
706 129519 : if (to_len == 0) {
707 : /* delete all occurrences of 'from' bytes */
708 86683 : if (from_len == 1) {
709 1254 : return stringlib_replace_delete_single_character(
710 1254 : self, from_s[0], maxcount);
711 : } else {
712 85429 : return stringlib_replace_delete_substring(
713 : self, from_s, from_len, maxcount);
714 : }
715 : }
716 :
717 : /* Handle special case where both bytes have the same length */
718 :
719 42836 : if (from_len == to_len) {
720 38474 : if (from_len == 1) {
721 38433 : return stringlib_replace_single_character_in_place(
722 38433 : self, from_s[0], to_s[0], maxcount);
723 : } else {
724 41 : return stringlib_replace_substring_in_place(
725 : self, from_s, from_len, to_s, to_len, maxcount);
726 : }
727 : }
728 :
729 : /* Otherwise use the more generic algorithms */
730 4362 : if (from_len == 1) {
731 185 : return stringlib_replace_single_character(
732 185 : self, from_s[0], to_s, to_len, maxcount);
733 : } else {
734 : /* len('from')>=2, len('to')>=1 */
735 4177 : return stringlib_replace_substring(
736 : self, from_s, from_len, to_s, to_len, maxcount);
737 : }
738 : }
739 :
740 : #undef findchar
|