diff --git a/CHANGELOG.md b/CHANGELOG.md index 891782c6..1a29ff03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. ## Unreleased +- `string/` functions that take a pattern to search for will throw an error + when receiving the empty string. - Replace (start:end) style stacktrace source position information with line, column. This should be more readable for humans. Also, range information can be recovered by re-parsing source. diff --git a/src/core/string.c b/src/core/string.c index c02b2bc7..44f943e2 100644 --- a/src/core/string.c +++ b/src/core/string.c @@ -108,6 +108,9 @@ static void kmp_init( if (!lookup) { JANET_OUT_OF_MEMORY; } + if (patlen == 0) { + janet_panic("expected non-empty pattern"); + } s->lookup = lookup; s->i = 0; s->j = 0; @@ -378,15 +381,13 @@ static Janet cfun_string_split(int32_t argc, Janet *argv) { } findsetup(argc, argv, &state, 1); array = janet_array(0); - while ((result = kmp_next(&state)) >= 0 && limit--) { + while ((result = kmp_next(&state)) >= 0 && --limit) { const uint8_t *slice = janet_string(state.text + lastindex, result - lastindex); janet_array_push(array, janet_wrap_string(slice)); lastindex = result + state.patlen; } - { - const uint8_t *slice = janet_string(state.text + lastindex, state.textlen - lastindex); - janet_array_push(array, janet_wrap_string(slice)); - } + const uint8_t *slice = janet_string(state.text + lastindex, state.textlen - lastindex); + janet_array_push(array, janet_wrap_string(slice)); kmp_deinit(&state); return janet_wrap_array(array); } @@ -600,10 +601,12 @@ static const JanetReg string_cfuns[] = { }, { "string/split", cfun_string_split, - JDOC("(string/split delim str)\n\n" + JDOC("(string/split delim str &opt start limit)\n\n" "Splits a string str with delimiter delim and returns an array of " "substrings. The substrings will not contain the delimiter delim. If delim " - "is not found, the returned array will have one element.") + "is not found, the returned array will have one element. Will start searching " + "for delim at the index start (if provided), and return up to a maximum " + "of limit results (if provided).") }, { "string/check-set", cfun_string_checkset, diff --git a/test/suite2.janet b/test/suite2.janet index ed747348..c0428019 100644 --- a/test/suite2.janet +++ b/test/suite2.janet @@ -62,8 +62,7 @@ # String functions (assert (= 3 (string/find "abc" " abcdefghijklmnop")) "string/find 1") -(assert (= nil (string/find "" "")) "string/find 2") -(assert (= 0 (string/find "A" "A")) "string/find 3") +(assert (= 0 (string/find "A" "A")) "string/find 2") (assert (string/has-prefix? "" "foo") "string/has-prefix? 1") (assert (string/has-prefix? "fo" "foo") "string/has-prefix? 2") (assert (not (string/has-prefix? "o" "foo")) "string/has-prefix? 3") @@ -98,6 +97,12 @@ (assert (deep= (string/find-all "e" "onetwothree") @[2 9 10]) "string/find-all 1") (assert (deep= (string/find-all "," "onetwothree") @[]) "string/find-all 2") +(assert-error "string/find error 1" (string/find "" "abcd")) +(assert-error "string/split error 1" (string/split "" "abcd")) +(assert-error "string/replace error 1" (string/replace "" "." "abcd")) +(assert-error "string/replace-all error 1" (string/replace-all "" "." "abcdabcd")) +(assert-error "string/find-all error 1" (string/find-all "" "abcd")) + # Check if abstract test works (assert (abstract? stdout) "abstract? stdout") (assert (abstract? stdin) "abstract? stdin")