summary refs log tree commit diff stats
path: root/lib/std
diff options
context:
space:
mode:
authorflywind <xzsflywind@gmail.com>2021-02-24 03:22:47 -0600
committerGitHub <noreply@github.com>2021-02-24 10:22:47 +0100
commit3f38f8fbb7c0dd3af641961ed98ef0e67ea91f3c (patch)
treef0ad53e014bcfb3bc321287c341198c9d349c9a5 /lib/std
parent46bd222c89c57217d1d4738f84f52de94f092c1d (diff)
downloadNim-3f38f8fbb7c0dd3af641961ed98ef0e67ea91f3c.tar.gz
add strbasics.strip (#16280)
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/strbasics.nim97
1 files changed, 97 insertions, 0 deletions
diff --git a/lib/std/strbasics.nim b/lib/std/strbasics.nim
new file mode 100644
index 000000000..ce061adca
--- /dev/null
+++ b/lib/std/strbasics.nim
@@ -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))