summary refs log tree commit diff stats
path: root/lib/std/private/strimpl.nim
blob: 7d42a7cf83b9f6b3f937a052d5565ae73ec1921e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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)