Skip to content

Instantly share code, notes, and snippets.

@onevcat
Created April 5, 2018 04:27
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 onevcat/7397d13b96ef10a63fc10db305f46e8e to your computer and use it in GitHub Desktop.
Save onevcat/7397d13b96ef10a63fc10db305f46e8e to your computer and use it in GitHub Desktop.
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