cstrutils.nim 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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. startsWithImpl(s, prefix)
  31. else:
  32. when defined(js):
  33. result = jsStartsWith(s, prefix)
  34. else:
  35. var i = 0
  36. while true:
  37. if prefix[i] == '\0': return true
  38. if s[i] != prefix[i]: return false
  39. inc(i)
  40. func endsWith*(s, suffix: cstring): bool {.rtl, extern: "csuEndsWith".} =
  41. ## Returns true if `s` ends with `suffix`.
  42. ##
  43. ## The JS backend uses the native `String.prototype.endsWith` function.
  44. runnableExamples:
  45. assert endsWith(cstring"Hello, Nimion", cstring"Nimion")
  46. assert not endsWith(cstring"Hello, Nimion", cstring"Hello")
  47. assert endsWith(cstring"Hello", cstring"")
  48. when nimvm:
  49. endsWithImpl(s, suffix)
  50. else:
  51. when defined(js):
  52. result = jsEndsWith(s, suffix)
  53. else:
  54. let slen = s.len
  55. var i = 0
  56. var j = slen - len(suffix)
  57. while i + j <% slen:
  58. if s[i + j] != suffix[i]: return false
  59. inc(i)
  60. if suffix[i] == '\0': return true
  61. func cmpIgnoreStyle*(a, b: cstring): int {.rtl, extern: "csuCmpIgnoreStyle".} =
  62. ## Semantically the same as `cmp(normalize($a), normalize($b))`. It
  63. ## is just optimized to not allocate temporary strings. This should
  64. ## NOT be used to compare Nim identifier names, use `macros.eqIdent`
  65. ## for that. Returns:
  66. ## * 0 if `a == b`
  67. ## * < 0 if `a < b`
  68. ## * \> 0 if `a > b`
  69. runnableExamples:
  70. assert cmpIgnoreStyle(cstring"hello", cstring"H_e_L_Lo") == 0
  71. when nimvm:
  72. cmpIgnoreStyleImpl(a, b)
  73. else:
  74. when defined(js):
  75. cmpIgnoreStyleImpl(a, b)
  76. else:
  77. var i = 0
  78. var j = 0
  79. while true:
  80. while a[i] == '_': inc(i)
  81. while b[j] == '_': inc(j) # BUGFIX: typo
  82. var aa = toLowerAscii(a[i])
  83. var bb = toLowerAscii(b[j])
  84. result = ord(aa) - ord(bb)
  85. if result != 0 or aa == '\0': break
  86. inc(i)
  87. inc(j)
  88. func cmpIgnoreCase*(a, b: cstring): int {.rtl, extern: "csuCmpIgnoreCase".} =
  89. ## Compares two strings in a case insensitive manner. Returns:
  90. ## * 0 if `a == b`
  91. ## * < 0 if `a < b`
  92. ## * \> 0 if `a > b`
  93. runnableExamples:
  94. assert cmpIgnoreCase(cstring"hello", cstring"HeLLo") == 0
  95. assert cmpIgnoreCase(cstring"echo", cstring"hello") < 0
  96. assert cmpIgnoreCase(cstring"yellow", cstring"hello") > 0
  97. when nimvm:
  98. cmpIgnoreCaseImpl(a, b)
  99. else:
  100. when defined(js):
  101. cmpIgnoreCaseImpl(a, b)
  102. else:
  103. var i = 0
  104. while true:
  105. var aa = toLowerAscii(a[i])
  106. var bb = toLowerAscii(b[i])
  107. result = ord(aa) - ord(bb)
  108. if result != 0 or aa == '\0': break
  109. inc(i)