Optimize Name hashCode
This commit is contained in:
parent
233639f0b6
commit
0cc4dc0db7
@ -9,6 +9,7 @@
|
|||||||
- More fine-grained types in Action builders.
|
- More fine-grained types in Action builders.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- Meta `get` method allows nullable receiver
|
||||||
- `withDefault` functions do not add new keys to meta children and are consistent.
|
- `withDefault` functions do not add new keys to meta children and are consistent.
|
||||||
- `dataforge.meta.values` package is merged into `dataforge.meta` for better star imports
|
- `dataforge.meta.values` package is merged into `dataforge.meta` for better star imports
|
||||||
- Kotlin 1.7.20
|
- Kotlin 1.7.20
|
||||||
|
@ -5,6 +5,7 @@ import kotlinx.serialization.json.Json
|
|||||||
import space.kscience.dataforge.misc.Type
|
import space.kscience.dataforge.misc.Type
|
||||||
import space.kscience.dataforge.misc.unsafeCast
|
import space.kscience.dataforge.misc.unsafeCast
|
||||||
import space.kscience.dataforge.names.*
|
import space.kscience.dataforge.names.*
|
||||||
|
import kotlin.jvm.JvmName
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,6 +95,10 @@ public interface Meta : MetaRepr, MetaProvider {
|
|||||||
public val Meta.isLeaf: Boolean get() = items.isEmpty()
|
public val Meta.isLeaf: Boolean get() = items.isEmpty()
|
||||||
|
|
||||||
|
|
||||||
|
public operator fun Meta?.get(token: NameToken): Meta? = this?.items?.get(token)
|
||||||
|
|
||||||
|
@Deprecated("Use nullable receiver", level = DeprecationLevel.HIDDEN)
|
||||||
|
@JvmName("getNonNullable")
|
||||||
public operator fun Meta.get(token: NameToken): Meta? = items[token]
|
public operator fun Meta.get(token: NameToken): Meta? = items[token]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,11 +108,19 @@ public operator fun Meta.get(token: NameToken): Meta? = items[token]
|
|||||||
*/
|
*/
|
||||||
public operator fun Meta?.get(name: Name): Meta? = this?.getMeta(name)
|
public operator fun Meta?.get(name: Name): Meta? = this?.getMeta(name)
|
||||||
|
|
||||||
|
@Deprecated("Use nullable receiver", level = DeprecationLevel.HIDDEN)
|
||||||
|
@JvmName("getNonNullable")
|
||||||
|
public operator fun Meta.get(name: Name): Meta? = getMeta(name)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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?.get(key.parseAsName(true))
|
public operator fun Meta?.get(key: String): Meta? = this?.get(key.parseAsName(true))
|
||||||
|
|
||||||
|
@Deprecated("Use nullable receiver", level = DeprecationLevel.HIDDEN)
|
||||||
|
@JvmName("getNonNullable")
|
||||||
|
public operator fun Meta.get(key: String): Meta? = 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],
|
||||||
* against which indexes of elements are matched.
|
* against which indexes of elements are matched.
|
||||||
@ -162,7 +175,7 @@ public inline val <M : TypedMeta<M>> TypedMeta<M>.self: M get() = unsafeCast()
|
|||||||
|
|
||||||
//public typealias Meta = TypedMeta<*>
|
//public typealias Meta = TypedMeta<*>
|
||||||
|
|
||||||
public operator fun <M : TypedMeta<M>> TypedMeta<M>.get(token: NameToken): M? = items[token]
|
public operator fun <M : TypedMeta<M>> TypedMeta<M>?.get(token: NameToken): M? = this?.items?.get(token)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform recursive item search using given [name]. Each [NameToken] is treated as a name in [TypedMeta.items] of a parent node.
|
* Perform recursive item search using given [name]. Each [NameToken] is treated as a name in [TypedMeta.items] of a parent node.
|
||||||
@ -175,11 +188,19 @@ public tailrec operator fun <M : TypedMeta<M>> TypedMeta<M>?.get(name: Name): M?
|
|||||||
else -> get(name.firstOrNull()!!)?.get(name.cutFirst())
|
else -> get(name.firstOrNull()!!)?.get(name.cutFirst())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Use nullable receiver", level = DeprecationLevel.HIDDEN)
|
||||||
|
@JvmName("getNonNullable")
|
||||||
|
public operator fun <M : TypedMeta<M>> TypedMeta<M>.get(name: Name): M? = get(name)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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[key.parseAsName(true)]
|
public operator fun <M : TypedMeta<M>> TypedMeta<M>?.get(key: String): M? = this[key.parseAsName(true)]
|
||||||
|
|
||||||
|
@Deprecated("Use nullable receiver", level = DeprecationLevel.HIDDEN)
|
||||||
|
@JvmName("getNonNullable")
|
||||||
|
public operator fun <M : TypedMeta<M>> TypedMeta<M>.get(key: String): M? = get(key)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a sequence of [Name]-[Value] pairs using top-down traversal of the tree
|
* Get a sequence of [Name]-[Value] pairs using top-down traversal of the tree
|
||||||
|
@ -24,14 +24,14 @@ public class Name(public val tokens: List<NameToken>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
private val cachedHashCode = if (tokens.size == 1) {
|
||||||
return if (tokens.size == 1) {
|
tokens.first().hashCode()
|
||||||
tokens.first().hashCode()
|
} else {
|
||||||
} else {
|
tokens.hashCode()
|
||||||
tokens.hashCode()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int = cachedHashCode
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
public const val NAME_SEPARATOR: String = "."
|
public const val NAME_SEPARATOR: String = "."
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import space.kscience.dataforge.misc.DFExperimental
|
|||||||
* A name token could have appendix in square brackets called *index*
|
* A name token could have appendix in square brackets called *index*
|
||||||
*/
|
*/
|
||||||
@Serializable(NameTokenSerializer::class)
|
@Serializable(NameTokenSerializer::class)
|
||||||
public data class NameToken(val body: String, val index: String? = null) {
|
public class NameToken(public val body: String, public val index: String? = null) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (body.isEmpty()) error("Syntax error: Name token body is empty")
|
if (body.isEmpty()) error("Syntax error: Name token body is empty")
|
||||||
@ -33,6 +33,7 @@ public data class NameToken(val body: String, val index: String? = null) {
|
|||||||
bodyEscaped
|
bodyEscaped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return unescaped version of the [NameToken]. Should be used only for output because it is not possible to correctly
|
* Return unescaped version of the [NameToken]. Should be used only for output because it is not possible to correctly
|
||||||
* parse it back.
|
* parse it back.
|
||||||
@ -43,6 +44,22 @@ public data class NameToken(val body: String, val index: String? = null) {
|
|||||||
body
|
body
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (other == null || this::class != other::class) return false
|
||||||
|
|
||||||
|
other as NameToken
|
||||||
|
|
||||||
|
if (body != other.body) return false
|
||||||
|
if (index != other.index) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private val cachedHashCode = body.hashCode() * 31 + (index?.hashCode() ?: 0)
|
||||||
|
|
||||||
|
override fun hashCode(): Int = cachedHashCode
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
|
||||||
private val escapedChars = listOf('\\', '.', '[', ']')
|
private val escapedChars = listOf('\\', '.', '[', ']')
|
||||||
|
@ -33,7 +33,7 @@ public fun Meta.toDynamic(): dynamic {
|
|||||||
public class DynamicMeta(internal val obj: dynamic) : TypedMeta<DynamicMeta> {
|
public class DynamicMeta(internal val obj: dynamic) : TypedMeta<DynamicMeta> {
|
||||||
private fun keys(): Array<String> = js("Object").keys(obj) as Array<String>
|
private fun keys(): Array<String> = js("Object").keys(obj) as Array<String>
|
||||||
|
|
||||||
private fun isArray(@Suppress("UNUSED_PARAMETER") obj: dynamic): Boolean =
|
private fun isArray(obj: dynamic): Boolean =
|
||||||
js("Array").isArray(obj) as Boolean
|
js("Array").isArray(obj) as Boolean
|
||||||
|
|
||||||
private fun isPrimitive(obj: dynamic): Boolean =
|
private fun isPrimitive(obj: dynamic): Boolean =
|
||||||
|
Loading…
Reference in New Issue
Block a user