How can we prove that copy on write is applied to strings of more than 15 characters in Swift? - swift

I wrote the following code in Xcode to try and prove copy on write in Swift:
func print(address o: UnsafeRawPointer) {
print(o)
}
func longStringMemoryTest() {
var longStr1 = "abcdefghijklmnopqr"
var longStr2 = longStr1
print(address: longStr1)
print(address: longStr2)
print("[append 'stu' to 'longStr2']")
longStr2 += "stu"
print(address: longStr1)
print(address: longStr2)
var test = "abcdefghijklmnopqr"
print(address: test)
print("[Fin]")
}
However, the console always prints the same address for longStr1 and longStr2, even though longStr1 has a value of "abcdefghijklmnopqr" and longStr2 has a value of "abcdefghijklmnopqrstu". I can't figure out what I'm missing in this code. Can you explain how to prove copy on write for strings in Swift and why the address is always the same for longStr1 and longStr2?

Related

getch() equivalent in Swift: read a single character from stdin without a newline

I'm looking for a Swift function like getch() from C to read a single character from terminal input without requiring the user to press the return key. getchar() and readLine() are not sufficient, as they both require return.
There's a getch() function from ncurses which looked promising, but unfortunately seems to require taking over the display of the whole window.
After searching for a while online, I landed on the following (partly based on this answer):
import Foundation
extension FileHandle {
func enableRawMode() -> termios {
var raw = termios()
tcgetattr(self.fileDescriptor, &raw)
let original = raw
raw.c_lflag &= ~UInt(ECHO | ICANON)
tcsetattr(self.fileDescriptor, TCSADRAIN, &raw)
return original
}
func restoreRawMode(originalTerm: termios) {
var term = originalTerm
tcsetattr(self.fileDescriptor, TCSADRAIN, &term)
}
}
func getch() -> UInt8 {
let handle = FileHandle.standardInput
let term = handle.enableRawMode()
defer { handle.restoreRawMode(originalTerm: term) }
var byte: UInt8 = 0
read(handle.fileDescriptor, &byte, 1)
return byte
}
fputs("Press any key to continue... ", stdout)
fflush(stdout)
let x = getch()
print()
print("Got character: \(UnicodeScalar(x))")

Swift 4.2 computed variable [String:Bool] does not assign value correctly

[MacOS 10.14.1, Xcode 10.1, Swift 4.2]
I'm working on creating a getopt style CLI argument processor whilst practising Swift. In my design, I decided to create a computed variable, represented as a [String:Bool] dictionary, that can be checked to see if an option (key) is just a switch (value = true) or whether it may include parameters (value = false). So I've written the code below, all of which is, at the moment, in my small (300 lines) main.swift file.
The code works correctly in a playground, but in my Swift Xcode project, whilst the dictionary's keys are correct, values are always false and inconsistent with the printed messages.
let options = "cwt:i:o:"
//lazy var optionIsSwitch : [String:Bool] = { (This will be moved to a class)
var optionIsSwitch : [String:Bool] = {
var tmpOptionIsSwitch : [String:Bool] = [:]
let optionsStrAsArray = Array(options)
let flags = Array(options.filter { !":".contains($0) } )
tmpOptionIsSwitch.reserveCapacity(flags.count)
for thisOption in 0...flags.count-1 {
var posInOptionsStr = 0
while posInOptionsStr < optionsStrAsArray.count-1 && flags[thisOption] != optionsStrAsArray[posInOptionsStr] {
posInOptionsStr += 1
}
if posInOptionsStr < optionsStrAsArray.count-1 && optionsStrAsArray[posInOptionsStr+1] == ":" {
tmpOptionIsSwitch[String(flags[thisOption])] = false
print("\(flags[thisOption]) is FALSE")
} else {
tmpOptionIsSwitch[String(flags[thisOption])] = true
print("\(flags[thisOption]) is TRUE")
}
}
return tmpOptionIsSwitch
}()
I've stepped through the code in my project to observe the execution sequence, and found it to be correct. As per the first image, tmpOptionIsSwitch returns a dictionary containing the right keys but all the values are set to false, which is inconsistent with the print statements.
As part of my debugging activities, I copied the above code into a Swift Playground where I found it gave the correct results, as per the image below.
Has anyone has such an issue? Is there something I've done wrong?

How to prove "copy-on-write" on String type in Swift

As the title said, I tried to prove myself that COW(copy on write) is supported for String in Swift. But I cannot find a proof. I proved the COW on Array and Dictionary after trying the following codes:
func address(of object: UnsafeRawPointer) -> String {
let addr = Int(bitPattern: object)
return String(format: "%p", addr)
}
var xArray = [20, 30, 40, 50, 60]
var yArray = xArray
// These two addresses were the same
address(of: xArray)
address(of: yArray)
yArray[0] = 200
// The address of yArray got changed
address(of: yArray)
But for String type, it was not working.
var xString = "Hello World"
var yString = xString
// These two addresses were different
address(of: xString)
address(of: yString)
And I dumped the test function from the official Swift code repo.
func _rawIdentifier(s: String) -> (UInt, UInt) {
let tripe = unsafeBitCast(s, to: (UInt, UInt, UInt).self)
let minusCount = (tripe.0, tripe.2)
return minusCount
}
But this function seems to only cast the actual value pointed to not the address. So two different String variables with the same value would have the same rawIdentifier. Still cannot prove COW to me.
var xString = "Hello World"
var yString = "Hello" + " World"
// These two rawIdentifiers were the same
_rawIdentifier(s: xString)
_rawIdentifier(s: yString)
So how does COW work on String type in Swift?
The compiler creates only a single storage for both
"Hello World" and "Hello" + " World".
You can verify that for example by examining the assembly code
obtained from
swiftc -emit-assembly cow.swift
which defines only a single string literal
.section __TEXT,__cstring,cstring_literals
L___unnamed_1:
.asciz "Hello World"
As soon as the string is mutated, the address of the string storage
buffer (the first member of that "magic" tuple, actually _baseAddress
of struct _StringCore, defined in StringCore.swift) changes:
var xString = "Hello World"
var yString = "Hello" + " World"
print(_rawIdentifier(s: xString)) // (4300325536, 0)
print(_rawIdentifier(s: yString)) // (4300325536, 0)
yString.append("!")
print(_rawIdentifier(s: yString)) // (4322384560, 4322384528)
And why does your
func address(of object: UnsafeRawPointer) -> String
function show the same values for xArray and yArray, but
not for xString and yString?
Passing an array to a function taking a unsafe pointer passes the
address of the first array element, that is the same for both
arrays if they share the storage.
Passing a string to a function taking an unsafe pointer passes a
pointer to a temporary UTF-8 representation of the string.
That address can be different in each call, even for the same string.
This behavior is documented in the "Using Swift with Cocoa and
Objective-C" reference for UnsafePointer<T> arguments, but apparently
works the same for UnsafeRawPointer arguments.

How to change the value of a child from a Mirror introspection

I'm doing a bunch of BLE in iOS, which means lots of tight packed C structures being encoded/decoded as byte packets. The following playground snippets illustrate what I'm trying to do generically.
import Foundation
// THE PROBLEM
struct Thing {
var a:UInt8 = 0
var b:UInt32 = 0
var c:UInt8 = 0
}
sizeof(Thing) // --> 9 :(
var thing = Thing(a: 0x42, b: 0xDEADBEAF, c: 0x13)
var data = NSData(bytes: &thing, length: sizeof(Thing)) // --> <42000000 afbeadde 13> :(
So given a series of fields of varying size, we don't get the "tightest" packing of bytes. Pretty well known and accepted. Given my simple structs, I'd like to be able to arbitrarily encode the fields back to back with no padding or alignment stuff. Relatively easy actually:
// ARBITRARY PACKING
var mirror = Mirror(reflecting: thing)
var output:[UInt8] = []
mirror.children.forEach { (label, child) in
switch child {
case let value as UInt32:
(0...3).forEach { output.append(UInt8((value >> ($0 * 8)) & 0xFF)) }
case let value as UInt8:
output.append(value)
default:
print("Don't know how to serialize \(child.dynamicType) (field \(label))")
}
}
output.count // --> 6 :)
data = NSData(bytes: &output, length: output.count) // --> <42afbead de13> :)
Huzzah! Works as expected. Could probably add a Class around it, or maybe a Protocol extension and have a nice utility. The problem I'm up against is the reverse process:
// ARBITRARY DEPACKING
var input = output.generate()
var thing2 = Thing()
"\(thing2.a), \(thing2.b), \(thing2.c)" // --> "0, 0, 0"
mirror = Mirror(reflecting:thing2)
mirror.children.forEach { (label, child) in
switch child {
case let oldValue as UInt8:
let newValue = input.next()!
print("new value for \(label!) would be \(newValue)")
// *(&child) = newValue // HOW TO DO THIS IN SWIFT??
case let oldValue as UInt32: // do little endian
var newValue:UInt32 = 0
(0...3).forEach {
newValue |= UInt32(input.next()!) << UInt32($0 * 8)
}
print("new value for \(label!) would be \(newValue)")
// *(&child) = newValue // HOW TO DO THIS IN SWIFT??
default:
print("skipping field \(label) of type \(child.dynamicType)")
}
}
Given an unpopulated struct value, I can decode the byte stream appropriately, figure out what the new value would be for each field. What I don't know how to do is to actually update the target struct with the new value. In my example above, I show how I might do it with C, get the pointer to the original child, and then update its value with the new value. I could do it easily in Python/Smalltalk/Ruby. But I don't know how one can do that in Swift.
UPDATE
As suggested in comments, I could do something like the following:
// SPECIFIC DEPACKING
extension GeneratorType where Element == UInt8 {
mutating func _UInt8() -> UInt8 {
return self.next()!
}
mutating func _UInt32() -> UInt32 {
var result:UInt32 = 0
(0...3).forEach {
result |= UInt32(self.next()!) << UInt32($0 * 8)
}
return result
}
}
extension Thing {
init(inout input:IndexingGenerator<[UInt8]>) {
self.init(a: input._UInt8(), b: input._UInt32(), c: input._UInt8())
}
}
input = output.generate()
let thing3 = Thing(input: &input)
"\(thing3.a), \(thing3.b), \(thing3.c)" // --> "66, 3735928495, 19"
Basically, I move the various stream decoding methods to byte stream (i.e. GeneratorType where Element == UInt8), and then I just have to write an initializer that strings those off in the same order and type the struct is defined as. I guess that part, which is essentially "copying" the structure definition itself (and therefore error prone), is what I had hoped to use some sort of introspection to handle. Mirrors are the only real Swift introspection I'm aware of, and it seems pretty limited.
As discussed in the comments, I suspect this is over-clever. Swift includes a lot of types not friendly to this approach. I would focus instead on how to make the boilerplate as easy as possible, without worrying about eliminating it. For example, this is very sloppy, but is in the direction I would probably go:
Start with some helper packer/unpacker functions:
func pack(values: Any...) -> [UInt8]{
var output:[UInt8] = []
for value in values {
switch value {
case let i as UInt32:
(0...3).forEach { output.append(UInt8((i >> ($0 * 8)) & 0xFF)) }
case let i as UInt8:
output.append(i)
default:
assertionFailure("Don't know how to serialize \(value.dynamicType)")
}
}
return output
}
func unpack<T>(bytes: AnyGenerator<UInt8>, inout target: T) throws {
switch target {
case is UInt32:
var newValue: UInt32 = 0
(0...3).forEach {
newValue |= UInt32(bytes.next()!) << UInt32($0 * 8)
}
target = newValue as! T
case is UInt8:
target = bytes.next()! as! T
default:
// Should throw an error here probably
assertionFailure("Don't know how to deserialize \(target.dynamicType)")
}
}
Then just call them:
struct Thing {
var a:UInt8 = 0
var b:UInt32 = 0
var c:UInt8 = 0
func encode() -> [UInt8] {
return pack(a, b, c)
}
static func decode(bytes: [UInt8]) throws -> Thing {
var thing = Thing()
let g = anyGenerator(bytes.generate())
try unpack(g, target: &thing.a)
try unpack(g, target: &thing.b)
try unpack(g, target: &thing.c)
return thing
}
}
A little more thought might be able to make the decode method a little less repetitive, but this is still probably the way I would go, explicitly listing the fields you want to encode rather than trying to introspect them. As you note, Swift introspection is very limited, and it may be that way for a long time. It's mostly used for debugging and logging, not logic.
I have tagged Rob's answer is the official answer. But I'd thought I'd share what I ended up doing as well, inspired by the comments and answers.
First, I fleshed out my "Problem" a little to include a nested structure:
struct Inner {
var ai:UInt16 = 0
var bi:UInt8 = 0
}
struct Thing {
var a:UInt8 = 0
var b:UInt32 = 0
var inner = Inner()
var c:UInt8 = 0
}
sizeof(Thing) // --> 12 :(
var thing = Thing(a: 0x42, b: 0xDEADBEAF, inner: Inner(ai: 0x1122, bi: 0xDD), c: 0x13)
var data = NSData(bytes: &thing, length: sizeof(Thing)) // --> <42000000 afbeadde 2211dd13> :(
For Arbitrary Packing, I stuck with the same generic approach:
protocol Packable {
func packed() -> [UInt8]
}
extension UInt8:Packable {
func packed() -> [UInt8] {
return [self]
}
}
extension UInt16:Packable {
func packed() -> [UInt8] {
return [(UInt8((self >> 0) & 0xFF)), (UInt8((self >> 8) & 0xFF))]
}
}
extension UInt32:Packable {
func packed() -> [UInt8] {
return [(UInt8((self >> 0) & 0xFF)), (UInt8((self >> 8) & 0xFF)), (UInt8((self >> 16) & 0xFF)), (UInt8((self >> 24) & 0xFF))]
}
}
extension Packable {
func packed() -> [UInt8] {
let mirror = Mirror(reflecting:self)
var bytes:[UInt8] = []
mirror.children.forEach { (label, child) in
switch child {
case let value as Packable:
bytes += value.packed()
default:
print("Don't know how to serialize \(child.dynamicType) (field \(label))")
}
}
return bytes
}
}
Being able to "pack" things is as easy adding them to the Packable protocol and telling them to pack themselves. For my cases above, I only need 3 different types of signed integers, but one could add lots more. For example, in my own code, I have some Enums derived from UInt8 which I added the packed method to.
extension Thing:Packable { }
extension Inner:Packable { }
var output = thing.packed()
output.count // --> 9 :)
data = NSData(bytes: &output, length: output.count) // --> <42afbead de2211dd 13> :)
To be able to unpack stuff, I came up with a little bit of support:
protocol UnpackablePrimitive {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> Self
}
extension UInt8:UnpackablePrimitive {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> UInt8 {
return input.next()!
}
}
extension UInt16:UnpackablePrimitive {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> UInt16 {
return UInt16(input.next()!) | (UInt16(input.next()!) << 8)
}
}
extension UInt32:UnpackablePrimitive {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> UInt32 {
return UInt32(input.next()!) | (UInt32(input.next()!) << 8) | (UInt32(input.next()!) << 16) | (UInt32(input.next()!) << 24)
}
}
With this, I can then add initializers to my high level structures, e.g.
extension Inner:Unpackable {
init(inout packed bytes:IndexingGenerator<[UInt8]>) {
self.init(ai: UInt16.unpack(&bytes), bi: UInt8.unpack(&bytes))
}
}
extension Thing:Unpackable {
init(inout packed bytes:IndexingGenerator<[UInt8]>) {
self.init(a: UInt8.unpack(&bytes), b: UInt32.unpack(&bytes), inner: Inner(packed:&bytes), c: UInt8.unpack(&bytes))
}
}
What I liked about this is that these initializers call the default initializer in the same order and types as the structure is defined. So if the structure changes in type or order, I have to revisit the (packed:) initializer. The kids a bit long, but not too.
What I didn't like about this, was having to pass the inout everywhere. I'm honestly not sure what the value is of value based generators, since passing them around you almost always want to share state. Kind of the whole point of reifying an object that captures the position of a stream of data, is to be able to share it. I also don't like having to specify IndexingGenerator directly, but I imagine there's some fu magic that would make that less specific and still work, but I'm not there yet.
I did play with something more pythonic, where I return a tuple of the type and the remainder of a passed array (rather than a stream/generator), but that wasn't nearly as easy to use at the top level init level.
I also tried putting the static methods as extensions on byte based generators, but you have to use a function (would rather have used a computed var with side effects) there whose name doesn't match a type, so you end up with something like
self.init(a: bytes._UInt8(), b: bytes._UInt32(), inner: Inner(packed:&bytes), c: bytes._UInt8())
This is shorter, but doesn't put the type like functions next to the argument names. And would require all kinds of application specific method names to be added as well as one extended the set of UnpackablePrimitives.

What's the best way to convert String into [Character] in Swift?

I would like to run a filter on a string. My first attempt failed as string is not automagically converted to Character[].
var s: String = "abc"
s.filter { $0 != "b" }
If I clumsily convert the String to Character[] with following code, it works as expected. But surely there has to be a neater way?
var cs:Character[] = []
for c in s {
cs = cs + [c]
}
cs = cs.filter { $0 != "b" }
println(cs)
String conforms to the CollectionType protocol, so you can pass it directly to the function forms of map and filter without converting it at all:
let cs = filter(s) { $0 != "f" }
cs here is an Array of Characters. You can turn it into a String by using the String(seq:) initializer, which constructs a String from any SequenceType of Characters. (SequenceType is a protocol that all lists conform to; for loops use them, among many other things.)
let filteredString = String(seq: cs)
Of course, you can just as easily put those two things in one statement:
let filteredString = String(seq: filter(s) { $0 != "f" })
Or, if you want to make a convenience filter method like the one on Array, you can use an extension:
extension String {
func filter(includeElement: Character -> Bool) -> String {
return String(seq: Swift.filter(self, includeElement))
}
}
(You write it "Swift.filter" so the compiler doesn't think you're trying to recursively call the filter method you're currently writing.)
As long as we're hiding how the filtering is performed, we might as well use a lazy filter, which should avoid constructing the temporary array at all:
extension String {
func filter(includeElement: Character -> Bool) -> String {
return String(seq: lazy(self).filter(includeElement))
}
}
I don't know of a built in way to do it, but you could write your own filter method for String:
extension String {
func filter(f: (Character) -> Bool) -> String {
var ret = ""
for character in self {
if (f(character)) {
ret += character
}
}
return ret
}
}
If you don't want to use an extension you could do this:
Array(s).filter({ $0 != "b" }).reduce("", combine: +)
You can use this syntax:
var chars = Character[]("abc")
I'm not 100% sure if the result is an array of Characters or not but works for my use case.
var str = "abc"
var chars = Character[](str)
var result = chars.map { char in "char is \(char)" }
result
The easiest way to convert a char to string is using the backslash (), for example I have a function to reverse a string, like so.
var identityNumber:String = id
for char in identityNumber{
reversedString = "\(char)" + reversedString
}