forked from nim-lang/Nim
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add strbasics.strip (nim-lang#16280)
- Loading branch information
Showing
4 changed files
with
226 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() |