summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/std/private/ospaths2.nim21
-rw-r--r--tests/stdlib/tos.nim32
2 files changed, 49 insertions, 4 deletions
diff --git a/lib/std/private/ospaths2.nim b/lib/std/private/ospaths2.nim
index 612003023..18a01b104 100644
--- a/lib/std/private/ospaths2.nim
+++ b/lib/std/private/ospaths2.nim
@@ -584,15 +584,28 @@ proc searchExtPos*(path: string): int =
     assert searchExtPos("c.nim") == 1
     assert searchExtPos("a/b/c.nim") == 5
     assert searchExtPos("a.b.c.nim") == 5
+    assert searchExtPos(".nim") == -1
+    assert searchExtPos("..nim") == -1
+    assert searchExtPos("a..nim") == 2
 
-  # BUGFIX: do not search until 0! .DS_Store is no file extension!
+  # Unless there is any char that is not `ExtSep` before last `ExtSep` in the file name,
+  # it is not a file extension.
+  const DirSeps = when doslikeFileSystem: {DirSep, AltSep, ':'} else: {DirSep, AltSep}
   result = -1
-  for i in countdown(len(path)-1, 1):
+  var i = path.high
+  while i >= 1:
     if path[i] == ExtSep:
+      break
+    elif path[i] in DirSeps:
+      return -1 # do not skip over path
+    dec i
+
+  for j in countdown(i - 1, 0):
+    if path[j] in DirSeps:
+      return -1
+    elif path[j] != ExtSep:
       result = i
       break
-    elif path[i] in {DirSep, AltSep}:
-      break # do not skip over path
 
 proc splitFile*(path: string): tuple[dir, name, ext: string] {.
   noSideEffect, rtl, extern: "nos$1".} =
diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim
index c2822d270..ad34e479a 100644
--- a/tests/stdlib/tos.nim
+++ b/tests/stdlib/tos.nim
@@ -830,3 +830,35 @@ block:  # isValidFilename
   doAssert isValidFilename("ux.bat")
   doAssert isValidFilename("nim.nim")
   doAssert isValidFilename("foo.log")
+
+block: # searchExtPos
+  doAssert "foo.nim".searchExtPos == 3
+  doAssert "/foo.nim".searchExtPos == 4
+  doAssert "".searchExtPos == -1
+  doAssert "/".searchExtPos == -1
+  doAssert "a.b/foo".searchExtPos == -1
+  doAssert ".".searchExtPos == -1
+  doAssert "foo.".searchExtPos == 3
+  doAssert "foo..".searchExtPos == 4
+  doAssert "..".searchExtPos == -1
+  doAssert "...".searchExtPos == -1
+  doAssert "./".searchExtPos == -1
+  doAssert "../".searchExtPos == -1
+  doAssert "/.".searchExtPos == -1
+  doAssert "/..".searchExtPos == -1
+  doAssert ".b".searchExtPos == -1
+  doAssert "..b".searchExtPos == -1
+  doAssert "/.b".searchExtPos == -1
+  doAssert "a/.b".searchExtPos == -1
+  doAssert ".a.b".searchExtPos == 2
+  doAssert "a/.b.c".searchExtPos == 4
+  doAssert "a/..b".searchExtPos == -1
+  doAssert "a/b..c".searchExtPos == 4
+
+  when doslikeFileSystem:
+    doAssert "c:a.b".searchExtPos == 3
+    doAssert "c:.a".searchExtPos == -1
+    doAssert r"c:\.a".searchExtPos == -1
+    doAssert "c:..a".searchExtPos == -1
+    doAssert r"c:\..a".searchExtPos == -1
+    doAssert "c:.a.b".searchExtPos == 4