Mercurial > projects > dstep
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 } |