summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--doc/tut1.rst7
-rw-r--r--lib/pure/strutils.nim29
2 files changed, 32 insertions, 4 deletions
diff --git a/doc/tut1.rst b/doc/tut1.rst
index d2d6f8fe7..cca4e8c0e 100644
--- a/doc/tut1.rst
+++ b/doc/tut1.rst
@@ -67,6 +67,11 @@ aiming for your debugging pleasure. With `-d:release` some checks are
 `turned off and optimizations are turned on
 <nimc.html#compiler-usage-compileminustime-symbols>`_.
 
+For benchmarking or production code, use the `-d:release` switch.
+For comparing the performance with unsafe languages like C, use the `-d:danger` switch
+in order to get meaningful, comparable results. Otherwise Nim might be handicapped
+by checks that are **not even available** for C.
+
 Though it should be pretty obvious what the program does, I will explain the
 syntax: statements which are not indented are executed when the program
 starts. Indentation is Nim's way of grouping statements. Indentation is
@@ -626,7 +631,7 @@ Some terminology: in the example `question` is called a (formal) *parameter*,
 Result variable
 ---------------
 A procedure that returns a value has an implicit `result` variable declared
-that represents the return value. A `return` statement with no expression is 
+that represents the return value. A `return` statement with no expression is
 shorthand for `return result`. The `result` value is always returned
 automatically at the end of a procedure if there is no `return` statement at
 the exit.
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 3680b11de..bfd53a3a0 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -1826,6 +1826,9 @@ func find*(a: SkipTable, s, sub: string, start: Natural = 0, last = 0): int {.
 when not (defined(js) or defined(nimdoc) or defined(nimscript)):
   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>".}
+
   const hasCStringBuiltin = true
 else:
   const hasCStringBuiltin = false
@@ -1889,9 +1892,29 @@ func find*(s, sub: string, start: Natural = 0, last = 0): int {.rtl,
   ## * `replace func<#replace,string,string,string>`_
   if sub.len > s.len: return -1
   if sub.len == 1: return find(s, sub[0], start, last)
-  var a {.noinit.}: SkipTable
-  initSkipTable(a, sub)
-  result = find(a, s, sub, start, last)
+
+  template useSkipTable {.dirty.} =
+    var a {.noinit.}: SkipTable
+    initSkipTable(a, sub)
+    result = find(a, s, sub, start, last)
+
+  when not hasCStringBuiltin:
+    useSkipTable()
+  else:
+    when nimvm:
+      useSkipTable()
+    else:
+      when hasCStringBuiltin:
+        if last == 0 and s.len > start:
+          let found = c_strstr(s[start].unsafeAddr, sub)
+          if not found.isNil:
+            result = cast[ByteAddress](found) -% cast[ByteAddress](s.cstring)
+          else:
+            result = -1
+        else:
+          useSkipTable()
+      else:
+        useSkipTable()
 
 func rfind*(s: string, sub: char, start: Natural = 0, last = -1): int {.rtl,
     extern: "nsuRFindChar".} =