123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- #
- #
- # Nim's Runtime Library
- # (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.
- ##
- ## Experimental API, subject to change.
- when defined(nimPreviewSlimSystem):
- import std/assertions
- 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] =
- ## 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:
- when defined(nimSeqsV2):
- prepareMutation(s)
- 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))
|