672 cx_strrepl_free_ibuf(firstbuf); |
672 cx_strrepl_free_ibuf(firstbuf); |
673 |
673 |
674 return result; |
674 return result; |
675 } |
675 } |
676 |
676 |
677 |
677 CxStrtokCtx cx_strtok( |
|
678 cxstring str, |
|
679 cxstring delim, |
|
680 size_t limit |
|
681 ) { |
|
682 CxStrtokCtx ctx; |
|
683 ctx.str = str; |
|
684 ctx.delim = delim; |
|
685 ctx.limit = limit; |
|
686 ctx.pos = 0; |
|
687 ctx.next_pos = 0; |
|
688 ctx.delim_pos = 0; |
|
689 ctx.found = 0; |
|
690 ctx.delim_more = NULL; |
|
691 ctx.delim_more_count = 0; |
|
692 return ctx; |
|
693 } |
|
694 |
|
695 CxStrtokCtx cx_strtok_m( |
|
696 cxmutstr str, |
|
697 cxstring delim, |
|
698 size_t limit |
|
699 ) { |
|
700 return cx_strtok(cx_strcast(str), delim, limit); |
|
701 } |
|
702 |
|
703 bool cx_strtok_next( |
|
704 CxStrtokCtx *ctx, |
|
705 cxstring *token |
|
706 ) { |
|
707 // abortion criteria |
|
708 if (ctx->found >= ctx->limit || ctx->delim_pos >= ctx->str.length) { |
|
709 return false; |
|
710 } |
|
711 |
|
712 // determine the search start |
|
713 cxstring haystack = cx_strsubs(ctx->str, ctx->next_pos); |
|
714 |
|
715 // search the next delimiter |
|
716 cxstring delim = cx_strstr(haystack, ctx->delim); |
|
717 |
|
718 // if found, make delim capture exactly the delimiter |
|
719 if (delim.length > 0) { |
|
720 delim.length = ctx->delim.length; |
|
721 } |
|
722 |
|
723 // if more delimiters are specified, check them now |
|
724 if (ctx->delim_more_count > 0) { |
|
725 cx_for_n(i, ctx->delim_more_count) { |
|
726 cxstring d = cx_strstr(haystack, ctx->delim_more[i]); |
|
727 if (d.length > 0 && (delim.length == 0 || d.ptr < delim.ptr)) { |
|
728 delim.ptr = d.ptr; |
|
729 delim.length = ctx->delim_more[i].length; |
|
730 } |
|
731 } |
|
732 } |
|
733 |
|
734 // store the token information and adjust the context |
|
735 ctx->found++; |
|
736 ctx->pos = ctx->next_pos; |
|
737 token->ptr = &ctx->str.ptr[ctx->pos]; |
|
738 ctx->delim_pos = delim.length == 0 ? |
|
739 ctx->str.length : (size_t) (delim.ptr - ctx->str.ptr); |
|
740 token->length = ctx->delim_pos - ctx->pos; |
|
741 ctx->next_pos = ctx->delim_pos + delim.length; |
|
742 |
|
743 return true; |
|
744 } |
|
745 |
|
746 bool cx_strtok_next_m( |
|
747 CxStrtokCtx *ctx, |
|
748 cxmutstr *token |
|
749 ) { |
|
750 return cx_strtok_next(ctx, (cxstring *) token); |
|
751 } |
|
752 |
|
753 void cx_strtok_delim( |
|
754 CxStrtokCtx *ctx, |
|
755 cxstring const *delim, |
|
756 size_t count |
|
757 ) { |
|
758 ctx->delim_more = delim; |
|
759 ctx->delim_more_count = count; |
|
760 } |