Name matching
This commit is contained in:
parent
ac8631e3a0
commit
366d32a04a
@ -1,5 +1,6 @@
|
||||
package hep.dataforge.names
|
||||
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||
@ -39,6 +40,18 @@ public class Name(public val tokens: List<NameToken>) {
|
||||
public companion object : KSerializer<Name> {
|
||||
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())
|
||||
|
||||
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