strutils2.nim 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. ##[
  2. internal API for now, subject to modifications and moving around
  3. string API's focusing on performance, that can be used as building blocks
  4. for other routines.
  5. Un-necessary allocations are avoided and appropriate algorithms are used at the
  6. expense of code clarity when justified.
  7. ]##
  8. proc dataPointer*[T](a: T): pointer =
  9. ## same as C++ `data` that works with std::string, std::vector etc.
  10. ## Note: safe to use when a.len == 0 but whether the result is nil or not
  11. ## is implementation defined for performance reasons.
  12. # this could be improved with ocmpiler support to avoid the `if`, eg in C++
  13. # `&a[0]` is well defined even if a.size() == 0
  14. when T is string | seq:
  15. if a.len == 0: nil else: cast[pointer](a[0].unsafeAddr)
  16. elif T is array:
  17. when a.len > 0: a.unsafeAddr
  18. else: nil
  19. elif T is cstring:
  20. cast[pointer](a)
  21. else: static: doAssert false, $T
  22. proc setLen*(result: var string, n: int, isInit: bool) =
  23. ## when isInit = false, elements are left uninitialized, analog to `{.noinit.}`
  24. ## else, there are 0-initialized.
  25. # xxx placeholder until system.setLen supports this
  26. # to distinguish between algorithms that need 0-initialization vs not; note
  27. # that `setLen` for string is inconsistent with `setLen` for seq.
  28. # likwise with `newString` vs `newSeq`. This should be fixed in `system`.
  29. let n0 = result.len
  30. result.setLen(n)
  31. if isInit and n > n0:
  32. zeroMem(result[n0].addr, n - n0)
  33. proc forceCopy*(result: var string, a: string) =
  34. ## also forces a copy if `a` is shallow
  35. # the naitve `result = a` would not work if `a` is shallow
  36. let n = a.len
  37. result.setLen n, isInit = false
  38. copyMem(result.dataPointer, a.dataPointer, n)
  39. proc isUpperAscii(c: char): bool {.inline.} =
  40. # avoids import strutils.isUpperAscii
  41. c in {'A'..'Z'}
  42. proc toLowerAscii*(a: var string) =
  43. ## optimized and inplace overload of strutils.toLowerAscii
  44. # refs https://github.com/timotheecour/Nim/pull/54
  45. # this is 10X faster than a naive implementation using a an optimization trick
  46. # that can be adapted in similar contexts. Predictable writes avoid write
  47. # hazards and lead to better machine code, compared to random writes arising
  48. # from: `if c.isUpperAscii: c = ...`
  49. for c in mitems(a):
  50. c = chr(c.ord + (if c.isUpperAscii: (ord('a') - ord('A')) else: 0))