Mercurial > projects > dstep
view dstep/objc/bridge/Capsule.d @ 24:ab33fc0c3fc1
Fixed the implementation for the methods in Capsule. Changed a method name in objc_class
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Wed, 10 Feb 2010 19:24:32 +0100 |
parents | 19885b43130e |
children | b9de51448c6b |
line wrap: on
line source
/** * Copyright: Copyright (c) 2009 Jacob Carlborg. * Authors: Jacob Carlborg * Version: Initial created: Feb 3, 2009 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) */ module dstep.objc.bridge.Capsule; version (Tango) { import tango.core.Memory; import tango.math.Math : log2; import tango.core.Traits; } else { import GC = std.gc : addRoot; import std.math : log2; } import dstep.internal.String; import dstep.objc.bridge.Bridge; import dstep.objc.bridge.Type; import dstep.objc.bridge.TypeEncoding; import dstep.objc.bridge.Wrapper; import dstep.objc.message; import dstep.objc.objc; import dstep.objc.runtime; import bindings = dstep.objc.bindings; /// Returns the capsule class Class capsuleClass () { if (!Capsule.capsuleClass) initCapsuleClass; return Capsule.capsuleClass; } private struct Capsule { static Class capsuleClass; static id create (Object object, Class capsuleClass) { id capsule = objc.createInstance(capsuleClass, 0); Bridge.setDObject(object, capsule); return capsule; } static id description (id self, SEL op) in { assert(isCapsule(self)); } body { if (auto object = decapsule!(Object)(self)) return encapsuleString(object.toString); objc_super superObject; superObject.cls = .capsuleClass.getSuperclass; superObject.receiver = self; return Bridge.invokeObjcSuperMethod!(id, "description")(&superObject); } static hash_t hash (id self, SEL op) in { assert(isCapsule(self)); } body { if (auto object = decapsule!(Object)(self)) return object.toHash; objc_super superObject; superObject.cls = .capsuleClass.getSuperclass; superObject.receiver = self; return Bridge.invokeObjcSuperMethod!(hash_t, "hash")(&superObject); } static bool isEqual (id self, SEL op, Object other) in { assert(isCapsule(self)); } body { if (auto object = decapsule!(Object)(self)) return cast(bool) (object == other); objc_super superObject; superObject.cls = .capsuleClass.getSuperclass; superObject.receiver = self; return Bridge.invokeObjcSuperMethod!(bool, "isEqual:", Object)(&superObject, other); } } private void initCapsuleClass () { Class superClass = cast(Class) objc.getClass!("NSObject"); Capsule.capsuleClass = objc.allocateClassPair!("D_Object")(superClass, 0); ubyte alignment = cast(ubyte) log2(Bridge.DObjectType.sizeof); Capsule.capsuleClass.addIvar!(Bridge.dObjectVar, encode!(Bridge.DObjectType))(Bridge.DObjectType.sizeof, alignment); Capsule.capsuleClass.addMethod!(encodeCallable!(Capsule.description))(sel.registerName!("description"), cast(IMP) &Capsule.description); Capsule.capsuleClass.addMethod!(encodeCallable!(Capsule.hash))(sel.registerName!("hash"), cast(IMP) &Capsule.hash); Capsule.capsuleClass.addMethod!(encodeCallable!(Capsule.isEqual))(sel.registerName!("isEqual"), cast (IMP) &Capsule.isEqual); objc.registerClassPair(capsuleClass); } /** * Returns $(D_KEYWORD true) if the given Objective-C instance is a capsule * * Params: * instance = the Objective-C instance * * Returns: $(D_KEYWORD true) if the given Objective-C instance is a capsule */ bool isCapsule (id instance) { //if (capsule && capsule.isa) //return capsule.isa.getInstanceVariable!(Bridge.dObjectVar) !is null; if (instance) { Class cls = instance.isa; while (cls && cls !is capsuleClass) cls = cls.super_class; return cls is capsuleClass; } return false; } /** * Returns $(D_KEYWORD true) if the given Objective-C class is a capsule * * Params: * cls = the Objective-C class * * Returns: true if the given Objective-C class is a capsule */ bool isCapsule (Class cls) { while (cls && cls !is capsuleClass) cls = cls.super_class; return cls is capsuleClass; } /** * Encapsulate the value of type $(D_PARAM T) to corresponding Objective-C type $(D_PSYMBOL ObjcType!(T)) * * Params: * T = the type of the value * value = the value to encapsulate * * Returns: the encapsulated value */ ObjcType!(T) encapsule (T) (T value) { static if (needsEncapsulation!(T)) { if (!value) return null; if (auto wrapper = cast(ObjcWrapper) value) return wrapper.objcObject; static if (is(T == interface)) return Capsule.create(cast(Object) value, capsuleClass); return Capsule.create(cast(Object) value, capsuleClass); } else return value; } /** * Decapsulate the given Objective-C value of type $(D_PSYMBOL ObjcType!(T)) to corresponding D type $(D_PARAM T). * * Params: * T = the type of the decapsulated value * value = the value to decapsulate * * Returns: the decapsulated value */ T decapsule (T) (ObjcType!(T) value) { static if (needsEncapsulation!(T)) { static if (hasIdConstructor!(T)) { T instance = cast(T) Bridge.getDObject(value); return instance ? instance : new T(value); } else return cast(T) Bridge.getDObject(value); } else return value; } private id encapsuleString (string str) { enum { NSUTF8StringEncoding = 4 } return objc.getClass!("NSString").msgSend(sel.registerName!("alloc")).msgSend(sel.registerName!("initWithBytes:length:encoding:"), str.ptr, str.length, NSUTF8StringEncoding); }