123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- func toLowerAscii*(c: char): char {.inline.} =
- if c in {'A'..'Z'}:
- result = chr(ord(c) + (ord('a') - ord('A')))
- else:
- result = c
- template firstCharCaseSensitiveImpl[T: string | cstring](a, b: T, aLen, bLen: int) =
- if aLen == 0 or bLen == 0:
- return aLen - bLen
- if a[0] != b[0]: return ord(a[0]) - ord(b[0])
- template cmpIgnoreStyleImpl*[T: string | cstring](a, b: T,
- firstCharCaseSensitive: static bool = false) =
- let aLen = a.len
- let bLen = b.len
- var i = 0
- var j = 0
- when firstCharCaseSensitive:
- firstCharCaseSensitiveImpl(a, b, aLen, bLen)
- inc i
- inc j
- while true:
- while i < aLen and a[i] == '_': inc i
- while j < bLen and b[j] == '_': inc j
- let aa = if i < aLen: toLowerAscii(a[i]) else: '\0'
- let bb = if j < bLen: toLowerAscii(b[j]) else: '\0'
- result = ord(aa) - ord(bb)
- if result != 0: return result
- # the characters are identical:
- if i >= aLen:
- # both cursors at the end:
- if j >= bLen: return 0
- # not yet at the end of 'b':
- return -1
- elif j >= bLen:
- return 1
- inc i
- inc j
- template cmpIgnoreCaseImpl*[T: string | cstring](a, b: T,
- firstCharCaseSensitive: static bool = false) =
- let aLen = a.len
- let bLen = b.len
- var i = 0
- when firstCharCaseSensitive:
- firstCharCaseSensitiveImpl(a, b, aLen, bLen)
- inc i
- var m = min(aLen, bLen)
- while i < m:
- result = ord(toLowerAscii(a[i])) - ord(toLowerAscii(b[i]))
- if result != 0: return
- inc i
- result = aLen - bLen
- template startsWithImpl*[T: string | cstring](s, prefix: T) =
- let prefixLen = prefix.len
- let sLen = s.len
- var i = 0
- while true:
- if i >= prefixLen: return true
- if i >= sLen or s[i] != prefix[i]: return false
- inc(i)
- template endsWithImpl*[T: string | cstring](s, suffix: T) =
- let suffixLen = suffix.len
- let sLen = s.len
- var i = 0
- var j = sLen - suffixLen
- while i+j >= 0 and i+j < sLen:
- if s[i+j] != suffix[i]: return false
- inc(i)
- if i >= suffixLen: return true
- func cmpNimIdentifier*[T: string | cstring](a, b: T): int =
- cmpIgnoreStyleImpl(a, b, true)
- func c_memchr(cstr: pointer, c: char, n: csize_t): pointer {.
- importc: "memchr", header: "<string.h>".}
- func c_strstr(haystack, needle: cstring): cstring {.
- importc: "strstr", header: "<string.h>".}
- func find*(s: cstring, sub: char, start: Natural = 0, last = 0): int =
- ## Searches for `sub` in `s` inside the range `start..last` (both ends included).
- ## If `last` is unspecified, it defaults to `s.high` (the last element).
- ##
- ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
- ## Otherwise the index returned is relative to `s[0]`, not `start`.
- ## Use `s[start..last].rfind` for a `start`-origin index.
- let last = if last == 0: s.high else: last
- let L = last-start+1
- if L > 0:
- let found = c_memchr(s[start].unsafeAddr, sub, cast[csize_t](L))
- if not found.isNil:
- return cast[int](found) -% cast[int](s)
- return -1
- func find*(s, sub: cstring, start: Natural = 0, last = 0): int =
- ## Searches for `sub` in `s` inside the range `start..last` (both ends included).
- ## If `last` is unspecified, it defaults to `s.high` (the last element).
- ##
- ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
- ## Otherwise the index returned is relative to `s[0]`, not `start`.
- ## Use `s[start..last].find` for a `start`-origin index.
- if sub.len > s.len - start: return -1
- if sub.len == 1: return find(s, sub[0], start, last)
- if last == 0 and s.len > start:
- let found = c_strstr(cast[cstring](s[start].unsafeAddr), sub)
- if not found.isNil:
- result = cast[int](found) -% cast[int](s)
- else:
- result = -1
|