KStarbound/src/main/kotlin/ru/dbotthepony/kstarbound/util/TwoDimensionalArray.kt
2022-09-13 19:22:31 +07:00

62 lines
1.7 KiB
Kotlin

package ru.dbotthepony.kstarbound.util
import it.unimi.dsi.fastutil.objects.ObjectSpliterators
import java.util.Arrays
import java.util.stream.Stream
import java.util.stream.StreamSupport
import kotlin.reflect.KClass
class TwoDimensionalArray<T : Any>(clazz: KClass<T>, private val width: Int, private val height: Int) {
data class Entry<out T>(
val x: Int,
val y: Int,
val value: T,
)
private val memory: Array<T?> = java.lang.reflect.Array.newInstance(clazz.java, width * height) as Array<T?>
fun isOutside(x: Int, y: Int): Boolean {
return (x !in 0 until width) || (y !in 0 until height)
}
operator fun get(x: Int, y: Int): T? {
if (x !in 0 until width) {
throw IndexOutOfBoundsException("X $x is out of bounds between 0 and $width")
}
if (y !in 0 until height) {
throw IndexOutOfBoundsException("Y $y is out of bounds between 0 and $height")
}
return memory[x + y * width]
}
operator fun set(x: Int, y: Int, value: T?): T? {
if (x !in 0 until width) {
throw IndexOutOfBoundsException("X $x is out of bounds between 0 and $width")
}
if (y !in 0 until height) {
throw IndexOutOfBoundsException("Y $y is out of bounds between 0 and $height")
}
val old = memory[x + y * width]
memory[x + y * width] = value
return old
}
fun stream(): Stream<out T?> {
return Arrays.stream(memory)
}
fun indexedStream(): Stream<out Entry<T?>> {
return StreamSupport.stream(IndexedArraySpliterator(memory), false).map {
val x = it.index % width
val y = (it.index - x) / width
Entry(x, y, it.value)
}
}
}
inline fun <reified T : Any> TwoDimensionalArray(width: Int, height: Int) = TwoDimensionalArray(T::class, width, height)