KT-11208 Remove readLine's lineSeparator parameter
This commit is contained in:
@@ -137,10 +137,7 @@ public inline fun println() {
|
||||
}
|
||||
|
||||
private const val BUFFER_SIZE: Int = 32
|
||||
|
||||
// Since System.in can change its value on the course of program running, we should always delegate to current value.
|
||||
private val stdin: InputStream
|
||||
get() = System.`in`
|
||||
private const val LINE_SEPARATOR_MAX_LENGTH: Int = 2
|
||||
|
||||
private var cachedDecoder: CharsetDecoder? = null
|
||||
|
||||
@@ -157,14 +154,13 @@ private fun decoderFor(charset: Charset): CharsetDecoder {
|
||||
*
|
||||
* @return the line read or `null` if the input stream is redirected to a file and the end of file has been reached.
|
||||
*/
|
||||
fun readLine(lineSeparator: String = System.lineSeparator(), charset: Charset = Charset.defaultCharset()): String? =
|
||||
readLine(stdin, lineSeparator, decoderFor(charset))
|
||||
fun readLine(charset: Charset = Charset.defaultCharset()): String? = readLine(System.`in`, decoderFor(charset))
|
||||
|
||||
internal fun readLine(inputStream: InputStream, lineSeparator: String, decoder: CharsetDecoder): String? {
|
||||
internal fun readLine(inputStream: InputStream, decoder: CharsetDecoder): String? {
|
||||
require(decoder.maxCharsPerByte() <= 1) { "Encodings with multiple chars per byte are not supported" }
|
||||
|
||||
val byteBuffer = ByteBuffer.allocate(BUFFER_SIZE)
|
||||
val charBuffer = CharBuffer.allocate(lineSeparator.length)
|
||||
val charBuffer = CharBuffer.allocate(LINE_SEPARATOR_MAX_LENGTH)
|
||||
val stringBuilder = StringBuilder()
|
||||
|
||||
var read = inputStream.read()
|
||||
@@ -172,7 +168,7 @@ internal fun readLine(inputStream: InputStream, lineSeparator: String, decoder:
|
||||
while (read != -1) {
|
||||
byteBuffer.put(read.toByte())
|
||||
if (decoder.tryDecode(byteBuffer, charBuffer, false)) {
|
||||
if (charBuffer.contentEquals(lineSeparator)) {
|
||||
if (charBuffer.containsLineSeparator()) {
|
||||
break
|
||||
}
|
||||
if (!charBuffer.hasRemaining()) {
|
||||
@@ -188,9 +184,16 @@ internal fun readLine(inputStream: InputStream, lineSeparator: String, decoder:
|
||||
}
|
||||
|
||||
with(charBuffer) {
|
||||
if (!contentEquals(lineSeparator)) {
|
||||
flip()
|
||||
while (hasRemaining()) stringBuilder.append(get())
|
||||
val length = position()
|
||||
val first = get(0)
|
||||
val second = get(1)
|
||||
flip()
|
||||
when (length) {
|
||||
2 -> {
|
||||
if (!(first == '\r' && second == '\n')) stringBuilder.append(first)
|
||||
if (second != '\n') stringBuilder.append(second)
|
||||
}
|
||||
1 -> if (first != '\n') stringBuilder.append(first)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,9 +211,8 @@ private fun CharsetDecoder.tryDecode(byteBuffer: ByteBuffer, charBuffer: CharBuf
|
||||
}
|
||||
}
|
||||
|
||||
private fun CharBuffer.contentEquals(string: String): Boolean {
|
||||
flip()
|
||||
return string.contentEquals(this).also { flipBack() }
|
||||
private fun CharBuffer.containsLineSeparator(): Boolean {
|
||||
return get(1) == '\n' || get(0) == '\n'
|
||||
}
|
||||
|
||||
private fun Buffer.flipBack(): Buffer = apply {
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.nio.charset.Charset
|
||||
import kotlin.test.*
|
||||
|
||||
class ConsoleTest {
|
||||
private val defaultLineSeparator: String = "\\n"
|
||||
private val defaultLineSeparator: String = "\n"
|
||||
|
||||
@Test
|
||||
fun shouldReadEmptyLine() {
|
||||
@@ -45,14 +45,8 @@ class ConsoleTest {
|
||||
|
||||
@Test
|
||||
fun shouldReadWindowsLineSeparator() {
|
||||
val lineSeparator = "\\r\\n"
|
||||
testReadLine("first${lineSeparator}second", "first", "second", lineSeparator = lineSeparator)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldReadOldMacLineSeparator() {
|
||||
val lineSeparator = "\\r"
|
||||
testReadLine("first${lineSeparator}second", "first", "second", lineSeparator = lineSeparator)
|
||||
val lineSeparator = "\r\n"
|
||||
testReadLine("first${lineSeparator}second", "first", "second")
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -60,20 +54,15 @@ class ConsoleTest {
|
||||
testReadLine("first${defaultLineSeparator}second", "first", "second", charset = Charsets.UTF_32)
|
||||
}
|
||||
|
||||
private fun testReadLine(
|
||||
text: String,
|
||||
vararg expected: String,
|
||||
lineSeparator: String = defaultLineSeparator,
|
||||
charset: Charset = Charsets.UTF_8
|
||||
) {
|
||||
val actual = readLines(text, lineSeparator, charset)
|
||||
private fun testReadLine(text: String, vararg expected: String, charset: Charset = Charsets.UTF_8) {
|
||||
val actual = readLines(text, charset)
|
||||
assertEquals(expected.asList(), actual)
|
||||
}
|
||||
|
||||
private fun readLines(text: String, lineSeparator: String, charset: Charset): List<String> {
|
||||
private fun readLines(text: String, charset: Charset): List<String> {
|
||||
text.byteInputStream(charset).use { stream ->
|
||||
val decoder = charset.newDecoder()
|
||||
return generateSequence { readLine(stream, lineSeparator, decoder) }.toList().also {
|
||||
return generateSequence { readLine(stream, decoder) }.toList().also {
|
||||
assertTrue("All bytes should be read") { stream.read() == -1 }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user