From c1d1a7108f14bc1b52370b662a52eb4e1f7617ca Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Thu, 16 Aug 2018 07:44:57 +0300 Subject: [PATCH] Provide unsigned number to string conversion in arbitrary base #KT-26161 --- .../test/text/StringNumberConversionTest.kt | 48 +++++++++++++++++++ .../src/kotlin/UStringNumberConversions.kt | 48 +++++++++++++++++++ .../unsigned/src/kotlin/UnsignedUtils.kt | 5 +- .../kotlin-stdlib-runtime-merged.txt | 7 +++ 4 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 libraries/stdlib/unsigned/src/kotlin/UStringNumberConversions.kt diff --git a/libraries/stdlib/test/text/StringNumberConversionTest.kt b/libraries/stdlib/test/text/StringNumberConversionTest.kt index 3ecdca441ea..97754b6c772 100644 --- a/libraries/stdlib/test/text/StringNumberConversionTest.kt +++ b/libraries/stdlib/test/text/StringNumberConversionTest.kt @@ -190,6 +190,54 @@ class StringNumberConversionTest { assertFailsWith("Expected to fail with radix 37") { 37L.toString(radix = 37) } assertFailsWith("Expected to fail with radix 1") { 1L.toString(radix = 1) } } + + @Test fun ubyteToStringWithRadix() { + assertEquals("7a", 0x7a.toUByte().toString(16)) + assertEquals("80", Byte.MIN_VALUE.toUByte().toString(radix = 16)) + assertEquals("ff", UByte.MAX_VALUE.toString(radix = 16)) + + assertEquals("40", Byte.MIN_VALUE.toUByte().toString(radix = 32)) + assertEquals("7v", UByte.MAX_VALUE.toString(radix = 32)) + + assertFailsWith("Expected to fail with radix 37") { 37.toUByte().toString(radix = 37) } + assertFailsWith("Expected to fail with radix 1") { 1.toUByte().toString(radix = 1) } + } + + @Test fun ushortToStringWithRadix() { + assertEquals("7FFF", 0x7FFF.toUShort().toString(radix = 16).toUpperCase()) + assertEquals("8000", 0x8000.toUShort().toString(radix = 16)) + assertEquals("ffff", UShort.MAX_VALUE.toString(radix = 16)) + + assertEquals("1ekf", UShort.MAX_VALUE.toString(radix = 36)) + + assertFailsWith("Expected to fail with radix 37") { 37.toUShort().toString(radix = 37) } + assertFailsWith("Expected to fail with radix 1") { 1.toUShort().toString(radix = 1) } + } + + @Test fun uintToStringWithRadix() { + assertEquals("ffffff01", (-255).toUInt().toString(radix = 16)) + assertEquals("ffffffff", UInt.MAX_VALUE.toString(radix = 16)) + + assertEquals("1100110", 102u.toString(radix = 2)) + assertEquals("kona", 411787u.toString(radix = 27)) + assertEquals("3vvvvvv", UInt.MAX_VALUE.toString(radix = 32)) + + assertFailsWith("Expected to fail with radix 37") { 37u.toString(radix = 37) } + assertFailsWith("Expected to fail with radix 1") { 1u.toString(radix = 1) } + + } + + @Test fun ulongToStringWithRadix() { + assertEquals("7f11223344556677", 0x7F11223344556677u.toString(radix = 16)) + assertEquals("89aabbccddeeff11", 0x89AABBCCDDEEFF11u.toString(radix = 16)) + assertEquals("8000000000000000", Long.MIN_VALUE.toULong().toString(radix = 16)) + assertEquals("ffffffffffffffff", ULong.MAX_VALUE.toString(radix = 16)) + + assertEquals("hazelnut", 1356099454469uL.toString(radix = 36)) + + assertFailsWith("Expected to fail with radix 37") { 37uL.toString(radix = 37) } + assertFailsWith("Expected to fail with radix 1") { 1uL.toString(radix = 1) } + } } internal fun doubleTotalOrderEquals(a: Double?, b: Double?): Boolean = (a as Any?) == b diff --git a/libraries/stdlib/unsigned/src/kotlin/UStringNumberConversions.kt b/libraries/stdlib/unsigned/src/kotlin/UStringNumberConversions.kt new file mode 100644 index 00000000000..e4e76fbc6e3 --- /dev/null +++ b/libraries/stdlib/unsigned/src/kotlin/UStringNumberConversions.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 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 kotlin.text + +/** + * Returns a string representation of this [Byte] value in the specified [radix]. + * + * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +//@kotlin.internal.InlineOnly +public /*inline*/ fun UByte.toString(radix: Int): String = this.toInt().toString(radix) + +/** + * Returns a string representation of this [Short] value in the specified [radix]. + * + * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +//@kotlin.internal.InlineOnly +public /*inline*/ fun UShort.toString(radix: Int): String = this.toInt().toString(radix) + + +/** + * Returns a string representation of this [Int] value in the specified [radix]. + * + * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +//@kotlin.internal.InlineOnly +public /*inline*/ fun UInt.toString(radix: Int): String = this.toLong().toString(radix) + +/** + * Returns a string representation of this [Long] value in the specified [radix]. + * + * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun ULong.toString(radix: Int): String = ulongToString(this.toLong(), checkRadix(radix)) + + diff --git a/libraries/stdlib/unsigned/src/kotlin/UnsignedUtils.kt b/libraries/stdlib/unsigned/src/kotlin/UnsignedUtils.kt index 28dd0724a5d..cfce017646e 100644 --- a/libraries/stdlib/unsigned/src/kotlin/UnsignedUtils.kt +++ b/libraries/stdlib/unsigned/src/kotlin/UnsignedUtils.kt @@ -60,8 +60,7 @@ internal fun ulongRemainder(v1: ULong, v2: ULong): ULong { internal fun ulongToString(v: Long): String = ulongToString(v, 10) internal fun ulongToString(v: Long, base: Int): String { - require(base == 10) // TODO: toString(base) support in common - if (v >= 0) return v.toString(/* base */) + if (v >= 0) return v.toString(base) var quotient = ((v ushr 1) / base) shl 1 var rem = v - quotient * base @@ -69,6 +68,6 @@ internal fun ulongToString(v: Long, base: Int): String { rem -= base quotient += 1 } - return quotient.toString(/* base */) + rem.toString(/* base */) + return quotient.toString(base) + rem.toString(base) } diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt index a6af68ae599..9d538b999da 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt @@ -5059,3 +5059,10 @@ public final class kotlin/text/Typography { public static final field tm C } +public final class kotlin/text/UStringNumberConversionsKt { + public static final fun toString (BI)Ljava/lang/String; + public static final fun toString (II)Ljava/lang/String; + public static final fun toString (JI)Ljava/lang/String; + public static final fun toString (SI)Ljava/lang/String; +} +