-
-
Save antmd/32fe6ddec67e71818473 to your computer and use it in GitHub Desktop.
This file contains 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
//////////////////////////////////////////////// | |
// | |
// Swift and Objective-C Class Parsing | |
// | |
//////////////////////////////////////////////// | |
import Foundation | |
// Class parsing | |
enum ClassType { | |
case Swift, ObjectiveC | |
func toString() -> String { | |
switch self { | |
case .Swift: | |
return "Swift" | |
case .ObjectiveC: | |
return "Objective-C" | |
} | |
} | |
} | |
struct ParsedClass { | |
let type: ClassType | |
let name: String | |
let mangledName: String? | |
let moduleName: String? | |
} | |
extension String { | |
subscript (r: Range<Int>) -> String { | |
get { | |
let startIndex = advance(self.startIndex, r.startIndex) | |
let endIndex = advance(startIndex, r.endIndex) | |
return self[Range(start: startIndex, end: endIndex)] | |
} | |
} | |
} | |
func parseClass(aClass: AnyClass) -> ParsedClass { | |
// Swift mangling details found here: http://www.eswick.com/2014/06/inside-swift | |
let originalName = NSStringFromClass(aClass) | |
if !originalName.hasPrefix("_T") { | |
// Not a Swift symbol | |
return ParsedClass(type: ClassType.ObjectiveC, | |
name: originalName, | |
mangledName: nil, | |
moduleName: nil) | |
} | |
let originalNameLength = originalName.utf16count | |
var cursor = 4 | |
var substring = originalName[cursor..originalNameLength-cursor] | |
// Module | |
let moduleLength = substring.bridgeToObjectiveC().integerValue | |
let moduleLengthLength = "\(moduleLength)".utf16count | |
let moduleName = substring[moduleLengthLength..moduleLength] | |
// Update cursor and substring | |
cursor += moduleLengthLength + moduleName.utf16count | |
substring = originalName[cursor..originalNameLength-cursor] | |
// Class name | |
let classLength = substring.bridgeToObjectiveC().integerValue | |
let classLengthLength = "\(classLength)".utf16count | |
let className = substring[classLengthLength..classLength] | |
return ParsedClass(type: ClassType.Swift, | |
name: className, | |
mangledName: originalName, | |
moduleName: moduleName) | |
} | |
// Playground start | |
class MySwiftClass { | |
// Empty class | |
} | |
var parsedClass = parseClass(MySwiftClass.self) | |
parsedClass.type.toString() | |
parsedClass.name | |
parsedClass.mangledName! | |
parsedClass.moduleName! | |
parsedClass = parseClass(NSObject.self) | |
parsedClass.type.toString() | |
parsedClass.name | |
parsedClass.mangledName! | |
parsedClass.moduleName! |
This file contains 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
func demangle(className: String) -> String { | |
let tmpClassName = ("__TMP" + className).bridgeToObjectiveC().UTF8String | |
let propertyName: CString = "tmpProperty" | |
let tmpClass: AnyClass! = objc_allocateClassPair(NSObject.self, tmpClassName, 0) | |
objc_registerClassPair(tmpClass) | |
let propertyType = "@\"\(className)\"".bridgeToObjectiveC().UTF8String | |
let attr = objc_property_attribute_t(name: "T", value: propertyType) | |
class_addProperty(tmpClass, propertyName, [attr], 1) | |
let property = class_getProperty(tmpClass, propertyName) | |
var attCount: CUnsignedInt = 0; | |
let atts = property_copyAttributeList(property, &attCount) | |
objc_disposeClassPair(tmpClass) | |
return "\(atts[0].value)" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment