diff options
author | Timothee Cour <timothee.cour2@gmail.com> | 2020-06-10 05:10:57 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-10 14:10:57 +0200 |
commit | 8bbdb8f43fb0da04d4b75bca011662f690972bfe (patch) | |
tree | 3dec6af1267a36d12f8b067aca49fb4f0bf95068 /compiler/strutils2.nim | |
parent | 5131af1a446140d275510d67bff281f2e42cc19b (diff) | |
download | Nim-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.nim | 57 |
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)) |