comparison 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
comparison
equal deleted inserted replaced
0:c7db221de6e8 1:033d260cfc9b
1 /**
2 * Copyright: Copyright (c) 2009 Jacob Carlborg.
3 * Authors: Jacob Carlborg
4 * Version: Initial created: Feb 3, 2009
5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
6 */
7 module dstep.objc.bridge.Capsule;
8
9 version (Tango)
10 {
11 import tango.core.Memory;
12 import tango.math.Math : log2;
13
14 alias GC.addRoot addRoot;
15
16 import tango.core.Traits;
17 }
18
19 else
20 {
21 import std.gc : addRoot;
22 import std.math : log2;
23 }
24
25 import dstep.internal.String;
26 import dstep.objc.bridge.Bridge;
27 import dstep.objc.bridge.TypeEncoding;
28 import dstep.objc.bridge.Wrapper;
29 import dstep.objc.message;
30 import dstep.objc.objc;
31 import dstep.objc.runtime;
32 import bindings = dstep.objc.bindings;
33
34 import mambo.io;
35
36 template ObjcType (T)
37 {
38 static if (needsEncapsulation!(T))
39 alias id ObjcType;
40
41 else
42 alias T ObjcType;
43 }
44
45 Class capsuleClass ()
46 {
47 if (!Capsule.capsuleClass)
48 initCapsuleClass;
49
50 return Capsule.capsuleClass;
51 }
52
53 private struct Capsule
54 {
55 static Class capsuleClass;
56
57 static id create (Object object, Class capsuleClass)
58 {
59 id capsule = objc.createInstance(capsuleClass, 0);
60
61 Bridge.setDObject(object, capsule);
62
63 return capsule;
64 }
65
66 static id description (id self, SEL op)
67 in
68 {
69 assert(isCapsule(self));
70 }
71 body
72 {
73 return encapsuleString(decapsule!(Object)(self).toString);
74 }
75
76 static hash_t hash (id self, SEL op)
77 in
78 {
79 assert(isCapsule(self));
80 }
81 body
82 {
83 return decapsule!(Object)(self).toHash;
84 }
85
86 static byte isEqual (id self, SEL op, Object object)
87 in
88 {
89 assert(isCapsule(self));
90 }
91 body
92 {
93 return decapsule!(Object)(self) == object;
94 }
95 }
96
97 private void initCapsuleClass ()
98 {
99 Class superClass = cast(Class) objc.getClass!("NSObject");
100 Capsule.capsuleClass = objc.allocateClassPair!("D_Object")(superClass, 0);
101
102 ubyte alignment = cast(ubyte) log2(Bridge.DObjectType.sizeof);
103
104 Capsule.capsuleClass.addIvar!(Bridge.dObjectVar, encode!(Bridge.DObjectType))(Bridge.DObjectType.sizeof, alignment);
105
106 Capsule.capsuleClass.addMethod!(encodeCallable!(Capsule.description))(sel.registerName!("description"), cast(IMP) &Capsule.description);
107 Capsule.capsuleClass.addMethod!(encodeCallable!(Capsule.hash))(sel.registerName!("hash"), cast(IMP) &Capsule.hash);
108 Capsule.capsuleClass.addMethod!(encodeCallable!(Capsule.isEqual))(sel.registerName!("isEqual"), cast (IMP) &Capsule.isEqual);
109
110 objc.registerClassPair(capsuleClass);
111 }
112
113 bool isCapsule (id capsule)
114 {
115 if (!capsule)
116 return false;
117
118 Class cls = capsule.isa;
119 return cls.getInstanceVariable!(Bridge.dObjectVar) !is null;
120 }
121
122 template needsEncapsulation (T)
123 {
124 static if (is(T == class))
125 const needsEncapsulation = true;
126
127 else
128 const needsEncapsulation = false;
129 }
130
131 ObjcType!(T) encapsule (T) (T value)
132 {
133 static if (needsEncapsulation!(T))
134 {
135 if (!value)
136 return null;
137
138 if (auto wrapper = cast(ObjcWrapper) value)
139 return wrapper.objcObject;
140
141 return Capsule.create(value, capsuleClass);
142 }
143
144 else
145 return value;
146 }
147
148 template decapsule (T)
149 {
150 T decapsule (ObjcType!(T) value)
151 {
152 static if (needsEncapsulation!(T))
153 {
154 if (isCapsule(value))
155 return cast(T) Bridge.getDObject(value);
156
157 else
158 {
159 static if (is(T : ObjcWrapper))
160 new T(value);
161
162 else
163 return null;
164 }
165 }
166
167 else
168 return value;
169 }
170 }
171
172 private id encapsuleString (string str)
173 {
174 enum { NSUTF8StringEncoding = 4 }
175
176 return objc.getClass!("NSString").msgSend(sel.registerName!("alloc")).msgSend(sel.registerName!("initWithBytes:length:encoding:"), str.ptr, str.length, NSUTF8StringEncoding);
177 }