644 size_t ibuflen = replmax < ibufmax ? replmax : ibufmax; |
646 size_t ibuflen = replmax < ibufmax ? replmax : ibufmax; |
645 if (ibuflen > CX_STRREPLACE_INDEX_BUFFER_SIZE) { |
647 if (ibuflen > CX_STRREPLACE_INDEX_BUFFER_SIZE) { |
646 ibuflen = CX_STRREPLACE_INDEX_BUFFER_SIZE; |
648 ibuflen = CX_STRREPLACE_INDEX_BUFFER_SIZE; |
647 } |
649 } |
648 |
650 |
649 // Allocate first index buffer |
651 // First index buffer can be on the stack |
650 struct cx_strreplace_ibuf *firstbuf, *curbuf; |
652 struct cx_strreplace_ibuf ibuf, *curbuf = &ibuf; |
651 firstbuf = curbuf = calloc(1, sizeof(struct cx_strreplace_ibuf)); |
653 size_t ibuf_sbo[CX_STRREPLACE_INDEX_BUFFER_SIZE]; |
652 if (!firstbuf) return cx_mutstrn(NULL, 0); |
654 ibuf.buf = ibuf_sbo; |
653 firstbuf->buf = calloc(ibuflen, sizeof(size_t)); |
655 ibuf.next = NULL; |
654 if (!firstbuf->buf) { |
656 ibuf.len = 0; |
655 free(firstbuf); |
|
656 return cx_mutstrn(NULL, 0); |
|
657 } |
|
658 |
657 |
659 // Search occurrences |
658 // Search occurrences |
660 cxstring searchstr = str; |
659 cxstring searchstr = str; |
661 size_t found = 0; |
660 size_t found = 0; |
662 do { |
661 do { |
665 // Allocate next buffer in chain, if required |
664 // Allocate next buffer in chain, if required |
666 if (curbuf->len == ibuflen) { |
665 if (curbuf->len == ibuflen) { |
667 struct cx_strreplace_ibuf *nextbuf = |
666 struct cx_strreplace_ibuf *nextbuf = |
668 calloc(1, sizeof(struct cx_strreplace_ibuf)); |
667 calloc(1, sizeof(struct cx_strreplace_ibuf)); |
669 if (!nextbuf) { |
668 if (!nextbuf) { |
670 cx_strrepl_free_ibuf(firstbuf); |
669 cx_strrepl_free_ibuf(&ibuf); |
671 return cx_mutstrn(NULL, 0); |
670 return cx_mutstrn(NULL, 0); |
672 } |
671 } |
673 nextbuf->buf = calloc(ibuflen, sizeof(size_t)); |
672 nextbuf->buf = calloc(ibuflen, sizeof(size_t)); |
674 if (!nextbuf->buf) { |
673 if (!nextbuf->buf) { |
675 free(nextbuf); |
674 free(nextbuf); |
676 cx_strrepl_free_ibuf(firstbuf); |
675 cx_strrepl_free_ibuf(&ibuf); |
677 return cx_mutstrn(NULL, 0); |
676 return cx_mutstrn(NULL, 0); |
678 } |
677 } |
679 curbuf->next = nextbuf; |
678 curbuf->next = nextbuf; |
680 curbuf = nextbuf; |
679 curbuf = nextbuf; |
681 } |
680 } |
694 // Allocate result string |
693 // Allocate result string |
695 cxmutstr result; |
694 cxmutstr result; |
696 { |
695 { |
697 ssize_t adjlen = (ssize_t) replacement.length - (ssize_t) pattern.length; |
696 ssize_t adjlen = (ssize_t) replacement.length - (ssize_t) pattern.length; |
698 size_t rcount = 0; |
697 size_t rcount = 0; |
699 curbuf = firstbuf; |
698 curbuf = &ibuf; |
700 do { |
699 do { |
701 rcount += curbuf->len; |
700 rcount += curbuf->len; |
702 curbuf = curbuf->next; |
701 curbuf = curbuf->next; |
703 } while (curbuf); |
702 } while (curbuf); |
704 result.length = str.length + rcount * adjlen; |
703 result.length = str.length + rcount * adjlen; |
705 result.ptr = cxMalloc(allocator, result.length + 1); |
704 result.ptr = cxMalloc(allocator, result.length + 1); |
706 if (!result.ptr) { |
705 if (!result.ptr) { |
707 cx_strrepl_free_ibuf(firstbuf); |
706 cx_strrepl_free_ibuf(&ibuf); |
708 return cx_mutstrn(NULL, 0); |
707 return cx_mutstrn(NULL, 0); |
709 } |
708 } |
710 } |
709 } |
711 |
710 |
712 // Build result string |
711 // Build result string |
713 curbuf = firstbuf; |
712 curbuf = &ibuf; |
714 size_t srcidx = 0; |
713 size_t srcidx = 0; |
715 char *destptr = result.ptr; |
714 char *destptr = result.ptr; |
716 do { |
715 do { |
717 for (size_t i = 0; i < curbuf->len; i++) { |
716 for (size_t i = 0; i < curbuf->len; i++) { |
718 // Copy source part up to next match |
717 // Copy source part up to next match |