src/string.c

changeset 1137
61939929030a
parent 1136
d9ff0f091f28
equal deleted inserted replaced
1136:d9ff0f091f28 1137:61939929030a
618 struct cx_strreplace_ibuf *next; 618 struct cx_strreplace_ibuf *next;
619 unsigned int len; 619 unsigned int len;
620 }; 620 };
621 621
622 static void cx_strrepl_free_ibuf(struct cx_strreplace_ibuf *buf) { 622 static void cx_strrepl_free_ibuf(struct cx_strreplace_ibuf *buf) {
623 // remember, the first data is on the stack!
624 buf = buf->next;
623 while (buf) { 625 while (buf) {
624 struct cx_strreplace_ibuf *next = buf->next; 626 struct cx_strreplace_ibuf *next = buf->next;
625 free(buf->buf); 627 free(buf->buf);
626 free(buf); 628 free(buf);
627 buf = next; 629 buf = next;
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
735 734
736 // Result is guaranteed to be zero-terminated 735 // Result is guaranteed to be zero-terminated
737 result.ptr[result.length] = '\0'; 736 result.ptr[result.length] = '\0';
738 737
739 // Free index buffer 738 // Free index buffer
740 cx_strrepl_free_ibuf(firstbuf); 739 cx_strrepl_free_ibuf(&ibuf);
741 740
742 return result; 741 return result;
743 } 742 }
744 743
745 CxStrtokCtx cx_strtok_( 744 CxStrtokCtx cx_strtok_(

mercurial