| 610 } | 610 } | 
| 611 | 611 | 
| 612 cxmutstr cx_strreplacen_a( | 612 cxmutstr cx_strreplacen_a( | 
| 613         const CxAllocator *allocator, | 613         const CxAllocator *allocator, | 
| 614         cxstring str, | 614         cxstring str, | 
| 615         cxstring pattern, | 615         cxstring search, | 
| 616         cxstring replacement, | 616         cxstring replacement, | 
| 617         size_t replmax | 617         size_t replmax | 
| 618 ) { | 618 ) { | 
| 619 | 619 | 
| 620     if (pattern.length == 0 || pattern.length > str.length || replmax == 0) | 620     if (search.length == 0 || search.length > str.length || replmax == 0) | 
| 621         return cx_strdup_a(allocator, str); | 621         return cx_strdup_a(allocator, str); | 
| 622 | 622 | 
| 623     // Compute expected buffer length | 623     // Compute expected buffer length | 
| 624     size_t ibufmax = str.length / pattern.length; | 624     size_t ibufmax = str.length / search.length; | 
| 625     size_t ibuflen = replmax < ibufmax ? replmax : ibufmax; | 625     size_t ibuflen = replmax < ibufmax ? replmax : ibufmax; | 
| 626     if (ibuflen > CX_STRREPLACE_INDEX_BUFFER_SIZE) { | 626     if (ibuflen > CX_STRREPLACE_INDEX_BUFFER_SIZE) { | 
| 627         ibuflen = CX_STRREPLACE_INDEX_BUFFER_SIZE; | 627         ibuflen = CX_STRREPLACE_INDEX_BUFFER_SIZE; | 
| 628     } | 628     } | 
| 629 | 629 | 
| 636 | 636 | 
| 637     // Search occurrences | 637     // Search occurrences | 
| 638     cxstring searchstr = str; | 638     cxstring searchstr = str; | 
| 639     size_t found = 0; | 639     size_t found = 0; | 
| 640     do { | 640     do { | 
| 641         cxstring match = cx_strstr(searchstr, pattern); | 641         cxstring match = cx_strstr(searchstr, search); | 
| 642         if (match.length > 0) { | 642         if (match.length > 0) { | 
| 643             // Allocate next buffer in chain, if required | 643             // Allocate next buffer in chain, if required | 
| 644             if (curbuf->len == ibuflen) { | 644             if (curbuf->len == ibuflen) { | 
| 645                 struct cx_strreplace_ibuf *nextbuf = | 645                 struct cx_strreplace_ibuf *nextbuf = | 
| 646                         calloc(1, sizeof(struct cx_strreplace_ibuf)); | 646                         calloc(1, sizeof(struct cx_strreplace_ibuf)); | 
| 660 | 660 | 
| 661             // Record match index | 661             // Record match index | 
| 662             found++; | 662             found++; | 
| 663             size_t idx = match.ptr - str.ptr; | 663             size_t idx = match.ptr - str.ptr; | 
| 664             curbuf->buf[curbuf->len++] = idx; | 664             curbuf->buf[curbuf->len++] = idx; | 
| 665             searchstr.ptr = match.ptr + pattern.length; | 665             searchstr.ptr = match.ptr + search.length; | 
| 666             searchstr.length = str.length - idx - pattern.length; | 666             searchstr.length = str.length - idx - search.length; | 
| 667         } else { | 667         } else { | 
| 668             break; | 668             break; | 
| 669         } | 669         } | 
| 670     } while (searchstr.length > 0 && found < replmax); | 670     } while (searchstr.length > 0 && found < replmax); | 
| 671 | 671 | 
| 672     // Allocate result string | 672     // Allocate result string | 
| 673     cxmutstr result; | 673     cxmutstr result; | 
| 674     { | 674     { | 
| 675         long long adjlen = (long long) replacement.length - (long long) pattern.length; | 675         long long adjlen = (long long) replacement.length - (long long) search.length; | 
| 676         size_t rcount = 0; | 676         size_t rcount = 0; | 
| 677         curbuf = &ibuf; | 677         curbuf = &ibuf; | 
| 678         do { | 678         do { | 
| 679             rcount += curbuf->len; | 679             rcount += curbuf->len; | 
| 680             curbuf = curbuf->next; | 680             curbuf = curbuf->next; | 
| 701                 destptr += srclen; | 701                 destptr += srclen; | 
| 702                 srcidx += srclen; | 702                 srcidx += srclen; | 
| 703             } | 703             } | 
| 704 | 704 | 
| 705             // Copy the replacement and skip the source pattern | 705             // Copy the replacement and skip the source pattern | 
| 706             srcidx += pattern.length; | 706             srcidx += search.length; | 
| 707             memcpy(destptr, replacement.ptr, replacement.length); | 707             memcpy(destptr, replacement.ptr, replacement.length); | 
| 708             destptr += replacement.length; | 708             destptr += replacement.length; | 
| 709         } | 709         } | 
| 710         curbuf = curbuf->next; | 710         curbuf = curbuf->next; | 
| 711     } while (curbuf); | 711     } while (curbuf); |