Skip to content

Commit 9a2e4f1

Browse files
committed
Moved all path trimming routines to the common source set
1 parent 7ba8c40 commit 9a2e4f1

File tree

21 files changed

+84
-101
lines changed

21 files changed

+84
-101
lines changed

core/apple/src/files/FileSystemApple.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,3 @@ internal actual fun realpathImpl(path: String): String {
5555
free(res)
5656
}
5757
}
58-
59-
internal actual fun removeTrailingSeparators(path: String): String {
60-
return removeTrailingSeparators(path, SystemPathSeparator)
61-
}

core/common/src/files/FileSystem.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,5 @@ public expect class FileNotFoundException(message: String?) : IOException
184184

185185
internal const val WindowsPathSeparator: Char = '\\'
186186
internal const val UnixPathSeparator: Char = '/'
187+
188+
internal expect val isWindows: Boolean

core/common/src/files/Paths.kt

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,20 +129,46 @@ public fun Path.source(): Source = SystemFileSystem.source(this).buffered()
129129
@JvmName("sinkDeprecated")
130130
public fun Path.sink(): Sink = SystemFileSystem.sink(this).buffered()
131131

132-
internal fun removeTrailingSeparators(path: String, sep: Char): String {
132+
internal fun removeTrailingSeparators(path: String, /* only for testing */ isWindows_: Boolean = isWindows): String {
133+
if (isWindows_) {
134+
// don't trim the path separator right after the drive name
135+
val limit = if (path.length > 1) {
136+
if (path[1] == ':') {
137+
3
138+
} else if (isUnc(path)) {
139+
2
140+
} else {
141+
1
142+
}
143+
} else {
144+
1
145+
}
146+
return removeTrailingSeparatorsWindws(limit, path)
147+
}
148+
return removeTrailingSeparatorsUnix(path)
149+
}
150+
151+
private fun isUnc(path: String): Boolean {
152+
if (path.length < 2) return false
153+
if (path.startsWith("$WindowsPathSeparator$WindowsPathSeparator")) return true
154+
if (path.startsWith("$UnixPathSeparator$UnixPathSeparator")) return true
155+
return false
156+
}
157+
158+
private fun removeTrailingSeparatorsUnix(path: String): String {
133159
var idx = path.length
134-
while (idx > 1 && path[idx - 1] == sep) {
160+
while (idx > 1 && path[idx - 1] == UnixPathSeparator) {
135161
idx--
136162
}
137163
return path.substring(0, idx)
138164
}
139165

140-
internal fun removeTrailingSeparators(suffixLength: Int, path: String, sep1: Char, sep2: Char): String {
166+
private fun removeTrailingSeparatorsWindws(suffixLength: Int, path: String): String {
141167
require(suffixLength >= 1)
142168
var idx = path.length
143169
while (idx > suffixLength) {
144170
val c = path[idx - 1]
145-
if (c != sep1 && c != sep2) break
171+
if (c != WindowsPathSeparator && c != UnixPathSeparator) break
146172
idx--
147173
}
148174
return path.substring(0, idx)

core/common/test/files/SmokeFileTestWindows.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
package kotlinx.io.files
77

8-
import kotlinx.io.isWindows
98
import kotlin.test.*
109

1110
class SmokeFileTestWindows {

core/common/test/files/UtilsTest.kt

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,47 @@ import kotlin.test.Test
99
import kotlin.test.assertEquals
1010

1111
class UtilsTest {
12+
private fun removeTrailingSeparatorsU(path: String): String = removeTrailingSeparators(path, false)
13+
private fun removeTrailingSeparatorsW(path: String): String = removeTrailingSeparators(path, true)
14+
15+
1216
@Test
13-
fun testPathTrimming() {
14-
assertEquals("", removeTrailingSeparators("", ' '))
15-
assertEquals("/", removeTrailingSeparators("/", '/'))
16-
assertEquals("///", removeTrailingSeparators("///", '\\'))
17-
assertEquals("/", removeTrailingSeparators("///", '/'))
18-
assertEquals("/a", removeTrailingSeparators("/a/", '/'))
19-
assertEquals("// ", removeTrailingSeparators("// ", '/'))
20-
21-
assertEquals("", removeTrailingSeparators(1, "", '/', '\\'))
22-
assertEquals("/", removeTrailingSeparators(1, "/", '/', '\\'))
23-
assertEquals("\\", removeTrailingSeparators(1, "\\", '/', '\\'))
24-
assertEquals("a", removeTrailingSeparators(1, "a//\\////\\\\//\\/\\", '/', '\\'))
25-
assertEquals("/\\/ ", removeTrailingSeparators(1,"/\\/ ", '\\', '/'))
26-
27-
assertEquals("", removeTrailingSeparators(1000, "", '/', '\\'))
28-
assertEquals("C:\\", removeTrailingSeparators(3, "C:\\", '/', '\\'))
29-
assertEquals("C:\\", removeTrailingSeparators(3, "C:\\/\\", '/', '\\'))
17+
fun testPathTrimmingUnix() {
18+
assertEquals("", removeTrailingSeparatorsU(""))
19+
assertEquals("/", removeTrailingSeparatorsU("/"))
20+
assertEquals("/", removeTrailingSeparatorsU("//"))
21+
assertEquals("// ", removeTrailingSeparatorsU("// "))
22+
assertEquals("/", removeTrailingSeparatorsU("///"))
23+
assertEquals("@@@", removeTrailingSeparatorsU("@@@"))
24+
assertEquals("/a", removeTrailingSeparatorsU("/a/"))
25+
assertEquals("\\", removeTrailingSeparatorsU("\\"))
26+
assertEquals("\\\\", removeTrailingSeparatorsU("\\\\"))
27+
assertEquals("\\a\\", removeTrailingSeparatorsU("\\a\\"))
28+
assertEquals("/\\/ ", removeTrailingSeparatorsU("/\\/ "))
29+
30+
assertEquals("a//\\////\\\\//\\/\\", removeTrailingSeparatorsU("a//\\////\\\\//\\/\\"))
31+
assertEquals("C:\\", removeTrailingSeparatorsU("C:\\"))
32+
assertEquals("C:\\/\\", removeTrailingSeparatorsU("C:\\/\\"))
33+
}
34+
35+
@Test
36+
fun testPathTrimmingWindows() {
37+
assertEquals("", removeTrailingSeparatorsW(""))
38+
assertEquals("/", removeTrailingSeparatorsW("/"))
39+
assertEquals("//", removeTrailingSeparatorsW("//"))
40+
assertEquals("// ", removeTrailingSeparatorsW("// "))
41+
assertEquals("//", removeTrailingSeparatorsW("///"))
42+
assertEquals("@@@", removeTrailingSeparatorsW("@@@"))
43+
assertEquals("/a", removeTrailingSeparatorsW("/a/"))
44+
assertEquals("\\", removeTrailingSeparatorsW("\\"))
45+
assertEquals("\\\\", removeTrailingSeparatorsW("\\\\"))
46+
assertEquals("\\a", removeTrailingSeparatorsW("\\a\\"))
47+
assertEquals("\\a", removeTrailingSeparatorsW("\\a\\\\"))
48+
assertEquals("/\\/ ", removeTrailingSeparatorsW("/\\/ "))
49+
50+
assertEquals("a", removeTrailingSeparatorsW("a//\\////\\\\//\\/\\"))
51+
assertEquals("C:a", removeTrailingSeparatorsW("C:a//\\////\\\\//\\/\\"))
52+
assertEquals("C:\\", removeTrailingSeparatorsW("C:\\"))
53+
assertEquals("C:\\", removeTrailingSeparatorsW("C:\\/\\"))
3054
}
3155
}

core/common/test/util.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,3 @@ fun Char.repeat(count: Int): String {
7171
fun assertArrayEquals(a: ByteArray, b: ByteArray) {
7272
assertEquals(a.contentToString(), b.contentToString())
7373
}
74-
75-
expect val isWindows: Boolean

core/js/src/-PlatfromJs.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,3 @@ public actual open class IOException actual constructor(
2121
public actual open class EOFException actual constructor(message: String?) : IOException(message) {
2222
public actual constructor() : this(null)
2323
}
24-
25-
internal val isWindows_ = os.platform() == "win32"

core/js/src/files/FileSystemJs.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66
package kotlinx.io.files
77

88
import kotlinx.io.*
9-
import kotlinx.io.buffer
10-
import kotlinx.io.fs
11-
import kotlinx.io.os
129

1310
public actual val SystemFileSystem: FileSystem = object : SystemFileSystemImpl() {
1411
override fun exists(path: Path): Boolean {
@@ -115,3 +112,5 @@ public actual val SystemTemporaryDirectory: Path
115112
public actual open class FileNotFoundException actual constructor(
116113
message: String?,
117114
) : IOException(message)
115+
116+
internal actual val isWindows = os.platform() == "win32"

core/js/src/files/PathsJs.kt

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public actual class Path internal constructor(
1717
get() {
1818
check(pathLib !== null) { "Path module not found" }
1919
if (path.isEmpty()) return null
20-
if (isWindows_) {
20+
if (isWindows) {
2121
if (!path.contains(UnixPathSeparator) && !path.contains(WindowsPathSeparator)) {
2222
return null
2323
}
@@ -151,29 +151,3 @@ internal class FileSink(private val path: Path, private var append: Boolean) : R
151151
closed = true
152152
}
153153
}
154-
155-
private fun isUnc(path: String): Boolean {
156-
if (path.length < 2) return false
157-
if (path.startsWith("$WindowsPathSeparator$WindowsPathSeparator")) return true
158-
if (path.startsWith("$UnixPathSeparator$UnixPathSeparator")) return true
159-
return false
160-
}
161-
162-
internal fun removeTrailingSeparators(path: String): String {
163-
if (isWindows_) {
164-
// don't trim the path separator right after the drive name
165-
val limit = if (path.length > 1) {
166-
if (path[1] == ':') {
167-
3
168-
} else if (isUnc(path)) {
169-
2
170-
} else {
171-
1
172-
}
173-
} else {
174-
1
175-
}
176-
return removeTrailingSeparators(limit, path, UnixPathSeparator, WindowsPathSeparator)
177-
}
178-
return removeTrailingSeparators(path, SystemPathSeparator)
179-
}

core/js/test/files/SmokeFileTestWindowsJS.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
package kotlinx.io.files
77

8-
import kotlinx.io.isWindows
98
import kotlin.test.Test
109
import kotlin.test.assertEquals
1110
import kotlin.test.assertNull

core/js/test/utils.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,3 @@ actual fun tempFileName(): String {
4747
return fullpath
4848
}
4949
}
50-
51-
actual val isWindows: Boolean = isWindows_

core/jvm/src/files/FileSystemJvm.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,5 @@ public actual val SystemFileSystem: FileSystem = object : SystemFileSystemImpl()
102102
public actual val SystemTemporaryDirectory: Path = Path(System.getProperty("java.io.tmpdir"))
103103

104104
public actual typealias FileNotFoundException = java.io.FileNotFoundException
105+
106+
internal actual val isWindows: Boolean = System.getProperty("os.name")?.startsWith("Windows") ?: false

core/jvm/test/files/SmokeFileTestWindowsJVM.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
package kotlinx.io.files
77

8-
import kotlinx.io.isWindows
98
import kotlin.test.Test
109
import kotlin.test.assertEquals
1110

core/jvm/test/utilJVM.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,3 @@ actual fun tempFileName(): String {
2424
fun assertByteArrayEquals(expectedUtf8: String, b: ByteArray) {
2525
assertEquals(expectedUtf8, b.toString(Charsets.UTF_8))
2626
}
27-
28-
actual val isWindows: Boolean = System.getProperty("os.name")?.startsWith("Windows") ?: false

core/mingw/src/files/FileSystemMingw.kt

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -60,26 +60,3 @@ internal actual fun realpathImpl(path: String): String {
6060
return buffer.toKString()
6161
}
6262
}
63-
64-
private fun isUnc(path: String): Boolean {
65-
if (path.length < 2) return false
66-
if (path.startsWith("$WindowsPathSeparator$WindowsPathSeparator")) return true
67-
if (path.startsWith("$SystemPathSeparator$SystemPathSeparator")) return true
68-
return false
69-
}
70-
71-
internal actual fun removeTrailingSeparators(path: String): String {
72-
// Don't trim path separator following the drive name
73-
val limit = if (path.length > 1) {
74-
if (path[1] == ':') {
75-
3
76-
} else if (isUnc(path)) {
77-
2
78-
} else {
79-
1
80-
}
81-
} else {
82-
1
83-
}
84-
return removeTrailingSeparators(limit, path, WindowsPathSeparator, SystemPathSeparator)
85-
}

core/native/src/files/FileSystemNative.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import kotlinx.io.IOException
1010
import kotlinx.io.RawSink
1111
import kotlinx.io.RawSource
1212
import platform.posix.*
13+
import kotlin.experimental.ExperimentalNativeApi
1314

1415
@OptIn(ExperimentalForeignApi::class)
1516
public actual val SystemFileSystem: FileSystem = object : SystemFileSystemImpl() {
@@ -115,3 +116,6 @@ public actual open class FileNotFoundException actual constructor(
115116

116117
// 777 in octal, rwx for all (owner, group and others).
117118
internal const val PermissionAllowAll: UShort = 511u
119+
120+
@OptIn(ExperimentalNativeApi::class)
121+
internal actual val isWindows: Boolean = Platform.osFamily == OsFamily.WINDOWS

core/native/src/files/PathsNative.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ internal expect fun basenameImpl(path: String): String
6262

6363
internal expect fun isAbsoluteImpl(path: String): Boolean
6464

65-
internal expect fun removeTrailingSeparators(path: String): String
66-
6765
public actual fun Path(path: String): Path = Path(path, null)
6866

6967
internal class FileSource(

core/native/test/util.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import kotlinx.cinterop.UnsafeNumber
1111
import kotlinx.io.files.SystemTemporaryDirectory
1212
import platform.posix.F_OK
1313
import platform.posix.access
14-
import kotlin.experimental.ExperimentalNativeApi
1514
import kotlin.random.Random
1615

1716
@OptIn(UnsafeNumber::class, ExperimentalStdlibApi::class)
@@ -26,6 +25,3 @@ actual fun tempFileName(): String {
2625
}
2726
throw IOException("Failed to generate temp file name")
2827
}
29-
30-
@OptIn(ExperimentalNativeApi::class)
31-
actual val isWindows: Boolean = Platform.osFamily == OsFamily.WINDOWS

core/unix/src/files/FileSystemUnix.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,3 @@ internal actual fun mkdirImpl(path: String) {
3434
throw IOException("mkdir failed: ${strerror(errno)?.toKString()}")
3535
}
3636
}
37-
38-
internal actual fun removeTrailingSeparators(path: String): String {
39-
return removeTrailingSeparators(path, SystemPathSeparator)
40-
}

core/wasm/src/files/FileSystemWasm.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,5 @@ public actual val SystemFileSystem: FileSystem = object : SystemFileSystemImpl()
3636
public actual open class FileNotFoundException actual constructor(
3737
message: String?,
3838
) : IOException(message)
39+
40+
internal actual val isWindows: Boolean = false

core/wasm/test/utils.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,3 @@ package kotlinx.io
88
import kotlinx.io.files.unsupported
99

1010
actual fun tempFileName(): String = unsupported()
11-
12-
actual val isWindows: Boolean = false

0 commit comments

Comments
 (0)