add overload add(a: var string, b: openArray[char]) (#15951)

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This commit is contained in:
Timothee Cour 2021-03-01 07:51:12 -08:00 • committed by GitHub
commit 0cb02fbbee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 152 additions and 122 deletions

View file

@ -173,9 +173,10 @@ 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.
- `hashes.hash` now supports `object`, but can be overloaded. - Added `std/strbasics` for high performance string operations.
Added `strip`, `setSlice`, `add(a: var string, b: openArray[char])`.
- Added `strip` and `setSlice` to `std/strbasics`. - `hashes.hash` now supports `object`, but can be overloaded.
- Added to `wrapnils` an option-like API via `??.`, `isSome`, `get`. - Added to `wrapnils` an option-like API via `??.`, `isSome`, `get`.

View file

@ -8,9 +8,25 @@
# #
## This module provides some high performance string operations. ## This module provides some high performance string operations.
##
## Experimental API, subject to change.
const whitespaces = {' ', '\t', '\v', '\r', '\l', '\f'} const whitespaces = {' ', '\t', '\v', '\r', '\l', '\f'}
proc add*(x: var string, y: openArray[char]) =
## Concatenates `x` and `y` in place. `y` must not overlap with `x` to
## allow future `memcpy` optimizations.
# Use `{.noalias.}` ?
let n = x.len
x.setLen n + y.len
# pending https://github.com/nim-lang/Nim/issues/14655#issuecomment-643671397
# use x.setLen(n + y.len, isInit = false)
var i = 0
while i < y.len:
x[n + i] = y[i]
i.inc
# xxx use `nimCopyMem(x[n].addr, y[0].addr, y.len)` after some refactoring
func stripSlice(s: openArray[char], leading = true, trailing = true, chars: set[char] = whitespaces): Slice[int] = 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`. ## Returns the slice range of `s` which is stripped `chars`.
runnableExamples: runnableExamples:

View file

@ -1069,15 +1069,16 @@ proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.}
## tmp.add('a') ## tmp.add('a')
## tmp.add('b') ## tmp.add('b')
## assert(tmp == "ab") ## assert(tmp == "ab")
proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.}
proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.} =
## Concatenates `x` and `y` in place. ## Concatenates `x` and `y` in place.
## ##
## .. code-block:: Nim ## See also `strbasics.add`.
## var tmp = "" runnableExamples:
## tmp.add("ab") var tmp = ""
## tmp.add("cd") tmp.add("ab")
## assert(tmp == "abcd") tmp.add("cd")
assert tmp == "abcd"
type type
Endianness* = enum ## Type describing the endianness of a processor. Endianness* = enum ## Type describing the endianness of a processor.

View file

@ -1,126 +1,139 @@
discard """ discard """
targets: "c cpp js" targets: "c cpp js"
matrix: "--gc:refc; --gc:arc"
""" """
import std/[strbasics, sugar] import std/[strbasics, sugar]
proc main() =
when not defined(gcArc): # pending bug #17173
block: # strip
var a = " vhellov "
strip(a)
doAssert a == "vhellov"
proc teststrip() = a = " vhellov "
var a = " vhellov " a.strip(leading = false)
strip(a) doAssert a == " vhellov"
doAssert a == "vhellov"
a = " vhellov " a = " vhellov "
a.strip(leading = false) a.strip(trailing = false)
doAssert a == " vhellov" doAssert a == "vhellov "
a = " vhellov " a.strip()
a.strip(trailing = false) a.strip(chars = {'v'})
doAssert a == "vhellov " doAssert a == "hello"
a.strip() a = " vhellov "
a.strip(chars = {'v'}) a.strip()
doAssert a == "hello" a.strip(leading = false, chars = {'v'})
doAssert a == "vhello"
a = " vhellov " var c = "blaXbla"
a.strip() c.strip(chars = {'b', 'a'})
a.strip(leading = false, chars = {'v'}) doAssert c == "laXbl"
doAssert a == "vhello" c = "blaXbla"
c.strip(chars = {'b', 'a', 'l'})
doAssert c == "X"
var c = "blaXbla" block:
c.strip(chars = {'b', 'a'}) var a = "xxxxxx"
doAssert c == "laXbl" a.strip(chars={'x'})
c = "blaXbla" doAssert a.len == 0
c.strip(chars = {'b', 'a', 'l'})
doAssert c == "X"
block: block:
var a = "xxxxxx" var a = "x"
a.strip(chars={'x'}) a.strip(chars={'x'})
doAssert a.len == 0 doAssert a.len == 0
block:
var a = "x"
a.strip(chars={'1'})
doAssert a.len == 1
block: block:
var a = "x" var a = ""
a.strip(chars={'x'}) a.strip(chars={'x'})
doAssert a.len == 0 doAssert a.len == 0
block:
var a = "x"
a.strip(chars={'1'})
doAssert a.len == 1
block: block:
var a = "" var a = "xxx xxx"
a.strip(chars={'x'}) a.strip(chars={'x'})
doAssert a.len == 0 doAssert a == " "
block: block:
var a = "xxx xxx" var a = "xxx wind"
a.strip(chars={'x'}) a.strip(chars={'x'})
doAssert a == " " doAssert a == " wind"
block: block:
var a = "xxx wind" var a = "xxx iii"
a.strip(chars={'x'}) a.strip(chars={'i'})
doAssert a == " wind" doAssert a == "xxx "
block: block:
var a = "xxx iii" var a = "xxx iii"
a.strip(chars={'i'}) doAssert a.dup(strip(chars = {'i'})) == "xxx "
doAssert a == "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: block:
var a = "xxx iii" var a = "x i"
doAssert a.dup(strip(chars = {'i'})) == "xxx " doAssert a.dup(strip(chars = {'i'})) == "x "
doAssert a.dup(strip(chars = {' '})) == "xxx iii" doAssert a.dup(strip(chars = {' '})) == "x i"
doAssert a.dup(strip(chars = {'x'})) == " iii" doAssert a.dup(strip(chars = {'x'})) == " i"
doAssert a.dup(strip(chars = {'x', ' '})) == "iii" 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 doAssert a.dup(strip(chars = {'x', 'i', ' '})).len == 0
block: block:
var a = "x i" var a = ""
doAssert a.dup(strip(chars = {'i'})) == "x " doAssert a.dup(strip(chars = {'i'})).len == 0
doAssert a.dup(strip(chars = {' '})) == "x i" doAssert a.dup(strip(chars = {' '})).len == 0
doAssert a.dup(strip(chars = {'x'})) == " i" doAssert a.dup(strip(chars = {'x'})).len == 0
doAssert a.dup(strip(chars = {'x', ' '})) == "i" doAssert a.dup(strip(chars = {'x', ' '})).len == 0
doAssert a.dup(strip(chars = {'x', 'i'})) == " " doAssert a.dup(strip(chars = {'x', 'i'})).len == 0
doAssert a.dup(strip(chars = {'x', 'i', ' '})).len == 0 doAssert a.dup(strip(chars = {'x', 'i', ' '})).len == 0
block: block:
var a = "" var a = " "
doAssert a.dup(strip(chars = {'i'})).len == 0 doAssert a.dup(strip(chars = {'i'})) == " "
doAssert a.dup(strip(chars = {' '})).len == 0 doAssert a.dup(strip(chars = {' '})).len == 0
doAssert a.dup(strip(chars = {'x'})).len == 0 doAssert a.dup(strip(chars = {'x'})) == " "
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'})) == " "
doAssert a.dup(strip(chars = {'x', 'i', ' '})).len == 0 doAssert a.dup(strip(chars = {'x', 'i', ' '})).len == 0
block: block: # setSlice
var a = " " var a = "Hello, Nim!"
doAssert a.dup(strip(chars = {'i'})) == " " doassert a.dup(setSlice(7 .. 9)) == "Nim"
doAssert a.dup(strip(chars = {' '})).len == 0 doAssert a.dup(setSlice(0 .. 0)) == "H"
doAssert a.dup(strip(chars = {'x'})) == " " doAssert a.dup(setSlice(0 .. 1)) == "He"
doAssert a.dup(strip(chars = {'x', ' '})).len == 0 doAssert a.dup(setSlice(0 .. 10)) == a
doAssert a.dup(strip(chars = {'x', 'i'})) == " " doAssert a.dup(setSlice(1 .. 0)).len == 0
doAssert a.dup(strip(chars = {'x', 'i', ' '})).len == 0 doAssert a.dup(setSlice(20 .. -1)).len == 0
doAssertRaises(AssertionDefect):
discard a.dup(setSlice(-1 .. 1))
block: doAssertRaises(AssertionDefect):
var a = "Hello, Nim!" discard a.dup(setSlice(1 .. 11))
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
block: # add
var a0 = "hi"
var b0 = "foobar"
when nimvm:
discard # pending bug #15952
else:
a0.add b0.toOpenArray(1,3)
doAssert a0 == "hioob"
proc fn(c: openArray[char]): string =
result.add c
doAssert fn("def") == "def"
doAssert fn(['d','\0', 'f'])[2] == 'f'
doAssertRaises(AssertionDefect): static: main()
discard a.dup(setSlice(-1 .. 1)) main()
doAssertRaises(AssertionDefect):
discard a.dup(setSlice(1 .. 11))
static: teststrip()
teststrip()

View file

@ -12,16 +12,16 @@ proc set_all[T](s: var openArray[T]; val: T) =
for i in 0..<s.len: for i in 0..<s.len:
s[i] = val s[i] = val
proc test() = proc main() =
var a0 = "hello_world" var a0 = "hello_world"
var a1 = [1,2,3,4,5,6,7,8,9] var a1 = [1,2,3,4,5,6,7,8,9]
var a2 = @[1,2,3,4,5,6,7,8,9] var a2 = @[1,2,3,4,5,6,7,8,9]
a0.set_all('i') a0.set_all('i')
a1.set_all(4) a1.set_all(4)
a2.set_all(4) a2.set_all(4)
doAssert a0 == "iiiiiiiiiii" doAssert a0 == "iiiiiiiiiii"
doAssert a1 == [4,4,4,4,4,4,4,4,4] doAssert a1 == [4,4,4,4,4,4,4,4,4]
doAssert a2 == @[4,4,4,4,4,4,4,4,4] doAssert a2 == @[4,4,4,4,4,4,4,4,4]
const constval0 = "hello".map(proc(x: char): char = x) const constval0 = "hello".map(proc(x: char): char = x)
const constval1 = [1,2,3,4].map(proc(x: int): int = x) const constval1 = [1,2,3,4].map(proc(x: int): int = x)
@ -29,6 +29,5 @@ const constval1 = [1,2,3,4].map(proc(x: int): int = x)
doAssert("hello".map(proc(x: char): char = x) == constval0) doAssert("hello".map(proc(x: char): char = x) == constval0)
doAssert([1,2,3,4].map(proc(x: int): int = x) == constval1) doAssert([1,2,3,4].map(proc(x: int): int = x) == constval1)
test() static: main()
static: main()
test()