cstrutils.nim 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2017 Nim contributors
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## This module supports helper routines for working with `cstring`
  10. ## without having to convert `cstring` to `string`, in order to
  11. ## save allocations.
  12. ##
  13. ## See also
  14. ## ========
  15. ## * `strutils module <strutils.html>`_ for working with `string`
  16. include system/inclrtl
  17. import std/private/strimpl
  18. when defined(js):
  19. func jsStartsWith(s, prefix: cstring): bool {.importjs: "#.startsWith(#)".}
  20. func jsEndsWith(s, suffix: cstring): bool {.importjs: "#.endsWith(#)".}
  21. func startsWith*(s, prefix: cstring): bool {.rtl, extern: "csuStartsWith".} =
  22. ## Returns true if `s` starts with `prefix`.
  23. ##
  24. ## The JS backend uses the native `String.prototype.startsWith` function.
  25. runnableExamples:
  26. assert startsWith(cstring"Hello, Nimion", cstring"Hello")
  27. assert not startsWith(cstring"Hello, Nimion", cstring"Nimion")
  28. assert startsWith(cstring"Hello", cstring"")
  29. when nimvm:
  30. result = false
  31. startsWithImpl(s, prefix)
  32. else:
  33. when defined(js):
  34. result = jsStartsWith(s, prefix)
  35. else:
  36. result = false
  37. var i = 0
  38. while true:
  39. if prefix[i] == '\0': return true
  40. if s[i] != prefix[i]: return false
  41. inc(i)
  42. func endsWith*(s, suffix: cstring): bool {.rtl, extern: "csuEndsWith".} =
  43. ## Returns true if `s` ends with `suffix`.
  44. ##
  45. ## The JS backend uses the native `String.prototype.endsWith` function.
  46. runnableExamples:
  47. assert endsWith(cstring"Hello, Nimion", cstring"Nimion")
  48. assert not endsWith(cstring"Hello, Nimion", cstring"Hello")
  49. assert endsWith(cstring"Hello", cstring"")
  50. when nimvm:
  51. result = false
  52. endsWithImpl(s, suffix)
  53. else:
  54. when defined(js):
  55. result = jsEndsWith(s, suffix)
  56. else:
  57. result = false
  58. let slen = s.len
  59. var i = 0
  60. var j = slen - len(suffix)
  61. while i + j <% slen:
  62. if s[i + j] != suffix[i]: return false
  63. inc(i)
  64. if suffix[i] == '\0': return true
  65. func cmpIgnoreStyle*(a, b: cstring): int {.rtl, extern: "csuCmpIgnoreStyle".} =
  66. ## Semantically the same as `cmp(normalize($a), normalize($b))`. It
  67. ## is just optimized to not allocate temporary strings. This should
  68. ## NOT be used to compare Nim identifier names, use `macros.eqIdent`
  69. ## for that. Returns:
  70. ## * 0 if `a == b`
  71. ## * < 0 if `a < b`
  72. ## * \> 0 if `a > b`
  73. runnableExamples:
  74. assert cmpIgnoreStyle(cstring"hello", cstring"H_e_L_Lo") == 0
  75. when nimvm:
  76. cmpIgnoreStyleImpl(a, b)
  77. else:
  78. when defined(js):
  79. cmpIgnoreStyleImpl(a, b)
  80. else:
  81. var i = 0
  82. var j = 0
  83. while true:
  84. while a[i] == '_': inc(i)
  85. while b[j] == '_': inc(j) # BUGFIX: typo
  86. var aa = toLowerAscii(a[i])
  87. var bb = toLowerAscii(b[j])
  88. result = ord(aa) - ord(bb)
  89. if result != 0 or aa == '\0': break
  90. inc(i)
  91. inc(j)
  92. func cmpIgnoreCase*(a, b: cstring): int {.rtl, extern: "csuCmpIgnoreCase".} =
  93. ## Compares two strings in a case insensitive manner. Returns:
  94. ## * 0 if `a == b`
  95. ## * < 0 if `a < b`
  96. ## * \> 0 if `a > b`
  97. runnableExamples:
  98. assert cmpIgnoreCase(cstring"hello", cstring"HeLLo") == 0
  99. assert cmpIgnoreCase(cstring"echo", cstring"hello") < 0
  100. assert cmpIgnoreCase(cstring"yellow", cstring"hello") > 0
  101. when nimvm:
  102. cmpIgnoreCaseImpl(a, b)
  103. else:
  104. when defined(js):
  105. cmpIgnoreCaseImpl(a, b)
  106. else:
  107. var i = 0
  108. while true:
  109. var aa = toLowerAscii(a[i])
  110. var bb = toLowerAscii(b[i])
  111. result = ord(aa) - ord(bb)
  112. if result != 0 or aa == '\0': break
  113. inc(i)