diff options
author | ringabout <43030857+ringabout@users.noreply.github.com> | 2023-05-30 19:40:09 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-30 13:40:09 +0200 |
commit | 40f88da90b0589a91f4f60b2ebf49859b79e2247 (patch) | |
tree | 4850674d0e8ce1726f7ab071693e198359d0a801 | |
parent | 7e055413f9bbec81fc9b7e1542695f2886787566 (diff) | |
download | Nim-40f88da90b0589a91f4f60b2ebf49859b79e2247.tar.gz |
alternative to #21914; split, rsplit now forbid an empty separator (#21961)
-rw-r--r-- | changelogs/changelog_2_0_0.md | 1 | ||||
-rw-r--r-- | lib/pure/strutils.nim | 26 | ||||
-rw-r--r-- | tests/stdlib/tstrutils.nim | 14 |
3 files changed, 37 insertions, 4 deletions
diff --git a/changelogs/changelog_2_0_0.md b/changelogs/changelog_2_0_0.md index 00c20f397..4a15855f4 100644 --- a/changelogs/changelog_2_0_0.md +++ b/changelogs/changelog_2_0_0.md @@ -255,6 +255,7 @@ - Pragma `{.inline.}` generates `__forceinline` if `__has_attribute(__forceinline)` for GCC and Clang. +- `strutils.split` and `strutils.rsplit` now forbid an empty separator. ## Standard library additions and changes diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 0a77e8bf6..fe9f2a8c3 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -487,12 +487,15 @@ iterator split*(s: string, seps: set[char] = Whitespace, ## "22" ## "08" ## "08.398990" + ## + ## .. warning:: `seps` should not be empty. ## ## See also: ## * `rsplit iterator<#rsplit.i,string,set[char],int>`_ ## * `splitLines iterator<#splitLines.i,string>`_ ## * `splitWhitespace iterator<#splitWhitespace.i,string,int>`_ ## * `split func<#split,string,set[char],int>`_ + assert seps.card > 0, "Empty separator" splitCommon(s, seps, maxsplit, 1) iterator split*(s: string, sep: string, maxsplit: int = -1): string = @@ -512,11 +515,14 @@ iterator split*(s: string, sep: string, maxsplit: int = -1): string = ## "is" ## "corrupted" ## + ## .. warning:: `sep` should not be empty. + ## ## See also: ## * `rsplit iterator<#rsplit.i,string,string,int,bool>`_ ## * `splitLines iterator<#splitLines.i,string>`_ ## * `splitWhitespace iterator<#splitWhitespace.i,string,int>`_ ## * `split func<#split,string,string,int>`_ + assert sep.len > 0, "Empty separator" splitCommon(s, sep, maxsplit, sep.len) @@ -585,13 +591,16 @@ iterator rsplit*(s: string, seps: set[char] = Whitespace, ## "bar" ## "foo" ## - ## Substrings are separated from the right by the set of chars `seps` + ## Substrings are separated from the right by the set of chars `seps`. + ## + ## .. warning:: `seps` should not be empty. ## ## See also: ## * `split iterator<#split.i,string,set[char],int>`_ ## * `splitLines iterator<#splitLines.i,string>`_ ## * `splitWhitespace iterator<#splitWhitespace.i,string,int>`_ ## * `rsplit func<#rsplit,string,set[char],int>`_ + assert seps.card > 0, "Empty separator" rsplitCommon(s, seps, maxsplit, 1) iterator rsplit*(s: string, sep: string, maxsplit: int = -1, @@ -610,13 +619,16 @@ iterator rsplit*(s: string, sep: string, maxsplit: int = -1, ## "bar" ## "foo" ## - ## Substrings are separated from the right by the string `sep` + ## Substrings are separated from the right by the string `sep`. + ## + ## .. warning:: `sep` should not be empty. ## ## See also: ## * `split iterator<#split.i,string,string,int>`_ ## * `splitLines iterator<#splitLines.i,string>`_ ## * `splitWhitespace iterator<#splitWhitespace.i,string,int>`_ ## * `rsplit func<#rsplit,string,string,int>`_ + assert sep.len > 0, "Empty separator" rsplitCommon(s, sep, maxsplit, sep.len) iterator splitLines*(s: string, keepEol = false): string = @@ -728,6 +740,8 @@ func split*(s: string, seps: set[char] = Whitespace, maxsplit: int = -1): seq[ ## The same as the `split iterator <#split.i,string,set[char],int>`_ (see its ## documentation), but is a func that returns a sequence of substrings. ## + ## .. warning:: `seps` should not be empty. + ## ## See also: ## * `split iterator <#split.i,string,set[char],int>`_ ## * `rsplit func<#rsplit,string,set[char],int>`_ @@ -745,6 +759,8 @@ func split*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl, ## Substrings are separated by the string `sep`. This is a wrapper around the ## `split iterator <#split.i,string,string,int>`_. ## + ## .. warning:: `sep` should not be empty. + ## ## See also: ## * `split iterator <#split.i,string,string,int>`_ ## * `rsplit func<#rsplit,string,string,int>`_ @@ -757,8 +773,6 @@ func split*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl, doAssert "a largely spaced sentence".split(" ") == @["a", "", "largely", "", "", "", "spaced", "sentence"] doAssert "a largely spaced sentence".split(" ", maxsplit = 1) == @["a", " largely spaced sentence"] - doAssert(sep.len > 0) - accResult(split(s, sep, maxsplit)) func rsplit*(s: string, sep: char, maxsplit: int = -1): seq[string] {.rtl, @@ -808,6 +822,8 @@ func rsplit*(s: string, seps: set[char] = Whitespace, ## .. code-block:: nim ## @["Root#Object#Method", "Index"] ## + ## .. warning:: `seps` should not be empty. + ## ## See also: ## * `rsplit iterator <#rsplit.i,string,set[char],int>`_ ## * `split func<#split,string,set[char],int>`_ @@ -835,6 +851,8 @@ func rsplit*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl, ## .. code-block:: nim ## @["Root#Object#Method", "Index"] ## + ## .. warning:: `sep` should not be empty. + ## ## See also: ## * `rsplit iterator <#rsplit.i,string,string,int,bool>`_ ## * `split func<#split,string,string,int>`_ diff --git a/tests/stdlib/tstrutils.nim b/tests/stdlib/tstrutils.nim index 67eb5cf3a..d53e9d8b4 100644 --- a/tests/stdlib/tstrutils.nim +++ b/tests/stdlib/tstrutils.nim @@ -53,6 +53,13 @@ template main() = doAssert s.split(maxsplit = 4) == @["", "this", "is", "an", "example "] doAssert s.split(' ', maxsplit = 1) == @["", "this is an example "] doAssert s.split(" ", maxsplit = 4) == @["", "this", "is", "an", "example "] + # Empty string: + doAssert "".split() == @[""] + doAssert "".split(" ") == @[""] + doAssert "".split({' '}) == @[""] + # Empty separators: + doAssertRaises(AssertionDefect): discard s.split({}) + doAssertRaises(AssertionDefect): discard s.split("") block: # splitLines let fixture = "a\nb\rc\r\nd" @@ -69,6 +76,13 @@ template main() = doAssert rsplit(":foo:bar", sep = ':', maxsplit = 2) == @["", "foo", "bar"] doAssert rsplit(":foo:bar", sep = ':', maxsplit = 3) == @["", "foo", "bar"] doAssert rsplit("foothebar", sep = "the") == @["foo", "bar"] + # Empty string: + doAssert "".rsplit() == @[""] + doAssert "".rsplit(" ") == @[""] + doAssert "".rsplit({' '}) == @[""] + # Empty separators: + doAssertRaises(AssertionDefect): discard "".rsplit({}) + doAssertRaises(AssertionDefect): discard "".rsplit("") block: # splitWhitespace let s = " this is an example " |