Created
August 4, 2020 16:20
-
-
Save yt8492/bd3ec40612296ed33284e99355ea547e to your computer and use it in GitHub Desktop.
Kotlin/Native posix FileLineInputIterator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import kotlinx.cinterop.ByteVar | |
import kotlinx.cinterop.allocArray | |
import kotlinx.cinterop.memScoped | |
import kotlinx.cinterop.toKString | |
import platform.posix.fclose | |
import platform.posix.fgets | |
import platform.posix.fopen | |
class FileLineInputIterator( | |
filename: String | |
) : Iterator<String> { | |
private val filePointer = fopen(filename, "r") | |
?: throw NullPointerException("file not found") | |
private var current = readLine() | |
override fun hasNext(): Boolean { | |
return current != null | |
} | |
override fun next(): String { | |
val retVal = current ?: error("unknown state") | |
current = readLine() | |
return retVal | |
} | |
private fun readLine(): String? { | |
return try { | |
val stringBuilder = StringBuilder() | |
memScoped { | |
val buffer = allocArray<ByteVar>(bufferLength) | |
while (true) { | |
val nextLine = fgets(buffer, bufferLength, filePointer)?.toKString() | |
if (nextLine == null) { | |
return if (stringBuilder.isEmpty()) { | |
null | |
} else { | |
stringBuilder.toString() | |
} | |
} else { | |
if (nextLine.last() == '\n') { | |
stringBuilder.append(nextLine.dropLast(1)) | |
break | |
} else { | |
stringBuilder.append(nextLine) | |
} | |
} | |
} | |
stringBuilder.toString() | |
} | |
} catch (e: Exception) { | |
fclose(filePointer) | |
throw e | |
} | |
} | |
companion object { | |
private const val bufferLength = 64 * 1024 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment