Introduce Common readln() and readlnOrNull() top-level functions #KT-48456

This commit is contained in:
Abduqodiri Qurbonzoda
2021-09-05 15:31:11 +00:00
committed by Space
parent 14b66872b5
commit 97eb28144f
37 changed files with 271 additions and 6 deletions
@@ -0,0 +1,2 @@
runtime/basic/readln*CR*.in binary
runtime/basic/readln*CR*.out binary
@@ -727,6 +727,61 @@ standaloneTest("hello2") {
source = "runtime/basic/hello2.kt"
}
standaloneTest("readlnOrNull_empty") {
useGoldenData = true
useTestData = true
source = "runtime/basic/readlnOrNull_empty.kt"
}
standaloneTest("readln_empty") {
useTestData = true
outputChecker = { s -> s.contains("ReadAfterEOFException") }
expectedExitStatusChecker = { it != 0 }
source = "runtime/basic/readln_empty.kt"
}
standaloneTest("readln_alone_CR") {
useGoldenData = true
useTestData = true
source = "runtime/basic/readln_alone_CR.kt"
}
standaloneTest("readln_empty_new_line") {
useGoldenData = true
useTestData = true
source = "runtime/basic/readln_empty_new_line.kt"
}
standaloneTest("readln_multiline") {
useGoldenData = true
useTestData = true
source = "runtime/basic/readln_multiline.kt"
}
standaloneTest("readln_CR_and_CRLF") {
useGoldenData = true
useTestData = true
source = "runtime/basic/readln_CR_and_CRLF.kt"
}
standaloneTest("readln_long_line") {
useGoldenData = true
useTestData = true
source = "runtime/basic/readln_long_line.kt"
}
standaloneTest("readln_cyrillic") {
useGoldenData = true
useTestData = true
source = "runtime/basic/readln_cyrillic.kt"
}
standaloneTest("readln_multiple_empty_new_lines") {
useGoldenData = true
useTestData = true
source = "runtime/basic/readln_multiple_empty_new_lines.kt"
}
task hello3(type: KonanLocalTest) {
useGoldenData = true
source = "runtime/basic/hello3.kt"
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
fun main() {
print("${readlnOrNull()}/${readlnOrNull()}/${readlnOrNull()}")
}
@@ -0,0 +1 @@
null/null/null
@@ -0,0 +1,2 @@
aaaaaa bbb
c
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
fun main() {
print(readln())
}
@@ -0,0 +1 @@
aaaaaa bbb
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
fun main() {
print(readln())
}
@@ -0,0 +1 @@
Привет!
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
fun main() {
print(readln())
}
@@ -0,0 +1 @@
Привет!
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
fun main() {
readln()
}
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
fun main() {
print(readln())
}
@@ -0,0 +1 @@
A very long line of input with length of more than initial buffer size
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
fun main() {
print(readln())
}
@@ -0,0 +1 @@
A very long line of input with length of more than initial buffer size
@@ -0,0 +1,3 @@
Hello World
Second line
Third line
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
fun main() {
print(readln())
}
@@ -0,0 +1 @@
Hello World
@@ -0,0 +1,4 @@
first
second
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
fun main() {
print("${readln()}/${readln()}/${readln()}/${readln()}/${readlnOrNull()}")
}
@@ -0,0 +1 @@
first/second///null
@@ -13,6 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cstdio>
#include "KAssert.h"
#include "Memory.h"
#include "Natives.h"
@@ -67,4 +69,35 @@ OBJ_GETTER0(Kotlin_io_Console_readLine) {
RETURN_RESULT_OF(CreateStringFromCString, data);
}
OBJ_GETTER0(Kotlin_io_Console_readlnOrNull) {
KStdVector<char> data;
data.reserve(16);
bool isEOF = false;
bool isError = false;
{
kotlin::ThreadStateGuard guard(kotlin::ThreadState::kNative);
while (true) {
int result = fgetc(stdin);
if (result == EOF || result == '\n') {
isEOF = (result == EOF);
isError = (ferror(stdin) != 0);
break;
}
data.push_back(result);
}
}
if (isError) {
ThrowIllegalStateException();
}
if (!isEOF && !data.empty() && data.back() == '\r') { // CRLF
data.pop_back();
}
if (data.empty() && isEOF) {
RETURN_OBJ(nullptr);
}
RETURN_RESULT_OF(StringFromUtf8Buffer, data.data(), data.size());
}
} // extern "C"
@@ -29,6 +29,29 @@ public actual fun println(message: Any?) {
@GCUnsafeCall("Kotlin_io_Console_println0")
public actual external fun println()
/**
* Reads a line of input from the standard input stream and returns it,
* or throws a [RuntimeException] if EOF has already been reached when [readln] is called.
*
* LF or CRLF is treated as the line terminator. Line terminator is not included in the returned string.
*
* The input is interpreted as UTF-8. Invalid bytes are replaced by the replacement character '\uFFFD'.
*/
@SinceKotlin("1.6")
public actual fun readln(): String = readlnOrNull() ?: throw ReadAfterEOFException("EOF has already been reached")
/**
* Reads a line of input from the standard input stream and returns it,
* or return `null` if EOF has already been reached when [readlnOrNull] is called.
*
* LF or CRLF is treated as the line terminator. Line terminator is not included in the returned string.
*
* The input is interpreted as UTF-8. Invalid bytes are replaced by the replacement character '\uFFFD'.
*/
@SinceKotlin("1.6")
@GCUnsafeCall("Kotlin_io_Console_readlnOrNull")
public actual external fun readlnOrNull(): String?
/**
* Reads a line of input from the standard input stream.
*
+7 -1
View File
@@ -2,4 +2,10 @@ public fun print(message: kotlin.Any?): kotlin.Unit
public fun println(): kotlin.Unit
public fun println(message: kotlin.Any?): kotlin.Unit
public fun println(message: kotlin.Any?): kotlin.Unit
@kotlin.SinceKotlin(version = "1.6")
public fun readln(): kotlin.String
@kotlin.SinceKotlin(version = "1.6")
public fun readlnOrNull(): kotlin.String?
+7 -1
View File
@@ -2,4 +2,10 @@ public fun print(message: kotlin.Any?): kotlin.Unit
public fun println(): kotlin.Unit
public fun println(message: kotlin.Any?): kotlin.Unit
public fun println(message: kotlin.Any?): kotlin.Unit
@kotlin.SinceKotlin(version = "1.6")
public fun readln(): kotlin.String
@kotlin.SinceKotlin(version = "1.6")
public fun readlnOrNull(): kotlin.String?
+24
View File
@@ -15,5 +15,29 @@ public expect fun println(message: Any?)
/** Prints the given [message] to the standard output stream. */
public expect fun print(message: Any?)
/**
* Reads a line of input from the standard input stream and returns it,
* or throws a [RuntimeException] if EOF has already been reached when [readln] is called.
*
* LF or CRLF is treated as the line terminator. Line terminator is not included in the returned string.
*
* Currently this function is not supported in Kotlin/JS and throws [UnsupportedOperationException].
*/
@SinceKotlin("1.6")
public expect fun readln(): String
/**
* Reads a line of input from the standard input stream and returns it,
* or return `null` if EOF has already been reached when [readlnOrNull] is called.
*
* LF or CRLF is treated as the line terminator. Line terminator is not included in the returned string.
*
* Currently this function is not supported in Kotlin/JS and throws [UnsupportedOperationException].
*/
@SinceKotlin("1.6")
public expect fun readlnOrNull(): String?
internal class ReadAfterEOFException(message: String?) : RuntimeException(message)
internal expect interface Serializable
@@ -104,3 +104,9 @@ public actual fun println(message: Any?) {
public actual fun print(message: Any?) {
output.print(message)
}
@SinceKotlin("1.6")
public actual fun readln(): String = throw UnsupportedOperationException("readln is not supported in Kotlin/JS")
@SinceKotlin("1.6")
public actual fun readlnOrNull(): String? = throw UnsupportedOperationException("readlnOrNull is not supported in Kotlin/JS")
@@ -149,7 +149,7 @@ public actual inline fun println() {
* The input is decoded using the system default Charset. A [CharacterCodingException] is thrown if input is malformed.
*/
@SinceKotlin("1.6")
public fun readln(): String = readlnOrNull() ?: throw ReadAfterEOFException("EOF has already been reached")
public actual fun readln(): String = readlnOrNull() ?: throw ReadAfterEOFException("EOF has already been reached")
/**
* Reads a line of input from the standard input stream and returns it,
@@ -160,9 +160,7 @@ public fun readln(): String = readlnOrNull() ?: throw ReadAfterEOFException("EOF
* The input is decoded using the system default Charset. A [CharacterCodingException] is thrown if input is malformed.
*/
@SinceKotlin("1.6")
public fun readlnOrNull(): String? = readLine()
private class ReadAfterEOFException(message: String?) : RuntimeException(message)
public actual fun readlnOrNull(): String? = readLine()
/**
* Reads a line of input from the standard input stream.
+14
View File
@@ -48,6 +48,20 @@ class ConsoleTest {
testReadLine("first${linuxLineSeparator}second", listOf("first", "second"))
}
@Test
fun shouldReadMultipleEmptyLines() {
testReadLine(
"first${linuxLineSeparator}second${linuxLineSeparator}${linuxLineSeparator}${linuxLineSeparator}",
listOf("first", "second", "", "")
)
}
@Test
fun shouldReadAloneCarriageReturn() {
val result = readLines("\r", Charsets.UTF_8)
assertEquals(listOf("\r"), result)
}
@Test
fun shouldReadConsecutiveEmptyLines() {
testReadLine("$linuxLineSeparator$linuxLineSeparator", listOf("", ""))
+6
View File
@@ -23,6 +23,12 @@ public actual fun print(message: Any?) {
println(message)
}
@SinceKotlin("1.6")
public actual fun readln(): String = TODO("Wasm stdlib: IO")
@SinceKotlin("1.6")
public actual fun readlnOrNull(): String? = TODO("Wasm stdlib: IO")
internal actual interface Serializable