Add support for file streams
This commit is contained in:
parent
3bc0017018
commit
92e7d50bab
11 changed files with 917 additions and 1 deletions
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||
* Licensed under the GNU General Public License v3.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.base.exception.io
|
||||
|
||||
import de.staropensource.engine.base.implementable.stream.FileStream
|
||||
|
||||
/**
|
||||
* Thrown when trying to
|
||||
* access a closed [FileStream].
|
||||
*
|
||||
* @see FileStream
|
||||
* @see FileStream.closed
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
class StreamClosedException(stream: FileStream) : RuntimeException("The file stream ${stream} was access whilst already closed")
|
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||
* Licensed under the GNU General Public License v3.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.base.implementable.stream
|
||||
|
||||
import de.staropensource.engine.base.annotation.NonKotlinContact
|
||||
import de.staropensource.engine.base.exception.io.IOAccessException
|
||||
import de.staropensource.engine.base.implementation.stream.NullFileStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
||||
/**
|
||||
* Makes streaming data easy.
|
||||
*
|
||||
* @param streamMode supported [StreamMode]s
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
abstract class FileStream(val streamMode: StreamMode) : AutoCloseable {
|
||||
/**
|
||||
* Companion object of [FileStream].
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
companion object {
|
||||
/**
|
||||
* Returns a [FileStream] which does nothing.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
val nullStream: FileStream = NullFileStream.instance
|
||||
}
|
||||
|
||||
|
||||
// -----> Properties
|
||||
/**
|
||||
* Indicates whether this stream is closed.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
var closed: Boolean = false
|
||||
private set
|
||||
|
||||
/**
|
||||
* Contains the [java.io.InputStream]
|
||||
* for this [FileStream] instance.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
private var inputStream: InputFileStream? = null
|
||||
|
||||
/**
|
||||
* Contains the [java.io.OutputStream]
|
||||
* for this [FileStream] instance.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
private var outputStream: OutputFileStream? = null
|
||||
|
||||
|
||||
// -----> Closure
|
||||
/**
|
||||
* Closes this stream.
|
||||
*
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
override fun close() {
|
||||
if (closed)
|
||||
return
|
||||
|
||||
closed = true
|
||||
closeStream()
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes this stream.
|
||||
*
|
||||
* This method may be used by the
|
||||
* implementation to close the stream.
|
||||
*
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
protected abstract fun closeStream()
|
||||
|
||||
|
||||
// -----> Writing
|
||||
/**
|
||||
* Writes (or rather: appends)
|
||||
* the specified [Byte].
|
||||
*
|
||||
* If you don't intend on optimizing
|
||||
* for a single byte, just add this
|
||||
* line to your implementation instead:
|
||||
* ```kotlin
|
||||
* override fun writeByte(byte: Byte): FileStream = writeBytes(byteArrayOf(byte))
|
||||
* ```
|
||||
*
|
||||
* @param byte [Byte] to write
|
||||
* @return this instance
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
abstract fun writeByte(byte: Byte): FileStream
|
||||
|
||||
/**
|
||||
* Writes (or rather: appends)
|
||||
* the specified [Byte]s.
|
||||
*
|
||||
* @param bytes [Byte]s to write
|
||||
* @return this instance
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
abstract fun writeBytes(bytes: ByteArray): FileStream
|
||||
|
||||
/**
|
||||
* Writes (or rather: appends)
|
||||
* the specified [String].
|
||||
*
|
||||
* @param string [String] to write
|
||||
* @return this instance
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
fun writeString(string: String): FileStream = writeBytes(string.toByteArray())
|
||||
|
||||
/**
|
||||
* Writes (or rather: appends)
|
||||
* the specified value.
|
||||
*
|
||||
* @param value value to write
|
||||
* @return this instance
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
fun write(value: Any): FileStream = writeBytes(value.toString().toByteArray())
|
||||
|
||||
|
||||
// -----> Reading
|
||||
/**
|
||||
* Returns whether any more
|
||||
* bytes can be read from
|
||||
* this stream.
|
||||
*
|
||||
* Returns `null` if unsupported
|
||||
* by the implementation.
|
||||
*
|
||||
* @return if bytes are remaining or `null` if unsupported
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
abstract fun remaining(): Boolean?
|
||||
|
||||
/**
|
||||
* Returns the amount of
|
||||
* [Byte]s which can be
|
||||
* read without blocking.
|
||||
*
|
||||
* May or may not be
|
||||
* equal to `0`
|
||||
*
|
||||
* @return amount of [Byte]s to read without blocking
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
abstract fun available(): UInt
|
||||
|
||||
/**
|
||||
* Reads the next [Byte].
|
||||
*
|
||||
* @return next [Byte] or `null` if no bytes are remaining
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
abstract fun readNextByte(): Byte?
|
||||
|
||||
/**
|
||||
* Reads the specified next [n] [Byte]s.
|
||||
*
|
||||
* @param n [Byte]s to read
|
||||
* @return next [n] bytes or an empty array if no bytes are remaining
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
abstract fun readNBytes(n: UInt): ByteArray
|
||||
|
||||
/**
|
||||
* Reads all remaining [Byte]s.
|
||||
*
|
||||
* @return remaining [Byte]s or an empty array if no bytes are remaining
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
abstract fun readRemainingBytes(): ByteArray
|
||||
|
||||
/**
|
||||
* Discards the next [Byte].
|
||||
*
|
||||
* @return this instance
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
fun skipNextByte(): FileStream {
|
||||
readNextByte()
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Discards the specified next [n] bytes.
|
||||
*
|
||||
* @param n [Byte]s to discard
|
||||
* @return this instance
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
fun skipNBytes(n: UInt): FileStream {
|
||||
readNBytes(n)
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Discards all remaining [Byte]s.
|
||||
*
|
||||
* @return this instance
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
fun skipRemainingBytes(): FileStream {
|
||||
readRemainingBytes()
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// -----> Redirection
|
||||
/**
|
||||
* Reads the next byte of this
|
||||
* [FileStream] and writes it
|
||||
* to the specified [FileStream].
|
||||
*
|
||||
* @param stream stream to write to
|
||||
* @return this instance
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
fun writeNextByteTo(stream: FileStream): FileStream {
|
||||
val byte: Byte? = readNextByte()
|
||||
|
||||
if (byte != null)
|
||||
stream.writeByte(byte)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next [n] byte of this
|
||||
* [FileStream] and writes it
|
||||
* to the specified [FileStream].
|
||||
*
|
||||
* @param stream stream to write to
|
||||
* @return this instance
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
fun writeNBytesTo(stream: FileStream, n: UInt): FileStream {
|
||||
stream.writeBytes(readNBytes(n))
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all bytes of this
|
||||
* [FileStream] and writes
|
||||
* them to the specified
|
||||
* [FileStream].
|
||||
*
|
||||
* @param stream stream to write to
|
||||
* @return this instance
|
||||
* @throws IOAccessException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOAccessException::class)
|
||||
fun writeRemainingBytesTo(stream: FileStream): FileStream {
|
||||
stream.writeBytes(readRemainingBytes())
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// -----> Java interoperability
|
||||
/**
|
||||
* Returns this stream as
|
||||
* a Java [InputStream].
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@NonKotlinContact
|
||||
fun toInputStream(): InputStream {
|
||||
if (inputStream == null)
|
||||
inputStream = InputFileStream(this)
|
||||
|
||||
return inputStream!!
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this stream as
|
||||
* a Java [OutputStream].
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@NonKotlinContact
|
||||
fun toOutputStream(): OutputStream {
|
||||
if (outputStream == null)
|
||||
outputStream = OutputFileStream(this)
|
||||
|
||||
return outputStream!!
|
||||
}
|
||||
|
||||
|
||||
// -----> Inner classes
|
||||
/**
|
||||
* Represents the mode in which
|
||||
* [FileStream]s can operate in.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
enum class StreamMode {
|
||||
/**
|
||||
* A [FileStream] which only
|
||||
* supports reading.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
READ,
|
||||
|
||||
/**
|
||||
* A [FileStream] which only
|
||||
* supports writing.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
WRITE,
|
||||
|
||||
/**
|
||||
* A [FileStream] which supports
|
||||
* both reading and writing.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
READ_WRITE,
|
||||
}
|
||||
|
||||
/**
|
||||
* An implementation of Java
|
||||
* [InputStream]s for [FileStream]s.
|
||||
*
|
||||
* @param fileStream [FileStream] to use
|
||||
* @throws IOException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
class InputFileStream
|
||||
@NonKotlinContact
|
||||
internal constructor(val fileStream: FileStream)
|
||||
: InputStream() {
|
||||
/**
|
||||
* Reads the next byte.
|
||||
*
|
||||
* @return byte read
|
||||
* @throws IOException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
override fun read(): Int = try {
|
||||
fileStream.readNextByte()?.toInt() ?: -1
|
||||
} catch (exception: IOAccessException) {
|
||||
throw IOException("Failed reading the next byte", exception)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An implementation of Java
|
||||
* [OutputStream]s for [FileStream]s.
|
||||
*
|
||||
* @param fileStream [FileStream] to use
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@NonKotlinContact
|
||||
class OutputFileStream
|
||||
@NonKotlinContact
|
||||
internal constructor(val fileStream: FileStream)
|
||||
: OutputStream() {
|
||||
/**
|
||||
* Writes (or rather: appends) a byte.
|
||||
*
|
||||
* @param byte byte to append
|
||||
* @throws IOException on IO error
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
override fun write(byte: Int) {
|
||||
try {
|
||||
fileStream.writeByte(byte.toByte())
|
||||
} catch (exception: IOAccessException) {
|
||||
throw IOException("Failed writing the next byte", exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||
* Licensed under the GNU General Public License v3.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.base.implementable.stream
|
||||
|
||||
/**
|
||||
* A read-only [FileStream].
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
abstract class ReadFileStream : FileStream(streamMode = StreamMode.READ) {
|
||||
override fun writeByte(byte: Byte): FileStream = this
|
||||
override fun writeBytes(bytes: ByteArray): FileStream = this
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||
* Licensed under the GNU General Public License v3.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.base.implementable.stream
|
||||
|
||||
/**
|
||||
* A write-only [FileStream].
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
abstract class WriteFileStream : FileStream(streamMode = StreamMode.WRITE) {
|
||||
override fun remaining(): Boolean = false
|
||||
override fun available(): UInt = 0u
|
||||
override fun readNextByte(): Byte? = 0x00
|
||||
override fun readNBytes(n: UInt): ByteArray = byteArrayOf()
|
||||
override fun readRemainingBytes(): ByteArray = byteArrayOf()
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||
* Licensed under the GNU General Public License v3.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Streams. Particularly [FileStream]s.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
package de.staropensource.engine.base.implementable.stream
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||
* Licensed under the GNU General Public License v3.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.base.implementation.stream
|
||||
|
||||
import de.staropensource.engine.base.exception.VerificationFailedException
|
||||
import de.staropensource.engine.base.exception.io.IOAccessException
|
||||
import de.staropensource.engine.base.exception.io.StreamClosedException
|
||||
import de.staropensource.engine.base.implementable.stream.FileStream
|
||||
import de.staropensource.engine.base.utility.FileAccess
|
||||
import java.io.InputStream
|
||||
|
||||
/**
|
||||
* A [FileStream] used exclusively for
|
||||
* accessing files via the [FileAccess]
|
||||
* API.
|
||||
*
|
||||
* @param file [FileAccess] to use
|
||||
* @see FileAccess.toStream
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
class FileAccessStream internal constructor(val file: FileAccess) : FileStream(streamMode = StreamMode.READ_WRITE) {
|
||||
// -----> Metadata
|
||||
/**
|
||||
* Contains the [InputStream] used
|
||||
* for reading to files.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
val inputStream: InputStream = file.file.inputStream()
|
||||
|
||||
|
||||
// -----> Closure
|
||||
override fun closeStream() = Unit
|
||||
|
||||
|
||||
// -----> Writing
|
||||
override fun writeByte(byte: Byte): FileStream = writeBytes(byteArrayOf(byte))
|
||||
|
||||
override fun writeBytes(bytes: ByteArray): FileStream {
|
||||
if (closed)
|
||||
throw StreamClosedException(this)
|
||||
|
||||
try {
|
||||
file
|
||||
.createFile()
|
||||
.verifyIsFile()
|
||||
.appendBytes(bytes = bytes, async = false)
|
||||
} catch (_: VerificationFailedException) {
|
||||
throw IOAccessException("File '${file}' does not exist")
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// -----> Reading
|
||||
override fun remaining(): Boolean? = null
|
||||
|
||||
override fun available(): UInt {
|
||||
if (closed)
|
||||
throw StreamClosedException(this)
|
||||
|
||||
try {
|
||||
file
|
||||
.createFile()
|
||||
.verifyIsFile()
|
||||
|
||||
return inputStream.available().toUInt()
|
||||
} catch (_: VerificationFailedException) {
|
||||
throw IOAccessException("File '${file}' does not exist")
|
||||
}
|
||||
}
|
||||
|
||||
override fun readNextByte(): Byte? {
|
||||
if (closed)
|
||||
throw StreamClosedException(this)
|
||||
|
||||
try {
|
||||
file
|
||||
.createFile()
|
||||
.verifyIsFile()
|
||||
|
||||
return inputStream.read().toByte()
|
||||
} catch (_: VerificationFailedException) {
|
||||
throw IOAccessException("File '${file}' does not exist")
|
||||
}
|
||||
}
|
||||
|
||||
override fun readNBytes(n: UInt): ByteArray {
|
||||
if (closed)
|
||||
throw StreamClosedException(this)
|
||||
|
||||
try {
|
||||
file
|
||||
.createFile()
|
||||
.verifyIsFile()
|
||||
|
||||
return inputStream.readNBytes(n.toInt())
|
||||
} catch (_: VerificationFailedException) {
|
||||
throw IOAccessException("File '${file}' does not exist")
|
||||
}
|
||||
}
|
||||
|
||||
override fun readRemainingBytes(): ByteArray {
|
||||
|
||||
try {
|
||||
file
|
||||
.createFile()
|
||||
.verifyIsFile()
|
||||
|
||||
return inputStream.readAllBytes()
|
||||
} catch (_: VerificationFailedException) {
|
||||
throw IOAccessException("File '${file}' does not exist")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||
* Licensed under the GNU General Public License v3.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.base.implementation.stream
|
||||
|
||||
import de.staropensource.engine.base.implementable.stream.FileStream
|
||||
import de.staropensource.engine.base.implementable.stream.WriteFileStream
|
||||
import de.staropensource.engine.base.logging.Logger
|
||||
import de.staropensource.engine.base.type.logging.Level
|
||||
import de.staropensource.engine.base.utility.FileAccess
|
||||
|
||||
/**
|
||||
* A [FileStream] used exclusively
|
||||
* for printing log messages.
|
||||
*
|
||||
* A log message is only printed
|
||||
* after a newline (`\n`) is written.
|
||||
*
|
||||
* @param logger [Logger] instance to use
|
||||
* @see FileAccess.toStream
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
class LoggerFileStream internal constructor(val logger: Logger, val level: Level) : WriteFileStream() {
|
||||
/**
|
||||
* Contains the current line.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
val line: StringBuilder = StringBuilder()
|
||||
|
||||
override fun closeStream() {
|
||||
logger.stream.remove(level)
|
||||
}
|
||||
|
||||
override fun writeByte(byte: Byte): FileStream = writeBytes(byteArrayOf(byte))
|
||||
|
||||
override fun writeBytes(bytes: ByteArray): FileStream {
|
||||
line.append(bytes.decodeToString())
|
||||
|
||||
checkAndPrint()
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies whether [line]
|
||||
* contains a newline and
|
||||
* if so, prints it.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
private fun checkAndPrint() {
|
||||
if (line.contains("\n")) {
|
||||
var lineFinal: String = line.toString()
|
||||
|
||||
// Remove last newline
|
||||
lineFinal = lineFinal.removeSuffix("\n")
|
||||
|
||||
// Print
|
||||
when (level) {
|
||||
Level.DIAGNOSTIC -> logger.diag(lineFinal)
|
||||
Level.VERBOSE -> logger.verb(lineFinal)
|
||||
Level.SILENT_WARNING -> logger.sarn(lineFinal)
|
||||
Level.INFORMATIONAL -> logger.info(lineFinal)
|
||||
Level.WARNING -> logger.warn(lineFinal)
|
||||
Level.ERROR -> logger.error(lineFinal)
|
||||
Level.CRASH -> logger.crash(lineFinal, throwable = null, fatal = true)
|
||||
}
|
||||
|
||||
// Clear line
|
||||
line.clear()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||
* Licensed under the GNU General Public License v3.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.engine.base.implementation.stream
|
||||
|
||||
import de.staropensource.engine.base.implementable.stream.FileStream
|
||||
|
||||
/**
|
||||
* A [de.staropensource.engine.base.implementable.stream.FileStream] which does nothing.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
class NullFileStream private constructor() : FileStream(streamMode = StreamMode.READ_WRITE) {
|
||||
/**
|
||||
* Companion object of [NullFileStream].
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
companion object {
|
||||
/**
|
||||
* Global instance of [NullFileStream].
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
@JvmStatic
|
||||
val instance: NullFileStream = NullFileStream()
|
||||
}
|
||||
|
||||
override fun closeStream() = Unit
|
||||
|
||||
override fun writeByte(byte: Byte): FileStream = this
|
||||
override fun writeBytes(bytes: ByteArray): FileStream = this
|
||||
|
||||
override fun remaining(): Boolean = true
|
||||
override fun available(): UInt = 0u
|
||||
override fun readNextByte(): Byte = 0
|
||||
override fun readNBytes(n: UInt): ByteArray = byteArrayOf()
|
||||
override fun readRemainingBytes(): ByteArray = byteArrayOf()
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||
* Licensed under the GNU General Public License v3.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementations of [FileStream] far and wide.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
package de.staropensource.engine.base.implementation.stream
|
||||
|
||||
import de.staropensource.engine.base.implementable.stream.FileStream
|
|
@ -20,7 +20,11 @@
|
|||
package de.staropensource.engine.base.logging
|
||||
|
||||
import de.staropensource.engine.base.EngineConfiguration
|
||||
import de.staropensource.engine.base.annotation.NonKotlinContact
|
||||
import de.staropensource.engine.base.implementable.logging.LoggerThreadingHandler
|
||||
import de.staropensource.engine.base.implementable.stream.FileStream
|
||||
import de.staropensource.engine.base.implementation.stream.FileAccessStream
|
||||
import de.staropensource.engine.base.implementation.stream.LoggerFileStream
|
||||
import de.staropensource.engine.base.type.logging.Call
|
||||
import de.staropensource.engine.base.type.logging.Level
|
||||
import de.staropensource.engine.base.utility.misc.StackTraceUtils
|
||||
|
@ -68,7 +72,7 @@ class Logger {
|
|||
}
|
||||
|
||||
|
||||
// -----> Fields
|
||||
// -----> Properties
|
||||
/**
|
||||
* Holds the channel this instance uses.
|
||||
*
|
||||
|
@ -76,6 +80,15 @@ class Logger {
|
|||
*/
|
||||
private val channel: String
|
||||
|
||||
/**
|
||||
* Contains the [LoggerFileStream] for this instance.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
internal val stream: MutableMap<Level, LoggerFileStream> = mutableMapOf()
|
||||
@NonKotlinContact
|
||||
@JvmName(name = "getActualStream") get
|
||||
|
||||
|
||||
// -----> Constructors
|
||||
/**
|
||||
|
@ -218,4 +231,15 @@ class Logger {
|
|||
fun flush() {
|
||||
EngineConfiguration.logThreadingHandler?.flush()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [FileStream] for
|
||||
* writing to the specified
|
||||
* [Level] using this instance.
|
||||
*
|
||||
* @param level [Level] to which the [FileStream] shall log to
|
||||
* @return [FileAccessStream] instance
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
fun toStream(level: Level): LoggerFileStream = stream.computeIfAbsent(level) { level -> LoggerFileStream(this, level) }
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ import de.staropensource.engine.base.exception.io.FileOrDirectoryNotFoundExcepti
|
|||
import de.staropensource.engine.base.exception.io.FileTooLargeException
|
||||
import de.staropensource.engine.base.exception.io.IOAccessException
|
||||
import de.staropensource.engine.base.exception.VerificationFailedException
|
||||
import de.staropensource.engine.base.implementable.stream.FileStream
|
||||
import de.staropensource.engine.base.implementation.stream.FileAccessStream
|
||||
import de.staropensource.engine.base.utility.Environment.OperatingSystem.*
|
||||
import de.staropensource.engine.base.utility.FileAccess.Companion.configDirectory
|
||||
import de.staropensource.engine.base.utility.FileAccess.Companion.format
|
||||
|
@ -301,6 +303,15 @@ class FileAccess {
|
|||
@JvmName(name = "getJavaFile")
|
||||
get
|
||||
|
||||
/**
|
||||
* Contains the [FileAccessStream] for this instance.
|
||||
*
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
private var stream: FileAccessStream? = null
|
||||
@NonKotlinContact
|
||||
@JvmName(name = "getActualStream") get
|
||||
|
||||
|
||||
// -----> Constructors
|
||||
/**
|
||||
|
@ -557,6 +568,22 @@ class FileAccess {
|
|||
}
|
||||
|
||||
|
||||
// -----> Streams getters
|
||||
/**
|
||||
* Returns a [FileStream] for reading
|
||||
* and writing from and to this file.
|
||||
*
|
||||
* @return [FileAccessStream] instance
|
||||
* @since v1-alpha10
|
||||
*/
|
||||
fun toStream(): FileAccessStream {
|
||||
if (stream == null)
|
||||
stream = FileAccessStream(this)
|
||||
|
||||
return stream!!
|
||||
}
|
||||
|
||||
|
||||
// -----> File creation, moving, copying and deletion
|
||||
/**
|
||||
* Creates a file at this location.
|
||||
|
|
Loading…
Reference in a new issue