Skip to content

Instantly share code, notes, and snippets.

@zhongwuzw
Last active August 31, 2017 09:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zhongwuzw/2b194c9fb2e4aaaca04cedb79bf207f1 to your computer and use it in GitHub Desktop.
Save zhongwuzw/2b194c9fb2e4aaaca04cedb79bf207f1 to your computer and use it in GitHub Desktop.
Array implements `COW` for Swift 3
class ArrayImpl<T> {
var space: Int
var count: Int
var ptr: UnsafeMutablePointer<T>!
init(count: Int = 0, ptr: UnsafeMutablePointer<T>? = nil) {
self.count = count
self.space = count
self.ptr = UnsafeMutablePointer<T>.allocate(capacity: count)
guard let ptr = ptr else {
return
}
self.ptr.initialize(from: ptr, count: count)
}
func append(obj: T) {
if space == count {
let newSpace = max(space * 2, 16)
let newPtr = UnsafeMutablePointer<T>.allocate(capacity: newSpace)
newPtr.moveInitialize(from: ptr, count: count)
ptr.deallocate(capacity: count)
ptr = newPtr
space = newSpace
}
(ptr + count).initialize(to: obj)
count += 1
}
func remove(at index: Int) {
(ptr + index).deinitialize()
(ptr + index).moveInitialize(from: ptr + index + 1, count: count - index - 1)
count -= 1
}
func copy() -> ArrayImpl<T> {
return ArrayImpl<T>(count: count, ptr: ptr)
}
deinit {
ptr.deinitialize(count: count)
ptr.deallocate(capacity: space)
}
}
struct Array<T> : CustomStringConvertible, Collection {
private var impl: ArrayImpl<T> = ArrayImpl<T>(count: 0, ptr: nil)
private mutating func ensureUnique() {
if !isKnownUniquelyReferenced(&impl) {
impl = impl.copy()
}
}
mutating func append(_ value: T) {
ensureUnique()
impl.append(obj: value)
}
mutating func remove(at index: Int) {
ensureUnique()
impl.remove(at: index)
}
var count: Int {
return impl.count
}
subscript(index: Int) -> T {
get {
return impl.ptr[index]
}
mutating set {
ensureUnique()
impl.ptr[index] = newValue
}
}
var description: String {
var str = ""
for value in self {
if !str.isEmpty {
str += ", "
}
str += String(describing: value)
}
return "(\(impl.ptr): " + str + ")"
}
typealias Index = Int
var startIndex: Index {
return 0
}
var endIndex: Index {
return count
}
func index(after i: Int) -> Int {
return i + 1
}
}
var array = Array<Int>()
var array2 = array
print((array, array2))
array.append(42)
array2.append(99)
array2.append(43)
print((array, array2))
var array3 = array2
array2[0] = 1
array3[0] = 0
print((array2, array3))
array3.remove(at: 1)
array3.remove(at: 0)
print(array3)
var array4 = Array<Int>()
for i in 0..<100 {
array4.append(i)
}
var array5 = array4
while array4.count > 3 {
array4.remove(at: 1)
}
print((array4, array5))
var strarray = Array<String>()
strarray.append("e")
for i in 0..<100 {
strarray.append("\(i)")
}
print(strarray)
var strarray2 = strarray
while strarray.count > 4 {
strarray.remove(at: 3)
}
while strarray2.count > 4 {
strarray2.remove(at: strarray2.count - 1)
}
print((strarray, strarray2))
for s in strarray {
print(s)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment