Last active
May 21, 2017 23:10
-
-
Save RoshanNindrai/b12b4fb3684a6a2ef354c7d32aaedf27 to your computer and use it in GitHub Desktop.
This is an exercise to implement List using swift mutable pointers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // List implementation using UnsafeMutablePointer. | |
| final class InternalList<T> { | |
| var count: Int | |
| var size: Int | |
| var ptr: UnsafeMutablePointer<T>? | |
| init(count: Int, ptrs: UnsafeMutablePointer<T>? = nil) { | |
| self.count = count | |
| size = count | |
| ptr = ptrs | |
| } | |
| func append(_ data: T) { | |
| // Time to allocate some memory ohh yeah | |
| if size == count { | |
| let newSize = max(2 * size, 16) | |
| let newPtr = UnsafeMutablePointer<T>.allocate(capacity: newSize) | |
| if ptr != nil { | |
| newPtr.moveInitialize(from: ptr!, count: count) | |
| } | |
| ptr?.deallocate(capacity: size) | |
| ptr = newPtr | |
| } | |
| (ptr! + count).initialize(to: data) | |
| count += 1 | |
| } | |
| func remove(at index: Int) { | |
| guard count != 0, index < count else { | |
| return | |
| } | |
| (ptr! + index).deinitialize() | |
| ptr!.moveInitialize(from: ptr! + index + 1, count: count - index - 1) | |
| count -= 1 | |
| } | |
| func at(_ index: Int) -> T { | |
| guard index < count else { | |
| fatalError("Index out of range") | |
| } | |
| return ptr![index] | |
| } | |
| func update(at index: Int, data: T) { | |
| guard index <= count else { | |
| return | |
| } | |
| (ptr! + index).initialize(to: data) | |
| count += 1 | |
| } | |
| func copy() -> InternalList<T> { | |
| return InternalList(count: count, ptrs: ptr) | |
| } | |
| } | |
| struct List<T> { | |
| fileprivate var _internalData: InternalList<T> = InternalList<T>(count: 0) | |
| var count: Int { | |
| return _internalData.count ?? 0 | |
| } | |
| var isEmpty: Bool { | |
| return count == 0 | |
| } | |
| } | |
| extension List { | |
| mutating func append(_ data: T) { | |
| copyIfNeeded() | |
| _internalData.append(data) | |
| } | |
| mutating func remove(at index: Int) { | |
| copyIfNeeded() | |
| _internalData.remove(at: index) | |
| } | |
| subscript(_ index: Int) -> T { | |
| get { | |
| return _internalData.at(index) | |
| } | |
| set { | |
| copyIfNeeded() | |
| _internalData.update(at: index, data: newValue) | |
| } | |
| } | |
| } | |
| extension List { | |
| mutating func copyIfNeeded() { | |
| if !isKnownUniquelyReferenced(&_internalData) { | |
| _internalData = _internalData.copy() | |
| } | |
| } | |
| } | |
| var testList = List<Int>() | |
| assert(testList.isEmpty) | |
| assert(testList.count == 0) | |
| testList.append(1) | |
| assert(testList.count == 1) | |
| assert(!testList.isEmpty) | |
| XCAssertTrue(testList[0] == 1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment