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
| 860 | * same function but for zero-terminated strings. |
| 861 | */ |
| 862 | sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count) { |
| 863 | int elements = 0, slots = 5; |
| 864 | long start = 0, j; |
| 865 | sds *tokens; |
| 866 | |
| 867 | if (seplen < 1 || len < 0) return NULL; |
| 868 | |
| 869 | tokens = s_malloc(sizeof(sds)*slots); |
| 870 | if (tokens == NULL) return NULL; |
| 871 | |
| 872 | if (len == 0) { |
| 873 | *count = 0; |
| 874 | return tokens; |
| 875 | } |
| 876 | for (j = 0; j < (len-(seplen-1)); j++) { |
| 877 | /* make sure there is room for the next element and the final one */ |
| 878 | if (slots < elements+2) { |
| 879 | sds *newtokens; |
| 880 | |
| 881 | slots *= 2; |
| 882 | newtokens = s_realloc(tokens,sizeof(sds)*slots); |
| 883 | if (newtokens == NULL) goto cleanup; |
| 884 | tokens = newtokens; |
| 885 | } |
| 886 | /* search the separator */ |
| 887 | if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) { |
| 888 | tokens[elements] = sdsnewlen(s+start,j-start); |
| 889 | if (tokens[elements] == NULL) goto cleanup; |
| 890 | elements++; |
| 891 | start = j+seplen; |
| 892 | j = j+seplen-1; /* skip the separator */ |
| 893 | } |
| 894 | } |
| 895 | /* Add the final element. We are sure there is room in the tokens array. */ |
| 896 | tokens[elements] = sdsnewlen(s+start,len-start); |
| 897 | if (tokens[elements] == NULL) goto cleanup; |
| 898 | elements++; |
| 899 | *count = elements; |
| 900 | return tokens; |
| 901 | |
| 902 | cleanup: |
| 903 | { |
| 904 | int i; |
| 905 | for (i = 0; i < elements; i++) sdsfree(tokens[i]); |
| 906 | s_free(tokens); |
| 907 | *count = 0; |
| 908 | return NULL; |
| 909 | } |
| 910 | } |
| 911 | |
| 912 | /* Free the result returned by sdssplitlen(), or do nothing if 'tokens' is NULL. */ |
| 913 | void sdsfreesplitres(sds *tokens, int count) { |
no test coverage detected