SOL_API struct sol_vector sol_str_slice_split(const struct sol_str_slice slice, const char *delim, size_t maxsplit) { struct sol_vector v = SOL_VECTOR_INIT(struct sol_str_slice); const char *str = slice.data; ssize_t dlen; size_t len; if (!slice.len || !delim) return v; maxsplit = (maxsplit) ? : slice.len - 1; if (maxsplit == SIZE_MAX) //once we compare to maxsplit + 1 maxsplit--; dlen = strlen(delim); len = slice.len; #define CREATE_SLICE(_str, _len) \ do { \ s = sol_vector_append(&v); \ if (!s) \ goto err; \ s->data = _str; \ s->len = _len; \ } while (0) while (str && (v.len < maxsplit + 1)) { struct sol_str_slice *s; char *token = memmem(str, len, delim, dlen); if (!token) { CREATE_SLICE(str, len); break; } if (v.len == (uint16_t)maxsplit) CREATE_SLICE(str, len); else CREATE_SLICE(str, (size_t)(token - str)); len -= (token - str) + dlen; str = token + dlen; } #undef CREATE_SLICE return v; err: sol_vector_clear(&v); return v; }
struct sol_vector sol_util_str_split(const struct sol_str_slice slice, const char *delim, size_t maxsplit) { struct sol_vector v = SOL_VECTOR_INIT(struct sol_str_slice); ssize_t dlen, len; const char *str = slice.data; if (!slice.len || !delim) return v; maxsplit = (maxsplit) ? : slice.len; dlen = strlen(delim); len = slice.len; #define CREATE_SLICE(_str, _len) \ do { \ s = sol_vector_append(&v); \ if (!s) \ goto err; \ s->data = _str; \ s->len = _len; \ } while (0) while (str && (v.len < maxsplit)) { struct sol_str_slice *s; char *token = memmem(str, len, delim, dlen); if (!token) { CREATE_SLICE(str, len); break; } len -= (token - str) + dlen; CREATE_SLICE(str, token - str); str = token + dlen; } #undef CREATE_SLICE return v; err: sol_vector_clear(&v); return v; }
static struct sol_vector string_regexp_search_and_split(struct string_regexp_search_data *mdata) { int r; size_t str_len, match_sz; pcre *compiled_re = NULL; pcre_extra *p_extra = NULL; int *match_vector, sub_match_count = 0; struct sol_vector v = SOL_VECTOR_INIT(struct sol_str_slice); #define CREATE_SLICE(_str, _len) \ do { \ struct sol_str_slice *s; \ s = sol_vector_append(&v); \ if (!s) \ goto err; \ s->data = (const char *)_str; \ s->len = _len; \ } while (0) //mdata->string should never be NULL str_len = strlen(mdata->string); if (!str_len) return v; r = pcre_compile_do(mdata->node, mdata->regexp, &compiled_re, &p_extra, &sub_match_count); SOL_INT_CHECK(r, < 0, v); match_sz = (sub_match_count + 1) * 3; match_vector = calloc(match_sz, sizeof(*match_vector)); r = pcre_exec(compiled_re, p_extra, mdata->string, str_len, 0, 0, match_vector, match_sz); if (r < 0) { sol_flow_send_error_packet(mdata->node, EINVAL, "Fail on matching regular expression '%s' on string %s", mdata->regexp, mdata->string); goto err; } else { int i; /* The value returned by pcre_exec() is one more than the * highest numbered pair that has been set. If the vector is * too small to hold all the captured substring offsets, it is * used as far as possible (up to two-thirds of its length), * and the function returns a value of zero. */ if (r == 0) { // should not happen, but let's treat the case sol_flow_send_error_packet(mdata->node, EINVAL, "A memory overflow happened while executing" " regular expression '%s' on string %s", mdata->regexp, mdata->string); goto err; } for (i = 0; i < r; i++) { CREATE_SLICE(mdata->string + match_vector[i * 2], match_vector[i * 2 + 1] - match_vector[i * 2]); } } err: if (p_extra != NULL) pcre_free(p_extra); pcre_free(compiled_re); free(match_vector); return v; #undef CREATE_SLICE }