add strbasics.strip (#16280)

This commit is contained in:
flywind 2021-02-24 03:22:47 -06:00 • committed by GitHub
commit 3f38f8fbb7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 226 additions and 0 deletions

View file

@ -171,6 +171,8 @@ provided by the operating system.
dumping (on select signals) and notifying the parent process about the cause dumping (on select signals) and notifying the parent process about the cause
of termination. of termination.
- Added `strip` and `setSlice` to `std/strbasics`.
## Language changes ## Language changes

View file

@ -2753,6 +2753,7 @@ func strip*(s: string, leading = true, trailing = true,
## If both are false, the string is returned unchanged. ## If both are false, the string is returned unchanged.
## ##
## See also: ## See also:
## * `strip proc<strbasics.html#strip,string,set[char]>`_ Inplace version.
## * `stripLineEnd func<#stripLineEnd,string>`_ ## * `stripLineEnd func<#stripLineEnd,string>`_
runnableExamples: runnableExamples:
let a = " vhellov " let a = " vhellov "

97
lib/std/strbasics.nim Normal file
View file

@ -0,0 +1,97 @@
#
#
# The Nim Compiler
# (c) Copyright 2021 Nim Contributors
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module provides some high performance string operations.
const whitespaces = {' ', '\t', '\v', '\r', '\l', '\f'}
func stripSlice(s: openArray[char], leading = true, trailing = true, chars: set[char] = whitespaces): Slice[int] =
## Returns the slice range of `s` which is stripped `chars`.
runnableExamples:
assert stripSlice(" abc ") == 1 .. 3
var
first = 0
last = high(s)
if leading:
while first <= last and s[first] in chars: inc(first)
if trailing:
while last >= first and s[last] in chars: dec(last)
result = first .. last
func setSlice*(s: var string, slice: Slice[int]) =
## Inplace version of `substr`.
runnableExamples:
import std/sugar
var a = "Hello, Nim!"
doassert a.dup(setSlice(7 .. 9)) == "Nim"
doAssert a.dup(setSlice(0 .. 0)) == "H"
doAssert a.dup(setSlice(0 .. 1)) == "He"
doAssert a.dup(setSlice(0 .. 10)) == a
doAssert a.dup(setSlice(1 .. 0)).len == 0
doAssert a.dup(setSlice(20 .. -1)).len == 0
doAssertRaises(AssertionDefect):
discard a.dup(setSlice(-1 .. 1))
doAssertRaises(AssertionDefect):
discard a.dup(setSlice(1 .. 11))
let first = slice.a
let last = slice.b
assert first >= 0
assert last <= s.high
if first > last:
s.setLen(0)
return
template impl =
for index in first .. last:
s[index - first] = s[index]
if first > 0:
when nimvm: impl()
else:
# not JS and not Nimscript
when not declared(moveMem):
impl()
else:
moveMem(addr s[0], addr s[first], last - first + 1)
s.setLen(last - first + 1)
func strip*(a: var string, leading = true, trailing = true, chars: set[char] = whitespaces) {.inline.} =
## Inplace version of `strip`. Strips leading or
## trailing `chars` (default: whitespace characters).
##
## If `leading` is true (default), leading `chars` are stripped.
## If `trailing` is true (default), trailing `chars` are stripped.
## If both are false, the string is unchanged.
runnableExamples:
var a = " vhellov "
strip(a)
assert a == "vhellov"
a = " vhellov "
a.strip(leading = false)
assert a == " vhellov"
a = " vhellov "
a.strip(trailing = false)
assert a == "vhellov "
var c = "blaXbla"
c.strip(chars = {'b', 'a'})
assert c == "laXbl"
c = "blaXbla"
c.strip(chars = {'b', 'a', 'l'})
assert c == "X"
setSlice(a, stripSlice(a, leading, trailing, chars))

126
tests/stdlib/tstrbasics.nim Normal file
View file

@ -0,0 +1,126 @@
discard """
targets: "c cpp js"
"""
import std/[strbasics, sugar]
proc teststrip() =
var a = " vhellov "
strip(a)
doAssert a == "vhellov"
a = " vhellov "
a.strip(leading = false)
doAssert a == " vhellov"
a = " vhellov "
a.strip(trailing = false)
doAssert a == "vhellov "
a.strip()
a.strip(chars = {'v'})
doAssert a == "hello"
a = " vhellov "
a.strip()
a.strip(leading = false, chars = {'v'})
doAssert a == "vhello"
var c = "blaXbla"
c.strip(chars = {'b', 'a'})
doAssert c == "laXbl"
c = "blaXbla"
c.strip(chars = {'b', 'a', 'l'})
doAssert c == "X"
block:
var a = "xxxxxx"
a.strip(chars={'x'})
doAssert a.len == 0
block:
var a = "x"
a.strip(chars={'x'})
doAssert a.len == 0
block:
var a = "x"
a.strip(chars={'1'})
doAssert a.len == 1
block:
var a = ""
a.strip(chars={'x'})
doAssert a.len == 0
block:
var a = "xxx xxx"
a.strip(chars={'x'})
doAssert a == " "
block:
var a = "xxx wind"
a.strip(chars={'x'})
doAssert a == " wind"
block:
var a = "xxx iii"
a.strip(chars={'i'})
doAssert a == "xxx "
block:
var a = "xxx iii"
doAssert a.dup(strip(chars = {'i'})) == "xxx "
doAssert a.dup(strip(chars = {' '})) == "xxx iii"
doAssert a.dup(strip(chars = {'x'})) == " iii"
doAssert a.dup(strip(chars = {'x', ' '})) == "iii"
doAssert a.dup(strip(chars = {'x', 'i'})) == " "
doAssert a.dup(strip(chars = {'x', 'i', ' '})).len == 0
block:
var a = "x i"
doAssert a.dup(strip(chars = {'i'})) == "x "
doAssert a.dup(strip(chars = {' '})) == "x i"
doAssert a.dup(strip(chars = {'x'})) == " i"
doAssert a.dup(strip(chars = {'x', ' '})) == "i"
doAssert a.dup(strip(chars = {'x', 'i'})) == " "
doAssert a.dup(strip(chars = {'x', 'i', ' '})).len == 0
block:
var a = ""
doAssert a.dup(strip(chars = {'i'})).len == 0
doAssert a.dup(strip(chars = {' '})).len == 0
doAssert a.dup(strip(chars = {'x'})).len == 0
doAssert a.dup(strip(chars = {'x', ' '})).len == 0
doAssert a.dup(strip(chars = {'x', 'i'})).len == 0
doAssert a.dup(strip(chars = {'x', 'i', ' '})).len == 0
block:
var a = " "
doAssert a.dup(strip(chars = {'i'})) == " "
doAssert a.dup(strip(chars = {' '})).len == 0
doAssert a.dup(strip(chars = {'x'})) == " "
doAssert a.dup(strip(chars = {'x', ' '})).len == 0
doAssert a.dup(strip(chars = {'x', 'i'})) == " "
doAssert a.dup(strip(chars = {'x', 'i', ' '})).len == 0
block:
var a = "Hello, Nim!"
doassert a.dup(setSlice(7 .. 9)) == "Nim"
doAssert a.dup(setSlice(0 .. 0)) == "H"
doAssert a.dup(setSlice(0 .. 1)) == "He"
doAssert a.dup(setSlice(0 .. 10)) == a
doAssert a.dup(setSlice(1 .. 0)).len == 0
doAssert a.dup(setSlice(20 .. -1)).len == 0
doAssertRaises(AssertionDefect):
discard a.dup(setSlice(-1 .. 1))
doAssertRaises(AssertionDefect):
discard a.dup(setSlice(1 .. 11))
static: teststrip()
teststrip()