empty string parsing fixed

This commit is contained in:
zhelenskiy 2021-05-12 00:58:27 +03:00
parent 2da0648d73
commit 74d14970b9
2 changed files with 28 additions and 1 deletions

View File

@ -452,6 +452,7 @@ private val hexChToInt: MutableMap<Char, Int> = hashMapOf(
* Returns null if a valid number can not be read from a string * Returns null if a valid number can not be read from a string
*/ */
public fun String.parseBigInteger(): BigInt? { public fun String.parseBigInteger(): BigInt? {
if (this.isEmpty()) return null
val sign: Int val sign: Int
val sPositive: String val sPositive: String
//TODO substring = O(n). Can be replaced by some drop that is O(1) //TODO substring = O(n). Can be replaced by some drop that is O(1)
@ -473,15 +474,18 @@ public fun String.parseBigInteger(): BigInt? {
var res = BigInt.ZERO var res = BigInt.ZERO
var digitValue = BigInt.ONE var digitValue = BigInt.ONE
val sPositiveUpper = sPositive.uppercase() val sPositiveUpper = sPositive.uppercase()
var isEmpty = true
if (sPositiveUpper.startsWith("0X")) { if (sPositiveUpper.startsWith("0X")) {
// hex representation // hex representation
val sHex = sPositiveUpper.substring(2) val sHex = sPositiveUpper.substring(2)
if (this.isEmpty()) return null
// TODO optimize O(n2) -> O(n) // TODO optimize O(n2) -> O(n)
for (ch in sHex.reversed()) { for (ch in sHex.reversed()) {
if (ch == '_') continue if (ch == '_') continue
res += digitValue * (hexChToInt[ch] ?: return null) res += digitValue * (hexChToInt[ch] ?: return null)
isEmpty = false
digitValue *= 16.toBigInt() digitValue *= 16.toBigInt()
} }
} else for (ch in sPositiveUpper.reversed()) { } else for (ch in sPositiveUpper.reversed()) {
@ -491,10 +495,11 @@ public fun String.parseBigInteger(): BigInt? {
return null return null
} }
res += digitValue * (ch.code - '0'.code) res += digitValue * (ch.code - '0'.code)
isEmpty = false
digitValue *= 10.toBigInt() digitValue *= 10.toBigInt()
} }
return res * sign return if (isEmpty) null else res * sign
} }
public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer<BigInt> = public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer<BigInt> =

View File

@ -7,9 +7,31 @@ package space.kscience.kmath.operations
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNull
@kotlin.ExperimentalUnsignedTypes @kotlin.ExperimentalUnsignedTypes
class BigIntConversionsTest { class BigIntConversionsTest {
@Test
fun emptyString() {
assertNull("".parseBigInteger())
assertNull("+".parseBigInteger())
assertNull("-".parseBigInteger())
assertNull("0x".parseBigInteger())
assertNull("+0x".parseBigInteger())
assertNull("-0x".parseBigInteger())
assertNull("_".parseBigInteger())
assertNull("+_".parseBigInteger())
assertNull("-_".parseBigInteger())
assertNull("0x_".parseBigInteger())
assertNull("+0x_".parseBigInteger())
assertNull("-0x_".parseBigInteger())
}
@Test @Test
fun testToString0x10() { fun testToString0x10() {
val x = 0x10.toBigInt() val x = 0x10.toBigInt()