Skip to content

Instantly share code, notes, and snippets.

@airspeedswift
Last active October 8, 2022 19:52
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save airspeedswift/1fb7d6e3e73e53ce64f6 to your computer and use it in GitHub Desktop.
Save airspeedswift/1fb7d6e3e73e53ce64f6 to your computer and use it in GitHub Desktop.
Array using ManagedBuffer
private class MyArrayBuffer<Element>: ManagedBuffer<Int,Element> {
func clone() -> MyArrayBuffer<Element> {
return self.withUnsafeMutablePointerToElements { elements -> MyArrayBuffer<Element> in
return MyArrayBuffer<Element>.create(self.allocatedElementCount) { newBuf in
newBuf.withUnsafeMutablePointerToElements { newElems->Void in
newElems.initializeFrom(elements, count: self.value)
}
return self.value
} as! MyArrayBuffer<Element>
}
}
func resize(newSize: Int) -> MyArrayBuffer<Element> {
return self.withUnsafeMutablePointers { (val, oldElems) -> MyArrayBuffer<Element> in
let elementCount = self.value
return MyArrayBuffer<Element>.create(newSize) { newBuf in
newBuf.withUnsafeMutablePointerToElements { newElems->Void in
newElems.moveInitializeFrom(oldElems, count: elementCount)
}
val.memory = 0
return elementCount
} as! MyArrayBuffer<Element>
}
}
deinit {
self.withUnsafeMutablePointerToElements { elems->Void in
elems.destroy(self.value)
}
}
}
public struct MyArray<Element> {
private var _buf: MyArrayBuffer<Element>
public init() {
_buf = MyArrayBuffer<Element>.create(8) { _ in 0 } as! MyArrayBuffer<Element>
}
}
extension MyArray {
private mutating func ensureUniquelyReferenced() {
if !isUniquelyReferencedNonObjC(&_buf) {
_buf = _buf.clone()
}
}
private mutating func reserveCapacity(n: Int) {
if _buf.allocatedElementCount < n {
self.ensureUniquelyReferenced()
let newSize = max(_buf.allocatedElementCount*2, n)
_buf = _buf.resize(newSize)
}
}
}
extension MyArray: CollectionType {
public var startIndex: Int { return 0 }
public var endIndex: Int { return _buf.value }
public subscript(idx: Int) -> Element {
get {
guard idx < endIndex else { fatalError("Array index out of range") }
return _buf.withUnsafeMutablePointerToElements { $0[idx] }
}
set(newValue) {
guard idx < endIndex else { fatalError("Array index out of range") }
self.ensureUniquelyReferenced()
_buf.withUnsafeMutablePointerToElements { elems->Void in
elems[idx] = newValue
}
}
}
}
extension MyArray {
public mutating func append(x: Element) {
ensureUniquelyReferenced()
reserveCapacity(endIndex+1)
_buf.withUnsafeMutablePointers { (val, elems)->Void in
(elems + val.memory++).initialize(x)
}
}
public mutating func extend<S: SequenceType where S.Generator.Element == Element>(seq: S) {
for x in seq { self.append(x) }
}
}
extension MyArray: ArrayLiteralConvertible {
public init(arrayLiteral elements: Element...) {
self = MyArray()
self.extend(elements)
}
}
extension MyArray: CustomStringConvertible {
public var description: String {
return "[" + ", ".join(self.map { String($0) }) + "]"
}
}
func +=<Element, S: SequenceType where S.Generator.Element == Element>(inout lhs: MyArray<Element>, rhs: S) {
lhs.extend(rhs)
}
func +<Element, S: SequenceType where S.Generator.Element == Element>(var lhs: MyArray<Element>, rhs: S) -> MyArray<Element> {
lhs += rhs
return lhs
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment