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
|
package de.staropensource.engine.base.logging
|
||||||
|
|
||||||
import de.staropensource.engine.base.EngineConfiguration
|
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.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.Call
|
||||||
import de.staropensource.engine.base.type.logging.Level
|
import de.staropensource.engine.base.type.logging.Level
|
||||||
import de.staropensource.engine.base.utility.misc.StackTraceUtils
|
import de.staropensource.engine.base.utility.misc.StackTraceUtils
|
||||||
|
@ -68,7 +72,7 @@ class Logger {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// -----> Fields
|
// -----> Properties
|
||||||
/**
|
/**
|
||||||
* Holds the channel this instance uses.
|
* Holds the channel this instance uses.
|
||||||
*
|
*
|
||||||
|
@ -76,6 +80,15 @@ class Logger {
|
||||||
*/
|
*/
|
||||||
private val channel: String
|
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
|
// -----> Constructors
|
||||||
/**
|
/**
|
||||||
|
@ -218,4 +231,15 @@ class Logger {
|
||||||
fun flush() {
|
fun flush() {
|
||||||
EngineConfiguration.logThreadingHandler?.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.FileTooLargeException
|
||||||
import de.staropensource.engine.base.exception.io.IOAccessException
|
import de.staropensource.engine.base.exception.io.IOAccessException
|
||||||
import de.staropensource.engine.base.exception.VerificationFailedException
|
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.Environment.OperatingSystem.*
|
||||||
import de.staropensource.engine.base.utility.FileAccess.Companion.configDirectory
|
import de.staropensource.engine.base.utility.FileAccess.Companion.configDirectory
|
||||||
import de.staropensource.engine.base.utility.FileAccess.Companion.format
|
import de.staropensource.engine.base.utility.FileAccess.Companion.format
|
||||||
|
@ -301,6 +303,15 @@ class FileAccess {
|
||||||
@JvmName(name = "getJavaFile")
|
@JvmName(name = "getJavaFile")
|
||||||
get
|
get
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the [FileAccessStream] for this instance.
|
||||||
|
*
|
||||||
|
* @since v1-alpha10
|
||||||
|
*/
|
||||||
|
private var stream: FileAccessStream? = null
|
||||||
|
@NonKotlinContact
|
||||||
|
@JvmName(name = "getActualStream") get
|
||||||
|
|
||||||
|
|
||||||
// -----> Constructors
|
// -----> 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
|
// -----> File creation, moving, copying and deletion
|
||||||
/**
|
/**
|
||||||
* Creates a file at this location.
|
* Creates a file at this location.
|
||||||
|
|
Loading…
Reference in a new issue