diff --git a/core/api/kotlinx-io-core.api b/core/api/kotlinx-io-core.api index e28bc59cd..25b6fa3a0 100644 --- a/core/api/kotlinx-io-core.api +++ b/core/api/kotlinx-io-core.api @@ -91,6 +91,7 @@ public abstract interface annotation class kotlinx/io/InternalIoApi : java/lang/ public final class kotlinx/io/JvmCoreKt { public static final fun asSink (Ljava/io/OutputStream;)Lkotlinx/io/RawSink; public static final fun asSource (Ljava/io/InputStream;)Lkotlinx/io/RawSource; + public static final fun getSystemLineSeparator ()Ljava/lang/String; } public abstract interface class kotlinx/io/RawSink : java/io/Flushable, java/lang/AutoCloseable { diff --git a/core/api/kotlinx-io-core.klib.api b/core/api/kotlinx-io-core.klib.api index 02d9050a7..c3e48dc9c 100644 --- a/core/api/kotlinx-io-core.klib.api +++ b/core/api/kotlinx-io-core.klib.api @@ -233,6 +233,8 @@ final val kotlinx.io.unsafe/SegmentReadContextImpl // kotlinx.io.unsafe/SegmentR final fun (): kotlinx.io.unsafe/SegmentReadContext // kotlinx.io.unsafe/SegmentReadContextImpl.|(){}[0] final val kotlinx.io.unsafe/SegmentWriteContextImpl // kotlinx.io.unsafe/SegmentWriteContextImpl|{}SegmentWriteContextImpl[0] final fun (): kotlinx.io.unsafe/SegmentWriteContext // kotlinx.io.unsafe/SegmentWriteContextImpl.|(){}[0] +final val kotlinx.io/SystemLineSeparator // kotlinx.io/SystemLineSeparator|{}SystemLineSeparator[0] + final fun (): kotlin/String // kotlinx.io/SystemLineSeparator.|(){}[0] final fun (kotlinx.io.files/Path).kotlinx.io.files/sink(): kotlinx.io/Sink // kotlinx.io.files/sink|sink@kotlinx.io.files.Path(){}[0] final fun (kotlinx.io.files/Path).kotlinx.io.files/source(): kotlinx.io/Source // kotlinx.io.files/source|source@kotlinx.io.files.Path(){}[0] diff --git a/core/apple/src/-PlatformApple.kt b/core/apple/src/-PlatformApple.kt new file mode 100644 index 000000000..1686fb31d --- /dev/null +++ b/core/apple/src/-PlatformApple.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2025 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file. + */ + +package kotlinx.io + +/** + * Sequence of characters used as a line separator by the underlying platform. + * + * The value of this property is always `"\n"`. + */ +public actual val SystemLineSeparator: String = "\n" diff --git a/core/common/src/Core.kt b/core/common/src/Core.kt index be72be491..05977a5c9 100644 --- a/core/common/src/Core.kt +++ b/core/common/src/Core.kt @@ -43,3 +43,12 @@ private class DiscardingSink : RawSink { override fun flush() {} override fun close() {} } + +/** + * Sequence of characters used as a line separator by the underlying platform. + * + * The value of this property is platform-specific, but usually it is either `"\n"` or `"\r\n"`. + * + * See the documentation for a particular platform to get more information about the value of this property. + */ +public expect val SystemLineSeparator: String diff --git a/core/common/test/LineSeparatorTest.kt b/core/common/test/LineSeparatorTest.kt new file mode 100644 index 000000000..1d3b4a75f --- /dev/null +++ b/core/common/test/LineSeparatorTest.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2025 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file. + */ + +package kotlinx.io + +import kotlinx.io.files.isWindows +import kotlin.test.Test +import kotlin.test.assertEquals + +class LineSeparatorTest { + @Test + public fun testLineSeparator() { + if (isWindows) { + assertEquals("\r\n", SystemLineSeparator) + } else { + assertEquals("\n", SystemLineSeparator) + } + } +} diff --git a/core/js/src/-PlatformJs.kt b/core/js/src/-PlatformJs.kt index 7e198e25c..a21af1c69 100644 --- a/core/js/src/-PlatformJs.kt +++ b/core/js/src/-PlatformJs.kt @@ -5,6 +5,8 @@ package kotlinx.io +import kotlinx.io.node.os + public actual open class IOException : Exception { public actual constructor() : super() @@ -31,3 +33,17 @@ internal actual fun withCaughtException(block: () -> Unit): Throwable? { return t } } + +/** + * Sequence of characters used as a line separator by the underlying platform. + * + * In NodeJS-compatible environments, this property derives value from [os.EOL](https://nodejs.org/api/os.html#oseol), + * in all other environments (like a web-browser), its value is always `"\n"`. + */ +public actual val SystemLineSeparator: String by lazy { + try { + os.EOL + } catch (_: Throwable) { + "\r\n" + } +} diff --git a/core/jvm/src/JvmCore.kt b/core/jvm/src/JvmCore.kt index e714f7740..a556c8916 100644 --- a/core/jvm/src/JvmCore.kt +++ b/core/jvm/src/JvmCore.kt @@ -109,3 +109,10 @@ internal val AssertionError.isAndroidGetsocknameError: Boolean get() { return cause != null && message?.contains("getsockname failed") ?: false } + +/** + * Sequence of characters used as a line separator by the underlying platform. + * + * Returns the same value as [System.lineSeparator]. + */ +public actual val SystemLineSeparator: String = System.lineSeparator() diff --git a/core/mingw/src/-PlatformMingw.kt b/core/mingw/src/-PlatformMingw.kt new file mode 100644 index 000000000..c1ab9e3c7 --- /dev/null +++ b/core/mingw/src/-PlatformMingw.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2025 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file. + */ + +package kotlinx.io + +/** + * Sequence of characters used as a line separator by the underlying platform. + * + * The value of this property is always `"\r\n"`. + */ +public actual val SystemLineSeparator: String = "\r\n" diff --git a/core/nodeFilesystemShared/src/node/os.kt b/core/nodeFilesystemShared/src/node/os.kt index 431d60a8f..6a55a0691 100644 --- a/core/nodeFilesystemShared/src/node/os.kt +++ b/core/nodeFilesystemShared/src/node/os.kt @@ -16,6 +16,11 @@ internal external interface Os { * See https://nodejs.org/api/os.html#osplatform */ fun platform(): String + + /** + * See https://nodejs.org/api/os.html#oseol + */ + val EOL: String } internal expect val os: Os diff --git a/core/unix/src/-PlatformUnix.kt b/core/unix/src/-PlatformUnix.kt new file mode 100644 index 000000000..1686fb31d --- /dev/null +++ b/core/unix/src/-PlatformUnix.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2025 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file. + */ + +package kotlinx.io + +/** + * Sequence of characters used as a line separator by the underlying platform. + * + * The value of this property is always `"\n"`. + */ +public actual val SystemLineSeparator: String = "\n" diff --git a/core/wasmJs/src/-PlatformWasmJs.kt b/core/wasmJs/src/-PlatformWasmJs.kt index d93280360..9d71dd0aa 100644 --- a/core/wasmJs/src/-PlatformWasmJs.kt +++ b/core/wasmJs/src/-PlatformWasmJs.kt @@ -5,6 +5,8 @@ package kotlinx.io +import kotlinx.io.node.os + internal class JsException(message: String) : RuntimeException(message) internal actual fun withCaughtException(block: () -> Unit): Throwable? { @@ -23,3 +25,16 @@ private fun catchJsThrowable(block: () -> Unit): JsAny? = js("""{ } }""") +/** + * Sequence of characters used as a line separator by the underlying platform. + * + * In NodeJS-compatible environments, this property derives value from [os.EOL](https://nodejs.org/api/os.html#oseol), + * in all other environments (like a web-browser), its value is always `"\n"`. + */ +public actual val SystemLineSeparator: String by lazy { + try { + os.EOL + } catch (_: Throwable) { + "\n" + } +} diff --git a/core/wasmWasi/src/-PlatformWasmWasi.kt b/core/wasmWasi/src/-PlatformWasmWasi.kt new file mode 100644 index 000000000..1686fb31d --- /dev/null +++ b/core/wasmWasi/src/-PlatformWasmWasi.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2025 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file. + */ + +package kotlinx.io + +/** + * Sequence of characters used as a line separator by the underlying platform. + * + * The value of this property is always `"\n"`. + */ +public actual val SystemLineSeparator: String = "\n"