stdlib: Rewrite deep content operations for Arrays

This commit is contained in:
Ilya Matveev
2017-04-24 16:05:52 +07:00
committed by ilmat192
parent f958573d05
commit a4f3691a7b
+60 -66
View File
@@ -11450,36 +11450,44 @@ public inline fun <T> Array<out T>.subarrayContentToString(offset: Int, length:
*/ */
@SinceKotlin("1.1") @SinceKotlin("1.1")
public infix fun <T> Array<out T>.contentDeepEquals(other: Array<out T>): Boolean { public infix fun <T> Array<out T>.contentDeepEquals(other: Array<out T>): Boolean {
if (this === other) if (this === other) {
return true return true
}
if (size != other.size) if (this.size != other.size) {
return false return false
}
for (i in indices) { for (i in indices) {
val e1 = this[i] val v1 = this[i]
val e2 = other[i] val v2 = other[i]
if (e1 === e2) if (v1 == null || v2 == null) {
continue if (v1 == v2) {
if (e1 == null) continue
return false } else {
return false
// Figure out whether the two elements are equal }
val eq = when { }
e1 is Array<*> && e2 is Array<*> -> e1 contentDeepEquals e2
e1 is ByteArray && e2 is ByteArray -> e1 contentEquals e2 // TODO: Do a typecheck like if(v1.class == v2.class) return false
e1 is ShortArray && e2 is ShortArray -> e1 contentEquals e2 // Cases:
e1 is IntArray && e2 is IntArray -> e1 contentEquals e2 // Array<T>
e1 is LongArray && e2 is LongArray -> e1 contentEquals e2 // Primitive array
e1 is CharArray && e2 is CharArray -> e1 contentEquals e2 // Some value (not an array)
e1 is FloatArray && e2 is FloatArray -> e1 contentEquals e2
e1 is DoubleArray && e2 is DoubleArray -> e1 contentEquals e2 when {
e1 is BooleanArray && e2 is BooleanArray -> e1 contentEquals e2 v1 is Array<*> && v2 is Array<*> -> if (!v1.contentDeepEquals(v2)) return false
else -> e1 == e2 v1 is ByteArray && v2 is ByteArray -> if (!v1.contentEquals(v2)) return false
v1 is ShortArray && v2 is ShortArray -> if (!v1.contentEquals(v2)) return false
v1 is IntArray && v2 is IntArray -> if (!v1.contentEquals(v2)) return false
v1 is LongArray && v2 is LongArray -> if (!v1.contentEquals(v2)) return false
v1 is FloatArray && v2 is FloatArray -> if (!v1.contentEquals(v2)) return false
v1 is DoubleArray && v2 is DoubleArray -> if (!v1.contentEquals(v2)) return false
v1 is CharArray && v2 is CharArray -> if (!v1.contentEquals(v2)) return false
v1 is BooleanArray && v2 is BooleanArray -> if (!v1.contentEquals(v2)) return false
else -> if (v1 != v2) return false
} }
if (!eq)
return false
} }
return true return true
@@ -11515,56 +11523,42 @@ public fun <T> Array<out T>.contentDeepHashCode(): Int {
*/ */
@SinceKotlin("1.1") @SinceKotlin("1.1")
public fun <T> Array<out T>.contentDeepToString(): String { public fun <T> Array<out T>.contentDeepToString(): String {
var bufLen = 20 * size val length = if (size * 5 + 2 > 0) size * 5 + 2 else Int.MAX_VALUE
if (size != 0 && bufLen <= 0) val result = StringBuilder(length)
bufLen = Int.MAX_VALUE contentDeepToStringInternal(result, mutableSetOf())
val buf = StringBuilder(bufLen) return result.toString()
contentDeepToString(buf, mutableSetOf())
return buf.toString()
} }
/** private fun <T> Array<out T>.contentDeepToStringInternal(result: StringBuilder, processed: MutableSet<Array<*>>) {
* Internal recursive function to build a string for [contentDeepToString]. if (this in processed) {
*/ result.append("[...]")
private fun <T> Array<out T>.contentDeepToString(buf: StringBuilder, dejaVu: MutableSet<Array<Any?>>) {
if (size == 0) {
buf.append("[]")
return return
} }
processed.add(this)
result.append('[')
val iMax = size - 1 for (i in indices) {
@Suppress("UNCHECKED_CAST") if (i != 0) {
dejaVu.add(this as Array<Any?>) // TODO: Is the cast correct? result.append(", ")
buf.append('[') }
var i = 0 val element = this[i]
while (true) { when (element) {
val element = this[i] null -> result.append("null")
when { is Array<*> -> element.contentDeepToStringInternal(result, processed)
element is Array<*> -> { is ByteArray -> result.append(element.contentToString())
@Suppress("UNCHECKED_CAST") is ShortArray -> result.append(element.contentToString())
if (dejaVu.contains(element as Array<Any?>)) { is IntArray -> result.append(element.contentToString())
buf.append("[...]") is LongArray -> result.append(element.contentToString())
} else { is FloatArray -> result.append(element.contentToString())
element.contentDeepToString(buf, dejaVu) is DoubleArray -> result.append(element.contentToString())
} is CharArray -> result.append(element.contentToString())
} is BooleanArray -> result.append(element.contentToString())
element is ByteArray -> buf.append(element.contentToString()) else -> result.append(element.toString())
element is ShortArray -> buf.append(element.contentToString())
element is IntArray -> buf.append(element.contentToString())
element is LongArray -> buf.append(element.contentToString())
element is CharArray -> buf.append(element.contentToString())
element is FloatArray -> buf.append(element.contentToString())
element is DoubleArray -> buf.append(element.contentToString())
element is BooleanArray -> buf.append(element.contentToString())
else -> buf.append(element.toString())
} }
if (i == iMax)
break
buf.append(", ")
i++
} }
buf.append(']')
dejaVu.remove(this) result.append(']')
processed.remove(this)
} }
/** /**