String <-> CharArray conversion, ArrayBuilder by @elizarov (#98)

This commit is contained in:
Nikolay Igotti
2016-11-30 13:06:36 +03:00
committed by GitHub
parent badecf8210
commit d4fda3bfe2
11 changed files with 236 additions and 15 deletions
+10
View File
@@ -314,6 +314,11 @@ task tostring1(type: RunKonanTest) {
source = "runtime/basic/tostring1.kt"
}
task tostring2(type: RunKonanTest) {
goldValue = "H e l l o \nHello\n"
source = "runtime/basic/tostring2.kt"
}
task array0(type: RunKonanTest) {
goldValue = "5\n6\n7\n8\n9\n10\n11\n12\n13\n"
source = "runtime/basic/array0.kt"
@@ -444,6 +449,11 @@ task moderately_large_array(type: RunKonanTest) {
source = "runtime/collections/moderately_large_array.kt"
}
task string_builder0(type: RunKonanTest) {
goldValue = "OK\n"
source = "runtime/text/string_builder0.kt"
}
task catch1(type: RunKonanTest) {
goldValue = "Before\nCaught Throwable\nDone\n"
source = "runtime/exceptions/catch1.kt"
@@ -0,0 +1,10 @@
fun main(args : Array<String>) {
val hello = "Hello"
val array = toCharArray(hello)
for (ch in array) {
print(ch)
print(" ")
}
println()
println(fromCharArray(array, 0, array.size))
}
@@ -182,6 +182,12 @@ fun testToString() {
assertTrue(a.toString() == makeList123().toString())
}
fun testToString2() {
val a = makeList123()
assertEquals(a.toString(), "[1, 2, 3]")
}
fun testSubList() {
val a0 = makeList01234()
val a = a0.subList(1, 4)
@@ -271,11 +277,12 @@ fun testIteratorAdd() {
val next = it.next()
if (i++ % 2 == 0)
it.add("-" + next)
it.next()
}
//assertEquals(listOf("1", "2", "-2", "3", "4", "-4", "5"), a)
}
fun main(args : Array<String>) {
testBasic()
testIterator()
@@ -286,6 +293,7 @@ fun main(args : Array<String>) {
testEquals()
testHashCode()
testToString()
testToString2()
testSubList()
testResize()
testSubListContains()
@@ -0,0 +1,46 @@
fun assertTrue(cond: Boolean) {
if (!cond)
println("FAIL")
}
fun assertFalse(cond: Boolean) {
if (cond)
println("FAIL")
}
fun assertEquals(value1: String, value2: String) {
if (value1 != value2)
println("FAIL: '" + value1 + "' != '" + value2 + "'")
}
fun assertEquals(value1: Int, value2: Int) {
if (value1 != value2)
println("FAIL" + value1.toString() + " != " + value2.toString())
}
fun testBasic() {
val sb = StringBuilder()
assertEquals(0, sb.length)
assertEquals("", sb.toString())
sb.append(1)
assertEquals(1, sb.length)
assertEquals("1", sb.toString())
sb.append(", ")
assertEquals(3, sb.length)
assertEquals("1, ", sb.toString())
sb.append(true)
assertEquals(7, sb.length)
assertEquals("1, true", sb.toString())
sb.append(12345678L)
assertEquals(15, sb.length)
assertEquals("1, true12345678", sb.toString())
sb.length = 0
assertEquals(0, sb.length)
assertEquals("", sb.toString())
}
fun main(args : Array<String>) {
testBasic()
println("OK")
}
+11
View File
@@ -115,6 +115,17 @@ ArrayHeader* Kotlin_CharArray_clone(const ArrayHeader* array) {
return result;
}
ArrayHeader* Kotlin_CharArray_copyOf(const ArrayHeader* array, KInt newSize) {
ArrayHeader* result = ArrayContainer(
theCharArrayTypeInfo, newSize).GetPlace();
KInt toCopy = array->count_ < newSize ? array->count_ : newSize;
memcpy(
PrimitiveArrayAddressOfElementAt<KChar>(result, 0),
PrimitiveArrayAddressOfElementAt<KChar>(array, 0),
toCopy * sizeof(KChar));
return result;
}
KInt Kotlin_CharArray_getArrayLength(const ArrayHeader* array) {
return array->count_;
}
+36 -6
View File
@@ -79,18 +79,48 @@ KInt Kotlin_String_getStringLength(KString thiz) {
return thiz->count_;
}
KString Kotlin_String_fromUtf8Array(const ArrayHeader* array) {
KString Kotlin_String_fromUtf8Array(
const ArrayHeader* array, KInt start, KInt size) {
RuntimeAssert(array->type_info() == theByteArrayTypeInfo, "Must use a byte array");
if (start < 0 || start + size > array->count_) {
ThrowArrayIndexOutOfBoundsException();
}
// TODO: support full UTF-8.
ArrayHeader* result = ArrayContainer(
theStringTypeInfo, array->count_).GetPlace();
ArrayHeader* result = ArrayContainer(theStringTypeInfo, size).GetPlace();
memcpy(
ByteArrayAddressOfElementAt(result, 0),
ByteArrayAddressOfElementAt(array, 0),
ArrayDataSizeBytes(array));
ByteArrayAddressOfElementAt(array, start),
size);
return result;
}
KString Kotlin_String_fromCharArray(
const ArrayHeader* array, KInt start, KInt size) {
RuntimeAssert(array->type_info() == theCharArrayTypeInfo, "Must use a byte array");
if (start < 0 || start + size > array->count_) {
ThrowArrayIndexOutOfBoundsException();
}
// TODO: support full UTF-8.
ArrayHeader* result = ArrayContainer(theStringTypeInfo, size).GetPlace();
for (KInt index = 0; index < size; ++index) {
*ByteArrayAddressOfElementAt(result, index) =
*PrimitiveArrayAddressOfElementAt<KChar>(array, start + index);
}
return result;
}
ArrayHeader* Kotlin_String_toCharArray(KString string) {
// TODO: support full UTF-8.
ArrayHeader* result = ArrayContainer(
theCharArrayTypeInfo, string->count_).GetPlace();
for (int index = 0; index < string->count_; ++index) {
*PrimitiveArrayAddressOfElementAt<KChar>(result, index) =
*ByteArrayAddressOfElementAt(string, index);
}
return result;
}
KString Kotlin_String_plusImpl(KString thiz, KString other) {
// TODO: support UTF-8
RuntimeAssert(thiz != nullptr, "this cannot be null");
@@ -113,7 +143,7 @@ KString Kotlin_String_plusImpl(KString thiz, KString other) {
KBoolean Kotlin_String_equals(KString thiz, KConstRef other) {
if (other == nullptr || other->type_info() != theStringTypeInfo) return 0;
const ArrayHeader* otherString = reinterpret_cast<const ArrayHeader*>(other);
KString otherString = reinterpret_cast<KString>(other);
return thiz->count_ == otherString->count_ &&
memcmp(ByteArrayAddressOfElementAt(thiz, 0),
ByteArrayAddressOfElementAt(otherString, 0),
+2 -1
View File
@@ -80,7 +80,8 @@ KInt Kotlin_String_hashCode(KString thiz);
KBoolean Kotlin_String_equals(KString thiz, KConstRef other);
KInt Kotlin_String_compareTo(KString thiz, KString other);
KChar Kotlin_String_get(KString thiz, KInt index);
KString Kotlin_String_fromUtf8Array(const ArrayHeader* array);
KString Kotlin_String_fromUtf8Array(const ArrayHeader* array, KInt start, KInt size);
KString Kotlin_String_fromCharArray(const ArrayHeader* array, KInt start, KInt size);
KString Kotlin_String_plusImpl(KString thiz, KString other);
KInt Kotlin_String_getStringLength(KString thiz);
KString Kotlin_String_subSequence(KString thiz, KInt startIndex, KInt endIndex);
+3
View File
@@ -66,6 +66,9 @@ public final class CharArray : Cloneable {
@SymbolName("Kotlin_CharArray_clone")
external public override fun clone(): Any
@SymbolName("Kotlin_CharArray_copyOf")
external public fun copyOf(newSize: Int): CharArray
@SymbolName("Kotlin_CharArray_getArrayLength")
external private fun getArrayLength(): Int
-2
View File
@@ -1,7 +1,5 @@
package kotlin
@SymbolName("Kotlin_String_fromUtf8Array")
external fun fromUtf8Array(array: ByteArray) : String
// TODO: enable, once global variables implemented.
// @SymbolName("theEmptyString")
@@ -167,15 +167,16 @@ class ArrayList<E> private constructor(
}
override fun toString(): String {
var result = "["
val sb = StringBuilder(2 + length * 3)
sb.append("[")
var i = 0
while (i < length) {
if (i > 0) result += ", "
result += array[offset + i].toString()
if (i > 0) sb.append(", ")
sb.append(array[offset + i])
i++
}
result += "]"
return result
sb.append("]")
return sb.toString()
}
// ---------------------------- private ----------------------------
@@ -0,0 +1,103 @@
package kotlin.text
@SymbolName("Kotlin_String_fromUtf8Array")
external fun fromUtf8Array(array: ByteArray, start: Int, size: Int) : String
// TODO: make it somewhat private?
@SymbolName("Kotlin_String_fromCharArray")
external fun fromCharArray(array: CharArray, start: Int, size: Int) : String
@SymbolName("Kotlin_String_toCharArray")
external fun toCharArray(string: String) : CharArray
class StringBuilder private constructor (
private var array: CharArray
) : CharSequence {
constructor() : this(10)
constructor(capacity: Int) : this(CharArray(capacity))
constructor(string: String) : this(toCharArray(string)) {
length = array.size
}
override var length: Int = 0
set(capacity) {
ensureCapacity(capacity)
field = capacity
}
override fun get(index: Int): Char {
checkIndex(index)
return array[index]
}
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence = substring(startIndex, endIndex)
override fun toString(): String = fromCharArray(array, 0, length)
fun substring(startIndex: Int, endIndex: Int): String {
checkInsertIndex(startIndex)
checkInsertIndexFrom(endIndex, startIndex)
return fromCharArray(array, startIndex, endIndex - startIndex)
}
fun trimToSize() {
if (length < array.size)
array = array.copyOf(length)
}
fun ensureCapacity(capacity: Int) {
if (capacity > array.size) {
var newSize = array.size * 3 / 2
if (capacity > newSize)
newSize = capacity
array = array.copyOf(newSize)
}
}
fun append(it: Char) {
ensureExtraCapacity(1)
array[length++] = it
}
fun append(it: CharArray) {
ensureExtraCapacity(it.size)
for (c in it)
array[length++] = c
}
fun append(it: String) {
ensureExtraCapacity(it.length)
for (c in toCharArray(it))
array[length++] = c
}
fun append(it: Boolean) = append(it.toString())
fun append(it: Byte) = append(it.toString())
fun append(it: Short) = append(it.toString())
fun append(it: Int) = append(it.toString())
fun append(it: Long) = append(it.toString())
fun append(it: Float) = append(it.toString())
fun append(it: Double) = append(it.toString())
fun append(it: Any?) = append(it.toString())
// ---------------------------- private ----------------------------
private fun ensureExtraCapacity(n: Int) {
ensureCapacity(length + n)
}
private fun checkIndex(index: Int) {
if (index < 0 || index >= length) throw IndexOutOfBoundsException()
}
private fun checkInsertIndex(index: Int) {
if (index < 0 || index > length) throw IndexOutOfBoundsException()
}
private fun checkInsertIndexFrom(index: Int, fromIndex: Int) {
if (index < fromIndex || index > length) throw IndexOutOfBoundsException()
}
}