Files
swift-mirror/test/1_stdlib/NewStringAppending.swift
Dmitri Hrybenko f5de8757e4 stdlib: remove Word and UWord
These types are leftovers from the early pre-1.0 times when Int and UInt
were always 64-bit on all platforms.  They serve no useful purpose
today.  Int and UInt are defined to be word-sized and should be used
instead.

rdar://18693488

Swift SVN r30564
2015-07-24 05:01:32 +00:00

138 lines
4.0 KiB
Swift

// RUN: %target-run-stdlib-swift | FileCheck %s
// REQUIRES: executable_test
//
// Parts of this test depend on memory allocator specifics. The test
// should be rewritten soon so it doesn't expose legacy components
// like OpaqueString anyway, so we can just disable the failing
// configuration
//
// Memory allocator specifics also vary across platorms.
// REQUIRES: CPU=x86_64, OS=macosx
import Foundation
import Swift
func hexAddrVal<T>(x: T) -> String {
return "@0x" + String(UInt64(unsafeBitCast(x, Int.self)), radix: 16)
}
func hexAddr(x: AnyObject?) -> String {
if let owner = x {
if let y = owner as? _StringBuffer._Storage.Storage {
return ".Native\(hexAddrVal(y))"
}
if let y = owner as? NSString {
return ".Cocoa\(hexAddrVal(y))"
}
else {
return "?Uknown?\(hexAddrVal(owner))"
}
}
return "nil"
}
func repr(x: NSString) -> String {
return "\(NSStringFromClass(object_getClass(x)))\(hexAddr(x)) = \"\(x)\""
}
func repr(x: _StringCore) -> String {
if x.hasContiguousStorage {
if let b = x.nativeBuffer {
var offset = x.elementWidth == 2
? UnsafeMutablePointer(b.start) - x.startUTF16
: UnsafeMutablePointer(b.start) - x.startASCII
return "Contiguous(owner: "
+ "\(hexAddr(x._owner))[\(offset)...\(x.count + offset)]"
+ ", capacity = \(b.capacity))"
}
return "Contiguous(owner: \(hexAddr(x._owner)), count: \(x.count))"
}
else if let b2 = x.cocoaBuffer {
return "Opaque(buffer: \(hexAddr(b2))[0...\(x.count)])"
}
return "?????"
}
func repr(x: String) -> String {
return "String(\(repr(x._core))) = \"\(x)\""
}
// ===------- Appending -------===
// CHECK: --- Appending ---
print("--- Appending ---")
var s = "" // start non-empty
// To make this test independent of the memory allocator implementation,
// explicitly request initial capacity.
s.reserveCapacity(8)
// CHECK-NEXT: String(Contiguous(owner: .Native@[[buffer0:[x0-9a-f]+]][0...2], capacity = 8)) = "1"
s += "1"
print("\(repr(s))")
// CHECK-NEXT: String(Contiguous(owner: .Native@[[buffer1:[x0-9a-f]+]][0...8], capacity = 8)) = "1234567"
s += "234567"
print("\(repr(s))")
// -- expect a reallocation here
// CHECK-NEXT: String(Contiguous(owner: .Native@[[buffer2:[x0-9a-f]+]][0...9], capacity = 16)) = "12345678"
// CHECK-NOT: .Native@[[buffer1]]
s += "8"
print("\(repr(s))")
// CHECK-NEXT: String(Contiguous(owner: .Native@[[buffer2]][0...16], capacity = 16)) = "123456789012345"
s += "9012345"
print("\(repr(s))")
// -- expect a reallocation here
// Appending more than the next level of capacity only takes as much
// as required. I'm not sure whether this is a great idea, but the
// point is to prevent huge amounts of fragmentation when a long
// string is appended to a short one. The question, of course, is
// whether more appends are coming, in which case we should give it
// more capacity. It might be better to always grow to a multiple of
// the current capacity when the capacity is exceeded.
// CHECK-NEXT: String(Contiguous(owner: .Native@[[buffer3:[x0-9a-f]+]][0...48], capacity = 48))
// CHECK-NOT: .Native@[[buffer2]]
s += s + s
print("\(repr(s))")
// -- expect a reallocation here
// CHECK-NEXT: String(Contiguous(owner: .Native@[[buffer4:[x0-9a-f]+]][0...49], capacity = 96))
// CHECK-NOT: .Native@[[buffer3]]
s += "C"
print("\(repr(s))")
/// An additional reference to the same buffer doesn't, by itself,
/// impede the use of available capacity
var s1 = s
// CHECK-NEXT: String(Contiguous(owner: .Native@[[buffer4]][0...50], capacity = 96))
s += "F"
print("\(repr(s))")
// CHECK-NEXT: String(Contiguous(owner: .Native@[[buffer4]][0...49], capacity = 96))
print("\(repr(s1))")
/// The use of later buffer capacity by another string forces
/// reallocation
// CHECK-NEXT: String{{.*}} = {{.*}}X"
// CHECK-NOT: .Native@[[buffer4]]
s1 += "X"
print("\(repr(s1))")
/// Appending to an empty string re-uses the RHS
// CHECK-NEXT: .Native@[[buffer4]]
var s2 = String()
s2 += s
print("\(repr(s2))")