diff dstep/objc/bridge/Capsule.d @ 1:033d260cfc9b

First upload of the bridge
author Jacob Carlborg <doob@me.com>
date Thu, 18 Jun 2009 22:00:13 +0200
parents
children 9fd439a28ce3
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/objc/bridge/Capsule.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,177 @@
+/**
+ * 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;
+	
+	alias GC.addRoot addRoot;
+	
+	import tango.core.Traits;
+}
+
+else
+{
+	import std.gc : addRoot;
+	import std.math : log2;
+}
+
+import dstep.internal.String;
+import dstep.objc.bridge.Bridge;
+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;
+
+import mambo.io;
+
+template ObjcType (T)
+{
+	static if (needsEncapsulation!(T))
+		alias id ObjcType;
+	
+	else
+		alias T ObjcType;
+}
+
+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
+	{
+		return encapsuleString(decapsule!(Object)(self).toString);
+	}
+	
+	static hash_t hash (id self, SEL op)
+	in
+	{
+		assert(isCapsule(self));
+	}
+	body
+	{
+		return decapsule!(Object)(self).toHash;
+	}
+	
+	static byte isEqual (id self, SEL op, Object object)
+	in
+	{
+		assert(isCapsule(self));
+	}
+	body
+	{
+		return decapsule!(Object)(self) == object;
+	}
+}
+
+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);
+}
+
+bool isCapsule (id capsule)
+{
+	if (!capsule)
+		return false;
+	
+	Class cls = capsule.isa;
+	return cls.getInstanceVariable!(Bridge.dObjectVar) !is null;
+}
+
+template needsEncapsulation (T)
+{
+	static if (is(T == class))
+		const needsEncapsulation = true;
+	
+	else
+		const needsEncapsulation = false;
+}
+
+ObjcType!(T) encapsule (T) (T value)
+{	
+	static if (needsEncapsulation!(T))
+	{
+		if (!value)
+			return null;
+		
+		if (auto wrapper = cast(ObjcWrapper) value)
+			return wrapper.objcObject;
+		
+		return Capsule.create(value, capsuleClass);
+	}
+	
+	else
+		return value;
+}
+
+template decapsule (T)
+{
+	T decapsule (ObjcType!(T) value)
+	{
+		static if (needsEncapsulation!(T))
+		{
+			if (isCapsule(value))
+				return cast(T) Bridge.getDObject(value);
+			
+			else
+			{
+				static if (is(T : ObjcWrapper))
+					new T(value);
+				
+				else
+					return null;
+			}
+		}
+		
+		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);
+}
\ No newline at end of file