Provide unsigned string to number conversion in arbitrary base

#KT-26161
This commit is contained in:
Ilya Gorbunov
2018-08-17 05:22:01 +03:00
parent c1d1a7108f
commit 2530a8e98c
5 changed files with 350 additions and 2 deletions
@@ -46,3 +46,212 @@ public /*inline*/ fun UInt.toString(radix: Int): String = this.toLong().toString
public fun ULong.toString(radix: Int): String = ulongToString(this.toLong(), checkRadix(radix))
/**
* Parses the string as a signed [UByte] number and returns the result.
* @throws NumberFormatException if the string is not a valid representation of a number.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toUByte(): UByte = toUByteOrNull() ?: numberFormatError(this)
/**
* Parses the string as a signed [UByte] number and returns the result.
* @throws NumberFormatException if the string is not a valid representation of a number.
* @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toUByte(radix: Int): UByte = toUByteOrNull(radix) ?: numberFormatError(this)
/**
* Parses the string as a [UShort] number and returns the result.
* @throws NumberFormatException if the string is not a valid representation of a number.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toUShort(): UShort = toUShortOrNull() ?: numberFormatError(this)
/**
* Parses the string as a [UShort] number and returns the result.
* @throws NumberFormatException if the string is not a valid representation of a number.
* @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toUShort(radix: Int): UShort = toUShortOrNull(radix) ?: numberFormatError(this)
/**
* Parses the string as an [UInt] number and returns the result.
* @throws NumberFormatException if the string is not a valid representation of a number.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toUInt(): UInt = toUIntOrNull() ?: numberFormatError(this)
/**
* Parses the string as an [UInt] number and returns the result.
* @throws NumberFormatException if the string is not a valid representation of a number.
* @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toUInt(radix: Int): UInt = toUIntOrNull(radix) ?: numberFormatError(this)
/**
* Parses the string as a [ULong] number and returns the result.
* @throws NumberFormatException if the string is not a valid representation of a number.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toULong(): ULong = toULongOrNull() ?: numberFormatError(this)
/**
* Parses the string as a [ULong] number and returns the result.
* @throws NumberFormatException if the string is not a valid representation of a number.
* @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toULong(radix: Int): ULong = toULongOrNull(radix) ?: numberFormatError(this)
/**
* Parses the string as an [UByte] number and returns the result
* or `null` if the string is not a valid representation of a number.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toUByteOrNull(): UByte? = toUByteOrNull(radix = 10)
/**
* Parses the string as an [UByte] number and returns the result
* or `null` if the string is not a valid representation of a number.
*
* @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toUByteOrNull(radix: Int): UByte? {
val int = this.toUIntOrNull(radix) ?: return null
if (int > UByte.MAX_VALUE) return null
return int.toUByte()
}
/**
* Parses the string as an [UShort] number and returns the result
* or `null` if the string is not a valid representation of a number.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toUShortOrNull(): UShort? = toUShortOrNull(radix = 10)
/**
* Parses the string as an [UShort] number and returns the result
* or `null` if the string is not a valid representation of a number.
*
* @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toUShortOrNull(radix: Int): UShort? {
val int = this.toUIntOrNull(radix) ?: return null
if (int > UShort.MAX_VALUE) return null
return int.toUShort()
}
/**
* Parses the string as an [UInt] number and returns the result
* or `null` if the string is not a valid representation of a number.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toUIntOrNull(): UInt? = toUIntOrNull(radix = 10)
/**
* Parses the string as an [UInt] number and returns the result
* or `null` if the string is not a valid representation of a number.
*
* @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toUIntOrNull(radix: Int): UInt? {
checkRadix(radix)
val length = this.length
if (length == 0) return null
val limit: UInt = UInt.MAX_VALUE
val firstChar = this[0]
if (firstChar < '0') return null
val uradix = radix.toUInt()
val limitBeforeMul = limit / uradix
var result = 0u
for (i in 0 until length) {
val digit = digitOf(this[i], radix)
if (digit < 0) return null
if (result > limitBeforeMul) return null
result *= uradix
if (result > limit - digit.toUInt()) return null
result += digit.toUInt()
}
return result
}
/**
* Parses the string as an [ULong] number and returns the result
* or `null` if the string is not a valid representation of a number.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toULongOrNull(): ULong? = toULongOrNull(radix = 10)
/**
* Parses the string as an [ULong] number and returns the result
* or `null` if the string is not a valid representation of a number.
*
* @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun String.toULongOrNull(radix: Int): ULong? {
checkRadix(radix)
val length = this.length
if (length == 0) return null
val limit: ULong = ULong.MAX_VALUE
val firstChar = this[0]
if (firstChar < '0') return null
val uradix = radix.toUInt()
val limitBeforeMul = limit / uradix
var result = 0uL
for (i in 0 until length) {
val digit = digitOf(this[i], radix)
if (digit < 0) return null
if (result > limitBeforeMul) return null
result *= uradix
if (result > limit - digit.toUInt()) return null
result += digit.toUInt()
}
return result
}