// // Measuable.swift // HandyJSON // // Created by zhouzhuo on 15/07/2017. // Copyright © 2017 aliyun. All rights reserved. // import Foundation typealias Byte = Int8 public protocol _Measurable {} extension _Measurable { // locate the head of a struct type object in memory mutating func headPointerOfStruct() -> UnsafeMutablePointer { return withUnsafeMutablePointer(to: &self) { return UnsafeMutableRawPointer($0).bindMemory(to: Byte.self, capacity: MemoryLayout.stride) } } // locating the head of a class type object in memory mutating func headPointerOfClass() -> UnsafeMutablePointer { let opaquePointer = Unmanaged.passUnretained(self as AnyObject).toOpaque() let mutableTypedPointer = opaquePointer.bindMemory(to: Byte.self, capacity: MemoryLayout.stride) return UnsafeMutablePointer(mutableTypedPointer) } // locating the head of an object mutating func headPointer() -> UnsafeMutablePointer { if Self.self is AnyClass { return self.headPointerOfClass() } else { return self.headPointerOfStruct() } } func isNSObjectType() -> Bool { return (type(of: self) as? NSObject.Type) != nil } func getBridgedPropertyList() -> Set { if let anyClass = type(of: self) as? AnyClass { return _getBridgedPropertyList(anyClass: anyClass) } return [] } func _getBridgedPropertyList(anyClass: AnyClass) -> Set { if !(anyClass is HandyJSON.Type) { return [] } var propertyList = Set() if let superClass = class_getSuperclass(anyClass), superClass != NSObject.self { propertyList = propertyList.union(_getBridgedPropertyList(anyClass: superClass)) } let count = UnsafeMutablePointer.allocate(capacity: 1) if let props = class_copyPropertyList(anyClass, count) { for i in 0 ..< count.pointee { let name = String(cString: property_getName(props.advanced(by: Int(i)).pointee)) propertyList.insert(name) } free(props) } #if swift(>=4.1) count.deallocate() #else count.deallocate(capacity: 1) #endif return propertyList } // memory size occupy by self object static func size() -> Int { return MemoryLayout.size } // align static func align() -> Int { return MemoryLayout.alignment } // Returns the offset to the next integer that is greater than // or equal to Value and is a multiple of Align. Align must be // non-zero. static func offsetToAlignment(value: Int, align: Int) -> Int { let m = value % align return m == 0 ? 0 : (align - m) } }