Support data parsing operations (#380)
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
Q: How do I run my program?
|
||||||
|
|
||||||
|
A: Define top level function `fun main(args: Array<String>)`, please ensure it's not
|
||||||
|
in a package.
|
||||||
+3
-1
@@ -23,7 +23,9 @@ the following platforms:
|
|||||||
|
|
||||||
* Mac OS X 10.10 and later (x86-64)
|
* Mac OS X 10.10 and later (x86-64)
|
||||||
* x86-64 Ubuntu Linux (14.04, 16.04 and later), other Linux flavours may work as well
|
* x86-64 Ubuntu Linux (14.04, 16.04 and later), other Linux flavours may work as well
|
||||||
* Apple iOS (arm64 and simulator on x86-64)
|
* Apple iOS (arm64 and simulator on x86-64), cross-compiled on MacOS X host
|
||||||
|
* Raspberry Pi, cross-compiled on Linux host
|
||||||
|
|
||||||
|
|
||||||
Adding support for other target platforms shalln't be too hard, if LLVM support
|
Adding support for other target platforms shalln't be too hard, if LLVM support
|
||||||
is available.
|
is available.
|
||||||
|
|||||||
@@ -1034,6 +1034,19 @@ task string0(type: RunKonanTest) {
|
|||||||
source = "runtime/text/string0.kt"
|
source = "runtime/text/string0.kt"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task parse0(type: RunKonanTest) {
|
||||||
|
goldValue = "false\n" +
|
||||||
|
"true\n" +
|
||||||
|
"-1\n" +
|
||||||
|
"-86\n" +
|
||||||
|
"30\n" +
|
||||||
|
"4294967295\n" +
|
||||||
|
"bad format\n" +
|
||||||
|
"0.5\n" +
|
||||||
|
"2.39\n"
|
||||||
|
source = "runtime/text/parse0.kt"
|
||||||
|
}
|
||||||
|
|
||||||
task catch1(type: RunKonanTest) {
|
task catch1(type: RunKonanTest) {
|
||||||
goldValue = "Before\nCaught Throwable\nDone\n"
|
goldValue = "Before\nCaught Throwable\nDone\n"
|
||||||
source = "runtime/exceptions/catch1.kt"
|
source = "runtime/exceptions/catch1.kt"
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fun main(args: Array<String>) {
|
||||||
|
println("false".toBoolean())
|
||||||
|
println("true".toBoolean())
|
||||||
|
println("-1".toByte())
|
||||||
|
println("aa".toByte(16))
|
||||||
|
println("11110".toInt(2))
|
||||||
|
println("ffffffff".toLong(16))
|
||||||
|
try {
|
||||||
|
val x = "ffffffff".toLong(10)
|
||||||
|
} catch (ne: NumberFormatException) {
|
||||||
|
println("bad format")
|
||||||
|
}
|
||||||
|
println("0.5".toFloat())
|
||||||
|
println("2.39".toDouble())
|
||||||
|
}
|
||||||
@@ -22,8 +22,10 @@ void ThrowNullPointerException();
|
|||||||
void ThrowArrayIndexOutOfBoundsException();
|
void ThrowArrayIndexOutOfBoundsException();
|
||||||
// Throws class cast exception.
|
// Throws class cast exception.
|
||||||
void ThrowClassCastException();
|
void ThrowClassCastException();
|
||||||
// Throws arithmetic exception
|
// Throws arithmetic exception.
|
||||||
void ThrowArithmeticException();
|
void ThrowArithmeticException();
|
||||||
|
// Throws number format exception.
|
||||||
|
void ThrowNumberFormatException();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
@@ -47,6 +47,58 @@ OBJ_GETTER(utf8ToUtf16, Raw<const char> rawString) {
|
|||||||
RETURN_OBJ(result->obj());
|
RETURN_OBJ(result->obj());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T> T parseInt(KString value, KInt radix) {
|
||||||
|
Raw<const KChar> utf16(
|
||||||
|
CharArrayAddressOfElementAt(value, 0), value->count_);
|
||||||
|
std::string utf8;
|
||||||
|
utf8::utf16to8(utf16.begin(), utf16.end(), back_inserter(utf8));
|
||||||
|
char* end = nullptr;
|
||||||
|
long result = strtol(utf8.c_str(), &end, radix);
|
||||||
|
if (end != utf8.c_str() + utf8.size()) {
|
||||||
|
ThrowNumberFormatException();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
KLong parseLong(KString value, KInt radix) {
|
||||||
|
Raw<const KChar> utf16(
|
||||||
|
CharArrayAddressOfElementAt(value, 0), value->count_);
|
||||||
|
std::string utf8;
|
||||||
|
utf8::utf16to8(utf16.begin(), utf16.end(), back_inserter(utf8));
|
||||||
|
char* end = nullptr;
|
||||||
|
KLong result = strtoll(utf8.c_str(), &end, radix);
|
||||||
|
if (end != utf8.c_str() + utf8.size()) {
|
||||||
|
ThrowNumberFormatException();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
KFloat parseFloat(KString value) {
|
||||||
|
Raw<const KChar> utf16(
|
||||||
|
CharArrayAddressOfElementAt(value, 0), value->count_);
|
||||||
|
std::string utf8;
|
||||||
|
utf8::utf16to8(utf16.begin(), utf16.end(), back_inserter(utf8));
|
||||||
|
char* end = nullptr;
|
||||||
|
KFloat result = strtof(utf8.c_str(), &end);
|
||||||
|
if (end != utf8.c_str() + utf8.size()) {
|
||||||
|
ThrowNumberFormatException();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
KDouble parseDouble(KString value) {
|
||||||
|
Raw<const KChar> utf16(
|
||||||
|
CharArrayAddressOfElementAt(value, 0), value->count_);
|
||||||
|
std::string utf8;
|
||||||
|
utf8::utf16to8(utf16.begin(), utf16.end(), back_inserter(utf8));
|
||||||
|
char* end = nullptr;
|
||||||
|
KDouble result = strtod(utf8.c_str(), &end);
|
||||||
|
if (end != utf8.c_str() + utf8.size()) {
|
||||||
|
ThrowNumberFormatException();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -301,6 +353,22 @@ KChar Kotlin_Char_toUpperCase(KChar ch) {
|
|||||||
return towupper(ch);
|
return towupper(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KInt Kotlin_Char_digitOf(KChar ch, KInt radix) {
|
||||||
|
// TODO: make smarter and support full unicode.
|
||||||
|
const static KInt digits[] = {
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1,
|
||||||
|
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||||
|
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
|
||||||
|
30, 31, 32, 33, 34, 35,
|
||||||
|
-1, -1, -1, -1, -1, -1,
|
||||||
|
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||||
|
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
|
||||||
|
30, 31, 32, 33, 34, 35 };
|
||||||
|
if (ch < 0x30 /* 0 */ || ch > 0x7a /* z */) return -1;
|
||||||
|
return digits[ch - 0x30];
|
||||||
|
}
|
||||||
|
|
||||||
KInt Kotlin_String_indexOfChar(KString thiz, KChar ch, KInt fromIndex) {
|
KInt Kotlin_String_indexOfChar(KString thiz, KChar ch, KInt fromIndex) {
|
||||||
if (fromIndex < 0 || fromIndex > thiz->count_) {
|
if (fromIndex < 0 || fromIndex > thiz->count_) {
|
||||||
return false;
|
return false;
|
||||||
@@ -430,4 +498,28 @@ OBJ_GETTER0(Kotlin_io_Console_readLine) {
|
|||||||
RETURN_RESULT_OF(CreateStringFromCString, data);
|
RETURN_RESULT_OF(CreateStringFromCString, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KByte Kotlin_String_parseByte(KString value, KInt radix) {
|
||||||
|
return parseInt<KByte>(value, radix);
|
||||||
|
}
|
||||||
|
|
||||||
|
KShort Kotlin_String_parseShort(KString value, KInt radix) {
|
||||||
|
return parseInt<KShort>(value, radix);
|
||||||
|
}
|
||||||
|
|
||||||
|
KInt Kotlin_String_parseInt(KString value, KInt radix) {
|
||||||
|
return parseInt<KInt>(value, radix);
|
||||||
|
}
|
||||||
|
|
||||||
|
KLong Kotlin_String_parseLong(KString value, KInt radix) {
|
||||||
|
return parseLong(value, radix);
|
||||||
|
}
|
||||||
|
|
||||||
|
KFloat Kotlin_String_parseFloat(KString value) {
|
||||||
|
return parseFloat(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
KDouble Kotlin_String_parseDouble(KString value) {
|
||||||
|
return parseDouble(value);
|
||||||
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
@@ -43,12 +43,50 @@ OBJ_GETTER(Kotlin_Int_toString, KInt value) {
|
|||||||
RETURN_RESULT_OF(CreateStringFromCString, cstring);
|
RETURN_RESULT_OF(CreateStringFromCString, cstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OBJ_GETTER(Kotlin_Int_toStringRadix, KInt value, KInt radix) {
|
||||||
|
// TODO: maye not fit for smaller radices.
|
||||||
|
char cstring[32];
|
||||||
|
switch (radix) {
|
||||||
|
case 8:
|
||||||
|
snprintf(cstring, sizeof(cstring), "%o", value);
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
snprintf(cstring, sizeof(cstring), "%d", value);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
snprintf(cstring, sizeof(cstring), "%x", value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
RuntimeAssert(false, "Unsupported radix");
|
||||||
|
}
|
||||||
|
RETURN_RESULT_OF(CreateStringFromCString, cstring);
|
||||||
|
}
|
||||||
|
|
||||||
OBJ_GETTER(Kotlin_Long_toString, KLong value) {
|
OBJ_GETTER(Kotlin_Long_toString, KLong value) {
|
||||||
char cstring[32];
|
char cstring[32];
|
||||||
snprintf(cstring, sizeof(cstring), "%lld", static_cast<long long>(value));
|
snprintf(cstring, sizeof(cstring), "%lld", static_cast<long long>(value));
|
||||||
RETURN_RESULT_OF(CreateStringFromCString, cstring);
|
RETURN_RESULT_OF(CreateStringFromCString, cstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OBJ_GETTER(Kotlin_Long_toStringRadix, KLong value, KInt radix) {
|
||||||
|
// TODO: may not fit for smaller radices.
|
||||||
|
char cstring[64];
|
||||||
|
switch (radix) {
|
||||||
|
case 8:
|
||||||
|
snprintf(cstring, sizeof(cstring), "%llo", value);
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
snprintf(cstring, sizeof(cstring), "%lld", value);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
snprintf(cstring, sizeof(cstring), "%llx", value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
RuntimeAssert(false, "Unsupported radix");
|
||||||
|
}
|
||||||
|
RETURN_RESULT_OF(CreateStringFromCString, cstring);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: use David Gay's dtoa() here instead. It's *very* big and ugly.
|
// TODO: use David Gay's dtoa() here instead. It's *very* big and ugly.
|
||||||
OBJ_GETTER(Kotlin_Float_toString, KFloat value) {
|
OBJ_GETTER(Kotlin_Float_toString, KFloat value) {
|
||||||
char cstring[32];
|
char cstring[32];
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ internal fun ThrowArithmeticException() : Nothing {
|
|||||||
throw ArithmeticException()
|
throw ArithmeticException()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExportForCppRuntime
|
||||||
|
internal fun ThrowNumberFormatException() : Nothing {
|
||||||
|
throw NumberFormatException()
|
||||||
|
}
|
||||||
|
|
||||||
fun ThrowNoWhenBranchMatchedException(): Nothing {
|
fun ThrowNoWhenBranchMatchedException(): Nothing {
|
||||||
throw NoWhenBranchMatchedException()
|
throw NoWhenBranchMatchedException()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,16 @@ public final class Char : Comparable<Char> {
|
|||||||
* The maximum value of a Unicode surrogate code unit.
|
* The maximum value of a Unicode surrogate code unit.
|
||||||
*/
|
*/
|
||||||
public const val MAX_SURROGATE: Char = MAX_LOW_SURROGATE
|
public const val MAX_SURROGATE: Char = MAX_LOW_SURROGATE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum radix available for conversion to and from strings.
|
||||||
|
*/
|
||||||
|
public const val MIN_RADIX: Int = 2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum radix available for conversion to and from strings.
|
||||||
|
*/
|
||||||
|
public const val MAX_RADIX: Int = 36
|
||||||
}
|
}
|
||||||
|
|
||||||
// Konan-specific.
|
// Konan-specific.
|
||||||
|
|||||||
@@ -193,3 +193,11 @@ public open class OutOfMemoryError : Error {
|
|||||||
constructor(s: String) : super(s) {
|
constructor(s: String) : super(s) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public open class NumberFormatException : IllegalArgumentException {
|
||||||
|
|
||||||
|
constructor() : super() {
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(s: String) : super(s) {}
|
||||||
|
}
|
||||||
@@ -79,3 +79,17 @@ external public fun Char.isHighSurrogate(): Boolean
|
|||||||
*/
|
*/
|
||||||
@SymbolName("Kotlin_Char_isLowSurrogate")
|
@SymbolName("Kotlin_Char_isLowSurrogate")
|
||||||
external public fun Char.isLowSurrogate(): Boolean
|
external public fun Char.isLowSurrogate(): Boolean
|
||||||
|
|
||||||
|
@SymbolName("Kotlin_Char_digitOf")
|
||||||
|
external internal fun digitOf(char: Char, radix: Int): Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given [radix] is valid radix for string to number and number to string conversion.
|
||||||
|
*/
|
||||||
|
@PublishedApi
|
||||||
|
internal fun checkRadix(radix: Int): Int {
|
||||||
|
if(radix !in Char.MIN_RADIX..Char.MAX_RADIX) {
|
||||||
|
throw IllegalArgumentException("radix $radix was not in valid range ${Char.MIN_RADIX..Char.MAX_RADIX}")
|
||||||
|
}
|
||||||
|
return radix
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,320 @@
|
|||||||
|
package kotlin.text
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of this [Byte] value in the specified [radix].
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
public inline fun Byte.toString(radix: Int): String = this.toInt().toString(checkRadix(radix))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of this [Short] value in the specified [radix].
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
public inline fun Short.toString(radix: Int): String = this.toInt().toString(checkRadix(radix))
|
||||||
|
|
||||||
|
@SymbolName("Kotlin_Int_toStringRadix")
|
||||||
|
external private fun intToString(value: Int, radix: Int): String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of this [Int] value in the specified [radix].
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||||
|
public inline fun Int.toString(radix: Int): String = intToString(this, checkRadix(radix))
|
||||||
|
|
||||||
|
@SymbolName("Kotlin_Long_toStringRadix")
|
||||||
|
external private fun longToString(value: Long, radix: Int): String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of this [Long] value in the specified [radix].
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||||
|
public inline fun Long.toString(radix: Int): String = longToString(this, checkRadix(radix))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns `true` if the contents of this string is equal to the word "true", ignoring case, and `false` otherwise.
|
||||||
|
*/
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
public inline fun String.toBoolean(): Boolean = this == "true"
|
||||||
|
|
||||||
|
@SymbolName("Kotlin_String_parseByte")
|
||||||
|
external private fun parseByte(value: String, radix: Int): Byte
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a signed [Byte] number and returns the result.
|
||||||
|
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||||
|
public inline fun String.toByte(): Byte = parseByte(this, 10)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a signed [Byte] number and returns the result.
|
||||||
|
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||||
|
public inline fun String.toByte(radix: Int): Byte = parseByte(this, checkRadix(radix))
|
||||||
|
|
||||||
|
@SymbolName("Kotlin_String_parseShort")
|
||||||
|
external private fun parseShort(value: String, radix: Int): Short
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a [Short] number and returns the result.
|
||||||
|
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||||
|
public inline fun String.toShort(): Short = parseShort(this, 10)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a [Short] number and returns the result.
|
||||||
|
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||||
|
public inline fun String.toShort(radix: Int): Short = parseShort(this, checkRadix(radix))
|
||||||
|
|
||||||
|
@SymbolName("Kotlin_String_parseInt")
|
||||||
|
external private fun parseInt(value: String, radix: Int): Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as an [Int] number and returns the result.
|
||||||
|
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||||
|
public inline fun String.toInt(): Int = parseInt(this, 10)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as an [Int] number and returns the result.
|
||||||
|
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||||
|
public inline fun String.toInt(radix: Int): Int = parseInt(this, checkRadix(radix))
|
||||||
|
|
||||||
|
|
||||||
|
@SymbolName("Kotlin_String_parseLong")
|
||||||
|
external private fun parseLong(value: String, radix: Int): Long
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a [Long] number and returns the result.
|
||||||
|
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||||
|
public inline fun String.toLong(): Long = parseLong(this, 10)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a [Long] number and returns the result.
|
||||||
|
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||||
|
public inline fun String.toLong(radix: Int): Long = parseLong(this, checkRadix(radix))
|
||||||
|
|
||||||
|
@SymbolName("Kotlin_String_parseFloat")
|
||||||
|
external private fun parseFloat(value: String): Float
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a [Float] number and returns the result.
|
||||||
|
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||||
|
public inline fun String.toFloat(): Float = parseFloat(this)
|
||||||
|
|
||||||
|
|
||||||
|
@SymbolName("Kotlin_String_parseDouble")
|
||||||
|
external private fun parseDouble(value: String): Double
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a [Double] number and returns the result.
|
||||||
|
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||||
|
public inline fun String.toDouble(): Double = parseDouble(this)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a signed [Byte] number and returns the result
|
||||||
|
* or `null` if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
public fun String.toByteOrNull(): Byte? = toByteOrNull(radix = 10)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a signed [Byte] number and returns the result
|
||||||
|
* or `null` if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
public fun String.toByteOrNull(radix: Int): Byte? {
|
||||||
|
val int = this.toIntOrNull(radix) ?: return null
|
||||||
|
if (int < Byte.MIN_VALUE || int > Byte.MAX_VALUE) return null
|
||||||
|
return int.toByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a [Short] number and returns the result
|
||||||
|
* or `null` if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
public fun String.toShortOrNull(): Short? = toShortOrNull(radix = 10)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a [Short] number and returns the result
|
||||||
|
* or `null` if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
public fun String.toShortOrNull(radix: Int): Short? {
|
||||||
|
val int = this.toIntOrNull(radix) ?: return null
|
||||||
|
if (int < Short.MIN_VALUE || int > Short.MAX_VALUE) return null
|
||||||
|
return int.toShort()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as an [Int] number and returns the result
|
||||||
|
* or `null` if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
public fun String.toIntOrNull(): Int? = toIntOrNull(radix = 10)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as an [Int] number and returns the result
|
||||||
|
* or `null` if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
public fun String.toIntOrNull(radix: Int): Int? {
|
||||||
|
checkRadix(radix)
|
||||||
|
|
||||||
|
val length = this.length
|
||||||
|
if (length == 0) return null
|
||||||
|
|
||||||
|
val start: Int
|
||||||
|
val isNegative: Boolean
|
||||||
|
val limit: Int
|
||||||
|
|
||||||
|
val firstChar = this[0]
|
||||||
|
if (firstChar < '0') { // Possible leading sign
|
||||||
|
if (length == 1) return null // non-digit (possible sign) only, no digits after
|
||||||
|
|
||||||
|
start = 1
|
||||||
|
|
||||||
|
if (firstChar == '-') {
|
||||||
|
isNegative = true
|
||||||
|
limit = Int.MIN_VALUE
|
||||||
|
} else if (firstChar == '+') {
|
||||||
|
isNegative = false
|
||||||
|
limit = -Int.MAX_VALUE
|
||||||
|
} else
|
||||||
|
return null
|
||||||
|
} else {
|
||||||
|
start = 0
|
||||||
|
isNegative = false
|
||||||
|
limit = -Int.MAX_VALUE
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val limitBeforeMul = limit / radix
|
||||||
|
var result = 0
|
||||||
|
for (i in start..(length - 1)) {
|
||||||
|
val digit = digitOf(this[i], radix)
|
||||||
|
|
||||||
|
if (digit < 0) return null
|
||||||
|
if (result < limitBeforeMul) return null
|
||||||
|
|
||||||
|
result *= radix
|
||||||
|
|
||||||
|
if (result < limit + digit) return null
|
||||||
|
|
||||||
|
result -= digit
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (isNegative) result else -result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a [Long] number and returns the result
|
||||||
|
* or `null` if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
public fun String.toLongOrNull(): Long? = toLongOrNull(radix = 10)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a [Long] number and returns the result
|
||||||
|
* or `null` if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
public fun String.toLongOrNull(radix: Int): Long? {
|
||||||
|
checkRadix(radix)
|
||||||
|
|
||||||
|
val length = this.length
|
||||||
|
if (length == 0) return null
|
||||||
|
|
||||||
|
val start: Int
|
||||||
|
val isNegative: Boolean
|
||||||
|
val limit: Long
|
||||||
|
|
||||||
|
val firstChar = this[0]
|
||||||
|
if (firstChar < '0') { // Possible leading sign
|
||||||
|
if (length == 1) return null // non-digit (possible sign) only, no digits after
|
||||||
|
|
||||||
|
start = 1
|
||||||
|
|
||||||
|
if (firstChar == '-') {
|
||||||
|
isNegative = true
|
||||||
|
limit = Long.MIN_VALUE
|
||||||
|
} else if (firstChar == '+') {
|
||||||
|
isNegative = false
|
||||||
|
limit = -Long.MAX_VALUE
|
||||||
|
} else
|
||||||
|
return null
|
||||||
|
} else {
|
||||||
|
start = 0
|
||||||
|
isNegative = false
|
||||||
|
limit = -Long.MAX_VALUE
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val limitBeforeMul = limit / radix
|
||||||
|
var result = 0L
|
||||||
|
for (i in start..(length - 1)) {
|
||||||
|
val digit = digitOf(this[i], radix)
|
||||||
|
|
||||||
|
if (digit < 0) return null
|
||||||
|
if (result < limitBeforeMul) return null
|
||||||
|
|
||||||
|
result *= radix
|
||||||
|
|
||||||
|
if (result < limit + digit) return null
|
||||||
|
|
||||||
|
result -= digit
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (isNegative) result else -result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a [Float] number and returns the result
|
||||||
|
* or `null` if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
public fun String.toFloatOrNull(): Float? = TODO()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the string as a [Double] number and returns the result
|
||||||
|
* or `null` if the string is not a valid representation of a number.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
public fun String.toDoubleOrNull(): Double? = TODO()
|
||||||
@@ -2,10 +2,16 @@ Start with building compiler by using `dist` and `cross_dist` for cross-targets.
|
|||||||
To build Tetris application for your host platform use
|
To build Tetris application for your host platform use
|
||||||
./build
|
./build
|
||||||
note that SDL2 must be installed on the host.
|
note that SDL2 must be installed on the host.
|
||||||
For cross-compilation to iOS use
|
For cross-compilation to iOS (on Mac host) use
|
||||||
TARGET=iphone ./build
|
TARGET=iphone ./build
|
||||||
|
For cross-compilation to Raspberry Pi (on Linux host) use
|
||||||
|
TARGET=raspberrypi ./build
|
||||||
|
|
||||||
During build process compilation script creates interoperability bindings to SDL2, using SDL C headers,
|
During build process compilation script creates interoperability bindings to SDL2, using SDL C headers,
|
||||||
and then compiles an application with the produced bindings.
|
and then compiles an application with the produced bindings.
|
||||||
|
|
||||||
To deploy executable to iPhone device take Info.plist, then use XCode and your own private signing identity.
|
To deploy executable to iPhone device take Info.plist, then use XCode and your own private signing identity.
|
||||||
|
|
||||||
|
To run on Raspberry Pi one need to install SDL package with `apt-get install libsdl2-2.0.0` on the Pi.
|
||||||
|
Also GLES2 renderer is recommended (use `SDL_RENDER_DRIVER=opengles2 ./tetris.kexe`).
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user