Name matching
This commit is contained in:
parent
ac8631e3a0
commit
366d32a04a
@ -1,5 +1,6 @@
|
|||||||
package hep.dataforge.names
|
package hep.dataforge.names
|
||||||
|
|
||||||
|
import hep.dataforge.meta.DFExperimental
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||||
@ -39,6 +40,18 @@ public class Name(public val tokens: List<NameToken>) {
|
|||||||
public companion object : KSerializer<Name> {
|
public companion object : KSerializer<Name> {
|
||||||
public const val NAME_SEPARATOR: String = "."
|
public const val NAME_SEPARATOR: String = "."
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match any single token (both body and index)
|
||||||
|
*/
|
||||||
|
@DFExperimental
|
||||||
|
public val MATCH_ANY_TOKEN: NameToken = NameToken("*")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token that allows to match the whole tail or the whole head of the name. Must match at least one token.
|
||||||
|
*/
|
||||||
|
@DFExperimental
|
||||||
|
public val MATCH_ALL_TOKEN: NameToken = NameToken("**")
|
||||||
|
|
||||||
public val EMPTY: Name = Name(emptyList())
|
public val EMPTY: Name = Name(emptyList())
|
||||||
|
|
||||||
override val descriptor: SerialDescriptor =
|
override val descriptor: SerialDescriptor =
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
package hep.dataforge.names
|
||||||
|
|
||||||
|
import hep.dataforge.meta.DFExperimental
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this token matches a given [NameToken]. The match successful if:
|
||||||
|
* * Token body matches pattern body as a regex
|
||||||
|
* * Index body matches pattern body as a regex of both are null
|
||||||
|
*/
|
||||||
|
@DFExperimental
|
||||||
|
public fun NameToken.matches(pattern: NameToken): Boolean {
|
||||||
|
if (pattern == Name.MATCH_ANY_TOKEN) return true
|
||||||
|
val bodyMatches = body.matches(pattern.body.toRegex())
|
||||||
|
val indexMatches = (index == null && pattern.index == null) || pattern.index?.let { patternIndex ->
|
||||||
|
(index ?: "").matches(patternIndex.toRegex())
|
||||||
|
} ?: false
|
||||||
|
return bodyMatches && indexMatches
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches all names in pattern according to [NameToken.matches] rules.
|
||||||
|
*/
|
||||||
|
@DFExperimental
|
||||||
|
public fun Name.matches(pattern: Name): Boolean = when {
|
||||||
|
pattern.endsWith(Name.MATCH_ALL_TOKEN) -> {
|
||||||
|
length >= pattern.length
|
||||||
|
&& Name(tokens.subList(0, pattern.length - 1)).matches(pattern.cutLast())
|
||||||
|
}
|
||||||
|
pattern.startsWith(Name.MATCH_ALL_TOKEN) -> {
|
||||||
|
length >= pattern.length
|
||||||
|
&& Name(tokens.subList(tokens.size - pattern.length + 1, tokens.size)).matches(pattern.cutFirst())
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
tokens.indices.forEach {
|
||||||
|
val thisToken = tokens.getOrNull(it) ?: return false
|
||||||
|
if (thisToken == Name.MATCH_ALL_TOKEN) error("Match-all token in the middle of the name is not supported yet")
|
||||||
|
val patternToken = pattern.tokens.getOrNull(it) ?: return false
|
||||||
|
if (!thisToken.matches(patternToken)) return false
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(DFExperimental::class)
|
||||||
|
public fun Name.matches(pattern: String): Boolean = matches(pattern.toName())
|
Loading…
Reference in New Issue
Block a user