Created
April 5, 2018 04:27
-
-
Save onevcat/7397d13b96ef10a63fc10db305f46e8e to your computer and use it in GitHub Desktop.
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
struct _ContiguousArrayBuffer<Element> : _ArrayBufferProtocol { | |
internal var _storage: _ContiguousArrayStorageBase | |
internal func _initStorageHeader(count: Int, capacity: Int) { | |
#if _runtime(_ObjC) | |
let verbatim = _isBridgedVerbatimToObjectiveC(Element.self) | |
#else | |
let verbatim = false | |
#endif | |
_storage.countAndCapacity = _ArrayBody(count: count, capacity: capacity, elementTypeIsBridgedVerbatim: verbatim) | |
} | |
internal init(_uninitializedCount uninitializedCount: Int, minimumCapacity: Int) { | |
let realMinimumCapacity = Swift.max(uninitializedCount, minimumCapacity) | |
if realMinimumCapacity == 0 { | |
self = _ContiguousArrayBuffer<Element>() | |
} else { | |
_storage = Builtin.allocWithTailElems_1(_ContiguousArrayStorage<Element>.self, realMinimumCapacity._builtinWordValue, Element.self) | |
let storageAddr = UnsafeMutableRawPointer(Builtin.bridgeToRawPointer(_storage)) | |
let endAddr = storageAddr + _stdlib_malloc_size(storageAddr) | |
let realCapacity = endAddr.assumingMemoryBound(to: Element.self) - firstElementAddress | |
_initStorageHeader(count: uninitializedCount, capacity: realCapacity) | |
} | |
} | |
internal init(count: Int, storage: _ContiguousArrayStorage<Element>) { | |
_storage = storage | |
_initStorageHeader(count: count, capacity: count) | |
} | |
internal init(_ storage: _ContiguousArrayStorageBase) { | |
_storage = storage | |
} | |
internal var arrayPropertyIsNativeTypeChecked: Bool { | |
return true | |
} | |
internal var firstElementAddress: UnsafeMutablePointer<Element> { | |
return UnsafeMutablePointer(Builtin.projectTailElems(_storage, | |
Element.self)) | |
} | |
internal var firstElementAddressIfContiguous: UnsafeMutablePointer<Element>? { | |
return firstElementAddress | |
} | |
internal func withUnsafeBufferPointer<R>(_ body: (UnsafeBufferPointer<Element>) throws -> R) rethrows -> R { | |
return try body(UnsafeBufferPointer(start: firstElementAddress, count: count)) | |
} | |
internal mutating func withUnsafeMutableBufferPointer<R>(_ body: (UnsafeMutableBufferPointer<Element>) throws -> R) rethrows -> R { | |
return try body(UnsafeMutableBufferPointer(start: firstElementAddress, count: count)) | |
} | |
internal init() { | |
_storage = _emptyArrayStorage | |
} | |
internal init(_buffer buffer: _ContiguousArrayBuffer, shiftedToStartIndex: Int) { | |
self = buffer | |
} | |
internal mutating func requestUniqueMutableBackingBuffer(minimumCapacity: Int) -> _ContiguousArrayBuffer<Element>? { | |
if isUniquelyReferenced() && capacity >= minimumCapacity { | |
return self | |
} | |
return nil | |
} | |
internal mutating func isMutableAndUniquelyReferenced() -> Bool { | |
return isUniquelyReferenced() | |
} | |
internal mutating func isMutableAndUniquelyReferencedOrPinned() -> Bool { | |
return isUniquelyReferencedOrPinned() | |
} | |
internal func requestNativeBuffer() -> _ContiguousArrayBuffer<Element>? { | |
return self | |
} | |
internal func getElement(_ i: Int) -> Element { | |
return firstElementAddress[i] | |
} | |
internal subscript(i: Int) -> Element { | |
get { return getElement(i) } | |
nonmutating set { | |
var nv = newValue | |
let tmp = nv | |
nv = firstElementAddress[i] | |
firstElementAddress[i] = tmp | |
} | |
} | |
internal var count: Int { | |
get { return _storage.countAndCapacity.count } | |
nonmutating set { | |
_storage.countAndCapacity.count = newValue | |
} | |
} | |
internal var capacity: Int { | |
return _storage.countAndCapacity.capacity | |
} | |
internal func _copyContents(subRange bounds: Range<Int>, initializing target: UnsafeMutablePointer<Element>) -> UnsafeMutablePointer<Element> { | |
let initializedCount = bounds.upperBound - bounds.lowerBound | |
target.initialize(from: firstElementAddress + bounds.lowerBound, count: initializedCount) | |
return target + initializedCount | |
} | |
internal subscript(bounds: Range<Int>) -> _SliceBuffer<Element> { | |
get { | |
return _SliceBuffer(owner: _storage, subscriptBaseAddress: subscriptBaseAddress, indices: bounds, hasNativeBuffer: true) | |
} | |
set { | |
fatalError("not implemented") | |
} | |
} | |
internal mutating func isUniquelyReferenced() -> Bool { | |
return _isUnique(&_storage) | |
} | |
internal mutating func isUniquelyReferencedOrPinned() -> Bool { | |
return _isUniqueOrPinned(&_storage) | |
} | |
//... | |
internal func _copyCollectionToContiguousArray<C : Collection>(_ source: C) -> ContiguousArray<C.Element> { | |
let count: Int = numericCast(source.count) | |
if count == 0 { | |
return ContiguousArray() | |
} | |
let result = _ContiguousArrayBuffer<C.Element>(_uninitializedCount: count, minimumCapacity: 0) | |
var p = result.firstElementAddress | |
var i = source.startIndex | |
for _ in 0..<count { | |
p.initialize(to: source[i]) | |
source.formIndex(after: &i) | |
p += 1 | |
} | |
_expectEnd(of: source, is: i) | |
return ContiguousArray(_buffer: result) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment