Optimize work with names and tokens
This commit is contained in:
parent
70bd92f019
commit
233639f0b6
@ -6,7 +6,7 @@ plugins {
|
|||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group = "space.kscience"
|
group = "space.kscience"
|
||||||
version = "0.6.0-dev-14"
|
version = "0.6.0-dev-15"
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
|
@ -3,9 +3,8 @@ package space.kscience.dataforge.context
|
|||||||
import kotlinx.coroutines.CoroutineName
|
import kotlinx.coroutines.CoroutineName
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.names.Name
|
|
||||||
import space.kscience.dataforge.names.Name.Companion.parse
|
|
||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
|
import space.kscience.dataforge.names.parseAsName
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlin.native.concurrent.ThreadLocal
|
import kotlin.native.concurrent.ThreadLocal
|
||||||
|
|
||||||
@ -22,4 +21,4 @@ private object GlobalContext : Context("GLOBAL".asName(), null, emptySet(), Meta
|
|||||||
public val Global: Context get() = GlobalContext
|
public val Global: Context get() = GlobalContext
|
||||||
|
|
||||||
public fun Context(name: String? = null, block: ContextBuilder.() -> Unit = {}): Context =
|
public fun Context(name: String? = null, block: ContextBuilder.() -> Unit = {}): Context =
|
||||||
Global.buildContext(name?.let(Name::parse), block)
|
Global.buildContext(name?.parseAsName(), block)
|
@ -6,6 +6,7 @@ import space.kscience.dataforge.meta.MetaRepr
|
|||||||
import space.kscience.dataforge.misc.Named
|
import space.kscience.dataforge.misc.Named
|
||||||
import space.kscience.dataforge.misc.Type
|
import space.kscience.dataforge.misc.Type
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
|
import space.kscience.dataforge.names.parseAsName
|
||||||
import space.kscience.dataforge.provider.Provider
|
import space.kscience.dataforge.provider.Provider
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,7 +31,7 @@ public interface Plugin : Named, ContextAware, Provider, MetaRepr {
|
|||||||
/**
|
/**
|
||||||
* The name of this plugin ignoring version and group
|
* The name of this plugin ignoring version and group
|
||||||
*/
|
*/
|
||||||
override val name: Name get() = Name.parse(tag.name)
|
override val name: Name get() = tag.name.parseAsName()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin dependencies which are required to attach this plugin. Plugin
|
* Plugin dependencies which are required to attach this plugin. Plugin
|
||||||
|
@ -3,7 +3,7 @@ package space.kscience.dataforge.properties
|
|||||||
|
|
||||||
import space.kscience.dataforge.meta.Scheme
|
import space.kscience.dataforge.meta.Scheme
|
||||||
import space.kscience.dataforge.misc.DFExperimental
|
import space.kscience.dataforge.misc.DFExperimental
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.parseAsName
|
||||||
import space.kscience.dataforge.names.startsWith
|
import space.kscience.dataforge.names.startsWith
|
||||||
import kotlin.reflect.KMutableProperty1
|
import kotlin.reflect.KMutableProperty1
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ public fun <S : Scheme, T : Any> S.property(property: KMutableProperty1<S, T?>):
|
|||||||
|
|
||||||
override fun onChange(owner: Any?, callback: (T?) -> Unit) {
|
override fun onChange(owner: Any?, callback: (T?) -> Unit) {
|
||||||
this@property.meta.onChange(this) { name ->
|
this@property.meta.onChange(this) { name ->
|
||||||
if (name.startsWith(Name.parse(property.name))) {
|
if (name.startsWith(property.name.parseAsName(true))) {
|
||||||
callback(property.get(this@property))
|
callback(property.get(this@property))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package space.kscience.dataforge.provider
|
package space.kscience.dataforge.provider
|
||||||
|
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
|
import space.kscience.dataforge.names.parseAsName
|
||||||
import kotlin.jvm.JvmInline
|
import kotlin.jvm.JvmInline
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,9 +61,10 @@ public data class PathToken(val name: Name, val target: String? = null) {
|
|||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
public const val TARGET_SEPARATOR: String = "::"
|
public const val TARGET_SEPARATOR: String = "::"
|
||||||
public fun parse(token: String): PathToken {
|
|
||||||
|
public fun parse(token: String, cache: Boolean = false): PathToken {
|
||||||
val target = token.substringBefore(TARGET_SEPARATOR, "")
|
val target = token.substringBefore(TARGET_SEPARATOR, "")
|
||||||
val name = Name.parse(token.substringAfter(TARGET_SEPARATOR))
|
val name = token.substringAfter(TARGET_SEPARATOR).parseAsName(cache)
|
||||||
if (target.contains("[")) TODO("target separators in queries are not supported")
|
if (target.contains("[")) TODO("target separators in queries are not supported")
|
||||||
return PathToken(name, target)
|
return PathToken(name, target)
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import space.kscience.dataforge.misc.DFBuilder
|
|||||||
import space.kscience.dataforge.misc.DFExperimental
|
import space.kscience.dataforge.misc.DFExperimental
|
||||||
import space.kscience.dataforge.misc.DFInternal
|
import space.kscience.dataforge.misc.DFInternal
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
|
import space.kscience.dataforge.names.parseAsName
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
import kotlin.reflect.typeOf
|
import kotlin.reflect.typeOf
|
||||||
|
|
||||||
@ -96,7 +97,7 @@ internal class ReduceAction<T : Any, R : Any>(
|
|||||||
|
|
||||||
val groupMeta = group.meta
|
val groupMeta = group.meta
|
||||||
|
|
||||||
val env = ActionEnv(Name.parse(groupName), groupMeta, meta)
|
val env = ActionEnv(groupName.parseAsName(), groupMeta, meta)
|
||||||
@OptIn(DFInternal::class) val res: Data<R> = dataFlow.reduceToData(
|
@OptIn(DFInternal::class) val res: Data<R> = dataFlow.reduceToData(
|
||||||
group.outputType,
|
group.outputType,
|
||||||
meta = groupMeta
|
meta = groupMeta
|
||||||
|
@ -7,6 +7,7 @@ import space.kscience.dataforge.meta.MutableMeta
|
|||||||
import space.kscience.dataforge.meta.toMutableMeta
|
import space.kscience.dataforge.meta.toMutableMeta
|
||||||
import space.kscience.dataforge.misc.DFExperimental
|
import space.kscience.dataforge.misc.DFExperimental
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
|
import space.kscience.dataforge.names.parseAsName
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
import kotlin.reflect.typeOf
|
import kotlin.reflect.typeOf
|
||||||
@ -35,7 +36,7 @@ public class SplitBuilder<T : Any, R : Any>(public val name: Name, public val me
|
|||||||
* @param rule the rule to transform fragment name and meta using
|
* @param rule the rule to transform fragment name and meta using
|
||||||
*/
|
*/
|
||||||
public fun fragment(name: String, rule: FragmentRule<T, R>.() -> Unit) {
|
public fun fragment(name: String, rule: FragmentRule<T, R>.() -> Unit) {
|
||||||
fragments[Name.parse(name)] = rule
|
fragments[name.parseAsName()] = rule
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,10 +6,7 @@ import kotlinx.coroutines.flow.map
|
|||||||
import kotlinx.coroutines.flow.mapNotNull
|
import kotlinx.coroutines.flow.mapNotNull
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.misc.DFExperimental
|
import space.kscience.dataforge.misc.DFExperimental
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.*
|
||||||
import space.kscience.dataforge.names.isEmpty
|
|
||||||
import space.kscience.dataforge.names.plus
|
|
||||||
import space.kscience.dataforge.names.removeHeadOrNull
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlin.coroutines.EmptyCoroutineContext
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
@ -31,8 +28,8 @@ public fun <T : Any> DataSet<T>.filter(
|
|||||||
override val meta: Meta get() = this@filter.meta
|
override val meta: Meta get() = this@filter.meta
|
||||||
|
|
||||||
override fun iterator(): Iterator<NamedData<T>> = iterator {
|
override fun iterator(): Iterator<NamedData<T>> = iterator {
|
||||||
for(d in this@filter){
|
for (d in this@filter) {
|
||||||
if(predicate(d.name, d.meta)){
|
if (predicate(d.name, d.meta)) {
|
||||||
yield(d)
|
yield(d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,7 +61,7 @@ public fun <T : Any> DataSet<T>.withNamePrefix(prefix: Name): DataSet<T> = if (p
|
|||||||
|
|
||||||
|
|
||||||
override fun iterator(): Iterator<NamedData<T>> = iterator {
|
override fun iterator(): Iterator<NamedData<T>> = iterator {
|
||||||
for(d in this@withNamePrefix){
|
for (d in this@withNamePrefix) {
|
||||||
yield(d.data.named(prefix + d.name))
|
yield(d.data.named(prefix + d.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,7 +86,7 @@ public fun <T : Any> DataSet<T>.branch(branchName: Name): DataSet<T> = if (branc
|
|||||||
override val meta: Meta get() = this@branch.meta
|
override val meta: Meta get() = this@branch.meta
|
||||||
|
|
||||||
override fun iterator(): Iterator<NamedData<T>> = iterator {
|
override fun iterator(): Iterator<NamedData<T>> = iterator {
|
||||||
for(d in this@branch){
|
for (d in this@branch) {
|
||||||
d.name.removeHeadOrNull(branchName)?.let { name ->
|
d.name.removeHeadOrNull(branchName)?.let { name ->
|
||||||
yield(d.data.named(name))
|
yield(d.data.named(name))
|
||||||
}
|
}
|
||||||
@ -101,7 +98,7 @@ public fun <T : Any> DataSet<T>.branch(branchName: Name): DataSet<T> = if (branc
|
|||||||
override val updates: Flow<Name> get() = this@branch.updates.mapNotNull { it.removeHeadOrNull(branchName) }
|
override val updates: Flow<Name> get() = this@branch.updates.mapNotNull { it.removeHeadOrNull(branchName) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <T : Any> DataSet<T>.branch(branchName: String): DataSet<T> = this@branch.branch(Name.parse(branchName))
|
public fun <T : Any> DataSet<T>.branch(branchName: String): DataSet<T> = this@branch.branch(branchName.parseAsName())
|
||||||
|
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
public suspend fun <T : Any> DataSet<T>.rootData(): Data<T>? = get(Name.EMPTY)
|
public suspend fun <T : Any> DataSet<T>.rootData(): Data<T>? = get(Name.EMPTY)
|
||||||
|
@ -101,14 +101,12 @@ public operator fun Meta.get(token: NameToken): Meta? = items[token]
|
|||||||
*
|
*
|
||||||
* If [name] is empty return current [Meta]
|
* If [name] is empty return current [Meta]
|
||||||
*/
|
*/
|
||||||
public operator fun Meta.get(name: Name): Meta? = this.getMeta(name)
|
public operator fun Meta?.get(name: Name): Meta? = this?.getMeta(name)
|
||||||
|
|
||||||
//TODO allow nullable receivers after Kotlin 1.7
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse [Name] from [key] using full name notation and pass it to [Meta.get]
|
* Parse [Name] from [key] using full name notation and pass it to [Meta.get]
|
||||||
*/
|
*/
|
||||||
public operator fun Meta.get(key: String): Meta? = this[Name.parse(key)]
|
public operator fun Meta?.get(key: String): Meta? = this?.get(key.parseAsName(true))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all items matching given name. The index of the last element, if present is used as a [Regex],
|
* Get all items matching given name. The index of the last element, if present is used as a [Regex],
|
||||||
@ -134,7 +132,7 @@ public fun Meta.getIndexed(name: Name): Map<String?, Meta> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Meta.getIndexed(name: String): Map<String?, Meta> = getIndexed(name.parseAsName())
|
public fun Meta.getIndexed(name: String): Map<String?, Meta> = getIndexed(name.parseAsName(true))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A meta node that ensures that all of its descendants has at least the same type.
|
* A meta node that ensures that all of its descendants has at least the same type.
|
||||||
@ -171,16 +169,16 @@ public operator fun <M : TypedMeta<M>> TypedMeta<M>.get(token: NameToken): M? =
|
|||||||
*
|
*
|
||||||
* If [name] is empty return current [Meta]
|
* If [name] is empty return current [Meta]
|
||||||
*/
|
*/
|
||||||
public tailrec operator fun <M : TypedMeta<M>> TypedMeta<M>.get(name: Name): M? = if (name.isEmpty()) {
|
public tailrec operator fun <M : TypedMeta<M>> TypedMeta<M>?.get(name: Name): M? = when {
|
||||||
self
|
this == null -> null
|
||||||
} else {
|
name.isEmpty() -> self
|
||||||
get(name.firstOrNull()!!)?.get(name.cutFirst())
|
else -> get(name.firstOrNull()!!)?.get(name.cutFirst())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse [Name] from [key] using full name notation and pass it to [TypedMeta.get]
|
* Parse [Name] from [key] using full name notation and pass it to [TypedMeta.get]
|
||||||
*/
|
*/
|
||||||
public operator fun <M : TypedMeta<M>> TypedMeta<M>.get(key: String): M? = this[Name.parse(key)]
|
public operator fun <M : TypedMeta<M>> TypedMeta<M>?.get(key: String): M? = this[key.parseAsName(true)]
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -223,7 +221,8 @@ public fun Meta.isEmpty(): Boolean = this === Meta.EMPTY
|
|||||||
public fun <M : TypedMeta<M>> TypedMeta<M>.getIndexed(name: Name): Map<String?, M> =
|
public fun <M : TypedMeta<M>> TypedMeta<M>.getIndexed(name: Name): Map<String?, M> =
|
||||||
(this as Meta).getIndexed(name) as Map<String?, M>
|
(this as Meta).getIndexed(name) as Map<String?, M>
|
||||||
|
|
||||||
public fun <M : TypedMeta<M>> TypedMeta<M>.getIndexed(name: String): Map<String?, Meta> = getIndexed(Name.parse(name))
|
public fun <M : TypedMeta<M>> TypedMeta<M>.getIndexed(name: String): Map<String?, Meta> =
|
||||||
|
getIndexed(name.parseAsName(true))
|
||||||
|
|
||||||
|
|
||||||
public val Meta?.string: String? get() = this?.value?.string
|
public val Meta?.string: String? get() = this?.value?.string
|
||||||
|
@ -77,7 +77,7 @@ public operator fun MetaDescriptor.get(name: Name): MetaDescriptor? = when (name
|
|||||||
else -> get(name.firstOrNull()!!.asName())?.get(name.cutFirst())
|
else -> get(name.firstOrNull()!!.asName())?.get(name.cutFirst())
|
||||||
}
|
}
|
||||||
|
|
||||||
public operator fun MetaDescriptor.get(name: String): MetaDescriptor? = get(Name.parse(name))
|
public operator fun MetaDescriptor.get(name: String): MetaDescriptor? = get(name.parseAsName(true))
|
||||||
|
|
||||||
public fun MetaDescriptor.validate(value: Value?): Boolean = if (value == null) {
|
public fun MetaDescriptor.validate(value: Value?): Boolean = if (value == null) {
|
||||||
valueRequirement != ValueRequirement.REQUIRED
|
valueRequirement != ValueRequirement.REQUIRED
|
||||||
|
@ -2,6 +2,7 @@ package space.kscience.dataforge.names
|
|||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import space.kscience.dataforge.misc.DFExperimental
|
import space.kscience.dataforge.misc.DFExperimental
|
||||||
|
import kotlin.native.concurrent.ThreadLocal
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,15 +56,15 @@ public class Name(public val tokens: List<NameToken>) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a [String] to name parsing it and extracting name tokens and index syntax.
|
* Convert a [String] to name parsing it and extracting name tokens and index syntax.
|
||||||
* This operation is rather heavy so it should be used with care in high performance code.
|
* This operation is rather heavy, so it should be used with care in high performance code.
|
||||||
*/
|
*/
|
||||||
public fun parse(string: String): Name{
|
public fun parse(string: String): Name {
|
||||||
if (string.isBlank()) return Name.EMPTY
|
if (string.isBlank()) return EMPTY
|
||||||
val tokens = sequence {
|
val tokens = sequence {
|
||||||
var bodyBuilder = StringBuilder()
|
var bodyBuilder = StringBuilder()
|
||||||
var queryBuilder = StringBuilder()
|
var queryBuilder = StringBuilder()
|
||||||
var bracketCount: Int = 0
|
var bracketCount = 0
|
||||||
var escape: Boolean = false
|
var escape = false
|
||||||
fun queryOn() = bracketCount > 0
|
fun queryOn() = bracketCount > 0
|
||||||
|
|
||||||
for (it in string) {
|
for (it in string) {
|
||||||
@ -76,9 +77,11 @@ public class Name(public val tokens: List<NameToken>) {
|
|||||||
}
|
}
|
||||||
escape = false
|
escape = false
|
||||||
}
|
}
|
||||||
|
|
||||||
it == '\\' -> {
|
it == '\\' -> {
|
||||||
escape = true
|
escape = true
|
||||||
}
|
}
|
||||||
|
|
||||||
queryOn() -> {
|
queryOn() -> {
|
||||||
when (it) {
|
when (it) {
|
||||||
'[' -> bracketCount++
|
'[' -> bracketCount++
|
||||||
@ -86,6 +89,7 @@ public class Name(public val tokens: List<NameToken>) {
|
|||||||
}
|
}
|
||||||
if (queryOn()) queryBuilder.append(it)
|
if (queryOn()) queryBuilder.append(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> when (it) {
|
else -> when (it) {
|
||||||
'.' -> {
|
'.' -> {
|
||||||
val query = if (queryBuilder.isEmpty()) null else queryBuilder.toString()
|
val query = if (queryBuilder.isEmpty()) null else queryBuilder.toString()
|
||||||
@ -93,6 +97,7 @@ public class Name(public val tokens: List<NameToken>) {
|
|||||||
bodyBuilder = StringBuilder()
|
bodyBuilder = StringBuilder()
|
||||||
queryBuilder = StringBuilder()
|
queryBuilder = StringBuilder()
|
||||||
}
|
}
|
||||||
|
|
||||||
'[' -> bracketCount++
|
'[' -> bracketCount++
|
||||||
']' -> error("Syntax error: closing bracket ] not have not matching open bracket")
|
']' -> error("Syntax error: closing bracket ] not have not matching open bracket")
|
||||||
else -> {
|
else -> {
|
||||||
@ -203,4 +208,14 @@ public fun Name.removeHeadOrNull(head: Name): Name? = if (startsWith(head)) {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun String.parseAsName(): Name = Name.parse(this)
|
@ThreadLocal
|
||||||
|
private val nameCache = HashMap<String, Name>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a string as name. If [cache], use global cache for parsed name to avoid multiple parsings.
|
||||||
|
*/
|
||||||
|
public fun String.parseAsName(cache: Boolean = false): Name = if (cache) {
|
||||||
|
nameCache.getOrPut(this) { Name.parse(this) }
|
||||||
|
} else {
|
||||||
|
Name.parse(this)
|
||||||
|
}
|
@ -15,16 +15,22 @@ public data class NameToken(val body: String, val index: String? = null) {
|
|||||||
if (body.isEmpty()) error("Syntax error: Name token body is empty")
|
if (body.isEmpty()) error("Syntax error: Name token body is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.escape() =
|
private val bodyEscaped by lazy {
|
||||||
replace("\\", "\\\\")
|
val escaped = buildString {
|
||||||
.replace(".", "\\.")
|
body.forEach {
|
||||||
.replace("[", "\\[")
|
if (it in escapedChars) {
|
||||||
.replace("]", "\\]")
|
append('\\')
|
||||||
|
}
|
||||||
|
append(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (escaped == body) body else escaped
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString(): String = if (hasIndex()) {
|
override fun toString(): String = if (hasIndex()) {
|
||||||
"${body.escape()}[$index]"
|
"${bodyEscaped}[$index]"
|
||||||
} else {
|
} else {
|
||||||
body.escape()
|
bodyEscaped
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,6 +45,8 @@ public data class NameToken(val body: String, val index: String? = null) {
|
|||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
|
||||||
|
private val escapedChars = listOf('\\', '.', '[', ']')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse name token from a string
|
* Parse name token from a string
|
||||||
*/
|
*/
|
||||||
@ -47,7 +55,7 @@ public data class NameToken(val body: String, val index: String? = null) {
|
|||||||
val body = string.substringBefore('[')
|
val body = string.substringBefore('[')
|
||||||
val index = string.substringAfter('[', "")
|
val index = string.substringAfter('[', "")
|
||||||
if (index.isNotEmpty() && index.endsWith(']')) error("NameToken with index must end with ']'")
|
if (index.isNotEmpty() && index.endsWith(']')) error("NameToken with index must end with ']'")
|
||||||
return NameToken(body,index.removeSuffix("]"))
|
return NameToken(body, index.removeSuffix("]"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,10 +28,12 @@ public fun Name.matches(pattern: Name): Boolean = when {
|
|||||||
length >= pattern.length
|
length >= pattern.length
|
||||||
&& Name(tokens.subList(0, pattern.length - 1)).matches(pattern.cutLast())
|
&& Name(tokens.subList(0, pattern.length - 1)).matches(pattern.cutLast())
|
||||||
}
|
}
|
||||||
|
|
||||||
pattern.startsWith(Name.MATCH_ALL_TOKEN) -> {
|
pattern.startsWith(Name.MATCH_ALL_TOKEN) -> {
|
||||||
length >= pattern.length
|
length >= pattern.length
|
||||||
&& Name(tokens.subList(tokens.size - pattern.length + 1, tokens.size)).matches(pattern.cutFirst())
|
&& Name(tokens.subList(tokens.size - pattern.length + 1, tokens.size)).matches(pattern.cutFirst())
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
tokens.indices.forEach {
|
tokens.indices.forEach {
|
||||||
val thisToken = tokens.getOrNull(it) ?: return false
|
val thisToken = tokens.getOrNull(it) ?: return false
|
||||||
@ -44,4 +46,4 @@ public fun Name.matches(pattern: Name): Boolean = when {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(DFExperimental::class)
|
@OptIn(DFExperimental::class)
|
||||||
public fun Name.matches(pattern: String): Boolean = matches(Name.parse(pattern))
|
public fun Name.matches(pattern: String): Boolean = matches(pattern.parseAsName(true))
|
Loading…
Reference in New Issue
Block a user