Split 's' with separator in 'sep'. An array * of sds strings is returned. *count will be set * by reference to the number of tokens returned. * * On out of memory, zero length string, zero length * separator, NULL is returned. * * Note that 'sep' is able to split a string using * a multi-character separator. For example * sdssplit("foo_-_bar","_-_"); will return two * elements "foo" and
| 818 | * same function but for zero-terminated strings. |
| 819 | */ |
| 820 | sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count) { |
| 821 | int elements = 0, slots = 5; |
| 822 | long start = 0, j; |
| 823 | sds *tokens; |
| 824 | |
| 825 | if (seplen < 1 || len < 0) return NULL; |
| 826 | |
| 827 | tokens = s_malloc(sizeof(sds)*slots); |
| 828 | if (tokens == NULL) return NULL; |
| 829 | |
| 830 | if (len == 0) { |
| 831 | *count = 0; |
| 832 | return tokens; |
| 833 | } |
| 834 | for (j = 0; j < (len-(seplen-1)); j++) { |
| 835 | /* make sure there is room for the next element and the final one */ |
| 836 | if (slots < elements+2) { |
| 837 | sds *newtokens; |
| 838 | |
| 839 | slots *= 2; |
| 840 | newtokens = s_realloc(tokens,sizeof(sds)*slots); |
| 841 | if (newtokens == NULL) goto cleanup; |
| 842 | tokens = newtokens; |
| 843 | } |
| 844 | /* search the separator */ |
| 845 | if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) { |
| 846 | tokens[elements] = sdsnewlen(s+start,j-start); |
| 847 | if (tokens[elements] == NULL) goto cleanup; |
| 848 | elements++; |
| 849 | start = j+seplen; |
| 850 | j = j+seplen-1; /* skip the separator */ |
| 851 | } |
| 852 | } |
| 853 | /* Add the final element. We are sure there is room in the tokens array. */ |
| 854 | tokens[elements] = sdsnewlen(s+start,len-start); |
| 855 | if (tokens[elements] == NULL) goto cleanup; |
| 856 | elements++; |
| 857 | *count = elements; |
| 858 | return tokens; |
| 859 | |
| 860 | cleanup: |
| 861 | { |
| 862 | int i; |
| 863 | for (i = 0; i < elements; i++) sdsfree(tokens[i]); |
| 864 | s_free(tokens); |
| 865 | *count = 0; |
| 866 | return NULL; |
| 867 | } |
| 868 | } |
| 869 | |
| 870 | /* Free the result returned by sdssplitlen(), or do nothing if 'tokens' is NULL. */ |
| 871 | void sdsfreesplitres(sds *tokens, int count) { |