You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
2.8 KiB
95 lines
2.8 KiB
// |
|
// 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<Byte> { |
|
|
|
return withUnsafeMutablePointer(to: &self) { |
|
return UnsafeMutableRawPointer($0).bindMemory(to: Byte.self, capacity: MemoryLayout<Self>.stride) |
|
} |
|
} |
|
|
|
// locating the head of a class type object in memory |
|
mutating func headPointerOfClass() -> UnsafeMutablePointer<Byte> { |
|
|
|
let opaquePointer = Unmanaged.passUnretained(self as AnyObject).toOpaque() |
|
let mutableTypedPointer = opaquePointer.bindMemory(to: Byte.self, capacity: MemoryLayout<Self>.stride) |
|
return UnsafeMutablePointer<Byte>(mutableTypedPointer) |
|
} |
|
|
|
// locating the head of an object |
|
mutating func headPointer() -> UnsafeMutablePointer<Byte> { |
|
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<String> { |
|
if let anyClass = type(of: self) as? AnyClass { |
|
return _getBridgedPropertyList(anyClass: anyClass) |
|
} |
|
return [] |
|
} |
|
|
|
func _getBridgedPropertyList(anyClass: AnyClass) -> Set<String> { |
|
if !(anyClass is HandyJSON.Type) { |
|
return [] |
|
} |
|
var propertyList = Set<String>() |
|
if let superClass = class_getSuperclass(anyClass), superClass != NSObject.self { |
|
propertyList = propertyList.union(_getBridgedPropertyList(anyClass: superClass)) |
|
} |
|
let count = UnsafeMutablePointer<UInt32>.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<Self>.size |
|
} |
|
|
|
// align |
|
static func align() -> Int { |
|
return MemoryLayout<Self>.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) |
|
} |
|
} |
|
|
|
|