strimpl.nim 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. func toLowerAscii*(c: char): char {.inline.} =
  2. if c in {'A'..'Z'}:
  3. result = chr(ord(c) + (ord('a') - ord('A')))
  4. else:
  5. result = c
  6. template firstCharCaseSensitiveImpl[T: string | cstring](a, b: T, aLen, bLen: int) =
  7. if aLen == 0 or bLen == 0:
  8. return aLen - bLen
  9. if a[0] != b[0]: return ord(a[0]) - ord(b[0])
  10. template cmpIgnoreStyleImpl*[T: string | cstring](a, b: T,
  11. firstCharCaseSensitive: static bool = false) =
  12. let aLen = a.len
  13. let bLen = b.len
  14. var i = 0
  15. var j = 0
  16. when firstCharCaseSensitive:
  17. firstCharCaseSensitiveImpl(a, b, aLen, bLen)
  18. inc i
  19. inc j
  20. while true:
  21. while i < aLen and a[i] == '_': inc i
  22. while j < bLen and b[j] == '_': inc j
  23. let aa = if i < aLen: toLowerAscii(a[i]) else: '\0'
  24. let bb = if j < bLen: toLowerAscii(b[j]) else: '\0'
  25. result = ord(aa) - ord(bb)
  26. if result != 0: return result
  27. # the characters are identical:
  28. if i >= aLen:
  29. # both cursors at the end:
  30. if j >= bLen: return 0
  31. # not yet at the end of 'b':
  32. return -1
  33. elif j >= bLen:
  34. return 1
  35. inc i
  36. inc j
  37. template cmpIgnoreCaseImpl*[T: string | cstring](a, b: T,
  38. firstCharCaseSensitive: static bool = false) =
  39. let aLen = a.len
  40. let bLen = b.len
  41. var i = 0
  42. when firstCharCaseSensitive:
  43. firstCharCaseSensitiveImpl(a, b, aLen, bLen)
  44. inc i
  45. var m = min(aLen, bLen)
  46. while i < m:
  47. result = ord(toLowerAscii(a[i])) - ord(toLowerAscii(b[i]))
  48. if result != 0: return
  49. inc i
  50. result = aLen - bLen
  51. template startsWithImpl*[T: string | cstring](s, prefix: T) =
  52. let prefixLen = prefix.len
  53. let sLen = s.len
  54. var i = 0
  55. while true:
  56. if i >= prefixLen: return true
  57. if i >= sLen or s[i] != prefix[i]: return false
  58. inc(i)
  59. template endsWithImpl*[T: string | cstring](s, suffix: T) =
  60. let suffixLen = suffix.len
  61. let sLen = s.len
  62. var i = 0
  63. var j = sLen - suffixLen
  64. while i+j >= 0 and i+j < sLen:
  65. if s[i+j] != suffix[i]: return false
  66. inc(i)
  67. if i >= suffixLen: return true
  68. func cmpNimIdentifier*[T: string | cstring](a, b: T): int =
  69. cmpIgnoreStyleImpl(a, b, true)
  70. from system/ansi_c import c_memchr, c_strstr
  71. func find*(s: cstring, sub: char, start: Natural = 0, last = 0): int =
  72. ## Searches for `sub` in `s` inside the range `start..last` (both ends included).
  73. ## If `last` is unspecified, it defaults to `s.high` (the last element).
  74. ##
  75. ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
  76. ## Otherwise the index returned is relative to `s[0]`, not `start`.
  77. ## Use `s[start..last].rfind` for a `start`-origin index.
  78. let last = if last == 0: s.high else: last
  79. let L = last-start+1
  80. if L > 0:
  81. let found = c_memchr(s[start].unsafeAddr, cint(sub), cast[csize_t](L))
  82. if not found.isNil:
  83. return cast[int](found) -% cast[int](s)
  84. return -1
  85. func find*(s, sub: cstring, start: Natural = 0, last = 0): int =
  86. ## Searches for `sub` in `s` inside the range `start..last` (both ends included).
  87. ## If `last` is unspecified, it defaults to `s.high` (the last element).
  88. ##
  89. ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
  90. ## Otherwise the index returned is relative to `s[0]`, not `start`.
  91. ## Use `s[start..last].find` for a `start`-origin index.
  92. if sub.len > s.len - start: return -1
  93. if sub.len == 1: return find(s, sub[0], start, last)
  94. if last == 0 and s.len > start:
  95. let found = c_strstr(cast[cstring](s[start].unsafeAddr), sub)
  96. if not found.isNil:
  97. result = cast[int](found) -% cast[int](s)
  98. else:
  99. result = -1
  100. else:
  101. result = 0