From c04f305bf791ee5ecfd17f5a40d009d9c6b6f07a Mon Sep 17 00:00:00 2001 From: flywind <43030857+xflywind@users.noreply.github.com> Date: Tue, 5 Jan 2021 10:52:26 -0600 Subject: make cstrutils work in VM (#16590) * make cstrutils work in VM * more --- lib/pure/cstrutils.nim | 180 ++++++++++++++++++++++++++----------------------- lib/pure/strutils.nim | 15 +---- 2 files changed, 98 insertions(+), 97 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/cstrutils.nim b/lib/pure/cstrutils.nim index 390aac00b..cdef7c804 100644 --- a/lib/pure/cstrutils.nim +++ b/lib/pure/cstrutils.nim @@ -16,93 +16,103 @@ import std/private/strimpl when defined(js): - func startsWith*(s, prefix: cstring): bool {.importjs: "#.startsWith(#)".} + func jsStartsWith(s, prefix: cstring): bool {.importjs: "#.startsWith(#)".} + func jsEndsWith(s, suffix: cstring): bool {.importjs: "#.endsWith(#)".} - func endsWith*(s, suffix: cstring): bool {.importjs: "#.endsWith(#)".} - func cmpIgnoreStyle*(a, b: cstring): int = - cmpIgnoreStyleImpl(a, b) - - func cmpIgnoreCase*(a, b: cstring): int = - cmpIgnoreCaseImpl(a, b) - - # JS string has more operations that might warrant its own module: - # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String -else: - func startsWith*(s, prefix: cstring): bool {.rtl, extern: "csuStartsWith".} = - ## Returns true if `s` starts with `prefix`. - ## - ## If `prefix == ""` true is returned. - ## - ## JS backend uses native `String.prototype.startsWith`. - runnableExamples: - assert startsWith(cstring"Hello, Nimion", cstring"Hello") - assert not startsWith(cstring"Hello, Nimion", cstring"Nimion") - - var i = 0 - while true: - if prefix[i] == '\0': return true - if s[i] != prefix[i]: return false - inc(i) +func startsWith*(s, prefix: cstring): bool {.rtl, extern: "csuStartsWith".} = + ## Returns true if `s` starts with `prefix`. + ## + ## JS backend uses native `String.prototype.startsWith`. + runnableExamples: + assert startsWith(cstring"Hello, Nimion", cstring"Hello") + assert not startsWith(cstring"Hello, Nimion", cstring"Nimion") + assert startsWith(cstring"Hello", cstring"") + when nimvm: + startsWithImpl(s, prefix) + else: + when defined(js): + result = jsStartsWith(s, prefix) + else: + var i = 0 + while true: + if prefix[i] == '\0': return true + if s[i] != prefix[i]: return false + inc(i) - func endsWith*(s, suffix: cstring): bool {.rtl, extern: "csuEndsWith".} = - ## Returns true if `s` ends with `suffix`. - ## - ## If `suffix == ""` true is returned. - ## - ## JS backend uses native `String.prototype.endsWith`. - runnableExamples: - assert endsWith(cstring"Hello, Nimion", cstring"Nimion") - assert not endsWith(cstring"Hello, Nimion", cstring"Hello") +func endsWith*(s, suffix: cstring): bool {.rtl, extern: "csuEndsWith".} = + ## Returns true if `s` ends with `suffix`. + ## + ## JS backend uses native `String.prototype.endsWith`. + runnableExamples: + assert endsWith(cstring"Hello, Nimion", cstring"Nimion") + assert not endsWith(cstring"Hello, Nimion", cstring"Hello") + assert endsWith(cstring"Hello", cstring"") + when nimvm: + endsWithImpl(s, suffix) + else: + when defined(js): + result = jsEndsWith(s, suffix) + else: + let slen = s.len + var i = 0 + var j = slen - len(suffix) + while i+j <% slen: + if s[i+j] != suffix[i]: return false + inc(i) + if suffix[i] == '\0': return true - let slen = s.len - var i = 0 - var j = slen - len(suffix) - while i+j <% slen: - if s[i+j] != suffix[i]: return false - inc(i) - if suffix[i] == '\0': return true - - func cmpIgnoreStyle*(a, b: cstring): int {.rtl, extern: "csuCmpIgnoreStyle".} = - ## Semantically the same as `cmp(normalize($a), normalize($b))`. It - ## is just optimized to not allocate temporary strings. This should - ## NOT be used to compare Nim identifier names. use `macros.eqIdent` - ## for that. Returns: - ## - ## .. code-block:: - ## 0 if a == b - ## < 0 if a < b - ## > 0 if a > b - runnableExamples: - assert cmpIgnoreStyle(cstring"hello", cstring"H_e_L_Lo") == 0 - var i = 0 - var j = 0 - while true: - while a[i] == '_': inc(i) - while b[j] == '_': inc(j) # BUGFIX: typo - var aa = toLowerAscii(a[i]) - var bb = toLowerAscii(b[j]) - result = ord(aa) - ord(bb) - if result != 0 or aa == '\0': break - inc(i) - inc(j) - - func cmpIgnoreCase*(a, b: cstring): int {.rtl, extern: "csuCmpIgnoreCase".} = - ## Compares two strings in a case insensitive manner. Returns: - ## - ## .. code-block:: - ## 0 if a == b - ## < 0 if a < b - ## > 0 if a > b - runnableExamples: - assert cmpIgnoreCase(cstring"hello", cstring"HeLLo") == 0 - assert cmpIgnoreCase(cstring"echo", cstring"hello") < 0 - assert cmpIgnoreCase(cstring"yellow", cstring"hello") > 0 +func cmpIgnoreStyle*(a, b: cstring): int {.rtl, extern: "csuCmpIgnoreStyle".} = + ## Semantically the same as `cmp(normalize($a), normalize($b))`. It + ## is just optimized to not allocate temporary strings. This should + ## NOT be used to compare Nim identifier names. use `macros.eqIdent` + ## for that. Returns: + ## + ## .. code-block:: + ## 0 if a == b + ## < 0 if a < b + ## > 0 if a > b + runnableExamples: + assert cmpIgnoreStyle(cstring"hello", cstring"H_e_L_Lo") == 0 + when nimvm: + cmpIgnoreStyleImpl(a, b) + else: + when defined(js): + cmpIgnoreStyleImpl(a, b) + else: + var i = 0 + var j = 0 + while true: + while a[i] == '_': inc(i) + while b[j] == '_': inc(j) # BUGFIX: typo + var aa = toLowerAscii(a[i]) + var bb = toLowerAscii(b[j]) + result = ord(aa) - ord(bb) + if result != 0 or aa == '\0': break + inc(i) + inc(j) - var i = 0 - while true: - var aa = toLowerAscii(a[i]) - var bb = toLowerAscii(b[i]) - result = ord(aa) - ord(bb) - if result != 0 or aa == '\0': break - inc(i) +func cmpIgnoreCase*(a, b: cstring): int {.rtl, extern: "csuCmpIgnoreCase".} = + ## Compares two strings in a case insensitive manner. Returns: + ## + ## .. code-block:: + ## 0 if a == b + ## < 0 if a < b + ## > 0 if a > b + runnableExamples: + assert cmpIgnoreCase(cstring"hello", cstring"HeLLo") == 0 + assert cmpIgnoreCase(cstring"echo", cstring"hello") < 0 + assert cmpIgnoreCase(cstring"yellow", cstring"hello") > 0 + when nimvm: + cmpIgnoreCaseImpl(a, b) + else: + when defined(js): + cmpIgnoreCaseImpl(a, b) + else: + var i = 0 + while true: + var aa = toLowerAscii(a[i]) + var bb = toLowerAscii(b[i]) + result = ord(aa) - ord(bb) + if result != 0 or aa == '\0': break + inc(i) diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index b1418a3ec..a25df9e42 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -81,7 +81,7 @@ when defined(nimVmExportFixed): include "system/inclrtl" import std/private/since -from std/private/strimpl import cmpIgnoreStyleImpl, cmpIgnoreCaseImpl +from std/private/strimpl import cmpIgnoreStyleImpl, cmpIgnoreCaseImpl, startsWithImpl, endsWithImpl const @@ -1530,11 +1530,7 @@ func startsWith*(s, prefix: string): bool {.rtl, extern: "nsuStartsWith".} = let a = "abracadabra" doAssert a.startsWith("abra") == true doAssert a.startsWith("bra") == false - var i = 0 - while true: - if i >= prefix.len: return true - if i >= s.len or s[i] != prefix[i]: return false - inc(i) + startsWithImpl(s, prefix) func endsWith*(s: string, suffix: char): bool {.inline.} = ## Returns true if `s` ends with `suffix`. @@ -1562,12 +1558,7 @@ func endsWith*(s, suffix: string): bool {.rtl, extern: "nsuEndsWith".} = let a = "abracadabra" doAssert a.endsWith("abra") == true doAssert a.endsWith("dab") == false - var i = 0 - var j = len(s) - len(suffix) - while i+j >= 0 and i+j < s.len: - if s[i+j] != suffix[i]: return false - inc(i) - if i >= suffix.len: return true + endsWithImpl(s, suffix) func continuesWith*(s, substr: string, start: Natural): bool {.rtl, extern: "nsuContinuesWith".} = -- cgit 1.4.1-2-gfad0