summary refs log tree commit diff stats
path: root/compiler/strutils2.nim
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2020-06-10 05:10:57 -0700
committerGitHub <noreply@github.com>2020-06-10 14:10:57 +0200
commit8bbdb8f43fb0da04d4b75bca011662f690972bfe (patch)
tree3dec6af1267a36d12f8b067aca49fb4f0bf95068 /compiler/strutils2.nim
parent5131af1a446140d275510d67bff281f2e42cc19b (diff)
downloadNim-8bbdb8f43fb0da04d4b75bca011662f690972bfe.tar.gz
fix #14545 windows CI docs (#14590)
* fix #14545 windows paths
* add lib/std/private/strutils2.nim
* remove dependency strutils2 => strutils
* address comment: lib/std/private/strutils2.nim => compiler/strutils2.nim
Diffstat (limited to 'compiler/strutils2.nim')
-rw-r--r--compiler/strutils2.nim57
1 files changed, 57 insertions, 0 deletions
diff --git a/compiler/strutils2.nim b/compiler/strutils2.nim
new file mode 100644
index 000000000..6cb50347f
--- /dev/null
+++ b/compiler/strutils2.nim
@@ -0,0 +1,57 @@
+##[
+internal API for now, subject to modifications and moving around
+
+string API's focusing on performance, that can be used as building blocks
+for other routines.
+
+Un-necessary allocations are avoided and appropriate algorithms are used at the
+expense of code clarity when justified.
+]##
+
+proc dataPointer*[T](a: T): pointer =
+  ## same as C++ `data` that works with std::string, std::vector etc.
+  ## Note: safe to use when a.len == 0 but whether the result is nil or not
+  ## is implementation defined for performance reasons.
+  # this could be improved with ocmpiler support to avoid the `if`, eg in C++
+  # `&a[0]` is well defined even if a.size() == 0
+  when T is string | seq:
+    if a.len == 0: nil else: cast[pointer](a[0].unsafeAddr)
+  elif T is array:
+    when a.len > 0: a.unsafeAddr
+    else: nil
+  elif T is cstring:
+    cast[pointer](a)
+  else: static: doAssert false, $T
+
+proc setLen*(result: var string, n: int, isInit: bool) =
+  ## when isInit = false, elements are left uninitialized, analog to `{.noinit.}`
+  ## else, there are 0-initialized.
+  # xxx placeholder until system.setLen supports this
+  # to distinguish between algorithms that need 0-initialization vs not; note
+  # that `setLen` for string is inconsistent with `setLen` for seq.
+  # likwise with `newString` vs `newSeq`. This should be fixed in `system`.
+  let n0 = result.len
+  result.setLen(n)
+  if isInit and n > n0:
+    zeroMem(result[n0].addr, n - n0)
+
+proc forceCopy*(result: var string, a: string) =
+  ## also forces a copy if `a` is shallow
+  # the naitve `result = a` would not work if `a` is shallow
+  let n = a.len
+  result.setLen n, isInit = false
+  copyMem(result.dataPointer, a.dataPointer, n)
+
+proc isUpperAscii(c: char): bool {.inline.} =
+  # avoids import strutils.isUpperAscii
+  c in {'A'..'Z'}
+
+proc toLowerAscii*(a: var string) =
+  ## optimized and inplace overload of strutils.toLowerAscii
+  # refs https://github.com/timotheecour/Nim/pull/54
+  # this is 10X faster than a naive implementation using a an optimization trick
+  # that can be adapted in similar contexts. Predictable writes avoid write
+  # hazards and lead to better machine code, compared to random writes arising
+  # from: `if c.isUpperAscii: c = ...`
+  for c in mitems(a):
+    c = chr(c.ord + (if c.isUpperAscii: (ord('a') - ord('A')) else: 0))