54 lines
1.2 KiB
Kotlin
54 lines
1.2 KiB
Kotlin
package ru.dbotthepony.kstarbound.util
|
|
|
|
import com.github.benmanes.caffeine.cache.Interner
|
|
import kotlin.concurrent.getOrSet
|
|
|
|
class PathStack(private val interner: Interner<String> = Interner { it }) {
|
|
private val _stack = object : ThreadLocal<ArrayDeque<String>>() {
|
|
override fun initialValue(): ArrayDeque<String> {
|
|
return ArrayDeque()
|
|
}
|
|
}
|
|
|
|
private val stack: ArrayDeque<String> get() = _stack.get()
|
|
|
|
fun push(value: String) {
|
|
stack.addLast(value)
|
|
}
|
|
|
|
fun pushFilename(value: String) {
|
|
push(value.substringBefore(':').substringBeforeLast('/'))
|
|
}
|
|
|
|
fun last() = stack.lastOrNull()
|
|
fun pop() = stack.removeLast()
|
|
|
|
inline fun <T> block(path: String, block: (String) -> T): T {
|
|
try {
|
|
push(path)
|
|
return block.invoke(path)
|
|
} finally {
|
|
pop()
|
|
}
|
|
}
|
|
|
|
inline operator fun <T> invoke(path: String, block: (String) -> T) = block(path, block)
|
|
|
|
private fun remap(a: String, b: String): String {
|
|
if (b.isEmpty())
|
|
return a
|
|
if (b[0] == '/')
|
|
return b
|
|
|
|
return interner.intern("$a/$b")
|
|
}
|
|
|
|
fun remap(path: String): String {
|
|
return remap(checkNotNull(last()) { "Not reading an asset on current thread" }, path)
|
|
}
|
|
|
|
fun remapSafe(path: String): String? {
|
|
return remap(last() ?: return null, path)
|
|
}
|
|
}
|