Implement contains extension functions for URanges (KT-26378)
This commit is contained in:
committed by
Ilya Gorbunov
parent
cb587893c0
commit
bf83f0e070
@@ -93,6 +93,60 @@ public inline operator fun ULongRange.contains(element: ULong?): Boolean {
|
|||||||
return element != null && contains(element)
|
return element != null && contains(element)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the specified [value] belongs to this range.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
public operator fun UIntRange.contains(value: UByte): Boolean {
|
||||||
|
return contains(value.toUInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the specified [value] belongs to this range.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
public operator fun ULongRange.contains(value: UByte): Boolean {
|
||||||
|
return contains(value.toULong())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the specified [value] belongs to this range.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
public operator fun ULongRange.contains(value: UInt): Boolean {
|
||||||
|
return contains(value.toULong())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the specified [value] belongs to this range.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
public operator fun UIntRange.contains(value: ULong): Boolean {
|
||||||
|
return (value shr UInt.SIZE_BITS) == 0uL && contains(value.toUInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the specified [value] belongs to this range.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
public operator fun UIntRange.contains(value: UShort): Boolean {
|
||||||
|
return contains(value.toUInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the specified [value] belongs to this range.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
public operator fun ULongRange.contains(value: UShort): Boolean {
|
||||||
|
return contains(value.toULong())
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a progression from this value down to the specified [to] value with the step -1.
|
* Returns a progression from this value down to the specified [to] value with the step -1.
|
||||||
*
|
*
|
||||||
@@ -187,7 +241,8 @@ public infix fun ULongProgression.step(step: Long): ULongProgression {
|
|||||||
@SinceKotlin("1.3")
|
@SinceKotlin("1.3")
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
public infix fun UByte.until(to: UByte): UIntRange {
|
public infix fun UByte.until(to: UByte): UIntRange {
|
||||||
return this.toUInt() .. (to.toUInt() - 1u).toUInt()
|
if (to <= UByte.MIN_VALUE) return UIntRange.EMPTY
|
||||||
|
return this.toUInt() .. (to - 1u).toUInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -222,6 +277,7 @@ public infix fun ULong.until(to: ULong): ULongRange {
|
|||||||
@SinceKotlin("1.3")
|
@SinceKotlin("1.3")
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
public infix fun UShort.until(to: UShort): UIntRange {
|
public infix fun UShort.until(to: UShort): UIntRange {
|
||||||
return this.toUInt() .. (to.toUInt() - 1u).toUInt()
|
if (to <= UShort.MIN_VALUE) return UIntRange.EMPTY
|
||||||
|
return this.toUInt() .. (to - 1u).toUInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -416,15 +416,11 @@ public class RangeTest {
|
|||||||
assertFailsWithIllegalArgument { CharProgression.fromClosedRange('a', 'b', Int.MIN_VALUE) }
|
assertFailsWithIllegalArgument { CharProgression.fromClosedRange('a', 'b', Int.MIN_VALUE) }
|
||||||
assertFailsWithIllegalArgument { IntProgression.fromClosedRange(0, 1, Int.MIN_VALUE) }
|
assertFailsWithIllegalArgument { IntProgression.fromClosedRange(0, 1, Int.MIN_VALUE) }
|
||||||
assertFailsWithIllegalArgument { LongProgression.fromClosedRange(0, 1, Long.MIN_VALUE) }
|
assertFailsWithIllegalArgument { LongProgression.fromClosedRange(0, 1, Long.MIN_VALUE) }
|
||||||
assertFailsWithIllegalArgument { UIntProgression.fromClosedRange(0u, 1u, Int.MIN_VALUE) }
|
|
||||||
assertFailsWithIllegalArgument { ULongProgression.fromClosedRange(0u, 1u, Long.MIN_VALUE) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun randomInEmptyRange() {
|
@Test fun randomInEmptyRange() {
|
||||||
assertFailsWith<NoSuchElementException> { IntRange.EMPTY.random() }
|
assertFailsWith<NoSuchElementException> { IntRange.EMPTY.random() }
|
||||||
assertFailsWith<NoSuchElementException> { LongRange.EMPTY.random() }
|
assertFailsWith<NoSuchElementException> { LongRange.EMPTY.random() }
|
||||||
assertFailsWith<NoSuchElementException> { CharRange.EMPTY.random() }
|
assertFailsWith<NoSuchElementException> { CharRange.EMPTY.random() }
|
||||||
assertFailsWith<NoSuchElementException> { UIntRange.EMPTY.random() }
|
|
||||||
assertFailsWith<NoSuchElementException> { ULongRange.EMPTY.random() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,244 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ranges
|
||||||
|
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
public class URangeTest {
|
||||||
|
@Test
|
||||||
|
fun uintRange() {
|
||||||
|
val range = 9u..(-5).toUInt()
|
||||||
|
assertFalse((-4).toUInt() in range)
|
||||||
|
assertFalse((-1).toUInt() in range)
|
||||||
|
assertFalse(0u in range)
|
||||||
|
assertFalse(3u in range)
|
||||||
|
assertFalse(8u in range)
|
||||||
|
|
||||||
|
assertTrue(9u in range)
|
||||||
|
assertTrue(10u in range)
|
||||||
|
assertTrue(9000u in range)
|
||||||
|
assertTrue((-1000).toUInt() in range)
|
||||||
|
assertTrue((-6).toUInt() in range)
|
||||||
|
assertTrue((-5).toUInt() in range)
|
||||||
|
|
||||||
|
assertFalse(range.isEmpty())
|
||||||
|
|
||||||
|
assertTrue(9u in (range as ClosedRange<UInt>))
|
||||||
|
assertFalse((range as ClosedRange<UInt>).isEmpty())
|
||||||
|
|
||||||
|
assertTrue(12.toUShort() in range)
|
||||||
|
assertTrue(12.toUByte() in range)
|
||||||
|
assertTrue(12.toULong() in range)
|
||||||
|
|
||||||
|
assertFalse((-1).toULong() in range)
|
||||||
|
assertFalse((-1000).toULong() in range)
|
||||||
|
|
||||||
|
assertFalse(null in range)
|
||||||
|
assertTrue(12u as UInt? in range)
|
||||||
|
assertFalse((-3).toUInt() as UInt? in range)
|
||||||
|
|
||||||
|
val openRange = 1u until 10u
|
||||||
|
assertTrue(9u in openRange)
|
||||||
|
assertFalse(10u in openRange)
|
||||||
|
|
||||||
|
assertTrue((1u until UInt.MIN_VALUE).isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun ubyteRange() {
|
||||||
|
val range = 9.toUByte()..(-5).toUByte()
|
||||||
|
assertFalse((-4).toUByte() in range)
|
||||||
|
assertFalse((-1).toUByte() in range)
|
||||||
|
assertFalse(0.toUByte() in range)
|
||||||
|
assertFalse(3.toUByte() in range)
|
||||||
|
assertFalse(8.toUByte() in range)
|
||||||
|
|
||||||
|
assertTrue(9.toUByte() in range)
|
||||||
|
assertTrue(10.toUByte() in range)
|
||||||
|
assertTrue(111.toUByte() in range)
|
||||||
|
assertTrue((-100).toUByte() in range)
|
||||||
|
assertTrue((-6).toUByte() in range)
|
||||||
|
assertTrue((-5).toUByte() in range)
|
||||||
|
|
||||||
|
assertFalse(range.isEmpty())
|
||||||
|
|
||||||
|
assertTrue(12.toUShort() in range)
|
||||||
|
assertTrue(12.toUInt() in range)
|
||||||
|
assertTrue(12.toULong() in range)
|
||||||
|
|
||||||
|
assertFalse((-1).toUShort() in range)
|
||||||
|
assertFalse((-1000).toUInt() in range)
|
||||||
|
|
||||||
|
// assertTrue(1.toUByte() as UByte? in range) // expected not to compile
|
||||||
|
|
||||||
|
val openRange = 1.toUByte() until 10.toUByte()
|
||||||
|
assertTrue(9.toUByte() in openRange)
|
||||||
|
assertFalse(10.toUByte() in openRange)
|
||||||
|
|
||||||
|
assertTrue((UByte.MAX_VALUE until UByte.MIN_VALUE).isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun ushortRange() {
|
||||||
|
val range = 9.toUShort()..(-5).toUShort()
|
||||||
|
assertFalse((-1).toUShort() in range)
|
||||||
|
assertFalse((-4).toUShort() in range)
|
||||||
|
assertFalse(0.toUShort() in range)
|
||||||
|
assertFalse(3.toUShort() in range)
|
||||||
|
assertFalse(8.toUShort() in range)
|
||||||
|
|
||||||
|
assertTrue(9.toUShort() in range)
|
||||||
|
assertTrue(10.toUShort() in range)
|
||||||
|
assertTrue(239.toUShort() in range)
|
||||||
|
assertTrue((-1000).toUShort() in range)
|
||||||
|
assertTrue((-6).toUShort() in range)
|
||||||
|
assertTrue((-5).toUShort() in range)
|
||||||
|
|
||||||
|
assertFalse(range.isEmpty())
|
||||||
|
|
||||||
|
assertTrue(12.toUByte() in range)
|
||||||
|
assertTrue(12.toUInt() in range)
|
||||||
|
assertTrue(12.toULong() in range)
|
||||||
|
|
||||||
|
assertFalse((-1).toUInt() in range)
|
||||||
|
assertFalse((-1000).toULong() in range)
|
||||||
|
|
||||||
|
// assertTrue(1.toUShort() as UShort? in range) // expected not to compile
|
||||||
|
|
||||||
|
val openRange = 1.toUShort() until 10.toUShort()
|
||||||
|
assertTrue(9.toUShort() in openRange)
|
||||||
|
assertFalse(10.toUShort() in openRange)
|
||||||
|
|
||||||
|
assertTrue((0.toUShort() until UShort.MIN_VALUE).isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun ulongRange() {
|
||||||
|
val range = 9uL..(-5).toULong()
|
||||||
|
assertFalse((-1).toULong() in range)
|
||||||
|
assertFalse((-4).toULong() in range)
|
||||||
|
assertFalse(0uL in range)
|
||||||
|
assertFalse(3uL in range)
|
||||||
|
assertFalse(8uL in range)
|
||||||
|
|
||||||
|
assertTrue(9uL in range)
|
||||||
|
assertTrue(10uL in range)
|
||||||
|
assertTrue(10000000uL in range)
|
||||||
|
assertTrue((-10000000).toULong() in range)
|
||||||
|
assertTrue((-6).toULong() in range)
|
||||||
|
assertTrue((-5).toULong() in range)
|
||||||
|
|
||||||
|
assertFalse(range.isEmpty())
|
||||||
|
|
||||||
|
assertTrue((-5).toULong() in (range as ClosedRange<ULong>))
|
||||||
|
assertFalse((range as ClosedRange<ULong>).isEmpty())
|
||||||
|
|
||||||
|
assertTrue(12.toUByte() in range)
|
||||||
|
assertTrue(12.toUShort() in range)
|
||||||
|
assertTrue(12.toUInt() in range)
|
||||||
|
|
||||||
|
assertFalse(null in range)
|
||||||
|
assertTrue(12uL as ULong? in range)
|
||||||
|
assertFalse((-3).toULong() as ULong? in range)
|
||||||
|
|
||||||
|
val openRange = 1uL until 10uL
|
||||||
|
assertTrue(9uL in openRange)
|
||||||
|
assertFalse(10uL in openRange)
|
||||||
|
|
||||||
|
assertTrue((0uL until ULong.MIN_VALUE).isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("EmptyRange")
|
||||||
|
@Test
|
||||||
|
fun isEmpty() {
|
||||||
|
assertTrue((2u..1u).isEmpty())
|
||||||
|
assertTrue((2uL..0uL).isEmpty())
|
||||||
|
assertTrue(((-1).toUShort()..1.toUShort()).isEmpty())
|
||||||
|
assertTrue(((-5).toUByte()..0.toUByte()).isEmpty())
|
||||||
|
|
||||||
|
assertTrue((1u downTo 2u).isEmpty())
|
||||||
|
assertTrue((0uL downTo 2uL).isEmpty())
|
||||||
|
assertFalse((2u downTo 1u).isEmpty())
|
||||||
|
assertFalse((2uL downTo 0uL).isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("ReplaceAssertBooleanWithAssertEquality", "EmptyRange")
|
||||||
|
@Test
|
||||||
|
fun emptyEquals() {
|
||||||
|
assertTrue(UIntRange.EMPTY == UIntRange.EMPTY)
|
||||||
|
assertEquals(UIntRange.EMPTY, UIntRange.EMPTY)
|
||||||
|
assertEquals(0uL..42uL, 0uL..42uL)
|
||||||
|
assertEquals(0uL..4200000042000000uL, 0uL..4200000042000000uL)
|
||||||
|
assertEquals(3u downTo 0u, 3u downTo 0u)
|
||||||
|
|
||||||
|
assertEquals(2u..1u, 1u..0u)
|
||||||
|
assertEquals(2uL..1uL, 1uL..0uL)
|
||||||
|
assertEquals(2u.toUShort()..1u.toUShort(), 1u.toUShort()..0u.toUShort())
|
||||||
|
assertEquals(2u.toUByte()..1u.toUByte(), 1u.toUByte()..0u.toUByte())
|
||||||
|
|
||||||
|
assertTrue(1u downTo 2u == 2u downTo 3u)
|
||||||
|
assertTrue(0uL downTo (-1).toULong() == (-2).toULong() downTo (-1).toULong())
|
||||||
|
|
||||||
|
assertFalse(0u..1u == UIntRange.EMPTY)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("EmptyRange")
|
||||||
|
@Test
|
||||||
|
fun emptyHashCode() {
|
||||||
|
assertEquals((0u..42u).hashCode(), (0u..42u).hashCode())
|
||||||
|
|
||||||
|
assertEquals(((-1).toUInt()..0u).hashCode(), UIntRange.EMPTY.hashCode())
|
||||||
|
assertEquals((2uL..1uL).hashCode(), (1uL..0uL).hashCode())
|
||||||
|
assertEquals(((-1).toUShort()..(-2).toUShort()).hashCode(), (42.toUShort()..0.toUShort()).hashCode())
|
||||||
|
assertEquals(((-1).toUByte()..(-2).toUByte()).hashCode(), (42.toUByte()..0.toUByte()).hashCode())
|
||||||
|
|
||||||
|
assertEquals((1u downTo 2u).hashCode(), (2u downTo 3U).hashCode())
|
||||||
|
assertEquals((1UL downTo 2uL).hashCode(), (2UL downTo 3UL).hashCode())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun assertFailsWithIllegalArgument(f: () -> Unit) = assertFailsWith<IllegalArgumentException> { f() }
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun illegalProgressionCreation() {
|
||||||
|
// create Progression explicitly with increment = 0
|
||||||
|
assertFailsWithIllegalArgument { UIntProgression.fromClosedRange(0u, 5u, 0) }
|
||||||
|
assertFailsWithIllegalArgument { ULongProgression.fromClosedRange(0uL, 5uL, 0) }
|
||||||
|
|
||||||
|
|
||||||
|
assertFailsWithIllegalArgument { 0u..5u step 0 }
|
||||||
|
assertFailsWithIllegalArgument { 0.toUByte()..5.toUByte() step 0 }
|
||||||
|
assertFailsWithIllegalArgument { 0.toUShort()..5.toUShort() step 0 }
|
||||||
|
assertFailsWithIllegalArgument { 0uL..5uL step 0 }
|
||||||
|
|
||||||
|
assertFailsWithIllegalArgument { (-5).toUInt() downTo 0u step 0 }
|
||||||
|
assertFailsWithIllegalArgument { (-5).toUByte() downTo 0.toUByte() step 0 }
|
||||||
|
assertFailsWithIllegalArgument { (-5).toUShort() downTo 0.toUShort() step 0 }
|
||||||
|
assertFailsWithIllegalArgument { (-5).toULong() downTo 0uL step 0L }
|
||||||
|
|
||||||
|
assertFailsWithIllegalArgument { 0u..5u step -2 }
|
||||||
|
assertFailsWithIllegalArgument { 0.toUByte()..5.toUByte() step -2 }
|
||||||
|
assertFailsWithIllegalArgument { 0.toUShort()..5.toUShort() step -2 }
|
||||||
|
assertFailsWithIllegalArgument { 0uL..5uL step -2L }
|
||||||
|
|
||||||
|
|
||||||
|
assertFailsWithIllegalArgument { (-5).toUInt() downTo 0u step -2 }
|
||||||
|
assertFailsWithIllegalArgument { (-5).toUByte() downTo 0.toUByte() step -2 }
|
||||||
|
assertFailsWithIllegalArgument { (-5).toUShort() downTo 0.toUShort() step -2 }
|
||||||
|
assertFailsWithIllegalArgument { (-5).toULong() downTo 0uL step -2L }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun stepSizeIsTooLow() {
|
||||||
|
assertFailsWithIllegalArgument { UIntProgression.fromClosedRange(0u, 1u, Int.MIN_VALUE) }
|
||||||
|
assertFailsWithIllegalArgument { ULongProgression.fromClosedRange(0u, 1u, Long.MIN_VALUE) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun randomInEmptyRange() {
|
||||||
|
assertFailsWith<NoSuchElementException> { UIntRange.EMPTY.random() }
|
||||||
|
assertFailsWith<NoSuchElementException> { ULongRange.EMPTY.random() }
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -4256,6 +4256,12 @@ public final class kotlin/ranges/ULongRange$Companion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class kotlin/ranges/URangesKt {
|
public final class kotlin/ranges/URangesKt {
|
||||||
|
public static final fun contains-68kG9v0 (Lkotlin/ranges/UIntRange;B)Z
|
||||||
|
public static final fun contains-Gab390E (Lkotlin/ranges/ULongRange;I)Z
|
||||||
|
public static final fun contains-ULb-yJY (Lkotlin/ranges/ULongRange;B)Z
|
||||||
|
public static final fun contains-ZsK3CEQ (Lkotlin/ranges/UIntRange;S)Z
|
||||||
|
public static final fun contains-fz5IDCE (Lkotlin/ranges/UIntRange;J)Z
|
||||||
|
public static final fun contains-uhHAxoY (Lkotlin/ranges/ULongRange;S)Z
|
||||||
public static final fun downTo-5PvTz6A (SS)Lkotlin/ranges/UIntProgression;
|
public static final fun downTo-5PvTz6A (SS)Lkotlin/ranges/UIntProgression;
|
||||||
public static final fun downTo-J1ME1BU (II)Lkotlin/ranges/UIntProgression;
|
public static final fun downTo-J1ME1BU (II)Lkotlin/ranges/UIntProgression;
|
||||||
public static final fun downTo-Kr8caGY (BB)Lkotlin/ranges/UIntProgression;
|
public static final fun downTo-Kr8caGY (BB)Lkotlin/ranges/UIntProgression;
|
||||||
|
|||||||
@@ -20,13 +20,18 @@ object RangeOps : TemplateGroupBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> Collection<T>.permutations(): List<Pair<T, T>> = flatMap { a -> map { b -> a to b } }
|
private fun shouldCheckForConversionOverflow(fromType: PrimitiveType, toType: PrimitiveType): Boolean {
|
||||||
|
return toType.isIntegral() && fromType.capacity > toType.capacity ||
|
||||||
|
toType.isUnsigned() && fromType.capacityUnsigned > toType.capacityUnsigned
|
||||||
|
}
|
||||||
|
|
||||||
private val numericPrimitives = PrimitiveType.numericPrimitives
|
private fun <T> Collection<T>.combinations(): List<Pair<T, T>> = flatMap { a -> map { b -> a to b } }
|
||||||
private val numericPermutations = numericPrimitives.permutations()
|
|
||||||
private val primitivePermutations = numericPermutations + (PrimitiveType.Char to PrimitiveType.Char)
|
private val numericCombinations = PrimitiveType.numericPrimitives.combinations()
|
||||||
private val integralPermutations = primitivePermutations.filter { it.first.isIntegral() && it.second.isIntegral() }
|
private val primitiveCombinations = numericCombinations + (PrimitiveType.Char to PrimitiveType.Char)
|
||||||
private val unsignedPermutations = PrimitiveType.unsignedPrimitives.map { it to it }
|
private val integralCombinations = primitiveCombinations.filter { it.first.isIntegral() && it.second.isIntegral() }
|
||||||
|
private val unsignedCombinations = PrimitiveType.unsignedPrimitives.combinations()
|
||||||
|
private val unsignedMappings = PrimitiveType.unsignedPrimitives.map { it to it }
|
||||||
|
|
||||||
val PrimitiveType.stepType get() = when(this) {
|
val PrimitiveType.stepType get() = when(this) {
|
||||||
PrimitiveType.Char -> "Int"
|
PrimitiveType.Char -> "Int"
|
||||||
@@ -72,7 +77,7 @@ object RangeOps : TemplateGroupBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val f_downTo = fn("downTo(to: Primitive)").byTwoPrimitives {
|
val f_downTo = fn("downTo(to: Primitive)").byTwoPrimitives {
|
||||||
include(Primitives, integralPermutations + unsignedPermutations)
|
include(Primitives, integralCombinations + unsignedMappings)
|
||||||
} builderWith { (fromType, toType) ->
|
} builderWith { (fromType, toType) ->
|
||||||
val elementType = rangeElementType(fromType, toType)
|
val elementType = rangeElementType(fromType, toType)
|
||||||
val progressionType = elementType.name + "Progression"
|
val progressionType = elementType.name + "Progression"
|
||||||
@@ -107,7 +112,7 @@ object RangeOps : TemplateGroupBase() {
|
|||||||
|
|
||||||
|
|
||||||
val f_until = fn("until(to: Primitive)").byTwoPrimitives {
|
val f_until = fn("until(to: Primitive)").byTwoPrimitives {
|
||||||
include(Primitives, integralPermutations + unsignedPermutations)
|
include(Primitives, integralCombinations + unsignedMappings)
|
||||||
} builderWith { (fromType, toType) ->
|
} builderWith { (fromType, toType) ->
|
||||||
infix()
|
infix()
|
||||||
signature("until(to: $toType)")
|
signature("until(to: $toType)")
|
||||||
@@ -115,7 +120,6 @@ object RangeOps : TemplateGroupBase() {
|
|||||||
val elementType = rangeElementType(fromType, toType)
|
val elementType = rangeElementType(fromType, toType)
|
||||||
val progressionType = elementType.name + "Range"
|
val progressionType = elementType.name + "Range"
|
||||||
returns(progressionType)
|
returns(progressionType)
|
||||||
val minValue = if (elementType == PrimitiveType.Char) "'\\u0000'" else "$elementType.MIN_VALUE"
|
|
||||||
|
|
||||||
doc {
|
doc {
|
||||||
"""
|
"""
|
||||||
@@ -125,16 +129,15 @@ object RangeOps : TemplateGroupBase() {
|
|||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val minValue = when {
|
||||||
|
elementType == PrimitiveType.Char -> "'\\u0000'"
|
||||||
|
elementType.isUnsigned() -> "$toType.MIN_VALUE"
|
||||||
|
else -> "$elementType.MIN_VALUE"
|
||||||
|
}
|
||||||
val fromExpr = if (elementType == fromType) "this" else "this.to$elementType()"
|
val fromExpr = if (elementType == fromType) "this" else "this.to$elementType()"
|
||||||
val u = if (elementType in PrimitiveType.unsignedPrimitives) "u" else ""
|
val u = if (elementType.isUnsigned()) "u" else ""
|
||||||
|
|
||||||
if (elementType == toType) {
|
if (elementType == toType || elementType.isUnsigned()) {
|
||||||
// hack to work around incorrect char overflow behavior in JVM and int overflow behavior in JS
|
|
||||||
val toExpr = when (toType) {
|
|
||||||
PrimitiveType.Char -> "to.toInt()"
|
|
||||||
PrimitiveType.Int -> "to.toLong()"
|
|
||||||
else -> "to"
|
|
||||||
}
|
|
||||||
body {
|
body {
|
||||||
// <= instead of == for JS
|
// <= instead of == for JS
|
||||||
"""
|
"""
|
||||||
@@ -148,7 +151,7 @@ object RangeOps : TemplateGroupBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val f_contains = fn("contains(value: Primitive)").byTwoPrimitives {
|
val f_contains = fn("contains(value: Primitive)").byTwoPrimitives {
|
||||||
include(Ranges, numericPermutations)
|
include(Ranges, numericCombinations)
|
||||||
filter { _, (rangeType, itemType) -> rangeType != itemType }
|
filter { _, (rangeType, itemType) -> rangeType != itemType }
|
||||||
} builderWith { (rangeType, itemType) ->
|
} builderWith { (rangeType, itemType) ->
|
||||||
operator()
|
operator()
|
||||||
@@ -158,14 +161,15 @@ object RangeOps : TemplateGroupBase() {
|
|||||||
if (rangeType.isIntegral() != itemType.isIntegral()) {
|
if (rangeType.isIntegral() != itemType.isIntegral()) {
|
||||||
deprecate(Deprecation("This `contains` operation mixing integer and floating point arguments has ambiguous semantics and is going to be removed.", level = DeprecationLevel.WARNING))
|
deprecate(Deprecation("This `contains` operation mixing integer and floating point arguments has ambiguous semantics and is going to be removed.", level = DeprecationLevel.WARNING))
|
||||||
}
|
}
|
||||||
|
|
||||||
platformName("${rangeType.name.decapitalize()}RangeContains")
|
platformName("${rangeType.name.decapitalize()}RangeContains")
|
||||||
returns("Boolean")
|
returns("Boolean")
|
||||||
doc { "Checks if the specified [value] belongs to this range." }
|
doc { "Checks if the specified [value] belongs to this range." }
|
||||||
body {
|
body {
|
||||||
if (rangeType.capacity > itemType.capacity || !rangeType.isIntegral())
|
if (shouldCheckForConversionOverflow(fromType = itemType, toType = rangeType))
|
||||||
"return contains(value.to$rangeType())"
|
|
||||||
else
|
|
||||||
"return value.to${rangeType}ExactOrNull().let { if (it != null) contains(it) else false }"
|
"return value.to${rangeType}ExactOrNull().let { if (it != null) contains(it) else false }"
|
||||||
|
else
|
||||||
|
"return contains(value.to$rangeType())"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,9 +192,28 @@ object RangeOps : TemplateGroupBase() {
|
|||||||
body { "return element != null && contains(element)" }
|
body { "return element != null && contains(element)" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val f_contains_unsigned = fn("contains(element: Primitive)").byTwoPrimitives {
|
||||||
|
include(RangesOfPrimitives, unsignedCombinations)
|
||||||
|
filter { _, (rangeType, itemType) -> rangeType in rangePrimitives && rangeType != itemType }
|
||||||
|
} builderWith { (rangeType, itemType) ->
|
||||||
|
operator()
|
||||||
|
signature("contains(value: $itemType)")
|
||||||
|
returns("Boolean")
|
||||||
|
|
||||||
|
since("1.3")
|
||||||
|
doc { "Checks if the specified [value] belongs to this range." }
|
||||||
|
|
||||||
|
body {
|
||||||
|
if (shouldCheckForConversionOverflow(fromType = itemType, toType = rangeType))
|
||||||
|
"return (value shr $rangeType.SIZE_BITS) == ${itemType.zero()} && contains(value.to$rangeType())"
|
||||||
|
else
|
||||||
|
"return contains(value.to$rangeType())"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val f_toPrimitiveExactOrNull = fn("to{}ExactOrNull()").byTwoPrimitives {
|
val f_toPrimitiveExactOrNull = fn("to{}ExactOrNull()").byTwoPrimitives {
|
||||||
include(Primitives, numericPermutations)
|
include(Primitives, numericCombinations)
|
||||||
filter { _, (fromType, toType) -> fromType.capacity > toType.capacity && toType.isIntegral() }
|
filter { _, (fromType, toType) -> shouldCheckForConversionOverflow(fromType, toType) }
|
||||||
} builderWith { (fromType, toType) ->
|
} builderWith { (fromType, toType) ->
|
||||||
check(toType.isIntegral())
|
check(toType.isIntegral())
|
||||||
visibility("internal")
|
visibility("internal")
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ enum class PrimitiveType {
|
|||||||
ULong;
|
ULong;
|
||||||
|
|
||||||
val capacity by lazy { descendingByDomainCapacity.indexOf(this).let { if (it < 0) it else descendingByDomainCapacity.size - it } }
|
val capacity by lazy { descendingByDomainCapacity.indexOf(this).let { if (it < 0) it else descendingByDomainCapacity.size - it } }
|
||||||
|
val capacityUnsigned by lazy { descendingByDomainCapacityUnsigned.indexOf(this).let { if (it < 0) it else descendingByDomainCapacityUnsigned.size - it } }
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val unsignedPrimitives = setOf(UInt, ULong, UByte, UShort)
|
val unsignedPrimitives = setOf(UInt, ULong, UByte, UShort)
|
||||||
|
|||||||
Reference in New Issue
Block a user