| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See http://swift.org/LICENSE.txt for license information |
| // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| |
| import CoreFoundation |
| |
| extension Dictionary : _ObjectTypeBridgeable { |
| |
| public typealias _ObjectType = NSDictionary |
| public func _bridgeToObjectiveC() -> _ObjectType { |
| let keyBuffer = UnsafeMutablePointer<NSObject>.allocate(capacity: count) |
| let valueBuffer = UnsafeMutablePointer<AnyObject>.allocate(capacity: count) |
| |
| var idx = 0 |
| |
| self.forEach { (keyItem, valueItem) in |
| let key = _SwiftValue.store(keyItem) |
| let value = _SwiftValue.store(valueItem) |
| keyBuffer.advanced(by: idx).initialize(to: key) |
| valueBuffer.advanced(by: idx).initialize(to: value) |
| idx += 1 |
| } |
| |
| let dict = NSDictionary(objects: valueBuffer, forKeys: keyBuffer, count: count) |
| |
| keyBuffer.deinitialize(count: count) |
| valueBuffer.deinitialize(count: count) |
| keyBuffer.deallocate(capacity: count) |
| valueBuffer.deallocate(capacity: count) |
| |
| return dict |
| |
| } |
| |
| static public func _forceBridgeFromObjectiveC(_ source: _ObjectType, result: inout Dictionary?) { |
| result = _unconditionallyBridgeFromObjectiveC(source) |
| } |
| |
| @discardableResult |
| static public func _conditionallyBridgeFromObjectiveC(_ source: _ObjectType, result: inout Dictionary?) -> Bool { |
| var dict = [Key: Value]() |
| var failedConversion = false |
| |
| if type(of: source) == NSDictionary.self || type(of: source) == NSMutableDictionary.self { |
| source.enumerateKeysAndObjects(options: []) { key, value, stop in |
| guard let key = key as? Key, let value = value as? Value else { |
| failedConversion = true |
| stop.pointee = true |
| return |
| } |
| dict[key] = value |
| } |
| } else if type(of: source) == _NSCFDictionary.self { |
| let cf = source._cfObject |
| let cnt = CFDictionaryGetCount(cf) |
| |
| let keys = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: cnt) |
| let values = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: cnt) |
| |
| CFDictionaryGetKeysAndValues(cf, keys, values) |
| |
| for idx in 0..<cnt { |
| let key = _SwiftValue.fetch(nonOptional: unsafeBitCast(keys.advanced(by: idx).pointee!, to: AnyObject.self)) |
| let value = _SwiftValue.fetch(nonOptional: unsafeBitCast(values.advanced(by: idx).pointee!, to: AnyObject.self)) |
| guard let k = key as? Key, let v = value as? Value else { |
| failedConversion = true |
| break |
| } |
| dict[k] = v |
| } |
| keys.deinitialize(count: cnt) |
| values.deinitialize(count: cnt) |
| keys.deallocate(capacity: cnt) |
| values.deallocate(capacity: cnt) |
| } |
| if !failedConversion { |
| result = dict |
| return true |
| } |
| return false |
| } |
| |
| static public func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectType?) -> Dictionary { |
| if let object = source { |
| var value: Dictionary<Key, Value>? |
| _conditionallyBridgeFromObjectiveC(object, result: &value) |
| return value! |
| } else { |
| return Dictionary<Key, Value>() |
| } |
| } |
| } |